-
Notifications
You must be signed in to change notification settings - Fork 43
Add ability to update the image and tag of knative serving images #20
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -18,8 +18,10 @@ package common | |||
| import ( | ||||
| mf "github.com/jcrossley3/manifestival" | ||||
| servingv1alpha1 "github.com/knative/serving-operator/pkg/apis/serving/v1alpha1" | ||||
| appsv1 "k8s.io/api/apps/v1" | ||||
| "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||||
| "k8s.io/apimachinery/pkg/runtime" | ||||
| caching "knative.dev/caching/pkg/apis/caching/v1alpha1" | ||||
| "sigs.k8s.io/controller-runtime/pkg/client" | ||||
| logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" | ||||
| ) | ||||
|
|
@@ -48,16 +50,24 @@ func (platforms Platforms) Extend(c client.Client, scheme *runtime.Scheme) (resu | |||
| return | ||||
| } | ||||
|
|
||||
| func (exts Extensions) Transform(instance *servingv1alpha1.KnativeServing) []mf.Transformer { | ||||
| func (exts Extensions) Transform(scheme *runtime.Scheme, instance *servingv1alpha1.KnativeServing) []mf.Transformer { | ||||
| log.V(1).Info("Transforming", "instance", instance) | ||||
| result := []mf.Transformer{ | ||||
| mf.InjectOwner(instance), | ||||
| mf.InjectNamespace(instance.GetNamespace()), | ||||
| } | ||||
| for _, extension := range exts { | ||||
| result = append(result, extension.Transformers...) | ||||
| } | ||||
| // Let any config in instance override everything else | ||||
| return append(result, func(u *unstructured.Unstructured) error { | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we start adding more conditions in here, it might make more sense to define There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, if |
||||
| // Update the deployment with the new registry and tag | ||||
| if u.GetAPIVersion() == "caching.internal.knative.dev/v1alpha1" && u.GetKind() == "Image" { | ||||
| updateCachingImage(scheme, instance, u) | ||||
| } | ||||
| if u.GetKind() == "Deployment" { | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment on line 60 should get moved in to this function block now since it is not purely about config overriding
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's one challenge here, just consider the image url in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm concerned with a common solution that supports replacing all possible values. I think if the configmap values need to be changed, they should use the The
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated to support |
||||
| updateDeployment(scheme, instance, u) | ||||
| } | ||||
| // Let any config in instance override everything else | ||||
| if u.GetKind() == "ConfigMap" { | ||||
| if data, ok := instance.Spec.Config[u.GetName()[len(`config-`):]]; ok { | ||||
| UpdateConfigMap(u, data, log) | ||||
|
|
@@ -67,6 +77,40 @@ func (exts Extensions) Transform(instance *servingv1alpha1.KnativeServing) []mf. | |||
| }) | ||||
| } | ||||
|
|
||||
| func updateCachingImage(scheme *runtime.Scheme, instance *servingv1alpha1.KnativeServing, u *unstructured.Unstructured) error { | ||||
| var image = &caching.Image{} | ||||
| err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, image) | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll look into why |
||||
| if err != nil { | ||||
| log.Error(err, "Error converting Unstructured to Image", "unstructured", u, "image", image) | ||||
| return err | ||||
| } | ||||
|
|
||||
| registry := instance.Spec.Registry | ||||
| log.V(1).Info("Updating Image", "name", u.GetName(), "registry", registry) | ||||
|
|
||||
| UpdateImageSpec(image, ®istry, log) | ||||
| scheme.Convert(image, u, nil) | ||||
| log.V(1).Info("Finished conversion", "name", u.GetName(), "unstructured", u.Object) | ||||
| return nil | ||||
| } | ||||
|
|
||||
| func updateDeployment(scheme *runtime.Scheme, instance *servingv1alpha1.KnativeServing, u *unstructured.Unstructured) error { | ||||
| var deployment = &appsv1.Deployment{} | ||||
| err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, deployment) | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this better than
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I couldn't get
I'll look more into the scheme tests and see if I can reproduce this issue: https://github.com/kubernetes/apimachinery/blob/961b39a1baa06f6c52bdd048a809b9f5b47f1337/pkg/runtime/scheme_test.go#L1 |
||||
| if err != nil { | ||||
| log.Error(err, "Error converting Unstructured to Deployment", "unstructured", u, "deployment", deployment) | ||||
| return err | ||||
| } | ||||
|
|
||||
| registry := instance.Spec.Registry | ||||
| log.V(1).Info("Updating Deployment", "name", u.GetName(), "registry", registry) | ||||
|
|
||||
| UpdateDeploymentImage(deployment, ®istry, log) | ||||
| scheme.Convert(deployment, u, nil) | ||||
| log.V(1).Info("Finished conversion", "name", u.GetName(), "unstructured", u.Object) | ||||
| return nil | ||||
| } | ||||
|
|
||||
| func (exts Extensions) PreInstall(instance *servingv1alpha1.KnativeServing) error { | ||||
| for _, extension := range exts { | ||||
| for _, f := range extension.PreInstalls { | ||||
|
|
||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| /* | ||
| Copyright 2019 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. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| 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 ( | ||
| "fmt" | ||
| "strings" | ||
|
|
||
| "github.com/go-logr/logr" | ||
| servingv1alpha1 "github.com/knative/serving-operator/pkg/apis/serving/v1alpha1" | ||
| appsv1 "k8s.io/api/apps/v1" | ||
| corev1 "k8s.io/api/core/v1" | ||
| caching "knative.dev/caching/pkg/apis/caching/v1alpha1" | ||
| ) | ||
|
|
||
| var ( | ||
| // The string to be replaced by the container name | ||
| containerNameVariable = "${NAME}" | ||
| ) | ||
|
|
||
| // UpdateDeploymentImage updates the image of the deployment with a new registry and tag | ||
| func UpdateDeploymentImage(deployment *appsv1.Deployment, registry *servingv1alpha1.Registry, log logr.Logger) { | ||
| containers := deployment.Spec.Template.Spec.Containers | ||
| for index := range containers { | ||
| container := &containers[index] | ||
| newImage := getNewImage(registry, container.Name) | ||
| if newImage != "" { | ||
| updateContainer(container, newImage, log) | ||
| } | ||
| } | ||
| log.V(1).Info("Finished updating images", "deployment", deployment.GetName()) | ||
| } | ||
|
|
||
| // UpdateImageSpec updates the image of a with a new registry and tag | ||
| func UpdateImageSpec(image *caching.Image, registry *servingv1alpha1.Registry, log logr.Logger) { | ||
| newImage := getNewImage(registry, image.Name) | ||
| if newImage != "" { | ||
| log.V(1).Info(fmt.Sprintf("Updating image from: %v, to: %v", image.Spec.Image, newImage)) | ||
| image.Spec.Image = newImage | ||
| } | ||
| log.V(1).Info("Finished updating image", "image", image.GetName()) | ||
| } | ||
|
|
||
| func getNewImage(registry *servingv1alpha1.Registry, containerName string) string { | ||
| overrideImage := registry.Override[containerName] | ||
| if overrideImage != "" { | ||
| return overrideImage | ||
| } | ||
| return replaceName(registry.Default, containerName) | ||
| } | ||
|
|
||
| func updateContainer(container *corev1.Container, newImage string, log logr.Logger) { | ||
| log.V(1).Info(fmt.Sprintf("Updating container image from: %v, to: %v", container.Image, newImage)) | ||
| container.Image = newImage | ||
| } | ||
|
|
||
| func replaceName(imageTemplate string, name string) string { | ||
| return strings.ReplaceAll(imageTemplate, containerNameVariable, name) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the "Default*" prefix meant to imply? Why not just
NameandTagas the only elements of theRegistrystruct?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per comment #20 (comment), it demonstrates the that this is the default registry and tag to use. I am starting to prefer the nested default map.