Skip to content

Commit

Permalink
Inject proxy env. variable to CSI snapshot controller
Browse files Browse the repository at this point in the history
  • Loading branch information
jsafrane committed Jan 13, 2021
1 parent 77f32fb commit ac74676
Show file tree
Hide file tree
Showing 14 changed files with 959 additions and 4 deletions.
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -21,7 +21,7 @@ require (
go.uber.org/zap v1.16.0 // indirect
golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
golang.org/x/text v0.3.5 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.20.1
k8s.io/apiextensions-apiserver v0.20.0
k8s.io/apimachinery v0.20.1
Expand Down
@@ -0,0 +1,51 @@
package configobservercontroller

import (
"github.com/openshift/library-go/pkg/operator/v1helpers"
"k8s.io/client-go/tools/cache"

cfginformers "github.com/openshift/client-go/config/informers/externalversions"
"github.com/openshift/library-go/pkg/controller/factory"
"github.com/openshift/library-go/pkg/operator/configobserver"
"github.com/openshift/library-go/pkg/operator/configobserver/proxy"
"github.com/openshift/library-go/pkg/operator/events"

"github.com/openshift/cluster-csi-snapshot-controller-operator/pkg/operator/configobservation"
"github.com/openshift/cluster-csi-snapshot-controller-operator/pkg/operator/configobservation/util"
)

// ConfigObserverController watches information that's relevant to CSI snapshot controller operatror and adds
// it to CR.Spec.ObservedConfig.
type ConfigObserverController struct {
factory.Controller
}

// NewConfigObserverController returns a new ConfigObserverController.
func NewConfigObserverController(
operatorClient v1helpers.OperatorClient,
configInformer cfginformers.SharedInformerFactory,
eventRecorder events.Recorder,
) *ConfigObserverController {
informers := []factory.Informer{
operatorClient.Informer(),
configInformer.Config().V1().Proxies().Informer(),
}

c := &ConfigObserverController{
Controller: configobserver.NewConfigObserver(
operatorClient,
eventRecorder.WithComponentSuffix("config-observer-controller-"),
configobservation.Listers{
ProxyLister_: configInformer.Config().V1().Proxies().Lister(),
PreRunCachesSynced: append([]cache.InformerSynced{},
operatorClient.Informer().HasSynced,
configInformer.Config().V1().Proxies().Informer().HasSynced,
),
},
informers,
proxy.NewProxyObserveFunc(util.ProxyConfigPath()),
),
}

return c
}
27 changes: 27 additions & 0 deletions pkg/operator/configobservation/interface.go
@@ -0,0 +1,27 @@
package configobservation

import (
configlistersv1 "github.com/openshift/client-go/config/listers/config/v1"
"github.com/openshift/library-go/pkg/operator/resourcesynccontroller"
"k8s.io/client-go/tools/cache"
)

// Listers implement the configobserver.Listers interface.
type Listers struct {
ProxyLister_ configlistersv1.ProxyLister

ResourceSync resourcesynccontroller.ResourceSyncer
PreRunCachesSynced []cache.InformerSynced
}

func (l Listers) ProxyLister() configlistersv1.ProxyLister {
return l.ProxyLister_
}

func (l Listers) ResourceSyncer() resourcesynccontroller.ResourceSyncer {
return l.ResourceSync
}

func (l Listers) PreRunHasSynced() []cache.InformerSynced {
return l.PreRunCachesSynced
}
29 changes: 29 additions & 0 deletions pkg/operator/configobservation/util/util.go
@@ -0,0 +1,29 @@
package util

import (
appsv1 "k8s.io/api/apps/v1"

operatorapi "github.com/openshift/api/operator/v1"
"github.com/openshift/library-go/pkg/operator/v1helpers"
)

// InjectObservedProxyInDeploymentContainers takes an observed proxy config and returns a patched Deployment with proxy env vars set.
func InjectObservedProxyInDeploymentContainers(deployment *appsv1.Deployment, opSpec *operatorapi.OperatorSpec) (*appsv1.Deployment, error) {
deploymentCopy := deployment.DeepCopy()
containers, err := v1helpers.InjectObservedProxyIntoContainers(
deploymentCopy.Spec.Template.Spec.Containers,
opSpec.ObservedConfig.Raw,
ProxyConfigPath()...,
)
if err != nil {
return nil, err
}
deploymentCopy.Spec.Template.Spec.Containers = containers
return deploymentCopy, nil
}

// ProxyConfigPath returns the path for the observed proxy config. This is a
// function to avoid exposing a slice that could potentially be appended.
func ProxyConfigPath() []string {
return []string{"targetconfig", "proxy"}
}
47 changes: 45 additions & 2 deletions pkg/operator/operator_test.go
Expand Up @@ -16,12 +16,15 @@ import (
"github.com/openshift/library-go/pkg/operator/resource/resourceapply"
"github.com/openshift/library-go/pkg/operator/resource/resourceread"
"github.com/openshift/library-go/pkg/operator/status"
"gopkg.in/yaml.v2"
appsv1 "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
fakeextapi "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
apiextinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions"
"k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
coreinformers "k8s.io/client-go/informers"
fakecore "k8s.io/client-go/kubernetes/fake"
Expand Down Expand Up @@ -244,6 +247,16 @@ func withFalseConditions(conditions ...string) csiSnapshotControllerModifier {
}
}

func withHTTPProxy(proxy string) csiSnapshotControllerModifier {
return func(i *opv1.CSISnapshotController) *opv1.CSISnapshotController {
observedConfig := map[string]interface{}{}
unstructured.SetNestedStringMap(observedConfig, map[string]string{"HTTP_PROXY": proxy}, "targetconfig", "proxy")
d, _ := yaml.Marshal(observedConfig)
i.Spec.ObservedConfig = runtime.RawExtension{Raw: d, Object: &unstructured.Unstructured{Object: observedConfig}}
return i
}
}

// Deployments

type deploymentModifier func(*appsv1.Deployment) *appsv1.Deployment
Expand All @@ -259,11 +272,10 @@ func getDeployment(args []string, image string, modifiers ...deploymentModifier)
if dep.Annotations == nil {
dep.Annotations = map[string]string{}
}
resourceapply.SetSpecHashAnnotation(&dep.ObjectMeta, dep.Spec)

for _, modifier := range modifiers {
dep = modifier(dep)
}
resourceapply.SetSpecHashAnnotation(&dep.ObjectMeta, dep.Spec)

return dep
}
Expand Down Expand Up @@ -294,6 +306,16 @@ func withDeploymentGeneration(generations ...int64) deploymentModifier {
}
}

