Skip to content

Commit

Permalink
Consolidate transformers for common CRD fields, registry and config
Browse files Browse the repository at this point in the history
Fixes knative#26

Also factored the common test utilities out of images.go and into a
common/testing package.

All tests should remain intact -- eventing had a few more than serving
-- now all in a single place.
  • Loading branch information
jcrossley3 committed Apr 22, 2020
1 parent cf1f02a commit d83df59
Show file tree
Hide file tree
Showing 15 changed files with 314 additions and 704 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,14 @@ import (
mf "github.com/manifestival/manifestival"
"go.uber.org/zap"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
eventingv1alpha1 "knative.dev/operator/pkg/apis/operator/v1alpha1"
)

// ConfigMapTransform updates the ConfigMap with the values specified in operator CR
func ConfigMapTransform(instance *eventingv1alpha1.KnativeEventing, log *zap.SugaredLogger) mf.Transformer {
func ConfigMapTransform(config map[string]map[string]string, log *zap.SugaredLogger) mf.Transformer {
return func(u *unstructured.Unstructured) error {
// Let any config in instance override everything else
if u.GetKind() == "ConfigMap" {
if data, ok := instance.Spec.Config[u.GetName()[len(`config-`):]]; ok {
if data, ok := config[u.GetName()[len(`config-`):]]; ok {
UpdateConfigMap(u, data, log)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/scheme"
eventingv1alpha1 "knative.dev/operator/pkg/apis/operator/v1alpha1"
util "knative.dev/operator/pkg/reconciler/common/testing"
)

type configMapData struct {
Expand Down Expand Up @@ -99,23 +99,18 @@ func TestConfigMapTransform(t *testing.T) {
}

func runConfigMapTransformTest(t *testing.T, tt *updateConfigMapTest) {
unstructuredConfigMap := makeUnstructured(t, &tt.configMap)
instance := &eventingv1alpha1.KnativeEventing{
Spec: eventingv1alpha1.KnativeEventingSpec{
Config: map[string]map[string]string{
tt.config.name: tt.config.data,
},
},
unstructuredConfigMap := util.MakeUnstructured(t, &tt.configMap)
config := map[string]map[string]string{
tt.config.name: tt.config.data,
}

configMapTransform := ConfigMapTransform(instance, log)
configMapTransform := ConfigMapTransform(config, log)
configMapTransform(&unstructuredConfigMap)
validateConfigMapChanged(t, tt, &unstructuredConfigMap)
}

func validateConfigMapChanged(t *testing.T, tt *updateConfigMapTest, u *unstructured.Unstructured) {
var configMap = &corev1.ConfigMap{}
err := scheme.Scheme.Convert(u, configMap, nil)
assertEqual(t, err, nil)
assertDeepEqual(t, configMap.Data, tt.expected.Data)
util.AssertEqual(t, err, nil)
util.AssertDeepEqual(t, configMap.Data, tt.expected.Data)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2019 The Knative Authors
Copyright 2020 The Knative Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package common

import (
Expand All @@ -26,7 +27,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/kubernetes/scheme"
caching "knative.dev/caching/pkg/apis/caching/v1alpha1"
servingv1alpha1 "knative.dev/operator/pkg/apis/operator/v1alpha1"
"knative.dev/operator/pkg/apis/operator/v1alpha1"
)

func init() {
Expand All @@ -36,34 +37,35 @@ func init() {
var (
// The string to be replaced by the container name
containerNameVariable = "${NAME}"
delimiter = "/"
)

// ImageTransform updates image with a new registry and tag
func ImageTransform(instance *servingv1alpha1.KnativeServing, log *zap.SugaredLogger) mf.Transformer {
func ImageTransform(registry *v1alpha1.Registry, log *zap.SugaredLogger) mf.Transformer {
return func(u *unstructured.Unstructured) error {
switch u.GetKind() {
// TODO need to use PodSpecable duck type in order to remove duplicates of deployment, daemonSet
case "Deployment":
return updateDeployment(instance, u, log)
return updateDeployment(registry, u, log)
case "DaemonSet":
return updateDaemonSet(instance, u, log)
return updateDaemonSet(registry, u, log)
case "Image":
if u.GetAPIVersion() == "caching.internal.knative.dev/v1alpha1" {
return updateCachingImage(instance, u)
return updateCachingImage(registry, u, log)
}
}
return nil
}
}

func updateDeployment(instance *servingv1alpha1.KnativeServing, u *unstructured.Unstructured, log *zap.SugaredLogger) error {
func updateDeployment(registry *v1alpha1.Registry, u *unstructured.Unstructured, log *zap.SugaredLogger) error {
var deployment = &appsv1.Deployment{}
if err := scheme.Scheme.Convert(u, deployment, nil); err != nil {
log.Error(err, "Error converting Unstructured to Deployment", "unstructured", u, "deployment", deployment)
return err
}

updateRegistry(&deployment.Spec.Template.Spec, instance, log, deployment.GetName())
updateRegistry(&deployment.Spec.Template.Spec, registry, log, deployment.GetName())
if err := scheme.Scheme.Convert(deployment, u, nil); err != nil {
return err
}
Expand All @@ -75,13 +77,13 @@ func updateDeployment(instance *servingv1alpha1.KnativeServing, u *unstructured.
return nil
}

func updateDaemonSet(instance *servingv1alpha1.KnativeServing, u *unstructured.Unstructured, log *zap.SugaredLogger) error {
func updateDaemonSet(registry *v1alpha1.Registry, u *unstructured.Unstructured, log *zap.SugaredLogger) error {
var daemonSet = &appsv1.DaemonSet{}
if err := scheme.Scheme.Convert(u, daemonSet, nil); err != nil {
log.Error(err, "Error converting Unstructured to daemonSet", "unstructured", u, "daemonSet", daemonSet)
return err
}
updateRegistry(&daemonSet.Spec.Template.Spec, instance, log, daemonSet.GetName())
updateRegistry(&daemonSet.Spec.Template.Spec, registry, log, daemonSet.GetName())
if err := scheme.Scheme.Convert(daemonSet, u, nil); err != nil {
return err
}
Expand All @@ -93,39 +95,52 @@ func updateDaemonSet(instance *servingv1alpha1.KnativeServing, u *unstructured.U
return nil
}

func updateRegistry(spec *corev1.PodSpec, instance *servingv1alpha1.KnativeServing, log *zap.SugaredLogger, name string) {
registry := instance.Spec.Registry
func updateRegistry(spec *corev1.PodSpec, registry *v1alpha1.Registry, log *zap.SugaredLogger, name string) {
log.Debugw("Updating", "name", name, "registry", registry)

updateImage(spec, &registry, log, name)
updateImage(spec, registry, log, name)
updateEnvVarImages(spec, registry, log, name)

spec.ImagePullSecrets = addImagePullSecrets(
spec.ImagePullSecrets, &registry, log)
spec.ImagePullSecrets, registry, log)
}

// updateImage updates the image with a new registry and tag
func updateImage(spec *corev1.PodSpec, registry *servingv1alpha1.Registry, log *zap.SugaredLogger, name string) {
func updateImage(spec *corev1.PodSpec, registry *v1alpha1.Registry, log *zap.SugaredLogger, name string) {
containers := spec.Containers
for index := range containers {
container := &containers[index]
newImage := getNewImage(registry, container.Name)
newImage := getNewImage(registry, container.Name, name)
if newImage != "" {
updateContainer(container, newImage, log)
}
}
log.Debugw("Finished updating images", "name", name, "containers", spec.Containers)
}

func updateCachingImage(instance *servingv1alpha1.KnativeServing, u *unstructured.Unstructured) error {
func updateEnvVarImages(spec *corev1.PodSpec, registry *v1alpha1.Registry, log *zap.SugaredLogger, name string) {
containers := spec.Containers
for index := range containers {
container := &containers[index]
for envIndex := range container.Env {
env := &container.Env[envIndex]
if newImage, ok := registry.Override[env.Name]; ok {
env.Value = newImage
}
}
}
}

func updateCachingImage(registry *v1alpha1.Registry, u *unstructured.Unstructured, log *zap.SugaredLogger) error {
var image = &caching.Image{}
if err := scheme.Scheme.Convert(u, image, nil); err != nil {
log.Error(err, "Error converting Unstructured to Image", "unstructured", u, "image", image)
return err
}

registry := instance.Spec.Registry
log.Debugw("Updating Image", "name", u.GetName(), "registry", registry)

updateImageSpec(image, &registry, log)
updateImageSpec(image, registry, log)
if err := scheme.Scheme.Convert(image, u, nil); err != nil {
return err
}
Expand All @@ -138,18 +153,21 @@ func updateCachingImage(instance *servingv1alpha1.KnativeServing, u *unstructure
}

// updateImageSpec updates the image of a with a new registry and tag
func updateImageSpec(image *caching.Image, registry *servingv1alpha1.Registry, log *zap.SugaredLogger) {
if newImage := getNewImage(registry, image.Name); newImage != "" {
func updateImageSpec(image *caching.Image, registry *v1alpha1.Registry, log *zap.SugaredLogger) {
if newImage := getNewImage(registry, image.Name, ""); newImage != "" {
log.Debugf("Updating image from: %v, to: %v", image.Spec.Image, newImage)
image.Spec.Image = newImage
}
image.Spec.ImagePullSecrets = addImagePullSecrets(image.Spec.ImagePullSecrets, registry, log)
log.Debugw("Finished updating image", "image", image.GetName())
}

func getNewImage(registry *servingv1alpha1.Registry, containerName string) string {
if overrideImage := registry.Override[containerName]; overrideImage != "" {
return overrideImage
func getNewImage(registry *v1alpha1.Registry, containerName, parent string) string {
if image, ok := registry.Override[parent+delimiter+containerName]; ok {
return image
}
if image, ok := registry.Override[containerName]; ok {
return image
}
return replaceName(registry.Default, containerName)
}
Expand All @@ -163,7 +181,7 @@ func replaceName(imageTemplate string, name string) string {
return strings.ReplaceAll(imageTemplate, containerNameVariable, name)
}

func addImagePullSecrets(imagePullSecrets []corev1.LocalObjectReference, registry *servingv1alpha1.Registry, log *zap.SugaredLogger) []corev1.LocalObjectReference {
func addImagePullSecrets(imagePullSecrets []corev1.LocalObjectReference, registry *v1alpha1.Registry, log *zap.SugaredLogger) []corev1.LocalObjectReference {
if len(registry.ImagePullSecrets) > 0 {
log.Debugf("Adding ImagePullSecrets: %v", registry.ImagePullSecrets)
imagePullSecrets = append(imagePullSecrets, registry.ImagePullSecrets...)
Expand Down
Loading

0 comments on commit d83df59

Please sign in to comment.