Make some steps exportable, add 'GetInstanceMetadata' method
This commit is contained in:
parent
696750de32
commit
9489a46f32
|
@ -26,7 +26,7 @@ func (a *Artifact) Id() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Artifact) Files() []string {
|
func (*Artifact) Files() []string {
|
||||||
return nil
|
return []string{""}
|
||||||
}
|
}
|
||||||
|
|
||||||
//revive:enable:var-naming
|
//revive:enable:var-naming
|
||||||
|
|
|
@ -54,11 +54,11 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||||
|
|
||||||
// Build the steps
|
// Build the steps
|
||||||
steps := []multistep.Step{
|
steps := []multistep.Step{
|
||||||
&stepCreateSSHKey{
|
&StepCreateSSHKey{
|
||||||
Debug: b.config.PackerDebug,
|
Debug: b.config.PackerDebug,
|
||||||
DebugKeyPath: fmt.Sprintf("yc_%s.pem", b.config.PackerBuildName),
|
DebugKeyPath: fmt.Sprintf("yc_%s.pem", b.config.PackerBuildName),
|
||||||
},
|
},
|
||||||
&stepCreateInstance{
|
&StepCreateInstance{
|
||||||
Debug: b.config.PackerDebug,
|
Debug: b.config.PackerDebug,
|
||||||
SerialLogFile: b.config.SerialLogFile,
|
SerialLogFile: b.config.SerialLogFile,
|
||||||
},
|
},
|
||||||
|
@ -72,7 +72,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||||
&common.StepCleanupTempKeys{
|
&common.StepCleanupTempKeys{
|
||||||
Comm: &b.config.Communicator,
|
Comm: &b.config.Communicator,
|
||||||
},
|
},
|
||||||
&stepTeardownInstance{},
|
&StepTeardownInstance{},
|
||||||
&stepCreateImage{},
|
&stepCreateImage{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +93,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
||||||
artifact := &Artifact{
|
artifact := &Artifact{
|
||||||
image: image.(*compute.Image),
|
image: image.(*compute.Image),
|
||||||
config: &b.config,
|
config: &b.config,
|
||||||
|
driver: driver,
|
||||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||||
}
|
}
|
||||||
return artifact, nil
|
return artifact, nil
|
||||||
|
|
|
@ -16,4 +16,5 @@ type Driver interface {
|
||||||
DeleteInstance(ctx context.Context, instanceID string) error
|
DeleteInstance(ctx context.Context, instanceID string) error
|
||||||
DeleteSubnet(ctx context.Context, subnetID string) error
|
DeleteSubnet(ctx context.Context, subnetID string) error
|
||||||
DeleteNetwork(ctx context.Context, networkID string) error
|
DeleteNetwork(ctx context.Context, networkID string) error
|
||||||
|
GetInstanceMetadata(ctx context.Context, name string, key string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,5 +232,22 @@ func (d *driverYC) DeleteDisk(ctx context.Context, diskID string) error {
|
||||||
|
|
||||||
_, err = op.Response()
|
_, err = op.Response()
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *driverYC) GetInstanceMetadata(ctx context.Context, id string, key string) (string, error) {
|
||||||
|
instance, err := d.sdk.Compute().Instance().Get(ctx, &compute.GetInstanceRequest{
|
||||||
|
InstanceId: id,
|
||||||
|
View: compute.InstanceView_FULL,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range instance.GetMetadata() {
|
||||||
|
if k == key {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("Instance metadata key, %s, not found.", key)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
|
|
||||||
const StandardImagesFolderID = "standard-images"
|
const StandardImagesFolderID = "standard-images"
|
||||||
|
|
||||||
type stepCreateInstance struct {
|
type StepCreateInstance struct {
|
||||||
Debug bool
|
Debug bool
|
||||||
SerialLogFile string
|
SerialLogFile string
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ func getImage(ctx context.Context, c *Config, d Driver) (*Image, error) {
|
||||||
return &Image{}, errors.New("neither source_image_name nor source_image_family defined in config")
|
return &Image{}, errors.New("neither source_image_name nor source_image_family defined in config")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
func (s *StepCreateInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||||
sdk := state.Get("sdk").(*ycsdk.SDK)
|
sdk := state.Get("sdk").(*ycsdk.SDK)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
|
@ -265,7 +265,7 @@ runcmd:
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stepCreateInstance) Cleanup(state multistep.StateBag) {
|
func (s *StepCreateInstance) Cleanup(state multistep.StateBag) {
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
driver := state.Get("driver").(Driver)
|
driver := state.Get("driver").(Driver)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
@ -339,7 +339,7 @@ func (s *stepCreateInstance) Cleanup(state multistep.StateBag) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stepCreateInstance) writeSerialLogFile(ctx context.Context, state multistep.StateBag) error {
|
func (s *StepCreateInstance) writeSerialLogFile(ctx context.Context, state multistep.StateBag) error {
|
||||||
sdk := state.Get("sdk").(*ycsdk.SDK)
|
sdk := state.Get("sdk").(*ycsdk.SDK)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,12 @@ import (
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepCreateSSHKey struct {
|
type StepCreateSSHKey struct {
|
||||||
Debug bool
|
Debug bool
|
||||||
DebugKeyPath string
|
DebugKeyPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stepCreateSSHKey) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
func (s *StepCreateSSHKey) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
|
|
||||||
|
@ -96,5 +96,5 @@ func (s *stepCreateSSHKey) Run(_ context.Context, state multistep.StateBag) mult
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stepCreateSSHKey) Cleanup(state multistep.StateBag) {
|
func (s *StepCreateSSHKey) Cleanup(state multistep.StateBag) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@ import (
|
||||||
ycsdk "github.com/yandex-cloud/go-sdk"
|
ycsdk "github.com/yandex-cloud/go-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepTeardownInstance struct{}
|
type StepTeardownInstance struct{}
|
||||||
|
|
||||||
func (s *stepTeardownInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
func (s *StepTeardownInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||||
sdk := state.Get("sdk").(*ycsdk.SDK)
|
sdk := state.Get("sdk").(*ycsdk.SDK)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
c := state.Get("config").(*Config)
|
c := state.Get("config").(*Config)
|
||||||
|
@ -52,6 +52,6 @@ func (s *stepTeardownInstance) Run(ctx context.Context, state multistep.StateBag
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stepTeardownInstance) Cleanup(state multistep.StateBag) {
|
func (s *StepTeardownInstance) Cleanup(state multistep.StateBag) {
|
||||||
// no cleanup
|
// no cleanup
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package yandex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/packer/common/retry"
|
||||||
|
"github.com/hashicorp/packer/helper/multistep"
|
||||||
|
"github.com/hashicorp/packer/packer"
|
||||||
|
)
|
||||||
|
|
||||||
|
const CloudInitScriptStatusKey = "cloud-init-status"
|
||||||
|
const StartupScriptStatusError = "cloud-init-error"
|
||||||
|
const StartupScriptStatusDone = "cloud-init-done"
|
||||||
|
|
||||||
|
type StepWaitCloudInitScript int
|
||||||
|
|
||||||
|
// Run reads the instance metadata and looks for the log entry
|
||||||
|
// indicating the cloud-init script finished.
|
||||||
|
func (s *StepWaitCloudInitScript) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||||
|
_ = state.Get("config").(*Config)
|
||||||
|
driver := state.Get("driver").(Driver)
|
||||||
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
instanceID := state.Get("instance_id").(string)
|
||||||
|
|
||||||
|
ui.Say("Waiting for any running cloud-init script to finish...")
|
||||||
|
|
||||||
|
// Keep checking the serial port output to see if the cloud-init script is done.
|
||||||
|
err := retry.Config{
|
||||||
|
ShouldRetry: func(error) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
RetryDelay: (&retry.Backoff{InitialBackoff: 10 * time.Second, MaxBackoff: 60 * time.Second, Multiplier: 2}).Linear,
|
||||||
|
}.Run(ctx, func(ctx context.Context) error {
|
||||||
|
status, err := driver.GetInstanceMetadata(ctx, instanceID, CloudInitScriptStatusKey)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Error getting cloud-init script status: %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if status == StartupScriptStatusError {
|
||||||
|
err = errors.New("Cloud-init script error.")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
done := status == StartupScriptStatusDone
|
||||||
|
if !done {
|
||||||
|
ui.Say("Cloud-init script not finished yet. Waiting...")
|
||||||
|
return errors.New("Cloud-init script not done.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Error waiting for cloud-init script to finish: %s", err)
|
||||||
|
state.Put("error", err)
|
||||||
|
ui.Error(err.Error())
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
ui.Say("Cloud-init script has finished running.")
|
||||||
|
return multistep.ActionContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup.
|
||||||
|
func (s *StepWaitCloudInitScript) Cleanup(state multistep.StateBag) {}
|
Loading…
Reference in New Issue