func resourceAliCloudInstanceCreate()

in alicloud/resource_alicloud_instance.go [703:1149]


func resourceAliCloudInstanceCreate(d *schema.ResourceData, meta interface{}) error {
	client := meta.(*connectivity.AliyunClient)
	ecsService := EcsService{client}
	var response map[string]interface{}
	action := "RunInstances"
	request := make(map[string]interface{})
	var err error

	request["RegionId"] = client.RegionId
	request["ClientToken"] = buildClientToken(action)

	if v, ok := d.GetOk("instance_type"); ok {
		request["InstanceType"] = v
	}

	if v, ok := d.GetOk("image_id"); ok {
		request["ImageId"] = v
	}

	if v, ok := d.GetOk("availability_zone"); ok {
		request["ZoneId"] = v
	}

	if v, ok := d.GetOk("system_disk_name"); ok {
		request["SystemDisk.DiskName"] = v
	}

	if v, ok := d.GetOk("system_disk_description"); ok {
		request["SystemDisk.Description"] = v
	}

	if v, ok := d.GetOk("system_disk_performance_level"); ok {
		request["SystemDisk.PerformanceLevel"] = v
	}

	if v, ok := d.GetOk("system_disk_category"); ok {
		request["SystemDisk.Category"] = v
	}

	if v, ok := d.GetOk("system_disk_size"); ok {
		request["SystemDisk.Size"] = v
	}

	if v, ok := d.GetOk("system_disk_auto_snapshot_policy_id"); ok {
		request["SystemDisk.AutoSnapshotPolicyId"] = v
	}

	if v, ok := d.GetOk("system_disk_storage_cluster_id"); ok {
		request["SystemDisk.StorageClusterId"] = v
	}

	if v, ok := d.GetOkExists("system_disk_encrypted"); ok {
		request["SystemDisk.Encrypted"] = v
	}

	if v, ok := d.GetOk("system_disk_kms_key_id"); ok {
		request["SystemDisk.KMSKeyId"] = v
	}

	if v, ok := d.GetOk("system_disk_encrypt_algorithm"); ok {
		request["SystemDisk.EncryptAlgorithm"] = v
	}

	if v, ok := d.GetOk("instance_name"); ok {
		request["InstanceName"] = v
	}

	if v, ok := d.GetOk("credit_specification"); ok {
		request["CreditSpecification"] = v
	}

	if v, ok := d.GetOk("resource_group_id"); ok {
		request["ResourceGroupId"] = v
	}

	if v, ok := d.GetOk("description"); ok {
		request["Description"] = v
	}

	if v, ok := d.GetOk("launch_template_name"); ok {
		request["LaunchTemplateName"] = v
	}
	if v, ok := d.GetOk("launch_template_id"); ok {
		request["LaunchTemplateId"] = v
	}
	if v, ok := d.GetOk("launch_template_version"); ok {
		request["LaunchTemplateVersion"] = v
	}

	if v, ok := d.GetOk("internet_charge_type"); ok {
		request["InternetChargeType"] = v
	}

	if v, ok := d.GetOk("internet_max_bandwidth_out"); ok {
		request["InternetMaxBandwidthOut"] = v
	}

	if v, ok := d.GetOk("internet_max_bandwidth_in"); ok {
		request["InternetMaxBandwidthIn"] = v
	}

	if v, ok := d.GetOk("host_name"); ok {
		request["HostName"] = v
	}

	if v, ok := d.GetOk("password"); ok {
		request["Password"] = v
	}

	if v, ok := d.GetOk("kms_encrypted_password"); ok {
		kmsService := KmsService{client}
		decryptResp, err := kmsService.Decrypt(v.(string), d.Get("kms_encryption_context").(map[string]interface{}))
		if err != nil {
			return WrapError(err)
		}
		request["Password"] = decryptResp
	}

	if v, ok := d.GetOkExists("password_inherit"); ok {
		request["PasswordInherit"] = v
	}

	vswitchValue := d.Get("vswitch_id")
	if vswitchValue == "" {
		vswitchValue = d.Get("subnet_id")
	}

	if v, ok := d.GetOk("instance_charge_type"); ok {
		request["InstanceChargeType"] = v
	}

	if request["InstanceChargeType"] == string(PrePaid) {
		if v, ok := d.GetOk("period"); ok {
			request["Period"] = v
		}
		if v, ok := d.GetOk("period_unit"); ok {
			request["PeriodUnit"] = v
		}
		if v, ok := d.GetOk("renewal_status"); ok && v.(string) == "AutoRenewal" {
			request["AutoRenew"] = true
		}
		if v, ok := d.GetOk("auto_renew_period"); ok {
			request["AutoRenewPeriod"] = v
		}
	} else {
		if v, ok := d.GetOk("spot_strategy"); ok {
			request["SpotStrategy"] = v
		}
		if v, ok := d.GetOk("spot_price_limit"); ok {
			request["SpotPriceLimit"] = v
		}
	}

	if v, ok := d.GetOk("user_data"); ok {
		_, base64DecodeError := base64.StdEncoding.DecodeString(v.(string))
		if base64DecodeError == nil {
			request["UserData"] = v
		} else {
			request["UserData"] = base64.StdEncoding.EncodeToString([]byte(v.(string)))
		}
	}

	if v, ok := d.GetOk("role_name"); ok {
		request["RamRoleName"] = v
	}

	if v, ok := d.GetOk("key_name"); ok {
		request["KeyPairName"] = v
	}

	if v, ok := d.GetOk("security_enhancement_strategy"); ok {
		request["SecurityEnhancementStrategy"] = v
	}

	if v, ok := d.GetOk("auto_release_time"); ok && v.(string) != "" {
		request["AutoReleaseTime"] = v
	}

	if v, ok := d.GetOkExists("dry_run"); ok {
		request["DryRun"] = v
	}

	if v, ok := d.GetOkExists("deletion_protection"); ok {
		request["DeletionProtection"] = v
	}

	if v, ok := d.GetOk("tags"); ok {
		count := 1
		for key, value := range v.(map[string]interface{}) {
			request[fmt.Sprintf("Tag.%d.Key", count)] = key
			request[fmt.Sprintf("Tag.%d.Value", count)] = value
			count++
		}
	}

	if v, ok := d.GetOk("data_disks"); ok {
		disksMaps := make([]map[string]interface{}, 0)
		disks := v.([]interface{})
		for _, rew := range disks {

			disksMap := make(map[string]interface{})
			item := rew.(map[string]interface{})

			disksMap["DeleteWithInstance"] = item["delete_with_instance"].(bool)
			disksMap["Encrypted"] = item["encrypted"].(bool)
			disksMap["Size"] = item["size"].(int)

			if category, ok := item["category"].(string); ok && category != "" {
				disksMap["Category"] = category
			}

			if name, ok := item["name"].(string); ok && name != "" {
				disksMap["DiskName"] = name
			}

			if kmsKeyId, ok := item["kms_key_id"].(string); ok && kmsKeyId != "" {
				disksMap["KMSKeyId"] = kmsKeyId
			}

			if snapshotId, ok := item["snapshot_id"].(string); ok && snapshotId != "" {
				disksMap["SnapshotId"] = snapshotId
			}

			if description, ok := item["description"].(string); ok && description != "" {
				disksMap["Description"] = description
			}

			if autoSnapshotPolicyId, ok := item["auto_snapshot_policy_id"].(string); ok && autoSnapshotPolicyId != "" {
				disksMap["AutoSnapshotPolicyId"] = autoSnapshotPolicyId
			}

			if device, ok := item["device"].(string); ok && device != "" {
				disksMap["Device"] = device
			}

			if performanceLevel, ok := item["performance_level"].(string); ok && performanceLevel != "" && disksMap["Category"] == string(DiskCloudESSD) {
				disksMap["PerformanceLevel"] = performanceLevel
			}

			if disksMap["Category"] == string(DiskEphemeralSSD) {
				disksMap["DeleteWithInstance"] = ""
			}

			disksMaps = append(disksMaps, disksMap)
		}
		request["DataDisk"] = disksMaps
	}

	networkInterfacesMaps := make([]map[string]interface{}, 0)

	_, networkInterfaceTrafficModeOk := d.GetOk("network_interface_traffic_mode")
	_, networkCardIndexOk := d.GetOkExists("network_card_index")
	_, queuePairNumberOk := d.GetOkExists("queue_pair_number")

	if networkInterfaceTrafficModeOk || networkCardIndexOk || queuePairNumberOk {
		primaryNetworkInterfacesMap := make(map[string]interface{})
		primaryNetworkInterfacesMap["InstanceType"] = "Primary"

		if v, ok := d.GetOk("security_groups"); ok {
			// At present, the classic network instance does not support multi sg in runInstances
			sgs := expandStringList(v.(*schema.Set).List())
			if d.Get("vswitch_id").(string) == "" && len(sgs) > 0 {
				primaryNetworkInterfacesMap["SecurityGroupId"] = sgs[0]
			} else {
				primaryNetworkInterfacesMap["SecurityGroupIds"] = sgs
			}
		}

		if vswitchValue != "" {
			primaryNetworkInterfacesMap["VSwitchId"] = vswitchValue

			if v, ok := d.GetOk("private_ip"); ok {
				primaryNetworkInterfacesMap["PrimaryIpAddress"] = v
			}
		}

		if v, ok := d.GetOk("ipv6_addresses"); ok {
			primaryNetworkInterfacesMap["Ipv6Address"] = v.(*schema.Set).List()
		}

		if v, ok := d.GetOkExists("ipv6_address_count"); ok {
			primaryNetworkInterfacesMap["Ipv6AddressCount"] = v
		}

		if v, ok := d.GetOk("network_interface_traffic_mode"); ok {
			primaryNetworkInterfacesMap["NetworkInterfaceTrafficMode"] = v
		}

		if v, ok := d.GetOkExists("network_card_index"); ok {
			primaryNetworkInterfacesMap["NetworkCardIndex"] = v
		}

		if v, ok := d.GetOkExists("queue_pair_number"); ok {
			primaryNetworkInterfacesMap["QueuePairNumber"] = v
		}

		networkInterfacesMaps = append(networkInterfacesMaps, primaryNetworkInterfacesMap)
	} else {
		if vswitchValue != "" {
			request["VSwitchId"] = vswitchValue

			if v, ok := d.GetOk("private_ip"); ok {
				request["PrivateIpAddress"] = v
			}
		}

		if v, ok := d.GetOk("security_groups"); ok {
			// At present, the classic network instance does not support multi sg in runInstances
			sgs := expandStringList(v.(*schema.Set).List())
			if d.Get("vswitch_id").(string) == "" && len(sgs) > 0 {
				request["SecurityGroupId"] = sgs[0]
			} else {
				request["SecurityGroupIds"] = sgs
			}
		}

		if v, ok := d.GetOk("ipv6_addresses"); ok {
			request["Ipv6Address"] = v.(*schema.Set).List()
		}

		if v, ok := d.GetOkExists("ipv6_address_count"); ok {
			request["Ipv6AddressCount"] = v
		}
	}

	if v, ok := d.GetOk("network_interfaces"); ok {
		for _, networkInterfaces := range v.([]interface{}) {
			secondaryNetworkInterfacesMap := make(map[string]interface{})
			secondaryNetworkInterfacesArg := networkInterfaces.(map[string]interface{})

			if networkInterfaceId, ok := secondaryNetworkInterfacesArg["network_interface_id"]; ok && fmt.Sprint(networkInterfaceId) != "" {
				secondaryNetworkInterfacesMap["NetworkInterfaceId"] = networkInterfaceId
			} else {
				secondaryNetworkInterfacesMap["InstanceType"] = "Secondary"

				if vSwitchId, ok := secondaryNetworkInterfacesArg["vswitch_id"]; ok {
					secondaryNetworkInterfacesMap["VSwitchId"] = vSwitchId
				}

				if networkInterfaceTrafficMode, ok := secondaryNetworkInterfacesArg["network_interface_traffic_mode"]; ok {
					secondaryNetworkInterfacesMap["NetworkInterfaceTrafficMode"] = networkInterfaceTrafficMode
				}

				isSupported, err := ecsService.isSupportedNetworkCardIndex(fmt.Sprint(request["InstanceType"]))
				if err != nil {
					return WrapError(err)
				}

				if networkCardIndex, ok := secondaryNetworkInterfacesArg["network_card_index"]; ok && isSupported {
					secondaryNetworkInterfacesMap["NetworkCardIndex"] = networkCardIndex
				}

				if queuePairNumber, ok := secondaryNetworkInterfacesArg["queue_pair_number"]; ok && fmt.Sprint(queuePairNumber) != "0" {
					secondaryNetworkInterfacesMap["QueuePairNumber"] = queuePairNumber
				}

				if securityGroupIds, ok := secondaryNetworkInterfacesArg["security_group_ids"]; ok {
					secondaryNetworkInterfacesMap["SecurityGroupIds"] = securityGroupIds
				}
			}

			networkInterfacesMaps = append(networkInterfacesMaps, secondaryNetworkInterfacesMap)
		}
	}

	if len(networkInterfacesMaps) > 0 {
		request["NetworkInterface"] = networkInterfacesMaps
	}

	networkOptionsMap := make(map[string]interface{})

	if v, ok := d.GetOkExists("enable_jumbo_frame"); ok {
		networkOptionsMap["EnableJumboFrame"] = v
	}

	if len(networkOptionsMap) > 0 {
		request["NetworkOptions"] = networkOptionsMap
	}

	if v, ok := d.GetOk("hpc_cluster_id"); ok {
		request["HpcClusterId"] = v
	}

	if v, ok := d.GetOk("deployment_set_id"); ok {
		request["DeploymentSetId"] = v
	}

	if v, ok := d.GetOk("http_tokens"); ok {
		request["HttpTokens"] = v
	}

	if v, ok := d.GetOk("http_endpoint"); ok {
		request["HttpEndpoint"] = v
	}

	if v, ok := d.GetOk("http_put_response_hop_limit"); ok {
		request["HttpPutResponseHopLimit"] = v
	}

	if d.Get("is_outdated").(bool) {
		request["IoOptimized"] = "none"
	}

	if v, ok := d.GetOkExists("spot_duration"); ok {
		request["SpotDuration"] = v
	}

	if v, ok := d.GetOk("dedicated_host_id"); ok {
		request["DedicatedHostId"] = v
	}

	if v, ok := d.GetOk("image_options"); ok {
		for _, raw := range v.(*schema.Set).List() {
			imageOptionsArg := raw.(map[string]interface{})
			if v, ok := imageOptionsArg["login_as_non_root"]; ok {
				request["ImageOptions.LoginAsNonRoot"] = v
			}
		}
	}

	wait := incrementalWait(1*time.Second, 1*time.Second)
	err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError {
		response, err = client.RpcPost("Ecs", "2014-05-26", action, nil, request, false)
		if err != nil {
			if NeedRetry(err) || IsExpectedErrors(err, []string{"IncorrectVSwitchStatus"}) {
				wait()
				return resource.RetryableError(err)
			}
			return resource.NonRetryableError(err)
		}
		return nil
	})
	addDebug(action, response, request)

	if err != nil {
		return WrapErrorf(err, DefaultErrorMsg, "alicloud_instance", action, AlibabaCloudSdkGoERROR)
	}

	d.SetId(fmt.Sprint(response["InstanceIdSets"].(map[string]interface{})["InstanceIdSet"].([]interface{})[0]))

	stateConf := BuildStateConf([]string{"Pending", "Starting", "Stopped"}, []string{"Running"}, d.Timeout(schema.TimeoutCreate), 10*time.Second, ecsService.InstanceStateRefreshFunc(d.Id(), []string{"Stopping"}))
	if _, err := stateConf.WaitForState(); err != nil {
		return WrapErrorf(err, IdMsg, d.Id())
	}

	return resourceAliCloudInstanceUpdate(d, meta)
}