Skip to content

Commit

Permalink
Add env. var replacer + unit test for it
Browse files Browse the repository at this point in the history
  • Loading branch information
jsafrane committed Oct 20, 2022
1 parent e6e785e commit f0bd4c7
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 69 deletions.
@@ -0,0 +1,82 @@
package storage

import (
v1 "k8s.io/api/core/v1"
)

var (
// map env. variable in CSO Deployment -> name of the image in payload.
operatorImageRefs = map[string]string{
"AWS_EBS_DRIVER_OPERATOR_IMAGE": "aws-ebs-csi-driver-operator",
"AWS_EBS_DRIVER_IMAGE": "aws-ebs-csi-driver",
"GCP_PD_DRIVER_OPERATOR_IMAGE": "gcp-pd-csi-driver-operator",
"GCP_PD_DRIVER_IMAGE": "gcp-pd-csi-driver",
"OPENSTACK_CINDER_DRIVER_OPERATOR_IMAGE": "openstack-cinder-csi-driver-operator",
"OPENSTACK_CINDER_DRIVER_IMAGE": "openstack-cinder-csi-driver",
"OVIRT_DRIVER_OPERATOR_IMAGE": "ovirt-csi-driver-operator",
"OVIRT_DRIVER_IMAGE": "ovirt-csi-driver",
"MANILA_DRIVER_OPERATOR_IMAGE": "csi-driver-manila-operator",
"MANILA_DRIVER_IMAGE": "csi-driver-manila",
"MANILA_NFS_DRIVER_IMAGE": "csi-driver-nfs",
"PROVISIONER_IMAGE": "csi-external-provisioner",
"ATTACHER_IMAGE": "csi-external-attacher",
"RESIZER_IMAGE": "csi-external-resizer",
"SNAPSHOTTER_IMAGE": "csi-external-snapshotter",
"NODE_DRIVER_REGISTRAR_IMAGE": "csi-node-driver-registrar",
"LIVENESS_PROBE_IMAGE": "csi-livenessprobe",
"VSPHERE_PROBLEM_DETECTOR_OPERATOR_IMAGE": "vsphere-problem-detector",
"AZURE_DISK_DRIVER_OPERATOR_IMAGE": "azure-disk-csi-driver-operator",
"AZURE_DISK_DRIVER_IMAGE": "azure-disk-csi-driver",
"AZURE_FILE_DRIVER_OPERATOR_IMAGE": "azure-file-csi-driver-operator",
"AZURE_FILE_DRIVER_IMAGE": "azure-file-csi-driver",
"KUBE_RBAC_PROXY_IMAGE": "kube-rbac-proxy",
"VMWARE_VSPHERE_DRIVER_OPERATOR_IMAGE": "vsphere-csi-driver-operator",
"VMWARE_VSPHERE_DRIVER_IMAGE": "vsphere-csi-driver",
"VMWARE_VSPHERE_SYNCER_IMAGE": "vsphere-csi-driver-syncer",
"CLUSTER_CLOUD_CONTROLLER_MANAGER_OPERATOR_IMAGE": "cluster-cloud-controller-manager-operator",
"SHARED_RESOURCE_DRIVER_OPERATOR_IMAGE": "csi-driver-shared-resource-operator",
"SHARED_RESOURCE_DRIVER_IMAGE": "csi-driver-shared-resource",
"SHARED_RESOURCE_DRIVER_WEBHOOK_IMAGE": "csi-driver-shared-resource-webhook",
"ALIBABA_DISK_DRIVER_OPERATOR_IMAGE": "alibaba-disk-csi-driver-operator",
"ALIBABA_CLOUD_DRIVER_IMAGE": "alibaba-cloud-csi-driver",
"IBM_VPC_BLOCK_DRIVER_OPERATOR_IMAGE": "ibm-vpc-block-csi-driver-operator",
"IBM_VPC_BLOCK_DRIVER_IMAGE": "ibm-vpc-block-csi-driver",
"IBM_VPC_NODE_LABEL_UPDATER_IMAGE": "ibm-vpc-node-label-updater",
"POWERVS_BLOCK_CSI_DRIVER_OPERATOR_IMAGE": "powervs-block-csi-driver-operator",
"POWERVS_BLOCK_CSI_DRIVER_IMAGE": "powervs-block-csi-driver",
"HYPERSHIFT_IMAGE": "token-minter",
}
)

type environmentReplacer struct {
// map env variable name -> new env. variable value
values map[string]string
}

func newEnvironmentReplacer() *environmentReplacer {
return &environmentReplacer{values: map[string]string{}}
}

