github.com/openshift/installer@v1.4.17/pkg/asset/manifests/openstack/cluster.go (about) 1 package openstack 2 3 import ( 4 "fmt" 5 "os" 6 7 "github.com/gophercloud/utils/v2/openstack/clientconfig" 8 corev1 "k8s.io/api/core/v1" 9 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 "k8s.io/utils/ptr" 11 capo "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" 12 "sigs.k8s.io/cluster-api-provider-openstack/pkg/utils/optional" 13 capi "sigs.k8s.io/cluster-api/api/v1beta1" 14 "sigs.k8s.io/yaml" 15 16 "github.com/openshift/installer/pkg/asset" 17 "github.com/openshift/installer/pkg/asset/installconfig" 18 "github.com/openshift/installer/pkg/asset/manifests/capiutils" 19 ) 20 21 const ( 22 cloudName = "openstack" 23 ) 24 25 // GenerateClusterAssets generates the cluster manifests for the cluster-api. 26 func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID *installconfig.ClusterID) (*capiutils.GenerateClusterAssetsOutput, error) { 27 manifests := []*asset.RuntimeFile{} 28 openstackInstallConfig := installConfig.Config.OpenStack 29 30 var ( 31 externalNetwork *capo.NetworkParam 32 disableExternalNetwork optional.Bool 33 ) 34 if e := openstackInstallConfig.ExternalNetwork; e != "" { 35 externalNetwork = &capo.NetworkParam{Filter: &capo.NetworkFilter{Name: e}} 36 } else { 37 disableExternalNetwork = ptr.To(true) 38 } 39 40 openStackCluster := &capo.OpenStackCluster{ 41 ObjectMeta: metav1.ObjectMeta{ 42 Name: clusterID.InfraID, 43 Namespace: capiutils.Namespace, 44 Labels: map[string]string{ 45 capi.ClusterNameLabel: clusterID.InfraID, 46 }, 47 }, 48 Spec: capo.OpenStackClusterSpec{ 49 IdentityRef: capo.OpenStackIdentityReference{ 50 Name: clusterID.InfraID + "-cloud-config", 51 CloudName: cloudName, 52 }, 53 // We disable management of most networking resources since either 54 // we (the installer) will create them, or the user will have 55 // pre-created them as part of a "Bring Your Own Network (BYON)" 56 // configuration 57 ManagedSecurityGroups: nil, 58 DisableAPIServerFloatingIP: ptr.To(true), 59 // TODO(stephenfin): update when we support dual-stack (there are 60 // potentially *two* IPs here) 61 APIServerFixedIP: &openstackInstallConfig.APIVIPs[0], 62 ExternalNetwork: externalNetwork, 63 DisableExternalNetwork: disableExternalNetwork, 64 Tags: []string{ 65 fmt.Sprintf("openshiftClusterID=%s", clusterID.InfraID), 66 }, 67 }, 68 } 69 if cpPort := openstackInstallConfig.ControlPlanePort; cpPort != nil { 70 if networkID := cpPort.Network.ID; networkID != "" { 71 openStackCluster.Spec.Network = &capo.NetworkParam{ID: &networkID} 72 } else if networkName := cpPort.Network.Name; networkName != "" { 73 openStackCluster.Spec.Network = &capo.NetworkParam{Filter: &capo.NetworkFilter{Name: networkName}} 74 } 75 openStackCluster.Spec.Subnets = make([]capo.SubnetParam, len(cpPort.FixedIPs)) 76 for i := range cpPort.FixedIPs { 77 if subnetID := cpPort.FixedIPs[i].Subnet.ID; subnetID != "" { 78 openStackCluster.Spec.Subnets[i] = capo.SubnetParam{ID: &subnetID} 79 } else { 80 openStackCluster.Spec.Subnets[i] = capo.SubnetParam{Filter: &capo.SubnetFilter{Name: cpPort.FixedIPs[i].Subnet.Name}} 81 } 82 } 83 } else { 84 openStackCluster.Spec.ManagedSubnets = []capo.SubnetSpec{ 85 { 86 CIDR: capiutils.CIDRFromInstallConfig(installConfig).String(), 87 DNSNameservers: openstackInstallConfig.ExternalDNS, 88 }, 89 } 90 } 91 openStackCluster.SetGroupVersionKind(capo.GroupVersion.WithKind("OpenStackCluster")) 92 93 manifests = append(manifests, &asset.RuntimeFile{ 94 Object: openStackCluster, 95 File: asset.File{Filename: "02_infra-cluster.yaml"}, 96 }) 97 98 cloudConfig, err := generateCloudConfig(installConfig) 99 if err != nil { 100 return nil, err 101 } 102 103 openStackIdentity := &corev1.Secret{ 104 ObjectMeta: metav1.ObjectMeta{ 105 Name: clusterID.InfraID + "-cloud-config", 106 Namespace: capiutils.Namespace, 107 }, 108 Data: cloudConfig, 109 } 110 openStackIdentity.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Secret")) 111 112 manifests = append(manifests, &asset.RuntimeFile{ 113 Object: openStackIdentity, 114 File: asset.File{Filename: "02_openstack-cloud-config.yaml"}, 115 }) 116 117 return &capiutils.GenerateClusterAssetsOutput{ 118 Manifests: manifests, 119 InfrastructureRefs: []*corev1.ObjectReference{ 120 { 121 APIVersion: capo.GroupVersion.String(), 122 Kind: "OpenStackCluster", 123 Name: openStackCluster.Name, 124 Namespace: openStackCluster.Namespace, 125 }, 126 }, 127 }, nil 128 } 129 130 func generateCloudConfig(installConfig *installconfig.InstallConfig) (map[string][]byte, error) { 131 opts := new(clientconfig.ClientOpts) 132 opts.Cloud = installConfig.Config.Platform.OpenStack.Cloud 133 134 cloud, err := clientconfig.GetCloudFromYAML(opts) 135 if err != nil { 136 return nil, err 137 } 138 139 // We need to replace the local cacert path with the one used by CAPO 140 caCert := []byte{} 141 if cloud.CACertFile != "" { 142 caCert, err = os.ReadFile(cloud.CACertFile) 143 if err != nil { 144 return nil, err 145 } 146 147 // TODO: Verify this path. This is taken from CAPO directly 148 // https://github.com/kubernetes-sigs/cluster-api-provider-openstack/blob/main/templates/env.rc 149 cloud.CACertFile = "/etc/certs/cacert" 150 } 151 152 clouds := make(map[string]map[string]*clientconfig.Cloud) 153 clouds["clouds"] = map[string]*clientconfig.Cloud{ 154 cloudName: cloud, 155 } 156 157 cloudsYAML, err := yaml.Marshal(clouds) 158 if err != nil { 159 return nil, err 160 } 161 162 creds := map[string][]byte{ 163 "clouds.yaml": cloudsYAML, 164 } 165 if len(caCert) != 0 { 166 creds["cacert"] = caCert 167 } 168 169 return creds, nil 170 }