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

Added a watcher for secret #169

Merged
merged 1 commit into from
Apr 3, 2023
Merged

Conversation

Nithish555
Copy link
Contributor

No description provided.

@Nithish555 Nithish555 force-pushed the secret branch 5 times, most recently from 796743b to 213b67b Compare March 27, 2023 11:26
Copy link
Contributor

@Anandkumar26 Anandkumar26 left a 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"
Copy link
Contributor

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?

Copy link
Contributor Author

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")
Copy link
Contributor

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.?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should we add.

Copy link
Contributor

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")
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-add the space.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solved.

pkg/controllers/cloud/cloudprovideraccount_controller.go Outdated Show resolved Hide resolved
}
}

// resetWatcher Create a watcher for secret
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// resetWatcher Create a watcher for secret
// resetWatcher creates a watcher for Secret

Copy link
Contributor Author

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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
r.Log.Error(err, "error while creating secret watcher")
r.Log.Error(err, "error creating Secret watcher")

Copy link
Contributor Author

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// setupSecretWatcher Set up a watcher.
// setupSecretWatcher set up a watcher for Secret objects.

Copy link
Contributor Author

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())
Copy link
Contributor

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.

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor Author

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) {
Copy link
Contributor

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.

Copy link
Contributor Author

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)
Copy link
Contributor

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?

Copy link
Contributor Author

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")
Copy link
Contributor

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// setupSecretWatcher Set up a watcher for Secret objects.
// setupSecretWatcher set up a watcher for Secret objects.

Copy link
Contributor Author

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove //comment

Copy link
Contributor Author

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).
Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solved.

@Nithish555 Nithish555 force-pushed the secret branch 6 times, most recently from e03b059 to dff0991 Compare March 30, 2023 12:01
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
r.Log.Info("Received request for update", "Secret", namespacedName)
r.Log.Info("Received request", "Secret", namespacedName, "operation", update)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solved.

Copy link
Contributor

@Anandkumar26 Anandkumar26 left a 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
Copy link
Contributor

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

Copy link
Contributor Author

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() {
Copy link
Contributor

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.

Copy link
Contributor Author

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() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Copy link
Contributor Author

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
Copy link
Contributor

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?

Copy link
Contributor Author

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: update function name

Copy link
Contributor Author

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()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Copy link
Contributor Author

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// otherwise the dependent CloudProvideAccount CR will be returned.
// otherwise the dependent CloudProvideAccount CRs will be returned.

Copy link
Contributor Author

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: for consistency

Suggested change
return fmt.Errorf("failed to get CloudProviderAccount list, err:%v", err), nil
return fmt.Errorf("failed to get CloudProviderAccount list, err %v", err), nil

Copy link
Contributor Author

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: function name different

Copy link
Contributor Author

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
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solved.

@Nithish555 Nithish555 force-pushed the secret branch 3 times, most recently from 855e065 to cfd4867 Compare March 31, 2023 10:29
func GetPodNamespace() string {
podNamespace := os.Getenv(PodNamespaceEnvKey)
if podNamespace == "" {
klog.Errorf("environment variable %v not found", PodNamespaceEnvKey)
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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")
Copy link
Contributor

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")

Copy link
Contributor Author

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.

Copy link
Contributor

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")

Copy link
Contributor Author

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solved.

Copy link
Contributor

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 ?

@Nithish555 Nithish555 force-pushed the secret branch 3 times, most recently from ebf6687 to b9b28ed Compare March 31, 2023 11:44
// 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")
Copy link
Contributor

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?

Copy link
Contributor Author

@Nithish555 Nithish555 Apr 3, 2023

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}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it a bug?

Copy link
Contributor Author

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.

Copy link
Contributor

@Anandkumar26 Anandkumar26 Apr 3, 2023

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)

Copy link
Contributor

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..

Copy link
Contributor

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 {
Copy link
Contributor

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.

Copy link
Contributor Author

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo clientset

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solved.

@reachjainrahul reachjainrahul linked an issue Apr 3, 2023 that may be closed by this pull request
reachjainrahul
reachjainrahul previously approved these changes Apr 3, 2023
Copy link
Contributor

@reachjainrahul reachjainrahul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/LGTM

@reachjainrahul
Copy link
Contributor

/nephe-test-e2e-kind

Copy link
Contributor

@reachjainrahul reachjainrahul left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/LGTM

@reachjainrahul reachjainrahul merged commit a54a589 into antrea-io:main Apr 3, 2023
@reachjainrahul reachjainrahul added this to the Nephe v0.5 release milestone Jun 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support updates for CPA Secrets
3 participants