func (er *environmentReplacer) setOperatorImageReferences(images map[string]string) {
// `operatorImageRefs` is map from env. var name -> payload image name
// `images` is map from payload image name -> image URL
// Create map from env. var name -> image URL
for envVar, payloadName := range operatorImageRefs {
if imageURL, ok := images[payloadName]; ok {
er.values[envVar] = imageURL
}
}
}

func (er *environmentReplacer) setVersions(ver string) {
er.values["OPERATOR_IMAGE_VERSION"] = ver
er.values["OPERAND_IMAGE_VERSION"] = ver
}

func (er *environmentReplacer) replaceEnvVars(envVars []v1.EnvVar) {
for i := range envVars {
if value, ok := er.values[envVars[i].Name]; ok {
envVars[i].Value = value
}
}
}
@@ -0,0 +1,53 @@
package storage

import (
"crypto/md5"
"encoding/hex"
"strings"
"testing"

"github.com/openshift/hypershift/control-plane-operator/controllers/hostedcontrolplane/common"
"github.com/openshift/hypershift/control-plane-operator/controllers/hostedcontrolplane/storage/assets"
"k8s.io/apimachinery/pkg/util/rand"
)

func TestEnvironmentReplacer(t *testing.T) {
// Test that EnvironmentReplaces replaces **all** env. vars in the operator Deployment.
// This protects us from adding a new image to assets/10_deployment-hypershift.yaml
// and not adding it to envreplace.go.

// All image URLs will point to hash(env. name)
images := map[string]string{}
for envVarName, payloadName := range operatorImageRefs {
images[payloadName] = hash(envVarName)
}

er := newEnvironmentReplacer()
er.setOperatorImageReferences(images)
version := rand.String(10)
er.setVersions(version)

deployment := common.MustDeployment(assets.ReadFile, "10_deployment-hypershift.yaml")
er.replaceEnvVars(deployment.Spec.Template.Spec.Containers[0].Env)

// Check that all env. vars were replaced.
// Feel free to add exceptions in the future, but right now *all* env. vars of the operator
// refer either to version or image name.
for _, env := range deployment.Spec.Template.Spec.Containers[0].Env {
if strings.HasSuffix(env.Name, "_VERSION") {
if env.Value != version {
t.Errorf("Environment variable %q in assets/10_deployment-hypershift.yaml was not replaced by the operator. Please update envreplace.go!", env.Name)
}
continue
}
// Not version -> it must be an image name
if env.Value != hash(env.Name) {
t.Errorf("Environment variable %q in assets/10_deployment-hypershift.yaml was not replaced by the operator. Please update envreplace.go!", env.Name)
}
}
}

func hash(data string) string {
hashBytes := md5.Sum([]byte(data))
return hex.EncodeToString(hashBytes[0:])
}
Expand Up @@ -27,22 +27,7 @@ func ReconcileOperatorDeployment(
switch container.Name {
case "cluster-storage-operator":
deployment.Spec.Template.Spec.Containers[i].Image = params.StorageOperatorImage
// Substitute env. vars
for j, env := range deployment.Spec.Template.Spec.Containers[i].Env {
// Substitute image names in env. vars
for envName, imageName := range params.EnvImages {
if env.Name == envName {
deployment.Spec.Template.Spec.Containers[i].Env[j].Value = imageName
}
}
// Substitute other env vars.
switch env.Name {
case "OPERATOR_IMAGE_VERSION":
deployment.Spec.Template.Spec.Containers[i].Env[j].Value = params.Version
case "OPERAND_IMAGE_VERSION":
deployment.Spec.Template.Spec.Containers[i].Env[j].Value = params.Version
}
}
params.ImageReplacer.replaceEnvVars(deployment.Spec.Template.Spec.Containers[i].Env)
}
}

Expand Down
Expand Up @@ -11,58 +11,12 @@ const (
storageOperatorImageName = "cluster-storage-operator"
)

