diff --git a/Gopkg.lock b/Gopkg.lock index 38d39e95c..4d90b63aa 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -975,6 +975,7 @@ "k8s.io/apimachinery/pkg/util/runtime", "k8s.io/apimachinery/pkg/util/yaml", "k8s.io/client-go/discovery", + "k8s.io/client-go/kubernetes", "k8s.io/client-go/plugin/pkg/client/auth/gcp", "k8s.io/client-go/rest", "k8s.io/client-go/restmapper", diff --git a/README.md b/README.md index cec88d409..04f54600d 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,20 @@ spec: Additionally, container image used to deliver this plugin can be set using `LINUX_BRIDGE_IMAGE` environment variable in operator deployment manifest. +## Image Pull Policy + +Administrator can specify [image pull policy](https://kubernetes.io/docs/concepts/containers/images/) +for deployed components. Default is `IfNotPresent`. + +```yaml +apiVersion: networkaddonsoperator.network.kubevirt.io/v1alpha1 +kind: NetworkAddonsConfig +metadata: + name: cluster +spec: + imagePullPolicy: Always +``` + # Deployment First install the operator itself: diff --git a/config-example.yaml b/config-example.yaml index a05dfabd0..6dcc4d085 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -5,3 +5,4 @@ metadata: spec: multus: {} linuxBridge: {} + imagePullPolicy: Always diff --git a/data/multus/002-multus.yaml b/data/multus/002-multus.yaml index a26e69883..621a50136 100644 --- a/data/multus/002-multus.yaml +++ b/data/multus/002-multus.yaml @@ -47,6 +47,7 @@ spec: command: ["/entrypoint.sh"] args: ["--multus-conf-file=auto"] image: {{ .MultusImage }} + imagePullPolicy: {{ .ImagePullPolicy }} resources: requests: cpu: "100m" diff --git a/deploy/cluster-network-addons-operator_03_deployment.yaml b/deploy/cluster-network-addons-operator_03_deployment.yaml index 9e83fd690..392e4af02 100644 --- a/deploy/cluster-network-addons-operator_03_deployment.yaml +++ b/deploy/cluster-network-addons-operator_03_deployment.yaml @@ -25,8 +25,6 @@ spec: cpu: 10m memory: 50Mi env: - - name: IMAGE_PULL_POLICY - value: "Always" - name: MULTUS_IMAGE value: "docker.io/nfvpe/multus:latest" - name: LINUX_BRIDGE_IMAGE diff --git a/pkg/apis/networkaddonsoperator/v1alpha1/networkaddonsconfig_types.go b/pkg/apis/networkaddonsoperator/v1alpha1/networkaddonsconfig_types.go index ae2730cc1..1ef3a924c 100644 --- a/pkg/apis/networkaddonsoperator/v1alpha1/networkaddonsconfig_types.go +++ b/pkg/apis/networkaddonsoperator/v1alpha1/networkaddonsconfig_types.go @@ -7,8 +7,9 @@ import ( // NetworkAddonsConfigSpec defines the desired state of NetworkAddonsConfig // +k8s:openapi-gen=true type NetworkAddonsConfigSpec struct { - Multus *Multus `json:"multus,omitempty"` - LinuxBridge *LinuxBridge `json:"linuxBridge,omitempty"` + Multus *Multus `json:"multus,omitempty"` + LinuxBridge *LinuxBridge `json:"linuxBridge,omitempty"` + ImagePullPolicy string `json:"imagePullPolicy,omitempty"` } // +k8s:openapi-gen=true diff --git a/pkg/network/image-pull-policy.go b/pkg/network/image-pull-policy.go new file mode 100644 index 000000000..5d6a1be79 --- /dev/null +++ b/pkg/network/image-pull-policy.go @@ -0,0 +1,54 @@ +package network + +import ( + "github.com/pkg/errors" + v1 "k8s.io/api/core/v1" + + opv1alpha1 "github.com/kubevirt/cluster-network-addons-operator/pkg/apis/networkaddonsoperator/v1alpha1" +) + +const defaultImagePullPolicy = string(v1.PullIfNotPresent) + +func validateImagePullPolicy(conf *opv1alpha1.NetworkAddonsConfigSpec) []error { + if conf.ImagePullPolicy == "" { + return []error{} + } + + if valid := verifyPullPolicyType(conf.ImagePullPolicy); !valid { + return []error{errors.Errorf("requested imagePullPolicy '%s' is not valid", conf.ImagePullPolicy)} + } + + return []error{} +} + +func fillDefaultsImagePullPolicy(conf, previous *opv1alpha1.NetworkAddonsConfigSpec) { + if conf.ImagePullPolicy == "" { + if previous != nil && previous.ImagePullPolicy != "" { + conf.ImagePullPolicy = previous.ImagePullPolicy + } else { + conf.ImagePullPolicy = defaultImagePullPolicy + } + } +} + +func changeSafeImagePullPolicy(prev, next *opv1alpha1.NetworkAddonsConfigSpec) []error { + if prev.ImagePullPolicy != "" && prev.ImagePullPolicy != next.ImagePullPolicy { + return []error{errors.Errorf("cannot modify ImagePullPolicy configuration once components were deployed")} + } + return nil +} + +// Verify if the value is a valid PullPolicy +func verifyPullPolicyType(policy string) bool { + imagePullPolicy := v1.PullPolicy(policy) + switch imagePullPolicy { + case v1.PullAlways: + return true + case v1.PullNever: + return true + case v1.PullIfNotPresent: + return true + default: + return false + } +} diff --git a/pkg/network/linux-bridge.go b/pkg/network/linux-bridge.go index 82ae33c08..79e029f31 100644 --- a/pkg/network/linux-bridge.go +++ b/pkg/network/linux-bridge.go @@ -28,7 +28,7 @@ func renderLinuxBridge(conf *opv1alpha1.NetworkAddonsConfigSpec, manifestDir str // render the manifests on disk data := render.MakeRenderData() data.Data["LinuxBridgeImage"] = os.Getenv("LINUX_BRIDGE_IMAGE") - data.Data["ImagePullPolicy"] = os.Getenv("IMAGE_PULL_POLICY") + data.Data["ImagePullPolicy"] = conf.ImagePullPolicy data.Data["EnableSCC"] = enableSCC objs, err := render.RenderDir(filepath.Join(manifestDir, "linux-bridge"), &data) diff --git a/pkg/network/multus.go b/pkg/network/multus.go index 6fe2b2eab..05433c83a 100644 --- a/pkg/network/multus.go +++ b/pkg/network/multus.go @@ -44,6 +44,7 @@ func renderMultus(conf *opv1alpha1.NetworkAddonsConfigSpec, manifestDir string, // render manifests from disk data := render.MakeRenderData() data.Data["MultusImage"] = os.Getenv("MULTUS_IMAGE") + data.Data["ImagePullPolicy"] = conf.ImagePullPolicy data.Data["EnableSCC"] = enableSCC objs, err := render.RenderDir(filepath.Join(manifestDir, "multus"), &data) diff --git a/pkg/network/network.go b/pkg/network/network.go index 9e159dc8c..f322e93b0 100644 --- a/pkg/network/network.go +++ b/pkg/network/network.go @@ -22,6 +22,7 @@ func Validate(conf *opv1alpha1.NetworkAddonsConfigSpec, openshiftNetworkConfig * errs := []error{} errs = append(errs, validateMultus(conf, openshiftNetworkConfig)...) + errs = append(errs, validateImagePullPolicy(conf)...) if len(errs) > 0 { return errors.Errorf("invalid configuration: %v", errs) @@ -35,7 +36,7 @@ func Validate(conf *opv1alpha1.NetworkAddonsConfigSpec, openshiftNetworkConfig * // Defaults are carried forward from previous if it is provided. This is so we // can change defaults as we move forward, but won't disrupt existing clusters. func FillDefaults(conf, previous *opv1alpha1.NetworkAddonsConfigSpec) { - // TODO + fillDefaultsImagePullPolicy(conf, previous) } // IsChangeSafe checks to see if the change between prev and next are allowed @@ -54,6 +55,7 @@ func IsChangeSafe(prev, next *opv1alpha1.NetworkAddonsConfigSpec) error { errs = append(errs, changeSafeMultus(prev, next)...) errs = append(errs, changeSafeLinuxBridge(prev, next)...) + errs = append(errs, changeSafeImagePullPolicy(prev, next)...) if len(errs) > 0 { return errors.Errorf("invalid configuration: %v", errs)