Skip to content

feat(app): add lifecycle_type support for app resource and datasources - #579

Merged
ANUGRAHG merged 7 commits into
cloudfoundry:mainfrom
SMendaci:feat/app-cnb-lifecycle
Sep 16, 2026
Merged

ANUGRAHG merged 7 commits into
cloudfoundry:mainfrom
SMendaci:feat/app-cnb-lifecycle

Conversation

@SMendaci

@SMendaci SMendaci commented Aug 20, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Cloud Foundry already supports the lifecycle attribute in application manifests. This change exposes that support through the provider as lifecycle_type, including the buildpack, cnb, and docker variants.

  • Add support for lifecycle_type on cloudfoundry_app so lifecycle configuration is read from and written to the app manifest mapping.
  • Restrict lifecycle_type to the allowed values buildpack, docker, and cnb to catch invalid values at plan time.
  • Expose lifecycle_type in cloudfoundry_app and cloudfoundry_apps data sources for read parity with the resource.
  • Add VCR-recorded tests covering the new lifecycle_type behavior.

Does this introduce a breaking change?

  • Yes
  • No

Pull Request Type

What kind of change does this Pull Request introduce?

  • Bugfix
  • Feature
  • Refactoring (no functional changes, no api changes)
  • Documentation content changes
  • Other... Please describe:

How to Test

  • Run the provider tests:
go test ./cloudfoundry/provider -run 'TestAppResource_Configure' -count=1 -v -timeout 20m
  • Validate lifecycle behavior manually with plan/apply:
    • lifecycle_type = "docker" with docker_image set should pass validation.
    • lifecycle_type = "docker" without docker_image should fail validation.
    • docker_image with a non-docker lifecycle_type should fail validation.
    • lifecycle_type = "cnb" with a buildpack app should be accepted.

What to Check

Verify that the following are valid:

  • Automated tests pass
  • lifecycle_type is persisted/read correctly on cloudfoundry_app
  • lifecycle_type is exposed by both app data sources
  • Invalid lifecycle values are rejected at plan time

Other Information

  • Scope is intentionally limited to lifecycle support and validation for the allowed lifecycle values.
  • The cnb lifecycle variant is now explicitly supported and covered by VCR tests.

Checklist for reviewer

The following organizational tasks must be completed before merging this PR:

  • The PR has the matching labels assigned to it.
  • The PR has a milestone assigned to it.
  • If the PR closes an issue, the issue is referenced.
  • Possible follow-up items are created and linked.

Copilot AI lite review requested due to automatic review settings August 20, 2026 12:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds lifecycle_type support across the Cloud Foundry app resource and app data sources, wiring the value through manifest mapping and exposing it for read parity, along with minimal validation to keep docker_image and lifecycle_type consistent.

Changes:

  • Add lifecycle_type to cloudfoundry_app schema, including config validation for docker lifecycle vs docker_image.
  • Expose lifecycle_type in cloudfoundry_app and cloudfoundry_apps data sources and map it from CF app/manifest values.
  • Update generated docs to document the new lifecycle_type attribute behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
docs/resources/app.md Documents lifecycle_type on the app resource.
docs/data-sources/apps.md Documents lifecycle_type on the apps data source.
docs/data-sources/app.md Documents lifecycle_type on the app data source.
cloudfoundry/provider/types_app.go Adds lifecycle_type to TF types and maps lifecycle to/from manifest/app values.
cloudfoundry/provider/resource_app.go Adds lifecycle_type schema + docker consistency validation.
cloudfoundry/provider/datasource_apps.go Adds lifecycle_type to apps list schema output.
cloudfoundry/provider/datasource_app.go Adds lifecycle_type to single app data source schema output.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cloudfoundry/provider/types_app.go Outdated
Comment thread cloudfoundry/provider/resource_app.go Outdated
Comment thread cloudfoundry/provider/resource_app.go
Adds an optional/computed lifecycle_type attribute to the cloudfoundry_app
resource and exposes it in the cloudfoundry_app and cloudfoundry_apps
data sources.

Wires lifecycle_type into app manifest push/read mapping, applies minimal
docker lifecycle consistency validation with docker_image, and updates
documentation to describe lifecycle support while allowing additional
lifecycle identifiers supported by the target Cloud Foundry platform.

Co-authored-by: Gmllt <gilles.miraillet@orange.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Suppressed comments (2)

