-
Notifications
You must be signed in to change notification settings - Fork 3
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
Refresh secret when data change #53
Refresh secret when data change #53
Conversation
637f5ae
to
c77306b
Compare
reconciler.ProvidersReconcileState[namespacedName].ExistingSecretReferences[secretObj.Name].SecretResourceVersion = secretObj.ResourceVersion | ||
reconciler.ProvidersReconcileState[namespacedName].ExistingSecretReferences[secretObj.Name].UpdateNeeded = false | ||
klog.V(5).Infof("Secret %q in %q namespace is %s", secretObj.Name, secretObj.Namespace, string(operationResult)) | ||
} |
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.
Add a v(5) log here if the secret is not updated.
@@ -28,6 +28,7 @@ type KeyVaultSecretUriSegment struct { | |||
HostName string |
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.
This is no longer just indicates the UriSegment of the Secret, how about rename this type to KeyVaultSecretMetadata
?
internal/controller/processor.go
Outdated
@@ -201,6 +210,7 @@ func (processor *AppConfigurationProviderProcessor) processSecretReferenceRefres | |||
|
|||
// Only resolve the secret references that not specified the secret version | |||
secretReferencesToSolve := make(map[string]*loader.TargetSecretReference) | |||
cachedSecretReferences := make(map[string]*loader.TargetSecretReference) |
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.
This variable seems useless, do we really need it?
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.
Currently ResolveSecretReferences
doesn't pass/return new parameters for secretID
of latest secret, it just update the secretID
in kvReferencesToResolve
. So need to cache secretRef before resolving.
internal/controller/processor.go
Outdated
@@ -332,3 +354,28 @@ func (processor *AppConfigurationProviderProcessor) calculateRequeueAfterInterva | |||
|
|||
return requeueAfterInterval | |||
} | |||
|
|||
func checkSecretVersion(existingSecretReferences map[string]*loader.TargetSecretReference, latestSecretReferences map[string]*loader.TargetSecretReference) { |
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.
This method is not well self-explained, check secret version for what? I can learn what the method do after reading the implementation, but this is not a good design to a method. A good method is that you can know what the method is doing from the method name and input/output params.
internal/controller/processor.go
Outdated
@@ -70,6 +70,9 @@ func (processor *AppConfigurationProviderProcessor) processFullReconciliation() | |||
return err | |||
} | |||
processor.Settings = updatedSettings | |||
for _, reference := range updatedSettings.SecretReferences { | |||
reference.UpdateNeeded = true | |||
} | |||
processor.ReconciliationState.ExistingSecretReferences = updatedSettings.SecretReferences |
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.
Since the SecretReferences now involves the information of secret now, we should set it to ExistingSecretReferences in the Finish()
step now, otherwise it might mismatch with the actual version in the K8s secret.
internal/controller/processor.go
Outdated
if _, ok := processor.ReconciliationState.ExistingSecretReferences[secretName]; ok { | ||
reference.SecretResourceVersion = processor.ReconciliationState.ExistingSecretReferences[secretName].SecretResourceVersion | ||
} | ||
} | ||
reconcileState.ExistingSecretReferences = keyValueRefreshedSettings.SecretReferences |
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.
Same with what I comment on the line 73
internal/controller/processor.go
Outdated
@@ -70,6 +70,9 @@ func (processor *AppConfigurationProviderProcessor) processFullReconciliation() | |||
return err | |||
} | |||
processor.Settings = updatedSettings | |||
for _, reference := range updatedSettings.SecretReferences { |
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.
Current all the version check are in the processor, result in we need to set the updateNeeded
everywhere for the secret references, could we put the version check in the controller right before trying to update the Secret? I think that would be more clear.
internal/controller/processor.go
Outdated
@@ -201,17 +199,26 @@ func (processor *AppConfigurationProviderProcessor) processSecretReferenceRefres | |||
|
|||
// Only resolve the secret references that not specified the secret version | |||
secretReferencesToSolve := make(map[string]*loader.TargetSecretReference) | |||
cachedSecretReferences := make(map[string]*loader.TargetSecretReference) |
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.
This name is really confusion-leading, what you do here is to deep copy the reconcileState.ExistingSecretReferences
, right?
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.
yes, how about copiedSecretReferences
?
@@ -50,7 +50,7 @@ type TargetKeyValueSettings struct { | |||
|
|||
type TargetSecretReference struct { | |||
Type corev1.SecretType | |||
UriSegments map[string]KeyVaultSecretUriSegment | |||
UriSegments map[string]KeyVaultSecretMetadata |
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.
The name UriSegments
does not make sense now, how about updated to SecretMetadatas
internal/controller/utils.go
Outdated
@@ -302,3 +302,41 @@ func verifySelectorObject(selector acpv1.Selector) error { | |||
|
|||
return nil | |||
} | |||
|
|||
func checkAndUpdateSecretRef(existingSecretReferences map[string]*loader.TargetSecretReference, latestSecretReferences map[string]*loader.TargetSecretReference, shouldReconcile bool) map[string]bool { |
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.
Could we let the method check secretUpdateNeeded
one by one?
Type: secret.Type, | ||
} | ||
secretToUpdate := checkAndUpdateSecretRef(reconciler.ProvidersReconcileState[namespacedName].ExistingSecretReferences, processor.Settings.SecretReferences, processor.ShouldReconcile) | ||
for secretName, secret := range processor.Settings.SecretSettings { |
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.
How about doing this:
for secretName, secret := range processor.Settings.SecretSettings {
if (!shouldCreateOrUpdate()){
continue;
}
// do create or update
.....
}
if _, ok := reconciler.ProvidersReconcileState[namespacedName].ExistingSecretReferences[secretName]; ok { | ||
processor.Settings.SecretReferences[secretName].SecretResourceVersion = reconciler.ProvidersReconcileState[namespacedName].ExistingSecretReferences[secretName].SecretResourceVersion | ||
} | ||
klog.V(5).Infof("Skip updating the secret %q in %q namespace since its data is up-to-date", secretName, provider.Namespace) |
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.
Skip updating the secret %q in %q namespace since data is not changed.
Type: secret.Type, | ||
} | ||
for secretName, secret := range processor.Settings.SecretSettings { | ||
if processor.ShouldReconcile || shouldCreateOrUpdate(reconciler.ProvidersReconcileState[namespacedName].ExistingSecretReferences, secretName, processor.Settings.SecretReferences[secretName]) { |
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.
This line is too long, break it into two lines.
Type: secret.Type, | ||
} | ||
for secretName, secret := range processor.Settings.SecretSettings { | ||
if processor.ShouldReconcile || shouldCreateOrUpdate(reconciler.ProvidersReconcileState[namespacedName].ExistingSecretReferences, secretName, processor.Settings.SecretReferences[secretName]) { |
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.
Nit: I know there's much difference in logic, but I think doing this is better for readability.
-
check
shouldReconcile
in theshouldCreateOrUpdate
method -
Change the logic to
if !shouldCreateOrUpdate(xxx) {
// do something
continue
}
// do something
@@ -728,6 +763,7 @@ var _ = Describe("AppConfiguationProvider controller", func() { | |||
Expect(string(secret.Data["testSecretKey3"])).Should(Equal("newTestSecretValue3")) | |||
Expect(secret.Type).Should(Equal(corev1.SecretType("Opaque"))) | |||
}) | |||
|
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.
Nit: extra line
SecretReferences: mockedSecretReference, | ||
} | ||
|
||
mockConfigurationSettings.EXPECT().ResolveSecretReferences(gomock.Any(), gomock.Any(), gomock.Any()).Return(newTargetSettings, nil) |
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 didn't quite sure why check the refresh two times. And seems you didn't add the mocks for the secretId, how it can be refreshed without checking secretID?
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.
This test covers 2 refresh scenarios, the first time refresh when secretMetaData change, the second time not refresh when data not change. The first time refresh because mocked secretReferences length changed. Will add secretID.
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.
Got you, and please add the scenario for the secretId check
internal/controller/utils.go
Outdated
@@ -302,3 +302,25 @@ func verifySelectorObject(selector acpv1.Selector) error { | |||
|
|||
return nil | |||
} | |||
|
|||
func shouldCreateOrUpdate(existingSecretReferences map[string]*loader.TargetSecretReference, secretName string, secretReference *loader.TargetSecretReference) bool { |
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.
Why not pass the existing and target secretMetadata as input?
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.
Target secretMetadata may not exist in existingSecretReferences map
@@ -50,7 +50,7 @@ type TargetKeyValueSettings struct { | |||
|
|||
type TargetSecretReference struct { | |||
Type corev1.SecretType | |||
UriSegments map[string]KeyVaultSecretUriSegment | |||
SecretMetadata map[string]KeyVaultSecretMetadata |
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.
SecretMetadatas
, should use the plural
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.
MetaData
is plural noun, no need s
@@ -425,7 +425,15 @@ func (reconciler *AzureAppConfigurationProviderReconciler) createOrUpdateSecrets | |||
Namespace: provider.Namespace, | |||
} | |||
|
|||
for secretName, secret := range settings.SecretSettings { | |||
for secretName, secret := range processor.Settings.SecretSettings { | |||
if !shouldCreateOrUpdate(reconciler.ProvidersReconcileState[namespacedName].ExistingSecretReferences, secretName, processor.Settings.SecretReferences[secretName], processor.ShouldReconcile) { |
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.
How about just pass the processor?
}, timeout, interval).Should(BeTrue()) | ||
|
||
Expect(secret.Namespace).Should(Equal(ProviderNamespace)) | ||
Expect(string(secret.Data["testSecretKey"])).Should(Equal("newTestSecretValue")) |
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.
We should also verify the secret with unchanged ID would not be updated.
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.
line746-763 include scenario when secretID
not changed.
@@ -245,7 +245,7 @@ func (csl *ConfigurationSettingLoader) CreateKeyValueSettings(ctx context.Contex | |||
} | |||
|
|||
currentUrl := *setting.Value | |||
secretUriSegment, err := parse(currentUrl) | |||
secretMetadata, err := parse(currentUrl) |
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.
This line and line200 are all using the secretMatadata word, that indeed causes confusion. I would suggest SecretMatadatas
(regardless the plural and singular same form) or SecretsMetadata
in TargetSecretReference
internal/controller/processor.go
Outdated
for secretName, reference := range reconcileState.ExistingSecretReferences { | ||
for key, uriSegment := range reference.UriSegments { | ||
for key, uriSegment := range reference.SecretsMetadata { |
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.
uriSegment -> secretMetadata
internal/controller/utils.go
Outdated
if _, ok := existingSecretReferences[secretName].SecretsMetadata[key]; !ok { | ||
return true | ||
} | ||
if existingSecretReferences[secretName].SecretsMetadata[key].SecretId != nil && secretMetadata.SecretId != nil && |
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.
Break this long check into multiple lines
@@ -386,7 +387,10 @@ func (csl *ConfigurationSettingLoader) ResolveSecretReferences( | |||
} | |||
lock.Lock() | |||
defer lock.Unlock() | |||
resolvedSecretReferences[name].Data[currentKey] = []byte(*resolvedSecret.Value) | |||
resolvedSecrets[name].Data[currentKey] = []byte(*resolvedSecret.Value) | |||
currentUriSegment := targetSecretReference.SecretMetadata[currentKey] |
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.
This name is not accurate now, currentSecretMetadata
* resolve confict * update * resolve comments * add test * update * update * update * rename secretMetadata to secretsMetadata * update
No description provided.