diff --git a/pkg/forklift-api/webhooks/mutating-webhook/mutators/secret-mutator.go b/pkg/forklift-api/webhooks/mutating-webhook/mutators/secret-mutator.go index ac9777f97..ee1bee6d3 100644 --- a/pkg/forklift-api/webhooks/mutating-webhook/mutators/secret-mutator.go +++ b/pkg/forklift-api/webhooks/mutating-webhook/mutators/secret-mutator.go @@ -159,7 +159,7 @@ func (mutator *SecretMutator) patchSecret() *admissionv1.AdmissionResponse { func (mutator *SecretMutator) mutateHostSecret() *admissionv1.AdmissionResponse { if _, ok := mutator.secret.GetLabels()["createdForResource"]; ok { // checking this just because there's no point in mutating an invalid secret var secretChanged bool - if _, ok := mutator.secret.Data["user"]; !ok { + if user, ok := mutator.secret.Data["user"]; !ok || string(user) == "" { provider := &api.Provider{} providerName := string(mutator.secret.Data["provider"]) providerNamespace := mutator.secret.Namespace diff --git a/pkg/forklift-api/webhooks/validating-webhook/admitters/secret-admitter.go b/pkg/forklift-api/webhooks/validating-webhook/admitters/secret-admitter.go index cda32acce..b785a8ce4 100644 --- a/pkg/forklift-api/webhooks/validating-webhook/admitters/secret-admitter.go +++ b/pkg/forklift-api/webhooks/validating-webhook/admitters/secret-admitter.go @@ -126,7 +126,7 @@ func (admitter *SecretAdmitter) validateProviderSecret() *admissionv1.AdmissionR func (admitter *SecretAdmitter) validateHostSecret() *admissionv1.AdmissionResponse { if hostName, ok := admitter.secret.GetLabels()["createdForResource"]; ok { if _, ok := admitter.secret.Data["user"]; !ok { - err := errors.New("Missing credentials on Host secret") + err := errors.New("missing credentials on Host secret") return webhookutils.ToAdmissionResponseError(err) } tested, err := admitter.testConnectionToHost(hostName) @@ -171,6 +171,27 @@ func (admitter *SecretAdmitter) buildProviderCollector(providerType *api.Provide } } +func (admitter *SecretAdmitter) ensureEsxiCredentials(provider *api.Provider) (*core.Secret, error) { + updatedSecret := admitter.secret.DeepCopy() + user, ok := updatedSecret.Data["user"] + + // if the user is not set and the api type is ESXi, we need to copy the credentials from the provider + if provider.Spec.Settings[api.SDK] == api.ESXI && (!ok || string(user) == "") { + ref := provider.Spec.Secret + providerSecret := &core.Secret{} + if err := admitter.Client.Get(context.TODO(), client.ObjectKey{Namespace: ref.Namespace, Name: ref.Name}, providerSecret); err != nil { + log.Error(err, "failed to get provider secret for Host secret without credentials") + return nil, err + } + + // update the deep copy with user and password + updatedSecret.Data["user"] = providerSecret.Data["user"] + updatedSecret.Data["password"] = providerSecret.Data["password"] + } + + return updatedSecret, nil +} + func (admitter *SecretAdmitter) testConnectionToHost(hostName string) (tested bool, err error) { provider := &api.Provider{} providerName := string(admitter.secret.Data["provider"]) @@ -203,8 +224,14 @@ func (admitter *SecretAdmitter) testConnectionToHost(hostName string) (tested bo } admitter.secret.Data["thumbprint"] = []byte(hostModel.Thumbprint) url := fmt.Sprintf("https://%s/sdk", admitter.secret.Data["ip"]) + + updatedSecret, err := admitter.ensureEsxiCredentials(provider) + if err != nil { + return false, err + } + h := adapter.EsxHost{ - Secret: &admitter.secret, + Secret: updatedSecret, URL: url, } log.Info("Testing provider connection")