Updates in secrets referenced by sensitive fields don't trigger resource reconciliation
- Dominant language
- Go
- Stars
- 481
- Forks
- 131
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 11
Description
### What happened?
Hi,
I attempted to generate a Crossplane provider with Upjet for [PostgreSQL Terraform provider](https://registry.terraform.io/providers/cyrilgdn/postgresql/latest), but discovered that generated controllers do not watch referenced resources.
Take, for example, [postgresql_role](https://registry.terraform.io/providers/cyrilgdn/postgresql/latest/docs/resources/postgresql_role) resource, which has sensitive attribute `password`. The generated CRD contains the following:
```go
// Sets the role's password. A password is only of use
// for roles having the login attribute set to true.
// Sets the role's password
// +kubebuilder:validation:Optional
PasswordSecretRef *v1.SecretKeySelector `json:"passwordSecretRef,omitempty" tf:"-"`
```
I was able to create a Role resource and it successfully reconciled, but when I changed the contents of the secret referenced from `passwordSecretRef` field, nothing happened.
The reason is that the following code in the generated controller doesn't specify that reconciliation should trigger whenever an associated secret is changed:
```go
return ctrl.NewControllerManagedBy(mgr).
Named(name).
WithOptions(o.ForControllerRuntime()).
WithEventFilter(xpresource.DesiredStateChanged()).
Watches(&v1alpha1.Database{}, eventHandler).
Complete(ratelimiter.NewReconciler(name, r, o.GlobalRateLimiter))
```
KubeBuilder book describes how to watch externally managed resources (such as secrets) in controllers: https://book.kubebuilder.io/reference/watching-resources/externally-managed
Perhaps Upjet could generate all necessary boilerplate code to watch externally managed secrets (and maybe all referenced resources as well?).
### How can we reproduce it?
I followed the "[Generating a Crossplane provider](https://github.com/crossplane/upjet/blob/main/docs/generating-a-provider.md)" guide from this repository and generated a Crossplane provider for [PostgreSQL Terraform provider](https://registry.terraform.io/providers/cyrilgdn/postgresql/latest) with "postgresql_role" resource.
Here's my `config/role/config.go` file
```go
package role
import (
"github.com/crossplane/upjet/pkg/config"
)
// Configure configures individual resources by adding custom ResourceConfigurators.
func Configure(p *config.Provider) {
p.AddResourceConfigurator("postgresql_role", func(r *config.Resource) {
r.ShortGroup = "postgresql"
r.ExternalName = config.NameAsIdentifier
})
}
```
I generated CRDs and controller using `make generate` and then ran it against local Kind cluster using `make run`.
After initial reconciliation, I changed the contents of a secret which I referenced from my Role custom resource.
I used upjet 1.3.0.
Contributor guide
Research direction
Use config/role/config.go and the provider-generation guide to reproduce the issue with the postgresql_role resource, then run make generate and make run. Inspect the generated controller setup shown in the report and determine how referenced Secrets are watched; done means changing passwordSecretRef causes resource reconciliation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, kubernetes, postgresql, terraform
- Domain
- devops, infrastructure
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100