Extract Hyperone (#10949)
This commit is contained in:
parent
0f6a081724
commit
2db338e322
|
@ -52,12 +52,6 @@
|
||||||
/builder/hcloud/ @LKaemmerling
|
/builder/hcloud/ @LKaemmerling
|
||||||
/website/pages/docs/builders/hcloud* @LKaemmerling
|
/website/pages/docs/builders/hcloud* @LKaemmerling
|
||||||
|
|
||||||
/examples/hyperone/ @m110 @gregorybrzeski @ad-m
|
|
||||||
/builder/hyperone/ @m110 @gregorybrzeski @ad-m
|
|
||||||
/website/pages/docs/builders/hyperone* @m110 @gregorybrzeski @ad-m
|
|
||||||
/test/builder_hyperone* @m110 @gregorybrzeski @ad-m
|
|
||||||
/test/fixtures/builder-hyperone/ @m110 @gregorybrzeski @ad-m
|
|
||||||
|
|
||||||
/examples/ucloud/ @shawnmssu
|
/examples/ucloud/ @shawnmssu
|
||||||
/builder/ucloud/ @shawnmssu
|
/builder/ucloud/ @shawnmssu
|
||||||
/website/pages/docs/builders/ucloud* @shawnmssu
|
/website/pages/docs/builders/ucloud* @shawnmssu
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
openapi "github.com/hyperonecom/h1-client-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Artifact struct {
|
|
||||||
imageName string
|
|
||||||
imageID string
|
|
||||||
client *openapi.APIClient
|
|
||||||
|
|
||||||
// StateData should store data such as GeneratedData
|
|
||||||
// to be shared with post-processors
|
|
||||||
StateData map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Artifact) BuilderId() string {
|
|
||||||
return BuilderID
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Artifact) Files() []string {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Artifact) Id() string {
|
|
||||||
return a.imageID
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Artifact) String() string {
|
|
||||||
return fmt.Sprintf("Image '%s' created, ID: %s", a.imageName, a.imageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Artifact) State(name string) interface{} {
|
|
||||||
return a.StateData[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Artifact) Destroy() error {
|
|
||||||
if a.imageID == "" {
|
|
||||||
// No image to destroy
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := a.client.ImageApi.ImageDelete(context.TODO(), a.imageID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/v2/hcldec"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
|
||||||
openapi "github.com/hyperonecom/h1-client-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
const BuilderID = "hyperone.builder"
|
|
||||||
|
|
||||||
type Builder struct {
|
|
||||||
config Config
|
|
||||||
runner multistep.Runner
|
|
||||||
client *openapi.APIClient
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
|
|
||||||
|
|
||||||
func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
|
||||||
warnings, errs := b.config.Prepare(raws...)
|
|
||||||
if errs != nil {
|
|
||||||
return nil, warnings, errs
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := openapi.NewConfiguration()
|
|
||||||
cfg.AddDefaultHeader("x-auth-token", b.config.Token)
|
|
||||||
if b.config.Project != "" {
|
|
||||||
cfg.AddDefaultHeader("x-project", b.config.Project)
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.config.APIURL != "" {
|
|
||||||
cfg.BasePath = b.config.APIURL
|
|
||||||
}
|
|
||||||
|
|
||||||
prefer := fmt.Sprintf("respond-async,wait=%d", int(b.config.StateTimeout.Seconds()))
|
|
||||||
cfg.AddDefaultHeader("Prefer", prefer)
|
|
||||||
|
|
||||||
b.client = openapi.NewAPIClient(cfg)
|
|
||||||
|
|
||||||
return nil, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type wrappedCommandTemplate struct {
|
|
||||||
Command string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) {
|
|
||||||
wrappedCommand := func(command string) (string, error) {
|
|
||||||
ictx := b.config.ctx
|
|
||||||
ictx.Data = &wrappedCommandTemplate{Command: command}
|
|
||||||
return interpolate.Render(b.config.ChrootCommandWrapper, &ictx)
|
|
||||||
}
|
|
||||||
|
|
||||||
state := &multistep.BasicStateBag{}
|
|
||||||
state.Put("config", &b.config)
|
|
||||||
state.Put("client", b.client)
|
|
||||||
state.Put("hook", hook)
|
|
||||||
state.Put("ui", ui)
|
|
||||||
state.Put("wrappedCommand", CommandWrapper(wrappedCommand))
|
|
||||||
|
|
||||||
steps := []multistep.Step{
|
|
||||||
&stepCreateSSHKey{},
|
|
||||||
&stepCreateVM{},
|
|
||||||
&communicator.StepConnect{
|
|
||||||
Config: &b.config.Comm,
|
|
||||||
Host: getPublicIP,
|
|
||||||
SSHConfig: b.config.Comm.SSHConfigFunc(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.config.ChrootDisk {
|
|
||||||
steps = append(steps,
|
|
||||||
&stepPrepareDevice{},
|
|
||||||
&stepPreMountCommands{},
|
|
||||||
&stepMountChroot{},
|
|
||||||
&stepPostMountCommands{},
|
|
||||||
&stepMountExtra{},
|
|
||||||
&stepCopyFiles{},
|
|
||||||
&stepChrootProvision{},
|
|
||||||
&stepStopVM{},
|
|
||||||
&stepDetachDisk{},
|
|
||||||
&stepCreateVMFromDisk{},
|
|
||||||
&stepCreateImage{},
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
steps = append(steps,
|
|
||||||
&commonsteps.StepProvision{},
|
|
||||||
&stepStopVM{},
|
|
||||||
&stepCreateImage{},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
|
|
||||||
b.runner.Run(ctx, state)
|
|
||||||
|
|
||||||
if rawErr, ok := state.GetOk("error"); ok {
|
|
||||||
return nil, rawErr.(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
artifact := &Artifact{
|
|
||||||
imageID: state.Get("image_id").(string),
|
|
||||||
imageName: state.Get("image_name").(string),
|
|
||||||
client: b.client,
|
|
||||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
|
||||||
}
|
|
||||||
|
|
||||||
return artifact, nil
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
builderT "github.com/hashicorp/packer/acctest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBuilderAcc_basic(t *testing.T) {
|
|
||||||
builderT.Test(t, builderT.TestCase{
|
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
|
||||||
Builder: &Builder{},
|
|
||||||
Template: testBuilderAccBasic,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuilderAcc_chroot(t *testing.T) {
|
|
||||||
builderT.Test(t, builderT.TestCase{
|
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
|
||||||
Builder: &Builder{},
|
|
||||||
Template: testBuilderAccChroot,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func testAccPreCheck(t *testing.T) {
|
|
||||||
if v := os.Getenv("HYPERONE_TOKEN"); v == "" {
|
|
||||||
t.Fatal("HYPERONE_TOKEN must be set for acceptance tests")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const testBuilderAccBasic = `
|
|
||||||
{
|
|
||||||
"builders": [{
|
|
||||||
"type": "test",
|
|
||||||
"vm_type": "a1.nano",
|
|
||||||
"source_image": "ubuntu",
|
|
||||||
"disk_size": 10,
|
|
||||||
"image_tags": {
|
|
||||||
"key":"value"
|
|
||||||
},
|
|
||||||
"vm_tags": {
|
|
||||||
"key_vm":"value_vm"
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const testBuilderAccChroot = `
|
|
||||||
{
|
|
||||||
"builders": [{
|
|
||||||
"type": "test",
|
|
||||||
"source_image": "ubuntu",
|
|
||||||
"disk_size": 10,
|
|
||||||
"vm_type": "a1.nano",
|
|
||||||
"chroot_disk": true,
|
|
||||||
"chroot_command_wrapper": "sudo {{.Command}}",
|
|
||||||
"pre_mount_commands": [
|
|
||||||
"parted {{.Device}} mklabel msdos mkpart primary 1M 100% set 1 boot on print",
|
|
||||||
"mkfs.ext4 {{.Device}}1"
|
|
||||||
],
|
|
||||||
"post_mount_commands": [
|
|
||||||
"apt-get update",
|
|
||||||
"apt-get install debootstrap",
|
|
||||||
"debootstrap --arch amd64 bionic {{.MountPath}}"
|
|
||||||
]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
`
|
|
|
@ -1,55 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CommandWrapper func(string) (string, error)
|
|
||||||
|
|
||||||
// ChrootCommunicator works as a wrapper on SSHCommunicator, modyfing paths in
|
|
||||||
// flight to be run in a chroot.
|
|
||||||
type ChrootCommunicator struct {
|
|
||||||
Chroot string
|
|
||||||
CmdWrapper CommandWrapper
|
|
||||||
Wrapped packersdk.Communicator
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ChrootCommunicator) Start(ctx context.Context, cmd *packersdk.RemoteCmd) error {
|
|
||||||
command := strconv.Quote(cmd.Command)
|
|
||||||
chrootCommand, err := c.CmdWrapper(
|
|
||||||
fmt.Sprintf("sudo chroot %s /bin/sh -c %s", c.Chroot, command))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.Command = chrootCommand
|
|
||||||
|
|
||||||
return c.Wrapped.Start(ctx, cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ChrootCommunicator) Upload(dst string, r io.Reader, fi *os.FileInfo) error {
|
|
||||||
dst = filepath.Join(c.Chroot, dst)
|
|
||||||
return c.Wrapped.Upload(dst, r, fi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ChrootCommunicator) UploadDir(dst string, src string, exclude []string) error {
|
|
||||||
dst = filepath.Join(c.Chroot, dst)
|
|
||||||
return c.Wrapped.UploadDir(dst, src, exclude)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ChrootCommunicator) Download(src string, w io.Writer) error {
|
|
||||||
src = filepath.Join(c.Chroot, src)
|
|
||||||
return c.Wrapped.Download(src, w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ChrootCommunicator) DownloadDir(src string, dst string, exclude []string) error {
|
|
||||||
src = filepath.Join(c.Chroot, src)
|
|
||||||
return c.Wrapped.DownloadDir(src, dst, exclude)
|
|
||||||
}
|
|
|
@ -1,352 +0,0 @@
|
||||||
//go:generate packer-sdc struct-markdown
|
|
||||||
//go:generate packer-sdc mapstructure-to-hcl2 -type Config
|
|
||||||
|
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/common"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/communicator"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/json"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/uuid"
|
|
||||||
"github.com/mitchellh/go-homedir"
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
configPath = "~/.h1-cli/conf.json"
|
|
||||||
tokenEnv = "HYPERONE_TOKEN"
|
|
||||||
|
|
||||||
defaultDiskType = "ssd"
|
|
||||||
defaultImageService = "564639bc052c084e2f2e3266"
|
|
||||||
defaultStateTimeout = 5 * time.Minute
|
|
||||||
defaultUserName = "guru"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
common.PackerConfig `mapstructure:",squash"`
|
|
||||||
Comm communicator.Config `mapstructure:",squash"`
|
|
||||||
// Custom API endpoint URL, compatible with HyperOne.
|
|
||||||
// It can also be specified via environment variable HYPERONE_API_URL.
|
|
||||||
APIURL string `mapstructure:"api_url" required:"false"`
|
|
||||||
// The authentication token used to access your account.
|
|
||||||
// This can be either a session token or a service account token.
|
|
||||||
// If not defined, the builder will attempt to find it in the following order:
|
|
||||||
Token string `mapstructure:"token" required:"true"`
|
|
||||||
// The id or name of the project. This field is required
|
|
||||||
// only if using session tokens. It should be skipped when using service
|
|
||||||
// account authentication.
|
|
||||||
Project string `mapstructure:"project" required:"true"`
|
|
||||||
// Login (an e-mail) on HyperOne platform. Set this
|
|
||||||
// if you want to fetch the token by SSH authentication.
|
|
||||||
TokenLogin string `mapstructure:"token_login" required:"false"`
|
|
||||||
// Timeout for waiting on the API to complete
|
|
||||||
// a request. Defaults to 5m.
|
|
||||||
StateTimeout time.Duration `mapstructure:"state_timeout" required:"false"`
|
|
||||||
// ID or name of the image to launch server from.
|
|
||||||
SourceImage string `mapstructure:"source_image" required:"true"`
|
|
||||||
// The name of the resulting image. Defaults to
|
|
||||||
// `packer-{{timestamp}}`
|
|
||||||
// (see configuration templates for more info).
|
|
||||||
ImageName string `mapstructure:"image_name" required:"false"`
|
|
||||||
// The description of the resulting image.
|
|
||||||
ImageDescription string `mapstructure:"image_description" required:"false"`
|
|
||||||
// Key/value pair tags to add to the created image.
|
|
||||||
ImageTags map[string]string `mapstructure:"image_tags" required:"false"`
|
|
||||||
// Same as [`image_tags`](#image_tags) but defined as a singular repeatable
|
|
||||||
// block containing a `key` and a `value` field. In HCL2 mode the
|
|
||||||
// [`dynamic_block`](/docs/templates/hcl_templates/expressions#dynamic-blocks)
|
|
||||||
// will allow you to create those programatically.
|
|
||||||
ImageTag config.KeyValues `mapstructure:"image_tag" required:"false"`
|
|
||||||
// The service of the resulting image.
|
|
||||||
ImageService string `mapstructure:"image_service" required:"false"`
|
|
||||||
// ID or name of the type this server should be created with.
|
|
||||||
VmType string `mapstructure:"vm_type" required:"true"`
|
|
||||||
// The name of the created server.
|
|
||||||
VmName string `mapstructure:"vm_name" required:"false"`
|
|
||||||
// Key/value pair tags to add to the created server.
|
|
||||||
VmTags map[string]string `mapstructure:"vm_tags" required:"false"`
|
|
||||||
// Same as [`vm_tags`](#vm_tags) but defined as a singular repeatable block
|
|
||||||
// containing a `key` and a `value` field. In HCL2 mode the
|
|
||||||
// [`dynamic_block`](/docs/templates/hcl_templates/expressions#dynamic-blocks)
|
|
||||||
// will allow you to create those programatically.
|
|
||||||
VmTag config.NameValues `mapstructure:"vm_tag" required:"false"`
|
|
||||||
// The name of the created disk.
|
|
||||||
DiskName string `mapstructure:"disk_name" required:"false"`
|
|
||||||
// The type of the created disk. Defaults to ssd.
|
|
||||||
DiskType string `mapstructure:"disk_type" required:"false"`
|
|
||||||
// Size of the created disk, in GiB.
|
|
||||||
DiskSize float32 `mapstructure:"disk_size" required:"true"`
|
|
||||||
// The ID of the network to attach to the created server.
|
|
||||||
Network string `mapstructure:"network" required:"false"`
|
|
||||||
// The ID of the private IP within chosen network
|
|
||||||
// that should be assigned to the created server.
|
|
||||||
PrivateIP string `mapstructure:"private_ip" required:"false"`
|
|
||||||
// The ID of the public IP that should be assigned to
|
|
||||||
// the created server. If network is chosen, the public IP will be associated
|
|
||||||
// with server's private IP.
|
|
||||||
PublicIP string `mapstructure:"public_ip" required:"false"`
|
|
||||||
// Custom service of public network adapter.
|
|
||||||
// Can be useful when using custom api_url. Defaults to public.
|
|
||||||
PublicNetAdpService string `mapstructure:"public_netadp_service" required:"false"`
|
|
||||||
|
|
||||||
ChrootDevice string `mapstructure:"chroot_device"`
|
|
||||||
ChrootDisk bool `mapstructure:"chroot_disk"`
|
|
||||||
ChrootDiskSize float32 `mapstructure:"chroot_disk_size"`
|
|
||||||
ChrootDiskType string `mapstructure:"chroot_disk_type"`
|
|
||||||
ChrootMountPath string `mapstructure:"chroot_mount_path"`
|
|
||||||
ChrootMounts [][]string `mapstructure:"chroot_mounts"`
|
|
||||||
ChrootCopyFiles []string `mapstructure:"chroot_copy_files"`
|
|
||||||
// How to run shell commands. This defaults to `{{.Command}}`. This may be
|
|
||||||
// useful to set if you want to set environmental variables or perhaps run
|
|
||||||
// it with sudo or so on. This is a configuration template where the
|
|
||||||
// .Command variable is replaced with the command to be run. Defaults to
|
|
||||||
// `{{.Command}}`.
|
|
||||||
ChrootCommandWrapper string `mapstructure:"chroot_command_wrapper"`
|
|
||||||
|
|
||||||
MountOptions []string `mapstructure:"mount_options"`
|
|
||||||
MountPartition string `mapstructure:"mount_partition"`
|
|
||||||
// A series of commands to execute after attaching the root volume and
|
|
||||||
// before mounting the chroot. This is not required unless using
|
|
||||||
// from_scratch. If so, this should include any partitioning and filesystem
|
|
||||||
// creation commands. The path to the device is provided by `{{.Device}}`.
|
|
||||||
PreMountCommands []string `mapstructure:"pre_mount_commands"`
|
|
||||||
// As pre_mount_commands, but the commands are executed after mounting the
|
|
||||||
// root device and before the extra mount and copy steps. The device and
|
|
||||||
// mount path are provided by `{{.Device}}` and `{{.MountPath}}`.
|
|
||||||
PostMountCommands []string `mapstructure:"post_mount_commands"`
|
|
||||||
// List of SSH keys by name or id to be added
|
|
||||||
// to the server on launch.
|
|
||||||
SSHKeys []string `mapstructure:"ssh_keys" required:"false"`
|
|
||||||
// User data to launch with the server. Packer will not
|
|
||||||
// automatically wait for a user script to finish before shutting down the
|
|
||||||
// instance, this must be handled in a provisioner.
|
|
||||||
UserData string `mapstructure:"user_data" required:"false"`
|
|
||||||
|
|
||||||
ctx interpolate.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
|
|
||||||
|
|
||||||
var md mapstructure.Metadata
|
|
||||||
err := config.Decode(c, &config.DecodeOpts{
|
|
||||||
Metadata: &md,
|
|
||||||
Interpolate: true,
|
|
||||||
InterpolateContext: &c.ctx,
|
|
||||||
InterpolateFilter: &interpolate.RenderFilter{
|
|
||||||
Exclude: []string{
|
|
||||||
"run_command",
|
|
||||||
"chroot_command_wrapper",
|
|
||||||
"post_mount_commands",
|
|
||||||
"pre_mount_commands",
|
|
||||||
"mount_path",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, raws...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cliConfig, err := loadCLIConfig()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defaults
|
|
||||||
if c.Comm.SSHUsername == "" {
|
|
||||||
c.Comm.SSHUsername = defaultUserName
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Comm.SSHTimeout == 0 {
|
|
||||||
c.Comm.SSHTimeout = 10 * time.Minute
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.APIURL == "" {
|
|
||||||
c.APIURL = os.Getenv("HYPERONE_API_URL")
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Token == "" {
|
|
||||||
c.Token = os.Getenv(tokenEnv)
|
|
||||||
|
|
||||||
if c.Token == "" {
|
|
||||||
c.Token = cliConfig.Profile.APIKey
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetching token by SSH is available only for the default API endpoint
|
|
||||||
if c.TokenLogin != "" && c.APIURL == "" {
|
|
||||||
c.Token, err = fetchTokenBySSH(c.TokenLogin)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Project == "" {
|
|
||||||
c.Project = cliConfig.Profile.Project.ID
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.StateTimeout == 0 {
|
|
||||||
c.StateTimeout = defaultStateTimeout
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ImageName == "" {
|
|
||||||
name, err := interpolate.Render("packer-{{timestamp}}", nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
c.ImageName = name
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ImageService == "" {
|
|
||||||
c.ImageService = defaultImageService
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.VmName == "" {
|
|
||||||
c.VmName = fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID())
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.DiskType == "" {
|
|
||||||
c.DiskType = defaultDiskType
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.PublicNetAdpService == "" {
|
|
||||||
c.PublicNetAdpService = "public"
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ChrootCommandWrapper == "" {
|
|
||||||
c.ChrootCommandWrapper = "{{.Command}}"
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ChrootDiskSize == 0 {
|
|
||||||
c.ChrootDiskSize = c.DiskSize
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ChrootDiskType == "" {
|
|
||||||
c.ChrootDiskType = c.DiskType
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ChrootMountPath == "" {
|
|
||||||
path, err := interpolate.Render("/mnt/packer-hyperone-volumes/{{timestamp}}", nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
c.ChrootMountPath = path
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ChrootMounts == nil {
|
|
||||||
c.ChrootMounts = make([][]string, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.ChrootMounts) == 0 {
|
|
||||||
c.ChrootMounts = [][]string{
|
|
||||||
{"proc", "proc", "/proc"},
|
|
||||||
{"sysfs", "sysfs", "/sys"},
|
|
||||||
{"bind", "/dev", "/dev"},
|
|
||||||
{"devpts", "devpts", "/dev/pts"},
|
|
||||||
{"binfmt_misc", "binfmt_misc", "/proc/sys/fs/binfmt_misc"},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ChrootCopyFiles == nil {
|
|
||||||
c.ChrootCopyFiles = []string{"/etc/resolv.conf"}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.MountPartition == "" {
|
|
||||||
c.MountPartition = "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validation
|
|
||||||
var errs *packersdk.MultiError
|
|
||||||
errs = packersdk.MultiErrorAppend(errs, c.ImageTag.CopyOn(&c.ImageTags)...)
|
|
||||||
errs = packersdk.MultiErrorAppend(errs, c.VmTag.CopyOn(&c.VmTags)...)
|
|
||||||
|
|
||||||
if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
|
|
||||||
errs = packersdk.MultiErrorAppend(errs, es...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Token == "" {
|
|
||||||
errs = packersdk.MultiErrorAppend(errs, errors.New("token is required"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.VmType == "" {
|
|
||||||
errs = packersdk.MultiErrorAppend(errs, errors.New("vm type is required"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.DiskSize == 0 {
|
|
||||||
errs = packersdk.MultiErrorAppend(errs, errors.New("disk size is required"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.SourceImage == "" {
|
|
||||||
errs = packersdk.MultiErrorAppend(errs, errors.New("source image is required"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ChrootDisk {
|
|
||||||
if len(c.PreMountCommands) == 0 {
|
|
||||||
errs = packersdk.MultiErrorAppend(errs, errors.New("pre-mount commands are required for chroot disk"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, mounts := range c.ChrootMounts {
|
|
||||||
if len(mounts) != 3 {
|
|
||||||
errs = packersdk.MultiErrorAppend(
|
|
||||||
errs, errors.New("each chroot_mounts entry should have three elements"))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if errs != nil && len(errs.Errors) > 0 {
|
|
||||||
return nil, errs
|
|
||||||
}
|
|
||||||
|
|
||||||
packersdk.LogSecretFilter.Set(c.Token)
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type cliConfig struct {
|
|
||||||
Profile struct {
|
|
||||||
APIKey string `json:"apiKey"`
|
|
||||||
Project struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
} `json:"project"`
|
|
||||||
} `json:"profile"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadCLIConfig() (cliConfig, error) {
|
|
||||||
path, err := homedir.Expand(configPath)
|
|
||||||
if err != nil {
|
|
||||||
return cliConfig{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = os.Stat(path)
|
|
||||||
if err != nil {
|
|
||||||
// Config not found
|
|
||||||
return cliConfig{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
content, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return cliConfig{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var c cliConfig
|
|
||||||
err = json.Unmarshal(content, &c)
|
|
||||||
if err != nil {
|
|
||||||
return cliConfig{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPublicIP(state multistep.StateBag) (string, error) {
|
|
||||||
return state.Get("public_ip").(string), nil
|
|
||||||
}
|
|
|
@ -1,216 +0,0 @@
|
||||||
// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
|
|
||||||
|
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/hashicorp/hcl/v2/hcldec"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
|
||||||
"github.com/zclconf/go-cty/cty"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FlatConfig is an auto-generated flat version of Config.
|
|
||||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
|
||||||
type FlatConfig struct {
|
|
||||||
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
|
|
||||||
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
|
|
||||||
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
|
|
||||||
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
|
|
||||||
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
|
|
||||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
|
||||||
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
|
|
||||||
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
|
||||||
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
|
|
||||||
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
|
|
||||||
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
|
|
||||||
SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port" hcl:"ssh_port"`
|
|
||||||
SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"`
|
|
||||||
SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"`
|
|
||||||
SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"`
|
|
||||||
SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" undocumented:"true" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"`
|
|
||||||
SSHTemporaryKeyPairType *string `mapstructure:"temporary_key_pair_type" cty:"temporary_key_pair_type" hcl:"temporary_key_pair_type"`
|
|
||||||
SSHTemporaryKeyPairBits *int `mapstructure:"temporary_key_pair_bits" cty:"temporary_key_pair_bits" hcl:"temporary_key_pair_bits"`
|
|
||||||
SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"`
|
|
||||||
SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"`
|
|
||||||
SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"`
|
|
||||||
SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" undocumented:"true" cty:"ssh_private_key_file" hcl:"ssh_private_key_file"`
|
|
||||||
SSHCertificateFile *string `mapstructure:"ssh_certificate_file" cty:"ssh_certificate_file" hcl:"ssh_certificate_file"`
|
|
||||||
SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty" hcl:"ssh_pty"`
|
|
||||||
SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout" hcl:"ssh_timeout"`
|
|
||||||
SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" undocumented:"true" cty:"ssh_wait_timeout" hcl:"ssh_wait_timeout"`
|
|
||||||
SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" undocumented:"true" cty:"ssh_agent_auth" hcl:"ssh_agent_auth"`
|
|
||||||
SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding" hcl:"ssh_disable_agent_forwarding"`
|
|
||||||
SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts" hcl:"ssh_handshake_attempts"`
|
|
||||||
SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host" hcl:"ssh_bastion_host"`
|
|
||||||
SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port" hcl:"ssh_bastion_port"`
|
|
||||||
SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth" hcl:"ssh_bastion_agent_auth"`
|
|
||||||
SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username" hcl:"ssh_bastion_username"`
|
|
||||||
SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password" hcl:"ssh_bastion_password"`
|
|
||||||
SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive" hcl:"ssh_bastion_interactive"`
|
|
||||||
SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file" hcl:"ssh_bastion_private_key_file"`
|
|
||||||
SSHBastionCertificateFile *string `mapstructure:"ssh_bastion_certificate_file" cty:"ssh_bastion_certificate_file" hcl:"ssh_bastion_certificate_file"`
|
|
||||||
SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method" hcl:"ssh_file_transfer_method"`
|
|
||||||
SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host" hcl:"ssh_proxy_host"`
|
|
||||||
SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port" hcl:"ssh_proxy_port"`
|
|
||||||
SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username" hcl:"ssh_proxy_username"`
|
|
||||||
SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password" hcl:"ssh_proxy_password"`
|
|
||||||
SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval" hcl:"ssh_keep_alive_interval"`
|
|
||||||
SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout" hcl:"ssh_read_write_timeout"`
|
|
||||||
SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels" hcl:"ssh_remote_tunnels"`
|
|
||||||
SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels" hcl:"ssh_local_tunnels"`
|
|
||||||
SSHPublicKey []byte `mapstructure:"ssh_public_key" undocumented:"true" cty:"ssh_public_key" hcl:"ssh_public_key"`
|
|
||||||
SSHPrivateKey []byte `mapstructure:"ssh_private_key" undocumented:"true" cty:"ssh_private_key" hcl:"ssh_private_key"`
|
|
||||||
WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username" hcl:"winrm_username"`
|
|
||||||
WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password" hcl:"winrm_password"`
|
|
||||||
WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host" hcl:"winrm_host"`
|
|
||||||
WinRMNoProxy *bool `mapstructure:"winrm_no_proxy" cty:"winrm_no_proxy" hcl:"winrm_no_proxy"`
|
|
||||||
WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port" hcl:"winrm_port"`
|
|
||||||
WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout" hcl:"winrm_timeout"`
|
|
||||||
WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl" hcl:"winrm_use_ssl"`
|
|
||||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"`
|
|
||||||
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"`
|
|
||||||
APIURL *string `mapstructure:"api_url" required:"false" cty:"api_url" hcl:"api_url"`
|
|
||||||
Token *string `mapstructure:"token" required:"true" cty:"token" hcl:"token"`
|
|
||||||
Project *string `mapstructure:"project" required:"true" cty:"project" hcl:"project"`
|
|
||||||
TokenLogin *string `mapstructure:"token_login" required:"false" cty:"token_login" hcl:"token_login"`
|
|
||||||
StateTimeout *string `mapstructure:"state_timeout" required:"false" cty:"state_timeout" hcl:"state_timeout"`
|
|
||||||
SourceImage *string `mapstructure:"source_image" required:"true" cty:"source_image" hcl:"source_image"`
|
|
||||||
ImageName *string `mapstructure:"image_name" required:"false" cty:"image_name" hcl:"image_name"`
|
|
||||||
ImageDescription *string `mapstructure:"image_description" required:"false" cty:"image_description" hcl:"image_description"`
|
|
||||||
ImageTags map[string]string `mapstructure:"image_tags" required:"false" cty:"image_tags" hcl:"image_tags"`
|
|
||||||
ImageTag []config.FlatKeyValue `mapstructure:"image_tag" required:"false" cty:"image_tag" hcl:"image_tag"`
|
|
||||||
ImageService *string `mapstructure:"image_service" required:"false" cty:"image_service" hcl:"image_service"`
|
|
||||||
VmType *string `mapstructure:"vm_type" required:"true" cty:"vm_type" hcl:"vm_type"`
|
|
||||||
VmName *string `mapstructure:"vm_name" required:"false" cty:"vm_name" hcl:"vm_name"`
|
|
||||||
VmTags map[string]string `mapstructure:"vm_tags" required:"false" cty:"vm_tags" hcl:"vm_tags"`
|
|
||||||
VmTag []config.FlatNameValue `mapstructure:"vm_tag" required:"false" cty:"vm_tag" hcl:"vm_tag"`
|
|
||||||
DiskName *string `mapstructure:"disk_name" required:"false" cty:"disk_name" hcl:"disk_name"`
|
|
||||||
DiskType *string `mapstructure:"disk_type" required:"false" cty:"disk_type" hcl:"disk_type"`
|
|
||||||
DiskSize *float32 `mapstructure:"disk_size" required:"true" cty:"disk_size" hcl:"disk_size"`
|
|
||||||
Network *string `mapstructure:"network" required:"false" cty:"network" hcl:"network"`
|
|
||||||
PrivateIP *string `mapstructure:"private_ip" required:"false" cty:"private_ip" hcl:"private_ip"`
|
|
||||||
PublicIP *string `mapstructure:"public_ip" required:"false" cty:"public_ip" hcl:"public_ip"`
|
|
||||||
PublicNetAdpService *string `mapstructure:"public_netadp_service" required:"false" cty:"public_netadp_service" hcl:"public_netadp_service"`
|
|
||||||
ChrootDevice *string `mapstructure:"chroot_device" cty:"chroot_device" hcl:"chroot_device"`
|
|
||||||
ChrootDisk *bool `mapstructure:"chroot_disk" cty:"chroot_disk" hcl:"chroot_disk"`
|
|
||||||
ChrootDiskSize *float32 `mapstructure:"chroot_disk_size" cty:"chroot_disk_size" hcl:"chroot_disk_size"`
|
|
||||||
ChrootDiskType *string `mapstructure:"chroot_disk_type" cty:"chroot_disk_type" hcl:"chroot_disk_type"`
|
|
||||||
ChrootMountPath *string `mapstructure:"chroot_mount_path" cty:"chroot_mount_path" hcl:"chroot_mount_path"`
|
|
||||||
ChrootMounts [][]string `mapstructure:"chroot_mounts" cty:"chroot_mounts" hcl:"chroot_mounts"`
|
|
||||||
ChrootCopyFiles []string `mapstructure:"chroot_copy_files" cty:"chroot_copy_files" hcl:"chroot_copy_files"`
|
|
||||||
ChrootCommandWrapper *string `mapstructure:"chroot_command_wrapper" cty:"chroot_command_wrapper" hcl:"chroot_command_wrapper"`
|
|
||||||
MountOptions []string `mapstructure:"mount_options" cty:"mount_options" hcl:"mount_options"`
|
|
||||||
MountPartition *string `mapstructure:"mount_partition" cty:"mount_partition" hcl:"mount_partition"`
|
|
||||||
PreMountCommands []string `mapstructure:"pre_mount_commands" cty:"pre_mount_commands" hcl:"pre_mount_commands"`
|
|
||||||
PostMountCommands []string `mapstructure:"post_mount_commands" cty:"post_mount_commands" hcl:"post_mount_commands"`
|
|
||||||
SSHKeys []string `mapstructure:"ssh_keys" required:"false" cty:"ssh_keys" hcl:"ssh_keys"`
|
|
||||||
UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FlatMapstructure returns a new FlatConfig.
|
|
||||||
// FlatConfig is an auto-generated flat version of Config.
|
|
||||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
|
||||||
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
|
||||||
return new(FlatConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HCL2Spec returns the hcl spec of a Config.
|
|
||||||
// This spec is used by HCL to read the fields of Config.
|
|
||||||
// The decoded values from this spec will then be applied to a FlatConfig.
|
|
||||||
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
|
||||||
s := map[string]hcldec.Spec{
|
|
||||||
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
|
|
||||||
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
|
|
||||||
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
|
|
||||||
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
|
|
||||||
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
|
|
||||||
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
|
|
||||||
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
|
|
||||||
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
|
||||||
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
|
|
||||||
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
|
|
||||||
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
|
|
||||||
"ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false},
|
|
||||||
"ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false},
|
|
||||||
"ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false},
|
|
||||||
"ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false},
|
|
||||||
"temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false},
|
|
||||||
"temporary_key_pair_type": &hcldec.AttrSpec{Name: "temporary_key_pair_type", Type: cty.String, Required: false},
|
|
||||||
"temporary_key_pair_bits": &hcldec.AttrSpec{Name: "temporary_key_pair_bits", Type: cty.Number, Required: false},
|
|
||||||
"ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false},
|
|
||||||
"ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false},
|
|
||||||
"ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false},
|
|
||||||
"ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false},
|
|
||||||
"ssh_certificate_file": &hcldec.AttrSpec{Name: "ssh_certificate_file", Type: cty.String, Required: false},
|
|
||||||
"ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false},
|
|
||||||
"ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false},
|
|
||||||
"ssh_wait_timeout": &hcldec.AttrSpec{Name: "ssh_wait_timeout", Type: cty.String, Required: false},
|
|
||||||
"ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false},
|
|
||||||
"ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false},
|
|
||||||
"ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false},
|
|
||||||
"ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false},
|
|
||||||
"ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false},
|
|
||||||
"ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false},
|
|
||||||
"ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false},
|
|
||||||
"ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false},
|
|
||||||
"ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false},
|
|
||||||
"ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false},
|
|
||||||
"ssh_bastion_certificate_file": &hcldec.AttrSpec{Name: "ssh_bastion_certificate_file", Type: cty.String, Required: false},
|
|
||||||
"ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false},
|
|
||||||
"ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false},
|
|
||||||
"ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false},
|
|
||||||
"ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false},
|
|
||||||
"ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false},
|
|
||||||
"ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false},
|
|
||||||
"ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false},
|
|
||||||
"ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false},
|
|
||||||
"ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false},
|
|
||||||
"ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false},
|
|
||||||
"ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false},
|
|
||||||
"winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false},
|
|
||||||
"winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false},
|
|
||||||
"winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false},
|
|
||||||
"winrm_no_proxy": &hcldec.AttrSpec{Name: "winrm_no_proxy", Type: cty.Bool, Required: false},
|
|
||||||
"winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false},
|
|
||||||
"winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false},
|
|
||||||
"winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false},
|
|
||||||
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false},
|
|
||||||
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
|
||||||
"api_url": &hcldec.AttrSpec{Name: "api_url", Type: cty.String, Required: false},
|
|
||||||
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
|
||||||
"project": &hcldec.AttrSpec{Name: "project", Type: cty.String, Required: false},
|
|
||||||
"token_login": &hcldec.AttrSpec{Name: "token_login", Type: cty.String, Required: false},
|
|
||||||
"state_timeout": &hcldec.AttrSpec{Name: "state_timeout", Type: cty.String, Required: false},
|
|
||||||
"source_image": &hcldec.AttrSpec{Name: "source_image", Type: cty.String, Required: false},
|
|
||||||
"image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false},
|
|
||||||
"image_description": &hcldec.AttrSpec{Name: "image_description", Type: cty.String, Required: false},
|
|
||||||
"image_tags": &hcldec.AttrSpec{Name: "image_tags", Type: cty.Map(cty.String), Required: false},
|
|
||||||
"image_tag": &hcldec.BlockListSpec{TypeName: "image_tag", Nested: hcldec.ObjectSpec((*config.FlatKeyValue)(nil).HCL2Spec())},
|
|
||||||
"image_service": &hcldec.AttrSpec{Name: "image_service", Type: cty.String, Required: false},
|
|
||||||
"vm_type": &hcldec.AttrSpec{Name: "vm_type", Type: cty.String, Required: false},
|
|
||||||
"vm_name": &hcldec.AttrSpec{Name: "vm_name", Type: cty.String, Required: false},
|
|
||||||
"vm_tags": &hcldec.AttrSpec{Name: "vm_tags", Type: cty.Map(cty.String), Required: false},
|
|
||||||
"vm_tag": &hcldec.BlockListSpec{TypeName: "vm_tag", Nested: hcldec.ObjectSpec((*config.FlatNameValue)(nil).HCL2Spec())},
|
|
||||||
"disk_name": &hcldec.AttrSpec{Name: "disk_name", Type: cty.String, Required: false},
|
|
||||||
"disk_type": &hcldec.AttrSpec{Name: "disk_type", Type: cty.String, Required: false},
|
|
||||||
"disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false},
|
|
||||||
"network": &hcldec.AttrSpec{Name: "network", Type: cty.String, Required: false},
|
|
||||||
"private_ip": &hcldec.AttrSpec{Name: "private_ip", Type: cty.String, Required: false},
|
|
||||||
"public_ip": &hcldec.AttrSpec{Name: "public_ip", Type: cty.String, Required: false},
|
|
||||||
"public_netadp_service": &hcldec.AttrSpec{Name: "public_netadp_service", Type: cty.String, Required: false},
|
|
||||||
"chroot_device": &hcldec.AttrSpec{Name: "chroot_device", Type: cty.String, Required: false},
|
|
||||||
"chroot_disk": &hcldec.AttrSpec{Name: "chroot_disk", Type: cty.Bool, Required: false},
|
|
||||||
"chroot_disk_size": &hcldec.AttrSpec{Name: "chroot_disk_size", Type: cty.Number, Required: false},
|
|
||||||
"chroot_disk_type": &hcldec.AttrSpec{Name: "chroot_disk_type", Type: cty.String, Required: false},
|
|
||||||
"chroot_mount_path": &hcldec.AttrSpec{Name: "chroot_mount_path", Type: cty.String, Required: false},
|
|
||||||
"chroot_mounts": &hcldec.AttrSpec{Name: "chroot_mounts", Type: cty.List(cty.List(cty.String)), Required: false},
|
|
||||||
"chroot_copy_files": &hcldec.AttrSpec{Name: "chroot_copy_files", Type: cty.List(cty.String), Required: false},
|
|
||||||
"chroot_command_wrapper": &hcldec.AttrSpec{Name: "chroot_command_wrapper", Type: cty.String, Required: false},
|
|
||||||
"mount_options": &hcldec.AttrSpec{Name: "mount_options", Type: cty.List(cty.String), Required: false},
|
|
||||||
"mount_partition": &hcldec.AttrSpec{Name: "mount_partition", Type: cty.String, Required: false},
|
|
||||||
"pre_mount_commands": &hcldec.AttrSpec{Name: "pre_mount_commands", Type: cty.List(cty.String), Required: false},
|
|
||||||
"post_mount_commands": &hcldec.AttrSpec{Name: "post_mount_commands", Type: cty.List(cty.String), Required: false},
|
|
||||||
"ssh_keys": &hcldec.AttrSpec{Name: "ssh_keys", Type: cty.List(cty.String), Required: false},
|
|
||||||
"user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false},
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"variables": {
|
|
||||||
"token": "{{ env `HYPERONE_TOKEN` }}",
|
|
||||||
"project": "{{ env `HYPERONE_PROJECT` }}"
|
|
||||||
},
|
|
||||||
"builders": [
|
|
||||||
{
|
|
||||||
"token": "{{ user `token` }}",
|
|
||||||
"project": "{{ user `project` }}",
|
|
||||||
"type": "hyperone",
|
|
||||||
"source_image": "ubuntu",
|
|
||||||
"disk_size": 10,
|
|
||||||
"vm_type": "a1.nano"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"provisioners": [
|
|
||||||
{
|
|
||||||
"type": "shell",
|
|
||||||
"inline": [
|
|
||||||
"apt-get update",
|
|
||||||
"apt-get upgrade -y"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
{
|
|
||||||
"variables": {
|
|
||||||
"token": "{{ env `HYPERONE_TOKEN` }}",
|
|
||||||
"project": "{{ env `HYPERONE_PROJECT` }}"
|
|
||||||
},
|
|
||||||
"builders": [
|
|
||||||
{
|
|
||||||
"token": "{{ user `token` }}",
|
|
||||||
"project": "{{ user `project` }}",
|
|
||||||
"type": "hyperone",
|
|
||||||
"source_image": "ubuntu",
|
|
||||||
"disk_size": 10,
|
|
||||||
"vm_type": "a1.nano",
|
|
||||||
|
|
||||||
"chroot_disk": true,
|
|
||||||
"chroot_command_wrapper": "sudo {{.Command}}",
|
|
||||||
"pre_mount_commands": [
|
|
||||||
"parted {{.Device}} mklabel msdos mkpart primary 1M 100% set 1 boot on print",
|
|
||||||
"mkfs.ext4 {{.Device}}1"
|
|
||||||
],
|
|
||||||
"post_mount_commands": [
|
|
||||||
"apt-get update",
|
|
||||||
"apt-get install debootstrap",
|
|
||||||
"debootstrap --arch amd64 bionic {{.MountPath}}"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"provisioners": []
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
variable "token" {
|
|
||||||
type = string
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "project" {
|
|
||||||
type = string
|
|
||||||
}
|
|
||||||
|
|
||||||
source "hyperone" "new-syntax" {
|
|
||||||
token = var.token
|
|
||||||
project = var.project
|
|
||||||
source_image = "debian"
|
|
||||||
disk_size = 10
|
|
||||||
vm_type = "a1.nano"
|
|
||||||
image_name = "packerbats-hcl-{{timestamp}}"
|
|
||||||
image_tags = {
|
|
||||||
key="value"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
build {
|
|
||||||
sources = [
|
|
||||||
"source.hyperone.new-syntax"
|
|
||||||
]
|
|
||||||
|
|
||||||
provisioner "shell" {
|
|
||||||
inline = [
|
|
||||||
"apt-get update",
|
|
||||||
"apt-get upgrade -y"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
)
|
|
||||||
|
|
||||||
type stepChrootProvision struct{}
|
|
||||||
|
|
||||||
func (s *stepChrootProvision) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
config := state.Get("config").(*Config)
|
|
||||||
wrappedCommand := state.Get("wrappedCommand").(CommandWrapper)
|
|
||||||
sshCommunicator := state.Get("communicator").(packersdk.Communicator)
|
|
||||||
|
|
||||||
comm := &ChrootCommunicator{
|
|
||||||
Chroot: config.ChrootMountPath,
|
|
||||||
CmdWrapper: wrappedCommand,
|
|
||||||
Wrapped: sshCommunicator,
|
|
||||||
}
|
|
||||||
|
|
||||||
stepProvision := commonsteps.StepProvision{Comm: comm}
|
|
||||||
return stepProvision.Run(ctx, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepChrootProvision) Cleanup(multistep.StateBag) {}
|
|
|
@ -1,40 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
)
|
|
||||||
|
|
||||||
type stepCopyFiles struct{}
|
|
||||||
|
|
||||||
func (s *stepCopyFiles) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
config := state.Get("config").(*Config)
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
|
|
||||||
if len(config.ChrootCopyFiles) == 0 {
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.Say("Copying files from host to chroot...")
|
|
||||||
for _, path := range config.ChrootCopyFiles {
|
|
||||||
chrootPath := filepath.Join(config.ChrootMountPath, path)
|
|
||||||
log.Printf("Copying '%s' to '%s'", path, chrootPath)
|
|
||||||
|
|
||||||
command := fmt.Sprintf("cp --remove-destination %s %s", path, chrootPath)
|
|
||||||
err := runCommands([]string{command}, config.ctx, state)
|
|
||||||
if err != nil {
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepCopyFiles) Cleanup(state multistep.StateBag) {}
|
|
|
@ -1,65 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
openapi "github.com/hyperonecom/h1-client-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
type stepCreateImage struct {
|
|
||||||
imageID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
client := state.Get("client").(*openapi.APIClient)
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
config := state.Get("config").(*Config)
|
|
||||||
vmID := state.Get("vm_id").(string)
|
|
||||||
|
|
||||||
ui.Say("Creating image...")
|
|
||||||
|
|
||||||
image, _, err := client.ImageApi.ImageCreate(ctx, openapi.ImageCreate{
|
|
||||||
Name: config.ImageName,
|
|
||||||
Vm: vmID,
|
|
||||||
Service: config.ImageService,
|
|
||||||
Description: config.ImageDescription,
|
|
||||||
Tag: config.ImageTags,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("error creating image: %s", formatOpenAPIError(err))
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
s.imageID = image.Id
|
|
||||||
|
|
||||||
state.Put("image_id", image.Id)
|
|
||||||
state.Put("image_name", image.Name)
|
|
||||||
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepCreateImage) Cleanup(state multistep.StateBag) {
|
|
||||||
if s.imageID == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
|
||||||
_, halted := state.GetOk(multistep.StateHalted)
|
|
||||||
if !cancelled && !halted {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
client := state.Get("client").(*openapi.APIClient)
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
|
|
||||||
_, err := client.ImageApi.ImageDelete(context.TODO(), s.imageID)
|
|
||||||
if err != nil {
|
|
||||||
ui.Error(fmt.Sprintf("error deleting image '%s' - consider deleting it manually: %s",
|
|
||||||
s.imageID, formatOpenAPIError(err)))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/rsa"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/pem"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
)
|
|
||||||
|
|
||||||
type stepCreateSSHKey struct {
|
|
||||||
Debug bool
|
|
||||||
DebugKeyPath string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepCreateSSHKey) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
c := state.Get("config").(*Config)
|
|
||||||
ui.Say("Creating a temporary ssh key for the VM...")
|
|
||||||
|
|
||||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
||||||
if err != nil {
|
|
||||||
state.Put("error", fmt.Errorf("error generating ssh key: %s", err))
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
privDER := x509.MarshalPKCS1PrivateKey(priv)
|
|
||||||
privBLK := pem.Block{
|
|
||||||
Type: "RSA PRIVATE KEY",
|
|
||||||
Headers: nil,
|
|
||||||
Bytes: privDER,
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Comm.SSHPrivateKey = pem.EncodeToMemory(&privBLK)
|
|
||||||
|
|
||||||
pub, err := ssh.NewPublicKey(&priv.PublicKey)
|
|
||||||
if err != nil {
|
|
||||||
state.Put("error", fmt.Errorf("error getting public key: %s", err))
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
pubSSHFormat := string(ssh.MarshalAuthorizedKey(pub))
|
|
||||||
|
|
||||||
// Remember public SSH key for future connections
|
|
||||||
state.Put("ssh_public_key", pubSSHFormat)
|
|
||||||
|
|
||||||
// If we're in debug mode, output the private key to the working directory.
|
|
||||||
if s.Debug {
|
|
||||||
ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath))
|
|
||||||
f, err := os.Create(s.DebugKeyPath)
|
|
||||||
if err != nil {
|
|
||||||
state.Put("error", fmt.Errorf("error saving debug key: %s", err))
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
// Write the key out
|
|
||||||
if _, err := f.Write(pem.EncodeToMemory(&privBLK)); err != nil {
|
|
||||||
state.Put("error", fmt.Errorf("error saving debug key: %s", err))
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chmod it so that it is SSH ready
|
|
||||||
if runtime.GOOS != "windows" {
|
|
||||||
if err := f.Chmod(0600); err != nil {
|
|
||||||
state.Put("error", fmt.Errorf("error setting permissions of debug key: %s", err))
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepCreateSSHKey) Cleanup(state multistep.StateBag) {}
|
|
|
@ -1,203 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
openapi "github.com/hyperonecom/h1-client-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
type stepCreateVM struct {
|
|
||||||
vmID string
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
chrootDiskName = "packer-chroot-disk"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *stepCreateVM) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
client := state.Get("client").(*openapi.APIClient)
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
config := state.Get("config").(*Config)
|
|
||||||
sshKey := state.Get("ssh_public_key").(string)
|
|
||||||
|
|
||||||
ui.Say("Creating VM...")
|
|
||||||
|
|
||||||
netAdapter := pickNetAdapter(config)
|
|
||||||
|
|
||||||
var sshKeys = []string{sshKey}
|
|
||||||
sshKeys = append(sshKeys, config.SSHKeys...)
|
|
||||||
|
|
||||||
disks := []openapi.VmCreateDisk{
|
|
||||||
{
|
|
||||||
Service: config.DiskType,
|
|
||||||
Size: config.DiskSize,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.ChrootDisk {
|
|
||||||
disks = append(disks, openapi.VmCreateDisk{
|
|
||||||
Service: config.ChrootDiskType,
|
|
||||||
Size: config.ChrootDiskSize,
|
|
||||||
Name: chrootDiskName,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
options := openapi.VmCreate{
|
|
||||||
Name: config.VmName,
|
|
||||||
Image: config.SourceImage,
|
|
||||||
Service: config.VmType,
|
|
||||||
SshKeys: sshKeys,
|
|
||||||
Disk: disks,
|
|
||||||
Netadp: []openapi.VmCreateNetadp{netAdapter},
|
|
||||||
UserMetadata: config.UserData,
|
|
||||||
Tag: config.VmTags,
|
|
||||||
Username: config.Comm.SSHUsername,
|
|
||||||
}
|
|
||||||
|
|
||||||
vm, _, err := client.VmApi.VmCreate(ctx, options)
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("error creating VM: %s", formatOpenAPIError(err))
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
s.vmID = vm.Id
|
|
||||||
state.Put("vm_id", vm.Id)
|
|
||||||
// instance_id is the generic term used so that users can have access to the
|
|
||||||
// instance id inside of the provisioners, used in step_provision.
|
|
||||||
state.Put("instance_id", vm.Id)
|
|
||||||
|
|
||||||
hdds, _, err := client.VmApi.VmListHdd(ctx, vm.Id)
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("error listing hdd: %s", formatOpenAPIError(err))
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, hdd := range hdds {
|
|
||||||
if hdd.Disk.Name == chrootDiskName {
|
|
||||||
state.Put("chroot_disk_id", hdd.Disk.Id)
|
|
||||||
controllerNumber := strings.ToLower(strings.Trim(hdd.ControllerNumber, "{}"))
|
|
||||||
state.Put("chroot_controller_number", controllerNumber)
|
|
||||||
state.Put("chroot_controller_location", int(hdd.ControllerLocation))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
netadp, _, err := client.VmApi.VmListNetadp(ctx, vm.Id)
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("error listing netadp: %s", formatOpenAPIError(err))
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(netadp) < 1 {
|
|
||||||
err := fmt.Errorf("no network adapters found")
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
publicIP, err := associatePublicIP(ctx, config, client, netadp[0])
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("error associating IP: %s", formatOpenAPIError(err))
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
state.Put("public_ip", publicIP)
|
|
||||||
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
func pickNetAdapter(config *Config) openapi.VmCreateNetadp {
|
|
||||||
if config.Network == "" {
|
|
||||||
if config.PublicIP != "" {
|
|
||||||
return openapi.VmCreateNetadp{
|
|
||||||
Service: config.PublicNetAdpService,
|
|
||||||
Ip: []string{config.PublicIP},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var privateIPs []string
|
|
||||||
|
|
||||||
if config.PrivateIP == "" {
|
|
||||||
privateIPs = nil
|
|
||||||
} else {
|
|
||||||
privateIPs = []string{config.PrivateIP}
|
|
||||||
}
|
|
||||||
|
|
||||||
return openapi.VmCreateNetadp{
|
|
||||||
Service: "private",
|
|
||||||
Network: config.Network,
|
|
||||||
Ip: privateIPs,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return openapi.VmCreateNetadp{
|
|
||||||
Service: config.PublicNetAdpService,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func associatePublicIP(ctx context.Context, config *Config, client *openapi.APIClient, netadp openapi.Netadp) (string, error) {
|
|
||||||
if config.Network == "" || config.PublicIP == "" {
|
|
||||||
// Public IP belongs to attached net adapter
|
|
||||||
return netadp.Ip[0].Address, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var privateIP string
|
|
||||||
if config.PrivateIP == "" {
|
|
||||||
privateIP = netadp.Ip[0].Id
|
|
||||||
} else {
|
|
||||||
privateIP = config.PrivateIP
|
|
||||||
}
|
|
||||||
|
|
||||||
ip, _, err := client.IpApi.IpActionAssociate(ctx, config.PublicIP, openapi.IpActionAssociate{Ip: privateIP})
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return ip.Address, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepCreateVM) Cleanup(state multistep.StateBag) {
|
|
||||||
if s.vmID == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Deleting VM %s...", s.vmID))
|
|
||||||
err := deleteVMWithDisks(s.vmID, state)
|
|
||||||
if err != nil {
|
|
||||||
ui.Error(err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteVMWithDisks(vmID string, state multistep.StateBag) error {
|
|
||||||
client := state.Get("client").(*openapi.APIClient)
|
|
||||||
hdds, _, err := client.VmApi.VmListHdd(context.TODO(), vmID)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error listing hdd: %s", formatOpenAPIError(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteOptions := openapi.VmDelete{}
|
|
||||||
for _, hdd := range hdds {
|
|
||||||
deleteOptions.RemoveDisks = append(deleteOptions.RemoveDisks, hdd.Disk.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = client.VmApi.VmDelete(context.TODO(), vmID, deleteOptions)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error deleting server '%s' - please delete it manually: %s", vmID, formatOpenAPIError(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
openapi "github.com/hyperonecom/h1-client-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
type stepCreateVMFromDisk struct {
|
|
||||||
vmID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepCreateVMFromDisk) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
client := state.Get("client").(*openapi.APIClient)
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
config := state.Get("config").(*Config)
|
|
||||||
sshKey := state.Get("ssh_public_key").(string)
|
|
||||||
chrootDiskID := state.Get("chroot_disk_id").(string)
|
|
||||||
|
|
||||||
ui.Say("Creating VM from disk...")
|
|
||||||
|
|
||||||
options := openapi.VmCreate{
|
|
||||||
Name: config.VmName,
|
|
||||||
Service: config.VmType,
|
|
||||||
Disk: []openapi.VmCreateDisk{
|
|
||||||
{
|
|
||||||
Id: chrootDiskID,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
SshKeys: []string{sshKey},
|
|
||||||
Boot: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
vm, _, err := client.VmApi.VmCreate(ctx, options)
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("error creating VM from disk: %s", formatOpenAPIError(err))
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
s.vmID = vm.Id
|
|
||||||
state.Put("vm_id", vm.Id)
|
|
||||||
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepCreateVMFromDisk) Cleanup(state multistep.StateBag) {
|
|
||||||
if s.vmID == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Deleting VM %s (from chroot disk)...", s.vmID))
|
|
||||||
err := deleteVMWithDisks(s.vmID, state)
|
|
||||||
if err != nil {
|
|
||||||
ui.Error(err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,116 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
openapi "github.com/hyperonecom/h1-client-go"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPickNetAdapter(t *testing.T) {
|
|
||||||
cases := []struct {
|
|
||||||
Name string
|
|
||||||
Config Config
|
|
||||||
Expected openapi.VmCreateNetadp
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Name: "no_network",
|
|
||||||
Config: Config{
|
|
||||||
PublicNetAdpService: "public",
|
|
||||||
},
|
|
||||||
Expected: openapi.VmCreateNetadp{
|
|
||||||
Service: "public",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "no_network_public_ip",
|
|
||||||
Config: Config{
|
|
||||||
PublicIP: "some-public-ip",
|
|
||||||
PublicNetAdpService: "public",
|
|
||||||
},
|
|
||||||
Expected: openapi.VmCreateNetadp{
|
|
||||||
Service: "public",
|
|
||||||
Ip: []string{"some-public-ip"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "no_network_private_ip",
|
|
||||||
Config: Config{
|
|
||||||
PrivateIP: "some-private-ip",
|
|
||||||
PublicNetAdpService: "public",
|
|
||||||
},
|
|
||||||
Expected: openapi.VmCreateNetadp{
|
|
||||||
Service: "public",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "no_network_both_ip",
|
|
||||||
Config: Config{
|
|
||||||
PublicIP: "some-public-ip",
|
|
||||||
PrivateIP: "some-private-ip",
|
|
||||||
PublicNetAdpService: "public",
|
|
||||||
},
|
|
||||||
Expected: openapi.VmCreateNetadp{
|
|
||||||
Service: "public",
|
|
||||||
Ip: []string{"some-public-ip"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "network_no_ip",
|
|
||||||
Config: Config{
|
|
||||||
Network: "some-network",
|
|
||||||
PublicNetAdpService: "public",
|
|
||||||
},
|
|
||||||
Expected: openapi.VmCreateNetadp{
|
|
||||||
Service: "private",
|
|
||||||
Network: "some-network",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "network_public_ip",
|
|
||||||
Config: Config{
|
|
||||||
Network: "some-network",
|
|
||||||
PublicIP: "some-public-ip",
|
|
||||||
PublicNetAdpService: "public",
|
|
||||||
},
|
|
||||||
Expected: openapi.VmCreateNetadp{
|
|
||||||
Service: "private",
|
|
||||||
Network: "some-network",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "network_private_ip",
|
|
||||||
Config: Config{
|
|
||||||
Network: "some-network",
|
|
||||||
PrivateIP: "some-private-ip",
|
|
||||||
PublicNetAdpService: "public",
|
|
||||||
},
|
|
||||||
Expected: openapi.VmCreateNetadp{
|
|
||||||
Service: "private",
|
|
||||||
Network: "some-network",
|
|
||||||
Ip: []string{"some-private-ip"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "network_both_ip",
|
|
||||||
Config: Config{
|
|
||||||
Network: "some-network",
|
|
||||||
PublicIP: "some-public-ip",
|
|
||||||
PrivateIP: "some-private-ip",
|
|
||||||
PublicNetAdpService: "public",
|
|
||||||
},
|
|
||||||
Expected: openapi.VmCreateNetadp{
|
|
||||||
Service: "private",
|
|
||||||
Network: "some-network",
|
|
||||||
Ip: []string{"some-private-ip"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range cases {
|
|
||||||
t.Run(c.Name, func(t *testing.T) {
|
|
||||||
result := pickNetAdapter(&c.Config)
|
|
||||||
assert.Equal(t, c.Expected, result)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
openapi "github.com/hyperonecom/h1-client-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
type stepDetachDisk struct {
|
|
||||||
vmID string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepDetachDisk) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
client := state.Get("client").(*openapi.APIClient)
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
vmID := state.Get("vm_id").(string)
|
|
||||||
chrootDiskID := state.Get("chroot_disk_id").(string)
|
|
||||||
|
|
||||||
ui.Say("Detaching chroot disk...")
|
|
||||||
_, _, err := client.VmApi.VmDeleteHddDiskId(ctx, vmID, chrootDiskID)
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("error detaching disk: %s", formatOpenAPIError(err))
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepDetachDisk) Cleanup(state multistep.StateBag) {}
|
|
|
@ -1,51 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
)
|
|
||||||
|
|
||||||
type stepMountChroot struct{}
|
|
||||||
|
|
||||||
func (s *stepMountChroot) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
config := state.Get("config").(*Config)
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
device := state.Get("device").(string)
|
|
||||||
|
|
||||||
log.Printf("Mount path: %s", config.ChrootMountPath)
|
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Creating mount directory: %s", config.ChrootMountPath))
|
|
||||||
|
|
||||||
opts := ""
|
|
||||||
if len(config.MountOptions) > 0 {
|
|
||||||
opts = "-o " + strings.Join(config.MountOptions, " -o ")
|
|
||||||
}
|
|
||||||
|
|
||||||
deviceMount := device
|
|
||||||
if config.MountPartition != "" {
|
|
||||||
deviceMount = fmt.Sprintf("%s%s", device, config.MountPartition)
|
|
||||||
}
|
|
||||||
|
|
||||||
commands := []string{
|
|
||||||
fmt.Sprintf("mkdir -m 755 -p %s", config.ChrootMountPath),
|
|
||||||
fmt.Sprintf("mount %s %s %s", opts, deviceMount, config.ChrootMountPath),
|
|
||||||
}
|
|
||||||
|
|
||||||
err := runCommands(commands, config.ctx, state)
|
|
||||||
if err != nil {
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
state.Put("mount_path", config.ChrootMountPath)
|
|
||||||
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepMountChroot) Cleanup(state multistep.StateBag) {}
|
|
|
@ -1,45 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
)
|
|
||||||
|
|
||||||
type stepMountExtra struct{}
|
|
||||||
|
|
||||||
func (s *stepMountExtra) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
config := state.Get("config").(*Config)
|
|
||||||
mountPath := state.Get("mount_path").(string)
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
|
|
||||||
ui.Say("Mounting additional paths within the chroot...")
|
|
||||||
for _, mountInfo := range config.ChrootMounts {
|
|
||||||
innerPath := mountPath + mountInfo[2]
|
|
||||||
|
|
||||||
flags := "-t " + mountInfo[0]
|
|
||||||
if mountInfo[0] == "bind" {
|
|
||||||
flags = "--bind"
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.Message(fmt.Sprintf("Mounting: %s", mountInfo[2]))
|
|
||||||
|
|
||||||
commands := []string{
|
|
||||||
fmt.Sprintf("mkdir -m 755 -p %s", innerPath),
|
|
||||||
fmt.Sprintf("mount %s %s %s", flags, mountInfo[1], innerPath),
|
|
||||||
}
|
|
||||||
|
|
||||||
err := runCommands(commands, config.ctx, state)
|
|
||||||
if err != nil {
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepMountExtra) Cleanup(state multistep.StateBag) {}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
)
|
|
||||||
|
|
||||||
type postMountCommandsData struct {
|
|
||||||
Device string
|
|
||||||
MountPath string
|
|
||||||
}
|
|
||||||
|
|
||||||
type stepPostMountCommands struct{}
|
|
||||||
|
|
||||||
func (s *stepPostMountCommands) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
config := state.Get("config").(*Config)
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
device := state.Get("device").(string)
|
|
||||||
|
|
||||||
ictx := config.ctx
|
|
||||||
ictx.Data = &postMountCommandsData{
|
|
||||||
Device: device,
|
|
||||||
MountPath: config.ChrootMountPath,
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.Say("Running post-mount commands...")
|
|
||||||
if err := runCommands(config.PostMountCommands, ictx, state); err != nil {
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepPostMountCommands) Cleanup(state multistep.StateBag) {}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
)
|
|
||||||
|
|
||||||
type preMountCommandsData struct {
|
|
||||||
Device string
|
|
||||||
MountPath string
|
|
||||||
}
|
|
||||||
|
|
||||||
type stepPreMountCommands struct{}
|
|
||||||
|
|
||||||
func (s *stepPreMountCommands) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
config := state.Get("config").(*Config)
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
device := state.Get("device").(string)
|
|
||||||
|
|
||||||
ictx := config.ctx
|
|
||||||
ictx.Data = &preMountCommandsData{
|
|
||||||
Device: device,
|
|
||||||
MountPath: config.ChrootMountPath,
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.Say("Running pre-mount commands...")
|
|
||||||
if err := runCommands(config.PreMountCommands, ictx, state); err != nil {
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepPreMountCommands) Cleanup(state multistep.StateBag) {}
|
|
|
@ -1,57 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
vmBusPath = "/sys/bus/vmbus/devices"
|
|
||||||
)
|
|
||||||
|
|
||||||
type stepPrepareDevice struct{}
|
|
||||||
|
|
||||||
func (s *stepPrepareDevice) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
config := state.Get("config").(*Config)
|
|
||||||
|
|
||||||
if config.ChrootDevice != "" {
|
|
||||||
state.Put("device", config.ChrootDevice)
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
controllerNumber := state.Get("chroot_controller_number").(string)
|
|
||||||
controllerLocation := state.Get("chroot_controller_location").(int)
|
|
||||||
|
|
||||||
log.Println("Searching for available device...")
|
|
||||||
|
|
||||||
cmd := fmt.Sprintf("find %s/%s/ -path *:%d/block -exec ls {} \\;",
|
|
||||||
vmBusPath, controllerNumber, controllerLocation)
|
|
||||||
|
|
||||||
block, err := captureOutput(cmd, state)
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("error finding available device: %s", err)
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
if block == "" {
|
|
||||||
err := fmt.Errorf("device not found")
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
device := fmt.Sprintf("/dev/%s", block)
|
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Found device: %s", device))
|
|
||||||
state.Put("device", device)
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepPrepareDevice) Cleanup(state multistep.StateBag) {}
|
|
|
@ -1,32 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
openapi "github.com/hyperonecom/h1-client-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
type stepStopVM struct{}
|
|
||||||
|
|
||||||
func (s *stepStopVM) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
|
||||||
client := state.Get("client").(*openapi.APIClient)
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
vmID := state.Get("vm_id").(string)
|
|
||||||
|
|
||||||
ui.Say("Stopping VM...")
|
|
||||||
|
|
||||||
_, _, err := client.VmApi.VmActionStop(ctx, vmID)
|
|
||||||
if err != nil {
|
|
||||||
err := fmt.Errorf("error stopping VM: %s", formatOpenAPIError(err))
|
|
||||||
state.Put("error", err)
|
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
return multistep.ActionContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stepStopVM) Cleanup(multistep.StateBag) {}
|
|
|
@ -1,89 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/sha1"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
"golang.org/x/crypto/ssh/agent"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
sshAddress = "api.hyperone.com:22"
|
|
||||||
sshSubsystem = "rbx-auth"
|
|
||||||
hostKeyHash = "3e2aa423d42d7e8b14d50625512c8ac19db767ed"
|
|
||||||
)
|
|
||||||
|
|
||||||
type sshData struct {
|
|
||||||
ID string `json:"_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func sshAgent() ssh.AuthMethod {
|
|
||||||
if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
|
|
||||||
return ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func fetchTokenBySSH(user string) (string, error) {
|
|
||||||
sshConfig := &ssh.ClientConfig{
|
|
||||||
User: user,
|
|
||||||
Auth: []ssh.AuthMethod{
|
|
||||||
sshAgent(),
|
|
||||||
},
|
|
||||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
|
||||||
hash := sha1Sum(key)
|
|
||||||
if hash != hostKeyHash {
|
|
||||||
return fmt.Errorf("invalid host key hash: %s", hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := ssh.Dial("tcp", sshAddress, sshConfig)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer client.Close()
|
|
||||||
|
|
||||||
session, err := client.NewSession()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer session.Close()
|
|
||||||
|
|
||||||
stdout, err := session.StdoutPipe()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = session.RequestSubsystem(sshSubsystem)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := ioutil.ReadAll(stdout)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
var data sshData
|
|
||||||
err = json.Unmarshal(out, &data)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.ID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func sha1Sum(pubKey ssh.PublicKey) string {
|
|
||||||
sum := sha1.Sum(pubKey.Marshal())
|
|
||||||
return hex.EncodeToString(sum[:])
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
package hyperone
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
||||||
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
|
|
||||||
openapi "github.com/hyperonecom/h1-client-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
func formatOpenAPIError(err error) string {
|
|
||||||
openAPIError, ok := err.(openapi.GenericOpenAPIError)
|
|
||||||
if !ok {
|
|
||||||
return err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("%s (body: %s)", openAPIError.Error(), openAPIError.Body())
|
|
||||||
}
|
|
||||||
|
|
||||||
func runCommands(commands []string, ictx interpolate.Context, state multistep.StateBag) error {
|
|
||||||
ctx := context.TODO()
|
|
||||||
ui := state.Get("ui").(packersdk.Ui)
|
|
||||||
wrappedCommand := state.Get("wrappedCommand").(CommandWrapper)
|
|
||||||
comm := state.Get("communicator").(packersdk.Communicator)
|
|
||||||
|
|
||||||
for _, rawCmd := range commands {
|
|
||||||
intCmd, err := interpolate.Render(rawCmd, &ictx)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error interpolating: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
command, err := wrappedCommand(intCmd)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error wrapping command: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
remoteCmd := &packersdk.RemoteCmd{
|
|
||||||
Command: command,
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Executing command: %s", command))
|
|
||||||
|
|
||||||
err = remoteCmd.RunWithUi(ctx, comm, ui)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error running remote cmd: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if remoteCmd.ExitStatus() != 0 {
|
|
||||||
return fmt.Errorf(
|
|
||||||
"received non-zero exit code %d from command: %s",
|
|
||||||
remoteCmd.ExitStatus(),
|
|
||||||
command)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func captureOutput(command string, state multistep.StateBag) (string, error) {
|
|
||||||
ctx := context.TODO()
|
|
||||||
comm := state.Get("communicator").(packersdk.Communicator)
|
|
||||||
|
|
||||||
var stdout bytes.Buffer
|
|
||||||
remoteCmd := &packersdk.RemoteCmd{
|
|
||||||
Command: command,
|
|
||||||
Stdout: &stdout,
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Println(fmt.Sprintf("Executing command: %s", command))
|
|
||||||
|
|
||||||
err := comm.Start(ctx, remoteCmd)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("error running remote cmd: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
remoteCmd.Wait()
|
|
||||||
if remoteCmd.ExitStatus() != 0 {
|
|
||||||
return "", fmt.Errorf(
|
|
||||||
"received non-zero exit code %d from command: %s",
|
|
||||||
remoteCmd.ExitStatus(),
|
|
||||||
command)
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.TrimSpace(stdout.String()), nil
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package version
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/hashicorp/packer-plugin-sdk/version"
|
|
||||||
packerVersion "github.com/hashicorp/packer/version"
|
|
||||||
)
|
|
||||||
|
|
||||||
var HyperonePluginVersion *version.PluginVersion
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
HyperonePluginVersion = version.InitializePluginVersion(
|
|
||||||
packerVersion.Version, packerVersion.VersionPrerelease)
|
|
||||||
}
|
|
|
@ -19,7 +19,6 @@ import (
|
||||||
digitaloceanbuilder "github.com/hashicorp/packer/builder/digitalocean"
|
digitaloceanbuilder "github.com/hashicorp/packer/builder/digitalocean"
|
||||||
filebuilder "github.com/hashicorp/packer/builder/file"
|
filebuilder "github.com/hashicorp/packer/builder/file"
|
||||||
hcloudbuilder "github.com/hashicorp/packer/builder/hcloud"
|
hcloudbuilder "github.com/hashicorp/packer/builder/hcloud"
|
||||||
hyperonebuilder "github.com/hashicorp/packer/builder/hyperone"
|
|
||||||
hypervisobuilder "github.com/hashicorp/packer/builder/hyperv/iso"
|
hypervisobuilder "github.com/hashicorp/packer/builder/hyperv/iso"
|
||||||
hypervvmcxbuilder "github.com/hashicorp/packer/builder/hyperv/vmcx"
|
hypervvmcxbuilder "github.com/hashicorp/packer/builder/hyperv/vmcx"
|
||||||
jdcloudbuilder "github.com/hashicorp/packer/builder/jdcloud"
|
jdcloudbuilder "github.com/hashicorp/packer/builder/jdcloud"
|
||||||
|
@ -72,7 +71,6 @@ var Builders = map[string]packersdk.Builder{
|
||||||
"digitalocean": new(digitaloceanbuilder.Builder),
|
"digitalocean": new(digitaloceanbuilder.Builder),
|
||||||
"file": new(filebuilder.Builder),
|
"file": new(filebuilder.Builder),
|
||||||
"hcloud": new(hcloudbuilder.Builder),
|
"hcloud": new(hcloudbuilder.Builder),
|
||||||
"hyperone": new(hyperonebuilder.Builder),
|
|
||||||
"hyperv-iso": new(hypervisobuilder.Builder),
|
"hyperv-iso": new(hypervisobuilder.Builder),
|
||||||
"hyperv-vmcx": new(hypervvmcxbuilder.Builder),
|
"hyperv-vmcx": new(hypervvmcxbuilder.Builder),
|
||||||
"jdcloud": new(jdcloudbuilder.Builder),
|
"jdcloud": new(jdcloudbuilder.Builder),
|
||||||
|
|
|
@ -30,6 +30,7 @@ import (
|
||||||
googlecomputebuilder "github.com/hashicorp/packer-plugin-googlecompute/builder/googlecompute"
|
googlecomputebuilder "github.com/hashicorp/packer-plugin-googlecompute/builder/googlecompute"
|
||||||
googlecomputeexportpostprocessor "github.com/hashicorp/packer-plugin-googlecompute/post-processor/googlecompute-export"
|
googlecomputeexportpostprocessor "github.com/hashicorp/packer-plugin-googlecompute/post-processor/googlecompute-export"
|
||||||
googlecomputeimportpostprocessor "github.com/hashicorp/packer-plugin-googlecompute/post-processor/googlecompute-import"
|
googlecomputeimportpostprocessor "github.com/hashicorp/packer-plugin-googlecompute/post-processor/googlecompute-import"
|
||||||
|
hyperonebuilder "github.com/hashicorp/packer-plugin-hyperone/builder/hyperone"
|
||||||
ncloudbuilder "github.com/hashicorp/packer-plugin-ncloud/builder/ncloud"
|
ncloudbuilder "github.com/hashicorp/packer-plugin-ncloud/builder/ncloud"
|
||||||
openstackbuilder "github.com/hashicorp/packer-plugin-openstack/builder/openstack"
|
openstackbuilder "github.com/hashicorp/packer-plugin-openstack/builder/openstack"
|
||||||
oscbsubuilder "github.com/hashicorp/packer-plugin-outscale/builder/osc/bsu"
|
oscbsubuilder "github.com/hashicorp/packer-plugin-outscale/builder/osc/bsu"
|
||||||
|
@ -94,6 +95,7 @@ var VendoredBuilders = map[string]packersdk.Builder{
|
||||||
"osc-bsusurrogate": new(oscbsusurrogatebuilder.Builder),
|
"osc-bsusurrogate": new(oscbsusurrogatebuilder.Builder),
|
||||||
"osc-bsuvolume": new(oscbsuvolumebuilder.Builder),
|
"osc-bsuvolume": new(oscbsuvolumebuilder.Builder),
|
||||||
"osc-chroot": new(oscchrootbuilder.Builder),
|
"osc-chroot": new(oscchrootbuilder.Builder),
|
||||||
|
"hyperone": new(hyperonebuilder.Builder),
|
||||||
}
|
}
|
||||||
|
|
||||||
// VendoredProvisioners are provisioner components that were once bundled with the
|
// VendoredProvisioners are provisioner components that were once bundled with the
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -44,6 +44,7 @@ require (
|
||||||
github.com/hashicorp/packer-plugin-cloudstack v0.0.1
|
github.com/hashicorp/packer-plugin-cloudstack v0.0.1
|
||||||
github.com/hashicorp/packer-plugin-docker v0.0.7
|
github.com/hashicorp/packer-plugin-docker v0.0.7
|
||||||
github.com/hashicorp/packer-plugin-googlecompute v0.0.1
|
github.com/hashicorp/packer-plugin-googlecompute v0.0.1
|
||||||
|
github.com/hashicorp/packer-plugin-hyperone v0.0.1
|
||||||
github.com/hashicorp/packer-plugin-ncloud v0.0.2
|
github.com/hashicorp/packer-plugin-ncloud v0.0.2
|
||||||
github.com/hashicorp/packer-plugin-openstack v0.0.1
|
github.com/hashicorp/packer-plugin-openstack v0.0.1
|
||||||
github.com/hashicorp/packer-plugin-outscale v0.0.1
|
github.com/hashicorp/packer-plugin-outscale v0.0.1
|
||||||
|
@ -57,7 +58,6 @@ require (
|
||||||
github.com/hashicorp/packer-plugin-vmware v0.0.1
|
github.com/hashicorp/packer-plugin-vmware v0.0.1
|
||||||
github.com/hashicorp/packer-plugin-vsphere v0.0.1
|
github.com/hashicorp/packer-plugin-vsphere v0.0.1
|
||||||
github.com/hetznercloud/hcloud-go v1.15.1
|
github.com/hetznercloud/hcloud-go v1.15.1
|
||||||
github.com/hyperonecom/h1-client-go v0.0.0-20191203060043-b46280e4c4a4
|
|
||||||
github.com/jdcloud-api/jdcloud-sdk-go v1.9.1-0.20190605102154-3d81a50ca961
|
github.com/jdcloud-api/jdcloud-sdk-go v1.9.1-0.20190605102154-3d81a50ca961
|
||||||
github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62
|
github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62
|
||||||
github.com/klauspost/pgzip v0.0.0-20151221113845-47f36e165cec
|
github.com/klauspost/pgzip v0.0.0-20151221113845-47f36e165cec
|
||||||
|
@ -66,7 +66,7 @@ require (
|
||||||
github.com/mattn/go-tty v0.0.0-20191112051231-74040eebce08
|
github.com/mattn/go-tty v0.0.0-20191112051231-74040eebce08
|
||||||
github.com/mitchellh/cli v1.1.0
|
github.com/mitchellh/cli v1.1.0
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/mitchellh/mapstructure v1.4.0
|
github.com/mitchellh/mapstructure v1.4.1
|
||||||
github.com/mitchellh/panicwrap v1.0.0
|
github.com/mitchellh/panicwrap v1.0.0
|
||||||
github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784
|
github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784
|
||||||
github.com/mitchellh/reflectwalk v1.0.0
|
github.com/mitchellh/reflectwalk v1.0.0
|
||||||
|
|
5
go.sum
5
go.sum
|
@ -476,6 +476,8 @@ github.com/hashicorp/packer-plugin-docker v0.0.7 h1:hMTrH7vrkFIjphtbbtpuzffTzSjM
|
||||||
github.com/hashicorp/packer-plugin-docker v0.0.7/go.mod h1:IpeKlwOSy2kdgQcysqd3gCsoqjME9jtmpFoKxn7RRNI=
|
github.com/hashicorp/packer-plugin-docker v0.0.7/go.mod h1:IpeKlwOSy2kdgQcysqd3gCsoqjME9jtmpFoKxn7RRNI=
|
||||||
github.com/hashicorp/packer-plugin-googlecompute v0.0.1 h1:Shjio88MraB+ocj0VI5+M65r4UBKbYI4eCqLNyPXKEo=
|
github.com/hashicorp/packer-plugin-googlecompute v0.0.1 h1:Shjio88MraB+ocj0VI5+M65r4UBKbYI4eCqLNyPXKEo=
|
||||||
github.com/hashicorp/packer-plugin-googlecompute v0.0.1/go.mod h1:MfV898IrEMpKH6wVnvOI5Tkhxm2snf3QxwVqV4k3bNI=
|
github.com/hashicorp/packer-plugin-googlecompute v0.0.1/go.mod h1:MfV898IrEMpKH6wVnvOI5Tkhxm2snf3QxwVqV4k3bNI=
|
||||||
|
github.com/hashicorp/packer-plugin-hyperone v0.0.1 h1:Owp1B5cI0VgFgR3pCyeeQdyKPTWls36mVedv+WxZMOM=
|
||||||
|
github.com/hashicorp/packer-plugin-hyperone v0.0.1/go.mod h1:9DglrxEBIig85Hr8r11YE+uMn3G0u+pt0AZHVP+wnAY=
|
||||||
github.com/hashicorp/packer-plugin-ncloud v0.0.2 h1:MGvGkOVfzeosqOSs5dteghLwv9VRcRxTuLoLX1ssUag=
|
github.com/hashicorp/packer-plugin-ncloud v0.0.2 h1:MGvGkOVfzeosqOSs5dteghLwv9VRcRxTuLoLX1ssUag=
|
||||||
github.com/hashicorp/packer-plugin-ncloud v0.0.2/go.mod h1:Hud2R1pkky96TQy3TPTTrr9Kej4b/4dqC/v+uEE0VDY=
|
github.com/hashicorp/packer-plugin-ncloud v0.0.2/go.mod h1:Hud2R1pkky96TQy3TPTTrr9Kej4b/4dqC/v+uEE0VDY=
|
||||||
github.com/hashicorp/packer-plugin-openstack v0.0.1 h1:FUaNjKguAipPZZXQ4UiJK6c5+2nS89CRxJHjAsfVyIQ=
|
github.com/hashicorp/packer-plugin-openstack v0.0.1 h1:FUaNjKguAipPZZXQ4UiJK6c5+2nS89CRxJHjAsfVyIQ=
|
||||||
|
@ -647,8 +649,9 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.2.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.2.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/mapstructure v1.4.0 h1:7ks8ZkOP5/ujthUsT07rNv+nkLXCQWKNHuwzOAesEks=
|
|
||||||
github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
|
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||||
|
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/panicwrap v1.0.0 h1:67zIyVakCIvcs69A0FGfZjBdPleaonSgGlXRSRlb6fE=
|
github.com/mitchellh/panicwrap v1.0.0 h1:67zIyVakCIvcs69A0FGfZjBdPleaonSgGlXRSRlb6fE=
|
||||||
github.com/mitchellh/panicwrap v1.0.0/go.mod h1:pKvZHwWrZowLUzftuFq7coarnxbBXU4aQh3N0BJOeeA=
|
github.com/mitchellh/panicwrap v1.0.0/go.mod h1:pKvZHwWrZowLUzftuFq7coarnxbBXU4aQh3N0BJOeeA=
|
||||||
github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784 h1:+DAetXqxv/mSyCkE9KBIYOZs9b68y7SUaDCxQMRjA68=
|
github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784 h1:+DAetXqxv/mSyCkE9KBIYOZs9b68y7SUaDCxQMRjA68=
|
||||||
|
|
|
@ -1,284 +0,0 @@
|
||||||
---
|
|
||||||
description: |
|
|
||||||
HyperOne Packer builder creates new images on the HyperOne platform.
|
|
||||||
The builder takes a source image, runs any provisioning necessary on
|
|
||||||
the image after launching it, then creates a reusable image.
|
|
||||||
page_title: HyperOne - Builders
|
|
||||||
---
|
|
||||||
|
|
||||||
# HyperOne Builder
|
|
||||||
|
|
||||||
Type: `hyperone`
|
|
||||||
Artifact BuilderId: `hyperone.builder`
|
|
||||||
|
|
||||||
The `hyperone` Packer builder is able to create new images on the [HyperOne
|
|
||||||
platform](http://www.hyperone.com/). The builder takes a source image, runs
|
|
||||||
any provisioning necessary on the image after launching it, then creates a
|
|
||||||
reusable image.
|
|
||||||
|
|
||||||
The builder does _not_ manage images. Once it creates an image, it is up to you
|
|
||||||
to use it or delete it.
|
|
||||||
|
|
||||||
## Authentication
|
|
||||||
|
|
||||||
HyperOne supports several authentication methods, which are all supported by
|
|
||||||
this builder.
|
|
||||||
|
|
||||||
### User session
|
|
||||||
|
|
||||||
If using user session, set the `token` field to your authentication token.
|
|
||||||
The `project` field is required when using this method.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"token": "YOUR TOKEN",
|
|
||||||
"project": "YOUR_PROJECT"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### User session by SSH key
|
|
||||||
|
|
||||||
If you've added an SSH key as a credential to your user account and the
|
|
||||||
private key is added to the ssh-agent on your local machine, you can
|
|
||||||
authenticate by setting just the platform login (your e-mail address):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"token_login": "your.user@example.com"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### h1 CLI
|
|
||||||
|
|
||||||
If you're using [h1-cli](https://github.com/hyperonecom/h1-cli) on your local
|
|
||||||
machine, HyperOne builder can use your credentials saved in a config file.
|
|
||||||
|
|
||||||
All you have to do is login within the tool:
|
|
||||||
|
|
||||||
```shell-session
|
|
||||||
$ h1 login --username your.user@example.com
|
|
||||||
```
|
|
||||||
|
|
||||||
You don't have to set `token` or `project` fields at all using this method.
|
|
||||||
|
|
||||||
### Service account
|
|
||||||
|
|
||||||
Using `h1`, you can create a new token associated with chosen project.
|
|
||||||
|
|
||||||
```shell-session
|
|
||||||
$ h1 project token add --name packer-builder --project PROJECT_ID
|
|
||||||
```
|
|
||||||
|
|
||||||
Set the `token` field to the generated token or save it in the `HYPERONE_TOKEN`
|
|
||||||
environment variable. You don't have to set the `project` option using this
|
|
||||||
method.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"token": "YOUR TOKEN"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration Reference
|
|
||||||
|
|
||||||
There are many configuration options available for the builder. They are
|
|
||||||
segmented below into two categories: required and optional parameters. Within
|
|
||||||
each category, the available configuration keys are alphabetized.
|
|
||||||
|
|
||||||
In addition to the options listed here, a
|
|
||||||
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
|
|
||||||
builder.
|
|
||||||
|
|
||||||
### Required:
|
|
||||||
|
|
||||||
- `disk_size` (float) - Size of the created disk, in GiB.
|
|
||||||
|
|
||||||
- `project` (string) - The id or name of the project. This field is required
|
|
||||||
only if using session tokens. It should be skipped when using service
|
|
||||||
account authentication.
|
|
||||||
|
|
||||||
- `source_image` (string) - ID or name of the image to launch server from.
|
|
||||||
|
|
||||||
- `token` (string) - The authentication token used to access your account.
|
|
||||||
This can be either a session token or a service account token.
|
|
||||||
If not defined, the builder will attempt to find it in the following order:
|
|
||||||
|
|
||||||
- In `HYPERONE_TOKEN` environment variable.
|
|
||||||
- In `~/.h1-cli/conf.json` config file used by [h1-cli](https://github.com/hyperonecom/h1-cli).
|
|
||||||
- By using SSH authentication if `token_login` variable has been set.
|
|
||||||
|
|
||||||
- `vm_type` (string) - ID or name of the type this server should be created with.
|
|
||||||
|
|
||||||
### Optional:
|
|
||||||
|
|
||||||
- `api_url` (string) - Custom API endpoint URL, compatible with HyperOne.
|
|
||||||
It can also be specified via environment variable `HYPERONE_API_URL`.
|
|
||||||
|
|
||||||
- `disk_name` (string) - The name of the created disk.
|
|
||||||
|
|
||||||
- `disk_type` (string) - The type of the created disk. Defaults to `ssd`.
|
|
||||||
|
|
||||||
- `image_description` (string) - The description of the resulting image.
|
|
||||||
|
|
||||||
- `image_name` (string) - The name of the resulting image. Defaults to
|
|
||||||
`packer-{{timestamp}}`
|
|
||||||
(see [configuration templates](/docs/templates/legacy_json_templates/engine) for more info).
|
|
||||||
|
|
||||||
- `image_service` (string) - The service of the resulting image.
|
|
||||||
|
|
||||||
- `image_tags` (map of key/value strings) - Key/value pair tags to
|
|
||||||
add to the created image.
|
|
||||||
|
|
||||||
- `network` (string) - The ID of the network to attach to the created server.
|
|
||||||
|
|
||||||
- `private_ip` (string) - The ID of the private IP within chosen `network`
|
|
||||||
that should be assigned to the created server.
|
|
||||||
|
|
||||||
- `public_ip` (string) - The ID of the public IP that should be assigned to
|
|
||||||
the created server. If `network` is chosen, the public IP will be associated
|
|
||||||
with server's private IP.
|
|
||||||
|
|
||||||
- `public_netadp_service` (string) - Custom service of public network adapter.
|
|
||||||
Can be useful when using custom `api_url`. Defaults to `public`.
|
|
||||||
|
|
||||||
- `ssh_keys` (array of strings) - List of SSH keys by name or id to be added
|
|
||||||
to the server on launch.
|
|
||||||
|
|
||||||
- `state_timeout` (string) - Timeout for waiting on the API to complete
|
|
||||||
a request. Defaults to 5m.
|
|
||||||
|
|
||||||
- `token_login` (string) - Login (an e-mail) on HyperOne platform. Set this
|
|
||||||
if you want to fetch the token by SSH authentication.
|
|
||||||
|
|
||||||
- `user_data` (string) - User data to launch with the server. Packer will not
|
|
||||||
automatically wait for a user script to finish before shutting down the
|
|
||||||
instance, this must be handled in a provisioner.
|
|
||||||
|
|
||||||
- `vm_name` (string) - The name of the created server.
|
|
||||||
|
|
||||||
- `vm_tags` (map of key/value strings) - Key/value pair tags to
|
|
||||||
add to the created server.
|
|
||||||
|
|
||||||
## Chroot disk
|
|
||||||
|
|
||||||
### Required:
|
|
||||||
|
|
||||||
- `chroot_disk` (bool) - Set to `true` to enable chroot disk build.
|
|
||||||
|
|
||||||
- `pre_mount_commands` (array of strings) - A series of commands to execute
|
|
||||||
before mounting the chroot. This should include any partitioning and
|
|
||||||
filesystem creation commands. The path to the device is provided by
|
|
||||||
`{{.Device}}`.
|
|
||||||
|
|
||||||
### Optional:
|
|
||||||
|
|
||||||
- `chroot_command_wrapper` (string) - How to run shell commands. This defaults
|
|
||||||
to `{{.Command}}`. This may be useful to set if you want to set
|
|
||||||
environment variables or run commands with `sudo`.
|
|
||||||
|
|
||||||
- `chroot_copy_files` (array of strings) - Paths to files on the running VM
|
|
||||||
that will be copied into the chroot environment before provisioning.
|
|
||||||
Defaults to `/etc/resolv.conf` so that DNS lookups work.
|
|
||||||
|
|
||||||
- `chroot_device` (string) - The path of chroot device. Defaults an attempt is
|
|
||||||
made to identify it based on the attach location.
|
|
||||||
|
|
||||||
- `chroot_disk_size` (float) - The size of the chroot disk in GiB. Defaults
|
|
||||||
to `disk_size`.
|
|
||||||
|
|
||||||
- `chroot_disk_type` (string) - The type of the chroot disk. Defaults to
|
|
||||||
`disk_type`.
|
|
||||||
|
|
||||||
- `chroot_mount_path` (string) - The path on which the device will be mounted.
|
|
||||||
|
|
||||||
- `chroot_mounts` (array of strings) - A list of devices to mount into the
|
|
||||||
chroot environment. This is a list of 3-element tuples, in order:
|
|
||||||
|
|
||||||
- The filesystem type. If this is "bind", then Packer will properly bind the
|
|
||||||
filesystem to another mount point.
|
|
||||||
|
|
||||||
- The source device.
|
|
||||||
|
|
||||||
- The mount directory.
|
|
||||||
|
|
||||||
- `mount_options` (array of tuples) - Options to supply the `mount` command
|
|
||||||
when mounting devices. Each option will be prefixed with `-o` and supplied
|
|
||||||
to the `mount` command.
|
|
||||||
|
|
||||||
- `mount_partition` (string) - The partition number containing the / partition.
|
|
||||||
By default this is the first partition of the volume (for example, sdb1).
|
|
||||||
|
|
||||||
- `post_mount_commands` (array of strings) - As `pre_mount_commands`, but the
|
|
||||||
commands are executed after mounting the root device and before the extra
|
|
||||||
mount and copy steps. The device and mount path are provided by
|
|
||||||
`{{.Device}}` and `{{.MountPath}}`.
|
|
||||||
|
|
||||||
## Basic Example
|
|
||||||
|
|
||||||
Here is a basic example. It is completely valid as soon as you enter your own
|
|
||||||
token.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "hyperone",
|
|
||||||
"token": "YOUR_AUTH_TOKEN",
|
|
||||||
"source_image": "ubuntu-18.04",
|
|
||||||
"vm_type": "a1.nano",
|
|
||||||
"disk_size": 10
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Chroot Example
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"type": "hyperone",
|
|
||||||
"token": "YOUR_AUTH_TOKEN",
|
|
||||||
"source_image": "ubuntu-18.04",
|
|
||||||
"vm_type": "a1.nano",
|
|
||||||
"disk_size": 10,
|
|
||||||
"chroot_disk": true,
|
|
||||||
"pre_mount_commands": [
|
|
||||||
"apt-get update",
|
|
||||||
"apt-get install debootstrap",
|
|
||||||
"debootstrap --arch amd64 bionic {{.MountPath}}"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## HCL Example
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
variable "token" {
|
|
||||||
type = string
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "project" {
|
|
||||||
type = string
|
|
||||||
}
|
|
||||||
|
|
||||||
source "hyperone" "new-syntax" {
|
|
||||||
token = var.token
|
|
||||||
project = var.project
|
|
||||||
source_image = "debian"
|
|
||||||
disk_size = 10
|
|
||||||
vm_type = "a1.nano"
|
|
||||||
image_name = "packerbats-hcl-{{timestamp}}"
|
|
||||||
image_tags = {
|
|
||||||
key="value"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
build {
|
|
||||||
sources = [
|
|
||||||
"source.hyperone.new-syntax"
|
|
||||||
]
|
|
||||||
|
|
||||||
provisioner "shell" {
|
|
||||||
inline = [
|
|
||||||
"apt-get update",
|
|
||||||
"apt-get upgrade -y"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -1,92 +0,0 @@
|
||||||
<!-- Code generated from the comments of the Config struct in builder/hyperone/config.go; DO NOT EDIT MANUALLY -->
|
|
||||||
|
|
||||||
- `api_url` (string) - Custom API endpoint URL, compatible with HyperOne.
|
|
||||||
It can also be specified via environment variable HYPERONE_API_URL.
|
|
||||||
|
|
||||||
- `token_login` (string) - Login (an e-mail) on HyperOne platform. Set this
|
|
||||||
if you want to fetch the token by SSH authentication.
|
|
||||||
|
|
||||||
- `state_timeout` (duration string | ex: "1h5m2s") - Timeout for waiting on the API to complete
|
|
||||||
a request. Defaults to 5m.
|
|
||||||
|
|
||||||
- `image_name` (string) - The name of the resulting image. Defaults to
|
|
||||||
`packer-{{timestamp}}`
|
|
||||||
(see configuration templates for more info).
|
|
||||||
|
|
||||||
- `image_description` (string) - The description of the resulting image.
|
|
||||||
|
|
||||||
- `image_tags` (map[string]string) - Key/value pair tags to add to the created image.
|
|
||||||
|
|
||||||
- `image_tag` ([]{key string, value string}) - Same as [`image_tags`](#image_tags) but defined as a singular repeatable
|
|
||||||
block containing a `key` and a `value` field. In HCL2 mode the
|
|
||||||
[`dynamic_block`](/docs/templates/hcl_templates/expressions#dynamic-blocks)
|
|
||||||
will allow you to create those programatically.
|
|
||||||
|
|
||||||
- `image_service` (string) - The service of the resulting image.
|
|
||||||
|
|
||||||
- `vm_name` (string) - The name of the created server.
|
|
||||||
|
|
||||||
- `vm_tags` (map[string]string) - Key/value pair tags to add to the created server.
|
|
||||||
|
|
||||||
- `vm_tag` ([]{name string, value string}) - Same as [`vm_tags`](#vm_tags) but defined as a singular repeatable block
|
|
||||||
containing a `key` and a `value` field. In HCL2 mode the
|
|
||||||
[`dynamic_block`](/docs/templates/hcl_templates/expressions#dynamic-blocks)
|
|
||||||
will allow you to create those programatically.
|
|
||||||
|
|
||||||
- `disk_name` (string) - The name of the created disk.
|
|
||||||
|
|
||||||
- `disk_type` (string) - The type of the created disk. Defaults to ssd.
|
|
||||||
|
|
||||||
- `network` (string) - The ID of the network to attach to the created server.
|
|
||||||
|
|
||||||
- `private_ip` (string) - The ID of the private IP within chosen network
|
|
||||||
that should be assigned to the created server.
|
|
||||||
|
|
||||||
- `public_ip` (string) - The ID of the public IP that should be assigned to
|
|
||||||
the created server. If network is chosen, the public IP will be associated
|
|
||||||
with server's private IP.
|
|
||||||
|
|
||||||
- `public_netadp_service` (string) - Custom service of public network adapter.
|
|
||||||
Can be useful when using custom api_url. Defaults to public.
|
|
||||||
|
|
||||||
- `chroot_device` (string) - Chroot Device
|
|
||||||
|
|
||||||
- `chroot_disk` (bool) - Chroot Disk
|
|
||||||
|
|
||||||
- `chroot_disk_size` (float32) - Chroot Disk Size
|
|
||||||
|
|
||||||
- `chroot_disk_type` (string) - Chroot Disk Type
|
|
||||||
|
|
||||||
- `chroot_mount_path` (string) - Chroot Mount Path
|
|
||||||
|
|
||||||
- `chroot_mounts` ([][]string) - Chroot Mounts
|
|
||||||
|
|
||||||
- `chroot_copy_files` ([]string) - Chroot Copy Files
|
|
||||||
|
|
||||||
- `chroot_command_wrapper` (string) - How to run shell commands. This defaults to `{{.Command}}`. This may be
|
|
||||||
useful to set if you want to set environmental variables or perhaps run
|
|
||||||
it with sudo or so on. This is a configuration template where the
|
|
||||||
.Command variable is replaced with the command to be run. Defaults to
|
|
||||||
`{{.Command}}`.
|
|
||||||
|
|
||||||
- `mount_options` ([]string) - Mount Options
|
|
||||||
|
|
||||||
- `mount_partition` (string) - Mount Partition
|
|
||||||
|
|
||||||
- `pre_mount_commands` ([]string) - A series of commands to execute after attaching the root volume and
|
|
||||||
before mounting the chroot. This is not required unless using
|
|
||||||
from_scratch. If so, this should include any partitioning and filesystem
|
|
||||||
creation commands. The path to the device is provided by `{{.Device}}`.
|
|
||||||
|
|
||||||
- `post_mount_commands` ([]string) - As pre_mount_commands, but the commands are executed after mounting the
|
|
||||||
root device and before the extra mount and copy steps. The device and
|
|
||||||
mount path are provided by `{{.Device}}` and `{{.MountPath}}`.
|
|
||||||
|
|
||||||
- `ssh_keys` ([]string) - List of SSH keys by name or id to be added
|
|
||||||
to the server on launch.
|
|
||||||
|
|
||||||
- `user_data` (string) - User data to launch with the server. Packer will not
|
|
||||||
automatically wait for a user script to finish before shutting down the
|
|
||||||
instance, this must be handled in a provisioner.
|
|
||||||
|
|
||||||
<!-- End of code generated from the comments of the Config struct in builder/hyperone/config.go; -->
|
|
|
@ -1,17 +0,0 @@
|
||||||
<!-- Code generated from the comments of the Config struct in builder/hyperone/config.go; DO NOT EDIT MANUALLY -->
|
|
||||||
|
|
||||||
- `token` (string) - The authentication token used to access your account.
|
|
||||||
This can be either a session token or a service account token.
|
|
||||||
If not defined, the builder will attempt to find it in the following order:
|
|
||||||
|
|
||||||
- `project` (string) - The id or name of the project. This field is required
|
|
||||||
only if using session tokens. It should be skipped when using service
|
|
||||||
account authentication.
|
|
||||||
|
|
||||||
- `source_image` (string) - ID or name of the image to launch server from.
|
|
||||||
|
|
||||||
- `vm_type` (string) - ID or name of the type this server should be created with.
|
|
||||||
|
|
||||||
- `disk_size` (float32) - Size of the created disk, in GiB.
|
|
||||||
|
|
||||||
<!-- End of code generated from the comments of the Config struct in builder/hyperone/config.go; -->
|
|
|
@ -708,10 +708,6 @@
|
||||||
"title": "Hetzner Cloud",
|
"title": "Hetzner Cloud",
|
||||||
"path": "builders/hetzner-cloud"
|
"path": "builders/hetzner-cloud"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"title": "HyperOne",
|
|
||||||
"path": "builders/hyperone"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"title": "Hyper-V",
|
"title": "Hyper-V",
|
||||||
"routes": [
|
"routes": [
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
"title": "Docker",
|
"title": "Docker",
|
||||||
"path": "docker",
|
"path": "docker",
|
||||||
"repo": "hashicorp/packer-plugin-docker",
|
"repo": "hashicorp/packer-plugin-docker",
|
||||||
|
|
||||||
"version": "latest"
|
"version": "latest"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -46,6 +45,13 @@
|
||||||
"repo": "hashicorp/packer-plugin-googlecompute",
|
"repo": "hashicorp/packer-plugin-googlecompute",
|
||||||
"version": "latest"
|
"version": "latest"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"title": "HyperOne",
|
||||||
|
"path": "hyperone",
|
||||||
|
"repo": "hashicorp/packer-plugin-hyperone",
|
||||||
|
"version": "latest",
|
||||||
|
"pluginTier": "community"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"title": "Naver Cloud",
|
"title": "Naver Cloud",
|
||||||
"path": "ncloud",
|
"path": "ncloud",
|
||||||
|
@ -87,6 +93,12 @@
|
||||||
"version": "latest",
|
"version": "latest",
|
||||||
"pluginTier": "community"
|
"pluginTier": "community"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"title": "QEMU",
|
||||||
|
"path": "qemu",
|
||||||
|
"repo": "hashicorp/packer-plugin-qemu",
|
||||||
|
"version": "latest"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"title": "Scaleway",
|
"title": "Scaleway",
|
||||||
"path": "scaleway",
|
"path": "scaleway",
|
||||||
|
@ -111,11 +123,5 @@
|
||||||
"path": "vmware",
|
"path": "vmware",
|
||||||
"repo": "hashicorp/packer-plugin-vmware",
|
"repo": "hashicorp/packer-plugin-vmware",
|
||||||
"version": "latest"
|
"version": "latest"
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "QEMU",
|
|
||||||
"path": "qemu",
|
|
||||||
"repo": "hashicorp/packer-plugin-qemu",
|
|
||||||
"version": "latest"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue