github.com/openshift/installer@v1.4.17/pkg/asset/manifests/clusterapi/cluster.go (about) 1 package clusterapi 2 3 import ( 4 "context" 5 "fmt" 6 "path/filepath" 7 "strings" 8 9 "github.com/pkg/errors" 10 "github.com/sirupsen/logrus" 11 corev1 "k8s.io/api/core/v1" 12 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 13 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 14 "k8s.io/utils/ptr" 15 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 16 "sigs.k8s.io/controller-runtime/pkg/client" 17 "sigs.k8s.io/yaml" 18 19 "github.com/openshift/installer/pkg/asset" 20 "github.com/openshift/installer/pkg/asset/installconfig" 21 "github.com/openshift/installer/pkg/asset/manifests" 22 "github.com/openshift/installer/pkg/asset/manifests/aws" 23 "github.com/openshift/installer/pkg/asset/manifests/azure" 24 "github.com/openshift/installer/pkg/asset/manifests/capiutils" 25 "github.com/openshift/installer/pkg/asset/manifests/gcp" 26 "github.com/openshift/installer/pkg/asset/manifests/nutanix" 27 "github.com/openshift/installer/pkg/asset/manifests/openstack" 28 "github.com/openshift/installer/pkg/asset/manifests/powervs" 29 "github.com/openshift/installer/pkg/asset/manifests/vsphere" 30 "github.com/openshift/installer/pkg/asset/openshiftinstall" 31 "github.com/openshift/installer/pkg/asset/rhcos" 32 "github.com/openshift/installer/pkg/clusterapi" 33 awstypes "github.com/openshift/installer/pkg/types/aws" 34 azuretypes "github.com/openshift/installer/pkg/types/azure" 35 gcptypes "github.com/openshift/installer/pkg/types/gcp" 36 nutanixtypes "github.com/openshift/installer/pkg/types/nutanix" 37 openstacktypes "github.com/openshift/installer/pkg/types/openstack" 38 powervstypes "github.com/openshift/installer/pkg/types/powervs" 39 vsphereplatform "github.com/openshift/installer/pkg/types/vsphere" 40 ) 41 42 var _ asset.WritableRuntimeAsset = (*Cluster)(nil) 43 44 // Cluster generates manifests for target cluster 45 // creation using CAPI. 46 type Cluster struct { 47 FileList []*asset.RuntimeFile 48 } 49 50 // Name returns a human friendly name for the operator. 51 func (c *Cluster) Name() string { 52 return "Cluster API Manifests" 53 } 54 55 // Dependencies returns all of the dependencies directly needed by the 56 // ClusterAPI asset. 57 func (c *Cluster) Dependencies() []asset.Asset { 58 return []asset.Asset{ 59 &installconfig.InstallConfig{}, 60 &installconfig.ClusterID{}, 61 &openshiftinstall.Config{}, 62 &manifests.FeatureGate{}, 63 new(rhcos.Image), 64 } 65 } 66 67 // Generate generates the respective operator config.yml files. 68 func (c *Cluster) Generate(_ context.Context, dependencies asset.Parents) error { 69 installConfig := &installconfig.InstallConfig{} 70 clusterID := &installconfig.ClusterID{} 71 openshiftInstall := &openshiftinstall.Config{} 72 featureGate := &manifests.FeatureGate{} 73 rhcosImage := new(rhcos.Image) 74 dependencies.Get(installConfig, clusterID, openshiftInstall, featureGate, rhcosImage) 75 76 // If the feature gate is not enabled, do not generate any manifests. 77 if !capiutils.IsEnabled(installConfig) { 78 return nil 79 } 80 81 c.FileList = []*asset.RuntimeFile{} 82 83 namespace := &corev1.Namespace{ 84 ObjectMeta: metav1.ObjectMeta{ 85 Name: capiutils.Namespace, 86 }, 87 } 88 namespace.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Namespace")) 89 c.FileList = append(c.FileList, &asset.RuntimeFile{Object: namespace, File: asset.File{Filename: "000_capi-namespace.yaml"}}) 90 91 var out *capiutils.GenerateClusterAssetsOutput 92 switch platform := installConfig.Config.Platform.Name(); platform { 93 case awstypes.Name: 94 var err error 95 out, err = aws.GenerateClusterAssets(installConfig, clusterID) 96 if err != nil { 97 return errors.Wrap(err, "failed to generate AWS manifests") 98 } 99 case azuretypes.Name: 100 var err error 101 out, err = azure.GenerateClusterAssets(installConfig, clusterID) 102 if err != nil { 103 return errors.Wrap(err, "failed to generate Azure manifests") 104 } 105 case gcptypes.Name: 106 var err error 107 out, err = gcp.GenerateClusterAssets(installConfig, clusterID) 108 if err != nil { 109 return fmt.Errorf("failed to generate GCP manifests: %w", err) 110 } 111 case vsphereplatform.Name: 112 var err error 113 out, err = vsphere.GenerateClusterAssets(installConfig, clusterID) 114 if err != nil { 115 return fmt.Errorf("failed to generate vSphere manifests %w", err) 116 } 117 case openstacktypes.Name: 118 var err error 119 out, err = openstack.GenerateClusterAssets(installConfig, clusterID) 120 if err != nil { 121 return errors.Wrap(err, "failed to generate OpenStack manifests") 122 } 123 case powervstypes.Name: 124 var err error 125 osImage := strings.SplitN(rhcosImage.ControlPlane, "/", 2) 126 out, err = powervs.GenerateClusterAssets(installConfig, clusterID, osImage[0], osImage[1]) 127 if err != nil { 128 return fmt.Errorf("failed to generate PowerVS manifests %w", err) 129 } 130 case nutanixtypes.Name: 131 var err error 132 out, err = nutanix.GenerateClusterAssets(installConfig, clusterID) 133 if err != nil { 134 return errors.Wrap(err, "failed to generate Nutanix manifests") 135 } 136 default: 137 return fmt.Errorf("unsupported platform %q", platform) 138 } 139 140 if len(out.InfrastructureRefs) == 0 { 141 return fmt.Errorf("failed to generate manifests: cluster.Spec.InfrastructureRef was never set") 142 } 143 144 logrus.Infof("Adding clusters...") 145 for index, infra := range out.InfrastructureRefs { 146 cluster := &clusterv1.Cluster{ 147 ObjectMeta: metav1.ObjectMeta{ 148 Name: infra.Name, 149 Namespace: capiutils.Namespace, 150 }, 151 Spec: clusterv1.ClusterSpec{ 152 ClusterNetwork: &clusterv1.ClusterNetwork{ 153 APIServerPort: ptr.To[int32](6443), 154 }, 155 }, 156 } 157 cluster.Spec.InfrastructureRef = infra 158 cluster.SetGroupVersionKind(clusterv1.GroupVersion.WithKind("Cluster")) 159 c.FileList = append(c.FileList, &asset.RuntimeFile{Object: cluster, File: asset.File{Filename: fmt.Sprintf("01_capi-cluster-%d.yaml", index)}}) 160 } 161 162 // Append the infrastructure manifests. 163 c.FileList = append(c.FileList, out.Manifests...) 164 165 // Create the infrastructure manifests. 166 for _, m := range c.FileList { 167 objData, err := yaml.Marshal(m.Object) 168 if err != nil { 169 return errors.Wrapf(err, "failed to marshal infrastructure manifest %s", m.Filename) 170 } 171 m.Data = objData 172 173 // If the filename is already a path, do not append the manifest dir. 174 if filepath.Dir(m.Filename) == capiutils.ManifestDir { 175 continue 176 } 177 m.Filename = filepath.Join(capiutils.ManifestDir, m.Filename) 178 } 179 180 asset.SortManifestFiles(c.FileList) 181 return nil 182 } 183 184 // Files returns the files generated by the asset. 185 func (c *Cluster) Files() []*asset.File { 186 files := []*asset.File{} 187 for _, f := range c.FileList { 188 f := f // TODO: remove with golang 1.22 189 files = append(files, &f.File) 190 } 191 return files 192 } 193 194 // RuntimeFiles returns the files generated by the asset. 195 func (c *Cluster) RuntimeFiles() []*asset.RuntimeFile { 196 return c.FileList 197 } 198 199 // Load returns the openshift asset from disk. 200 func (c *Cluster) Load(f asset.FileFetcher) (bool, error) { 201 yamlFileList, err := f.FetchByPattern(filepath.Join(capiutils.ManifestDir, "*.yaml")) 202 if err != nil { 203 return false, errors.Wrap(err, "failed to load *.yaml files") 204 } 205 ymlFileList, err := f.FetchByPattern(filepath.Join(capiutils.ManifestDir, "*.yml")) 206 if err != nil { 207 return false, errors.Wrap(err, "failed to load *.yml files") 208 } 209 jsonFileList, err := f.FetchByPattern(filepath.Join(capiutils.ManifestDir, "*.json")) 210 if err != nil { 211 return false, errors.Wrap(err, "failed to load *.json files") 212 } 213 fileList := append(yamlFileList, ymlFileList...) //nolint:gocritic 214 fileList = append(fileList, jsonFileList...) 215 216 for _, file := range fileList { 217 u := &unstructured.Unstructured{} 218 if err := yaml.Unmarshal(file.Data, u); err != nil { 219 return false, errors.Wrap(err, "failed to unmarshal file") 220 } 221 obj, err := clusterapi.Scheme.New(u.GroupVersionKind()) 222 if err != nil { 223 return false, errors.Wrap(err, "failed to create object") 224 } 225 if err := clusterapi.Scheme.Convert(u, obj, nil); err != nil { 226 return false, errors.Wrap(err, "failed to convert object") 227 } 228 c.FileList = append(c.FileList, &asset.RuntimeFile{ 229 File: asset.File{ 230 Filename: file.Filename, 231 Data: file.Data, 232 }, 233 Object: obj.(client.Object), 234 }) 235 } 236 237 asset.SortManifestFiles(c.FileList) 238 return len(c.FileList) > 0, nil 239 }