Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ RUN make build

FROM registry.ci.openshift.org/openshift/origin-v4.0:base
COPY --from=builder /go/src/github.com/openshift/cluster-cloud-controller-manager-operator/bin/cluster-controller-manager-operator .
COPY --from=builder /go/src/github.com/openshift/cluster-cloud-controller-manager-operator/bin/render .
COPY --from=builder /go/src/github.com/openshift/cluster-cloud-controller-manager-operator/manifests manifests

LABEL io.openshift.release.operator true
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ unit:
go test ./... -coverprofile cover.out

# Build operator binary
build: fmt vet
build: fmt vet operator render

operator:
go build -o bin/cluster-controller-manager-operator cmd/cluster-cloud-controller-manager-operator/main.go

render:
go build -o bin/render cmd/render/main.go

# Run against the configured Kubernetes cluster in ~/.kube/config
run: fmt vet manifests
go run cmd/cluster-cloud-controller-manager-operator/main.go
Expand Down
96 changes: 96 additions & 0 deletions cmd/render/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package main

import (
"flag"
"fmt"
"os"

"github.com/openshift/cluster-cloud-controller-manager-operator/pkg/render"
"github.com/spf13/cobra"
utilerrors "k8s.io/apimachinery/pkg/util/errors"

"k8s.io/klog/v2"
)

var (
renderCmd = &cobra.Command{
Use: "run",
Short: "Starts Cluster Cloud Controller Manager in render mode",
Long: "",
RunE: runRenderCmd,
}

renderOpts struct {
destinationDir string
clusterInfrastructure string
imagesFile string
}
)

func init() {
renderCmd.PersistentFlags().AddGoFlagSet(flag.CommandLine)
renderCmd.PersistentFlags().StringVar(&renderOpts.destinationDir, "dest-dir", "", "The destination dir where CCCMO writes the generated static pods for CCM.")
renderCmd.PersistentFlags().StringVar(&renderOpts.clusterInfrastructure, "cluster-infrastructure-file", "", "Input path for the cluster infrastructure file.")
renderCmd.PersistentFlags().StringVar(&renderOpts.imagesFile, "images-file", "", "Input path for the images config map file.")
renderCmd.MarkFlagRequired("dest-dir")
renderCmd.MarkFlagRequired("cluster-infrastructure-file")
renderCmd.MarkFlagRequired("images-file")
}

func runRenderCmd(cmd *cobra.Command, args []string) error {
flag.Set("logtostderr", "true")
flag.Parse()

if err := validate(
renderOpts.destinationDir,
renderOpts.clusterInfrastructure,
renderOpts.imagesFile); err != nil {
return err
}

if err := render.New(renderOpts.clusterInfrastructure, renderOpts.imagesFile).Run(renderOpts.destinationDir); err != nil {
return err
}

return nil
}

// validate verifies all file and dirs exist
func validate(destinationDir, clusterInfrastructure, imagesFile string) error {
errs := []error{}
if err := isFile(clusterInfrastructure); err != nil {
klog.Errorf("error reading --cluster-infrastructure-file=%q: %s", clusterInfrastructure, err)
errs = append(errs, fmt.Errorf("error reading --cluster-infrastructure-file: %s", err))
}
if err := isFile(imagesFile); err != nil {
klog.Errorf("error reading --images-file=%q: %s", imagesFile, err)
errs = append(errs, fmt.Errorf("error reading --images-file: %s", err))
}

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

return nil
}

func isFile(path string) error {
st, err := os.Stat(path)
if err != nil {
return err
}
if !st.Mode().IsRegular() {
return fmt.Errorf("%q is not a regular file", path)
}
if st.Size() <= 0 {
return fmt.Errorf("%q is empty", path)
}

return nil
}

