Skip to content

Commit 6b4be09

Browse files
gtherondclaude
andcommitted
[1952] fix: round 2 of Devin review findings on platform9#1955
Two new findings from Devin's re-run on the previous fix commit: 1. Post-validation enrichment failed for clouds.yaml-backed Secrets. GetOpenStackClients (used by fetchAndUpdateFlavors / updateOpenstackInfo) and GetOpenstackCredentialsFromSecret (used by syncProjectName) only read OS_* keys. For clouds.yaml-backed Secrets those keys are missing, so after successful validation the post-validation enrichment loop spun forever logging "OS_AUTH_URL is missing". New helper GetOpenstackCredsInfoFromCreds(ctx, k3sclient, *OpenstackCreds) branches on SecretContainsCloudsYAML: for clouds.yaml, parses with Spec.CloudName and returns an OpenStackCredsInfo populated from the parsed CloudConfig (auth_type=v3applicationcredential leaves Username/Password/TenantName empty since App Creds carry scope at creation time). For legacy OS_*-keyed Secrets, delegates to the existing GetOpenstackCredentialsFromSecret path unchanged. Four call sites switched to the new helper: - GetOpenStackClients (credutils.go:320, region for endpoint) - GetOpenstackInfo's security-group lookup (credutils.go:277, TenantName for filter) - syncProjectName (openstackcreds_controller.go:673, TenantName -> Spec.ProjectName) - Cinder backend pool discovery (credutils.go:2212, region) The ValidateAndGetProviderClient legacy branch (credutils.go:374) is unchanged — it only runs when SecretContainsCloudsYAML is false. 2. checkStatusSuccess broke during upgrade window. Previous patch changed migrationplan_controller.go:1869 to read only Conditions; pre-upgrade OpenstackCreds resources have the flat OpenStackValidationStatus = Succeeded but an empty Conditions slice until the OpenstackCreds controller re-reconciles. During that small window MigrationPlan reconciliation blocked for those credentials. Added a legacy fallback: ready if either CredentialsValidated=True (new) OR OpenStackValidationStatus == PodSucceeded (legacy). Both paths produce the same operational signal; the OR is a transient bridge across the upgrade window. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 185c05e commit 6b4be09

6 files changed

Lines changed: 65 additions & 8 deletions

graphify-out/cache/ast/99b618dd91866e242d11720ad340b249d1f8e6b12c86330e819af288addb2ae7.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

graphify-out/cache/ast/b717f121844d1836654cdc16d645ba1bf2475573abca1400911877840148ff44.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

graphify-out/cache/ast/dca3fbfa816b37c135741217ddf8128ceac0f9284f831f53b7841f5ad7d3a353.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

