Skip to content
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

Implement annotation replicator.v1.mittwald.de/strip-labels #155

Merged
merged 5 commits into from
Nov 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,25 @@ data:
.dockerconfigjson: e30K
```

#### Special case: Strip labels while replicate the resources.

Operators like [/~https://github.com/strimzi/strimzi-kafka-operator](strimzi-kafka-operator) implement an own garbage collection based on specific labels defined on resources. If mittwald replicator replicate secrets to different namespace, the strimzi-kafka-operator will remove the replicated secrets because from operators point of view the secret is a left-over. To mitigate the issue, set the annotation `replicator.v1.mittwald.de/strip-labels=true` to remove all labels on the replicated resource.

```yaml
apiVersion: v1
kind: Secret
metadata:
labels:
app.kubernetes.io/managed-by: "strimzi-kafka-operator"
name: cluster-ca-certs
annotations:
replicator.v1.mittwald.de/strip-labels: "true"
type: kubernetes.io/tls
data:
tls.key: ""
tls.crt: ""
```

#### Special case: Resource with .metadata.ownerReferences

Sometimes, secrets are generated by external components. Such secrets are configured with an ownerReference. By default, the kubernetes-replicator will delete the
Expand Down
1 change: 1 addition & 0 deletions replicate/common/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ const (
ReplicateTo = "replicator.v1.mittwald.de/replicate-to"
ReplicateToMatching = "replicator.v1.mittwald.de/replicate-to-matching"
KeepOwnerReferences = "replicator.v1.mittwald.de/keep-owner-references"
StripLabels = "replicator.v1.mittwald.de/strip-labels"
)
16 changes: 7 additions & 9 deletions replicate/configmap/configmaps.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,6 @@ func (r *Replicator) ReplicateDataFrom(sourceObj interface{}, targetObj interfac
}

targetCopy := target.DeepCopy()

keepOwnerReferences, ok := source.Annotations[common.KeepOwnerReferences]
if !ok || keepOwnerReferences != "true" {
targetCopy.OwnerReferences = nil
}

if targetCopy.Data == nil {
targetCopy.Data = make(map[string]string)
}
Expand Down Expand Up @@ -200,9 +194,13 @@ func (r *Replicator) ReplicateObjectTo(sourceObj interface{}, target *v1.Namespa
}

labelsCopy := make(map[string]string)
if source.Labels != nil {
for key, value := range source.Labels {
labelsCopy[key] = value

stripLabels, ok := source.Annotations[common.StripLabels]
if !ok && stripLabels != "true" {
if source.Labels != nil {
for key, value := range source.Labels {
labelsCopy[key] = value
}
}
}

Expand Down
16 changes: 7 additions & 9 deletions replicate/role/roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,6 @@ func (r *Replicator) ReplicateDataFrom(sourceObj interface{}, targetObj interfac
}

targetCopy := target.DeepCopy()

keepOwnerReferences, ok := source.Annotations[common.KeepOwnerReferences]
if !ok || keepOwnerReferences != "true" {
targetCopy.OwnerReferences = nil
}

targetCopy.Rules = source.Rules

logger.Infof("updating target %s/%s", target.Namespace, target.Name)
Expand Down Expand Up @@ -141,9 +135,13 @@ func (r *Replicator) ReplicateObjectTo(sourceObj interface{}, target *v1.Namespa
}

labelsCopy := make(map[string]string)
if source.Labels != nil {
for key, value := range source.Labels {
labelsCopy[key] = value

stripLabels, ok := source.Annotations[common.StripLabels]
if !ok && stripLabels != "true" {
if source.Labels != nil {
for key, value := range source.Labels {
labelsCopy[key] = value
}
}
}

Expand Down
16 changes: 8 additions & 8 deletions replicate/rolebinding/rolebindings.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,6 @@ func (r *Replicator) ReplicateDataFrom(sourceObj interface{}, targetObj interfac
}

targetCopy := target.DeepCopy()
keepOwnerReferences, ok := source.Annotations[common.KeepOwnerReferences]
if !ok || keepOwnerReferences != "true" {
targetCopy.OwnerReferences = nil
}

targetCopy.Subjects = source.Subjects

log.Infof("updating target %s/%s", target.Namespace, target.Name)
Expand Down Expand Up @@ -139,10 +134,15 @@ func (r *Replicator) ReplicateObjectTo(sourceObj interface{}, target *v1.Namespa
}

labelsCopy := make(map[string]string)
if source.Labels != nil {
for key, value := range source.Labels {
labelsCopy[key] = value

stripLabels, ok := source.Annotations[common.StripLabels]
if !ok && stripLabels != "true" {
if source.Labels != nil {
for key, value := range source.Labels {
labelsCopy[key] = value
}
}

}

targetCopy.Name = source.Name
Expand Down
16 changes: 7 additions & 9 deletions replicate/secret/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,6 @@ func (r *Replicator) ReplicateDataFrom(sourceObj interface{}, targetObj interfac
}

targetCopy := target.DeepCopy()

keepOwnerReferences, ok := source.Annotations[common.KeepOwnerReferences]
if !ok || keepOwnerReferences != "true" {
targetCopy.OwnerReferences = nil
}

if targetCopy.Data == nil {
targetCopy.Data = make(map[string][]byte)
}
Expand Down Expand Up @@ -172,9 +166,13 @@ func (r *Replicator) ReplicateObjectTo(sourceObj interface{}, target *v1.Namespa
sort.Strings(replicatedKeys)

labelsCopy := make(map[string]string)
if source.Labels != nil {
for key, value := range source.Labels {
labelsCopy[key] = value

stripLabels, ok := source.Annotations[common.StripLabels]
if !ok && stripLabels != "true" {
if source.Labels != nil {
for key, value := range source.Labels {
labelsCopy[key] = value
}
}
}

Expand Down
56 changes: 56 additions & 0 deletions replicate/secret/secrets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,62 @@ func TestSecretReplicator(t *testing.T) {
require.Equal(t, []byte("Hello Bar"), updTarget.Data["bar"])
})

t.Run("replication is pushed to other namespaces and strip labels", func(t *testing.T) {
sourceLabels := map[string]string{
"foo": "bar",
"hello": "world",
}
source := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "source-pushed-to-other-with-strip-labels",
Namespace: ns.Name,
Annotations: map[string]string{
common.ReplicateTo: prefix + "test2",
common.StripLabels: "true",
},
Labels: sourceLabels,
OwnerReferences: []metav1.OwnerReference{{
APIVersion: "v1",
Kind: "Namespace",
Name: nsData.Name,
UID: nsData.UID,
}},
},
Type: corev1.SecretTypeOpaque,
Data: map[string][]byte{
"foo": []byte("Hello Foo"),
"bar": []byte("Hello Bar"),
},
}

wg, stop := waitForSecrets(client, 2, EventHandlerFuncs{
AddFunc: func(wg *sync.WaitGroup, obj interface{}) {
secret := obj.(*corev1.Secret)
if secret.Namespace == source.Namespace && secret.Name == source.Name {
log.Debugf("AddFunc %+v", obj)
wg.Done()
} else if secret.Namespace == prefix+"test2" && secret.Name == source.Name {
log.Debugf("AddFunc %+v", obj)
wg.Done()
}
},
})
_, err := secrets.Create(context.TODO(), &source, metav1.CreateOptions{})
require.NoError(t, err)

waitWithTimeout(wg, MaxWaitTime)
close(stop)

secrets2 := client.CoreV1().Secrets(prefix + "test2")
updTarget, err := secrets2.Get(context.TODO(), source.Name, metav1.GetOptions{})

require.NoError(t, err)
require.Equal(t, []byte("Hello Foo"), updTarget.Data["foo"])
require.False(t, reflect.DeepEqual(sourceLabels, updTarget.Labels))

require.Equal(t, map[string]string(nil), updTarget.Labels)
})

t.Run("replication is pushed to other namespaces by label selector", func(t *testing.T) {
source := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Expand Down