diff --git a/.gitignore b/.gitignore index 86758081..fa052642 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ .idea/ bin/ examples/secret.yaml +config/bootstrap-master.yaml +config/bootstrap-worker.yaml + + diff --git a/Makefile b/Makefile index 8c195c78..aa6eb8a9 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,7 @@ bin: ##@ Development CONTROLLER_GEN = $(shell pwd)/bin/controller-gen controller-gen: ## Download controller-gen locally if necessary. - $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.4.1) + $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.7.0) deepcopy: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. diff --git a/config/master-machine-with-tags.yaml b/config/master-machine-with-tags.yaml new file mode 100644 index 00000000..f8de1bf8 --- /dev/null +++ b/config/master-machine-with-tags.yaml @@ -0,0 +1,52 @@ +--- +apiVersion: machine.openshift.io/v1beta1 +kind: Machine +metadata: + name: master-machine + namespace: default + labels: + machine.openshift.io/cluster-api-cluster: alibabacloud-actuator-k8s +spec: + metadata: + labels: + node-role.kubernetes.io/master: "" + providerSpec: + value: + apiVersion: alibabacloudproviderconfig.openshift.io/v1alpha1 + kind: AlibabaCloudMachineProviderConfig + instanceType: FILLIN + imageId: FILLIN + regionId: FILLIN + zoneId: FILLIN + securityGroups: + - tags: + - key: Name + value: ocp-test-sg + - key: "kubernetes.io/cluster/abc-def" + value: owned + - key: OCP + value: ISVAlibaba + vpcId: FILLIN + vSwitch: + tags: + - key: Name + value: ocp-test-vswitch + - key: "kubernetes.io/cluster/abc-def" + value: owned + - key: OCP + value: ISVAlibaba + systemDiskCategory: FILLIN + systemDiskSize: FILLIN + internetMaxBandwidthOut: FILLIN + password: FILLIN + tags: + - key: openshift-node-group-config + value: node-config-node + - key: host-type + value: node + - key: sub-host-type + value: default + userDataSecret: + name: master-user-data-secret + credentialsSecret: + name: alibabacloud-credentials-secret diff --git a/config/worker-machine-with-tags.yaml b/config/worker-machine-with-tags.yaml new file mode 100644 index 00000000..a5018a81 --- /dev/null +++ b/config/worker-machine-with-tags.yaml @@ -0,0 +1,52 @@ +--- +apiVersion: machine.openshift.io/v1beta1 +kind: Machine +metadata: + name: worker-machine + namespace: default + labels: + machine.openshift.io/cluster-api-cluster: alicloud-actuator-k8s +spec: + metadata: + labels: + node-role.kubernetes.io/infra: "" + providerSpec: + value: + apiVersion: alicloudproviderconfig.openshift.io/v1alpha1 + kind: AlibabaCloudMachineProviderConfig + instanceType: FILLIN + imageId: FILLIN + regionId: FILLIN + zoneId: FILLIN + securityGroups: + - tags: + - key: Name + value: ocp-test-sg + - key: "kubernetes.io/cluster/abc-def" + value: owned + - key: OCP + value: ISVAlibaba + vpcId: FILLIN + vSwitch: + tags: + - key: Name + value: ocp-test-vswitch + - key: "kubernetes.io/cluster/abc-def" + value: owned + - key: OCP + value: ISVAlibaba + systemDiskCategory: FILLIN + systemDiskSize: FILLIN + internetMaxBandwidthOut: FILLIN + password: FILLIN + tags: + - key: openshift-node-group-config + value: node-config-node + - key: host-type + value: node + - key: sub-host-type + value: default + userDataSecret: + name: worker-user-data-secret + credentialsSecret: + name: alibabacloud-credentials-secret diff --git a/pkg/actuators/machine/instances.go b/pkg/actuators/machine/instances.go index 16ea1b3a..af1e2d35 100644 --- a/pkg/actuators/machine/instances.go +++ b/pkg/actuators/machine/instances.go @@ -24,6 +24,8 @@ import ( "strings" "time" + "github.com/aliyun/alibaba-cloud-sdk-go/services/vpc" + "k8s.io/klog" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" @@ -85,12 +87,18 @@ func runInstances(machine *machinev1.Machine, machineProviderConfig *alibabaclou return nil, mapierrors.InvalidMachineConfiguration("error getting ImageID: %v", err) } - // SecurgityGroupId - securityGroupID, err := getSecurityGroupID(machineKey, machineProviderConfig, client) + // SecurgityGroupIds + securityGroupIDs, err := getSecurityGroupIDs(machineKey, machineProviderConfig, client) if err != nil { return nil, mapierrors.InvalidMachineConfiguration("error getting security groups ID: %v", err) } + // VSwitchID + vSwitchID, err := getVSwitchID(machineKey, machineProviderConfig, client) + if err != nil { + return nil, mapierrors.InvalidMachineConfiguration("error getting vswitch ID: %v", err) + } + clusterID, ok := getClusterID(machine) if !ok { klog.Errorf("Unable to get cluster ID for machine: %q", machine.Name) @@ -105,8 +113,13 @@ func runInstances(machine *machinev1.Machine, machineProviderConfig *alibabaclou // RegionID runInstancesRequest.RegionId = machineProviderConfig.RegionID - // SecurityGroupID - runInstancesRequest.SecurityGroupId = securityGroupID + // ResourceGroupID + if machineProviderConfig.ResourceGroupID != "" { + runInstancesRequest.ResourceGroupId = machineProviderConfig.ResourceGroupID + } + + // SecurityGroupIDs + runInstancesRequest.SecurityGroupIds = securityGroupIDs // Add tags to the created machine tagList := buildTagList(machine.Name, clusterID, machineProviderConfig.Tags) @@ -147,7 +160,7 @@ func runInstances(machine *machinev1.Machine, machineProviderConfig *alibabaclou } // VswitchId - runInstancesRequest.VSwitchId = machineProviderConfig.VSwitchID + runInstancesRequest.VSwitchId = vSwitchID // SystemDisk runInstancesRequest.SystemDiskCategory = machineProviderConfig.SystemDiskCategory @@ -363,68 +376,142 @@ func getImageID(machine runtimeclient.ObjectKey, machineProviderConfig *alibabac return image.ImageId, nil } -func getSecurityGroupID(machine runtimeclient.ObjectKey, machineProviderConfig *alibabacloudproviderv1.AlibabaCloudMachineProviderConfig, client alibabacloudClient.Client) (string, error) { +func getSecurityGroupIDs(machine runtimeclient.ObjectKey, machineProviderConfig *alibabacloudproviderv1.AlibabaCloudMachineProviderConfig, client alibabacloudClient.Client) (*[]string, error) { klog.Infof("%s validate security group in region %s", machineProviderConfig.SecurityGroupID, machineProviderConfig.RegionID) + var securityGroupIDs []string + + // If SecurityGroupID is assigned, use it directly + if machineProviderConfig.SecurityGroupID != "" { + securityGroupIDs = append(securityGroupIDs, machineProviderConfig.SecurityGroupID) + } else { + // Otherwise, the query securityGroupIDs by the tags + for _, sg := range machineProviderConfig.SecurityGroups { + if sg.ID != "" { + securityGroupIDs = append(securityGroupIDs, sg.ID) + } else { + if sg.Tags != nil { + request := ecs.CreateDescribeSecurityGroupsRequest() + if machineProviderConfig.VpcID != "" { + request.VpcId = machineProviderConfig.VpcID + } + if machineProviderConfig.ResourceGroupID != "" { + request.ResourceGroupId = machineProviderConfig.ResourceGroupID + } + request.RegionId = machineProviderConfig.RegionID + request.Tag = buildDescribeSecurityGroupsTag(sg.Tags) + request.Scheme = "https" + + response, err := client.DescribeSecurityGroups(request) + if err != nil { + metrics.RegisterFailedInstanceCreate(&metrics.MachineLabels{ + Name: machine.Name, + Namespace: machine.Namespace, + Reason: err.Error(), + }) + klog.Errorf("error describing securitygroup: %v", err) + return nil, fmt.Errorf("error describing securitygroup: %v", err) + } + + if len(response.SecurityGroups.SecurityGroup) < 1 { + klog.Errorf("no securitygroup for given tags not found") + return nil, fmt.Errorf("no securitygroup for given tags not found") + } + + for _, sg := range response.SecurityGroups.SecurityGroup { + securityGroupIDs = append(securityGroupIDs, sg.SecurityGroupId) + } + } + } + } + } - request := ecs.CreateDescribeSecurityGroupsRequest() - request.VpcId = machineProviderConfig.VpcID - request.RegionId = machineProviderConfig.RegionID - request.SecurityGroupId = machineProviderConfig.SecurityGroupID - request.Scheme = "https" + return &securityGroupIDs, nil +} - response, err := client.DescribeSecurityGroups(request) - if err != nil { - metrics.RegisterFailedInstanceCreate(&metrics.MachineLabels{ - Name: machine.Name, - Namespace: machine.Namespace, - Reason: err.Error(), - }) - klog.Errorf("error describing securitygroup: %v", err) - return "", fmt.Errorf("error describing securitygroup: %v", err) +func getMaxInstancesBySecurityGroupType(securityGroupType string) int { + switch securityGroupType { + case SecurityGroupTypeNoraml: + return MaxInstanceOfSecurityGroupTypeNoraml + case SecurityGroupTypeEnterprise: + return MaxInstanceOfSecurityGroupTypeEnterprise + default: + return MaxInstanceOfSecurityGroupTypeNoraml } +} + +func buildDescribeSecurityGroupsTag(tags []alibabacloudproviderv1.Tag) *[]ecs.DescribeSecurityGroupsTag { + describeSecurityGroupsTag := make([]ecs.DescribeSecurityGroupsTag, len(tags)) - if len(response.SecurityGroups.SecurityGroup) < 1 { - klog.Errorf("no securitygroup for given filters not found") - return "", fmt.Errorf("no securitygroup for given filters not found") + for index, tag := range tags { + describeSecurityGroupsTag[index] = ecs.DescribeSecurityGroupsTag{ + Key: tag.Key, + Value: tag.Value, + } } - securityGroup := response.SecurityGroups.SecurityGroup[0] + return &describeSecurityGroupsTag +} - // Query how many instances are under the security group - describeInstancesRequest := ecs.CreateDescribeInstancesRequest() - describeInstancesRequest.RegionId = machineProviderConfig.RegionID - describeInstancesRequest.SecurityGroupId = securityGroup.SecurityGroupId - describeInstancesRequest.PageSize = requests.NewInteger(1) - describeInstancesRequest.Scheme = "https" +func getVSwitchID(machine runtimeclient.ObjectKey, machineProviderConfig *alibabacloudproviderv1.AlibabaCloudMachineProviderConfig, client alibabacloudClient.Client) (string, error) { + klog.Infof("validate vswitch in region %s", machineProviderConfig.RegionID) + vSwitchID := "" + if machineProviderConfig.VSwitchID != "" { + vSwitchID = machineProviderConfig.VSwitchID + } - describeInstancesResponse, err := client.DescribeInstances(describeInstancesRequest) - if err != nil { - metrics.RegisterFailedInstanceCreate(&metrics.MachineLabels{ - Name: machine.Name, - Namespace: machine.Namespace, - Reason: err.Error(), - }) - klog.Errorf("error describing instances: %v", err) - return "", fmt.Errorf("error describing instances: %v", err) + if machineProviderConfig.VSwitch != nil { + if machineProviderConfig.VSwitch.ID != "" { + vSwitchID = machineProviderConfig.VSwitch.ID + } else { + if machineProviderConfig.VSwitch.Tags != nil { + describeVSwitchesRequest := vpc.CreateDescribeVSwitchesRequest() + describeVSwitchesRequest.Scheme = "https" + + describeVSwitchesRequest.RegionId = machineProviderConfig.RegionID + if machineProviderConfig.VpcID != "" { + describeVSwitchesRequest.VpcId = machineProviderConfig.VpcID + } + describeVSwitchesRequest.Tag = buildDescribeVSwitchesTag(machineProviderConfig.VSwitch.Tags) + + describeVSwitchesResponse, err := client.DescribeVSwitches(describeVSwitchesRequest) + if err != nil { + metrics.RegisterFailedInstanceCreate(&metrics.MachineLabels{ + Name: machine.Name, + Namespace: machine.Namespace, + Reason: err.Error(), + }) + klog.Errorf("error describing vswitches: %v", err) + return "", fmt.Errorf("error describing vswitches: %v", err) + } + + if len(describeVSwitchesResponse.VSwitches.VSwitch) < 1 { + klog.Errorf("no vswitches for given tags not found") + return "", fmt.Errorf("no vswitches for given tags not found") + } + + vSwitchID = describeVSwitchesResponse.VSwitches.VSwitch[0].VSwitchId + } + } } - maxInstances := getMaxInstancesBySecurityGroupType(securityGroup.SecurityGroupType) - if describeInstancesResponse.TotalCount >= maxInstances { - return "", fmt.Errorf("the maximum number of instances in the security group has been exceeded: %d", maxInstances) + if vSwitchID == "" { + return "", fmt.Errorf("no vswitches were found") } - return securityGroup.SecurityGroupId, nil + return vSwitchID, nil } -func getMaxInstancesBySecurityGroupType(securityGroupType string) int { - switch securityGroupType { - case SecurityGroupTypeNoraml: - return MaxInstanceOfSecurityGroupTypeNoraml - case SecurityGroupTypeEnterprise: - return MaxInstanceOfSecurityGroupTypeEnterprise - default: - return MaxInstanceOfSecurityGroupTypeNoraml +func buildDescribeVSwitchesTag(tags []alibabacloudproviderv1.Tag) *[]vpc.DescribeVSwitchesTag { + describeVSwitchesTag := make([]vpc.DescribeVSwitchesTag, len(tags)) + + for index, tag := range tags { + describeVSwitchesTag[index] = vpc.DescribeVSwitchesTag{ + Key: tag.Key, + Value: tag.Value, + } } + + return &describeVSwitchesTag } // buildTagList compile a list of ecs tags from machine provider spec and infrastructure object platform spec diff --git a/pkg/actuators/machine/reconciler.go b/pkg/actuators/machine/reconciler.go index 758e59a4..3c8e6e1e 100644 --- a/pkg/actuators/machine/reconciler.go +++ b/pkg/actuators/machine/reconciler.go @@ -309,11 +309,7 @@ func (r *Reconciler) setProviderID(instance *ecs.Instance) error { return nil } - providerID := fmt.Sprintf("alibabacloud:///%s/%s/%s", instance.RegionId, instance.ZoneId, instance.InstanceId) - // If resourceGroupId is not empty, set to providerId - if instance.ResourceGroupId != "" { - providerID = fmt.Sprintf("alibabacloud:///%s/%s/%s/%s", instance.ResourceGroupId, instance.RegionId, instance.ZoneId, instance.InstanceId) - } + providerID := fmt.Sprintf("alicloud://%s.%s", instance.RegionId, instance.InstanceId) if existingProviderID != nil && *existingProviderID == providerID { klog.Infof("%s: ProviderID already set in the machine Spec with value:%s", r.machine.Name, *existingProviderID) diff --git a/pkg/actuators/machineset/controller.go b/pkg/actuators/machineset/controller.go index 420e1893..f8509b4a 100644 --- a/pkg/actuators/machineset/controller.go +++ b/pkg/actuators/machineset/controller.go @@ -118,14 +118,15 @@ func (r *Reconciler) reconcile(machineSet *machinev1.MachineSet) (ctrl.Result, e if err != nil { return ctrl.Result{}, mapierrors.InvalidMachineConfiguration("failed to get providerConfig: %v", err) } - instanceType, ok := InstanceTypes[providerConfig.InstanceType] - if !ok { - klog.Error("Unable to set scale from zero annotations: unknown instance type: %s", providerConfig.InstanceType) - klog.Error("Autoscaling from zero will not work. To fix this, manually populate machine annotations for your instance type: %v", []string{cpuKey, memoryKey, gpuKey}) + + instanceType, err := r.getInstanceType(machineSet, providerConfig) + if err != nil { + klog.Errorf("Unable to set scale from zero annotations: unknown instance type: %s", providerConfig.InstanceType) + klog.Errorf("Autoscaling from zero will not work. To fix this, manually populate machine annotations for your instance type: %v", []string{cpuKey, memoryKey, gpuKey}) // Returning no error to prevent further reconciliation, as user intervention is now required but emit an informational event r.recorder.Eventf(machineSet, corev1.EventTypeWarning, "FailedUpdate", "Failed to set autoscaling from zero annotations, instance type unknown") - return ctrl.Result{}, nil + return ctrl.Result{}, mapierrors.InvalidMachineConfiguration("failed to get instance type: %v", err) } if machineSet.Annotations == nil { diff --git a/pkg/actuators/machineset/ecs_instance_types.go b/pkg/actuators/machineset/ecs_instance_types.go index fbeca5ea..06e3dfd1 100644 --- a/pkg/actuators/machineset/ecs_instance_types.go +++ b/pkg/actuators/machineset/ecs_instance_types.go @@ -13,6 +13,16 @@ limitations under the License. package machineset +import ( + "fmt" + + alibabacloudproviderv1 "github.com/AliyunContainerService/cluster-api-provider-alibabacloud/pkg/apis/alibabacloudprovider/v1beta1" + alibabacloudClient "github.com/AliyunContainerService/cluster-api-provider-alibabacloud/pkg/client" + "github.com/aliyun/alibaba-cloud-sdk-go/services/ecs" + machinev1 "github.com/openshift/machine-api-operator/pkg/apis/machine/v1beta1" + "k8s.io/klog" +) + type instanceType struct { InstanceType string VCPU int64 @@ -20,13 +30,42 @@ type instanceType struct { GPU int64 } -// InstanceTypes is a map of ecs resources -// TODO next version will be supported -var InstanceTypes = map[string]*instanceType{ - "ecs.c6.2xlarge": { - InstanceType: "ecs.c6.2xlarge", - VCPU: 8, - MemoryMb: 16384, - GPU: 0, - }, +// Check whether instanceType is correct, and return the corresponding CPU, MEM, and GPU data +func (r *Reconciler) getInstanceType(machineSet *machinev1.MachineSet, providerSpec *alibabacloudproviderv1.AlibabaCloudMachineProviderConfig) (*instanceType, error) { + credentialsSecretName := "" + if providerSpec.CredentialsSecret != nil { + credentialsSecretName = providerSpec.CredentialsSecret.Name + } + + aliClient, err := alibabacloudClient.NewClient(r.Client, credentialsSecretName, machineSet.Namespace, providerSpec.RegionID, nil) + if err != nil { + klog.Errorf("Failed to create alibabacloud client: %v", err) + return nil, err + } + + instanceTypes := []string{providerSpec.InstanceType} + describeInstanceTypesRequest := ecs.CreateDescribeInstanceTypesRequest() + describeInstanceTypesRequest.RegionId = providerSpec.RegionID + describeInstanceTypesRequest.Scheme = "https" + describeInstanceTypesRequest.InstanceTypes = &instanceTypes + + response, err := aliClient.DescribeInstanceTypes(describeInstanceTypesRequest) + if err != nil { + klog.Errorf("Failed to describeInstanceTypes: %v", err) + return nil, err + } + + if len(response.InstanceTypes.InstanceType) <= 0 { + klog.Errorf("%s no instanceType for given filters not found", providerSpec.InstanceType) + return nil, fmt.Errorf("%s no instanceType for given filters not found ", providerSpec.InstanceType) + } + + it := response.InstanceTypes.InstanceType[0] + + return &instanceType{ + InstanceType: it.InstanceType, + VCPU: int64(it.CpuCoreCount), + MemoryMb: int64(it.MemorySize * 1024), + GPU: int64(it.GPUAmount), + }, nil } diff --git a/pkg/apis/alibabacloudprovider/v1beta1/alibabacloudmachineproviderconfig_types.go b/pkg/apis/alibabacloudprovider/v1beta1/alibabacloudmachineproviderconfig_types.go index 170cbc7f..2b30a38d 100644 --- a/pkg/apis/alibabacloudprovider/v1beta1/alibabacloudmachineproviderconfig_types.go +++ b/pkg/apis/alibabacloudprovider/v1beta1/alibabacloudmachineproviderconfig_types.go @@ -39,7 +39,6 @@ type AlibabaCloudMachineProviderConfig struct { // More detail about alibabacloud ECS // https://www.alibabacloud.com/help/doc-detail/25499.htm?spm=a2c63.l28256.b99.727.496d7453jF7Moz - //The instance type of the instance. InstanceType string `json:"instanceType"` @@ -58,6 +57,11 @@ type AlibabaCloudMachineProviderConfig struct { // The ID of the security group to which to assign the instance. Instances in the same security group can communicate with each other. SecurityGroupID string `json:"securityGroupId"` + // SecurityGroups is an array of references to security groups which to assign the instance. The valid values of N vary based on the + // maximum number of security groups to which an instance can belong. For more information, see the "Security group limits" section in Limits. + // https://www.alibabacloud.com/help/doc-detail/101348.htm?spm=a2c63.p38356.879954.48.78f0199aX3dfIE + SecurityGroups []ResourceTagReference `json:"securityGroups,omitempty"` + //The name of the instance. The name must be 2 to 128 characters in length. It must start with a letter and cannot start with //http:// or https://. It can contain letters, digits, colons (:), underscores (_), periods (.), and hyphens (-). If you do not specify //this parameter, the instance ID is used as the instance name. @@ -69,47 +73,38 @@ type AlibabaCloudMachineProviderConfig struct { InternetChargeType string `json:"internetChargeType,omitempty"` //Specifies whether to enable auto-renewal for the instance. This parameter is valid only when the InstanceChargeType parameter is set to PrePaid. Default value: false. Valid values: - // //true: enables automatic renewal for the instance. //false: does not enable auto-renewal for the instance. AutoRenew bool `json:"autoRenew,omitempty"` //The auto-renewal period of the instance. This parameter is required when AutoRenew is set to true. - // //If PeriodUnit is set to Month, the valid values of the AutoRenewPeriod parameter are 1, 2, 3, 6, and 12. AutoRenewPeriod int `json:"autoRenewPeriod,omitempty"` //The maximum inbound public bandwidth. Unit: Mbit/s. Valid values: - // //When the purchased outbound public bandwidth is less than or equal to 10 Mbit/s, the valid values of this parameter are 1 to 10, and the default value is 10. //When the purchased outbound public bandwidth is greater than 10, the valid values are 1 to the InternetMaxBandwidthOut value, and the default value is the InternetMaxBandwidthOut value. InternetMaxBandwidthIn int `json:"internetMaxBandwidthIn,omitempty"` //The maximum outbound public bandwidth. Unit: Mbit/s. Valid values: 0 to 100. - // //Default value: 0. InternetMaxBandwidthOut int `json:"internetMaxBandwidthOut,omitempty"` //The hostname of the instance. - // //The hostname cannot start or end with a period (.) or a hyphen (-).It cannot contain consecutive periods (,) or hyphens (-). //For Windows instances, the hostname must be 2 to 15 characters in length and can contain letters, digits, and hyphens (-). It cannot contain periods (.) or contain only digits. //For an instance that runs one of other operating systems such as Linux, the hostname must be 2 to 64 characters in length. You can use periods (.) to separate the hostname into multiple segments. Each segment can contain letters, digits, and hyphens (-). HostName string `json:"hostName,omitempty"` //The password of the instance. The password must be 8 to 30 characters in length and include at least three of the following character types: uppercase letters, lowercase letters, digits, and special characters. Special characters include: - // - // //( ) ` ~ ! @ # $ % ^ & * - _ + = | { } [ ] : ; ' < > , . ? / //Take note of the following items: - // //For security reasons, we recommend that you use HTTPS to send requests if the Password parameter is specified. //Passwords of Windows instances cannot start with a forward slash (/). //Passwords cannot be set for instances that run some types of operating systems such as Others Linux and Fedora CoreOS. For these instances, only key pairs can be set. Password string `json:"password,omitempty"` //The category of the system disk. Valid values: - // //cloud_essd: ESSD. When the parameter is set to this value, you can use the SystemDisk.PerformanceLevel parameter to specify the performance level of the disk. //cloud_efficiency: ultra disk. //cloud_ssd: standard SSD. @@ -118,7 +113,6 @@ type AlibabaCloudMachineProviderConfig struct { SystemDiskCategory string `json:"systemDiskCategory,omitempty"` //The performance level of the ESSD used as the system disk. Default value: PL1. Valid values: - // //PL0: A single ESSD can deliver up to 10,000 random read/write IOPS. //PL1: A single ESSD can deliver up to 50,000 random read/write IOPS. //PL2: A single ESSD can deliver up to 100,000 random read/write IOPS. @@ -127,64 +121,58 @@ type AlibabaCloudMachineProviderConfig struct { SystemDiskPerformanceLevel string `json:"systemDiskPerformanceLevel,omitempty"` //The name of the system disk. The name must be 2 to 128 characters in length. It must start with a letter and cannot start with http:// or https://. It can contain letters, digits, colons (:), underscores (_), and hyphens (-). - // //This parameter is empty by default. SystemDiskDiskName string `json:"systemDiskDiskName,omitempty"` //The size of the system disk. Unit: GiB. Valid values: 20 to 500. - // //The value must be at least 20 and greater than or equal to the size of the image. - // //The default value is 40 or the size of the image, depending on whichever is greater. SystemDiskSize int `json:"systemDiskSize,omitempty"` //The description of the system disk. The description must be 2 to 256 characters in length and cannot start with http:// or https://. - // //This parameter is empty by default. SystemDiskDescription string `json:"systemDiskDescription,omitempty"` DataDisks []DataDisk `json:"dataDisk,omitempty"` //The description of the instance. The description must be 2 to 256 characters in length and cannot start with http:// or https://. - // //This parameter is empty by default. Description string `json:"description,omitempty"` //The ID of the vSwitch to which to connect the instance. This parameter is required when you create an instance of the VPC type. You can call the DescribeVSwitches operation to query the created vSwitches. VSwitchID string `json:"vSwitchId,omitempty"` + //VSwitch is a reference to the vswitch to use for this instance + //This parameter is required when you create an instance of the VPC type. + //You can call the DescribeVSwitches operation to query the created vSwitches. + VSwitch *ResourceTagReference `json:"vSwitch,omitempty"` + //Specifies whether the instance is I/O optimized. Valid values: - // //none: The instance is not I/O optimized. //optimized: The instance is I/O optimized. //For retired instance types, the default value is none. For more information, see Retired instance types. - // //For other instance types, the default value is optimized. IoOptimized string `json:"ioOptimized,omitempty"` //The billing method of the instance. Default value: PostPaid. Valid values: - // //PrePaid: subscription. If you set this parameter to PrePaid, make sure that you have sufficient balance or credit within your account. Otherwise, an InvalidPayMethod error is returned. //PostPaid: pay-as-you-go. InstanceChargeType string `json:"instanceChargeType,omitempty"` //The subscription period of the instance. The unit is specified by the PeriodUnit parameter. This parameter is valid and required only when InstanceChargeType is set to PrePaid. If the DedicatedHostID parameter is specified, the subscription period of the instance cannot be longer than that of the dedicated host. Valid values: - // //Valid values when PeriodUnit is set to Month: 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 24, 36, 48, and 60. Period int `json:"period,omitempty"` //The unit of the subscription period. Default value: Month. - // //Set the value to Month. PeriodUnit string `json:"periodUnit,omitempty"` - Tags []Tag `json:"tag,omitempty"` + Tags []Tag `json:"tags,omitempty"` //The user data of the instance. The user data must be encoded in Base64. The maximum size of raw data is 16 KB. UserData string `json:"userData,omitempty"` //The name of the key pair. - // //For Windows instances, this parameter is ignored and is empty by default. The Password parameter takes effect even if the KeyPairName parameter is specified. //For Linux instances, the password-based logon method is disabled by default. To make the instance more secure, we recommend that you use key pairs for logons. KeyPairName string `json:"keyPairName,omitempty"` @@ -192,9 +180,7 @@ type AlibabaCloudMachineProviderConfig struct { //The name of the instance Resource Access Management (RAM) role. You can call the ListRoles operation provided by RAM to query the instance RAM roles that you have created. RAMRoleName string `json:"ramRoleName,omitempty"` - // //Specifies whether to enable security hardening. Valid values: - // //Active: enables security hardening. This value is applicable only to public images. //Deactive: does not enable security hardening. This value is applicable to all images. SecurityEnhancementStrategy string `json:"securityEnhancementStrategy,omitempty"` @@ -203,29 +189,24 @@ type AlibabaCloudMachineProviderConfig struct { ResourceGroupID string `json:"resourceGroupId,omitempty"` //The release protection property of the instance. It specifies whether you can use the ECS console or call the DeleteInstance operation to manually release the instance. Default value: false. Valid values: - // //true: enables release protection. //false: disables release protection. DeletionProtection bool `json:"deletionProtection,omitempty"` //Specifies whether to associate the instance on a dedicated host with the dedicated host. Valid values: - // //default: does not associate the instance with the dedicated host. When you restart an instance in the No Fees for Stopped Instances (VPC-Connected) state, the instance is automatically deployed to another dedicated host in the automatic deployment resource pool if the available resources of the original dedicated host are insufficient. //host: associates the instance with the dedicated host. When you restart an instance in the No Fees for Stopped Instances (VPC-Connected) state, the instance still resides on the original dedicated host. If the available resources of the original dedicated host are insufficient, the instance fails to restart. //Default value: default. Affinity string `json:"affinity,omitempty"` //Specifies whether to create the instance on a dedicated host. Valid values: - // //default: creates the instance on a non-dedicated host. //host: creates the instance on a dedicated host. If you do not specify the DedicatedHostID parameter, Alibaba Cloud automatically selects a dedicated host for the instance. //Default value: default. Tenancy InstanceTenancy `json:"tenancy,omitempty"` //The ID of the dedicated host on which to create the instance. - // //You can call the DescribeDedicatedHosts operation to query the dedicated host list. - // //When the DedicatedHostID parameter is specified, the SpotStrategy and SpotPriceLimit parameters are ignored. This is because preemptible instances cannot be created on dedicated hosts. DedicatedHostID string `json:"dedicatedHostId"` @@ -238,6 +219,18 @@ type AlibabaCloudMachineProviderConfig struct { CredentialsSecret *corev1.LocalObjectReference `json:"credentialsSecret,omitempty"` } +// ResourceTagReference is a reference to a specific AlibabaCloud resource by ID, or tags. +// Only one of ID or Tags may be specified. Specifying more than one will result in +// a validation error. +type ResourceTagReference struct { + // ID of resource + // +optional + ID string `json:"id,omitempty"` + + // Tags is a set of tags used to identify a resource + Tags []Tag `json:"tags,omitempty"` +} + // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // AlibabaCloudMachineProviderConfigList contains a list of AlibabaCloudMachineProviderConfig diff --git a/pkg/apis/alibabacloudprovider/v1beta1/types.go b/pkg/apis/alibabacloudprovider/v1beta1/types.go index b2facec8..2397aa30 100644 --- a/pkg/apis/alibabacloudprovider/v1beta1/types.go +++ b/pkg/apis/alibabacloudprovider/v1beta1/types.go @@ -96,5 +96,5 @@ type DataDisk struct { // Tag The tags of ECS Instance type Tag struct { Value string `name:"value"` - Key string `name:"Key"` + Key string `name:"key"` } diff --git a/pkg/apis/alibabacloudprovider/v1beta1/zz_generated.deepcopy.go b/pkg/apis/alibabacloudprovider/v1beta1/zz_generated.deepcopy.go index b3a352a2..d60830ec 100644 --- a/pkg/apis/alibabacloudprovider/v1beta1/zz_generated.deepcopy.go +++ b/pkg/apis/alibabacloudprovider/v1beta1/zz_generated.deepcopy.go @@ -47,6 +47,13 @@ func (in *AlibabaCloudMachineProviderConfig) DeepCopyInto(out *AlibabaCloudMachi *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.SecurityGroups != nil { + in, out := &in.SecurityGroups, &out.SecurityGroups + *out = make([]ResourceTagReference, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } if in.DataDisks != nil { in, out := &in.DataDisks, &out.DataDisks *out = make([]DataDisk, len(*in)) @@ -54,6 +61,11 @@ func (in *AlibabaCloudMachineProviderConfig) DeepCopyInto(out *AlibabaCloudMachi (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.VSwitch != nil { + in, out := &in.VSwitch, &out.VSwitch + *out = new(ResourceTagReference) + (*in).DeepCopyInto(*out) + } if in.Tags != nil { in, out := &in.Tags, &out.Tags *out = make([]Tag, len(*in)) @@ -183,6 +195,26 @@ func (in *DataDisk) DeepCopy() *DataDisk { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceTagReference) DeepCopyInto(out *ResourceTagReference) { + *out = *in + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]Tag, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceTagReference. +func (in *ResourceTagReference) DeepCopy() *ResourceTagReference { + if in == nil { + return nil + } + out := new(ResourceTagReference) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Tag) DeepCopyInto(out *Tag) { *out = *in