packer-cn/builder/scaleway/step_pre_validate.go
Marco Molteni 4d7e42220b
scaleway: add pre validate step (check image and snapshot names) (#9840)
* Implement Stringer inteface for multistep.StepAction

* scaleway: add pre validate step (check image and snapshot names)

Before, it was possible to create multiple images with the same name,
leading to a confusing and wasteful situation (same for snapshots).

Now, we perform the same kind of checks done by the AWS EC2 builder,
and refuse to proceed if there is an existing image with the same name
(same for snapshots).

As usual, invoking `packer build -force` will bypass the checks.

Closes #9839.
2020-09-18 15:37:48 -04:00

81 lines
2.1 KiB
Go

package scaleway
import (
"context"
"fmt"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
)
// StepPreValidate provides an opportunity to pre-validate any configuration for
// the build before actually doing any time consuming work
//
type stepPreValidate struct {
Force bool
ImageName string
SnapshotName string
}
func (s *stepPreValidate) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
if s.Force {
ui.Say("Force flag found, skipping prevalidating image name")
return multistep.ActionContinue
}
ui.Say(fmt.Sprintf("Prevalidating image name: %s", s.ImageName))
instanceAPI := instance.NewAPI(state.Get("client").(*scw.Client))
images, err := instanceAPI.ListImages(
&instance.ListImagesRequest{Name: &s.ImageName},
scw.WithAllPages())
if err != nil {
err := fmt.Errorf("Error: getting image list: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
for _, im := range images.Images {
if im.Name == s.ImageName {
err := fmt.Errorf("Error: image name: '%s' is used by existing image with ID %s",
s.ImageName, im.ID)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
}
ui.Say(fmt.Sprintf("Prevalidating snapshot name: %s", s.SnapshotName))
snapshots, err := instanceAPI.ListSnapshots(
&instance.ListSnapshotsRequest{Name: &s.SnapshotName},
scw.WithAllPages())
if err != nil {
err := fmt.Errorf("Error: getting snapshot list: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
for _, sn := range snapshots.Snapshots {
if sn.Name == s.SnapshotName {
err := fmt.Errorf("Error: snapshot name: '%s' is used by existing snapshot with ID %s",
s.SnapshotName, sn.ID)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
}
return multistep.ActionContinue
}
func (s *stepPreValidate) Cleanup(multistep.StateBag) {
}