Skip to content

Commit 65b8a82

Browse files
committed
capi: refactor bootstrap building to use shared ConfigBuilder
The intent is that the ConfigBuilder from bare-metal support is reusable.
1 parent 8f61cc0 commit 65b8a82

File tree

2 files changed

+41
-210
lines changed

2 files changed

+41
-210
lines changed

pkg/commands/toolbox_enroll.go

Lines changed: 7 additions & 7 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
@@ -450,9 +450,9 @@ type ConfigBuilder struct {
450450
// Use GetInstanceGroup to read and auto-populate.
451451
InstanceGroup *kops.InstanceGroup
452452

453-
// instanceGroups holds the (unexpanded) instance group configurations
453+
// InstanceGroups holds the (unexpanded) instance group configurations
454454
// Use GetInstanceGroups to read and auto-populate
455-
instanceGroups *kops.InstanceGroupList
455+
InstanceGroups *kops.InstanceGroupList
456456

457457
// wellKnownAddresses holds the known IP/host endpoints for the cluster.
458458
// Use GetWellKnownAddresses to read and auto-populate.
@@ -603,8 +603,8 @@ func (b *ConfigBuilder) GetCloud(ctx context.Context) (fi.Cloud, error) {
603603
}
604604

605605
func (b *ConfigBuilder) GetInstanceGroups(ctx context.Context) (*kops.InstanceGroupList, error) {
606-
if b.instanceGroups != nil {
607-
return b.instanceGroups, nil
606+
if b.InstanceGroups != nil {
607+
return b.InstanceGroups, nil
608608
}
609609

610610
cluster, err := b.GetCluster(ctx)
@@ -622,7 +622,7 @@ func (b *ConfigBuilder) GetInstanceGroups(ctx context.Context) (*kops.InstanceGr
622622
return nil, fmt.Errorf("reading instance groups: %w", err)
623623
}
624624

625-
b.instanceGroups = instanceGroupList
625+
b.InstanceGroups = instanceGroupList
626626
return instanceGroupList, nil
627627
}
628628

pkg/controllers/clusterapi/kopsconfig_controller.go

Lines changed: 34 additions & 203 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"
@@ -33,15 +31,11 @@ import (
3331
"k8s.io/kops/pkg/apis/kops"
3432
"k8s.io/kops/pkg/apis/kops/registry"
3533
kopsapi "k8s.io/kops/pkg/apis/kops/v1alpha2"
36-
"k8s.io/kops/pkg/apis/nodeup"
37-
"k8s.io/kops/pkg/assets"
3834
"k8s.io/kops/pkg/client/simple/vfsclientset"
35+
"k8s.io/kops/pkg/commands"
3936
"k8s.io/kops/pkg/kopscodecs"
4037
"k8s.io/kops/pkg/model"
41-
"k8s.io/kops/pkg/model/resources"
42-
"k8s.io/kops/pkg/nodemodel"
4338
"k8s.io/kops/pkg/wellknownservices"
44-
"k8s.io/kops/upup/pkg/fi"
4539
"k8s.io/kops/upup/pkg/fi/cloudup"
4640
"k8s.io/kops/util/pkg/vfs"
4741
"k8s.io/utils/pointer"
@@ -176,25 +170,14 @@ func (r *KopsConfigReconciler) storeBootstrapData(ctx context.Context, parent *a
176170
}
177171

178172
func (r *KopsConfigReconciler) buildBootstrapData(ctx context.Context, cluster *kopsapi.Cluster, kopsControlPlane *capikops.KopsControlPlane) ([]byte, error) {
179-
180173
config, err := BuildNodeupConfig(ctx, cluster, kopsControlPlane)
181174
if err != nil {
182175
return nil, err
183176
}
184177
return config.NodeupScript, nil
185178
}
186179

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-
// }
180+
func BuildNodeupConfig(ctx context.Context, cluster *kopsapi.Cluster, kopsControlPlane *capikops.KopsControlPlane) (*commands.BootstrapData, error) {
198181
wellKnownAddresses := model.WellKnownAddresses{}
199182
for _, systemEndpoint := range kopsControlPlane.Status.SystemEndpoints {
200183
switch systemEndpoint.Type {
@@ -205,210 +188,58 @@ func BuildNodeupConfig(ctx context.Context, cluster *kopsapi.Cluster, kopsContro
205188
}
206189
}
207190

208-
// TODO: Sync with other nodeup config builder
209191
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 = ""
215192

216-
// if clusterInternal.Spec.KubeAPIServer == nil {
217-
// clusterInternal.Spec.KubeAPIServer = &kops.KubeAPIServerConfig{}
218-
// }
193+
configBuilder := &commands.ConfigBuilder{}
219194

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-
}
234-
235-
clientset := vfsclientset.NewVFSClientset(vfsContext, basePath)
236-
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)
195+
{
196+
if err := kopscodecs.Scheme.Convert(cluster, clusterInternal, nil); err != nil {
197+
return nil, fmt.Errorf("converting cluster object: %w", err)
270198
}
271-
fullInstanceGroups = append(fullInstanceGroups, fullGroup)
272-
}
199+
// TODO: Fix validation
200+
clusterInternal.Namespace = ""
273201

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
202+
configBuilder.Cluster = clusterInternal
203+
configBuilder.ClusterName = clusterInternal.Name
293204
}
294205

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
329-
}
206+
{
207+
vfsContext := vfs.NewVFSContext()
330208

331-
for _, keyName := range []string{"kubernetes-ca"} {
332-
keyset, err := keystore.FindKeyset(ctx, keyName)
209+
basePath, err := registry.ConfigBase(vfsContext, clusterInternal)
333210
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)
211+
return nil, fmt.Errorf("parsing vfs base path: %w", err)
339212
}
340213

341-
keysets[keyName] = keyset
214+
clientset := vfsclientset.NewVFSClientset(vfsContext, basePath)
215+
configBuilder.Clientset = clientset
342216
}
343217

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-
362218
{
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)
219+
ig := &kops.InstanceGroup{}
220+
// TODO: Name
221+
ig.SetName("todo-ig-name")
222+
ig.Spec.Role = kops.InstanceGroupRoleNode
223+
224+
configBuilder.InstanceGroup = ig
225+
configBuilder.InstanceGroupName = ig.Name
226+
configBuilder.InstanceGroups = &kops.InstanceGroupList{
227+
Items: []kops.InstanceGroup{*ig},
388228
}
389229
}
390230

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
231+
{
232+
cloud, err := cloudup.BuildCloud(clusterInternal)
233+
if err != nil {
234+
return nil, fmt.Errorf("building cloud: %w", err)
235+
}
236+
configBuilder.Cloud = cloud
403237
}
404238

405-
b, err := fi.ResourceAsBytes(nodeupScriptResource)
239+
bootstrapData, err := configBuilder.GetBootstrapData(ctx)
406240
if err != nil {
407-
return nil, err
241+
return nil, fmt.Errorf("building bootstrap data: %w", err)
408242
}
409243

410-
return &NodeupConfig{
411-
NodeupScript: b,
412-
NodeupConfig: nodeupConfig,
413-
}, nil
244+
return bootstrapData, nil
414245
}

0 commit comments

Comments
 (0)