diff --git a/CHANGELOG.md b/CHANGELOG.md index c1542de73..d4014811a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ Major refactor: Extracted a majority of HashiCorp-maintained and community plugi * "github.com/hashicorp/packer-plugin-oracle" [GH-10962] * "github.com/hashicorp/packer-plugin-outscale" [GH-10941] * "github.com/hashicorp/packer-plugin-parallels" [GH-10936] +* "github.com/hashicorp/packer-plugin-profitbricks" [GH-11084] * "github.com/hashicorp/packer-plugin-proxmox" [GH-10930] * "github.com/hashicorp/packer-plugin-puppet" [GH-10943] * "github.com/hashicorp/packer-plugin-qemu" [GH-10929] diff --git a/builder/profitbricks/artifact.go b/builder/profitbricks/artifact.go deleted file mode 100644 index 344033fd0..000000000 --- a/builder/profitbricks/artifact.go +++ /dev/null @@ -1,37 +0,0 @@ -package profitbricks - -import ( - "fmt" -) - -type Artifact struct { - snapshotData string - - // StateData should store data such as GeneratedData - // to be shared with post-processors - StateData map[string]interface{} -} - -func (*Artifact) BuilderId() string { - return BuilderId -} - -func (a *Artifact) Files() []string { - return []string{} -} - -func (*Artifact) Id() string { - return "Null" -} - -func (a *Artifact) String() string { - return fmt.Sprintf("A snapshot was created: '%v'", a.snapshotData) -} - -func (a *Artifact) State(name string) interface{} { - return a.StateData[name] -} - -func (a *Artifact) Destroy() error { - return nil -} diff --git a/builder/profitbricks/artifact_test.go b/builder/profitbricks/artifact_test.go deleted file mode 100644 index 70a640e73..000000000 --- a/builder/profitbricks/artifact_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package profitbricks - -import ( - "testing" - - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -func TestArtifact_Impl(t *testing.T) { - var raw interface{} - raw = &Artifact{} - if _, ok := raw.(packersdk.Artifact); !ok { - t.Fatalf("Artifact should be artifact") - } -} - -func TestArtifactString(t *testing.T) { - generatedData := make(map[string]interface{}) - a := &Artifact{"packer-foobar", generatedData} - expected := "A snapshot was created: 'packer-foobar'" - - if a.String() != expected { - t.Fatalf("artifact string should match: %v", expected) - } -} - -func TestArtifactState_StateData(t *testing.T) { - expectedData := "this is the data" - artifact := &Artifact{ - StateData: map[string]interface{}{"state_data": expectedData}, - } - - // Valid state - result := artifact.State("state_data") - if result != expectedData { - t.Fatalf("Bad: State data was %s instead of %s", result, expectedData) - } - - // Invalid state - result = artifact.State("invalid_key") - if result != nil { - t.Fatalf("Bad: State should be nil for invalid state data name") - } - - // Nil StateData should not fail and should return nil - artifact = &Artifact{} - result = artifact.State("key") - if result != nil { - t.Fatalf("Bad: State should be nil for nil StateData") - } -} diff --git a/builder/profitbricks/builder.go b/builder/profitbricks/builder.go deleted file mode 100644 index e980582d4..000000000 --- a/builder/profitbricks/builder.go +++ /dev/null @@ -1,70 +0,0 @@ -package profitbricks - -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" -) - -const BuilderId = "packer.profitbricks" - -type Builder struct { - config Config - runner multistep.Runner -} - -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 - } - - return nil, warnings, nil -} - -func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) { - state := new(multistep.BasicStateBag) - - state.Put("config", &b.config) - state.Put("hook", hook) - state.Put("ui", ui) - steps := []multistep.Step{ - &StepCreateSSHKey{ - Debug: b.config.PackerDebug, - DebugKeyPath: fmt.Sprintf("pb_%s", b.config.SnapshotName), - }, - new(stepCreateServer), - &communicator.StepConnect{ - Config: &b.config.Comm, - Host: communicator.CommHost(b.config.Comm.Host(), "server_ip"), - SSHConfig: b.config.Comm.SSHConfigFunc(), - }, - &commonsteps.StepProvision{}, - &commonsteps.StepCleanupTempKeys{ - Comm: &b.config.Comm, - }, - new(stepTakeSnapshot), - } - - config := state.Get("config").(*Config) - - 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{ - snapshotData: config.SnapshotName, - StateData: map[string]interface{}{"generated_data": state.Get("generated_data")}, - } - return artifact, nil -} diff --git a/builder/profitbricks/builder_acc_test.go b/builder/profitbricks/builder_acc_test.go deleted file mode 100644 index 9419a2a5c..000000000 --- a/builder/profitbricks/builder_acc_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package profitbricks - -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 testAccPreCheck(t *testing.T) { - if v := os.Getenv("PROFITBRICKS_USERNAME"); v == "" { - t.Fatal("PROFITBRICKS_USERNAME must be set for acceptance tests") - } - - if v := os.Getenv("PROFITBRICKS_PASSWORD"); v == "" { - t.Fatal("PROFITBRICKS_PASSWORD must be set for acceptance tests") - } -} - -const testBuilderAccBasic = ` -{ - "builders": [{ - "image": "Ubuntu-16.04", - "password": "password", - "username": "username", - "snapshot_name": "packer", - "type": "profitbricks" - }] -} -` diff --git a/builder/profitbricks/builder_test.go b/builder/profitbricks/builder_test.go deleted file mode 100644 index 1d8d55012..000000000 --- a/builder/profitbricks/builder_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package profitbricks - -import ( - "fmt" - "testing" - - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -func testConfig() map[string]interface{} { - return map[string]interface{}{ - "image": "Ubuntu-16.04", - "password": "password", - "username": "username", - "snapshot_name": "packer", - "type": "profitbricks", - } -} - -func TestImplementsBuilder(t *testing.T) { - var raw interface{} - raw = &Builder{} - if _, ok := raw.(packersdk.Builder); !ok { - t.Fatalf("Builder should be a builder") - } -} - -func TestBuilder_Prepare_BadType(t *testing.T) { - b := &Builder{} - c := map[string]interface{}{ - "api_key": []string{}, - } - - _, warns, err := b.Prepare(c) - if len(warns) > 0 { - t.Fatalf("bad: %#v", warns) - } - if err == nil { - fmt.Println(err) - fmt.Println(warns) - t.Fatalf("prepare should fail") - } -} - -func TestBuilderPrepare_InvalidKey(t *testing.T) { - var b Builder - config := testConfig() - - config["i_should_not_be_valid"] = true - _, warnings, err := b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err == nil { - t.Fatal("should have error") - } -} diff --git a/builder/profitbricks/config.go b/builder/profitbricks/config.go deleted file mode 100644 index eaa2e473d..000000000 --- a/builder/profitbricks/config.go +++ /dev/null @@ -1,128 +0,0 @@ -//go:generate packer-sdc mapstructure-to-hcl2 -type Config - -package profitbricks - -import ( - "errors" - "os" - - "github.com/hashicorp/packer-plugin-sdk/common" - "github.com/hashicorp/packer-plugin-sdk/communicator" - 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/mitchellh/mapstructure" -) - -type Config struct { - common.PackerConfig `mapstructure:",squash"` - Comm communicator.Config `mapstructure:",squash"` - - PBUsername string `mapstructure:"username"` - PBPassword string `mapstructure:"password"` - PBUrl string `mapstructure:"url"` - - Region string `mapstructure:"location"` - Image string `mapstructure:"image"` - SSHKey string - SnapshotName string `mapstructure:"snapshot_name"` - DiskSize int `mapstructure:"disk_size"` - DiskType string `mapstructure:"disk_type"` - Cores int `mapstructure:"cores"` - Ram int `mapstructure:"ram"` - Retries int `mapstructure:"retries"` - 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", - }, - }, - }, raws...) - if err != nil { - return nil, err - } - - var errs *packersdk.MultiError - - if c.Comm.SSHPassword == "" && c.Comm.SSHPrivateKeyFile == "" { - errs = packersdk.MultiErrorAppend( - errs, errors.New("Either ssh private key path or ssh password must be set.")) - } - - if c.SnapshotName == "" { - def, err := interpolate.Render("packer-{{timestamp}}", nil) - if err != nil { - panic(err) - } - - // Default to packer-{{ unix timestamp (utc) }} - c.SnapshotName = def - } - - if c.PBUsername == "" { - c.PBUsername = os.Getenv("PROFITBRICKS_USERNAME") - } - - if c.PBPassword == "" { - c.PBPassword = os.Getenv("PROFITBRICKS_PASSWORD") - } - - if c.PBUrl == "" { - c.PBUrl = "https://api.profitbricks.com/cloudapi/v4" - } - - if c.Cores == 0 { - c.Cores = 4 - } - - if c.Ram == 0 { - c.Ram = 2048 - } - - if c.DiskSize == 0 { - c.DiskSize = 50 - } - - if c.Region == "" { - c.Region = "us/las" - } - - if c.DiskType == "" { - c.DiskType = "HDD" - } - - if es := c.Comm.Prepare(&c.ctx); len(es) > 0 { - errs = packersdk.MultiErrorAppend(errs, es...) - } - - if c.Image == "" { - errs = packersdk.MultiErrorAppend( - errs, errors.New("ProfitBricks 'image' is required")) - } - - if c.PBUsername == "" { - errs = packersdk.MultiErrorAppend( - errs, errors.New("ProfitBricks username is required")) - } - - if c.PBPassword == "" { - errs = packersdk.MultiErrorAppend( - errs, errors.New("ProfitBricks password is required")) - } - - if errs != nil && len(errs.Errors) > 0 { - return nil, errs - } - packersdk.LogSecretFilter.Set(c.PBUsername) - - return nil, nil -} diff --git a/builder/profitbricks/config.hcl2spec.go b/builder/profitbricks/config.hcl2spec.go deleted file mode 100644 index ff975b345..000000000 --- a/builder/profitbricks/config.hcl2spec.go +++ /dev/null @@ -1,167 +0,0 @@ -// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT. - -package profitbricks - -import ( - "github.com/hashicorp/hcl/v2/hcldec" - "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"` - PBUsername *string `mapstructure:"username" cty:"username" hcl:"username"` - PBPassword *string `mapstructure:"password" cty:"password" hcl:"password"` - PBUrl *string `mapstructure:"url" cty:"url" hcl:"url"` - Region *string `mapstructure:"location" cty:"location" hcl:"location"` - Image *string `mapstructure:"image" cty:"image" hcl:"image"` - SSHKey *string `cty:"ssh_key" hcl:"ssh_key"` - SnapshotName *string `mapstructure:"snapshot_name" cty:"snapshot_name" hcl:"snapshot_name"` - DiskSize *int `mapstructure:"disk_size" cty:"disk_size" hcl:"disk_size"` - DiskType *string `mapstructure:"disk_type" cty:"disk_type" hcl:"disk_type"` - Cores *int `mapstructure:"cores" cty:"cores" hcl:"cores"` - Ram *int `mapstructure:"ram" cty:"ram" hcl:"ram"` - Retries *int `mapstructure:"retries" cty:"retries" hcl:"retries"` -} - -// 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}, - "username": &hcldec.AttrSpec{Name: "username", Type: cty.String, Required: false}, - "password": &hcldec.AttrSpec{Name: "password", Type: cty.String, Required: false}, - "url": &hcldec.AttrSpec{Name: "url", Type: cty.String, Required: false}, - "location": &hcldec.AttrSpec{Name: "location", Type: cty.String, Required: false}, - "image": &hcldec.AttrSpec{Name: "image", Type: cty.String, Required: false}, - "ssh_key": &hcldec.AttrSpec{Name: "ssh_key", Type: cty.String, Required: false}, - "snapshot_name": &hcldec.AttrSpec{Name: "snapshot_name", Type: cty.String, Required: false}, - "disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false}, - "disk_type": &hcldec.AttrSpec{Name: "disk_type", Type: cty.String, Required: false}, - "cores": &hcldec.AttrSpec{Name: "cores", Type: cty.Number, Required: false}, - "ram": &hcldec.AttrSpec{Name: "ram", Type: cty.Number, Required: false}, - "retries": &hcldec.AttrSpec{Name: "retries", Type: cty.Number, Required: false}, - } - return s -} diff --git a/builder/profitbricks/step_create_server.go b/builder/profitbricks/step_create_server.go deleted file mode 100644 index f8a7667dd..000000000 --- a/builder/profitbricks/step_create_server.go +++ /dev/null @@ -1,279 +0,0 @@ -package profitbricks - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "strconv" - "strings" - "time" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/profitbricks/profitbricks-sdk-go" -) - -type stepCreateServer struct{} - -func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packersdk.Ui) - c := state.Get("config").(*Config) - - profitbricks.SetAuth(c.PBUsername, c.PBPassword) - profitbricks.SetDepth("5") - if c.Comm.SSHPublicKey != nil { - c.SSHKey = string(c.Comm.SSHPublicKey) - } else { - ui.Error("No ssh private key set; ssh authentication won't be possible. Please specify your private key in the ssh_private_key_file configuration key.") - return multistep.ActionHalt - } - ui.Say("Creating Virtual Data Center...") - img := s.getImageId(c.Image, c) - alias := "" - if img == "" { - alias = s.getImageAlias(c.Image, c.Region, ui) - } - - datacenter := profitbricks.Datacenter{ - Properties: profitbricks.DatacenterProperties{ - Name: c.SnapshotName, - Location: c.Region, - }, - } - server := profitbricks.Server{ - Properties: profitbricks.ServerProperties{ - Name: c.SnapshotName, - Ram: c.Ram, - Cores: c.Cores, - }, - Entities: &profitbricks.ServerEntities{ - Volumes: &profitbricks.Volumes{ - Items: []profitbricks.Volume{ - { - Properties: profitbricks.VolumeProperties{ - Type: c.DiskType, - Size: c.DiskSize, - Name: c.SnapshotName, - ImageAlias: alias, - Image: img, - }, - }, - }, - }, - }, - } - if c.SSHKey != "" { - server.Entities.Volumes.Items[0].Properties.SshKeys = []string{c.SSHKey} - } - - if c.Comm.SSHPassword != "" { - server.Entities.Volumes.Items[0].Properties.ImagePassword = c.Comm.SSHPassword - } - - datacenter = profitbricks.CompositeCreateDatacenter(datacenter) - if datacenter.StatusCode > 299 { - if datacenter.StatusCode > 299 { - var restError RestError - err := json.Unmarshal([]byte(datacenter.Response), &restError) - if err != nil { - ui.Error(fmt.Sprintf("Error decoding json response: %s", err.Error())) - return multistep.ActionHalt - } - if len(restError.Messages) > 0 { - ui.Error(restError.Messages[0].Message) - } else { - ui.Error(datacenter.Response) - } - return multistep.ActionHalt - } - } - - err := s.waitTillProvisioned(datacenter.Headers.Get("Location"), *c) - if err != nil { - ui.Error(fmt.Sprintf("Error occurred while creating a datacenter %s", err.Error())) - return multistep.ActionHalt - } - - state.Put("datacenter_id", datacenter.Id) - - server = profitbricks.CreateServer(datacenter.Id, server) - if server.StatusCode > 299 { - ui.Error(fmt.Sprintf("Error occurred %s", parseErrorMessage(server.Response))) - return multistep.ActionHalt - } - - err = s.waitTillProvisioned(server.Headers.Get("Location"), *c) - if err != nil { - ui.Error(fmt.Sprintf("Error occurred while creating a server %s", err.Error())) - return multistep.ActionHalt - } - - lan := profitbricks.CreateLan(datacenter.Id, profitbricks.CreateLanRequest{ - Properties: profitbricks.CreateLanProperties{ - Public: true, - Name: c.SnapshotName, - }, - }) - - if lan.StatusCode > 299 { - ui.Error(fmt.Sprintf("Error occurred %s", parseErrorMessage(lan.Response))) - return multistep.ActionHalt - } - - err = s.waitTillProvisioned(lan.Headers.Get("Location"), *c) - if err != nil { - ui.Error(fmt.Sprintf("Error occurred while creating a LAN %s", err.Error())) - return multistep.ActionHalt - } - - lanId, _ := strconv.Atoi(lan.Id) - nic := profitbricks.CreateNic(datacenter.Id, server.Id, profitbricks.Nic{ - Properties: &profitbricks.NicProperties{ - Name: c.SnapshotName, - Lan: lanId, - Dhcp: true, - }, - }) - - if lan.StatusCode > 299 { - ui.Error(fmt.Sprintf("Error occurred %s", parseErrorMessage(nic.Response))) - return multistep.ActionHalt - } - - err = s.waitTillProvisioned(nic.Headers.Get("Location"), *c) - if err != nil { - ui.Error(fmt.Sprintf("Error occurred while creating a NIC %s", err.Error())) - return multistep.ActionHalt - } - - state.Put("volume_id", server.Entities.Volumes.Items[0].Id) - - server = profitbricks.GetServer(datacenter.Id, server.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", server.Id) - - state.Put("server_ip", server.Entities.Nics.Items[0].Properties.Ips[0]) - - return multistep.ActionContinue -} - -func (s *stepCreateServer) Cleanup(state multistep.StateBag) { - c := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - - ui.Say("Removing Virtual Data Center...") - - profitbricks.SetAuth(c.PBUsername, c.PBPassword) - - if dcId, ok := state.GetOk("datacenter_id"); ok { - resp := profitbricks.DeleteDatacenter(dcId.(string)) - if err := s.checkForErrors(resp); err != nil { - ui.Error(fmt.Sprintf( - "Error deleting Virtual Data Center. Please destroy it manually: %s", err)) - } - if err := s.waitTillProvisioned(resp.Headers.Get("Location"), *c); err != nil { - ui.Error(fmt.Sprintf( - "Error deleting Virtual Data Center. Please destroy it manually: %s", err)) - } - } -} - -func (d *stepCreateServer) waitTillProvisioned(path string, config Config) error { - d.setPB(config.PBUsername, config.PBPassword, config.PBUrl) - waitCount := 120 - if config.Retries > 0 { - waitCount = config.Retries - } - for i := 0; i < waitCount; i++ { - request := profitbricks.GetRequestStatus(path) - if request.Metadata.Status == "DONE" { - return nil - } - if request.Metadata.Status == "FAILED" { - return errors.New(request.Metadata.Message) - } - time.Sleep(1 * time.Second) - i++ - } - return nil -} - -func (d *stepCreateServer) setPB(username string, password string, url string) { - profitbricks.SetAuth(username, password) - profitbricks.SetEndpoint(url) -} - -func (d *stepCreateServer) checkForErrors(instance profitbricks.Resp) error { - if instance.StatusCode > 299 { - return fmt.Errorf("Error occurred %s", string(instance.Body)) - } - return nil -} - -type RestError struct { - HttpStatus int `json:"httpStatus,omitempty"` - Messages []Message `json:"messages,omitempty"` -} - -type Message struct { - ErrorCode string `json:"errorCode,omitempty"` - Message string `json:"message,omitempty"` -} - -func (d *stepCreateServer) getImageId(imageName string, c *Config) string { - d.setPB(c.PBUsername, c.PBPassword, c.PBUrl) - - images := profitbricks.ListImages() - - for i := 0; i < len(images.Items); i++ { - imgName := "" - if images.Items[i].Properties.Name != "" { - imgName = images.Items[i].Properties.Name - } - diskType := c.DiskType - if c.DiskType == "SSD" { - diskType = "HDD" - } - if imgName != "" && strings.Contains(strings.ToLower(imgName), strings.ToLower(imageName)) && images.Items[i].Properties.ImageType == diskType && images.Items[i].Properties.Location == c.Region && images.Items[i].Properties.Public == true { - return images.Items[i].Id - } - } - return "" -} - -func (d *stepCreateServer) getImageAlias(imageAlias string, location string, ui packersdk.Ui) string { - if imageAlias == "" { - return "" - } - locations := profitbricks.GetLocation(location) - if len(locations.Properties.ImageAliases) > 0 { - for _, i := range locations.Properties.ImageAliases { - alias := "" - if i != "" { - alias = i - } - if alias != "" && strings.EqualFold(alias, imageAlias) { - return alias - } - } - } - return "" -} - -func parseErrorMessage(raw string) (toreturn string) { - var tmp map[string]interface{} - if json.Unmarshal([]byte(raw), &tmp) != nil { - return "" - } - - for _, v := range tmp["messages"].([]interface{}) { - for index, i := range v.(map[string]interface{}) { - if index == "message" { - toreturn = toreturn + i.(string) + "\n" - } - } - } - return toreturn -} diff --git a/builder/profitbricks/step_create_ssh_key.go b/builder/profitbricks/step_create_ssh_key.go deleted file mode 100644 index e0c4a145a..000000000 --- a/builder/profitbricks/step_create_ssh_key.go +++ /dev/null @@ -1,61 +0,0 @@ -package profitbricks - -import ( - "context" - "crypto/x509" - "encoding/pem" - "fmt" - - "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) - - if c.Comm.SSHPrivateKeyFile != "" { - pemBytes, err := c.Comm.ReadSSHPrivateKeyFile() - if err != nil { - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - block, _ := pem.Decode(pemBytes) - - priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) - - if err != nil { - - state.Put("error", err.Error()) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - priv_blk := pem.Block{ - Type: "RSA PRIVATE KEY", - Headers: nil, - Bytes: x509.MarshalPKCS1PrivateKey(priv), - } - - pub, err := ssh.NewPublicKey(&priv.PublicKey) - if err != nil { - err := fmt.Errorf("Error creating temporary ssh key: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - c.Comm.SSHPrivateKey = pem.EncodeToMemory(&priv_blk) - c.Comm.SSHPublicKey = ssh.MarshalAuthorizedKey(pub) - } - return multistep.ActionContinue -} - -func (s *StepCreateSSHKey) Cleanup(state multistep.StateBag) {} diff --git a/builder/profitbricks/step_take_snapshot.go b/builder/profitbricks/step_take_snapshot.go deleted file mode 100644 index 962341b8e..000000000 --- a/builder/profitbricks/step_take_snapshot.go +++ /dev/null @@ -1,190 +0,0 @@ -package profitbricks - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "strings" - "time" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/profitbricks/profitbricks-sdk-go" -) - -type stepTakeSnapshot struct{} - -func (s *stepTakeSnapshot) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packersdk.Ui) - c := state.Get("config").(*Config) - - ui.Say("Creating ProfitBricks snapshot...") - - profitbricks.SetAuth(c.PBUsername, c.PBPassword) - - dcId := state.Get("datacenter_id").(string) - volumeId := state.Get("volume_id").(string) - serverId := state.Get("instance_id").(string) - - comm, _ := state.Get("communicator").(packersdk.Communicator) - if comm == nil { - ui.Error("no communicator found") - return multistep.ActionHalt - } - - /* sync fs changes from the provisioning step */ - os, err := s.getOs(dcId, serverId) - if err != nil { - ui.Error(fmt.Sprintf("an error occurred while getting the server os: %s", err.Error())) - return multistep.ActionHalt - } - ui.Say(fmt.Sprintf("Server OS is %s", os)) - - switch strings.ToLower(os) { - case "linux": - ui.Say("syncing file system changes") - if err := s.syncFs(ctx, comm); err != nil { - ui.Error(fmt.Sprintf("error syncing fs changes: %s", err.Error())) - return multistep.ActionHalt - } - } - - snapshot := profitbricks.CreateSnapshot(dcId, volumeId, c.SnapshotName, "") - state.Put("snapshotname", c.SnapshotName) - - if snapshot.StatusCode > 299 { - var restError RestError - if err := json.Unmarshal([]byte(snapshot.Response), &restError); err != nil { - ui.Error(err.Error()) - return multistep.ActionHalt - } - if len(restError.Messages) > 0 { - ui.Error(restError.Messages[0].Message) - } else { - ui.Error(snapshot.Response) - } - - return multistep.ActionHalt - } - - ui.Say(fmt.Sprintf("Creating a snapshot for %s/volumes/%s", dcId, volumeId)) - - err = s.waitForRequest(snapshot.Headers.Get("Location"), *c, ui) - if err != nil { - ui.Error(fmt.Sprintf("An error occurred while waiting for the request to be done: %s", err.Error())) - return multistep.ActionHalt - } - - err = s.waitTillSnapshotAvailable(snapshot.Id, *c, ui) - if err != nil { - ui.Error(fmt.Sprintf("An error occurred while waiting for the snapshot to be created: %s", err.Error())) - return multistep.ActionHalt - } - - return multistep.ActionContinue -} - -func (s *stepTakeSnapshot) Cleanup(_ multistep.StateBag) { -} - -func (s *stepTakeSnapshot) waitForRequest(path string, config Config, ui packersdk.Ui) error { - - ui.Say(fmt.Sprintf("Watching request %s", path)) - s.setPB(config.PBUsername, config.PBPassword, config.PBUrl) - waitCount := 50 - var waitInterval = 10 * time.Second - if config.Retries > 0 { - waitCount = config.Retries - } - done := false - for i := 0; i < waitCount; i++ { - request := profitbricks.GetRequestStatus(path) - ui.Say(fmt.Sprintf("request status = %s", request.Metadata.Status)) - if request.Metadata.Status == "DONE" { - done = true - break - } - if request.Metadata.Status == "FAILED" { - return fmt.Errorf("Request failed: %s", request.Response) - } - time.Sleep(waitInterval) - i++ - } - - if done == false { - return fmt.Errorf("request not fulfilled after waiting %d seconds", - int64(waitCount)*int64(waitInterval)/int64(time.Second)) - } - return nil -} - -func (s *stepTakeSnapshot) waitTillSnapshotAvailable(id string, config Config, ui packersdk.Ui) error { - s.setPB(config.PBUsername, config.PBPassword, config.PBUrl) - waitCount := 50 - var waitInterval = 10 * time.Second - if config.Retries > 0 { - waitCount = config.Retries - } - done := false - ui.Say(fmt.Sprintf("waiting for snapshot %s to become available", id)) - for i := 0; i < waitCount; i++ { - snap := profitbricks.GetSnapshot(id) - ui.Say(fmt.Sprintf("snapshot status = %s", snap.Metadata.State)) - if snap.StatusCode != 200 { - return fmt.Errorf("%s", snap.Response) - } - if snap.Metadata.State == "AVAILABLE" { - done = true - break - } - time.Sleep(waitInterval) - i++ - ui.Say(fmt.Sprintf("... still waiting, %d seconds have passed", int64(waitInterval)*int64(i))) - } - - if done == false { - return fmt.Errorf("snapshot not created after waiting %d seconds", - int64(waitCount)*int64(waitInterval)/int64(time.Second)) - } - - ui.Say("snapshot created") - return nil -} - -func (s *stepTakeSnapshot) syncFs(ctx context.Context, comm packersdk.Communicator) error { - cmd := &packersdk.RemoteCmd{ - Command: "sync", - } - if err := comm.Start(ctx, cmd); err != nil { - return err - } - if cmd.Wait() != 0 { - return fmt.Errorf("sync command exited with code %d", cmd.ExitStatus()) - } - return nil -} - -func (s *stepTakeSnapshot) getOs(dcId string, serverId string) (string, error) { - server := profitbricks.GetServer(dcId, serverId) - if server.StatusCode != 200 { - return "", errors.New(server.Response) - } - - if server.Properties.BootVolume == nil { - return "", errors.New("no boot volume found on server") - } - - volumeId := server.Properties.BootVolume.Id - volume := profitbricks.GetVolume(dcId, volumeId) - if volume.StatusCode != 200 { - return "", errors.New(volume.Response) - } - - return volume.Properties.LicenceType, nil -} - -func (s *stepTakeSnapshot) setPB(username string, password string, url string) { - profitbricks.SetAuth(username, password) - profitbricks.SetEndpoint(url) -} diff --git a/builder/profitbricks/version/version.go b/builder/profitbricks/version/version.go deleted file mode 100644 index c71c8d860..000000000 --- a/builder/profitbricks/version/version.go +++ /dev/null @@ -1,13 +0,0 @@ -package version - -import ( - "github.com/hashicorp/packer-plugin-sdk/version" - packerVersion "github.com/hashicorp/packer/version" -) - -var ProfitbricksPluginVersion *version.PluginVersion - -func init() { - ProfitbricksPluginVersion = version.InitializePluginVersion( - packerVersion.Version, packerVersion.VersionPrerelease) -} diff --git a/command/plugin.go b/command/plugin.go index 348bbf558..a1842d495 100644 --- a/command/plugin.go +++ b/command/plugin.go @@ -15,7 +15,6 @@ import ( filebuilder "github.com/hashicorp/packer/builder/file" nullbuilder "github.com/hashicorp/packer/builder/null" - profitbricksbuilder "github.com/hashicorp/packer/builder/profitbricks" artificepostprocessor "github.com/hashicorp/packer/post-processor/artifice" checksumpostprocessor "github.com/hashicorp/packer/post-processor/checksum" compresspostprocessor "github.com/hashicorp/packer/post-processor/compress" @@ -38,9 +37,8 @@ type PluginCommand struct { } var Builders = map[string]packersdk.Builder{ - "file": new(filebuilder.Builder), - "null": new(nullbuilder.Builder), - "profitbricks": new(profitbricksbuilder.Builder), + "file": new(filebuilder.Builder), + "null": new(nullbuilder.Builder), } var Provisioners = map[string]packersdk.Provisioner{ diff --git a/command/vendored_plugins.go b/command/vendored_plugins.go index e03cac710..150d30fab 100644 --- a/command/vendored_plugins.go +++ b/command/vendored_plugins.go @@ -56,6 +56,7 @@ import ( oscchrootbuilder "github.com/hashicorp/packer-plugin-outscale/builder/osc/chroot" parallelsisobuilder "github.com/hashicorp/packer-plugin-parallels/builder/parallels/iso" parallelspvmbuilder "github.com/hashicorp/packer-plugin-parallels/builder/parallels/pvm" + profitbricksbuilder "github.com/hashicorp/packer-plugin-profitbricks/builder/profitbricks" proxmoxclone "github.com/hashicorp/packer-plugin-proxmox/builder/proxmox/clone" proxmoxiso "github.com/hashicorp/packer-plugin-proxmox/builder/proxmox/iso" puppetmasterlessprovisioner "github.com/hashicorp/packer-plugin-puppet/provisioner/puppet-masterless" @@ -119,6 +120,7 @@ var VendoredBuilders = map[string]packersdk.Builder{ "openstack": new(openstackbuilder.Builder), "oracle-classic": new(oracleclassicbuilder.Builder), "oracle-oci": new(oracleocibuilder.Builder), + "profitbricks": new(profitbricksbuilder.Builder), "proxmox": new(proxmoxiso.Builder), "proxmox-iso": new(proxmoxiso.Builder), "proxmox-clone": new(proxmoxclone.Builder), diff --git a/go.mod b/go.mod index ec7b8e443..63e723901 100644 --- a/go.mod +++ b/go.mod @@ -40,6 +40,7 @@ require ( github.com/hashicorp/packer-plugin-oracle v0.0.3 github.com/hashicorp/packer-plugin-outscale v0.0.1 github.com/hashicorp/packer-plugin-parallels v0.0.1 + github.com/hashicorp/packer-plugin-profitbricks v1.0.1 github.com/hashicorp/packer-plugin-proxmox v0.0.2 github.com/hashicorp/packer-plugin-puppet v0.0.2 github.com/hashicorp/packer-plugin-qemu v0.0.1 @@ -63,7 +64,6 @@ require ( github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784 github.com/pierrec/lz4 v2.0.5+incompatible github.com/posener/complete v1.2.3 - github.com/profitbricks/profitbricks-sdk-go v4.0.2+incompatible github.com/shirou/gopsutil v3.21.1+incompatible github.com/stretchr/testify v1.7.0 github.com/ulikunitz/xz v0.5.8 diff --git a/go.sum b/go.sum index 4bf506983..be2992b2c 100644 --- a/go.sum +++ b/go.sum @@ -587,6 +587,8 @@ github.com/hashicorp/packer-plugin-outscale v0.0.1 h1:BrL8hKypNYrvP3NR+d+xX03SZK github.com/hashicorp/packer-plugin-outscale v0.0.1/go.mod h1:6jEWfJO7TgAbaL3e+St1bN5PoIC/MmDIsYqNUzAHF1w= github.com/hashicorp/packer-plugin-parallels v0.0.1 h1:fcaaiGWdU1+X4IGadXdUhJ2si1ZA3apXS9tMNJXln2A= github.com/hashicorp/packer-plugin-parallels v0.0.1/go.mod h1:FGNtZ7XFBr3IYuj7uvJtSaNnyhAwe457zP464m06+20= +github.com/hashicorp/packer-plugin-profitbricks v1.0.1 h1:yFLUoDvm/zwzqj3J4a4pe49JpeDDGx08U9B38FXEyNk= +github.com/hashicorp/packer-plugin-profitbricks v1.0.1/go.mod h1:qtDQ7sbc0hMXWuxt0gweUwsVyVIazRLyNCHPO19CPU0= github.com/hashicorp/packer-plugin-proxmox v0.0.2 h1:x6QW7PeKh+IJymPEt3QdpBhSRi5vqXb8qTWv7rMLuns= github.com/hashicorp/packer-plugin-proxmox v0.0.2/go.mod h1:3URutEWX1yy10qcHNJncS4OMpZknA1FyvlrfL+5usYk= github.com/hashicorp/packer-plugin-puppet v0.0.2 h1:ER0znnTwRAlWqnTg3JLo//Cgj3wy+LjTVzrzcYFbT7k= diff --git a/scripts/upgrade_plugins.sh b/scripts/upgrade_plugins.sh index d2f6d2502..a962621a6 100755 --- a/scripts/upgrade_plugins.sh +++ b/scripts/upgrade_plugins.sh @@ -28,6 +28,7 @@ declare -a plugins=( "oracle" "outscale" "parallels" + "profitbricks" "proxmox" "puppet" "qemu" diff --git a/website/content/docs/builders/profitbricks.mdx b/website/content/docs/builders/profitbricks.mdx deleted file mode 100644 index 6e83eabc9..000000000 --- a/website/content/docs/builders/profitbricks.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -description: The ProfitBricks builder is able to create images for ProfitBricks cloud. -page_title: ProfitBricks - Builders ---- - -# ProfitBricks Builder - -Type: `profitbricks` -Artifact BuilderId: `packer.profitbricks` - -The ProfitBricks Builder is able to create virtual machines for -[ProfitBricks](https://www.profitbricks.com). - -## 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. In addition to the options defined there, a private key file -can also be supplied to override the typical auto-generated key: - -@include 'packer-plugin-sdk/communicator/SSH-Private-Key-File-not-required.mdx' - -### Required - -- `image` (string) - ProfitBricks volume image. Only Linux public images are - supported. To obtain full list of available images you can use - [ProfitBricks CLI](https://github.com/profitbricks/profitbricks-cli#image). - -- `password` (string) - ProfitBricks password. This can be specified via - environment variable \`PROFITBRICKS_PASSWORD', if provided. The value - defined in the config has precedence over environemnt variable. - -- `username` (string) - ProfitBricks username. This can be specified via - environment variable \`PROFITBRICKS_USERNAME', if provided. The value - defined in the config has precedence over environemnt variable. - -### Optional - -- `cores` (number) - Amount of CPU cores to use for this build. Defaults to - "4". - -- `disk_size` (string) - Amount of disk space for this image in GB. Defaults - to "50" - -- `disk_type` (string) - Type of disk to use for this image. Defaults to - "HDD". - -- `location` (string) - Defaults to "us/las". - -- `ram` (number) - Amount of RAM to use for this image. Defaults to "2048". - -- `retries` (string) - Number of retries Packer will make status requests - while waiting for the build to complete. Default value 120 seconds. - -- `snapshot_name` (string) - If snapshot name is not provided Packer will - generate it - -- `snapshot_password` (string) - Password for the snapshot. - -- `url` (string) - Endpoint for the ProfitBricks REST API. Default URL -"" - - -## Example - -Here is a basic example: - -```json -{ - "builders": [ - { - "image": "Ubuntu-16.04", - "type": "profitbricks", - "disk_size": "5", - "snapshot_name": "double", - "snapshot_password": "test1234", - "ssh_username": "root", - "timeout": 100 - } - ] -} -``` diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index b10bf2864..7dac457e3 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -687,10 +687,6 @@ "title": "Null", "path": "builders/null" }, - { - "title": "ProfitBricks", - "path": "builders/profitbricks" - }, { "title": "Custom", "path": "builders/custom" diff --git a/website/data/docs-remote-plugins.json b/website/data/docs-remote-plugins.json index 91469e982..fc00adeb2 100644 --- a/website/data/docs-remote-plugins.json +++ b/website/data/docs-remote-plugins.json @@ -162,6 +162,13 @@ "repo": "hashicorp/packer-plugin-parallels", "version": "latest" }, + { + "title": "Profitbricks", + "path": "profitbricks", + "repo": "hashicorp/packer-plugin-profitbricks", + "pluginTier": "community", + "version": "latest" + }, { "title": "Proxmox", "path": "proxmox",