Skip to content

Commit

Permalink
Add OpenStack credential propagation support
Browse files Browse the repository at this point in the history
Signed-off-by: Bharath Nallapeta <[email protected]>
  • Loading branch information
bnallapeta committed Nov 28, 2024
1 parent e38f582 commit ce9f3fb
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ dev-vsphere-creds: envsubst

dev-eks-creds: dev-aws-creds

.PHONY: dev-openstack-creds
dev-openstack-creds: envsubst
@NAMESPACE=$(NAMESPACE) $(ENVSUBST) -no-unset -i config/dev/openstack-credentials.yaml | $(KUBECTL) apply -f -

.PHONY: dev-apply ## Apply the development environment by deploying the kind cluster, local registry and the HMC helm chart.
dev-apply: kind-deploy registry-deploy dev-push dev-deploy dev-templates dev-release

Expand Down
33 changes: 33 additions & 0 deletions config/dev/openstack-credentials.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
apiVersion: v1
kind: Secret
metadata:
name: openstack-cloud-config
namespace: ${NAMESPACE}
stringData:
clouds.yaml: |
clouds:
openstack:
auth:
auth_url: ${OS_AUTH_URL}
username: ${OS_USERNAME}
password: ${OS_PASSWORD}
project_id: ${OS_PROJECT_ID}
project_name: ${OS_PROJECT_NAME}
user_domain_name: ${OS_USER_DOMAIN_NAME}
region_name: ${OS_REGION_NAME}
interface: ${OS_INTERFACE}
identity_api_version: ${OS_IDENTITY_API_VERSION}
---
apiVersion: hmc.mirantis.com/v1alpha1
kind: Credential
metadata:
name: openstack-cluster-identity-cred
namespace: ${NAMESPACE}
spec:
description: OpenStack credentials
identityRef:
apiVersion: v1
kind: Secret
name: openstack-cloud-config
namespace: ${NAMESPACE}
19 changes: 19 additions & 0 deletions internal/controller/managedcluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,25 @@ func (r *ManagedClusterReconciler) reconcileCredentialPropagation(ctx context.Co
Reason: hmc.SucceededReason,
Message: "vSphere CCM credentials created",
})
case "openstack":
l.Info("OpenStack creds propagation start")
if err := credspropagation.PropagateOpenStackSecrets(ctx, propnCfg); err != nil {
errMsg := fmt.Sprintf("failed to create OpenStack CCM credentials: %s", err)
apimeta.SetStatusCondition(managedCluster.GetConditions(), metav1.Condition{
Type: hmc.CredentialsPropagatedCondition,
Status: metav1.ConditionFalse,
Reason: hmc.FailedReason,
Message: errMsg,
})
return errors.New(errMsg)
}

apimeta.SetStatusCondition(managedCluster.GetConditions(), metav1.Condition{
Type: hmc.CredentialsPropagatedCondition,
Status: metav1.ConditionTrue,
Reason: hmc.SucceededReason,
Message: "OpenStack CCM credentials created",
})
default:
apimeta.SetStatusCondition(managedCluster.GetConditions(), metav1.Condition{
Type: hmc.CredentialsPropagatedCondition,
Expand Down
76 changes: 76 additions & 0 deletions internal/credspropagation/openstack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright 2024
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package credspropagation

import (
"context"
"fmt"

hmc "github.com/Mirantis/hmc/api/v1alpha1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func PropagateOpenStackSecrets(ctx context.Context, cfg *PropagationCfg) error {
openstackManagedCluster := &hmc.ManagedCluster{}
if err := cfg.Client.Get(ctx, client.ObjectKey{
Name: cfg.ManagedCluster.Name,
Namespace: cfg.ManagedCluster.Namespace,
}, openstackManagedCluster); err != nil {
return fmt.Errorf("failed to get ManagedCluster %s: %w", cfg.ManagedCluster.Name, err)
}

openstackCredential := &hmc.Credential{}
if err := cfg.Client.Get(ctx, client.ObjectKey{
Name: openstackManagedCluster.Spec.Credential,
Namespace: openstackManagedCluster.Namespace,
}, openstackCredential); err != nil {
return fmt.Errorf("failed to get OpenStackCredential %s: %w", cfg.ManagedCluster.Spec.Credential, err)
}

// Fetch the secret containing OpenStack credentials
openstackSecret := &corev1.Secret{}
openstackSecretName := openstackCredential.Spec.IdentityRef.Name
openstackSecretNamespace := openstackCredential.Spec.IdentityRef.Namespace
if err := cfg.Client.Get(ctx, client.ObjectKey{
Name: openstackSecretName,
Namespace: openstackSecretNamespace,
}, openstackSecret); err != nil {
return fmt.Errorf("failed to get OpenStack secret %s: %w", openstackSecretName, err)
}

// Generate CCM secret
ccmSecret, err := generateOpenStackCCMSecret(openstackSecret)
if err != nil {
return fmt.Errorf("failed to generate OpenStack CCM secret: %s", err)

Check failure on line 58 in internal/credspropagation/openstack.go

View workflow job for this annotation

GitHub Actions / Build and Unit Test

non-wrapping format verb for fmt.Errorf. Use `%w` to format errors (errorlint)
}

// Apply CCM config
if err := applyCCMConfigs(ctx, cfg.KubeconfSecret, ccmSecret); err != nil {
return fmt.Errorf("failed to apply OpenStack CCM secret: %s", err)

Check failure on line 63 in internal/credspropagation/openstack.go

View workflow job for this annotation

GitHub Actions / Build and Unit Test

non-wrapping format verb for fmt.Errorf. Use `%w` to format errors (errorlint)
}

return nil
}

func generateOpenStackCCMSecret(openstackSecret *corev1.Secret) (*corev1.Secret, error) {

Check failure on line 69 in internal/credspropagation/openstack.go

View workflow job for this annotation

GitHub Actions / Build and Unit Test

generateOpenStackCCMSecret - result 1 (error) is always nil (unparam)
// Use the data from the fetched secret
secretData := map[string][]byte{
"clouds.yaml": openstackSecret.Data["clouds.yaml"],
}

return makeSecret("openstack-cloud-config", metav1.NamespaceSystem, secretData), nil
}
4 changes: 4 additions & 0 deletions internal/webhook/managedcluster_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,10 @@ func isCredMatchTemplate(cred *hmcv1alpha1.Credential, template *hmcv1alpha1.Clu
if idtyKind != "VSphereClusterIdentity" {
return errMsg(provider)
}
case "infrastructure-openstack":
if idtyKind != "Secret" {
return errMsg(provider)
}
default:
if strings.HasPrefix(provider, "infrastructure-") {
return fmt.Errorf("unsupported infrastructure provider %s", provider)
Expand Down

0 comments on commit ce9f3fb

Please sign in to comment.