@@ -19,14 +19,30 @@ import (
19
19
"github.com/Azure/azure-service-operator/v2/internal/genericarmclient"
20
20
. "github.com/Azure/azure-service-operator/v2/internal/logging"
21
21
"github.com/Azure/azure-service-operator/v2/internal/resolver"
22
+ "github.com/Azure/azure-service-operator/v2/internal/set"
22
23
"github.com/Azure/azure-service-operator/v2/internal/util/to"
23
24
"github.com/Azure/azure-service-operator/v2/pkg/genruntime"
24
25
"github.com/Azure/azure-service-operator/v2/pkg/genruntime/extensions"
25
26
)
26
27
27
28
var _ extensions.PostReconciliationChecker = & BackupVaultsBackupInstanceExtension {}
28
29
29
- var protectionError = "ProtectionError"
30
+ // These are the states on which there's no future change possible, hence best to return PostReconcileCheck success on them.
31
+ // Then further we let Operator decide what condition to put on the resource.
32
+ // These terminal states are determined and confirmed by the dataprotection team from the swagger below:
33
+ // https://github.com/Azure/azure-rest-api-specs/blob/a651ba25cda4eec698a3a4e35f867ecc2681d126/specification/dataprotection/resource-manager/Microsoft.DataProtection/stable/2023-11-01/dataprotection.json#L5014
34
+ var terminalStates = set .Make (
35
+ "configuringprotectionfailed" ,
36
+ "invalid" ,
37
+ "notprotected" ,
38
+ "protectionconfigured" ,
39
+ "softdeleted" ,
40
+ "protectionstopped" ,
41
+ "backupschedulessuspended" ,
42
+ "retentionschedulessuspended" ,
43
+ )
44
+
45
+ var protectionError = "protectionerror"
30
46
31
47
const (
32
48
BackupInstancePollerResumeTokenAnnotation = "serviceoperator.azure.com/bi-poller-resume-token"
@@ -80,69 +96,73 @@ func (extension *BackupVaultsBackupInstanceExtension) PostReconcileCheck(
80
96
}
81
97
82
98
protectionStatus := * backupInstance .Status .Properties .ProtectionStatus .Status
99
+ protectionStatus = strings .ToLower (protectionStatus )
83
100
log .V (Debug ).Info (fmt .Sprintf ("Protection Status is %q" , protectionStatus ))
84
101
85
- // We only want to continue if protectionStatus == ProtectionError.
86
- if ! strings . EqualFold (protectionStatus , protectionError ) {
102
+ // Return success if the status is in a terminal state
103
+ if terminalStates . Contains (protectionStatus ) {
87
104
log .V (Debug ).Info ("Returning PostReconcileCheckResultSuccess" )
88
105
return next (ctx , obj , owner , resolver , armClient , log )
89
106
}
90
107
91
- // call sync api only when protection status is ProtectionError and error code is usererror
92
- var protectionStatusErrorCode string
93
- protectionStatusErrorCode = strings .ToLower (* backupInstance .Status .Properties .ProtectionStatus .ErrorDetails .Code )
94
- log .V (Debug ).Info (fmt .Sprintf ("Protection Error code is %q" , protectionStatusErrorCode ))
108
+ if protectionStatus == protectionError {
109
+ // call sync api only when protection status is ProtectionError and error code is usererror
110
+ var protectionStatusErrorCode string
111
+ protectionStatusErrorCode = strings .ToLower (* backupInstance .Status .Properties .ProtectionStatus .ErrorDetails .Code )
112
+ log .V (Debug ).Info (fmt .Sprintf ("Protection Error code is %q" , protectionStatusErrorCode ))
95
113
96
- if protectionStatusErrorCode != "" && strings .Contains (protectionStatusErrorCode , "usererror" ) {
97
- id , _ := genruntime .GetAndParseResourceID (backupInstance )
98
- subscription := id .SubscriptionID
99
- rg := id .ResourceGroupName
100
- vaultName := id .Parent .Name
114
+ if strings .Contains (protectionStatusErrorCode , "usererror" ) {
115
+ id , _ := genruntime .GetAndParseResourceID (backupInstance )
116
+ subscription := id .SubscriptionID
117
+ rg := id .ResourceGroupName
118
+ vaultName := id .Parent .Name
101
119
102
- clientFactory , err := armdataprotection .NewClientFactory (subscription , armClient .Creds (), armClient .ClientOptions ())
103
- if err != nil {
104
- return extensions .PostReconcileCheckResultFailure ("failed to create armdataprotection client" ), err
105
- }
120
+ clientFactory , err := armdataprotection .NewClientFactory (subscription , armClient .Creds (), armClient .ClientOptions ())
121
+ if err != nil {
122
+ return extensions .PostReconcileCheckResultFailure ("failed to create armdataprotection client" ), err
123
+ }
106
124
107
- var parameters armdataprotection.SyncBackupInstanceRequest
108
- parameters .SyncType = to .Ptr (armdataprotection .SyncTypeDefault )
125
+ var parameters armdataprotection.SyncBackupInstanceRequest
126
+ parameters .SyncType = to .Ptr (armdataprotection .SyncTypeDefault )
109
127
110
- // get the resume token from the resource
111
- pollerResumeToken , _ := GetPollerResumeToken (obj , log )
128
+ // get the resume token from the resource
129
+ pollerResumeToken , _ := GetPollerResumeToken (obj , log )
112
130
113
- // BeginSyncBackupInstance is in-progress - poller resume token is available
114
- log .V (Debug ).Info ("Starting BeginSyncBackupInstance" )
131
+ // BeginSyncBackupInstance is in-progress - poller resume token is available
132
+ log .V (Debug ).Info ("Starting BeginSyncBackupInstance" )
115
133
116
- poller , err := clientFactory .NewBackupInstancesClient ().BeginSyncBackupInstance (ctx , rg , vaultName , backupInstance .AzureName (), parameters , & armdataprotection.BackupInstancesClientBeginSyncBackupInstanceOptions {
117
- ResumeToken : pollerResumeToken ,
118
- })
119
- if err != nil {
120
- return extensions .PostReconcileCheckResultFailure ("Failed Polling for BeginSyncBackupInstance to get the result" ), err
121
- }
134
+ poller , err := clientFactory .NewBackupInstancesClient ().BeginSyncBackupInstance (ctx , rg , vaultName , backupInstance .AzureName (), parameters , & armdataprotection.BackupInstancesClientBeginSyncBackupInstanceOptions {
135
+ ResumeToken : pollerResumeToken ,
136
+ })
137
+ if err != nil {
138
+ return extensions .PostReconcileCheckResultFailure ("Failed Polling for BeginSyncBackupInstance to get the result" ), err
139
+ }
122
140
123
- if pollerResumeToken == "" {
124
- resumeToken , resumeTokenErr := poller .ResumeToken ()
125
- if resumeTokenErr != nil {
126
- return extensions .PostReconcileCheckResultFailure ("couldn't create PUT resume token for resource" ), resumeTokenErr
127
- } else {
128
- SetPollerResumeToken (obj , resumeToken , log )
141
+ if pollerResumeToken == "" {
142
+ resumeToken , resumeTokenErr := poller .ResumeToken ()
143
+ if resumeTokenErr != nil {
144
+ return extensions .PostReconcileCheckResultFailure ("couldn't create PUT resume token for resource" ), resumeTokenErr
145
+ } else {
146
+ SetPollerResumeToken (obj , resumeToken , log )
147
+ }
129
148
}
130
- }
131
149
132
- _ , pollErr := poller .Poll (ctx )
133
- if pollErr != nil {
134
- return extensions .PostReconcileCheckResultFailure ("couldn't create PUT resume token for resource" ), pollErr
135
- }
150
+ _ , pollErr := poller .Poll (ctx )
151
+ if pollErr != nil {
152
+ return extensions .PostReconcileCheckResultFailure ("couldn't create PUT resume token for resource" ), pollErr
153
+ }
136
154
137
- if poller .Done () {
138
- log .V (Debug ).Info ("Polling is completed" )
139
- ClearPollerResumeToken (obj , log )
140
- _ , err := poller .Result (ctx )
141
- if err != nil {
142
- return extensions .PostReconcileCheckResultFailure ("couldn't create PUT resume token for resource" ), err
155
+ if poller .Done () {
156
+ log .V (Debug ).Info ("Polling is completed" )
157
+ ClearPollerResumeToken (obj , log )
158
+ _ , err := poller .Result (ctx )
159
+ if err != nil {
160
+ return extensions .PostReconcileCheckResultFailure ("couldn't create PUT resume token for resource" ), err
161
+ }
143
162
}
163
+ log .V (Debug ).Info ("Polling is in-progress" )
144
164
}
145
- log .V (Debug ).Info ("Polling is in-progress" )
146
165
}
166
+
147
167
return extensions .PostReconcileCheckResultFailure ("Backup Instance is in non terminal state" ), nil
148
168
}
0 commit comments