Sub-issue 1 — clouds.yaml in OpenstackCreds Secret
Title: Accept clouds.yaml in OpenstackCreds Secret (parser, CRD, Conditions, microversion floor, Secret watch)
Parent: #1951
Labels (suggested): enhancement, area/credentials
Problem
OpenstackCredsSpec requires per-field credentials supplied via individual Kubernetes Secret keys (OS_AUTH_URL, OS_USERNAME, OS_PASSWORD, OS_DOMAIN_NAME, OS_REGION_NAME, OS_TENANT_NAME, OS_INTERFACE, OS_IDENTITY_API_VERSION). Operators with existing clouds.yaml files must re-flatten them into this schema, creating drift potential and locking the credential schema to username/password auth only. Microversion configuration that clouds.yaml carries (compute_api_version, volume_api_version, etc.) is not honored by the controller. Validation status is reported in two flat string fields that cannot represent multiple concurrent status concerns.
Proposal
Accept a clouds.yaml key in the credential Secret, parsed via github.com/gophercloud/utils/openstack/clientconfig. Add a cloudName field to OpenstackCredsSpec to select which cloud entry to use. Existing OS_* keys remain functional (legacy path preserved). Wire per-service *_api_version values from clouds.yaml (compute, volume, image, network, identity) as an operator-configurable floor over internal hardcoded microversion values. Replace the flat OpenStackValidationStatus / OpenStackValidationMessage status fields with a Kubernetes-style status.conditions slice. Watch every referenced Secret so credential rotation is observed automatically.
Scope
- CRD changes (
k8s/migration/api/v1alpha1/openstackcreds_types.go):
- Add
CloudName string \json:"cloudName,omitempty"`` to spec.
- Replace
OpenStackValidationStatus / OpenStackValidationMessage with Conditions []metav1.Condition (kubebuilder +listType=map +listMapKey=type).
make generate to refresh zz_generated.deepcopy.go and the CRD YAML.
- Parser (
k8s/migration/pkg/utils/):
- New
clouds_yaml.go wrapping clientconfig.AuthOptions (tmpfile-based for Secret-sourced YAML).
- Refactor
credutils.go ValidateAndGetProviderClient to branch on Secret content (clouds.yaml key present → new path; else → legacy OS_* path unchanged).
- New
conditions.go defining Condition Type / Reason constants per the proposed contract.
- Microversion floor (
v2v-helper/pkg/utils/):
- New
microversion.go exporting MicroversionFloor(configValue, hardcodedValue string) string.
- Wire into every service client constructor in
openstackopsutils.go; per-call hardcoded values (e.g. 2.60 for multi-attach attach) remain as floors over operator config when config is lower.
- Controller (
k8s/migration/internal/controller/openstackcreds_controller.go):
- Add a
Watches(&corev1.Secret{}, ...) mapping Secret events to all OpenstackCreds resources whose SecretRef points to that Secret.
- Populate
status.conditions per reconcile pass.
- On first reconcile observing legacy flat status populated, clear those fields after writing equivalent Conditions.
- Schedule a periodic 1-hour requeue for time-sensitive Conditions.
Out of scope (covered in follow-up sub-issues)
Acceptance criteria
Open questions for maintainers
- Microversion floor semantics: confirm preference for floor-over-hardcoded (operator value wins only when higher), versus alternative options (hardcoded-wins or config-wins).
CloudName default behavior: confirm "use the only entry if single; error if multi-entry and unset" instead of e.g., defaulting to "default".
- Tmpfile vs vendored YAML parser for
clouds.yaml content sourced from Secret: tmpfile uses the upstream library directly; vendoring avoids filesystem I/O in the controller pod. Tmpfile preferred unless the project disallows on-disk credential material even transiently.
- One-time
MigratedFromFlatStatus=True Condition tracking the flat→Conditions transition: include or omit.
Branch name
1952-clouds-yaml-credentials (matches repo convention).
Design references (private to contributor)
Detailed design lives in the contributor's private spec/plan workspace and will be linked alongside the PR opened against this issue.
Sub-issue 1 — clouds.yaml in OpenstackCreds Secret
Title: Accept clouds.yaml in OpenstackCreds Secret (parser, CRD, Conditions, microversion floor, Secret watch)
Parent: #1951
Labels (suggested):
enhancement,area/credentialsProblem
OpenstackCredsSpecrequires per-field credentials supplied via individual Kubernetes Secret keys (OS_AUTH_URL,OS_USERNAME,OS_PASSWORD,OS_DOMAIN_NAME,OS_REGION_NAME,OS_TENANT_NAME,OS_INTERFACE,OS_IDENTITY_API_VERSION). Operators with existingclouds.yamlfiles must re-flatten them into this schema, creating drift potential and locking the credential schema to username/password auth only. Microversion configuration thatclouds.yamlcarries (compute_api_version,volume_api_version, etc.) is not honored by the controller. Validation status is reported in two flat string fields that cannot represent multiple concurrent status concerns.Proposal
Accept a
clouds.yamlkey in the credential Secret, parsed viagithub.com/gophercloud/utils/openstack/clientconfig. Add acloudNamefield toOpenstackCredsSpecto select which cloud entry to use. Existing OS_* keys remain functional (legacy path preserved). Wire per-service*_api_versionvalues fromclouds.yaml(compute, volume, image, network, identity) as an operator-configurable floor over internal hardcoded microversion values. Replace the flatOpenStackValidationStatus/OpenStackValidationMessagestatus fields with a Kubernetes-stylestatus.conditionsslice. Watch every referenced Secret so credential rotation is observed automatically.Scope
k8s/migration/api/v1alpha1/openstackcreds_types.go):CloudName string \json:"cloudName,omitempty"`` to spec.OpenStackValidationStatus/OpenStackValidationMessagewithConditions []metav1.Condition(kubebuilder+listType=map +listMapKey=type).make generateto refreshzz_generated.deepcopy.goand the CRD YAML.k8s/migration/pkg/utils/):clouds_yaml.gowrappingclientconfig.AuthOptions(tmpfile-based for Secret-sourced YAML).credutils.goValidateAndGetProviderClientto branch on Secret content (clouds.yamlkey present → new path; else → legacy OS_* path unchanged).conditions.godefining Condition Type / Reason constants per the proposed contract.v2v-helper/pkg/utils/):microversion.goexportingMicroversionFloor(configValue, hardcodedValue string) string.openstackopsutils.go; per-call hardcoded values (e.g.2.60for multi-attach attach) remain as floors over operator config when config is lower.k8s/migration/internal/controller/openstackcreds_controller.go):Watches(&corev1.Secret{}, ...)mapping Secret events to allOpenstackCredsresources whoseSecretRefpoints to that Secret.status.conditionsper reconcile pass.Out of scope (covered in follow-up sub-issues)
auth_type: v3applicationcredential) — sub-issue Support v3applicationcredential auth_type in clouds.yaml #1953.clouds.yaml— sub-issue UI: clouds.yaml credential input form #1954.Acceptance criteria
OpenstackCredsSpec.CloudNamefield present with godoc documenting the multi-entry selection semantics.OpenstackCredsStatus.Conditionsslice present; legacy flat status fields retired.make generate; not hand-edited.clouds.yamlprecedence over OS_* when both present.clouds.yamlworks withoutcloudNameset; multi-entry withoutcloudNamereturnsCredentialsParsed=False, Reason=AmbiguousCloudNamelisting entries.clouds.yamlapplies as a floor (operator value wins when higher; hardcoded value wins when configured value is lower or absent). Compute / volume / image / network / identity services all honored.OpenstackCredsresources referencing the sameclouds.yaml-backed Secret with differentcloudNamevalues reconcile independently; legacy OS_*-backed Secrets retain implicit 1:1 binding.RequeueAfterscheduled for time-sensitive Conditions (relevant for Support v3applicationcredential auth_type in clouds.yaml #1953 but plumbing lands here).README.mdcredentials section, newdocs/credentials.mdoperator guide).Open questions for maintainers
CloudNamedefault behavior: confirm "use the only entry if single; error if multi-entry and unset" instead of e.g., defaulting to"default".clouds.yamlcontent sourced from Secret: tmpfile uses the upstream library directly; vendoring avoids filesystem I/O in the controller pod. Tmpfile preferred unless the project disallows on-disk credential material even transiently.MigratedFromFlatStatus=TrueCondition tracking the flat→Conditions transition: include or omit.Branch name
1952-clouds-yaml-credentials(matches repo convention).Design references (private to contributor)
Detailed design lives in the contributor's private spec/plan workspace and will be linked alongside the PR opened against this issue.