Skip to content

Commit 941b7c0

Browse files
authored
Merge pull request #17703 from justinsb/clusterapi_controllers_refactor_nodeup
capi: refactor to use shared nodeup builder
2 parents b8f3385 + aa3e332 commit 941b7c0

File tree

6 files changed

+56
-229
lines changed

6 files changed

+56
-229
lines changed

cmd/kops-controller/main.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"k8s.io/kops/pkg/apis/kops/v1alpha2"
3838
"k8s.io/kops/pkg/bootstrap"
3939
"k8s.io/kops/pkg/bootstrap/pkibootstrap"
40+
"k8s.io/kops/pkg/client/simple"
4041
"k8s.io/kops/pkg/controllers/clusterapi"
4142
"k8s.io/kops/pkg/nodeidentity"
4243
nodeidentityaws "k8s.io/kops/pkg/nodeidentity/aws"
@@ -136,6 +137,8 @@ func main() {
136137
capiManager = nodeidentityclusterapi.NewManager(mgr.GetClient())
137138
}
138139

140+
var clientset simple.Clientset
141+
139142
if opt.Server != nil {
140143
var verifiers []bootstrap.Verifier
141144
var err error
@@ -225,6 +228,7 @@ func main() {
225228
setupLog.Error(err, "unable to create server")
226229
os.Exit(1)
227230
}
231+
clientset = srv.GetClientset()
228232
mgr.Add(srv)
229233
}
230234