func main() {
if err := renderCmd.Execute(); err != nil {
klog.Exitf("Error executing render: %v", err)
}
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/onsi/gomega v1.10.2
github.com/openshift/api v0.0.0-20201216151826-78a19e96f9eb
github.com/openshift/library-go v0.0.0-20210318152630-323ad8a8f7d8
github.com/spf13/cobra v1.1.1
github.com/stretchr/testify v1.7.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/api v0.20.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.10 h1:6q5mVkdH/vYmqngx7kZQTjJ5HRsx+ImorDIEQ+beJgc=
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
Expand Down Expand Up @@ -462,6 +463,7 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
Expand Down
63 changes: 58 additions & 5 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ import (
"path/filepath"

configv1 "github.com/openshift/api/config/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const configMapImagesKey = "images.json"

// imagesReference allows build systems to inject imagesReference for CCCMO components
type imagesReference struct {
CloudControllerManagerAWS string `json:"cloudControllerManagerAWS"`
Expand All @@ -26,6 +30,7 @@ type OperatorConfig struct {
Platform configv1.PlatformType
}

// GetProviderFromInfrastructure reads the Infrastructure resource and returns Platform value
func GetProviderFromInfrastructure(infra *configv1.Infrastructure) (configv1.PlatformType, error) {
if infra == nil || infra.Status.PlatformStatus == nil {
return "", fmt.Errorf("platform status is not populated on infrastructure")
Expand All @@ -37,6 +42,29 @@ func GetProviderFromInfrastructure(infra *configv1.Infrastructure) (configv1.Pla
return infra.Status.PlatformStatus.Type, nil
}

// getImagesFromImagesConfigMap collects the content of provided ConfigMap with images
// via --images-file which is used for rendering bootstrap manifests.
func getImagesFromImagesConfigMap(config *corev1.ConfigMap) (imagesReference, error) {
if config == nil || config.Data == nil {
return imagesReference{}, fmt.Errorf("unable to find Data field in provided ConfigMap")
}

data, ok := config.Data[configMapImagesKey]
if !ok {
return imagesReference{},
fmt.Errorf("unable to find images key %q in ConfigMap %s", configMapImagesKey, client.ObjectKeyFromObject(config))
}

i := imagesReference{}
if err := json.Unmarshal([]byte(data), &i); err != nil {
return imagesReference{},
fmt.Errorf("unable to decode images content from ConfigMap %s: %v", client.ObjectKeyFromObject(config), err)
}
return i, nil
}

// getImagesFromJSONFile is used in operator to read the content of mounted ConfigMap
// containing images for substitution in templates
func getImagesFromJSONFile(filePath string) (imagesReference, error) {
data, err := ioutil.ReadFile(filepath.Clean(filePath))
if err != nil {
Expand All @@ -50,6 +78,7 @@ func getImagesFromJSONFile(filePath string) (imagesReference, error) {
return i, nil
}

// getCloudControllerManagerFromImages returns a CCM binary image later used in substitution
func getCloudControllerManagerFromImages(platform configv1.PlatformType, images imagesReference) string {
switch platform {
case configv1.AWSPlatformType:
Expand All @@ -72,20 +101,44 @@ func getCloudNodeManagerFromImages(platform configv1.PlatformType, images images
}
}

// ComposeConfig creates a Config for operator
func ComposeConfig(platform configv1.PlatformType, imagesFile, managedNamespace string) (OperatorConfig, error) {
images, err := getImagesFromJSONFile(imagesFile)
if err != nil {
klog.Errorf("Unable to decode images file from location %s", imagesFile, err)
return OperatorConfig{}, err
}

config := OperatorConfig{
Platform: platform,
ManagedNamespace: managedNamespace,
ControllerImage: getCloudControllerManagerFromImages(platform, images),
CloudNodeImage: getCloudNodeManagerFromImages(platform, images),
}

images, err := getImagesFromJSONFile(imagesFile)
return config, nil
}

// ComposeBootstrapConfig creates a Config for render
func ComposeBootstrapConfig(infra *configv1.Infrastructure, imagesConfig *corev1.ConfigMap, managedNamespace string) (OperatorConfig, error) {
platform, err := GetProviderFromInfrastructure(infra)
if err != nil {
klog.Errorf("Unable to decode images file from location %s", imagesFile, err)
return config, err
klog.Errorf("Unable to detemine platform from cluster infrastrucutre file: %s", err)
return OperatorConfig{}, err
}

config.ControllerImage = getCloudControllerManagerFromImages(platform, images)
config.CloudNodeImage = getCloudNodeManagerFromImages(platform, images)
images, err := getImagesFromImagesConfigMap(imagesConfig)
if err != nil {
klog.Errorf("Unable to decode images file from location %s", images, err)
return OperatorConfig{}, err
}

config := OperatorConfig{
Platform: platform,
ManagedNamespace: managedNamespace,
ControllerImage: getCloudControllerManagerFromImages(platform, images),
CloudNodeImage: getCloudNodeManagerFromImages(platform, images),
}

return config, nil
}
Loading