Skip to content

Commit

Permalink
render: generate cloud config when infrastructure and configmap are p…
Browse files Browse the repository at this point in the history
…rovided
  • Loading branch information
jhixson74 committed Jul 2, 2020
1 parent 3ff40a9 commit f6b5e2b
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 12 deletions.
54 changes: 49 additions & 5 deletions pkg/cmd/render/render.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package render

import (
"fmt"
"io/ioutil"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
"k8s.io/klog"

configv1 "github.com/openshift/api/config/v1"
kubecloudconfig "github.com/openshift/cluster-config-operator/pkg/operator/kube_cloud_config"
genericrender "github.com/openshift/library-go/pkg/operator/render"
genericrenderoptions "github.com/openshift/library-go/pkg/operator/render/options"
)
Expand All @@ -17,7 +19,12 @@ type renderOpts struct {
manifest genericrenderoptions.ManifestOptions
generic genericrenderoptions.GenericOptions

// XXX: What is this file used for?
clusterConfigFile string

clusterInfrastructureInputFile string
cloudProviderConfigInputFile string
cloudProviderConfigOutputFile string
}

// NewRenderCommand creates a render command.
Expand Down Expand Up @@ -51,7 +58,18 @@ func (r *renderOpts) AddFlags(fs *pflag.FlagSet) {
r.manifest.AddFlags(fs, "config")
r.generic.AddFlags(fs, configv1.GroupVersion.WithKind("Config"))

// XXX: What is this file used for?
fs.StringVar(&r.clusterConfigFile, "cluster-config-file", r.clusterConfigFile, "Openshift Cluster API Config file.")

// This is the file containing the infrastructure object
fs.StringVar(&r.clusterInfrastructureInputFile, "cluster-infrastructure-input-file", r.clusterInfrastructureInputFile, "Input path for the cluster infrastructure file.")

// This is the file containing the configmap for the kube cloud config provided by the user
fs.StringVar(&r.cloudProviderConfigInputFile, "cloud-provider-config-input-file", r.cloudProviderConfigInputFile, "Input path for the cloud provider config file.")

// This is the generated kube cloud config
fs.StringVar(&r.cloudProviderConfigOutputFile, "cloud-provider-config-output-file", r.cloudProviderConfigOutputFile, "Output path for the generated cloud provider config file.")

}

// Validate verifies the inputs.
Expand All @@ -63,6 +81,18 @@ func (r *renderOpts) Validate() error {
return err
}

// Validate all files are specified when specifying infrastructure and configmap files
if len(r.clusterInfrastructureInputFile) != 0 || len(r.cloudProviderConfigOutputFile) != 0 {
if !(len(r.clusterInfrastructureInputFile) != 0 && len(r.cloudProviderConfigOutputFile) != 0) {
return fmt.Errorf("clulster-infrastructure-file and cloud-provider-config-output-file must be specified.")
}
if len(r.clusterInfrastructureInputFile) != 0 {
if err := kubecloudconfig.ValidateFile(r.clusterInfrastructureInputFile); err != nil {
return err
}
}
}

return nil
}

