//go:generate struct-markdown package ecs import ( "errors" "fmt" "os" "strings" "github.com/hashicorp/packer-plugin-sdk/communicator" "github.com/hashicorp/packer-plugin-sdk/template/config" "github.com/hashicorp/packer-plugin-sdk/template/interpolate" "github.com/hashicorp/packer-plugin-sdk/uuid" ) type RunConfig struct { AssociatePublicIpAddress bool `mapstructure:"associate_public_ip_address"` // ID of the zone to which the disk belongs. ZoneId string `mapstructure:"zone_id" required:"false"` // Whether an ECS instance is I/O optimized or not. If this option is not // provided, the value will be determined by product API according to what // `instance_type` is used. IOOptimized config.Trilean `mapstructure:"io_optimized" required:"false"` // Type of the instance. For values, see [Instance Type // Table](https://www.alibabacloud.com/help/doc-detail/25378.htm?spm=a3c0i.o25499en.a3.9.14a36ac8iYqKRA). // You can also obtain the latest instance type table by invoking the // [Querying Instance Type // Table](https://intl.aliyun.com/help/doc-detail/25620.htm?spm=a3c0i.o25499en.a3.6.Dr1bik) // interface. InstanceType string `mapstructure:"instance_type" required:"true"` Description string `mapstructure:"description"` // This is the base image id which you want to // create your customized images. AlicloudSourceImage string `mapstructure:"source_image" required:"true"` // Whether to force shutdown upon device // restart. The default value is `false`. // // If it is set to `false`, the system is shut down normally; if it is set to // `true`, the system is forced to shut down. ForceStopInstance bool `mapstructure:"force_stop_instance" required:"false"` // If this option is set to true, Packer // will not stop the instance for you, and you need to make sure the instance // will be stopped in the final provisioner command. Otherwise, Packer will // timeout while waiting the instance to be stopped. This option is provided // for some specific scenarios that you want to stop the instance by yourself. // E.g., Sysprep a windows which may shutdown the instance within its command. // The default value is false. DisableStopInstance bool `mapstructure:"disable_stop_instance" required:"false"` // ID of the security group to which a newly // created instance belongs. Mutual access is allowed between instances in one // security group. If not specified, the newly created instance will be added // to the default security group. If the default group doesn’t exist, or the // number of instances in it has reached the maximum limit, a new security // group will be created automatically. SecurityGroupId string `mapstructure:"security_group_id" required:"false"` // The security group name. The default value // is blank. [2, 128] English or Chinese characters, must begin with an // uppercase/lowercase letter or Chinese character. Can contain numbers, ., // _ or -. It cannot begin with `http://` or `https://`. SecurityGroupName string `mapstructure:"security_group_name" required:"false"` // User data to apply when launching the instance. Note // that you need to be careful about escaping characters due to the templates // being JSON. It is often more convenient to use user_data_file, instead. // Packer will not automatically wait for a user script to finish before // shutting down the instance this must be handled in a provisioner. UserData string `mapstructure:"user_data" required:"false"` // Path to a file that will be used for the user // data when launching the instance. UserDataFile string `mapstructure:"user_data_file" required:"false"` // VPC ID allocated by the system. VpcId string `mapstructure:"vpc_id" required:"false"` // The VPC name. The default value is blank. [2, 128] // English or Chinese characters, must begin with an uppercase/lowercase // letter or Chinese character. Can contain numbers, _ and -. The disk // description will appear on the console. Cannot begin with `http://` or // `https://`. VpcName string `mapstructure:"vpc_name" required:"false"` // Value options: 192.168.0.0/16 and // 172.16.0.0/16. When not specified, the default value is 172.16.0.0/16. CidrBlock string `mapstructure:"vpc_cidr_block" required:"false"` // The ID of the VSwitch to be used. VSwitchId string `mapstructure:"vswitch_id" required:"false"` // The ID of the VSwitch to be used. VSwitchName string `mapstructure:"vswitch_name" required:"false"` // Display name of the instance, which is a string of 2 to 128 Chinese or // English characters. It must begin with an uppercase/lowercase letter or // a Chinese character and can contain numerals, `.`, `_`, or `-`. The // instance name is displayed on the Alibaba Cloud console. If this // parameter is not specified, the default value is InstanceId of the // instance. It cannot begin with `http://` or `https://`. InstanceName string `mapstructure:"instance_name" required:"false"` // Internet charge type, which can be // `PayByTraffic` or `PayByBandwidth`. Optional values: // - `PayByBandwidth` // - `PayByTraffic` // // If this parameter is not specified, the default value is `PayByBandwidth`. // For the regions out of China, currently only support `PayByTraffic`, you // must set it manfully. InternetChargeType string `mapstructure:"internet_charge_type" required:"false"` // Maximum outgoing bandwidth to the // public network, measured in Mbps (Mega bits per second). // // Value range: // - `PayByBandwidth`: \[0, 100\]. If this parameter is not specified, API // automatically sets it to 0 Mbps. // - `PayByTraffic`: \[1, 100\]. If this parameter is not specified, an // error is returned. InternetMaxBandwidthOut int `mapstructure:"internet_max_bandwidth_out" required:"false"` // Timeout of creating snapshot(s). // The default timeout is 3600 seconds if this option is not set or is set // to 0. For those disks containing lots of data, it may require a higher // timeout value. WaitSnapshotReadyTimeout int `mapstructure:"wait_snapshot_ready_timeout" required:"false"` // Communicator settings Comm communicator.Config `mapstructure:",squash"` // If this value is true, packer will connect to // the ECS created through private ip instead of allocating a public ip or an // EIP. The default value is false. SSHPrivateIp bool `mapstructure:"ssh_private_ip" required:"false"` } func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { if c.Comm.SSHKeyPairName == "" && c.Comm.SSHTemporaryKeyPairName == "" && c.Comm.SSHPrivateKeyFile == "" && c.Comm.SSHPassword == "" && c.Comm.WinRMPassword == "" { c.Comm.SSHTemporaryKeyPairName = fmt.Sprintf("packer_%s", uuid.TimeOrderedUUID()) } // Validation errs := c.Comm.Prepare(ctx) if c.AlicloudSourceImage == "" { errs = append(errs, errors.New("A source_image must be specified")) } if strings.TrimSpace(c.AlicloudSourceImage) != c.AlicloudSourceImage { errs = append(errs, errors.New("The source_image can't include spaces")) } if c.InstanceType == "" { errs = append(errs, errors.New("An alicloud_instance_type must be specified")) } if c.UserData != "" && c.UserDataFile != "" { errs = append(errs, fmt.Errorf("Only one of user_data or user_data_file can be specified.")) } else if c.UserDataFile != "" { if _, err := os.Stat(c.UserDataFile); err != nil { errs = append(errs, fmt.Errorf("user_data_file not found: %s", c.UserDataFile)) } } return errs }