k8s/migration/internal/controller/migrationplan_controller.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,9 +1864,15 @@ func (r *MigrationPlanReconciler) checkStatusSuccess(ctx context.Context,
18641864
if !ok {
18651865
return false, errors.Wrap(err, "failed to convert credentials to OpenstackCreds")
18661866
}
1867-
// Check the standard Kubernetes Condition rather than the retired flat
1868-
// status fields. A resource is ready when CredentialsValidated=True.
1869-
if !meta.IsStatusConditionTrue(openstackCreds.Status.Conditions, utils.ConditionCredentialsValidated) {
1867+
// Prefer the Kubernetes Condition (CredentialsValidated=True). Fall
1868+
// back to the legacy flat OpenStackValidationStatus field for
1869+
// resources that haven't been re-reconciled by the upgraded
1870+
// OpenstackCreds controller yet — those resources still carry the
1871+
// old flat status but no Conditions slice, and we shouldn't block
1872+
// MigrationPlan reconciliation on the upgrade window.
1873+
conditionReady := meta.IsStatusConditionTrue(openstackCreds.Status.Conditions, utils.ConditionCredentialsValidated)
1874+
legacyReady := openstackCreds.Status.OpenStackValidationStatus == string(corev1.PodSucceeded)
1875+
if !conditionReady && !legacyReady {
18701876
return false, errors.Errorf("openstackcreds '%s' CR is not validated", openstackCreds.Name)
18711877
}
18721878
}

k8s/migration/internal/controller/openstackcreds_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ func fetchAndUpdateFlavors(ctx context.Context, r *OpenstackCredsReconciler, sco
670670

671671
func syncProjectName(ctx context.Context, r *OpenstackCredsReconciler, scope *scope.OpenstackCredsScope) error {
672672
ctxlog := scope.Logger
673-
openstackCredential, err := utils.GetOpenstackCredentialsFromSecret(ctx, r.Client, scope.OpenstackCreds.Spec.SecretRef.Name)
673+
openstackCredential, err := utils.GetOpenstackCredsInfoFromCreds(ctx, r.Client, scope.OpenstackCreds)
674674
if err != nil {
675675
ctxlog.Error(err, "Failed to get OpenStack credentials from secret", "secretName", scope.OpenstackCreds.Spec.SecretRef.Name)
676676
return errors.Wrap(err, "failed to get Openstack credentials from secret")

k8s/migration/pkg/utils/credutils.go

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,59 @@ func GetVMwareCredentialsFromSecret(ctx context.Context, k3sclient client.Client
112112
return vmwarecommon.GetVMwareCredentialsFromSecret(ctx, k3sclient, secretName)
113113
}
114114

115-
// GetOpenstackCredentialsFromSecret retrieves and checks the secret
115+
// GetOpenstackCredentialsFromSecret retrieves and checks the secret. Handles
116+
// only the legacy OS_*-keyed Secret format. Callers that may encounter a
117+
// clouds.yaml-backed Secret must use GetOpenstackCredsInfoFromCreds (which
118+
// branches on Secret content and uses the OpenstackCreds.Spec.CloudName for
119+
// multi-entry clouds.yaml selection).
116120
func GetOpenstackCredentialsFromSecret(ctx context.Context, k3sclient client.Client, secretName string) (vjailbreakv1alpha1.OpenStackCredsInfo, error) {
117121
return openstackcommon.GetOpenstackCredentialsFromSecret(ctx, k3sclient, secretName)
118122
}
119123

124+
// GetOpenstackCredsInfoFromCreds returns an OpenStackCredsInfo for the given
125+
// OpenstackCreds resource, supporting both clouds.yaml-keyed Secrets (the new
126+
// path that consults Spec.CloudName for multi-entry selection) and legacy
127+
// OS_*-keyed Secrets (the existing path).
128+
//
129+
// Post-validation enrichment functions (flavor discovery, network/volume-type
130+
// listing, security group listing, project name sync, Cinder backend pool
131+
// discovery) must use this helper rather than GetOpenstackCredentialsFromSecret
132+
// directly so they work for clouds.yaml-backed credentials. For
133+
// auth_type=v3applicationcredential, the returned info has empty
134+
// Username/Password/TenantName since Application Credentials carry scope at
135+
// creation time; consumers that require those fields must check explicitly.
136+
func GetOpenstackCredsInfoFromCreds(ctx context.Context, k3sclient client.Client, openstackcreds *vjailbreakv1alpha1.OpenstackCreds) (vjailbreakv1alpha1.OpenStackCredsInfo, error) {
137+
if openstackcreds == nil {
138+
return vjailbreakv1alpha1.OpenStackCredsInfo{}, errors.New("openstackcreds cannot be nil")
139+
}
140+
secret := &corev1.Secret{}
141+
if err := k3sclient.Get(ctx, k8stypes.NamespacedName{
142+
Namespace: constants.NamespaceMigrationSystem,
143+
Name: openstackcreds.Spec.SecretRef.Name,
144+
}, secret); err != nil {
145+
return vjailbreakv1alpha1.OpenStackCredsInfo{}, errors.Wrapf(err, "failed to get secret %q", openstackcreds.Spec.SecretRef.Name)
146+
}
147+
if SecretContainsCloudsYAML(secret.Data) {
148+
cfg, err := ParseCloudsYAML(secret.Data["clouds.yaml"], openstackcreds.Spec.CloudName)
149+
if err != nil {
150+
return vjailbreakv1alpha1.OpenStackCredsInfo{}, errors.Wrap(err, "failed to parse clouds.yaml")
151+
}
152+
info := vjailbreakv1alpha1.OpenStackCredsInfo{
153+
AuthURL: cfg.AuthOptions.IdentityEndpoint,
154+
Username: cfg.AuthOptions.Username,
155+
Password: cfg.AuthOptions.Password,
156+
RegionName: cfg.RegionName,
157+
TenantName: cfg.AuthOptions.TenantName,
158+
DomainName: cfg.AuthOptions.DomainName,
159+
}
160+
if cfg.Verify != nil && !*cfg.Verify {
161+
info.Insecure = true
162+
}
163+
return info, nil
164+
}
165+
return openstackcommon.GetOpenstackCredentialsFromSecret(ctx, k3sclient, openstackcreds.Spec.SecretRef.Name)
166+
}
167+
120168
// VerifyNetworks verifies the existence of specified networks in OpenStack
121169
func VerifyNetworks(ctx context.Context, k3sclient client.Client, openstackcreds *vjailbreakv1alpha1.OpenstackCreds, targetnetworks []string) error {
122170
openstackClients, err := GetOpenStackClients(ctx, k3sclient, openstackcreds)
@@ -274,7 +322,7 @@ func GetOpenstackInfo(ctx context.Context, k3sclient client.Client, openstackcre
274322
})
275323
}
276324

277-
credsInfo, err := GetOpenstackCredentialsFromSecret(ctx, k3sclient, openstackcreds.Spec.SecretRef.Name)
325+
credsInfo, err := GetOpenstackCredsInfoFromCreds(ctx, k3sclient, openstackcreds)
278326
if err != nil {
279327
return nil, errors.Wrap(err, "failed to get openstack credentials for project lookup")
280328
}
@@ -317,7 +365,7 @@ func GetOpenStackClients(ctx context.Context, k3sclient client.Client, openstack
317365
return nil, errors.New("openstackcreds cannot be nil")
318366
}
319367

320-
openstackCredential, err := GetOpenstackCredentialsFromSecret(ctx, k3sclient, openstackcreds.Spec.SecretRef.Name)
368+
openstackCredential, err := GetOpenstackCredsInfoFromCreds(ctx, k3sclient, openstackcreds)
321369
if err != nil {
322370
return nil, errors.Wrap(err, "failed to get openstack credentials from secret")
323371
}
@@ -2209,7 +2257,7 @@ func GetBackendPools(ctx context.Context, k3sclient client.Client, openstackcred
22092257
ctxlog.Info("Discovering backend pools from OpenStack Cinder")
22102258

22112259
// Get OpenStack credentials to extract region
2212-
openstackCredential, err := GetOpenstackCredentialsFromSecret(ctx, k3sclient, openstackcreds.Spec.SecretRef.Name)
2260+
openstackCredential, err := GetOpenstackCredsInfoFromCreds(ctx, k3sclient, openstackcreds)
22132261
if err != nil {
22142262
return nil, errors.Wrap(err, "failed to get OpenStack credentials from secret")
22152263
}

0 commit comments

Comments
 (0)