Skip to content

Commit

Permalink
Fix a golangci-lint issue: unparam namespace
Browse files Browse the repository at this point in the history
Signed-off-by: Bharath Nallapeta <bnallapeta@mirantis.com>
  • Loading branch information
bnallapeta committed Dec 27, 2024
1 parent 5ff6b17 commit 78698de
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 49 deletions.
2 changes: 2 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth"
capz "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
capo "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
capv "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
Expand Down Expand Up @@ -57,6 +58,7 @@ func init() {
utilruntime.Must(sveltosv1beta1.AddToScheme(scheme))
utilruntime.Must(capz.AddToScheme(scheme))
utilruntime.Must(capv.AddToScheme(scheme))
utilruntime.Must(capo.AddToScheme(scheme))
// +kubebuilder:scaffold:scheme
}

Expand Down
8 changes: 3 additions & 5 deletions config/dev/openstack-credentials.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ stringData:
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}
application_credential_id: ${OS_APPLICATION_CREDENTIAL_ID}
application_credential_secret: ${OS_APPLICATION_CREDENTIAL_SECRET}
region_name: ${OS_REGION_NAME}
interface: ${OS_INTERFACE}
identity_api_version: ${OS_IDENTITY_API_VERSION}
auth_type: ${OS_AUTH_TYPE}
---
apiVersion: hmc.mirantis.com/v1alpha1
kind: Credential
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ require (
sigs.k8s.io/cluster-api v1.9.3
sigs.k8s.io/cluster-api-operator v0.14.0
sigs.k8s.io/cluster-api-provider-azure v1.17.2
sigs.k8s.io/cluster-api-provider-openstack v0.11.3
sigs.k8s.io/cluster-api-provider-vsphere v1.12.0
sigs.k8s.io/controller-runtime v0.19.3
sigs.k8s.io/yaml v1.4.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,8 @@ sigs.k8s.io/cluster-api-operator v0.14.0 h1:0QgO6+XGrNNJnNHKBwvQD5v6w+EaH3Z0RL1n
sigs.k8s.io/cluster-api-operator v0.14.0/go.mod h1:euShpVN6HyxXas28HkrYxhCPVDW1UV6ljbRBAeCxp8Y=
sigs.k8s.io/cluster-api-provider-azure v1.17.2 h1:uS9ggE/bryI0hiOWHBa56nYHkWmsPZW3bzYeAddL4vM=
sigs.k8s.io/cluster-api-provider-azure v1.17.2/go.mod h1:ohdf0TYutOn5vKsXpNVeZUVfUSNIwNhfF6wDjbiqPI0=
sigs.k8s.io/cluster-api-provider-openstack v0.11.3 h1:ZJ3G+m11bgaD227EuFjuFsFC95MRzJm9JbDIte0xwII=
sigs.k8s.io/cluster-api-provider-openstack v0.11.3/go.mod h1:0rH6yksLcuwWK/SoSoCOJi4A0kOSL3qrA+qvDVZ9NjU=
sigs.k8s.io/cluster-api-provider-vsphere v1.12.0 h1:9ze+1JSdLAGiLklsnORvj/vs2XpR9jyVmkT0Dwo1nuc=
sigs.k8s.io/cluster-api-provider-vsphere v1.12.0/go.mod h1:2y9fsZQ3qjT1kL6IXiOUVcyV0n8DLBQGvyPnId9xRzk=
sigs.k8s.io/controller-runtime v0.19.3 h1:XO2GvC9OPftRst6xWCpTgBZO04S2cbp0Qqkj8bX1sPw=
Expand Down
7 changes: 4 additions & 3 deletions internal/controller/clusterdeployment_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ func (r *ClusterDeploymentReconciler) updateCluster(ctx context.Context, mc *hmc
}

if mc.Spec.PropagateCredentials {
if err := r.reconcileCredentialPropagation(ctx, mc); err != nil {
if err := r.reconcileCredentialPropagation(ctx, mc, cred); err != nil {
l.Error(err, "failed to reconcile credentials propagation")
return ctrl.Result{}, err
}
Expand Down Expand Up @@ -696,7 +696,7 @@ func (r *ClusterDeploymentReconciler) objectsAvailable(ctx context.Context, name
return len(itemsList.Items) != 0, nil
}

func (r *ClusterDeploymentReconciler) reconcileCredentialPropagation(ctx context.Context, clusterDeployment *hmc.ClusterDeployment) error {
func (r *ClusterDeploymentReconciler) reconcileCredentialPropagation(ctx context.Context, clusterDeployment *hmc.ClusterDeployment, credential *hmc.Credential) error {
l := ctrl.LoggerFrom(ctx)
l.Info("Reconciling CCM credentials propagation")

Expand All @@ -715,8 +715,9 @@ func (r *ClusterDeploymentReconciler) reconcileCredentialPropagation(ctx context

propnCfg := &credspropagation.PropagationCfg{
Client: r.Client,
ClusterDeployment: clusterDeployment,
IdentityRef: credential.Spec.IdentityRef,
KubeconfSecret: kubeconfSecret,
ClusterDeployment: clusterDeployment,
SystemNamespace: r.SystemNamespace,
}

Expand Down
3 changes: 1 addition & 2 deletions internal/credspropagation/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"fmt"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
capz "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
Expand Down Expand Up @@ -94,7 +93,7 @@ func generateAzureCCMSecret(azureCluster *capz.AzureCluster, azureClIdty *capz.A
"cloud-config": azureJSON,
}

return makeSecret("azure-cloud-provider", metav1.NamespaceSystem, secretData), nil
return makeSecret("azure-cloud-provider", secretData), nil
}

func getAzureSubnetData(azureCluster *capz.AzureCluster) (subnetName, secGroup, routeTable string) {
Expand Down
17 changes: 11 additions & 6 deletions internal/credspropagation/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ import (

type PropagationCfg struct {
Client client.Client
ClusterDeployment *hmc.ClusterDeployment
KubeconfSecret *corev1.Secret
IdentityRef *corev1.ObjectReference
ClusterDeployment *hmc.ClusterDeployment
SystemNamespace string
}

Expand All @@ -53,23 +54,23 @@ func applyCCMConfigs(ctx context.Context, kubeconfSecret *corev1.Secret, objects
return nil
}

func makeSecret(name, namespace string, data map[string][]byte) *corev1.Secret {
func makeSecret(name string, data map[string][]byte) *corev1.Secret {
s := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Namespace: metav1.NamespaceSystem,
},
Data: data,
}
s.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Secret"))
return s
}

func makeConfigMap(name, namespace string, data map[string]string) *corev1.ConfigMap {
func makeConfigMap(name string, data map[string]string) *corev1.ConfigMap {
c := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Namespace: metav1.NamespaceSystem,
},
Data: data,
}
Expand All @@ -86,7 +87,11 @@ func makeClientFromSecret(kubeconfSecret *corev1.Secret) (client.Client, error)
if err != nil {
return nil, err
}
return client.New(restConfig, client.Options{
cl, err := client.New(restConfig, client.Options{
Scheme: scheme,
})
if err != nil {
return nil, err
}
return cl, nil
}
205 changes: 175 additions & 30 deletions internal/credspropagation/openstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,62 +15,207 @@
package credspropagation

import (
"bytes"
"context"
"errors"
"fmt"
texttemplate "text/template"

hmc "github.com/Mirantis/hmc/api/v1alpha1"
"gopkg.in/yaml.v3"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
capo "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

type (
cloudConfFields struct {
AuthURL string
ApplicationCredentialID string
ApplicationCredentialName string
ApplicationCredentialSecret string
Username string
Password string
RegionName string
FloatingNetworkID string
PublicNetworkName string
}

cloudsYaml struct {
Clouds map[string]cloud `yaml:"clouds"`
}

cloud struct {
Auth auth `yaml:"auth"`
RegionName string `yaml:"region_name"`
}

auth struct {
AuthURL string `yaml:"auth_url"`
ApplicationCredentialID string `yaml:"application_credential_id"`
ApplicationCredentialName string `yaml:"application_credential_name"`
ApplicationCredentialSecret string `yaml:"application_credential_secret"`
Username string `yaml:"username"`
Password string `yaml:"password"`
ProjectDomainName string `yaml:"project_domain_name"`
}
)

// PropagateOpenStackSecrets propagates OpenStack secrets
func PropagateOpenStackSecrets(ctx context.Context, cfg *PropagationCfg) error {
openstackManagedCluster := &hmc.ManagedCluster{}
if cfg == nil {
return errors.New("PropagationCfg is nil")
}
// Fetch the OpenStackCluster resource
openstackCluster := &capo.OpenStackCluster{}
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)
Name: cfg.ClusterDeployment.Name,
Namespace: cfg.ClusterDeployment.Namespace,
}, openstackCluster); err != nil {
return fmt.Errorf("unable to get OpenStackCluster %s/%s: %w",
cfg.ClusterDeployment.Namespace, cfg.ClusterDeployment.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 OpenStack secret
openstackSecret, err := fetchOpenStackSecret(ctx, cfg)
if err != nil {
return fmt.Errorf("failed to fetch OpenStack secret: %w", err)
}

// Fetch the secret containing OpenStack credentials
// Generate the CCM secret using the extracted cloudName
ccmSecret, err := generateOpenStackCCMSecret(openstackCluster, openstackSecret)
if err != nil {
return fmt.Errorf("failed to generate CCM secret: %w", err)
}

// Apply the CCM configuration
if err := applyCCMConfigs(ctx, cfg.KubeconfSecret, ccmSecret); err != nil {
return fmt.Errorf("failed to apply CCM configuration: %w", err)
}

return nil
}

// Fetch the OpenStack secret
func fetchOpenStackSecret(ctx context.Context, cfg *PropagationCfg) (*corev1.Secret, error) {
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,
Name: cfg.IdentityRef.Name,
Namespace: cfg.IdentityRef.Namespace,
}, openstackSecret); err != nil {
return fmt.Errorf("failed to get OpenStack secret %s: %w", openstackSecretName, err)
return nil, fmt.Errorf("failed to get OpenStack secret %s/%s: %w",
cfg.IdentityRef.Namespace, cfg.IdentityRef.Name, err)
}
return openstackSecret, nil
}

// Generate the CCM secret from the OpenStack secret
func generateOpenStackCCMSecret(openstackCluster *capo.OpenStackCluster, openstackSecret *corev1.Secret) (*corev1.Secret, error) {
const cloudConfTemplate = `
[Global]
auth-url="{{ .AuthURL }}"
{{- if .ApplicationCredentialID }}
application-credential-id="{{ .ApplicationCredentialID }}"
{{- end }}
{{- if .ApplicationCredentialName }}
application-credential-name="{{ .ApplicationCredentialName }}"
{{- end }}
{{- if .ApplicationCredentialSecret }}
application-credential-secret="{{ .ApplicationCredentialSecret }}"
{{- end }}
{{- if and (not .ApplicationCredentialID) (not .ApplicationCredentialSecret) }}
username="{{ .Username }}"
password="{{ .Password }}"
{{- end }}
region="{{ .RegionName }}"
[LoadBalancer]
{{- if .FloatingNetworkID }}
floating-network-id="{{ .FloatingNetworkID }}"
{{- end }}
// Generate CCM secret
ccmSecret, err := generateOpenStackCCMSecret(openstackSecret)
[Network]
{{- if .PublicNetworkName }}
public-network-name="{{ .PublicNetworkName }}"
{{- end }}
`

// Parse the clouds.yaml content
cloudsYamlData, ok := openstackSecret.Data["clouds.yaml"]
if !ok {
return nil, errors.New("missing clouds.yaml in OpenStack secret")
}

parsedCloudsYaml, err := parseCloudsYaml(cloudsYamlData)
if err != nil {
return fmt.Errorf("failed to generate OpenStack CCM secret: %s", err)
return nil, fmt.Errorf("failed to parse clouds.yaml: %w", err)
}

// Apply CCM config
if err := applyCCMConfigs(ctx, cfg.KubeconfSecret, ccmSecret); err != nil {
return fmt.Errorf("failed to apply OpenStack CCM secret: %s", err)
// Extract cloudConfFields using the provided cloudName
fields, err := extractCloudConfFields(parsedCloudsYaml, openstackCluster.Spec.IdentityRef.CloudName)
if err != nil {
return nil, fmt.Errorf("failed to extract cloud.conf fields: %w", err)
}

return nil
// Fetch external network details from OpenStackCluster
// externalNetwork, err := fetchExternalNetwork(ctx, cfg)
externalNetwork := openstackCluster.Status.ExternalNetwork
if externalNetwork == nil || externalNetwork.ID == "" || externalNetwork.Name == "" {
return nil, errors.New("external network details are incomplete")
}
fields.FloatingNetworkID = externalNetwork.ID
fields.PublicNetworkName = externalNetwork.Name

// Render the cloud.conf secret
return renderCloudConf(cloudConfTemplate, fields)
}

// Parse the clouds.yaml content into structured types
func parseCloudsYaml(data []byte) (*cloudsYaml, error) {
var parsed cloudsYaml
if err := yaml.Unmarshal(data, &parsed); err != nil {
return nil, fmt.Errorf("failed to parse clouds.yaml: %w", err)
}
return &parsed, nil
}

func generateOpenStackCCMSecret(openstackSecret *corev1.Secret) (*corev1.Secret, error) {
// Use the data from the fetched secret
// Extract fields required for the cloud.conf file
func extractCloudConfFields(cy *cloudsYaml, cloudName string) (cloudConfFields, error) {
var fields cloudConfFields

cloud, exists := cy.Clouds[cloudName]
if !exists {
return fields, fmt.Errorf("cloud '%s' not found in clouds.yaml", cloudName)
}

auth := cloud.Auth
fields = cloudConfFields{
AuthURL: auth.AuthURL,
ApplicationCredentialID: auth.ApplicationCredentialID,
ApplicationCredentialName: auth.ApplicationCredentialName,
ApplicationCredentialSecret: auth.ApplicationCredentialSecret,
Username: auth.Username,
Password: auth.Password,
RegionName: cloud.RegionName,
}

return fields, nil
}

// Render cloud.conf using the template and fields
func renderCloudConf(templateStr string, fields cloudConfFields) (*corev1.Secret, error) {
tmpl, err := texttemplate.New("cloudConf").Parse(templateStr)
if err != nil {
return nil, fmt.Errorf("failed to parse cloud.conf template: %w", err)
}

var buf bytes.Buffer
if err := tmpl.Execute(&buf, fields); err != nil {
return nil, fmt.Errorf("failed to render cloud.conf template: %w", err)
}

secretData := map[string][]byte{
"clouds.yaml": openstackSecret.Data["clouds.yaml"],
"cloud.conf": buf.Bytes(),
}

return makeSecret("openstack-cloud-config", metav1.NamespaceSystem, secretData), nil
return makeSecret("openstack-cloud-config", secretData), nil
}
Loading

0 comments on commit 78698de

Please sign in to comment.