-
Notifications
You must be signed in to change notification settings - Fork 708
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move controller revision to annotations #1234
Changes from all commits
102d584
bbe0110
f9df0a1
d548ccb
8caa814
82f72e2
a8b1746
2f95a27
1cb82b6
303e53c
e1f0c7f
92f3761
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 |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
// or more contributor license agreements. Licensed under the Elastic License; | ||
// you may not use this file except in compliance with the Elastic License. | ||
|
||
package annotation | ||
|
||
import ( | ||
"github.com/elastic/cloud-on-k8s/operators/pkg/utils/k8s" | ||
"k8s.io/apimachinery/pkg/api/meta" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
) | ||
|
||
// ControllerVersionAnnotation is the annotation name that indicates the last controller version to update a resource | ||
const ControllerVersionAnnotation = "common.k8s.elastic.co/controller-version" | ||
|
||
// UpdateControllerVersion updates the controller version annotation to the current version if necessary | ||
func UpdateControllerVersion(client k8s.Client, obj runtime.Object, version string) error { | ||
accessor := meta.NewAccessor() | ||
namespace, err := accessor.Namespace(obj) | ||
if err != nil { | ||
log.Error(err, "error getting namespace", "kind", obj.GetObjectKind().GroupVersionKind().Kind) | ||
return err | ||
} | ||
name, err := accessor.Name(obj) | ||
if err != nil { | ||
log.Error(err, "error getting name", "namespace", namespace, "kind", obj.GetObjectKind().GroupVersionKind().Kind) | ||
return err | ||
} | ||
annotations, err := accessor.Annotations(obj) | ||
if err != nil { | ||
log.Error(err, "error getting annotations", "namespace", namespace, "name", name, "kind", obj.GetObjectKind().GroupVersionKind().Kind) | ||
return err | ||
} | ||
if annotations == nil { | ||
annotations = make(map[string]string) | ||
} | ||
|
||
// do not send unnecessary update if the value would not change | ||
if annotations[ControllerVersionAnnotation] == version { | ||
log.V(1).Info("Skipping controller version annotation update, version already matches", "namespace", namespace, "name", name, "kind", obj.GetObjectKind()) | ||
return nil | ||
} | ||
|
||
annotations[ControllerVersionAnnotation] = version | ||
err = accessor.SetAnnotations(obj, annotations) | ||
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. Can we not reuse 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 don't think so because accessor's But your question did make me realize that I didn't look closely enough at the funcs available to the metav1 Accessor so there's some small bit of refactoring I can do here 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 also modifies the original object you passed to it, which you can the use for the update call. 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. Ah that was not my understanding just from scanning through the code but it's deeeeefinitely possible I am misunderstanding |
||
if err != nil { | ||
log.Error(err, "error updating controller version annotation", "namespace", namespace, "name", name, "kind", obj.GetObjectKind()) | ||
return err | ||
} | ||
log.V(1).Info("updating controller version annotation", "namespace", namespace, "name", name, "kind", obj.GetObjectKind()) | ||
return client.Update(obj) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
// or more contributor license agreements. Licensed under the Elastic License; | ||
// you may not use this file except in compliance with the Elastic License. | ||
|
||
package annotation | ||
|
||
import ( | ||
"testing" | ||
|
||
kibanav1alpha1 "github.com/elastic/cloud-on-k8s/operators/pkg/apis/kibana/v1alpha1" | ||
"github.com/elastic/cloud-on-k8s/operators/pkg/utils/k8s" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/apimachinery/pkg/types" | ||
"sigs.k8s.io/controller-runtime/pkg/client/fake" | ||
|
||
apmtype "github.com/elastic/cloud-on-k8s/operators/pkg/apis/apm/v1alpha1" | ||
assoctype "github.com/elastic/cloud-on-k8s/operators/pkg/apis/associations/v1alpha1" | ||
estype "github.com/elastic/cloud-on-k8s/operators/pkg/apis/elasticsearch/v1alpha1" | ||
"k8s.io/client-go/kubernetes/scheme" | ||
) | ||
|
||
// Test UpdateControllerVersion updates annotation if there is an older version | ||
func TestAnnotationUpdated(t *testing.T) { | ||
kibana := kibanav1alpha1.Kibana{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Namespace: "ns", | ||
Name: "kibana", | ||
Annotations: map[string]string{ | ||
ControllerVersionAnnotation: "oldversion", | ||
}, | ||
}, | ||
} | ||
obj := kibana.DeepCopy() | ||
sc := setupScheme(t) | ||
client := k8s.WrapClient(fake.NewFakeClientWithScheme(sc, obj)) | ||
err := UpdateControllerVersion(client, obj, "newversion") | ||
require.NoError(t, err) | ||
require.Equal(t, obj.GetAnnotations()[ControllerVersionAnnotation], "newversion") | ||
} | ||
|
||
// Test UpdateControllerVersion creates an annotation even if there are no current annotations | ||
func TestAnnotationCreated(t *testing.T) { | ||
kibana := kibanav1alpha1.Kibana{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Namespace: "ns", | ||
Name: "kibana", | ||
}, | ||
} | ||
|
||
obj := kibana.DeepCopy() | ||
sc := setupScheme(t) | ||
client := k8s.WrapClient(fake.NewFakeClientWithScheme(sc, obj)) | ||
err := UpdateControllerVersion(client, obj, "newversion") | ||
require.NoError(t, err) | ||
actualKibana := &kibanav1alpha1.Kibana{} | ||
err = client.Get(types.NamespacedName{ | ||
Namespace: obj.Namespace, | ||
Name: obj.Name, | ||
}, actualKibana) | ||
require.NoError(t, err) | ||
require.NotNil(t, actualKibana.GetAnnotations()) | ||
assert.Equal(t, actualKibana.GetAnnotations()[ControllerVersionAnnotation], "newversion") | ||
} | ||
|
||
// setupScheme creates a scheme to use for our fake clients so they know about our custom resources | ||
// TODO move this into one of the upper level common packages and make public, refactor out this code that's in a lot of our tests | ||
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. +1, can you create an issue for that one? 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. Technically you only need to register the Kibana types here? 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. Yeah that's true @pebrc, wanted to make it easy to just copy it later |
||
func setupScheme(t *testing.T) *runtime.Scheme { | ||
sc := scheme.Scheme | ||
if err := assoctype.SchemeBuilder.AddToScheme(sc); err != nil { | ||
assert.Fail(t, "failed to add Association types") | ||
} | ||
if err := apmtype.SchemeBuilder.AddToScheme(sc); err != nil { | ||
assert.Fail(t, "failed to add APM types") | ||
} | ||
if err := estype.SchemeBuilder.AddToScheme(sc); err != nil { | ||
assert.Fail(t, "failed to add ES types") | ||
} | ||
if err := kibanav1alpha1.SchemeBuilder.AddToScheme(sc); err != nil { | ||
assert.Fail(t, "failed to add Kibana types") | ||
} | ||
return sc | ||
} |
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.
Should this not also return if there is any version set?
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.
I thought we would want to use this func because the caller decided that we do want to proceed with an update -- for instance it might be okay with going from 0.9.0 to 0.9.1. We might need additional funcs before calling this