@@ -249,7 +253,11 @@ func main() {
249253
// +kubebuilder:scaffold:builder
250254

251255
if opt.CAPI.IsEnabled() {
252-
if err := clusterapi.RegisterControllers(mgr); err != nil {
256+
if clientset == nil {
257+
setupLog.Error(fmt.Errorf("clientset is not initialized"), "registering Cluster API controllers")
258+
os.Exit(1)
259+
}
260+
if err := clusterapi.RegisterControllers(mgr, clientset); err != nil {
253261
setupLog.Error(err, "registering Cluster API controllers")
254262
os.Exit(1)
255263
}

cmd/kops-controller/pkg/server/server.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ func NewServer(vfsContext *vfs.VFSContext, opt *config.Options, verifier bootstr
126126
return s, nil
127127
}
128128

129+
func (s *Server) GetClientset() simple.Clientset {
130+
return s.clientset
131+
}
132+
129133
func (s *Server) NeedLeaderElection() bool {
130134
return false
131135
}

pkg/commands/toolbox_enroll.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,11 +423,11 @@ type BootstrapData struct {
423423
// ConfigBuilder builds bootstrap configuration for a node.
424424
type ConfigBuilder struct {
425425
// ClusterName is the name of the cluster to build.
426-
// Required.
426+
// Required (unless Cluster is set).
427427
ClusterName string
428428

429429
// InstanceGroupName is the name of the InstanceGroup we are building configuration for.
430-
// Required.
430+
// Required (unless InstanceGroup is set).
431431
InstanceGroupName string
432432

433433
// Clientset is the clientset to use to query for clusters / instancegroups etc

pkg/controllers/clusterapi/kopsconfig_controller.go

Lines changed: 30 additions & 220 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@ limitations under the License.
1717
package clusterapi
1818

1919
import (
20-
"bytes"
2120
"context"
2221
"fmt"
23-
"sort"
2422

2523
corev1 "k8s.io/api/core/v1"
2624
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -31,29 +29,24 @@ import (
3129
capikops "k8s.io/kops/clusterapi/controlplane/kops/api/v1beta1"
3230
clusterv1 "k8s.io/kops/clusterapi/snapshot/cluster-api/api/v1beta1"
3331
"k8s.io/kops/pkg/apis/kops"
34-
"k8s.io/kops/pkg/apis/kops/registry"
3532
kopsapi "k8s.io/kops/pkg/apis/kops/v1alpha2"
36-
"k8s.io/kops/pkg/apis/nodeup"
37-
"k8s.io/kops/pkg/assets"
38-
"k8s.io/kops/pkg/client/simple/vfsclientset"
33+
"k8s.io/kops/pkg/client/simple"
34+
"k8s.io/kops/pkg/commands"
3935
"k8s.io/kops/pkg/kopscodecs"
4036
"k8s.io/kops/pkg/model"
41-
"k8s.io/kops/pkg/model/resources"
42-
"k8s.io/kops/pkg/nodemodel"
4337
"k8s.io/kops/pkg/wellknownservices"
44-
"k8s.io/kops/upup/pkg/fi"
4538
"k8s.io/kops/upup/pkg/fi/cloudup"
46-
"k8s.io/kops/util/pkg/vfs"
4739
"k8s.io/utils/pointer"
4840
ctrl "sigs.k8s.io/controller-runtime"
4941
"sigs.k8s.io/controller-runtime/pkg/client"
5042
"sigs.k8s.io/controller-runtime/pkg/manager"
5143
)
5244

5345
// NewKopsConfigReconciler is the constructor for a KopsConfigReconciler
54-
func NewKopsConfigReconciler(mgr manager.Manager) error {
46+
func NewKopsConfigReconciler(mgr manager.Manager, clientset simple.Clientset) error {
5547
r := &KopsConfigReconciler{
56-
client: mgr.GetClient(),
48+
client: mgr.GetClient(),
49+
clientset: clientset,
5750
}
5851

5952
return ctrl.NewControllerManagedBy(mgr).
@@ -65,6 +58,9 @@ func NewKopsConfigReconciler(mgr manager.Manager) error {
6558
type KopsConfigReconciler struct {
6659
// client is the controller-runtime client
6760
client client.Client
61+
62+
// clientset is a kops clientset
63+
clientset simple.Clientset
6864
}
6965

7066
// +kubebuilder:rbac:groups=,resources=nodes,verbs=get;list;watch;patch
@@ -176,25 +172,6 @@ func (r *KopsConfigReconciler) storeBootstrapData(ctx context.Context, parent *a
176172
}
177173

178174
func (r *KopsConfigReconciler) buildBootstrapData(ctx context.Context, cluster *kopsapi.Cluster, kopsControlPlane *capikops.KopsControlPlane) ([]byte, error) {
179-
180-
config, err := BuildNodeupConfig(ctx, cluster, kopsControlPlane)
181-
if err != nil {
182-
return nil, err
183-
}
184-
return config.NodeupScript, nil
185-
}
186-
187-
type NodeupConfig struct {
188-
NodeupScript []byte
189-
NodeupConfig *nodeup.Config
190-
}
191-
192-
// TODO: Dedup with b.builder.NodeUpConfigBuilder.BuildConfig
193-
func BuildNodeupConfig(ctx context.Context, cluster *kopsapi.Cluster, kopsControlPlane *capikops.KopsControlPlane) (*NodeupConfig, error) {
194-
// tf := &TemplateFunctions{
195-
// KopsModelContext: *modelContext,
196-
// cloud: cloud,
197-
// }
198175
wellKnownAddresses := model.WellKnownAddresses{}
199176
for _, systemEndpoint := range kopsControlPlane.Status.SystemEndpoints {
200177
switch systemEndpoint.Type {
@@ -205,210 +182,43 @@ func BuildNodeupConfig(ctx context.Context, cluster *kopsapi.Cluster, kopsContro
205182
}
206183
}
207184

208-
// TODO: Sync with other nodeup config builder
209185
clusterInternal := &kops.Cluster{}
210-
if err := kopscodecs.Scheme.Convert(cluster, clusterInternal, nil); err != nil {
211-
return nil, fmt.Errorf("converting cluster object: %w", err)
212-
}
213-
// TODO: Fix validation
214-
clusterInternal.Namespace = ""
215-
216-
// if clusterInternal.Spec.KubeAPIServer == nil {
217-
// clusterInternal.Spec.KubeAPIServer = &kops.KubeAPIServerConfig{}
218-
// }
219-
220-
// cluster := &kops.Cluster{}
221-
// cluster.Spec.KubernetesVersion = "1.28.3"
222-
// cluster.Spec.KubeAPIServer = &kops.KubeAPIServerConfig{}
223-
224-
// if cluster.Spec.KubeAPIServer == nil {
225-
// cluster.Spec.KubeAPIServer = &kopsapi.KubeAPIServerConfig{}
226-
// }
227-
228-
vfsContext := vfs.NewVFSContext()
229-
230-
basePath, err := registry.ConfigBase(vfsContext, clusterInternal)
231-
if err != nil {
232-
return nil, fmt.Errorf("parsing vfs base path: %w", err)
233-
}
234186

235-
clientset := vfsclientset.NewVFSClientset(vfsContext, basePath)
187+
configBuilder := &commands.ConfigBuilder{}
188+
configBuilder.Clientset = r.clientset
236189

237-
ig := &kops.InstanceGroup{}
238-
// TODO: Name
239-
ig.SetName("todo-ig-name")
240-
ig.Spec.Role = kops.InstanceGroupRoleNode
241-
242-
getAssets := false
243-
assetBuilder := assets.NewAssetBuilder(vfsContext, clusterInternal.Spec.Assets, getAssets)
244-
245-
cloud, err := cloudup.BuildCloud(clusterInternal)
246-
if err != nil {
247-
return nil, fmt.Errorf("building cloud: %w", err)
248-
}
249-
250-
// assetBuilder := assets.NewAssetBuilder(clientset.VFSContext(), cluster.Spec.Assets, cluster.Spec.KubernetesVersion, false)
251-
var instanceGroups []*kops.InstanceGroup
252-
instanceGroups = append(instanceGroups, ig)
253-
254-
fullCluster, err := cloudup.PopulateClusterSpec(ctx, clientset, clusterInternal, instanceGroups, cloud, assetBuilder)
255-
if err != nil {
256-
return nil, fmt.Errorf("building full cluster spec: %w", err)
257-
}
258-
259-
channel, err := cloudup.ChannelForCluster(clientset.VFSContext(), fullCluster)
260-
if err != nil {
261-
// TODO: Maybe this should be a warning
262-
return nil, fmt.Errorf("building channel for cluster: %w", err)
263-
}
264-
265-
var fullInstanceGroups []*kops.InstanceGroup
266-
for _, instanceGroup := range instanceGroups {
267-
fullGroup, err := cloudup.PopulateInstanceGroupSpec(fullCluster, instanceGroup, cloud, channel)
268-
if err != nil {
269-
return nil, fmt.Errorf("building full instance group spec: %w", err)
190+
{
191+
if err := kopscodecs.Scheme.Convert(cluster, clusterInternal, nil); err != nil {
192+
return nil, fmt.Errorf("converting cluster object: %w", err)
270193
}
271-
fullInstanceGroups = append(fullInstanceGroups, fullGroup)
272-
}
273-
274-
encryptionConfigSecretHash := ""
275-
// if fi.ValueOf(c.Cluster.Spec.EncryptionConfig) {
276-
// secret, err := secretStore.FindSecret("encryptionconfig")
277-
// if err != nil {
278-
// return fmt.Errorf("could not load encryptionconfig secret: %v", err)
279-
// }
280-
// if secret == nil {
281-
// fmt.Println("")
282-
// fmt.Println("You have encryptionConfig enabled, but no encryptionconfig secret has been set.")
283-
// fmt.Println("See `kops create secret encryptionconfig -h` and https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/")
284-
// return fmt.Errorf("could not find encryptionconfig secret")
285-
// }
286-
// hashBytes := sha256.Sum256(secret.Data)
287-
// encryptionConfigSecretHash = base64.URLEncoding.EncodeToString(hashBytes[:])
288-
// }
289-
290-
nodeUpAssets, err := nodemodel.BuildNodeUpAssets(ctx, assetBuilder)
291-
if err != nil {
292-
return nil, err
293-
}
194+
// TODO: Fix validation
195+
clusterInternal.Namespace = ""
294196

295-
configBuilder, err := nodemodel.NewNodeUpConfigBuilder(fullCluster, assetBuilder, encryptionConfigSecretHash)
296-
if err != nil {
297-
return nil, fmt.Errorf("building node config: %w", err)
298-
}
299-
300-
// bootstrapScript := &model.BootstrapScript{
301-
// // KopsModelContext: modelContext,
302-
// Lifecycle: fi.LifecycleSync,
303-
// // NodeUpConfigBuilder: configBuilder,
304-
// // NodeUpAssets: c.NodeUpAssets,
305-
// }
306-
307-
keysets := make(map[string]*fi.Keyset)
308-
309-
// var keystoreBase vfs.Path
310-
311-
// if cluster.Spec.ConfigStore.Keypairs == "" {
312-
// configBase, err := registry.ConfigBase(vfsContext, clusterInternal)
313-
// if err != nil {
314-
// return nil, err
315-
// }
316-
// keystoreBase = configBase.Join("pki")
317-
// } else {
318-
// storePath, err := vfsContext.BuildVfsPath(cluster.Spec.ConfigStore.Keypairs)
319-
// if err != nil {
320-
// return nil, err
321-
// }
322-
// keystoreBase = storePath
323-
// }
324-
325-
// keystore := fi.NewVFSCAStore(clusterInternal, keystoreBase)
326-
keystore, err := clientset.KeyStore(fullCluster)
327-
if err != nil {
328-
return nil, err
197+
configBuilder.Cluster = clusterInternal
198+
configBuilder.ClusterName = clusterInternal.Name
329199
}
330200

331-
for _, keyName := range []string{"kubernetes-ca"} {
332-
keyset, err := keystore.FindKeyset(ctx, keyName)
333-
if err != nil {
334-
return nil, fmt.Errorf("getting keyset %q: %w", keyName, err)
335-
}
336-
337-
if keyset == nil {
338-
return nil, fmt.Errorf("failed to find keyset %q", keyName)
339-
}
201+
ig := &kops.InstanceGroup{}
202+
{
203+
ig.SetName("placeholder-ig-name") // IG name is not used for nodeup config generation
204+
ig.Spec.Role = kops.InstanceGroupRoleNode
340205

341-
keysets[keyName] = keyset
206+
configBuilder.InstanceGroup = ig
207+
configBuilder.InstanceGroupName = ig.Name
342208
}
343209

344-
nodeupConfig, bootConfig, err := configBuilder.BuildConfig(fullInstanceGroups[0], wellKnownAddresses, keysets)
345-
if err != nil {
346-
return nil, err
347-
}
348-
349-
// configData, err := utils.YamlMarshal(config)
350-
// if err != nil {
351-
// return nil, fmt.Errorf("error converting nodeup config to yaml: %v", err)
352-
// }
353-
// sum256 := sha256.Sum256(configData)
354-
// bootConfig.NodeupConfigHash = base64.StdEncoding.EncodeToString(sum256[:])
355-
// b.nodeupConfig.Resource = fi.NewBytesResource(configData)
356-
357-
var nodeupScript resources.NodeUpScript
358-
nodeupScript.NodeUpAssets = nodeUpAssets.NodeUpAssets
359-
// nodeupScript.NodeUpAssets = configBuilder.NodeUpAssets()
360-
nodeupScript.BootConfig = bootConfig
361-
362210
{
363-
nodeupScript.EnvironmentVariables = func() (string, error) {
364-
env := make(map[string]string)
365-
366-
// env, err := b.buildEnvironmentVariables()
367-
// if err != nil {
368-
// return "", err
369-
// }
370-
371-
// Sort keys to have a stable sequence of "export xx=xxx"" statements
372-
var keys []string
373-
for k := range env {
374-
keys = append(keys, k)
375-
}
376-
sort.Strings(keys)
377-
378-
var b bytes.Buffer
379-
for _, k := range keys {
380-
b.WriteString(fmt.Sprintf("export %s=%s\n", k, env[k]))
381-
}
382-
return b.String(), nil
383-
}
384-
385-
nodeupScript.ProxyEnv = func() (string, error) {
386-
return "", nil
387-
// return b.createProxyEnv(cluster.Spec.Networking.EgressProxy)
211+
cloud, err := cloudup.BuildCloud(clusterInternal)
212+
if err != nil {
213+
return nil, fmt.Errorf("building cloud: %w", err)
388214
}
215+
configBuilder.Cloud = cloud
389216
}
390217

391-
// TODO: nodeupScript.CompressUserData = fi.ValueOf(b.ig.Spec.CompressUserData)
392-
393-
// By setting some sysctls early, we avoid broken configurations that prevent nodeup download.
394-
// See https://github.com/kubernetes/kops/issues/10206 for details.
395-
// TODO: nodeupScript.SetSysctls = setSysctls()
396-
397-
// nodeupScript.CloudProvider = string(cluster.Spec.GetCloudProvider())
398-
nodeupScript.CloudProvider = string(clusterInternal.GetCloudProvider())
399-
400-
nodeupScriptResource, err := nodeupScript.Build()
401-
if err != nil {
402-
return nil, err
403-
}
404-
405-
b, err := fi.ResourceAsBytes(nodeupScriptResource)
218+
bootstrapData, err := configBuilder.GetBootstrapData(ctx)
406219
if err != nil {
407-
return nil, err
220+
return nil, fmt.Errorf("building bootstrap data: %w", err)
408221
}
409222

410-
return &NodeupConfig{
411-
NodeupScript: b,
412-
NodeupConfig: nodeupConfig,
413-
}, nil
223+
return bootstrapData.NodeupScript, nil
414224
}

pkg/controllers/clusterapi/register.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ package clusterapi
1919
import (
2020
"fmt"
2121

22+
"k8s.io/kops/pkg/client/simple"
2223
"sigs.k8s.io/controller-runtime/pkg/manager"
2324
)
2425

25-
func RegisterControllers(mgr manager.Manager) error {
26-
if err := NewKopsConfigReconciler(mgr); err != nil {
26+
func RegisterControllers(mgr manager.Manager, clientset simple.Clientset) error {
27+
if err := NewKopsConfigReconciler(mgr, clientset); err != nil {
2728
return fmt.Errorf("error creating KopsConfig controller: %w", err)
2829
}
2930

0 commit comments

Comments
 (0)