github.com/openshift/installer@v1.4.17/pkg/asset/machines/gcp/machines.go (about) 1 // Package gcp generates Machine objects for gcp. 2 package gcp 3 4 import ( 5 "fmt" 6 "sort" 7 8 "github.com/pkg/errors" 9 corev1 "k8s.io/api/core/v1" 10 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 11 "k8s.io/apimachinery/pkg/runtime" 12 13 v1 "github.com/openshift/api/config/v1" 14 machinev1 "github.com/openshift/api/machine/v1" 15 machineapi "github.com/openshift/api/machine/v1beta1" 16 "github.com/openshift/installer/pkg/types" 17 "github.com/openshift/installer/pkg/types/gcp" 18 ) 19 20 // Machines returns a list of machines for a machinepool. 21 func Machines(clusterID string, config *types.InstallConfig, pool *types.MachinePool, osImage, role, userDataSecret string) ([]machineapi.Machine, *machinev1.ControlPlaneMachineSet, error) { 22 if configPlatform := config.Platform.Name(); configPlatform != gcp.Name { 23 return nil, nil, fmt.Errorf("non-GCP configuration: %q", configPlatform) 24 } 25 if poolPlatform := pool.Platform.Name(); poolPlatform != gcp.Name { 26 return nil, nil, fmt.Errorf("non-GCP machine-pool: %q", poolPlatform) 27 } 28 platform := config.Platform.GCP 29 mpool := pool.Platform.GCP 30 azs := mpool.Zones 31 32 credentialsMode := config.CredentialsMode 33 34 total := int64(1) 35 if pool.Replicas != nil { 36 total = *pool.Replicas 37 } 38 39 var machines []machineapi.Machine 40 machineSetProvider := &machineapi.GCPMachineProviderSpec{} 41 for idx := int64(0); idx < total; idx++ { 42 azIndex := int(idx) % len(azs) 43 provider, err := provider(clusterID, platform, mpool, osImage, azIndex, role, userDataSecret, credentialsMode) 44 if err != nil { 45 return nil, nil, errors.Wrap(err, "failed to create provider") 46 } 47 machine := machineapi.Machine{ 48 TypeMeta: metav1.TypeMeta{ 49 APIVersion: "machine.openshift.io/v1beta1", 50 Kind: "Machine", 51 }, 52 ObjectMeta: metav1.ObjectMeta{ 53 Namespace: "openshift-machine-api", 54 Name: fmt.Sprintf("%s-%s-%d", clusterID, pool.Name, idx), 55 Labels: map[string]string{ 56 "machine.openshift.io/cluster-api-cluster": clusterID, 57 "machine.openshift.io/cluster-api-machine-role": role, 58 "machine.openshift.io/cluster-api-machine-type": role, 59 }, 60 }, 61 Spec: machineapi.MachineSpec{ 62 ProviderSpec: machineapi.ProviderSpec{ 63 Value: &runtime.RawExtension{Object: provider}, 64 }, 65 // we don't need to set Versions, because we control those via operators. 66 }, 67 } 68 *machineSetProvider = *provider 69 machines = append(machines, machine) 70 } 71 replicas := int32(total) 72 failureDomains := []machinev1.GCPFailureDomain{} 73 sort.Strings(mpool.Zones) 74 for _, zone := range mpool.Zones { 75 domain := machinev1.GCPFailureDomain{ 76 Zone: zone, 77 } 78 failureDomains = append(failureDomains, domain) 79 } 80 machineSetProvider.Zone = "" 81 controlPlaneMachineSet := &machinev1.ControlPlaneMachineSet{ 82 TypeMeta: metav1.TypeMeta{ 83 APIVersion: "machine.openshift.io/v1", 84 Kind: "ControlPlaneMachineSet", 85 }, 86 ObjectMeta: metav1.ObjectMeta{ 87 Namespace: "openshift-machine-api", 88 Name: "cluster", 89 Labels: map[string]string{ 90 "machine.openshift.io/cluster-api-cluster": clusterID, 91 }, 92 }, 93 Spec: machinev1.ControlPlaneMachineSetSpec{ 94 Replicas: &replicas, 95 State: machinev1.ControlPlaneMachineSetStateActive, 96 Selector: metav1.LabelSelector{ 97 MatchLabels: map[string]string{ 98 "machine.openshift.io/cluster-api-machine-role": role, 99 "machine.openshift.io/cluster-api-machine-type": role, 100 "machine.openshift.io/cluster-api-cluster": clusterID, 101 }, 102 }, 103 Template: machinev1.ControlPlaneMachineSetTemplate{ 104 MachineType: machinev1.OpenShiftMachineV1Beta1MachineType, 105 OpenShiftMachineV1Beta1Machine: &machinev1.OpenShiftMachineV1Beta1MachineTemplate{ 106 FailureDomains: &machinev1.FailureDomains{ 107 Platform: v1.GCPPlatformType, 108 GCP: &failureDomains, 109 }, 110 ObjectMeta: machinev1.ControlPlaneMachineSetTemplateObjectMeta{ 111 Labels: map[string]string{ 112 "machine.openshift.io/cluster-api-cluster": clusterID, 113 "machine.openshift.io/cluster-api-machine-role": role, 114 "machine.openshift.io/cluster-api-machine-type": role, 115 }, 116 }, 117 Spec: machineapi.MachineSpec{ 118 ProviderSpec: machineapi.ProviderSpec{ 119 Value: &runtime.RawExtension{Object: machineSetProvider}, 120 }, 121 }, 122 }, 123 }, 124 }, 125 } 126 127 return machines, controlPlaneMachineSet, nil 128 } 129 130 func provider(clusterID string, platform *gcp.Platform, mpool *gcp.MachinePool, osImage string, azIdx int, role, userDataSecret string, credentialsMode types.CredentialsMode) (*machineapi.GCPMachineProviderSpec, error) { 131 az := mpool.Zones[azIdx] 132 if mpool.OSImage != nil { 133 osImage = fmt.Sprintf("projects/%s/global/images/%s", mpool.OSImage.Project, mpool.OSImage.Name) 134 } 135 network, subnetwork, err := getNetworks(platform, clusterID, role) 136 if err != nil { 137 return nil, err 138 } 139 140 var encryptionKey *machineapi.GCPEncryptionKeyReference 141 142 if mpool.OSDisk.EncryptionKey != nil { 143 encryptionKey = &machineapi.GCPEncryptionKeyReference{ 144 KMSKey: &machineapi.GCPKMSKeyReference{ 145 Name: mpool.OSDisk.EncryptionKey.KMSKey.Name, 146 KeyRing: mpool.OSDisk.EncryptionKey.KMSKey.KeyRing, 147 ProjectID: mpool.OSDisk.EncryptionKey.KMSKey.ProjectID, 148 Location: mpool.OSDisk.EncryptionKey.KMSKey.Location, 149 }, 150 KMSKeyServiceAccount: mpool.OSDisk.EncryptionKey.KMSKeyServiceAccount, 151 } 152 } 153 154 serviceAccountEmail := gcp.GetConfiguredServiceAccount(platform, mpool) 155 if serviceAccountEmail == "" { 156 serviceAccountEmail = gcp.GetDefaultServiceAccount(platform, clusterID, role[0:1]) 157 } 158 159 shieldedInstanceConfig := machineapi.GCPShieldedInstanceConfig{} 160 if mpool.SecureBoot == string(machineapi.SecureBootPolicyEnabled) { 161 shieldedInstanceConfig.SecureBoot = machineapi.SecureBootPolicyEnabled 162 } 163 labels := make(map[string]string, len(platform.UserLabels)) 164 for _, label := range platform.UserLabels { 165 labels[label.Key] = label.Value 166 } 167 tags := make([]machineapi.ResourceManagerTag, len(platform.UserTags)) 168 for i, tag := range platform.UserTags { 169 tags[i] = machineapi.ResourceManagerTag{ 170 ParentID: tag.ParentID, 171 Key: tag.Key, 172 Value: tag.Value, 173 } 174 } 175 return &machineapi.GCPMachineProviderSpec{ 176 TypeMeta: metav1.TypeMeta{ 177 APIVersion: "machine.openshift.io/v1beta1", 178 Kind: "GCPMachineProviderSpec", 179 }, 180 UserDataSecret: &corev1.LocalObjectReference{Name: userDataSecret}, 181 CredentialsSecret: &corev1.LocalObjectReference{Name: "gcp-cloud-credentials"}, 182 Disks: []*machineapi.GCPDisk{{ 183 AutoDelete: true, 184 Boot: true, 185 SizeGB: mpool.OSDisk.DiskSizeGB, 186 Type: mpool.OSDisk.DiskType, 187 Image: osImage, 188 Labels: labels, 189 EncryptionKey: encryptionKey, 190 }}, 191 NetworkInterfaces: []*machineapi.GCPNetworkInterface{{ 192 Network: network, 193 ProjectID: platform.NetworkProjectID, 194 Subnetwork: subnetwork, 195 }}, 196 ServiceAccounts: []machineapi.GCPServiceAccount{{ 197 Email: serviceAccountEmail, 198 Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"}, 199 }}, 200 Tags: append(mpool.Tags, []string{fmt.Sprintf("%s-%s", clusterID, role)}...), 201 MachineType: mpool.InstanceType, 202 Region: platform.Region, 203 Zone: az, 204 ProjectID: platform.ProjectID, 205 ShieldedInstanceConfig: shieldedInstanceConfig, 206 ConfidentialCompute: machineapi.ConfidentialComputePolicy(mpool.ConfidentialCompute), 207 OnHostMaintenance: machineapi.GCPHostMaintenanceType(mpool.OnHostMaintenance), 208 Labels: labels, 209 ResourceManagerTags: tags, 210 }, nil 211 } 212 213 // ConfigMasters assigns a set of load balancers to the given machines 214 func ConfigMasters(machines []machineapi.Machine, controlPlane *machinev1.ControlPlaneMachineSet, clusterID string, publish types.PublishingStrategy) error { 215 var targetPools []string 216 if publish == types.ExternalPublishingStrategy { 217 targetPools = append(targetPools, fmt.Sprintf("%s-api", clusterID)) 218 } 219 220 for _, machine := range machines { 221 providerSpec := machine.Spec.ProviderSpec.Value.Object.(*machineapi.GCPMachineProviderSpec) 222 providerSpec.TargetPools = targetPools 223 } 224 225 providerSpec, ok := controlPlane.Spec.Template.OpenShiftMachineV1Beta1Machine.Spec.ProviderSpec.Value.Object.(*machineapi.GCPMachineProviderSpec) 226 if !ok { 227 return errors.New("Unable to set target pools to control plane machine set") 228 } 229 providerSpec.TargetPools = targetPools 230 return nil 231 } 232 func getNetworks(platform *gcp.Platform, clusterID, role string) (string, string, error) { 233 if platform.Network == "" { 234 return fmt.Sprintf("%s-network", clusterID), fmt.Sprintf("%s-%s-subnet", clusterID, role), nil 235 } 236 237 switch role { 238 case "worker": 239 return platform.Network, platform.ComputeSubnet, nil 240 case "master": 241 return platform.Network, platform.ControlPlaneSubnet, nil 242 default: 243 return "", "", fmt.Errorf("unrecognized machine role %s", role) 244 } 245 }