Expand All @@ -85,28 +115,42 @@ type TemplateData struct {
// Run contains the logic of the render command.
func (r *renderOpts) Run() error {
renderConfig := TemplateData{}

// XXX: What is this file used for?
if len(r.clusterConfigFile) > 0 {
_, err := ioutil.ReadFile(r.clusterConfigFile)
if err != nil {
return err
}
// TODO I'm thinking we parse this into a map and reference it that way
}

if err := r.manifest.ApplyTo(&renderConfig.ManifestConfig); err != nil {
return err
}
if err := r.generic.ApplyTo(
&renderConfig.FileConfig,

// TODO I don't think we have these
genericrenderoptions.Template{},
genericrenderoptions.Template{},

&renderConfig,
nil,
nil, // XXX: Can this be used to merge resources and write out config file? (map[string]resourcemerge.MergeFunc)
); err != nil {
return err
}

return genericrender.WriteFiles(&r.generic, &renderConfig.FileConfig, renderConfig)
if err := genericrender.WriteFiles(&r.generic, &renderConfig.FileConfig, renderConfig); err != nil {
return err
}

if len(r.clusterInfrastructureInputFile) > 0 && len(r.cloudProviderConfigOutputFile) > 0 {
targetCloudConfigMapData, err := kubecloudconfig.BootstrapTransformer(r.clusterInfrastructureInputFile, r.cloudProviderConfigInputFile)
if err != nil {
return err
}
if err := ioutil.WriteFile(r.cloudProviderConfigOutputFile, targetCloudConfigMapData, 0644); err != nil {
return fmt.Errorf("failed to write merged config to %q: %v", r.cloudProviderConfigOutputFile, err)
}
}

return nil
}
86 changes: 86 additions & 0 deletions pkg/operator/kube_cloud_config/bootstrap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package kube_cloud_config

import (
"fmt"
"io/ioutil"
"os"

corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/yaml"

configv1 "github.com/openshift/api/config/v1"
operatorclient "github.com/openshift/cluster-config-operator/pkg/operator/operatorclient"
)

// ValidateFile verifies a file exists, has content, and is a regular file
func ValidateFile(path string) error {
st, err := os.Stat(path)
if err != nil {
return err
}
if !st.Mode().IsRegular() {
return fmt.Errorf("%s is not a regular file.", path)
}
if st.Size() <= 0 {
return fmt.Errorf("%s is empty.", path)
}
return nil
}

func BootstrapTransformer(infrastructureFile string, cloudProviderFile string) ([]byte, error) {

// Read, parse, and save the infrastructure object
var clusterInfrastructure configv1.Infrastructure
fileData, err := ioutil.ReadFile(infrastructureFile)
if err != nil {
return nil, err
}
err = yaml.Unmarshal(fileData, &clusterInfrastructure)
if err != nil {
return nil, err
}

// Read, parse, and save the user provided cloud configmap
var cloudProviderConfigInput corev1.ConfigMap
if len(cloudProviderFile) > 0 {
fileData, err = ioutil.ReadFile(cloudProviderFile)
if err != nil {
return nil, err
}
err = yaml.Unmarshal(fileData, &cloudProviderConfigInput)
if err != nil {
return nil, err
}
}

// Determine the platform type
var platformName configv1.PlatformType
if pstatus := clusterInfrastructure.Status.PlatformStatus; pstatus != nil {
platformName = pstatus.Type
}
if len(platformName) == 0 {
platformName = clusterInfrastructure.Status.Platform
}

// Determine the platform specific transformer method to use
cloudConfigTransformers := cloudConfigTransformers()
cloudConfigTransformerFn, ok := cloudConfigTransformers[platformName]
if !ok {
cloudConfigTransformerFn = asIsTransformer
}
target, err := cloudConfigTransformerFn(&cloudProviderConfigInput, clusterInfrastructure.Spec.CloudConfig.Key, &clusterInfrastructure)
if err != nil {
return nil, err
}

target.Name = targetConfigName
target.Namespace = operatorclient.GlobalMachineSpecifiedConfigNamespace
/* ApplyConfigMap() */

targetCloudConfigMapData, err := yaml.Marshal(target)
if err != nil {
return nil, err
}

return targetCloudConfigMapData, nil
}
20 changes: 13 additions & 7 deletions pkg/operator/kube_cloud_config/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,10 @@ func NewController(operatorClient operatorv1helpers.OperatorClient,
openshiftConfigConfigMapInformer cache.SharedIndexInformer, openshiftConfigManagedConfigMapInformer cache.SharedIndexInformer,
recorder events.Recorder) factory.Controller {
c := &KubeCloudConfigController{
infraClient: infraClient.Infrastructures(),
infraLister: infraLister,
configMapClient: configMapClient,
cloudConfigTransformers: map[configv1.PlatformType]cloudConfigTransformer{
configv1.AWSPlatformType: awsTransformer,
configv1.AzurePlatformType: azureTransformer,
},
infraClient: infraClient.Infrastructures(),
infraLister: infraLister,
configMapClient: configMapClient,
cloudConfigTransformers: cloudConfigTransformers(),
}
return factory.New().
WithInformers(
Expand Down Expand Up @@ -154,3 +151,12 @@ func asIsTransformer(input *corev1.ConfigMap, sourceKey string, _ *configv1.Infr

return output, nil
}

// cloudConfigTransformers returns all configured cloud transformers
func cloudConfigTransformers() map[configv1.PlatformType]cloudConfigTransformer {
cloudConfigTransformers := map[configv1.PlatformType]cloudConfigTransformer{
configv1.AWSPlatformType: awsTransformer,
configv1.AzurePlatformType: azureTransformer,
}
return cloudConfigTransformers
}

0 comments on commit f6b5e2b

Please sign in to comment.