Files
Packer-Cn/builder/tencentcloud/cvm/builder.go
T
ZhiQiang Fan 310a40f8fe feature: add run_tags to instance in tencentcloud builder
Instance tags are useful, our customer asks us to support it in packer as
well, to enable them to identify the purpose of the instance, even the
instance runs in a very short time.
2019-06-28 23:18:41 +08:00

152 lines
4.3 KiB
Go

package cvm
import (
"context"
"fmt"
"log"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
)
const BuilderId = "tencent.cloud"
type Config struct {
common.PackerConfig `mapstructure:",squash"`
TencentCloudAccessConfig `mapstructure:",squash"`
TencentCloudImageConfig `mapstructure:",squash"`
TencentCloudRunConfig `mapstructure:",squash"`
ctx interpolate.Context
}
type Builder struct {
config Config
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
err := config.Decode(&b.config, &config.DecodeOpts{
Interpolate: true,
InterpolateContext: &b.config.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"run_command",
},
},
}, raws...)
b.config.ctx.EnableEnv = true
if err != nil {
return nil, err
}
// Accumulate any errors
var errs *packer.MultiError
errs = packer.MultiErrorAppend(errs, b.config.TencentCloudAccessConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.TencentCloudImageConfig.Prepare(&b.config.ctx)...)
errs = packer.MultiErrorAppend(errs, b.config.TencentCloudRunConfig.Prepare(&b.config.ctx)...)
if errs != nil && len(errs.Errors) > 0 {
return nil, errs
}
packer.LogSecretFilter.Set(b.config.SecretId, b.config.SecretKey)
log.Println(b.config)
return nil, nil
}
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
cvmClient, vpcClient, err := b.config.Client()
if err != nil {
return nil, err
}
state := new(multistep.BasicStateBag)
state.Put("config", &b.config)
state.Put("cvm_client", cvmClient)
state.Put("vpc_client", vpcClient)
state.Put("hook", hook)
state.Put("ui", ui)
var steps []multistep.Step
// Build the steps
steps = []multistep.Step{
&stepCheckSourceImage{b.config.SourceImageId},
&stepConfigKeyPair{
Debug: b.config.PackerDebug,
Comm: &b.config.Comm,
DebugKeyPath: fmt.Sprintf("cvm_%s.pem", b.config.PackerBuildName),
},
&stepConfigVPC{
VpcId: b.config.VpcId,
CidrBlock: b.config.CidrBlock,
VpcName: b.config.VpcName,
},
&stepConfigSubnet{
SubnetId: b.config.SubnetId,
SubnetCidrBlock: b.config.SubnectCidrBlock,
SubnetName: b.config.SubnetName,
Zone: b.config.Zone,
},
&stepConfigSecurityGroup{
SecurityGroupId: b.config.SecurityGroupId,
SecurityGroupName: b.config.SecurityGroupName,
Description: "a simple security group",
},
&stepRunInstance{
InstanceType: b.config.InstanceType,
UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile,
ZoneId: b.config.Zone,
InstanceName: b.config.InstanceName,
DiskType: b.config.DiskType,
DiskSize: b.config.DiskSize,
HostName: b.config.HostName,
InternetMaxBandwidthOut: b.config.InternetMaxBandwidthOut,
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
Tags: b.config.RunTags,
},
&communicator.StepConnect{
Config: &b.config.TencentCloudRunConfig.Comm,
SSHConfig: b.config.TencentCloudRunConfig.Comm.SSHConfigFunc(),
Host: SSHHost(b.config.AssociatePublicIpAddress),
},
&common.StepProvision{},
&common.StepCleanupTempKeys{
Comm: &b.config.TencentCloudRunConfig.Comm,
},
// We need this step to detach temporary key from instance, otherwise
// it always fails to delete the key.
&stepDetachTempKeyPair{},
&stepCreateImage{},
&stepShareImage{
b.config.ImageShareAccounts,
},
&stepCopyImage{
DesinationRegions: b.config.ImageCopyRegions,
SourceRegion: b.config.Region,
},
}
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(ctx, state)
if rawErr, ok := state.GetOk("error"); ok {
return nil, rawErr.(error)
}
if _, ok := state.GetOk("image"); !ok {
return nil, nil
}
artifact := &Artifact{
TencentCloudImages: state.Get("tencentcloudimages").(map[string]string),
BuilderIdValue: BuilderId,
Client: cvmClient,
}
return artifact, nil
}