cloudfoundry/provider/resource_app.go:365

  • The new lifecycle_type behavior and ValidateConfig rules (docker_image vs lifecycle_type) are not covered by existing tests in this package (no *_test.go assertions mention lifecycle_type). Adding unit tests for the happy path and the two invalid combinations would help prevent regressions, and adding coverage for both cloudfoundry_app and the app data sources would confirm the new read parity.
	if !config.Lifecycle.IsNull() && !config.Lifecycle.IsUnknown() && config.Lifecycle.ValueString() == string(cfv3operation.Docker) &&
		!config.DockerImage.IsUnknown() && config.DockerImage.IsNull() {
		resp.Diagnostics.AddAttributeError(
			path.Root("docker_image"),
			"Missing docker image",

cloudfoundry/provider/types_app.go:401

  • mapLifecycleToStringType currently prefers app.Lifecycle.Type over the generated manifest's lifecycle field. That can diverge from the PR goal of reading lifecycle configuration from the manifest mapping (and makes it harder to preserve a "missing" lifecycle when the app API always returns a default). Consider preferring appManifest.Lifecycle first (with nil checks) and only falling back to app.Lifecycle.Type when the manifest does not provide a value.
func mapLifecycleToStringType(appManifest *cfv3operation.AppManifest, app *cfv3resource.App) types.String {
	if app.Lifecycle.Type != "" {
		return types.StringValue(app.Lifecycle.Type)
	}
	if appManifest.Lifecycle != "" {

Removes duplicated null/unknown guard conditions flagged as new-code
duplication in ValidateConfig by factoring them into isDockerLifecycle
and hasDockerImage booleans.
@SMendaci
SMendaci requested a lite review from Copilot August 20, 2026 14:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Suppressed comments (4)

cloudfoundry/provider/types_app.go:398

  • mapLifecycleToStringType currently prefers app.Lifecycle.Type over the generated manifest's lifecycle. Since app.Lifecycle.Type is typically always populated by the CF API, lifecycle_type will almost never be null in state, which conflicts with the PR goal of keeping lifecycle_type explicitly null when lifecycle is absent from the manifest mapping. Prefer reading from the manifest first (and return null if the manifest omits it).
	if app.Lifecycle.Type != "" {
		return types.StringValue(app.Lifecycle.Type)
	}
	if appManifest.Lifecycle != "" {
		return types.StringValue(string(appManifest.Lifecycle))

cloudfoundry/provider/resource_app.go:357

  • ValidateConfig introduces new lifecycle_type/docker_image validation behavior, but there are no unit tests covering the valid/invalid combinations (e.g., lifecycle_type="docker" without docker_image, docker_image with lifecycle_type set to a non-docker value, omitted lifecycle_type with docker_image). Adding test cases in the existing app resource tests would prevent regressions.
func (r *appResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) {
	var config AppType
	resp.Diagnostics.Append(req.Config.Get(ctx, &config)...)

	if resp.Diagnostics.HasError() {

cloudfoundry/provider/types_app.go:31

  • The new struct field name Lifecycle is ambiguous given the schema attribute is lifecycle_type and CF apps have a broader lifecycle concept (type+data). Renaming this field to LifecycleType would better match the attribute name and avoid confusion when adding lifecycle data support later.
	Lifecycle                             types.String       `tfsdk:"lifecycle_type"`

cloudfoundry/provider/types_app.go:204

  • docker_image is Optional (and can be Unknown during planning). mapAppTypeToValues currently treats Unknown as "set" (because it only checks IsNull), which can push a manifest with an empty docker image string. This becomes more likely now that lifecycle_type can be Computed/Unknown; it should ignore docker_image when it's Unknown.

This issue also appears on line 394 of the same file.

		appmanifest.Docker = &appManifestDocker
	}
	if !appType.Lifecycle.IsNull() && !appType.Lifecycle.IsUnknown() {
		appmanifest.Lifecycle = cfv3operation.AppLifecycle(appType.Lifecycle.ValueString())
	}

@SMendaci

Copy link
Copy Markdown
Contributor Author

Quality Gate Failed Quality Gate failed

Failed conditions 16.2% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

This duplication already existed in the codebase before this PR (mapAppValuesToType/mapAppDatasourceValuesToType and datasource_app.go/datasource_apps.go were already near-identical). This PR just follows that existing pattern and doesn't introduce new duplication.

@ANUGRAHG

ANUGRAHG commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

@SMendaci Could we restrict lifecycle_type to a defined set of allowed values? The CF v3 API only supports three lifecycle types — buildpack, docker, and cnb — and the current implementation accepts any arbitrary string. Adding an enum constraint would catch misconfigured values at plan time rather than surfacing a CF API error at apply time.

Additionally, could you add VCR-recorded tests covering the new lifecycle_type attribute? You can spin up a local CF environment using kind-deployment to record the fixtures.

@SMendaci
SMendaci marked this pull request as draft September 8, 2026 07:18
Comment thread cloudfoundry/provider/types_app.go Outdated
EnableSSH types.Bool `tfsdk:"enable_ssh"`
Stack types.String `tfsdk:"stack"`
Buildpacks types.List `tfsdk:"buildpacks"`
Lifecycle types.String `tfsdk:"lifecycle_type"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you rename it to LifecycleType? This makes the attribute name more explicit about what it represents. Same for DatasourceAppType too.

reqPlanType is required here to identify whether attributes like "health-check-interval", "readiness-health-check-interval"
are present as part of app spec or not, since cf api controller converts them to be part of process spec internally
*/
func mapLifecycleToStringType(appManifest *cfv3operation.AppManifest, app *cfv3resource.App) types.String {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we move mapLifecycleToStringType above these comments? These comments describe the behavior of mapAppValuesToType, so keeping them immediately above that function would make the context clearer.

@SMendaci
SMendaci marked this pull request as ready for review September 8, 2026 13:31
@SMendaci

SMendaci commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @ANUGRAHG

  • lifecycle_type is now constrained to buildpack, docker, and cnb, with VCR coverage added.
  • The field has been renamed to LifecycleType, and mapLifecycleToStringType was moved for better readability.

@ANUGRAHG

ANUGRAHG commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Hi @SMendaci,
The lifecycle-type specific tests in resource_app_lifecycle_test.go would fit better inside the existing resource_app_test.go alongside the other app resource tests — could you move them there? the convention in this repo is one test file per resource.
Also, how you recorded the VCR fixtures? did you use a local CF deployment (e.g. kind-deployment)?

@lechnerc77 lechnerc77 added the enhancement New feature or request label Sep 9, 2026
@lechnerc77 lechnerc77 added this to the 1.19.0 milestone Sep 9, 2026
@SMendaci

SMendaci commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor Author

Hi @SMendaci, The lifecycle-type specific tests in resource_app_lifecycle_test.go would fit better inside the existing resource_app_test.go alongside the other app resource tests — could you move them there? the convention in this repo is one test file per resource. Also, how you recorded the VCR fixtures? did you use a local CF deployment (e.g. kind-deployment)?

Hi @ANUGRAHG
Thanks for the review. I'll move the lifecycle-specific tests back into resource_app_test.go.
For the VCR fixtures, yes, we recorded them against a local CF deployment using kind-deployment , like the other app resource tests, for the lifecycle tests, we created and used the PerformanceTeamBLR org and tf-space-1 space.
I'll make the adjustment shortly.

@SMendaci
SMendaci requested a review from ANUGRAHG September 10, 2026 10:26
@ANUGRAHG

Copy link
Copy Markdown
Contributor

Hello @SMendaci ,
Rather than having a separate function, TestAppResource_Lifecycle, can we add these tests to TestAppResource_Configure instead?
Also, there are fixtures for the error cases where the YAML files are currently empty. Do we really need these fixtures? If they are not required, we can skip or remove them.

@SMendaci

Copy link
Copy Markdown
Contributor Author

Hello @SMendaci , Rather than having a separate function, TestAppResource_Lifecycle, can we add these tests to TestAppResource_Configure instead? Also, there are fixtures for the error cases where the YAML files are currently empty. Do we really need these fixtures? If they are not required, we can skip or remove them.

Hello @ANUGRAHG ,
I split the lifecycle tests into a separate function because the existing fixtures were recorded against an environment where the required domains and services already existed. When re-recording them in my environment, the tests failed unless I first reproduced the same setup.
I’ll try moving the lifecycle tests back into TestAppResource_Configure and run the tests again.

@ANUGRAHG

Copy link
Copy Markdown
Contributor

Hi @SMendaci

There’s no need to record all the tests. You can only record the newly added test cases.

@sonarqubecloud

Copy link
Copy Markdown

@SMendaci

Copy link
Copy Markdown
Contributor Author

Hi @ANUGRAHG ,
The requested modification has been made, and I only re-recorded the newly added test cases. It worked well.

@ANUGRAHG ANUGRAHG left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lgtm

@ANUGRAHG
ANUGRAHG merged commit 2af7760 into cloudfoundry:main Sep 16, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants