151 lines
4.0 KiB
Go
151 lines
4.0 KiB
Go
|
package yandexexport
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
||
|
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
||
|
"github.com/hashicorp/packer/builder/yandex"
|
||
|
)
|
||
|
|
||
|
type StepPrepareTools struct{}
|
||
|
|
||
|
// Run reads the instance metadata and looks for the log entry
|
||
|
// indicating the cloud-init script finished.
|
||
|
func (s *StepPrepareTools) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||
|
ui := state.Get("ui").(packersdk.Ui)
|
||
|
comm := state.Get("communicator").(packersdk.Communicator)
|
||
|
pkgManager, errPkgManager := detectPkgManager(ctx, comm)
|
||
|
|
||
|
if which(ctx, comm, "qemu-img") != nil {
|
||
|
if errPkgManager != nil {
|
||
|
return yandex.StepHaltWithError(state, errPkgManager)
|
||
|
}
|
||
|
ui.Message("Install qemu-img...")
|
||
|
if err := pkgManager.InstallQemuIMG(ctx, comm); err != nil {
|
||
|
return yandex.StepHaltWithError(state, err)
|
||
|
}
|
||
|
}
|
||
|
if which(ctx, comm, "aws") != nil {
|
||
|
if errPkgManager != nil {
|
||
|
return yandex.StepHaltWithError(state, errPkgManager)
|
||
|
}
|
||
|
ui.Message("Install aws...")
|
||
|
if err := pkgManager.InstallAWS(ctx, comm); err != nil {
|
||
|
return yandex.StepHaltWithError(state, err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return multistep.ActionContinue
|
||
|
}
|
||
|
|
||
|
// Cleanup nothing
|
||
|
func (s *StepPrepareTools) Cleanup(state multistep.StateBag) {}
|
||
|
|
||
|
func detectPkgManager(ctx context.Context, comm packersdk.Communicator) (pkgManager, error) {
|
||
|
if err := which(ctx, comm, "apt"); err == nil {
|
||
|
return &apt{}, nil
|
||
|
}
|
||
|
if err := which(ctx, comm, "yum"); err == nil {
|
||
|
return &yum{}, nil
|
||
|
}
|
||
|
|
||
|
return nil, fmt.Errorf("Cannot detect package manager")
|
||
|
}
|
||
|
|
||
|
func which(ctx context.Context, comm packersdk.Communicator, what string) error {
|
||
|
cmdCheckAPT := &packersdk.RemoteCmd{
|
||
|
Command: fmt.Sprintf("which %s", what),
|
||
|
}
|
||
|
if err := comm.Start(ctx, cmdCheckAPT); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if cmdCheckAPT.Wait() == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
return fmt.Errorf("Not found: %s", what)
|
||
|
}
|
||
|
|
||
|
type pkgManager interface {
|
||
|
InstallQemuIMG(ctx context.Context, comm packersdk.Communicator) error
|
||
|
InstallAWS(ctx context.Context, comm packersdk.Communicator) error
|
||
|
}
|
||
|
|
||
|
type apt struct {
|
||
|
updated bool
|
||
|
}
|
||
|
|
||
|
func (p *apt) InstallAWS(ctx context.Context, comm packersdk.Communicator) error {
|
||
|
if err := p.Update(ctx, comm); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if err := execCMDWithSudo(ctx, comm, "apt install -y awscli"); err != nil {
|
||
|
return fmt.Errorf("Cannot install awscli")
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (p *apt) InstallQemuIMG(ctx context.Context, comm packersdk.Communicator) error {
|
||
|
if err := p.Update(ctx, comm); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if err := execCMDWithSudo(ctx, comm, "apt install -y qemu-utils"); err != nil {
|
||
|
return fmt.Errorf("Cannot install qemu-utils")
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
func (p *apt) Update(ctx context.Context, comm packersdk.Communicator) error {
|
||
|
if p.updated {
|
||
|
return nil
|
||
|
}
|
||
|
if err := execCMDWithSudo(ctx, comm, "apt update"); err != nil {
|
||
|
return fmt.Errorf("Cannot update: %s", err)
|
||
|
}
|
||
|
p.updated = true
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
type yum struct{}
|
||
|
|
||
|
func (p *yum) InstallAWS(ctx context.Context, comm packersdk.Communicator) error {
|
||
|
if which(ctx, comm, "pip3") != nil {
|
||
|
if err := execCMDWithSudo(ctx, comm, "yum install -y python3-pip"); err != nil {
|
||
|
return fmt.Errorf("Cannot install qemu-img: %s", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if err := execCMDWithSudo(ctx, comm, "pip3 install awscli"); err != nil {
|
||
|
return fmt.Errorf("Install awscli: %s", err)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (p *yum) InstallQemuIMG(ctx context.Context, comm packersdk.Communicator) error {
|
||
|
if err := execCMDWithSudo(ctx, comm, "yum install -y libgcrypt qemu-img"); err != nil {
|
||
|
return fmt.Errorf("Cannot install qemu-img: %s", err)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func execCMDWithSudo(ctx context.Context, comm packersdk.Communicator, cmdStr string) error {
|
||
|
cmd := &packersdk.RemoteCmd{
|
||
|
Command: cmdStr,
|
||
|
}
|
||
|
if err := comm.Start(ctx, cmd); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if cmd.Wait() != 0 {
|
||
|
cmd := &packersdk.RemoteCmd{
|
||
|
Command: fmt.Sprintf("sudo %s", cmdStr),
|
||
|
}
|
||
|
if err := comm.Start(ctx, cmd); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if cmd.Wait() != 0 {
|
||
|
return fmt.Errorf("Bad exit code: %d", cmd.ExitStatus())
|
||
|
}
|
||
|
}
|
||
|
return nil
|
||
|
}
|