2019-05-31 08:27:41 -04:00
|
|
|
|
//go:generate struct-markdown
|
|
|
|
|
|
2017-03-03 03:56:17 -05:00
|
|
|
|
package ecs
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
2017-06-01 20:14:51 -04:00
|
|
|
|
"os"
|
2017-06-11 04:03:28 -04:00
|
|
|
|
"strings"
|
2017-06-01 20:14:51 -04:00
|
|
|
|
|
2017-04-17 09:04:52 -04:00
|
|
|
|
"github.com/hashicorp/packer/common/uuid"
|
|
|
|
|
"github.com/hashicorp/packer/helper/communicator"
|
2019-08-19 12:48:32 -04:00
|
|
|
|
"github.com/hashicorp/packer/helper/config"
|
2017-04-17 09:04:52 -04:00
|
|
|
|
"github.com/hashicorp/packer/template/interpolate"
|
2017-03-03 03:56:17 -05:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type RunConfig struct {
|
2019-06-06 10:29:25 -04:00
|
|
|
|
AssociatePublicIpAddress bool `mapstructure:"associate_public_ip_address"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// ID of the zone to which the disk belongs.
|
2019-06-06 10:29:25 -04:00
|
|
|
|
ZoneId string `mapstructure:"zone_id" required:"false"`
|
2019-06-14 09:17:56 -04:00
|
|
|
|
// 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.
|
2019-09-20 04:54:38 -04:00
|
|
|
|
IOOptimized config.Trilean `mapstructure:"io_optimized" required:"false"`
|
2019-06-14 09:56:05 -04:00
|
|
|
|
// 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).
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// You can also obtain the latest instance type table by invoking the
|
2019-06-14 09:56:05 -04:00
|
|
|
|
// [Querying Instance Type
|
|
|
|
|
// Table](https://intl.aliyun.com/help/doc-detail/25620.htm?spm=a3c0i.o25499en.a3.6.Dr1bik)
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// interface.
|
|
|
|
|
InstanceType string `mapstructure:"instance_type" required:"true"`
|
|
|
|
|
Description string `mapstructure:"description"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// This is the base image id which you want to
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// create your customized images.
|
|
|
|
|
AlicloudSourceImage string `mapstructure:"source_image" required:"true"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// Whether to force shutdown upon device
|
2019-06-14 09:56:05 -04:00
|
|
|
|
// 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.
|
2019-06-06 10:29:25 -04:00
|
|
|
|
ForceStopInstance bool `mapstructure:"force_stop_instance" required:"false"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// If this option is set to true, Packer
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// 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"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// ID of the security group to which a newly
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// 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"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// The security group name. The default value
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// is blank. [2, 128] English or Chinese characters, must begin with an
|
|
|
|
|
// uppercase/lowercase letter or Chinese character. Can contain numbers, .,
|
2020-04-01 15:15:54 -04:00
|
|
|
|
// _ or -. It cannot begin with `http://` or `https://`.
|
2019-06-06 10:29:25 -04:00
|
|
|
|
SecurityGroupName string `mapstructure:"security_group_name" required:"false"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// User data to apply when launching the instance. Note
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// 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"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// Path to a file that will be used for the user
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// data when launching the instance.
|
|
|
|
|
UserDataFile string `mapstructure:"user_data_file" required:"false"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// VPC ID allocated by the system.
|
2019-06-06 10:29:25 -04:00
|
|
|
|
VpcId string `mapstructure:"vpc_id" required:"false"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// The VPC name. The default value is blank. [2, 128]
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// English or Chinese characters, must begin with an uppercase/lowercase
|
|
|
|
|
// letter or Chinese character. Can contain numbers, _ and -. The disk
|
2020-04-01 15:15:54 -04:00
|
|
|
|
// description will appear on the console. Cannot begin with `http://` or
|
|
|
|
|
// `https://`.
|
2019-06-06 10:29:25 -04:00
|
|
|
|
VpcName string `mapstructure:"vpc_name" required:"false"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// Value options: 192.168.0.0/16 and
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// 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"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// The ID of the VSwitch to be used.
|
2019-06-06 10:29:25 -04:00
|
|
|
|
VSwitchId string `mapstructure:"vswitch_id" required:"false"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// The ID of the VSwitch to be used.
|
2019-06-14 09:56:05 -04:00
|
|
|
|
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://`.
|
2019-06-06 10:29:25 -04:00
|
|
|
|
InstanceName string `mapstructure:"instance_name" required:"false"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// Internet charge type, which can be
|
2019-06-14 09:56:05 -04:00
|
|
|
|
// `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.
|
2019-06-06 10:29:25 -04:00
|
|
|
|
InternetChargeType string `mapstructure:"internet_charge_type" required:"false"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// Maximum outgoing bandwidth to the
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// public network, measured in Mbps (Mega bits per second).
|
2019-06-14 09:56:05 -04:00
|
|
|
|
//
|
|
|
|
|
// 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.
|
2019-06-06 10:29:25 -04:00
|
|
|
|
InternetMaxBandwidthOut int `mapstructure:"internet_max_bandwidth_out" required:"false"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// Timeout of creating snapshot(s).
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// 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"`
|
2017-03-03 03:56:17 -05:00
|
|
|
|
// Communicator settings
|
2019-06-06 10:29:25 -04:00
|
|
|
|
Comm communicator.Config `mapstructure:",squash"`
|
2019-05-28 11:50:58 -04:00
|
|
|
|
// If this value is true, packer will connect to
|
2019-06-06 10:29:25 -04:00
|
|
|
|
// 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"`
|
2017-03-03 03:56:17 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
|
2018-08-28 11:46:41 -04:00
|
|
|
|
if c.Comm.SSHKeyPairName == "" && c.Comm.SSHTemporaryKeyPairName == "" &&
|
2018-08-23 10:35:07 -04:00
|
|
|
|
c.Comm.SSHPrivateKeyFile == "" && c.Comm.SSHPassword == "" && c.Comm.WinRMPassword == "" {
|
2017-03-03 03:56:17 -05:00
|
|
|
|
|
2018-08-28 11:46:41 -04:00
|
|
|
|
c.Comm.SSHTemporaryKeyPairName = fmt.Sprintf("packer_%s", uuid.TimeOrderedUUID())
|
2017-03-03 03:56:17 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Validation
|
|
|
|
|
errs := c.Comm.Prepare(ctx)
|
|
|
|
|
if c.AlicloudSourceImage == "" {
|
|
|
|
|
errs = append(errs, errors.New("A source_image must be specified"))
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-01 23:28:41 -04:00
|
|
|
|
if strings.TrimSpace(c.AlicloudSourceImage) != c.AlicloudSourceImage {
|
|
|
|
|
errs = append(errs, errors.New("The source_image can't include spaces"))
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-03 03:56:17 -05:00
|
|
|
|
if c.InstanceType == "" {
|
2018-03-13 03:09:12 -04:00
|
|
|
|
errs = append(errs, errors.New("An alicloud_instance_type must be specified"))
|
2017-03-03 03:56:17 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|