github.com/openshift/installer@v1.4.17/pkg/asset/cluster/cluster.go (about) 1 package cluster 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "strings" 9 10 "github.com/pkg/errors" 11 "github.com/sirupsen/logrus" 12 13 "github.com/openshift/installer/pkg/asset" 14 "github.com/openshift/installer/pkg/asset/cluster/aws" 15 "github.com/openshift/installer/pkg/asset/cluster/azure" 16 "github.com/openshift/installer/pkg/asset/cluster/openstack" 17 "github.com/openshift/installer/pkg/asset/cluster/tfvars" 18 "github.com/openshift/installer/pkg/asset/ignition/bootstrap" 19 "github.com/openshift/installer/pkg/asset/ignition/machine" 20 "github.com/openshift/installer/pkg/asset/installconfig" 21 "github.com/openshift/installer/pkg/asset/kubeconfig" 22 "github.com/openshift/installer/pkg/asset/machines" 23 "github.com/openshift/installer/pkg/asset/manifests" 24 capimanifests "github.com/openshift/installer/pkg/asset/manifests/clusterapi" 25 "github.com/openshift/installer/pkg/asset/password" 26 "github.com/openshift/installer/pkg/asset/quota" 27 "github.com/openshift/installer/pkg/asset/rhcos" 28 "github.com/openshift/installer/pkg/clusterapi" 29 infra "github.com/openshift/installer/pkg/infrastructure/platform" 30 typesaws "github.com/openshift/installer/pkg/types/aws" 31 typesazure "github.com/openshift/installer/pkg/types/azure" 32 typesopenstack "github.com/openshift/installer/pkg/types/openstack" 33 ) 34 35 var ( 36 // InstallDir is the directory containing install assets. 37 InstallDir string 38 ) 39 40 // Cluster uses the terraform executable to launch a cluster 41 // with the given terraform tfvar and generated templates. 42 type Cluster struct { 43 FileList []*asset.File 44 } 45 46 var _ asset.WritableAsset = (*Cluster)(nil) 47 48 // Name returns the human-friendly name of the asset. 49 func (c *Cluster) Name() string { 50 return "Cluster" 51 } 52 53 // Dependencies returns the direct dependency for launching 54 // the cluster. 55 func (c *Cluster) Dependencies() []asset.Asset { 56 return []asset.Asset{ 57 &installconfig.ClusterID{}, 58 &installconfig.InstallConfig{}, 59 // PlatformCredsCheck, PlatformPermsCheck, PlatformProvisionCheck, and VCenterContexts. 60 // perform validations & check perms required to provision infrastructure. 61 // We do not actually use them in this asset directly, hence 62 // they are put in the dependencies but not fetched in Generate. 63 &installconfig.PlatformCredsCheck{}, 64 &installconfig.PlatformPermsCheck{}, 65 &installconfig.PlatformProvisionCheck{}, 66 new(rhcos.Image), 67 "a.PlatformQuotaCheck{}, 68 &tfvars.TerraformVariables{}, 69 &password.KubeadminPassword{}, 70 &manifests.Manifests{}, 71 &capimanifests.Cluster{}, 72 &kubeconfig.AdminClient{}, 73 &bootstrap.Bootstrap{}, 74 &machine.Master{}, 75 &machines.Worker{}, 76 &machines.ClusterAPI{}, 77 new(rhcos.Image), 78 &manifests.Manifests{}, 79 } 80 } 81 82 // Generate launches the cluster and generates the terraform state file on disk. 83 func (c *Cluster) Generate(ctx context.Context, parents asset.Parents) (err error) { 84 if InstallDir == "" { 85 logrus.Fatalf("InstallDir has not been set for the %q asset", c.Name()) 86 } 87 88 clusterID := &installconfig.ClusterID{} 89 installConfig := &installconfig.InstallConfig{} 90 rhcosImage := new(rhcos.Image) 91 terraformVariables := &tfvars.TerraformVariables{} 92 parents.Get(clusterID, installConfig, terraformVariables, rhcosImage) 93 94 if fs := installConfig.Config.FeatureSet; strings.HasSuffix(string(fs), "NoUpgrade") { 95 logrus.Warnf("FeatureSet %q is enabled. This FeatureSet does not allow upgrades and may affect the supportability of the cluster.", fs) 96 } 97 98 if installConfig.Config.Platform.None != nil { 99 return errors.New("cluster cannot be created with platform set to 'none'") 100 } 101 102 if installConfig.Config.BootstrapInPlace != nil { 103 return errors.New("cluster cannot be created with bootstrapInPlace set") 104 } 105 106 platform := installConfig.Config.Platform.Name() 107 108 if azure := installConfig.Config.Platform.Azure; azure != nil && azure.CloudName == typesazure.StackCloud { 109 platform = typesazure.StackTerraformName 110 } 111 112 // TODO(padillon): determine whether CAPI handles tagging shared subnets, in which case we should be able 113 // to encapsulate these into the terraform package. 114 logrus.Infof("Creating infrastructure resources...") 115 switch platform { 116 case typesaws.Name: 117 if err := aws.PreTerraform(ctx, clusterID.InfraID, installConfig); err != nil { 118 return err 119 } 120 case typesazure.Name, typesazure.StackTerraformName: 121 if err := azure.PreTerraform(ctx, clusterID.InfraID, installConfig); err != nil { 122 return err 123 } 124 case typesopenstack.Name: 125 var tfvarsFile *asset.File 126 for _, f := range terraformVariables.Files() { 127 if f.Filename == tfvars.TfPlatformVarsFileName { 128 tfvarsFile = f 129 break 130 } 131 } 132 if err := openstack.PreTerraform(ctx, tfvarsFile, installConfig, clusterID, rhcosImage); err != nil { 133 return err 134 } 135 } 136 137 provider, err := infra.ProviderForPlatform(platform, installConfig.Config.EnabledFeatureGates()) 138 if err != nil { 139 return fmt.Errorf("error getting infrastructure provider: %w", err) 140 } 141 files, err := provider.Provision(ctx, InstallDir, parents) 142 if files != nil { 143 c.FileList = append(c.FileList, files...) // append state files even in case of failure 144 } 145 if err != nil { 146 return fmt.Errorf("%s: %w", asset.ClusterCreationError, err) 147 } 148 149 return nil 150 } 151 152 // Files returns the FileList generated by the asset. 153 func (c *Cluster) Files() []*asset.File { 154 return c.FileList 155 } 156 157 // Load returns error if the tfstate file is already on-disk, because we want to 158 // prevent user from accidentally re-launching the cluster. 159 func (c *Cluster) Load(f asset.FileFetcher) (found bool, err error) { 160 matches, err := filepath.Glob("terraform(.*)?.tfstate") 161 if err != nil { 162 return true, err 163 } 164 if len(matches) != 0 { 165 return true, fmt.Errorf("terraform state files already exist. There may already be a running cluster") 166 } 167 168 matches, err = filepath.Glob(filepath.Join(InstallDir, clusterapi.ArtifactsDir, "envtest.kubeconfig")) 169 if err != nil { 170 return true, fmt.Errorf("error checking for existence of envtest.kubeconfig: %w", err) 171 } 172 173 // Cluster-API based installs can be re-entered, but this is an experimental feature 174 // that should be opted into and only used for testing and development. 175 reentrant := strings.EqualFold(os.Getenv("OPENSHIFT_INSTALL_REENTRANT"), "true") 176 177 if !reentrant && len(matches) != 0 { 178 return true, fmt.Errorf("local infrastructure provisioning artifacts already exist. There may already be a running cluster") 179 } 180 return false, nil 181 }