github.com/openshift/installer@v1.4.17/pkg/tfvars/ibmcloud/ibmcloud.go (about) 1 package ibmcloud 2 3 import ( 4 "encoding/json" 5 "fmt" 6 7 "github.com/pkg/errors" 8 "github.com/sirupsen/logrus" 9 10 configv1 "github.com/openshift/api/config/v1" 11 "github.com/openshift/installer/pkg/rhcos/cache" 12 "github.com/openshift/installer/pkg/types" 13 ibmcloudtypes "github.com/openshift/installer/pkg/types/ibmcloud" 14 ibmcloudprovider "github.com/openshift/machine-api-provider-ibmcloud/pkg/apis/ibmcloudprovider/v1" 15 ) 16 17 // IBMCloudEndpointJSONFileName is the file containing the IBM Cloud Terraform provider's endpoint override JSON. 18 const IBMCloudEndpointJSONFileName = "ibmcloud_endpoints_override.json" 19 20 // Auth is the collection of credentials that will be used by terrform. 21 type Auth struct { 22 APIKey string `json:"ibmcloud_api_key,omitempty"` 23 } 24 25 // DedicatedHost is the format used by terraform. 26 type DedicatedHost struct { 27 ID string `json:"id,omitempty"` 28 Profile string `json:"profile,omitempty"` 29 } 30 31 type config struct { 32 Auth `json:",inline"` 33 BootstrapInstanceType string `json:"ibmcloud_bootstrap_instance_type,omitempty"` 34 CISInstanceCRN string `json:"ibmcloud_cis_crn,omitempty"` 35 ComputeSubnets []string `json:"ibmcloud_compute_subnets,omitempty"` 36 ControlPlaneBootVolumeKey string `json:"ibmcloud_control_plane_boot_volume_key"` 37 ControlPlaneSubnets []string `json:"ibmcloud_control_plane_subnets,omitempty"` 38 DNSInstanceID string `json:"ibmcloud_dns_id,omitempty"` 39 EndpointsJSONFile string `json:"ibmcloud_endpoints_json_file,omitempty"` 40 ExtraTags []string `json:"ibmcloud_extra_tags,omitempty"` 41 ImageFilePath string `json:"ibmcloud_image_filepath,omitempty"` 42 MasterAvailabilityZones []string `json:"ibmcloud_master_availability_zones"` 43 MasterInstanceType string `json:"ibmcloud_master_instance_type,omitempty"` 44 MasterDedicatedHosts []DedicatedHost `json:"ibmcloud_master_dedicated_hosts,omitempty"` 45 NetworkResourceGroupName string `json:"ibmcloud_network_resource_group_name,omitempty"` 46 PreexistingVPC bool `json:"ibmcloud_preexisting_vpc,omitempty"` 47 PublishStrategy string `json:"ibmcloud_publish_strategy,omitempty"` 48 Region string `json:"ibmcloud_region,omitempty"` 49 ResourceGroupName string `json:"ibmcloud_resource_group_name,omitempty"` 50 TerraformPrivateVisibility bool `json:"ibmcloud_terraform_private_visibility,omitempty"` 51 VPC string `json:"ibmcloud_vpc,omitempty"` 52 VPCPermitted bool `json:"ibmcloud_vpc_permitted,omitempty"` 53 WorkerAvailabilityZones []string `json:"ibmcloud_worker_availability_zones"` 54 WorkerDedicatedHosts []DedicatedHost `json:"ibmcloud_worker_dedicated_hosts,omitempty"` 55 } 56 57 // TFVarsSources contains the parameters to be converted into Terraform variables 58 type TFVarsSources struct { 59 Auth Auth 60 CISInstanceCRN string 61 DNSInstanceID string 62 EndpointsJSONFile string 63 ImageURL string 64 MasterConfigs []*ibmcloudprovider.IBMCloudMachineProviderSpec 65 MasterDedicatedHosts []DedicatedHost 66 NetworkResourceGroupName string 67 PreexistingVPC bool 68 PublishStrategy types.PublishingStrategy 69 ResourceGroupName string 70 TerraformPrivateVisibility bool 71 VPCPermitted bool 72 WorkerConfigs []*ibmcloudprovider.IBMCloudMachineProviderSpec 73 WorkerDedicatedHosts []DedicatedHost 74 } 75 76 // TFVars generates ibmcloud-specific Terraform variables launching the cluster. 77 func TFVars(sources TFVarsSources) ([]byte, error) { 78 cachedImage, err := cache.DownloadImageFile(sources.ImageURL, cache.InstallerApplicationName) 79 if err != nil { 80 return nil, errors.Wrap(err, "failed to use cached ibmcloud image") 81 } 82 83 masterConfig := sources.MasterConfigs[0] 84 masterAvailabilityZones := make([]string, len(sources.MasterConfigs)) 85 for i, c := range sources.MasterConfigs { 86 masterAvailabilityZones[i] = c.Zone 87 } 88 workerAvailabilityZones := make([]string, len(sources.WorkerConfigs)) 89 for i, c := range sources.WorkerConfigs { 90 workerAvailabilityZones[i] = c.Zone 91 } 92 93 // Set pre-existing network config 94 var vpc string 95 masterSubnets := make([]string, len(sources.MasterConfigs)) 96 workerSubnets := make([]string, len(sources.WorkerConfigs)) 97 if sources.PreexistingVPC { 98 vpc = sources.MasterConfigs[0].VPC 99 for index, config := range sources.MasterConfigs { 100 masterSubnets[index] = config.PrimaryNetworkInterface.Subnet 101 } 102 for index, config := range sources.WorkerConfigs { 103 workerSubnets[index] = config.PrimaryNetworkInterface.Subnet 104 } 105 } 106 107 cfg := &config{ 108 Auth: sources.Auth, 109 BootstrapInstanceType: masterConfig.Profile, 110 CISInstanceCRN: sources.CISInstanceCRN, 111 ComputeSubnets: workerSubnets, 112 ControlPlaneBootVolumeKey: masterConfig.BootVolume.EncryptionKey, 113 ControlPlaneSubnets: masterSubnets, 114 DNSInstanceID: sources.DNSInstanceID, 115 EndpointsJSONFile: sources.EndpointsJSONFile, 116 ImageFilePath: cachedImage, 117 MasterAvailabilityZones: masterAvailabilityZones, 118 MasterDedicatedHosts: sources.MasterDedicatedHosts, 119 MasterInstanceType: masterConfig.Profile, 120 NetworkResourceGroupName: sources.NetworkResourceGroupName, 121 PreexistingVPC: sources.PreexistingVPC, 122 PublishStrategy: string(sources.PublishStrategy), 123 Region: masterConfig.Region, 124 ResourceGroupName: sources.ResourceGroupName, 125 TerraformPrivateVisibility: sources.TerraformPrivateVisibility, 126 VPC: vpc, 127 VPCPermitted: sources.VPCPermitted, 128 WorkerAvailabilityZones: workerAvailabilityZones, 129 WorkerDedicatedHosts: sources.WorkerDedicatedHosts, 130 131 // TODO: IBM: Future support 132 // ExtraTags: masterConfig.Tags, 133 } 134 135 return json.MarshalIndent(cfg, "", " ") 136 } 137 138 // CreateEndpointJSON creates JSON data containing IBM Cloud service endpoint override mappings. 139 func CreateEndpointJSON(endpoints []configv1.IBMCloudServiceEndpoint, region string) ([]byte, error) { 140 // If no endpoint overrides, simply return 141 if len(endpoints) == 0 { 142 return nil, nil 143 } 144 145 endpointContents := ibmcloudtypes.EndpointsJSON{} 146 for _, endpoint := range endpoints { 147 switch endpoint.Name { 148 // COS endpoint is not used in Terraform 149 case configv1.IBMCloudServiceCOS: 150 continue 151 case configv1.IBMCloudServiceCIS: 152 endpointContents.IBMCloudEndpointCIS = &ibmcloudtypes.EndpointsVisibility{ 153 Private: map[string]string{ 154 region: endpoint.URL, 155 }, 156 Public: map[string]string{ 157 region: endpoint.URL, 158 }, 159 } 160 case configv1.IBMCloudServiceDNSServices: 161 endpointContents.IBMCloudEndpointDNSServices = &ibmcloudtypes.EndpointsVisibility{ 162 Private: map[string]string{ 163 region: endpoint.URL, 164 }, 165 Public: map[string]string{ 166 region: endpoint.URL, 167 }, 168 } 169 case configv1.IBMCloudServiceGlobalSearch: 170 endpointContents.IBMCloudEndpointGlobalSearch = &ibmcloudtypes.EndpointsVisibility{ 171 Private: map[string]string{ 172 region: endpoint.URL, 173 }, 174 Public: map[string]string{ 175 region: endpoint.URL, 176 }, 177 } 178 case configv1.IBMCloudServiceGlobalTagging: 179 endpointContents.IBMCloudEndpointGlobalTagging = &ibmcloudtypes.EndpointsVisibility{ 180 Private: map[string]string{ 181 region: endpoint.URL, 182 }, 183 Public: map[string]string{ 184 region: endpoint.URL, 185 }, 186 } 187 case configv1.IBMCloudServiceHyperProtect: 188 endpointContents.IBMCloudEndpointHyperProtect = &ibmcloudtypes.EndpointsVisibility{ 189 Private: map[string]string{ 190 region: endpoint.URL, 191 }, 192 Public: map[string]string{ 193 region: endpoint.URL, 194 }, 195 } 196 case configv1.IBMCloudServiceIAM: 197 endpointContents.IBMCloudEndpointIAM = &ibmcloudtypes.EndpointsVisibility{ 198 Private: map[string]string{ 199 region: endpoint.URL, 200 }, 201 Public: map[string]string{ 202 region: endpoint.URL, 203 }, 204 } 205 case configv1.IBMCloudServiceKeyProtect: 206 endpointContents.IBMCloudEndpointKeyProtect = &ibmcloudtypes.EndpointsVisibility{ 207 Private: map[string]string{ 208 region: endpoint.URL, 209 }, 210 Public: map[string]string{ 211 region: endpoint.URL, 212 }, 213 } 214 case configv1.IBMCloudServiceResourceController: 215 endpointContents.IBMCloudEndpointResourceController = &ibmcloudtypes.EndpointsVisibility{ 216 Private: map[string]string{ 217 region: endpoint.URL, 218 }, 219 Public: map[string]string{ 220 region: endpoint.URL, 221 }, 222 } 223 case configv1.IBMCloudServiceResourceManager: 224 endpointContents.IBMCloudEndpointResourceManager = &ibmcloudtypes.EndpointsVisibility{ 225 Private: map[string]string{ 226 region: endpoint.URL, 227 }, 228 Public: map[string]string{ 229 region: endpoint.URL, 230 }, 231 } 232 case configv1.IBMCloudServiceVPC: 233 endpointContents.IBMCloudEndpointVPC = &ibmcloudtypes.EndpointsVisibility{ 234 Private: map[string]string{ 235 region: endpoint.URL, 236 }, 237 Public: map[string]string{ 238 region: endpoint.URL, 239 }, 240 } 241 default: 242 return nil, fmt.Errorf("unable to build override values for unknown service: %s", endpoint.Name) 243 } 244 } 245 jsonData, err := json.Marshal(endpointContents) 246 if err != nil { 247 return nil, fmt.Errorf("failure building service endpoint override JSON data: %w", err) 248 } 249 250 // If the JSON contains no data, none was populated (jsonData == "{}"), but endpoints is not empty, we assume the Services are not required for Terraform (e.g., COS) 251 // Log this as a warning, but continue as if no service endpoints were provided 252 if len(jsonData) <= 2 { 253 logrus.Warnf("no terraform endpoint json was created for services: %s", endpoints) 254 return nil, nil 255 } 256 return jsonData, nil 257 }