func withDeploymentHTTPProxyEnv(proxy string) deploymentModifier {
return func(instance *appsv1.Deployment) *appsv1.Deployment {
containers := instance.Spec.Template.Spec.Containers
for i := range containers {
containers[i].Env = append(containers[i].Env, v1.EnvVar{Name: "HTTP_PROXY", Value: proxy})
}
return instance
}
}

// CRDs

type crdModifier func(*apiextv1.CustomResourceDefinition) *apiextv1.CustomResourceDefinition
Expand Down Expand Up @@ -670,6 +692,27 @@ func TestSync(t *testing.T) {
crds: addCRDEstablishedRector,
},
},
{
// Proxy env. var is injected into Deployment
name: "proxy injection",
image: defaultImage,
initialObjects: testObjects{
csiSnapshotController: csiSnapshotController(withHTTPProxy("http://proxy.com")),
},
expectedObjects: testObjects{
crds: getCRDs(),
deployment: getDeployment(argsLevel2, defaultImage, withDeploymentGeneration(1, 0), withDeploymentHTTPProxyEnv("http://proxy.com")),
csiSnapshotController: csiSnapshotController(
withHTTPProxy("http://proxy.com"),
withStatus(replica0),
withGenerations(1),
withTrueConditions(opv1.OperatorStatusTypeUpgradeable, opv1.OperatorStatusTypePrereqsSatisfied, opv1.OperatorStatusTypeProgressing),
withFalseConditions(opv1.OperatorStatusTypeDegraded, opv1.OperatorStatusTypeAvailable)),
},
reactors: testReactors{
crds: addCRDEstablishedRector,
},
},

// TODO: more error cases? Deployment creation fails and things like that?
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/operator/starter.go
Expand Up @@ -13,6 +13,7 @@ import (
csisnapshotconfigclient "github.com/openshift/client-go/operator/clientset/versioned"
informer "github.com/openshift/client-go/operator/informers/externalversions"
"github.com/openshift/cluster-csi-snapshot-controller-operator/pkg/common"
"github.com/openshift/cluster-csi-snapshot-controller-operator/pkg/operator/configobservation/configobservercontroller"
"github.com/openshift/cluster-csi-snapshot-controller-operator/pkg/operator/webhookdeployment"
"github.com/openshift/cluster-csi-snapshot-controller-operator/pkg/operatorclient"
"github.com/openshift/library-go/pkg/controller/controllercmd"
Expand Down Expand Up @@ -105,6 +106,9 @@ func RunOperator(ctx context.Context, controllerConfig *controllercmd.Controller
managementStateController := management.NewOperatorManagementStateController(targetName, operatorClient, controllerConfig.EventRecorder)
management.SetOperatorNotRemovable()

// This controller observes a config (proxy for now) and writes it to CR.Spec.ObservedConfig for later use by the operator
configObserverController := configobservercontroller.NewConfigObserverController(operatorClient, configInformers, controllerConfig.EventRecorder)

klog.Info("Starting the Informers.")
for _, informer := range []interface {
Start(stopCh <-chan struct{})
Expand All @@ -125,6 +129,7 @@ func RunOperator(ctx context.Context, controllerConfig *controllercmd.Controller
logLevelController,
managementStateController,
webhookOperator,
configObserverController,
} {
go controller.Run(ctx, 1)
}
Expand Down
8 changes: 7 additions & 1 deletion pkg/operator/sync.go
Expand Up @@ -5,6 +5,7 @@ import (
"strings"
"time"

"github.com/openshift/cluster-csi-snapshot-controller-operator/pkg/operator/configobservation/util"
appsv1 "k8s.io/api/apps/v1"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -110,7 +111,12 @@ func (c *csiSnapshotOperator) checkAlphaCRDs() error {
func (c *csiSnapshotOperator) syncDeployment(instance *operatorv1.CSISnapshotController) (*appsv1.Deployment, error) {
deploy := c.getExpectedDeployment(instance)

deploy, _, err := resourceapply.ApplyDeployment(
deploy, err := util.InjectObservedProxyInDeploymentContainers(deploy, &instance.Spec.OperatorSpec)
if err != nil {
return nil, err
}

deploy, _, err = resourceapply.ApplyDeployment(
c.kubeClient.AppsV1(),
c.eventRecorder,
deploy,
Expand Down

0 comments on commit ac74676

Please sign in to comment.