From bb19cdeb55f5e6754aefdf8fbdce2375f8f341c1 Mon Sep 17 00:00:00 2001 From: "bozhi.ch" Date: Tue, 25 Sep 2018 19:21:28 +0800 Subject: [PATCH] support disable_stop_instance option for some specific scenarios --- builder/alicloud/ecs/builder.go | 3 ++- builder/alicloud/ecs/run_config.go | 1 + builder/alicloud/ecs/run_config_test.go | 27 +++++++++++++++++++ .../ecs/step_delete_images_snapshots.go | 5 +++- builder/alicloud/ecs/step_run_instance.go | 4 ++- builder/alicloud/ecs/step_stop_instance.go | 12 ++++++--- .../source/docs/builders/alicloud-ecs.html.md | 6 +++++ 7 files changed, 51 insertions(+), 7 deletions(-) diff --git a/builder/alicloud/ecs/builder.go b/builder/alicloud/ecs/builder.go index f3d9d73a1..cc1472a64 100644 --- a/builder/alicloud/ecs/builder.go +++ b/builder/alicloud/ecs/builder.go @@ -163,7 +163,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Comm: &b.config.RunConfig.Comm, }, &stepStopAlicloudInstance{ - ForceStop: b.config.ForceStopInstance, + ForceStop: b.config.ForceStopInstance, + DisableStop: b.config.DisableStopInstance, }, &stepDeleteAlicloudImageSnapshots{ AlicloudImageForceDeleteSnapshots: b.config.AlicloudImageForceDeleteSnapshots, diff --git a/builder/alicloud/ecs/run_config.go b/builder/alicloud/ecs/run_config.go index 2dd6602f6..aaab9f785 100644 --- a/builder/alicloud/ecs/run_config.go +++ b/builder/alicloud/ecs/run_config.go @@ -19,6 +19,7 @@ type RunConfig struct { Description string `mapstructure:"description"` AlicloudSourceImage string `mapstructure:"source_image"` ForceStopInstance bool `mapstructure:"force_stop_instance"` + DisableStopInstance bool `mapstructure:"disable_stop_instance"` SecurityGroupId string `mapstructure:"security_group_id"` SecurityGroupName string `mapstructure:"security_group_name"` UserData string `mapstructure:"user_data"` diff --git a/builder/alicloud/ecs/run_config_test.go b/builder/alicloud/ecs/run_config_test.go index 19dbb5e73..46d9b11de 100644 --- a/builder/alicloud/ecs/run_config_test.go +++ b/builder/alicloud/ecs/run_config_test.go @@ -147,3 +147,30 @@ func TestRunConfigPrepare_SSHPrivateIp(t *testing.T) { t.Fatalf("invalid value, expected: %t, actul: %t", false, c.SSHPrivateIp) } } + +func TestRunConfigPrepare_DisableStopInstance(t *testing.T) { + c := testConfig() + + if err := c.Prepare(nil); len(err) != 0 { + t.Fatalf("err: %s", err) + } + if c.DisableStopInstance != false { + t.Fatalf("invalid value, expected: %t, actul: %t", false, c.DisableStopInstance) + } + + c.DisableStopInstance = true + if err := c.Prepare(nil); len(err) != 0 { + t.Fatalf("err: %s", err) + } + if c.DisableStopInstance != true { + t.Fatalf("invalid value, expected: %t, actul: %t", true, c.DisableStopInstance) + } + + c.DisableStopInstance = false + if err := c.Prepare(nil); len(err) != 0 { + t.Fatalf("err: %s", err) + } + if c.DisableStopInstance != false { + t.Fatalf("invalid value, expected: %t, actul: %t", false, c.DisableStopInstance) + } +} diff --git a/builder/alicloud/ecs/step_delete_images_snapshots.go b/builder/alicloud/ecs/step_delete_images_snapshots.go index 6718744d9..97f1bec2c 100644 --- a/builder/alicloud/ecs/step_delete_images_snapshots.go +++ b/builder/alicloud/ecs/step_delete_images_snapshots.go @@ -21,7 +21,7 @@ func (s *stepDeleteAlicloudImageSnapshots) Run(_ context.Context, state multiste client := state.Get("client").(*ecs.Client) ui := state.Get("ui").(packer.Ui) config := state.Get("config").(*Config) - ui.Say("Deleting image snapshots.") + // Check for force delete if s.AlicloudImageForceDelete { images, _, err := client.DescribeImages(&ecs.DescribeImagesArgs{ @@ -31,6 +31,9 @@ func (s *stepDeleteAlicloudImageSnapshots) Run(_ context.Context, state multiste if len(images) < 1 { return multistep.ActionContinue } + + ui.Say(fmt.Sprintf("Deleting duplicated image and snapshot: %s", s.AlicloudImageName)) + for _, image := range images { if image.ImageOwnerAlias != string(ecs.ImageOwnerSelf) { log.Printf("You can only delete instances based on customized images %s ", image.ImageId) diff --git a/builder/alicloud/ecs/step_run_instance.go b/builder/alicloud/ecs/step_run_instance.go index 57a799183..06e21df7f 100644 --- a/builder/alicloud/ecs/step_run_instance.go +++ b/builder/alicloud/ecs/step_run_instance.go @@ -24,7 +24,9 @@ func (s *stepRunAlicloudInstance) Run(_ context.Context, state multistep.StateBa ui.Error(err.Error()) return multistep.ActionHalt } - ui.Say("Starting instance.") + + ui.Say(fmt.Sprintf("Starting instance: %s", instance.InstanceId)) + err = client.WaitForInstance(instance.InstanceId, ecs.Running, ALICLOUD_DEFAULT_TIMEOUT) if err != nil { err := fmt.Errorf("Timeout waiting for instance to start: %s", err) diff --git a/builder/alicloud/ecs/step_stop_instance.go b/builder/alicloud/ecs/step_stop_instance.go index d57a52c12..ee4d79e3a 100644 --- a/builder/alicloud/ecs/step_stop_instance.go +++ b/builder/alicloud/ecs/step_stop_instance.go @@ -10,7 +10,8 @@ import ( ) type stepStopAlicloudInstance struct { - ForceStop bool + ForceStop bool + DisableStop bool } func (s *stepStopAlicloudInstance) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { @@ -18,8 +19,9 @@ func (s *stepStopAlicloudInstance) Run(_ context.Context, state multistep.StateB instance := state.Get("instance").(*ecs.InstanceAttributesType) ui := state.Get("ui").(packer.Ui) - err := client.StopInstance(instance.InstanceId, s.ForceStop) - if err != nil { + if !s.DisableStop { + ui.Say(fmt.Sprintf("Stopping instance: %s", instance.InstanceId)) + err := client.StopInstance(instance.InstanceId, s.ForceStop) if err != nil { err := fmt.Errorf("Error stopping alicloud instance: %s", err) state.Put("error", err) @@ -28,7 +30,9 @@ func (s *stepStopAlicloudInstance) Run(_ context.Context, state multistep.StateB } } - err = client.WaitForInstance(instance.InstanceId, ecs.Stopped, ALICLOUD_DEFAULT_TIMEOUT) + ui.Say(fmt.Sprintf("Waiting instance stopped: %s", instance.InstanceId)) + + err := client.WaitForInstance(instance.InstanceId, ecs.Stopped, ALICLOUD_DEFAULT_TIMEOUT) if err != nil { err := fmt.Errorf("Error waiting for alicloud instance to stop: %s", err) state.Put("error", err) diff --git a/website/source/docs/builders/alicloud-ecs.html.md b/website/source/docs/builders/alicloud-ecs.html.md index e4e2f8b11..7a39a784b 100644 --- a/website/source/docs/builders/alicloud-ecs.html.md +++ b/website/source/docs/builders/alicloud-ecs.html.md @@ -56,6 +56,12 @@ builder. 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. +- `disable_stop_instance` (boolean) - 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`. + - `image_copy_names` (array of string) - The name of the destination image, \[2, 128\] English or Chinese characters. It must begin with an uppercase/lowercase letter or a Chinese character, and may contain numbers, `_` or `-`. It cannot