feat: support environment variables for App (#188)#284
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements functional support for spec.environment on the App managed resource by wiring environment variables into manifest generation, drift detection, and update behavior, addressing #188.
Changes:
- Include environment variables when building the Cloud Foundry app manifest for pushes.
- Detect environment-variable drift and trigger a re-push when env changes are observed.
- Update API comments to reflect that environment variables are now supported.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| internal/controller/app/controller.go | Triggers UpdateAndPush when env drift is detected (in addition to docker image drift). |
| internal/clients/app/push.go | Adds env var mapping into the CF manifest used for push operations. |
| internal/clients/app/app.go | Adds env var drift detection by comparing desired env JSON vs generated manifest env. |
| apis/resources/v1alpha1/app_types.go | Removes “NOT SUPPORTED YET” note from the Environment field comment. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
SatabdiG
left a comment
There was a problem hiding this comment.
We should definitely add test file.
As far as I am aware there are two ways CF handles env vars
- The Manifest/Push path - A sledgehammer of sorts, applies a full manifest, res-stages, restarts the app.
- The Environment Variable API — CF has a dedicated PUT /v3/apps/:guid/environment_variables endpoint. This is more of a scalpel and doesn't require a full restage of the app.
My core concern and question is that we are reusing the existing pattern for docker image changed -> push, does env variable need a push? It likely does not if we go via the API. Also push are expensive even more for crossplane reconcilers than the plain cf push.
Maybe you could help me through your reasoning here.
SatabdiG
left a comment
There was a problem hiding this comment.
good work on the restructure.
SatabdiG
left a comment
There was a problem hiding this comment.
Nice work but I think it introduced some new bugs
- Replace UpdateAndPush with SetEnvironmentVariables for env var updates - Fix nil deletion bug in envVarsChanged (env vars removed from spec now detected as drift) - Parse AppManifest once in DetectChanges instead of twice - Separate docker_image and environment handling in controller - Add SetEnvironmentVariables to AppClient interface and fake mock - Add 5 env var test cases covering drift detection scenarios
- Extract updateDockerImage and updateEnvVars helpers from Update - Add HasOtherChanges method to ChangeDetection to simplify condition - Fix import grouping in app_test.go (goimports)
When an env var is removed from spec.forProvider.environment, it was not being deleted from CF because SetEnvironmentVariables merges rather than replaces. Fix by calling GetEnvironmentVariables first to get current CF state, then sending nil for any var present in CF but absent from spec. Also adds GetEnvironmentVariables to AppClient interface and mock.
… assert mock expectations
da23538 to
e0672b9
Compare
|
Thanks for the detailed review. Here's what I addressed:
|
…t detection, add Stop/Start failure tests
SatabdiG
left a comment
There was a problem hiding this comment.
Very good work, this is almost there. I have just one comment.
SatabdiG
left a comment
There was a problem hiding this comment.
lgtm. Thanks for sticking with this 🥇
Closes #188
Changes
Architecture
Replaced UpdateAndPush with direct CF Environment Variable API (PATCH /v3/apps/:guid/environment_variables) for env var updates: no push, no restage, no unnecessary restart.
Bug fixes
Fixed nil deletion bug: updateEnvVars now calls GET /v3/apps/:guid/environment_variables first, then sends nil for any var present in CF but absent from spec , so removed vars are actually deleted.
Fixed resulting infinite update loop: was caused by removed vars never being cleared from CF, keeping drift alive.
Fixed double manifest parse: DetectChanges now calls getAppManifest once and shares the result across all checks.
Refactoring
Separated docker_image and environment handling in the controller: docker credentials are only fetched when the docker image actually changes.
Added GetEnvironmentVariables and SetEnvironmentVariables to AppClient interface and fake mock.
Tests
Added 5 unit tests covering env var drift detection (app_test.go):
Same in spec and CF → no drift
Different in spec vs CF → drift detected
Set in spec, missing in CF → drift detected
Removed from spec, still in CF → drift detected (the nil deletion bug)
Nil in both → no drift
Added 3 controller TestUpdate cases (controller_test.go):
EnvVarAdded — new var in spec, CF has none → SetEnvironmentVariables called correctly
EnvVarDeleted — var removed from spec, CF still has it → sent as nil to CF
EnvVarGetFails — GetEnvironmentVariables errors → update returns wrapped error