Currently, I'm working as a platform engineer. Kubernetes (and its ecosystem, e.g., External Secrets, ArgoCD) and AWS services, including AWS Secrets Manager and EKS, are things I deal with every day. From my point of view, I am an end user of those CNCF projects and AWS. As I want to go further into the cloud-native path, I decided to start my open source contributor journey just 2 months ago. For this note, I will explain what I did in this contribution, from start, investigation to delivering the PR.
Normally, The feature requests, bugs, documentation requests, questions are listed on the issues page. This post is about my contribution to the issue number #6104.
This contribution is related to 2 CNCF projects: ArgoCD and External Secrets Operator (ESO).
ArgoCD
A CNCF graduated project and a popular GitOps continuous delivery tool for Kubernetes. It watches your Git repository and ensures your cluster state always matches what's defined there. Its UI console gives you a visual overview of all your application resources and their health status. (https://argo-cd.readthedocs.io/)
External Secrets Operator (ESO)
A CNCF sandbox project that acts as a bridge between Kubernetes and external secret management systems such as AWS Secrets Manager, HashiCorp Vault, and Google Secret Manager. Instead of hardcoding secrets into your cluster, ESO automatically syncs them into Kubernetes Secret from your preferred secret provider. (https://external-secrets.io/)
For ESO, there are 2 main CRDs: SecretStore and ExternalSecret.
-
SecretStoreis where we define how to reach the external API, such as AWS Secrets Manager. -
ExternalSecretis where we define which data to retrieve and what to create in your cluster.
If you define everything correctly (happy path), the ESO operator will create a Kubernetes native Secret in your cluster. ArgoCD also shows the relationship between the ExternalSecret resource and the created Secret, which looks like this on the ArgoCD console:
The problem statement
This was something new to me as well. ESO is not only able to create Kubernetes Secrets, but it can also create other resources in your cluster. For example, if you want ESO to create a Kubernetes ConfigMap from AWS Parameter Store, this is also doable. This feature is called Targeting Custom Resources
But one key difference between creating Secret and other resources is that the relationship for resources other than Secret is not shown on the ArgoCD console.
So, in the case of non-Secret resources, it looked like this on the ArgoCD console:

Which should have looked like this:

I was not the original reporter of this issue (#6104), but I picked it up while exploring this feature.
Investigation
So, I tried creating two ExternalSecret resources, one for a Secret and another for a ConfigMap, to see what distinguishes them. This was what I found:

The key differences between the two cases were the ownerReferences attribute and the external-secrets annotations and labels. They were added only in the Secret, not in the ConfigMap case.
-
ownerReferences: This is the Kubernetes native way of indicating which resource owns another resource and ArgoCD relies on this attribute to understand resource relationships and visualize them in the UI. An example of this is the relationship between aDeployment,ReplicaSet, andPod. When you create aDeployment, theReplicaSetthat is created from it will haveownerReferencesthat refer to theDeployment. The same concept applies to thePods created by theReplicaSet. (See more detail)
- The external-secrets annotations and labels: These are required for the ESO controller to reconcile the resource.
So, my plan to fix this was to add the missing ownerReferences attribute, labels, and annotations.
Implementation
The ESO project is implemented in Go. The main codebase for this fix is in pkg/controllers/externalsecret, which holds the key logic for how Secret and generic targets (e.g., ConfigMap) are created by the controllers.
In this folder, there are several controllers:
externalsecret_controller.go: The main reconcile loop. It routes to the Secret path or the generic target path based on whether
spec.target.manifestis set. TheSecretpath's ownership logic (mutationFunc) already worked correctly which I aimed to replicate for generic targets.externalsecret_controller_template.go: Handles templating and metadata for the
Secretpath only. ItssetMetadata()function already propagated ExternalSecretlabels/annotationsas a fallback. The generic target path was missing this same behavior.externalsecret_controller_manifest.go: Handles create/update/delete for generic targets. The metadata propagation and the ownership logic were missing here.
externalsecret_controller_manifest_test.go: The unit tests for the above controller.
With this understanding, the changes came down to two things in externalsecret_controller_manifest.go:
- Propagate the ExternalSecret's labels and annotations to the target resource (the same fallback that setMetadata() already did for Secrets)
- Add an
applyOwnership()function to setownerReferenceson generic targets (replicating the existingmutationFuncpattern for Secrets).
The pull request was raised for these changes plus the unit tests that cover the proposed changes.
Conclusion
The PR was finally reviewed and merged. It was my very first contribution to open source software, and I'm quite proud of that. This work was included in version 2.3.0, It feels really good seeing my name there and I gained several key learnings from this contribution.
On AI in open source contribution
AI is increasingly welcomed in the contribution process. In fact, ESO already has AI in place. For example, ESO's code review bot, which looks very impressive. However, this doesn't mean contributors can rely on AI 100% for their contributions. They are still the ones accountable for their changes.
From my experience, I used AI to help understand the codebase and code generation. But if you have no foundational knowledge of the project, say, no idea about Kubernetes, ESO, or ArgoCD then AI is not quite useful. It can even be worse as it might suggest hallucinated or unrelated changes that you don't have a chance to challenge.
My suggestions for using AI in contributions:
- Understand the coding standards and conventions of the project before you start.
- Strictly review what AI produces. Try to understand every output and the reasons behind the change.
- Build and test the change locally. Deploy to your local cluster and make sure it works as expected. Don't trust AI-generated code blindly.
- Most importantly, interact with other contributors and maintainers in your own words. Do not copy and paste responses from AI. Always remember that another contributor, maintainer, or issue requester on the other end is a human (at least from what I’ve seen so far 😄). So, treat them with respect.
On the open source experience
The maintainers were very supportive throughout the process. They are responsive in reviews and helpful with guidance. It was also great to see the extensive automation in the project especially the GitHub Actions workflows and bots. There's a lot to learn just from working with others in the community and seeing how a well-maintained project operates.


Top comments (0)