Skip to content

resource/pingone_application: add export support - #137

Closed
samir-gandhi wants to merge 3 commits into
mainfrom
polaris/GH-67-pingone-application-export-support
Closed

resource/pingone_application: add export support#137
samir-gandhi wants to merge 3 commits into
mainfrom
polaris/GH-67-pingone-application-export-support

Conversation

@samir-gandhi

Copy link
Copy Markdown
Contributor

Summary

  • Adds Terraform export support for pingone_application, covering the 4 application types the pingone_application Terraform resource schema actually supports: OIDC, SAML, External Link, and WS-Fed.
  • The management SDK's ReadOneApplication200Response (and the EntityArrayEmbedded.Applications list item type) is a discriminated union with 7 possible variants. A custom Go handler (internal/platform/pingone/resource_sso_application.go) unwraps the union via GetActualInstance() and projects the result into a flat applicationData struct with one nilable field per supported variant (OIDC, SAML, ExternalLink, WSFED). The YAML definition then models each variant as a plain object + nested_attributes block — because exactly one variant field is non-nil, the generic engine naturally emits only the one matching *_options block per resource.

Scope decision: the 3 built-in PingOne system application types — ApplicationPingOneAdminConsole, ApplicationPingOnePortal, ApplicationPingOneSelfService — have no corresponding nested schema block in the pingone_application Terraform resource (confirmed against the provider docs). They are provisioned automatically per environment and cannot be declaratively created/imported via this resource. Rather than silently emit an invalid resource block, the handler skips them and records a warning via c.AddWarning (visible in pingcli-terraformer output). This was verified live: the target test environment had all 3 system app types present, and each produced a clear skip warning while the 3 real OIDC/WORKER applications exported correctly.

Dependency: base SDK integration (#132, adding the pingone-go-sdk-v2/management client) is a prerequisite — this PR should not be merged before #132.

Files changed

  • definitions/pingone/sso/application.yaml — new YAML definition (new sso category directory)
  • internal/platform/pingone/resource_sso_application.go — new Go handler, registers pingone_application as a resource type distinct from the pre-existing pingone_davinci_application (different filename to avoid colliding with resource_application.go, which remains untouched)
  • internal/platform/pingone/resource_sso_application_test.go — new unit tests
  • internal/platform/pingone/dispatch_test.go, internal/schema/integration_test.go — bumped hardcoded resource/definition-count assertions (same pattern used by the sibling pilot resources pingone_group/pingone_population/pingone_resource)
  • contributing/RESOURCE_COVERAGE.md — flipped pingone_application to ✅
  • .changelog/pr-137.txt — changelog entry

Test plan

  • go run ./tools/validate-definitions definitions/ — all 9 definitions pass
  • go build ./..., go vet ./..., go fmt ./... — clean
  • go test ./internal/... -v -count=1 — all packages pass, including:
    • TestPingOneApplicationRegistered — new resource registered
    • TestDaVinciApplicationStillRegistered — regression guard confirming pingone_davinci_application is untouched
    • TestSSOAndDaVinciApplicationAreDistinctResourceTypes
    • TestToApplicationData_OIDC, TestToApplicationData_SAML, TestToApplicationData_ExternalLink, TestToApplicationData_WSFED (+ nested-block variants) — union unwrapping for all 4 supported types
    • TestToApplicationData_SkipsAdminConsole, _SkipsPortal, _SkipsSelfService — system app type skip behavior
    • TestToApplicationData_NilInput, _UnknownType — edge cases
  • Live export against a real PingOne environment (3 real applications: 1 WEB_APP OIDC, 2 WORKER OIDC; 3 system apps correctly skipped with warnings). Verified environment_id resolves to var.pingone_environment_id, no unresolved raw UUIDs for reference-eligible fields (icon IDs are correctly left as raw UUIDs — no exportable resource type owns them), and pingone_davinci_application.tf output is unchanged.
  • make regression-local — PASS, only acceptable additions (new pingone_application.tf file + a new fallback variable for the not-yet-exported pingone_key_rotation_policy_id reference)

Known gaps / follow-ups

  • oidc_options.certificate_based_authentication and oidc_options.mobile_app.push are present in the Terraform provider schema but have no backing field in the management SDK struct — not modeled (nothing to source from the API).
  • Cross-resource references to pingone_key, pingone_key_rotation_policy, and pingone_gateway fall back to Terraform variables since none of those resource types are exported yet — expected until those resources land.

Closes #67

samir-gandhi and others added 3 commits July 24, 2026 15:34
…sources

pingone-go-client only covers DaVinci, Environments, Connectors, and
ConfigurationManagement APIs, so the ~92 open Platform/SSO/Authorize/MFA/
Protect/Verify export-support issues cannot be implemented against it.
Add patrickcping/pingone-go-sdk-v2/management (the SDK terraform-provider-
pingone itself uses) as a second client on Client, built lazily since it
performs an OAuth exchange at construction time rather than on first
request.
The go:embed directive listed pingone/base and pingone/davinci explicitly,
so every new resource category (sso, platform, mfa, ...) would require
editing this file — violating the "new resource requires zero edits to
existing files" invariant. A single pingone/*/*.yaml wildcard covers any
category subdirectory automatically.
Adds a schema-driven definition and Go handler for pingone_application,
covering OIDC, SAML, External Link, and WS-Fed application types (the
four the pingone_application Terraform resource schema actually supports).
The management SDK's ReadOneApplication200Response is a discriminated
union with 7 possible variants; a custom handler unwraps it via
GetActualInstance() and projects the result into a flat struct with one
nilable field per supported variant, letting the generic object/
nested_attributes engine emit exactly one *_options block per resource.

The 3 built-in PingOne system application types (Admin Console, Portal,
Self Service) have no corresponding schema block in the provider and are
skipped with a warning (c.AddWarning) rather than exported incorrectly.

Also bumps the hardcoded definition-count assertions in
internal/schema/integration_test.go and the sorted resource-type list in
internal/platform/pingone/dispatch_test.go, both of which track the total
number of registered definitions/resources and needed updating for the
new pingone_application entry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Regression Test Results

Matrix Entry Status Breaking Acceptable
default-hcl ✅ PASS 0 5
default-tfjson ✅ PASS 0 5
hcl-include-all ✅ PASS 0 10
hcl-skip-deps ✅ PASS 0 1
tfjson-skip-deps ✅ PASS 0 1

✅ No regressions detected

All export configurations produced compatible output.


Generated by regression workflow • View run

@samir-gandhi

Copy link
Copy Markdown
Contributor Author

Superseded by the pingone-core-resources branch — this PR's commits now live directly on that branch, which is being used as the integration target for the ongoing PingOne resource coverage pilot (tracked in #119) instead of main. Future resource PRs in this pilot target pingone-core-resources directly. Closing without merging to main.

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.

resource/pingone_application: add export support

1 participant