Skip to content

Commit fe7b9ff

Browse files
authored
Merge pull request #4154 from nojnhuh/aso-tags
[release-1.11] wait for ASO tags to converge before updating
2 parents 1db4717 + 4a9486d commit fe7b9ff

File tree

3 files changed

+55
-6
lines changed

3 files changed

+55
-6
lines changed

azure/services/aso/aso_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ func TestCreateOrUpdateResource(t *testing.T) {
736736

737737
specMock.MockTagsGetterSetter.EXPECT().GetActualTags(gomock.Any()).Return(nil, nil)
738738
specMock.MockTagsGetterSetter.EXPECT().GetAdditionalTags().Return(nil)
739-
specMock.MockTagsGetterSetter.EXPECT().GetDesiredTags(gomock.Any()).Return(nil, nil)
739+
specMock.MockTagsGetterSetter.EXPECT().GetDesiredTags(gomock.Any()).Return(nil, nil).Times(2)
740740
specMock.MockTagsGetterSetter.EXPECT().SetTags(gomock.Any(), gomock.Any())
741741

742742
ctx := context.Background()

azure/services/aso/tags.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@ package aso
1818

1919
import (
2020
"encoding/json"
21+
"reflect"
2122

23+
asoannotations "github.com/Azure/azure-service-operator/v2/pkg/common/annotations"
2224
"github.com/Azure/azure-service-operator/v2/pkg/genruntime"
2325
"github.com/pkg/errors"
26+
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
27+
"sigs.k8s.io/cluster-api-provider-azure/azure"
2428
"sigs.k8s.io/cluster-api-provider-azure/azure/converters"
2529
"sigs.k8s.io/cluster-api-provider-azure/azure/services/tags"
2630
"sigs.k8s.io/cluster-api-provider-azure/util/maps"
@@ -33,6 +37,7 @@ const tagsLastAppliedAnnotation = "sigs.k8s.io/cluster-api-provider-azure-last-a
3337

3438
// reconcileTags modifies parameters in place to update its tags and its last-applied annotation.
3539
func reconcileTags(t TagsGetterSetter, existing genruntime.MetaObject, parameters genruntime.MetaObject) error {
40+
var existingTags infrav1.Tags
3641
lastAppliedTags := map[string]interface{}{}
3742
if existing != nil {
3843
lastAppliedTagsJSON := existing.GetAnnotations()[tagsLastAppliedAnnotation]
@@ -42,14 +47,29 @@ func reconcileTags(t TagsGetterSetter, existing genruntime.MetaObject, parameter
4247
return errors.Wrapf(err, "failed to unmarshal JSON from %s annotation", tagsLastAppliedAnnotation)
4348
}
4449
}
45-
}
4650

47-
existingTags, err := t.GetActualTags(existing)
48-
if err != nil {
49-
return errors.Wrapf(err, "failed to get actual tags for %s %s/%s", existing.GetObjectKind().GroupVersionKind(), existing.GetNamespace(), existing.GetName())
51+
var err error
52+
existingTags, err = t.GetActualTags(existing)
53+
if err != nil {
54+
return errors.Wrapf(err, "failed to get actual tags for %s %s/%s", existing.GetObjectKind().GroupVersionKind(), existing.GetNamespace(), existing.GetName())
55+
}
56+
desiredTags, err := t.GetDesiredTags(existing)
57+
if err != nil {
58+
return errors.Wrapf(err, "failed to get desired tags for %s %s/%s", existing.GetObjectKind().GroupVersionKind(), existing.GetNamespace(), existing.GetName())
59+
}
60+
// Wait for tags to converge so we know for sure which ones are deleted from additionalTags (and
61+
// should be deleted) and which were added manually (and should be kept).
62+
if !reflect.DeepEqual(desiredTags, existingTags) &&
63+
existing.GetAnnotations()[asoannotations.ReconcilePolicy] == string(asoannotations.ReconcilePolicyManage) {
64+
return azure.WithTransientError(azure.NewOperationNotDoneError(&infrav1.Future{
65+
Type: createOrUpdateFutureType,
66+
ResourceGroup: existing.GetNamespace(),
67+
Name: existing.GetName(),
68+
}), requeueInterval)
69+
}
5070
}
51-
existingTagsMap := converters.TagsToMap(existingTags)
5271

72+
existingTagsMap := converters.TagsToMap(existingTags)
5373
_, createdOrUpdated, deleted, newAnnotation := tags.TagsChanged(lastAppliedTags, t.GetAdditionalTags(), existingTagsMap)
5474
desiredTags, err := t.GetDesiredTags(parameters)
5575
if err != nil {

azure/services/aso/tags_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ import (
2121
"testing"
2222

2323
asoresourcesv1 "github.com/Azure/azure-service-operator/v2/api/resources/v1api20200601"
24+
asoannotations "github.com/Azure/azure-service-operator/v2/pkg/common/annotations"
2425
. "github.com/onsi/gomega"
2526
"github.com/pkg/errors"
2627
"go.uber.org/mock/gomock"
2728
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2829
infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
30+
"sigs.k8s.io/cluster-api-provider-azure/azure"
2931
"sigs.k8s.io/cluster-api-provider-azure/azure/services/aso/mock_aso"
3032
)
3133

@@ -44,6 +46,7 @@ func TestReconcileTags(t *testing.T) {
4446
"oldAdditionalTag": "oldAdditionalVal",
4547
},
4648
existingTags: infrav1.Tags{
49+
"oldAdditionalTag": "oldAdditionalVal",
4750
"nonAdditionalTag": "nonAdditionalVal",
4851
},
4952
additionalTagsSpec: infrav1.Tags{
@@ -95,6 +98,7 @@ func TestReconcileTags(t *testing.T) {
9598
})
9699
}
97100
tag.EXPECT().GetActualTags(existing).Return(test.existingTags, nil)
101+
tag.EXPECT().GetDesiredTags(existing).Return(test.existingTags, nil)
98102
tag.EXPECT().GetAdditionalTags().Return(test.additionalTagsSpec)
99103

100104
parameters := &asoresourcesv1.ResourceGroup{}
@@ -146,6 +150,7 @@ func TestReconcileTags(t *testing.T) {
146150

147151
existing := &asoresourcesv1.ResourceGroup{}
148152
tag.EXPECT().GetActualTags(existing).Return(nil, nil)
153+
tag.EXPECT().GetDesiredTags(existing).Return(nil, nil)
149154
tag.EXPECT().GetAdditionalTags().Return(nil)
150155

151156
parameters := &asoresourcesv1.ResourceGroup{}
@@ -163,6 +168,7 @@ func TestReconcileTags(t *testing.T) {
163168

164169
existing := &asoresourcesv1.ResourceGroup{}
165170
tag.EXPECT().GetActualTags(existing).Return(nil, nil)
171+
tag.EXPECT().GetDesiredTags(existing).Return(nil, nil)
166172
tag.EXPECT().GetAdditionalTags().Return(nil)
167173

168174
parameters := &asoresourcesv1.ResourceGroup{}
@@ -172,4 +178,27 @@ func TestReconcileTags(t *testing.T) {
172178
err := reconcileTags(tag, existing, parameters)
173179
g.Expect(err).To(MatchError(ContainSubstring("some error")))
174180
})
181+
182+
t.Run("existing tags not up to date", func(t *testing.T) {
183+
g := NewWithT(t)
184+
185+
mockCtrl := gomock.NewController(t)
186+
tag := mock_aso.NewMockTagsGetterSetter(mockCtrl)
187+
188+
existing := &asoresourcesv1.ResourceGroup{
189+
ObjectMeta: metav1.ObjectMeta{
190+
Annotations: map[string]string{
191+
asoannotations.ReconcilePolicy: string(asoannotations.ReconcilePolicyManage),
192+
},
193+
},
194+
}
195+
tag.EXPECT().GetActualTags(existing).Return(infrav1.Tags{"new": "value"}, nil)
196+
tag.EXPECT().GetDesiredTags(existing).Return(infrav1.Tags{"old": "tag"}, nil)
197+
198+
err := reconcileTags(tag, existing, nil)
199+
g.Expect(azure.IsOperationNotDoneError(err)).To(BeTrue())
200+
var recerr azure.ReconcileError
201+
g.Expect(errors.As(err, &recerr)).To(BeTrue())
202+
g.Expect(recerr.IsTransient()).To(BeTrue())
203+
})
175204
}

0 commit comments

Comments
 (0)