var (
// map env. variable in CSO Deployment -> key in `images` map (= name of the image in payload).
operatorImageRefs = map[string]string{
"AWS_EBS_DRIVER_OPERATOR_IMAGE": "aws-ebs-csi-driver-operator",
"AWS_EBS_DRIVER_IMAGE": "aws-ebs-csi-driver",
"GCP_PD_DRIVER_OPERATOR_IMAGE": "gcp-pd-csi-driver-operator",
"GCP_PD_DRIVER_IMAGE": "gcp-pd-csi-driver",
"OPENSTACK_CINDER_DRIVER_OPERATOR_IMAGE": "openstack-cinder-csi-driver-operator",
"OPENSTACK_CINDER_DRIVER_IMAGE": "openstack-cinder-csi-driver",
"OVIRT_DRIVER_OPERATOR_IMAGE": "ovirt-csi-driver-operator",
"OVIRT_DRIVER_IMAGE": "ovirt-csi-driver",
"MANILA_DRIVER_OPERATOR_IMAGE": "csi-driver-manila-operator",
"MANILA_DRIVER_IMAGE": "csi-driver-manila",
"MANILA_NFS_DRIVER_IMAGE": "csi-driver-nfs",
"PROVISIONER_IMAGE": "csi-external-provisioner",
"ATTACHER_IMAGE": "csi-external-attacher",
"RESIZER_IMAGE": "csi-external-resizer",
"SNAPSHOTTER_IMAGE": "csi-external-snapshotter",
"NODE_DRIVER_REGISTRAR_IMAGE": "csi-node-driver-registrar",
"LIVENESS_PROBE_IMAGE": "csi-livenessprobe",
"VSPHERE_PROBLEM_DETECTOR_OPERATOR_IMAGE": "vsphere-problem-detector",
"AZURE_DISK_DRIVER_OPERATOR_IMAGE": "azure-disk-csi-driver-operator",
"AZURE_DISK_DRIVER_IMAGE": "azure-disk-csi-driver",
"AZURE_FILE_DRIVER_OPERATOR_IMAGE": "azure-file-csi-driver-operator",
"AZURE_FILE_DRIVER_IMAGE": "azure-file-csi-driver",
"KUBE_RBAC_PROXY_IMAGE": "kube-rbac-proxy",
"VMWARE_VSPHERE_DRIVER_OPERATOR_IMAGE": "vsphere-csi-driver-operator",
"VMWARE_VSPHERE_DRIVER_IMAGE": "vsphere-csi-driver",
"VMWARE_VSPHERE_SYNCER_IMAGE": "vsphere-csi-driver-syncer",
"CLUSTER_CLOUD_CONTROLLER_MANAGER_OPERATOR_IMAGE": "cluster-cloud-controller-manager-operator",
"SHARED_RESOURCE_DRIVER_OPERATOR_IMAGE": "csi-driver-shared-resource-operator",
"SHARED_RESOURCE_DRIVER_IMAGE": "csi-driver-shared-resource",
"SHARED_RESOURCE_DRIVER_WEBHOOK_IMAGE": "csi-driver-shared-resource-webhook",
"ALIBABA_DISK_DRIVER_OPERATOR_IMAGE": "alibaba-disk-csi-driver-operator",
"ALIBABA_CLOUD_DRIVER_IMAGE": "alibaba-cloud-csi-driver",
"IBM_VPC_BLOCK_DRIVER_OPERATOR_IMAGE": "ibm-vpc-block-csi-driver-operator",
"IBM_VPC_BLOCK_DRIVER_IMAGE": "ibm-vpc-block-csi-driver",
"IBM_VPC_NODE_LABEL_UPDATER_IMAGE": "ibm-vpc-node-label-updater",
"POWERVS_BLOCK_CSI_DRIVER_OPERATOR_IMAGE": "powervs-block-csi-driver-operator",
"POWERVS_BLOCK_CSI_DRIVER_IMAGE": "powervs-block-csi-driver",
"HYPERSHIFT_IMAGE": "token-minter",
}
)

type Params struct {
OwnerRef config.OwnerRef
StorageOperatorImage string
// Map env. variable -> image name
EnvImages map[string]string
ImageReplacer *environmentReplacer

AvailabilityProberImage string
Version string
APIPort *int32
config.DeploymentConfig
}
Expand All @@ -73,19 +27,18 @@ func NewParams(
images map[string]string,
setDefaultSecurityContext bool) *Params {

ir := newEnvironmentReplacer()
ir.setVersions(version)
ir.setOperatorImageReferences(images)

params := Params{
OwnerRef: config.OwnerRefFrom(hcp),
StorageOperatorImage: images[storageOperatorImageName],
AvailabilityProberImage: images[util.AvailabilityProberImageName],
EnvImages: make(map[string]string),
Version: version,
ImageReplacer: ir,
APIPort: util.APIPort(hcp),
}

for envVar, imageRef := range operatorImageRefs {
params.EnvImages[envVar] = images[imageRef]
}

params.DeploymentConfig.SetDefaultSecurityContext = setDefaultSecurityContext
// Run only one replica of the operator
params.DeploymentConfig.Scheduling = config.Scheduling{
Expand Down

0 comments on commit f0bd4c7

Please sign in to comment.