-
Notifications
You must be signed in to change notification settings - Fork 9
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
Added a watcher for secret #169
Conversation
796743b
to
213b67b
Compare
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.
Remove the update related functions in the secret_webhook.go and secret_webhook_test.go.
ctrl "sigs.k8s.io/controller-runtime" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
|
||
"antrea.io/antrea/pkg/util/env" |
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 we really import a new package to access the environment variable? Can we not access it directly?
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.
Yeah. We should import os or this package.
// Client in controller requires reconciler for each object that are under watch. So to avoid reconciler and use only | ||
// watch, that can be implemented by clientset. | ||
if r.clientset, err = kubernetes.NewForConfig(ctrl.GetConfigOrDie()); err != nil { | ||
r.Log.Error(err, "error while creating config") |
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.
Can you re-phrase the error, as config does not indicate which config is being referred to.?
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.
What should we add.
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.
may be "error while fetching cluster configuration"?
r.Log.Info("Waiting for shared informer caches to be synced") | ||
// Blocking call to wait till the informer caches are synced by controller run-time | ||
// or the context is Done. | ||
if !(*r.Mgr).GetCache().WaitForCacheSync(context.TODO()) { | ||
return fmt.Errorf("failed to sync shared informer cache") | ||
} | ||
|
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.
re-add the space.
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.
Solved.
} | ||
} | ||
|
||
// resetWatcher Create a watcher for secret |
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.
// resetWatcher Create a watcher for secret | |
// resetWatcher creates a watcher for Secret |
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.
Solved.
var err error | ||
for { | ||
if r.watcher, err = r.clientset.CoreV1().Secrets(env.GetPodNamespace()).Watch(context.Background(), metav1.ListOptions{}); err != nil { | ||
r.Log.Error(err, "error while creating secret watcher") |
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.
r.Log.Error(err, "error while creating secret watcher") | |
r.Log.Error(err, "error creating Secret watcher") |
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.
Solved.
|
||
} | ||
|
||
// setupSecretWatcher Set up a watcher. |
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.
// setupSecretWatcher Set up a watcher. | |
// setupSecretWatcher set up a watcher for Secret objects. |
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.
Solved.
_ = fakeClient.Create(context.Background(), account) | ||
go func() { | ||
//err = reconciler.setupSecretWatcher() | ||
//Expect(err).Should(HaveOccurred()) |
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: remove?
Cleanup the unit-tests and remove unused code.
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.
Solved.
go.mod
Outdated
@@ -38,6 +38,7 @@ require ( | |||
github.com/PuerkitoBio/purell v1.1.1 // indirect | |||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect | |||
github.com/beorn7/perks v1.0.1 // indirect | |||
github.com/blang/semver v3.5.1+incompatible // indirect |
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.
In the L42, latest version of github.com/blang/semver is already added as indirect dependency. So you can remove this. Same for go.sum file as well.
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.
Solved.
|
||
// getCPABySecret returns nil only when the Secret is not used by any CloudProvideAccount CR, | ||
// otherwise the dependent CloudProvideAccount CR will be returned. | ||
func (r *CloudProviderAccountReconciler) getCPABySecret(s types.NamespacedName) (error, []cloudv1alpha1.CloudProviderAccount) { |
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.
Change the function to getCpaBySecret.
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.
Solved.
namespacedName := types.NamespacedName{Namespace: secret.Namespace, Name: secret.Name} | ||
err, cpaItems := r.getCPABySecret(namespacedName) | ||
if err != nil { | ||
r.Log.Error(err, "error while getting CPA by Secret %v", secret.Name) |
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.
For consistent logging(Similiar to L297), can you dump the secret NamespacedName instead of Name?
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.
Solved.
// result vpc cache will contain vpcs from old and new accounts. | ||
err := r.processCreate(&namespacedName, &cpa) | ||
if err != nil { | ||
r.Log.Error(err, "error while adding the secret in CPAs") |
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.
Any error returned in watchSecret() will exit the controller and restart the pod.
IMO, we should not be restarting for error in L293, since only one CPA credentials update failed. May be we can just log an error and let user check the logs.
@reachjainrahul Any suggestions here?
} | ||
} | ||
|
||
// setupSecretWatcher Set up a watcher for Secret objects. |
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.
// setupSecretWatcher Set up a watcher for Secret objects. | |
// setupSecretWatcher set up a watcher for Secret objects. |
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.
Solved.
// Create CPA | ||
_ = fakeClient.Create(context.Background(), account) | ||
go func() { | ||
ch <- reconciler.setupSecretWatcher() // writing |
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: remove //comment
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.
Solved.
err = os.Setenv("POD_NAMESPACE", testSecretNamespacedName.Namespace) | ||
Expect(err).ShouldNot(HaveOccurred()) | ||
// Create secret | ||
_, err = reconciler.clientset.CoreV1().Secrets(testSecretNamespacedName.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.
Add a comment explaining why you need to created a Secret using clientset and fakeClient
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.
Solved.
e03b059
to
dff0991
Compare
r.mutex.Lock() | ||
secret := event.Object.(*v1.Secret) | ||
namespacedName := types.NamespacedName{Namespace: secret.Namespace, Name: secret.Name} | ||
r.Log.Info("Received request for update", "Secret", namespacedName) |
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.
r.Log.Info("Received request for update", "Secret", namespacedName) | |
r.Log.Info("Received request", "Secret", namespacedName, "operation", update) |
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.
Solved.
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 brief explanation in the commit body about this PR.
- name: POD_NAMESPACE | ||
valueFrom: | ||
fieldRef: | ||
fieldPath: metadata.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.
This will require changes in the helm charts as well.
here: nephe/build/charts/nephe/templates/controller/deployment.yaml
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.
Solved.
_, _ = GinkgoWriter.Write([]byte(fmt.Sprintf("Got admission response %+v\n", response))) | ||
Expect(response.Allowed).To(BeTrue()) | ||
}) | ||
It("Validate Secret delete without dependent AWS CPA", func() { |
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.
Delete tests should not be removed.
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.
Solved.
}) | ||
|
||
// The below set of tests validate Secret update/delete for Azure config. | ||
It("Validate Azure Secret delete with dependent Azure CPA", func() { |
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 here
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.
Solved.
r.accountProviderType = make(map[types.NamespacedName]common.ProviderType) | ||
// Client in controller requires reconciler for each object that are under watch. So to avoid reconciler and use only |
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.
When you say client, you are referring to client from controller-runtime/pkg/client 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.
Solved.
} | ||
} | ||
} | ||
|
||
// setWatcher sets the controller sync status and watcher. |
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: update function name
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.
Solved.
|
||
delete(r.accountProviderType, *namespacedName) | ||
} | ||
|
||
func (r *CloudProviderAccountReconciler) getAccountProviderType(namespacedName *types.NamespacedName) common.ProviderType { | ||
r.mutex.Lock() | ||
defer r.mutex.Unlock() | ||
|
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 here
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.
Solved.
|
||
return r.accountProviderType[*namespacedName] | ||
} | ||
|
||
// getCpaBySecret returns nil only when the Secret is not used by any CloudProvideAccount CR, | ||
// otherwise the dependent CloudProvideAccount CR will be returned. |
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.
// otherwise the dependent CloudProvideAccount CR will be returned. | |
// otherwise the dependent CloudProvideAccount CRs will be returned. |
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.
Solved.
func (r *CloudProviderAccountReconciler) getCpaBySecret(s types.NamespacedName) (error, []crdv1alpha1.CloudProviderAccount) { | ||
cpaList := &crdv1alpha1.CloudProviderAccountList{} | ||
if err := r.Client.List(context.TODO(), cpaList, &client.ListOptions{}); err != nil { | ||
return fmt.Errorf("failed to get CloudProviderAccount list, err:%v", err), 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.
nit: for consistency
return fmt.Errorf("failed to get CloudProviderAccount list, err:%v", err), nil | |
return fmt.Errorf("failed to get CloudProviderAccount list, err %v", err), 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.
Solved.
} | ||
} | ||
|
||
// resetWatcher create a watcher for Secret |
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: function name different
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.
Solved.
Expect(err).ShouldNot(HaveOccurred()) | ||
// Create secret | ||
// Created a secret using clientset because watcher is created using clientset. So inorder to know | ||
// watcher if the secret is modified secret should be created using clientset. Secret should be created using |
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.
Does this convey message correctly?
Create a secret using both fakeClient and clientSet, since secret watcher uses cleintset while reconciler using client from controller run-time. Both secret watcher and reconciler should be able to retrieve the secret object.
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.
Solved.
855e065
to
cfd4867
Compare
pkg/config/env.go
Outdated
func GetPodNamespace() string { | ||
podNamespace := os.Getenv(PodNamespaceEnvKey) | ||
if podNamespace == "" { | ||
klog.Errorf("environment variable %v not found", PodNamespaceEnvKey) |
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.
Do not add new logger package here. We don't use klog.
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.
What log should we add.
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.
Its actually a FATAL error in our case. If this does not exist, then we should continue further.
The log message you added does not crash the pod. Suppose namespace is not set, what would happen to the watcher? will it throw an error? If it throws an error, then we will be in state where we are continuously calling resetting the watcher object.
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.
In our class we handle this error.
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.
Solved.
r.mutex.Lock() | ||
secret := event.Object.(*v1.Secret) | ||
namespacedName := types.NamespacedName{Namespace: secret.Namespace, Name: secret.Name} | ||
r.Log.WithName("Secret").Info("Received request", "Secret", namespacedName, "operation", "update") |
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.
Instead of prefixing all the log messages with r.Log.WithName("Secret")
can we do initialize a local variable and use it?
log := Log.WithName("Secret")
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.
Then we should initialize logger for each secret methods.
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.
In the other functions, you can keep r.Log.WithName("Secret")
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 only this function requires variable
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.
Solved.
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.
Is it temporary, or this is the way we will have Secret prefix ?
ebf6687
to
b9b28ed
Compare
// Client in controller requires reconciler for each object that are under watch. So to avoid reconciler and use only | ||
// watch, that can be implemented by clientset. | ||
if r.clientset, err = kubernetes.NewForConfig(ctrl.GetConfigOrDie()); err != nil { | ||
r.Log.Error(err, "error creating client config") |
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.
creating config or just client?
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.
Both right. Because ctr.GetConfigOrDie creates config and kubernetes creates clientset
for _, cpa := range cpaItems { | ||
// If the credentials are updated to new cloud account then vpc cache is not updated. As a | ||
// result vpc cache will contain vpcs from old and new accounts. | ||
accountNamespacedName := types.NamespacedName{Namespace: cpa.Namespace, Name: cpa.Name} |
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.
is it a bug?
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.
@Anandkumar26 Please comment on this.
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.
@reachjainrahul Consider we have account 1, with cred 1. We get 10 VPCs from account.
Now user updates the cred 1 to cred 2. (Cred 2 can potential point to different account, same region).
In this particular scenario, VPCs cache will have:
- VPCs from account 1 (Since they never got deleted upon secret modification)
- VPCs from new account (updated credentials)
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.
@Nithish555 please remove the comment..
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.
Please remove the entire comment
} | ||
|
||
// getPodNamespace gets the namespace of the pod. | ||
func (r *CloudProviderAccountReconciler) getPodNamespace() 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.
I dont think this is required here.. You should check for empty ns in GetPodNamespace. not here.. Also verify if nephe is launched in default Namespace, whats the value you get.
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 required because the GetPodNamespace is generic so we should not handle it there. Because in this case we exit the pod.
The same namespace value which is configured in the pod metadata.
credential := `{"accessKeyId": "keyId","accessKeySecret": "Secret"}` | ||
err = os.Setenv("POD_NAMESPACE", testSecretNamespacedName.Namespace) | ||
Expect(err).ShouldNot(HaveOccurred()) | ||
// Create a secret using both fakeClient and clientSet, since secret watcher uses cleintset |
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.
typo clientset
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.
Solved.
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.
/LGTM
2632dfa
to
a48b6f0
Compare
/nephe-test-e2e-kind |
Signed-off-by: nithishs <[email protected]>
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.
/LGTM
No description provided.