packer-cn/post-processor/yandex-export/step-upload-to-s3.go

102 lines
2.6 KiB
Go

package yandexexport
import (
"bytes"
"context"
"fmt"
"strings"
"sync"
"github.com/hashicorp/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/builder/yandex"
)
type StepUploadToS3 struct {
Paths []string
}
// Run reads the instance metadata and looks for the log entry
// indicating the cloud-init script finished.
func (s *StepUploadToS3) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packersdk.Ui)
comm := state.Get("communicator").(packersdk.Communicator)
cmdUploadToS3 := &packersdk.RemoteCmd{
Command: fmt.Sprintf(
"%s=%s aws s3 --region=%s --endpoint-url=https://%s cp disk.qcow2 %s",
"AWS_SHARED_CREDENTIALS_FILE",
sharedAWSCredFile,
defaultStorageRegion,
defaultStorageEndpoint,
s.Paths[0],
),
}
ui.Say("Upload to S3...")
if err := cmdUploadToS3.RunWithUi(ctx, comm, ui); err != nil {
return yandex.StepHaltWithError(state, err)
}
if cmdUploadToS3.ExitStatus() != 0 {
return yandex.StepHaltWithError(state, fmt.Errorf("Cannout upload to S3, exit code %d", cmdUploadToS3.ExitStatus()))
}
versionExtraFlags, err := getVersionExtraFlags(ctx, comm)
if err != nil {
ui.Message(fmt.Sprintf("[WARN] Cannot upload to other storage: %s", err))
return multistep.ActionContinue
}
wg := new(sync.WaitGroup)
defer wg.Wait()
for _, path := range s.Paths[1:] {
wg.Add(1)
go func(path string) {
defer wg.Done()
ui.Message(fmt.Sprintf("Start copy %s to %s...", s.Paths[0], path))
cmd := &packersdk.RemoteCmd{
Command: fmt.Sprintf(
"%s=%s aws s3 --region=%s --endpoint-url=https://%s cp %s %s %s",
"AWS_SHARED_CREDENTIALS_FILE",
sharedAWSCredFile,
defaultStorageRegion,
defaultStorageEndpoint,
versionExtraFlags,
s.Paths[0],
path,
),
}
if err := cmd.RunWithUi(ctx, comm, ui); err != nil {
ui.Message(fmt.Sprintf("[WARN] Failed upload to %s", path))
}
if cmd.ExitStatus() != 0 {
ui.Message(fmt.Sprintf("[WARN] Failed upload to %s", path))
}
}(path)
}
return multistep.ActionContinue
}
// Cleanup nothing
func (s *StepUploadToS3) Cleanup(state multistep.StateBag) {}
func getVersionExtraFlags(ctx context.Context, comm packersdk.Communicator) (string, error) {
buff := new(bytes.Buffer)
cmd := &packersdk.RemoteCmd{
Command: "aws --version",
Stdout: buff,
}
if err := comm.Start(ctx, cmd); err != nil {
return "", err
}
if cmd.Wait() != 0 {
return "", fmt.Errorf("Cannot detect aws version")
}
vsn := buff.String()
switch {
case strings.HasPrefix(vsn, "aws-cli/2."):
return "--copy-props metadata-directive", nil
}
return "", nil
}