Skip to content

Commit 8d1e009

Browse files
Merge pull request #55 from Danil-Grigorev/render-cloud-config
OCPCLOUD-1194: Implement cloud-config-file flag in CCCMO render
2 parents 976e294 + 8ad771f commit 8d1e009

3 files changed

Lines changed: 259 additions & 23 deletions

File tree

cmd/render/main.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var (
2424
destinationDir string
2525
clusterInfrastructure string
2626
imagesFile string
27+
cloudConfigFile string
2728
}
2829
)
2930

@@ -32,6 +33,7 @@ func init() {
3233
renderCmd.PersistentFlags().StringVar(&renderOpts.destinationDir, "dest-dir", "", "The destination dir where CCCMO writes the generated static pods for CCM.")
3334
renderCmd.PersistentFlags().StringVar(&renderOpts.clusterInfrastructure, "cluster-infrastructure-file", "", "Input path for the cluster infrastructure file.")
3435
renderCmd.PersistentFlags().StringVar(&renderOpts.imagesFile, "images-file", "", "Input path for the images config map file.")
36+
renderCmd.PersistentFlags().StringVar(&renderOpts.cloudConfigFile, "cloud-config-file", "", "Input path for the cloud config configMap manifest generated by cluster-config-operator.")
3537
renderCmd.MarkFlagRequired("dest-dir")
3638
renderCmd.MarkFlagRequired("cluster-infrastructure-file")
3739
renderCmd.MarkFlagRequired("images-file")
@@ -44,19 +46,23 @@ func runRenderCmd(cmd *cobra.Command, args []string) error {
4446
if err := validate(
4547
renderOpts.destinationDir,
4648
renderOpts.clusterInfrastructure,
47-
renderOpts.imagesFile); err != nil {
49+
renderOpts.imagesFile,
50+
renderOpts.cloudConfigFile); err != nil {
4851
return err
4952
}
5053

51-
if err := render.New(renderOpts.clusterInfrastructure, renderOpts.imagesFile).Run(renderOpts.destinationDir); err != nil {
54+
if err := render.New(
55+
renderOpts.clusterInfrastructure,
56+
renderOpts.imagesFile,
57+
renderOpts.cloudConfigFile).Run(renderOpts.destinationDir); err != nil {
5258
return err
5359
}
5460

5561
return nil
5662
}
5763

5864
// validate verifies all file and dirs exist
59-
func validate(destinationDir, clusterInfrastructure, imagesFile string) error {
65+
func validate(destinationDir, clusterInfrastructure, imagesFile, cloudConfigFile string) error {
6066
errs := []error{}
6167
if err := isFile(clusterInfrastructure); err != nil {
6268
klog.Errorf("error reading --cluster-infrastructure-file=%q: %s", clusterInfrastructure, err)
@@ -66,6 +72,12 @@ func validate(destinationDir, clusterInfrastructure, imagesFile string) error {
6672
klog.Errorf("error reading --images-file=%q: %s", imagesFile, err)
6773
errs = append(errs, fmt.Errorf("error reading --images-file: %s", err))
6874
}
75+
if cloudConfigFile != "" {
76+
if err := isFile(cloudConfigFile); err != nil {
77+
klog.Errorf("error reading --cloud-config-file=%q: %s", imagesFile, err)
78+
errs = append(errs, fmt.Errorf("error reading --cloud-config-file: %s", err))
79+
}
80+
}
6981

7082
if len(errs) > 0 {
7183
return utilerrors.NewAggregate(errs)

pkg/render/render.go

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ import (
2020
)
2121

2222
const (
23+
configDataKey = "cloud.conf"
2324
bootstrapNamespace = "kube-system"
2425
bootstrapPrefix = "bootstrap"
26+
configPrefix = "config"
2527
// bootstrapFileName is built from bootstrapPrefix, resource name and kind
2628
bootstrapFileName = "%s/%s-%s.yaml"
2729
)
@@ -32,20 +34,24 @@ type Render struct {
3234
infrastructureFile string
3335
// path to rendered cloud-controller-manager-images ConfigMap manifest for image references to use
3436
imagesFile string
37+
// path to populated cloud-config ConfigMap manifest from cluster-config-operator
38+
// where cloud-config could be extracted for use in CCM static pod
39+
cloudConfigFile string
3540
}
3641

3742
// New returns controller for render
38-
func New(infrastructureFile, imagesFile string) *Render {
43+
func New(infrastructureFile, imagesFile, cloudConfigFile string) *Render {
3944
return &Render{
4045
infrastructureFile: infrastructureFile,
4146
imagesFile: imagesFile,
47+
cloudConfigFile: cloudConfigFile,
4248
}
4349
}
4450

4551
// Run runs boostrap for Machine Config Controller
4652
// It writes all the assets to destDir
4753
func (r *Render) Run(destinationDir string) error {
48-
infra, imagesMap, err := r.readAssets()
54+
infra, imagesMap, cloudConfig, err := r.readAssets()
4955
if err != nil {
5056
klog.Errorf("Cannot read assets from provided paths: %v", err)
5157
return err
@@ -63,36 +69,51 @@ func (r *Render) Run(destinationDir string) error {
6369
klog.Infof("Collected resource %s %q successfully", resource.GetObjectKind().GroupVersionKind(), client.ObjectKeyFromObject(resource))
6470
}
6571

66-
return writeAssets(destinationDir, resources)
72+
if err := writeAssets(destinationDir, resources); err != nil {
73+
klog.Errorf("Could not write assets to bootstrap dir: %v", err)
74+
return err
75+
}
76+
77+
return writeCloudConfig(destinationDir, cloudConfig)
6778
}
6879

6980
// readAssets collects infrastructure resource and images config map from provided paths
70-
func (r *Render) readAssets() (*configv1.Infrastructure, *corev1.ConfigMap, error) {
81+
func (r *Render) readAssets() (*configv1.Infrastructure, *corev1.ConfigMap, string, error) {
7182
infraData, err := ioutil.ReadFile(r.infrastructureFile)
7283
if err != nil {
7384
klog.Errorf("Unable to read data from %q: %v", r.infrastructureFile, err)
74-
return nil, nil, err
85+
return nil, nil, "", err
7586
}
7687

7788
infra := &configv1.Infrastructure{}
7889
if err := yaml.UnmarshalStrict(infraData, infra); err != nil {
7990
klog.Errorf("Cannot decode data into configv1.Infrastructure from %q: %v", r.infrastructureFile, err)
80-
return nil, nil, err
91+
return nil, nil, "", err
8192
}
8293

8394
imagesData, err := ioutil.ReadFile(r.imagesFile)
8495
if err != nil {
8596
klog.Errorf("Unable to read data from %q: %v", r.imagesFile, err)
86-
return nil, nil, err
97+
return nil, nil, "", err
8798
}
8899

89100
imagesConfigMap := &corev1.ConfigMap{}
90101
if err := yaml.UnmarshalStrict(imagesData, imagesConfigMap); err != nil {
91102
klog.Errorf("Cannot decode data into v1.ConfigMap from %q: %v", r.imagesFile, err)
92-
return nil, nil, err
103+
return nil, nil, "", err
104+
}
105+
106+
cloudConfig := ""
107+
// if the cloudConfig is set in infra read the cloudConfigFile
108+
if infra.Spec.CloudConfig.Name != "" {
109+
cloudConfig, err = loadBootstrapCloudProviderConfig(infra, r.cloudConfigFile)
110+
if err != nil {
111+
klog.Errorf("failed to load the cloud provider config: %v", err)
112+
return nil, nil, "", err
113+
}
93114
}
94115

95-
return infra, imagesConfigMap, nil
116+
return infra, imagesConfigMap, cloudConfig, nil
96117
}
97118

98119
// writeAssets writes static pods to disk into <destinationDir>/<bootstrapPrefix>/<resourceName>-<resourceKind>.yaml
@@ -118,5 +139,48 @@ func writeAssets(destinationDir string, resources []client.Object) error {
118139
return err
119140
}
120141
}
142+
143+
return nil
144+
}
145+
146+
// writeCloudConfig creates config folder and writes resources such as cloud-config file
147+
// for use in bootstrap
148+
func writeCloudConfig(destinationDir string, cloudConfig string) error {
149+
// Create config directory in advance to ensure it is present for any provider
150+
configDir := filepath.Join(destinationDir, configPrefix)
151+
if err := os.MkdirAll(configDir, fs.ModePerm); err != nil {
152+
klog.Errorf("Unable to create destination dir %q: %v", configDir, err)
153+
return err
154+
}
155+
156+
if cloudConfig != "" {
157+
cloudConfigFile := filepath.Join(configDir, configDataKey)
158+
159+
klog.Infof("Writing cloud config on disk in %q", cloudConfigFile)
160+
err := os.WriteFile(cloudConfigFile, []byte(cloudConfig), 0666)
161+
if err != nil {
162+
klog.Errorf("Failed to write cloud config to disk in %q: %v", cloudConfigFile, err)
163+
return err
164+
}
165+
}
166+
121167
return nil
122168
}
169+
170+
// loadBootstrapCloudProviderConfig reads the cloud provider config from cloudConfigFile based on infra object.
171+
func loadBootstrapCloudProviderConfig(infra *configv1.Infrastructure, cloudConfigFile string) (string, error) {
172+
data, err := os.ReadFile(cloudConfigFile)
173+
if err != nil {
174+
return "", err
175+
}
176+
cloudConfigMap := &corev1.ConfigMap{}
177+
if err := yaml.UnmarshalStrict(data, cloudConfigMap); err != nil {
178+
return "", err
179+
}
180+
cloudConf, ok := cloudConfigMap.Data[configDataKey]
181+
if !ok {
182+
klog.Infof("falling back to reading cloud provider config from user specified key %s", infra.Spec.CloudConfig.Key)
183+
cloudConf = cloudConfigMap.Data[infra.Spec.CloudConfig.Key]
184+
}
185+
return cloudConf, nil
186+
}

0 commit comments

Comments
 (0)