diff --git a/builder/jdcloud/artifact.go b/builder/jdcloud/artifact.go deleted file mode 100644 index e90fad148..000000000 --- a/builder/jdcloud/artifact.go +++ /dev/null @@ -1,47 +0,0 @@ -package jdcloud - -import ( - "fmt" - "sort" - "strings" -) - -type Artifact struct { - ImageId string - RegionID string - - // StateData should store data such as GeneratedData - // to be shared with post-processors - StateData map[string]interface{} -} - -func (*Artifact) BuilderId() string { - return BUILDER_ID -} - -func (*Artifact) Files() []string { - return nil -} - -// Plan -// Though this part is supposed to be an array of Image Ids associated -// with its region, but currently only a single image is supported -func (a *Artifact) Id() string { - parts := []string{fmt.Sprintf("%s:%s", a.RegionID, a.ImageId)} - sort.Strings(parts) - return strings.Join(parts, ",") -} - -func (a *Artifact) String() string { - return fmt.Sprintf("A VMImage was created: %s", a.ImageId) -} - -// Plan -// State and destroy function is abandoned -func (a *Artifact) State(name string) interface{} { - return a.StateData[name] -} - -func (a *Artifact) Destroy() error { - return nil -} diff --git a/builder/jdcloud/builder.go b/builder/jdcloud/builder.go deleted file mode 100644 index b93bc1d5c..000000000 --- a/builder/jdcloud/builder.go +++ /dev/null @@ -1,97 +0,0 @@ -package jdcloud - -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/config" - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" -) - -func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } - -func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { - err := config.Decode(&b.config, &config.DecodeOpts{ - PluginType: BUILDER_ID, - Interpolate: true, - InterpolateContext: &b.config.ctx, - InterpolateFilter: &interpolate.RenderFilter{ - Exclude: []string{ - "boot_command", - }, - }, - }, raws...) - if err != nil { - return nil, nil, fmt.Errorf("[ERROR] Failed in decoding JSON->mapstructure") - } - - errs := &packersdk.MultiError{} - errs = packersdk.MultiErrorAppend(errs, b.config.JDCloudCredentialConfig.Prepare(&b.config.ctx)...) - errs = packersdk.MultiErrorAppend(errs, b.config.JDCloudInstanceSpecConfig.Prepare(&b.config.ctx)...) - if errs != nil && len(errs.Errors) != 0 { - return nil, nil, errs - } - - packersdk.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey) - - return nil, nil, nil -} - -func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) { - - state := new(multistep.BasicStateBag) - state.Put("hook", hook) - state.Put("ui", ui) - state.Put("config", &b.config) - - steps := []multistep.Step{ - - &stepValidateParameters{ - InstanceSpecConfig: &b.config.JDCloudInstanceSpecConfig, - }, - - &stepConfigCredentials{ - InstanceSpecConfig: &b.config.JDCloudInstanceSpecConfig, - }, - - &stepCreateJDCloudInstance{ - InstanceSpecConfig: &b.config.JDCloudInstanceSpecConfig, - CredentialConfig: &b.config.JDCloudCredentialConfig, - }, - - &communicator.StepConnect{ - Config: &b.config.JDCloudInstanceSpecConfig.Comm, - SSHConfig: b.config.JDCloudInstanceSpecConfig.Comm.SSHConfigFunc(), - Host: instanceHost, - }, - - &commonsteps.StepProvision{}, - - &stepStopJDCloudInstance{ - InstanceSpecConfig: &b.config.JDCloudInstanceSpecConfig, - }, - - &stepCreateJDCloudImage{ - InstanceSpecConfig: &b.config.JDCloudInstanceSpecConfig, - }, - } - - b.runner = commonsteps.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state) - b.runner.Run(ctx, state) - - if rawErr, ok := state.GetOk("error"); ok { - return nil, rawErr.(error) - } - - artifact := &Artifact{ - ImageId: b.config.ArtifactId, - RegionID: b.config.RegionId, - StateData: map[string]interface{}{"generated_data": state.Get("generated_data")}, - } - return artifact, nil -} diff --git a/builder/jdcloud/common.go b/builder/jdcloud/common.go deleted file mode 100644 index 049421b72..000000000 --- a/builder/jdcloud/common.go +++ /dev/null @@ -1,435 +0,0 @@ -//go:generate packer-sdc mapstructure-to-hcl2 -type Config - -package jdcloud - -import ( - "fmt" - "log" - "strings" - "sync" - "time" - - "github.com/hashicorp/packer-plugin-sdk/common" - "github.com/hashicorp/packer-plugin-sdk/multistep" - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" - vm "github.com/jdcloud-api/jdcloud-sdk-go/services/vm/client" - vpc "github.com/jdcloud-api/jdcloud-sdk-go/services/vpc/client" -) - -const ( - FINE = 0 - CONNECT_FAILED = "Client.Timeout exceeded" - VM_PENDING = "pending" - VM_RUNNING = "running" - VM_STARTING = "starting" - VM_STOPPING = "stopping" - VM_STOPPED = "stopped" - READY = "ready" - BUILDER_ID = "hashicorp.jdcloud" -) - -var ( - VmClient *vm.VmClient - VpcClient *vpc.VpcClient - Region string -) - -type Config struct { - JDCloudCredentialConfig `mapstructure:",squash"` - JDCloudInstanceSpecConfig `mapstructure:",squash"` - common.PackerConfig `mapstructure:",squash"` - ctx interpolate.Context -} - -type Builder struct { - config Config - runner multistep.Runner -} - -func Retry(timeout time.Duration, f RetryFunc) error { - // These are used to pull the error out of the function; need a mutex to - // avoid a data race. - var resultErr error - var resultErrMu sync.Mutex - - c := &StateChangeConf{ - Pending: []string{"retryableerror"}, - Target: []string{"success"}, - Timeout: timeout, - MinTimeout: 500 * time.Millisecond, - Refresh: func() (interface{}, string, error) { - rerr := f() - - resultErrMu.Lock() - defer resultErrMu.Unlock() - - if rerr == nil { - resultErr = nil - return 42, "success", nil - } - - resultErr = rerr.Err - - if rerr.Retryable { - return 42, "retryableerror", nil - } - return nil, "quit", rerr.Err - }, - } - - _, waitErr := c.WaitForState() - - // Need to acquire the lock here to be able to avoid race using resultErr as - // the return value - resultErrMu.Lock() - defer resultErrMu.Unlock() - - // resultErr may be nil because the wait timed out and resultErr was never - // set; this is still an error - if resultErr == nil { - return waitErr - } - // resultErr takes precedence over waitErr if both are set because it is - // more likely to be useful - return resultErr -} - -// RetryFunc is the function retried until it succeeds. -type RetryFunc func() *RetryError - -// RetryError is the required return type of RetryFunc. It forces client code -// to choose whether or not a given error is retryable. -type RetryError struct { - Err error - Retryable bool -} - -// RetryableError is a helper to create a RetryError that's retryable from a -// given error. -func RetryableError(err error) *RetryError { - if err == nil { - return nil - } - return &RetryError{Err: err, Retryable: true} -} - -// NonRetryableError is a helper to create a RetryError that's _not_ retryable -// from a given error. -func NonRetryableError(err error) *RetryError { - if err == nil { - return nil - } - return &RetryError{Err: err, Retryable: false} -} - -// WaitForState watches an object and waits for it to achieve the state -// specified in the configuration using the specified Refresh() func, -// waiting the number of seconds specified in the timeout configuration. -// -// If the Refresh function returns an error, exit immediately with that error. -// -// If the Refresh function returns a state other than the Target state or one -// listed in Pending, return immediately with an error. -// -// If the Timeout is exceeded before reaching the Target state, return an -// error. -// -// Otherwise, the result is the result of the first call to the Refresh function to -// reach the target state. -func (conf *StateChangeConf) WaitForState() (interface{}, error) { - log.Printf("[DEBUG] Waiting for state to become: %s", conf.Target) - - notfoundTick := 0 - targetOccurence := 0 - - // Set a default for times to check for not found - if conf.NotFoundChecks == 0 { - conf.NotFoundChecks = 20 - } - - if conf.ContinuousTargetOccurence == 0 { - conf.ContinuousTargetOccurence = 1 - } - - type Result struct { - Result interface{} - State string - Error error - Done bool - } - - // Read every result from the refresh loop, waiting for a positive result.Done. - resCh := make(chan Result, 1) - // cancellation channel for the refresh loop - cancelCh := make(chan struct{}) - - result := Result{} - - go func() { - defer close(resCh) - - time.Sleep(conf.Delay) - - // start with 0 delay for the first loop - var wait time.Duration - - for { - // store the last result - resCh <- result - - // wait and watch for cancellation - select { - case <-cancelCh: - return - case <-time.After(wait): - // first round had no wait - if wait == 0 { - wait = 100 * time.Millisecond - } - } - - res, currentState, err := conf.Refresh() - result = Result{ - Result: res, - State: currentState, - Error: err, - } - - if err != nil { - resCh <- result - return - } - - // If we're waiting for the absence of a thing, then return - if res == nil && len(conf.Target) == 0 { - targetOccurence++ - if conf.ContinuousTargetOccurence == targetOccurence { - result.Done = true - resCh <- result - return - } - continue - } - - if res == nil { - // If we didn't find the resource, check if we have been - // not finding it for awhile, and if so, report an error. - notfoundTick++ - if notfoundTick > conf.NotFoundChecks { - result.Error = &NotFoundError{ - LastError: err, - Retries: notfoundTick, - } - resCh <- result - return - } - } else { - // Reset the counter for when a resource isn't found - notfoundTick = 0 - found := false - - for _, allowed := range conf.Target { - if currentState == allowed { - found = true - targetOccurence++ - if conf.ContinuousTargetOccurence == targetOccurence { - result.Done = true - resCh <- result - return - } - continue - } - } - - for _, allowed := range conf.Pending { - if currentState == allowed { - found = true - targetOccurence = 0 - break - } - } - - if !found && len(conf.Pending) > 0 { - result.Error = &UnexpectedStateError{ - LastError: err, - State: result.State, - ExpectedState: conf.Target, - } - resCh <- result - return - } - } - - // Wait between refreshes using exponential backoff, except when - // waiting for the target state to reoccur. - if targetOccurence == 0 { - wait *= 2 - } - - // If a poll interval has been specified, choose that interval. - // Otherwise bound the default value. - if conf.PollInterval > 0 && conf.PollInterval < 180*time.Second { - wait = conf.PollInterval - } else { - if wait < conf.MinTimeout { - wait = conf.MinTimeout - } else if wait > 10*time.Second { - wait = 10 * time.Second - } - } - - log.Printf("[TRACE] Waiting %s before next try", wait) - } - }() - - // store the last value result from the refresh loop - lastResult := Result{} - - timeout := time.After(conf.Timeout) - for { - select { - case r, ok := <-resCh: - // channel closed, so return the last result - if !ok { - return lastResult.Result, lastResult.Error - } - - // we reached the intended state - if r.Done { - return r.Result, r.Error - } - - // still waiting, store the last result - lastResult = r - - case <-timeout: - log.Printf("[WARN] WaitForState timeout after %s", conf.Timeout) - log.Printf("[WARN] WaitForState starting %s refresh grace period", 30*time.Second) - - // cancel the goroutine and start our grace period timer - close(cancelCh) - timeout := time.After(30 * time.Second) - - // we need a for loop and a label to break on, because we may have - // an extra response value to read, but still want to wait for the - // channel to close. - forSelect: - for { - select { - case r, ok := <-resCh: - if r.Done { - // the last refresh loop reached the desired state - return r.Result, r.Error - } - - if !ok { - // the goroutine returned - break forSelect - } - - // target state not reached, save the result for the - // TimeoutError and wait for the channel to close - lastResult = r - case <-timeout: - log.Println("[ERROR] WaitForState exceeded refresh grace period") - break forSelect - } - } - - return nil, &TimeoutError{ - LastError: lastResult.Error, - LastState: lastResult.State, - Timeout: conf.Timeout, - ExpectedState: conf.Target, - } - } - } -} - -type StateChangeConf struct { - Delay time.Duration // Wait this time before starting checks - Pending []string // States that are "allowed" and will continue trying - Refresh StateRefreshFunc // Refreshes the current state - Target []string // Target state - Timeout time.Duration // The amount of time to wait before timeout - MinTimeout time.Duration // Smallest time to wait before refreshes - PollInterval time.Duration // Override MinTimeout/backoff and only poll this often - NotFoundChecks int // Number of times to allow not found - - // This is to work around inconsistent APIs - ContinuousTargetOccurence int // Number of times the Target state has to occur continuously -} - -type NotFoundError struct { - LastError error - LastRequest interface{} - LastResponse interface{} - Message string - Retries int -} - -func (e *NotFoundError) Error() string { - if e.Message != "" { - return e.Message - } - - if e.Retries > 0 { - return fmt.Sprintf("couldn't find resource (%d retries)", e.Retries) - } - - return "couldn't find resource" -} - -// UnexpectedStateError is returned when Refresh returns a state that's neither in Target nor Pending -type UnexpectedStateError struct { - LastError error - State string - ExpectedState []string -} - -func (e *UnexpectedStateError) Error() string { - return fmt.Sprintf( - "unexpected state '%s', wanted target '%s'. last error: %s", - e.State, - strings.Join(e.ExpectedState, ", "), - e.LastError, - ) -} - -// TimeoutError is returned when WaitForState times out -type TimeoutError struct { - LastError error - LastState string - Timeout time.Duration - ExpectedState []string -} - -func (e *TimeoutError) Error() string { - expectedState := "resource to be gone" - if len(e.ExpectedState) > 0 { - expectedState = fmt.Sprintf("state to become '%s'", strings.Join(e.ExpectedState, ", ")) - } - - extraInfo := make([]string, 0) - if e.LastState != "" { - extraInfo = append(extraInfo, fmt.Sprintf("last state: '%s'", e.LastState)) - } - if e.Timeout > 0 { - extraInfo = append(extraInfo, fmt.Sprintf("timeout: %s", e.Timeout.String())) - } - - suffix := "" - if len(extraInfo) > 0 { - suffix = fmt.Sprintf(" (%s)", strings.Join(extraInfo, ", ")) - } - - if e.LastError != nil { - return fmt.Sprintf("timeout while waiting for %s%s: %s", - expectedState, suffix, e.LastError) - } - - return fmt.Sprintf("timeout while waiting for %s%s", - expectedState, suffix) -} - -type StateRefreshFunc func() (result interface{}, state string, err error) diff --git a/builder/jdcloud/common.hcl2spec.go b/builder/jdcloud/common.hcl2spec.go deleted file mode 100644 index 8cfe8d8b5..000000000 --- a/builder/jdcloud/common.hcl2spec.go +++ /dev/null @@ -1,169 +0,0 @@ -// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT. - -package jdcloud - -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 { - AccessKey *string `mapstructure:"access_key" cty:"access_key" hcl:"access_key"` - SecretKey *string `mapstructure:"secret_key" cty:"secret_key" hcl:"secret_key"` - RegionId *string `mapstructure:"region_id" cty:"region_id" hcl:"region_id"` - Az *string `mapstructure:"az" cty:"az" hcl:"az"` - ImageId *string `mapstructure:"image_id" cty:"image_id" hcl:"image_id"` - InstanceName *string `mapstructure:"instance_name" cty:"instance_name" hcl:"instance_name"` - InstanceType *string `mapstructure:"instance_type" cty:"instance_type" hcl:"instance_type"` - ImageName *string `mapstructure:"image_name" cty:"image_name" hcl:"image_name"` - SubnetId *string `mapstructure:"subnet_id" cty:"subnet_id" hcl:"subnet_id"` - 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"` - InstanceId *string `cty:"instance_id" hcl:"instance_id"` - ArtifactId *string `cty:"artifact_id" hcl:"artifact_id"` - PublicIpAddress *string `cty:"public_ip_address" hcl:"public_ip_address"` - PublicIpId *string `cty:"public_ip_id" hcl:"public_ip_id"` - 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"` -} - -// 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{ - "access_key": &hcldec.AttrSpec{Name: "access_key", Type: cty.String, Required: false}, - "secret_key": &hcldec.AttrSpec{Name: "secret_key", Type: cty.String, Required: false}, - "region_id": &hcldec.AttrSpec{Name: "region_id", Type: cty.String, Required: false}, - "az": &hcldec.AttrSpec{Name: "az", Type: cty.String, Required: false}, - "image_id": &hcldec.AttrSpec{Name: "image_id", Type: cty.String, Required: false}, - "instance_name": &hcldec.AttrSpec{Name: "instance_name", Type: cty.String, Required: false}, - "instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false}, - "image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false}, - "subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: 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}, - "instance_id": &hcldec.AttrSpec{Name: "instance_id", Type: cty.String, Required: false}, - "artifact_id": &hcldec.AttrSpec{Name: "artifact_id", Type: cty.String, Required: false}, - "public_ip_address": &hcldec.AttrSpec{Name: "public_ip_address", Type: cty.String, Required: false}, - "public_ip_id": &hcldec.AttrSpec{Name: "public_ip_id", Type: cty.String, Required: false}, - "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}, - } - return s -} diff --git a/builder/jdcloud/credential_config.go b/builder/jdcloud/credential_config.go deleted file mode 100644 index 97b7962bc..000000000 --- a/builder/jdcloud/credential_config.go +++ /dev/null @@ -1,87 +0,0 @@ -package jdcloud - -import ( - "fmt" - "os" - - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" - "github.com/jdcloud-api/jdcloud-sdk-go/core" - vm "github.com/jdcloud-api/jdcloud-sdk-go/services/vm/client" - vpc "github.com/jdcloud-api/jdcloud-sdk-go/services/vpc/client" -) - -type JDCloudCredentialConfig struct { - AccessKey string `mapstructure:"access_key"` - SecretKey string `mapstructure:"secret_key"` - RegionId string `mapstructure:"region_id"` - Az string `mapstructure:"az"` -} - -func (jd *JDCloudCredentialConfig) Prepare(ctx *interpolate.Context) []error { - - errorArray := []error{} - - if jd == nil { - return append(errorArray, fmt.Errorf("[PRE-FLIGHT] Empty JDCloudCredentialConfig detected")) - } - - if err := jd.ValidateKeyPair(); err != nil { - errorArray = append(errorArray, err) - } - - if err := jd.validateRegion(); err != nil { - errorArray = append(errorArray, err) - } - - if err := jd.validateAz(); err != nil { - errorArray = append(errorArray, err) - } - - if len(errorArray) != 0 { - return errorArray - } - - credential := core.NewCredentials(jd.AccessKey, jd.SecretKey) - VmClient = vm.NewVmClient(credential) - VpcClient = vpc.NewVpcClient(credential) - Region = jd.RegionId - - return nil -} - -func (jd *JDCloudCredentialConfig) ValidateKeyPair() error { - - if jd.AccessKey == "" { - jd.AccessKey = os.Getenv("JDCLOUD_ACCESS_KEY") - } - - if jd.SecretKey == "" { - jd.SecretKey = os.Getenv("JDCLOUD_SECRET_KEY") - } - - if jd.AccessKey == "" || jd.SecretKey == "" { - return fmt.Errorf("[PRE-FLIGHT] We can't find your key pairs," + - "write them here {access_key=xxx , secret_key=xxx} " + - "or export them as env-variable, {export JDCLOUD_ACCESS_KEY=xxx, export JDCLOUD_SECRET_KEY=xxx} ") - } - - return nil -} - -func (jd *JDCloudCredentialConfig) validateRegion() error { - regionArray := []string{"cn-north-1", "cn-south-1", "cn-east-1", "cn-east-2"} - for _, item := range regionArray { - if item == jd.RegionId { - return nil - } - } - return fmt.Errorf("[PRE-FLIGHT] Invalid RegionId:%s. "+ - "Legit RegionId are: {cn-north-1, cn-south-1, cn-east-1, cn-east-2}", jd.RegionId) -} - -func (jd *JDCloudCredentialConfig) validateAz() error { - if len(jd.Az) == 0 { - return fmt.Errorf("[PRE-FLIGHT] az info missing") - } - return nil -} diff --git a/builder/jdcloud/credential_config_test.go b/builder/jdcloud/credential_config_test.go deleted file mode 100644 index ca245a1b4..000000000 --- a/builder/jdcloud/credential_config_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package jdcloud - -import ( - "testing" -) - -func TestJDCloudCredentialConfig_Prepare(t *testing.T) { - - creds := &JDCloudCredentialConfig{} - - if err := creds.Prepare(nil); err == nil { - t.Fatalf("Test shouldn't pass when there's nothing set") - } - - creds.AccessKey = "abc" - if err := creds.Prepare(nil); err == nil { - t.Fatalf("Test shouldn't pass when theres no Secret key") - } - - creds.SecretKey = "123" - if err := creds.Prepare(nil); err == nil { - t.Fatalf("Test shouldn't pass when theres no Az and region") - } - - creds.RegionId = "cn-west-1" - creds.Az = "cn-north-1c" - if err := creds.Prepare(nil); err == nil { - t.Fatalf("Test shouldn't pass when region_id illegal") - } - creds.RegionId = "cn-north-1" - if err := creds.Prepare(nil); err != nil { - t.Fatalf("Test shouldn't fail...") - } -} diff --git a/builder/jdcloud/examples/credential-key.json b/builder/jdcloud/examples/credential-key.json deleted file mode 100644 index b2f4da03e..000000000 --- a/builder/jdcloud/examples/credential-key.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "builders": [ - { - "type": "jdcloud", - "image_id": "", - "access_key": "", - "secret_key": "", - "region_id": "cn-north-1", - "az": "cn-north-1c", - "instance_name": "created_by_packer", - "instance_type": "g.n2.medium", - - "ssh_private_key_file":"/Path/to/your/.ssh/id_rsa", - "ssh_keypair_name":"packer_keys", - - "image_name": "created_by_packer", - "subnet_id": "", - "communicator":"ssh", - "ssh_username": "root", - "ssh_timeout" : "60s" - } - ], - - "provisioners": [ - { - "type": "shell", - "inline": [ - "sleep 3", - "echo 123", - "pwd" - ] - } - ] -} diff --git a/builder/jdcloud/examples/credential-new-key.json b/builder/jdcloud/examples/credential-new-key.json deleted file mode 100644 index 7b7187b61..000000000 --- a/builder/jdcloud/examples/credential-new-key.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "builders": [ - { - "type": "jdcloud", - "image_id": "", - "access_key": "", - "secret_key": "", - "region_id": "cn-north-1", - "az": "cn-north-1c", - "instance_name": "created_by_packer", - "instance_type": "g.n2.medium", - "image_name": "packerImage", - "temporary_key_pair_name": "whatever_new_key_name", - "subnet_id": "", - "communicator":"ssh", - "ssh_username": "root", - "ssh_timeout" : "60s" - } - ], - - "provisioners": [ - { - "type": "shell", - "inline": [ - "sleep 3", - "echo 123", - "pwd" - ] - } - ] -} diff --git a/builder/jdcloud/examples/credential-password.json b/builder/jdcloud/examples/credential-password.json deleted file mode 100644 index 5e6aa80db..000000000 --- a/builder/jdcloud/examples/credential-password.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "builders": [ - { - "type": "jdcloud", - "image_id": "img-h8ly274zg9", - "access_key": "", - "secret_key": "", - "region_id": "cn-north-1", - "az": "cn-north-1c", - "instance_name": "created_by_packer", - "instance_type": "g.n2.medium", - "ssh_password":"/Users/mac/.ssh/id_rsa", - "ssh_keypair_name":"created_by_xiaohan", - "image_name": "packerImage", - "subnet_id": "subnet-jo6e38sdli", - "communicator":"ssh", - "ssh_username": "root", - "ssh_timeout" : "60s" - } - ], - - "provisioners": [ - { - "type": "shell", - "inline": [ - "sleep 3", - "echo 123", - "pwd" - ] - } - ] -} diff --git a/builder/jdcloud/examples/use_new_subnet.json b/builder/jdcloud/examples/use_new_subnet.json deleted file mode 100644 index a4881ca0a..000000000 --- a/builder/jdcloud/examples/use_new_subnet.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "builders": [ - { - "type": "jdcloud", - "image_id": "img-h8ly274zg9", - "access_key": "", - "secret_key": "", - "region_id": "cn-north-1", - "az": "cn-north-1c", - "instance_name": "created_by_packer", - "instance_type": "g.n2.medium", - "ssh_password":"/Users/mac/.ssh/id_rsa", - "ssh_keypair_name":"created_by_xiaohan", - "image_name": "packerImage", - - - - "communicator":"ssh", - "ssh_username": "root", - "ssh_timeout" : "60s" - } - ], - - "provisioners": [ - { - "type": "shell", - "inline": [ - "sleep 3", - "echo 123", - "pwd" - ] - } - ] -} diff --git a/builder/jdcloud/instance_config.go b/builder/jdcloud/instance_config.go deleted file mode 100644 index c7b069214..000000000 --- a/builder/jdcloud/instance_config.go +++ /dev/null @@ -1,54 +0,0 @@ -package jdcloud - -import ( - "fmt" - - "github.com/hashicorp/packer-plugin-sdk/communicator" - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" -) - -type JDCloudInstanceSpecConfig struct { - ImageId string `mapstructure:"image_id"` - InstanceName string `mapstructure:"instance_name"` - InstanceType string `mapstructure:"instance_type"` - ImageName string `mapstructure:"image_name"` - SubnetId string `mapstructure:"subnet_id"` - Comm communicator.Config `mapstructure:",squash"` - InstanceId string - ArtifactId string - PublicIpAddress string - PublicIpId string -} - -func (jd *JDCloudInstanceSpecConfig) Prepare(ctx *interpolate.Context) []error { - - errs := jd.Comm.Prepare(ctx) - - if jd == nil { - return append(errs, fmt.Errorf("[PRE-FLIGHT] Configuration appears to be empty")) - } - - if len(jd.ImageId) == 0 { - errs = append(errs, fmt.Errorf("[PRE-FLIGHT] 'image_id' empty")) - } - - if len(jd.InstanceName) == 0 { - errs = append(errs, fmt.Errorf("[PRE-FLIGHT] 'instance_name' empty")) - } - - if len(jd.InstanceType) == 0 { - errs = append(errs, fmt.Errorf("[PRE-FLIGHT] 'instance-type' empty")) - } - - noPassword := len(jd.Comm.SSHPassword) == 0 - noKeys := len(jd.Comm.SSHKeyPairName) == 0 && len(jd.Comm.SSHPrivateKeyFile) == 0 - noTempKey := len(jd.Comm.SSHTemporaryKeyPairName) == 0 - if noPassword && noKeys && noTempKey { - errs = append(errs, fmt.Errorf("[PRE-FLIGHT] Didn't detect any credentials, you have to specify either "+ - "{password} or "+ - "{key_name+local_private_key_path} or "+ - "{temporary_key_pair_name} cheers :)")) - } - - return errs -} diff --git a/builder/jdcloud/instance_config_test.go b/builder/jdcloud/instance_config_test.go deleted file mode 100644 index 36ede82ca..000000000 --- a/builder/jdcloud/instance_config_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package jdcloud - -import ( - "testing" -) - -func TestJDCloudInstanceSpecConfig_Prepare(t *testing.T) { - - specs := &JDCloudInstanceSpecConfig{} - if err := specs.Prepare(nil); err == nil { - t.Fatalf("Test shouldn't pass when there's nothing set") - } - - specs.InstanceName = "packer_test_instance_name" - specs.InstanceType = "packer_test_instance_type" - if err := specs.Prepare(nil); err == nil { - t.Fatalf("Test shouldn't pass when base-image not given") - } - - specs.ImageId = "img-packer-test" - if err := specs.Prepare(nil); err == nil { - t.Fatalf("Test shouldn't pass when credentials not set") - } - - specs.Comm.SSHPassword = "abc123" - if err := specs.Prepare(nil); err == nil { - t.Fatalf("Test shouldn't pass when username = nil") - } - - specs.Comm.SSHUsername = "root" - if err := specs.Prepare(nil); err != nil { - t.Fatalf("Test shouldn't fail when password set ") - } - - specs.Comm.SSHPassword = "" - specs.Comm.SSHTemporaryKeyPairName = "abc" - if err := specs.Prepare(nil); err != nil { - t.Fatalf("Test shouldn't fail when temp password set") - } - - specs.Comm.SSHTemporaryKeyPairName = "" - specs.Comm.SSHPrivateKeyFile = "abc" - specs.Comm.SSHKeyPairName = "" - if err := specs.Prepare(nil); err == nil { - t.Fatalf("Test shouldn't pass when SSHKeypairName missing") - } - - specs.Comm.SSHPrivateKeyFile = "abc" - specs.Comm.SSHKeyPairName = "123" - if err := specs.Prepare(nil); err == nil { - t.Fatalf("Test shouldn't pass when private key pair path is wrong ") - } - -} diff --git a/builder/jdcloud/step_config_credentials.go b/builder/jdcloud/step_config_credentials.go deleted file mode 100644 index 58965555a..000000000 --- a/builder/jdcloud/step_config_credentials.go +++ /dev/null @@ -1,74 +0,0 @@ -package jdcloud - -import ( - "context" - "fmt" - "io/ioutil" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/jdcloud-api/jdcloud-sdk-go/services/vm/apis" -) - -type stepConfigCredentials struct { - InstanceSpecConfig *JDCloudInstanceSpecConfig - ui packersdk.Ui -} - -func (s *stepConfigCredentials) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { - - s.ui = state.Get("ui").(packersdk.Ui) - password := s.InstanceSpecConfig.Comm.SSHPassword - privateKeyPath := s.InstanceSpecConfig.Comm.SSHPrivateKeyFile - privateKeyName := s.InstanceSpecConfig.Comm.SSHKeyPairName - newKeyName := s.InstanceSpecConfig.Comm.SSHTemporaryKeyPairName - - if len(privateKeyPath) > 0 && len(privateKeyName) > 0 { - s.ui.Message("\t Private key detected, we are going to login with this private key :)") - return s.ReadExistingPair() - } - - if len(newKeyName) > 0 { - s.ui.Message("\t We are going to create a new key pair with its name=" + newKeyName) - return s.CreateRandomKeyPair(newKeyName) - } - - if len(password) > 0 { - s.ui.Message("\t Password detected, we are going to login with this password :)") - return multistep.ActionContinue - } - - s.ui.Error("[ERROR] Didn't detect any credentials, you have to specify either " + - "{password} or " + - "{key_name+local_private_key_path} or " + - "{temporary_key_pair_name} cheers :)") - return multistep.ActionHalt -} - -func (s *stepConfigCredentials) ReadExistingPair() multistep.StepAction { - privateKeyBytes, err := ioutil.ReadFile(s.InstanceSpecConfig.Comm.SSHPrivateKeyFile) - if err != nil { - s.ui.Error("Cannot read local private-key, were they correctly placed? Here's the error" + err.Error()) - return multistep.ActionHalt - } - s.ui.Message("\t\t Keys read successfully :)") - s.InstanceSpecConfig.Comm.SSHPrivateKey = privateKeyBytes - return multistep.ActionContinue -} - -func (s *stepConfigCredentials) CreateRandomKeyPair(keyName string) multistep.StepAction { - req := apis.NewCreateKeypairRequest(Region, keyName) - resp, err := VmClient.CreateKeypair(req) - if err != nil || resp.Error.Code != FINE { - s.ui.Error(fmt.Sprintf("[ERROR] Cannot create a new key pair for you, \n error=%v \n response=%v", err, resp)) - return multistep.ActionHalt - } - s.ui.Message("\t\t Keys created successfully :)") - s.InstanceSpecConfig.Comm.SSHPrivateKey = []byte(resp.Result.PrivateKey) - s.InstanceSpecConfig.Comm.SSHKeyPairName = keyName - return multistep.ActionContinue -} - -func (s *stepConfigCredentials) Cleanup(state multistep.StateBag) { - -} diff --git a/builder/jdcloud/step_create_image.go b/builder/jdcloud/step_create_image.go deleted file mode 100644 index db29cf017..000000000 --- a/builder/jdcloud/step_create_image.go +++ /dev/null @@ -1,75 +0,0 @@ -package jdcloud - -import ( - "context" - "fmt" - "time" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/jdcloud-api/jdcloud-sdk-go/services/vm/apis" -) - -type stepCreateJDCloudImage struct { - InstanceSpecConfig *JDCloudInstanceSpecConfig -} - -func (s *stepCreateJDCloudImage) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { - - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Creating images") - - req := apis.NewCreateImageRequest(Region, s.InstanceSpecConfig.InstanceId, s.InstanceSpecConfig.ImageName, "") - resp, err := VmClient.CreateImage(req) - if err != nil || resp.Error.Code != FINE { - ui.Error(fmt.Sprintf("[ERROR] Creating image: Error-%v ,Resp:%v", err, resp)) - return multistep.ActionHalt - } - - s.InstanceSpecConfig.ArtifactId = resp.Result.ImageId - if err := ImageStatusWaiter(s.InstanceSpecConfig.ArtifactId); err != nil { - ui.Error(err.Error()) - return multistep.ActionHalt - } - - return multistep.ActionContinue -} - -func ImageStatusWaiter(imageId string) error { - req := apis.NewDescribeImageRequest(Region, imageId) - - return Retry(5*time.Minute, func() *RetryError { - resp, err := VmClient.DescribeImage(req) - if err == nil && resp.Result.Image.Status == READY { - return nil - } - if connectionError(err) { - return RetryableError(err) - } else { - return NonRetryableError(err) - } - }) - -} - -// Delete created instance image on error -func (s *stepCreateJDCloudImage) Cleanup(state multistep.StateBag) { - - if s.InstanceSpecConfig.ArtifactId != "" { - - req := apis.NewDeleteImageRequest(Region, s.InstanceSpecConfig.ArtifactId) - - _ = Retry(time.Minute, func() *RetryError { - _, err := VmClient.DeleteImage(req) - if err == nil { - return nil - } - if connectionError(err) { - return RetryableError(err) - } else { - return NonRetryableError(err) - } - }) - } - -} diff --git a/builder/jdcloud/step_create_instance.go b/builder/jdcloud/step_create_instance.go deleted file mode 100644 index d00faf30d..000000000 --- a/builder/jdcloud/step_create_instance.go +++ /dev/null @@ -1,227 +0,0 @@ -package jdcloud - -import ( - "context" - "fmt" - "regexp" - "time" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/jdcloud-api/jdcloud-sdk-go/core" - "github.com/jdcloud-api/jdcloud-sdk-go/services/vm/apis" - vm "github.com/jdcloud-api/jdcloud-sdk-go/services/vm/models" - vpcApis "github.com/jdcloud-api/jdcloud-sdk-go/services/vpc/apis" - vpcClient "github.com/jdcloud-api/jdcloud-sdk-go/services/vpc/client" - vpc "github.com/jdcloud-api/jdcloud-sdk-go/services/vpc/models" -) - -type stepCreateJDCloudInstance struct { - InstanceSpecConfig *JDCloudInstanceSpecConfig - CredentialConfig *JDCloudCredentialConfig - ui packersdk.Ui -} - -func (s *stepCreateJDCloudInstance) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { - - privateKey := s.InstanceSpecConfig.Comm.SSHPrivateKey - keyName := s.InstanceSpecConfig.Comm.SSHKeyPairName - password := s.InstanceSpecConfig.Comm.SSHPassword - s.ui = state.Get("ui").(packersdk.Ui) - s.ui.Say("Creating instances") - - instanceSpec := vm.InstanceSpec{ - Az: &s.CredentialConfig.Az, - InstanceType: &s.InstanceSpecConfig.InstanceType, - ImageId: &s.InstanceSpecConfig.ImageId, - Name: s.InstanceSpecConfig.InstanceName, - PrimaryNetworkInterface: &vm.InstanceNetworkInterfaceAttachmentSpec{ - NetworkInterface: &vpc.NetworkInterfaceSpec{ - SubnetId: s.InstanceSpecConfig.SubnetId, - Az: &s.CredentialConfig.Az, - }, - }, - } - - if len(password) > 0 { - instanceSpec.Password = &password - } - if len(keyName) > 0 && len(privateKey) > 0 { - instanceSpec.KeyNames = []string{keyName} - } - - req := apis.NewCreateInstancesRequest(Region, &instanceSpec) - resp, err := VmClient.CreateInstances(req) - - if err != nil || resp.Error.Code != FINE { - err := fmt.Errorf("Error creating instance, error-%v response:%v", err, resp) - s.ui.Error(err.Error()) - return multistep.ActionHalt - } - - s.InstanceSpecConfig.InstanceId = resp.Result.InstanceIds[0] - instanceInterface, err := InstanceStatusRefresher(s.InstanceSpecConfig.InstanceId, []string{VM_PENDING, VM_STARTING}, []string{VM_RUNNING}) - if err != nil { - s.ui.Error(err.Error()) - return multistep.ActionHalt - } - - instance := instanceInterface.(vm.Instance) - privateIpAddress := instance.PrivateIpAddress - networkInterfaceId := instance.PrimaryNetworkInterface.NetworkInterface.NetworkInterfaceId - - s.ui.Message("Creating public-ip") - s.InstanceSpecConfig.PublicIpId, err = createElasticIp(state) - if err != nil { - s.ui.Error(err.Error()) - return multistep.ActionHalt - } - - s.ui.Message("Associating public-ip with instance") - err = associatePublicIp(networkInterfaceId, s.InstanceSpecConfig.PublicIpId, privateIpAddress) - if err != nil { - s.ui.Error(err.Error()) - return multistep.ActionHalt - } - - req_ := vpcApis.NewDescribeElasticIpRequest(Region, s.InstanceSpecConfig.PublicIpId) - eip, err := VpcClient.DescribeElasticIp(req_) - if err != nil || eip.Error.Code != FINE { - s.ui.Error(fmt.Sprintf("[ERROR] Failed in getting eip,error:%v \n response:%v", err, eip)) - return multistep.ActionHalt - } - - s.InstanceSpecConfig.PublicIpAddress = eip.Result.ElasticIp.ElasticIpAddress - state.Put("eip", s.InstanceSpecConfig.PublicIpAddress) - s.ui.Message(fmt.Sprintf( - "Hi, we have created the instance, its name=%v , "+ - "its id=%v, "+ - "and its eip=%v :) ", instance.InstanceName, s.InstanceSpecConfig.InstanceId, eip.Result.ElasticIp.ElasticIpAddress)) - // 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", s.InstanceSpecConfig.InstanceId) - return multistep.ActionContinue -} - -// Delete created resources {instance,ip} on error -func (s *stepCreateJDCloudInstance) Cleanup(state multistep.StateBag) { - - if s.InstanceSpecConfig.PublicIpId != "" { - - req := vpcApis.NewDeleteElasticIpRequest(Region, s.InstanceSpecConfig.PublicIpId) - - _ = Retry(time.Minute, func() *RetryError { - _, err := VpcClient.DeleteElasticIp(req) - if err == nil { - return nil - } - if connectionError(err) { - return RetryableError(err) - } else { - return NonRetryableError(err) - } - }) - } - - if s.InstanceSpecConfig.InstanceId != "" { - - req := apis.NewDeleteInstanceRequest(Region, s.InstanceSpecConfig.InstanceId) - _ = Retry(time.Minute, func() *RetryError { - _, err := VmClient.DeleteInstance(req) - if err == nil { - return nil - } - if connectionError(err) { - return RetryableError(err) - } else { - return NonRetryableError(err) - } - }) - } -} - -func createElasticIp(state multistep.StateBag) (string, error) { - - generalConfig := state.Get("config").(*Config) - regionId := generalConfig.RegionId - credential := core.NewCredentials(generalConfig.AccessKey, generalConfig.SecretKey) - vpcclient := vpcClient.NewVpcClient(credential) - - req := vpcApis.NewCreateElasticIpsRequest(regionId, 1, &vpc.ElasticIpSpec{ - BandwidthMbps: 1, - Provider: "bgp", - }) - - resp, err := vpcclient.CreateElasticIps(req) - - if err != nil || resp.Error.Code != 0 { - return "", fmt.Errorf("[ERROR] Failed in creating new publicIp, Error-%v, Response:%v", err, resp) - } - return resp.Result.ElasticIpIds[0], nil -} - -func associatePublicIp(networkInterfaceId string, eipId string, privateIpAddress string) error { - req := vpcApis.NewAssociateElasticIpRequest(Region, networkInterfaceId) - req.ElasticIpId = &eipId - req.PrivateIpAddress = &privateIpAddress - resp, err := VpcClient.AssociateElasticIp(req) - if err != nil || resp.Error.Code != FINE { - return fmt.Errorf("[ERROR] Failed in associating publicIp, Error-%v, Response:%v", err, resp) - } - return nil -} -func instanceHost(state multistep.StateBag) (string, error) { - return state.Get("eip").(string), nil -} - -func InstanceStatusRefresher(id string, pending, target []string) (instance interface{}, err error) { - - stateConf := &StateChangeConf{ - Pending: pending, - Target: target, - Refresh: instanceStatusRefresher(id), - Delay: 3 * time.Second, - Timeout: 10 * time.Minute, - MinTimeout: 1 * time.Second, - } - if instance, err = stateConf.WaitForState(); err != nil { - return nil, fmt.Errorf("[ERROR] Failed in creating instance ,err message:%v", err) - } - return instance, nil -} - -func instanceStatusRefresher(instanceId string) StateRefreshFunc { - - return func() (instance interface{}, status string, err error) { - - err = Retry(time.Minute, func() *RetryError { - - req := apis.NewDescribeInstanceRequest(Region, instanceId) - resp, err := VmClient.DescribeInstance(req) - - if err == nil && resp.Error.Code == FINE { - instance = resp.Result.Instance - status = resp.Result.Instance.Status - return nil - } - - instance = nil - status = "" - if connectionError(err) { - return RetryableError(err) - } else { - return NonRetryableError(err) - } - }) - return instance, status, err - } -} - -func connectionError(e error) bool { - - if e == nil { - return false - } - ok, _ := regexp.MatchString(CONNECT_FAILED, e.Error()) - return ok -} diff --git a/builder/jdcloud/step_stop_instance.go b/builder/jdcloud/step_stop_instance.go deleted file mode 100644 index 31b529b09..000000000 --- a/builder/jdcloud/step_stop_instance.go +++ /dev/null @@ -1,40 +0,0 @@ -package jdcloud - -import ( - "context" - "fmt" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/jdcloud-api/jdcloud-sdk-go/services/vm/apis" -) - -type stepStopJDCloudInstance struct { - InstanceSpecConfig *JDCloudInstanceSpecConfig -} - -func (s *stepStopJDCloudInstance) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { - - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Stopping this instance") - - req := apis.NewStopInstanceRequest(Region, s.InstanceSpecConfig.InstanceId) - resp, err := VmClient.StopInstance(req) - if err != nil || resp.Error.Code != FINE { - ui.Error(fmt.Sprintf("[ERROR] Failed in trying to stop this vm: Error-%v ,Resp:%v", err, resp)) - return multistep.ActionHalt - } - - _, err = InstanceStatusRefresher(s.InstanceSpecConfig.InstanceId, []string{VM_RUNNING, VM_STOPPING}, []string{VM_STOPPED}) - if err != nil { - ui.Error(err.Error()) - return multistep.ActionHalt - } - - ui.Message("Instance has been stopped :)") - return multistep.ActionContinue -} - -func (s *stepStopJDCloudInstance) Cleanup(multistep.StateBag) { - return -} diff --git a/builder/jdcloud/step_validate_parameters.go b/builder/jdcloud/step_validate_parameters.go deleted file mode 100644 index f4ce1e442..000000000 --- a/builder/jdcloud/step_validate_parameters.go +++ /dev/null @@ -1,110 +0,0 @@ -package jdcloud - -import ( - "context" - "fmt" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - vm "github.com/jdcloud-api/jdcloud-sdk-go/services/vm/apis" - vpc "github.com/jdcloud-api/jdcloud-sdk-go/services/vpc/apis" -) - -type stepValidateParameters struct { - InstanceSpecConfig *JDCloudInstanceSpecConfig - ui packersdk.Ui - state multistep.StateBag -} - -func (s *stepValidateParameters) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { - - s.ui = state.Get("ui").(packersdk.Ui) - s.state = state - s.ui.Say("Validating parameters...") - - if err := s.ValidateSubnetFunc(); err != nil { - s.ui.Error(err.Error()) - return multistep.ActionHalt - } - - if err := s.ValidateImageFunc(); err != nil { - s.ui.Error(err.Error()) - return multistep.ActionHalt - } - - return multistep.ActionContinue -} - -func (s *stepValidateParameters) ValidateSubnetFunc() error { - - subnetId := s.InstanceSpecConfig.SubnetId - if len(subnetId) == 0 { - s.ui.Message("\t 'subnet' is not specified, we will create a new one for you :) ") - return s.CreateRandomSubnet() - } - - s.ui.Message("\t validating your subnet:" + s.InstanceSpecConfig.SubnetId) - req := vpc.NewDescribeSubnetRequest(Region, subnetId) - resp, err := VpcClient.DescribeSubnet(req) - if err != nil { - return fmt.Errorf("[ERROR] Failed in validating subnet->%s, reasons:%v", subnetId, err) - } - if resp != nil && resp.Error.Code != FINE { - return fmt.Errorf("[ERROR] Something wrong with your subnet->%s, reasons:%v", subnetId, resp.Error) - } - - s.ui.Message("\t subnet found:" + resp.Result.Subnet.SubnetName) - return nil - -} - -func (s *stepValidateParameters) ValidateImageFunc() error { - - s.ui.Message("\t validating your base image:" + s.InstanceSpecConfig.ImageId) - imageId := s.InstanceSpecConfig.ImageId - req := vm.NewDescribeImageRequest(Region, imageId) - resp, err := VmClient.DescribeImage(req) - if err != nil { - return fmt.Errorf("[ERROR] Failed in validating your image->%s, reasons:%v", imageId, err) - } - if resp != nil && resp.Error.Code != FINE { - return fmt.Errorf("[ERROR] Something wrong with your image->%s, reasons:%v", imageId, resp.Error) - } - - s.ui.Message("\t image found:" + resp.Result.Image.Name) - s.state.Put("source_image", &resp.Result.Image) - return nil -} - -func (s *stepValidateParameters) CreateRandomSubnet() error { - - newVpc, err := s.CreateRandomVpc() - if err != nil { - return err - } - - req := vpc.NewCreateSubnetRequest(Region, newVpc, "created_by_packer", "192.168.0.0/20") - resp, err := VpcClient.CreateSubnet(req) - if err != nil || resp.Error.Code != FINE { - errorMessage := fmt.Sprintf("[ERROR] Failed in creating new subnet :( \n error:%v \n response:%v", err, resp) - s.ui.Error(errorMessage) - return fmt.Errorf(errorMessage) - } - - s.InstanceSpecConfig.SubnetId = resp.Result.SubnetId - s.ui.Message("\t\t Hi, we have created a new subnet for you :) its name is 'created_by_packer' and its id=" + resp.Result.SubnetId) - return nil -} - -func (s *stepValidateParameters) CreateRandomVpc() (string, error) { - req := vpc.NewCreateVpcRequest(Region, "created_by_packer") - resp, err := VpcClient.CreateVpc(req) - if err != nil || resp.Error.Code != FINE { - errorMessage := fmt.Sprintf("[ERROR] Failed in creating new vpc :( \n error :%v, \n response:%v", err, resp) - s.ui.Error(errorMessage) - return "", fmt.Errorf(errorMessage) - } - return resp.Result.VpcId, nil -} - -func (s *stepValidateParameters) Cleanup(state multistep.StateBag) {} diff --git a/builder/jdcloud/version/version.go b/builder/jdcloud/version/version.go deleted file mode 100644 index 5383c98ac..000000000 --- a/builder/jdcloud/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 JDCloudPluginVersion *version.PluginVersion - -func init() { - JDCloudPluginVersion = version.InitializePluginVersion( - packerVersion.Version, packerVersion.VersionPrerelease) -} diff --git a/builder/linode/artifact.go b/builder/linode/artifact.go deleted file mode 100644 index 9fe2e9a86..000000000 --- a/builder/linode/artifact.go +++ /dev/null @@ -1,38 +0,0 @@ -package linode - -import ( - "context" - "fmt" - "log" - - "github.com/linode/linodego" -) - -type Artifact struct { - ImageID string - ImageLabel string - - Driver *linodego.Client - - // 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("Linode image: %s (%s)", a.ImageLabel, a.ImageID) -} - -func (a Artifact) State(name string) interface{} { - return a.StateData[name] -} - -func (a Artifact) Destroy() error { - log.Printf("Destroying image: %s (%s)", a.ImageID, a.ImageLabel) - err := a.Driver.DeleteImage(context.TODO(), a.ImageID) - return err -} diff --git a/builder/linode/artifact_test.go b/builder/linode/artifact_test.go deleted file mode 100644 index 2bc6242b3..000000000 --- a/builder/linode/artifact_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package linode - -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 TestArtifactId(t *testing.T) { - generatedData := make(map[string]interface{}) - a := &Artifact{"private/42", "packer-foobar", nil, generatedData} - expected := "private/42" - - if a.Id() != expected { - t.Fatalf("artifact ID should match: %v", expected) - } -} - -func TestArtifactString(t *testing.T) { - generatedData := make(map[string]interface{}) - a := &Artifact{"private/42", "packer-foobar", nil, generatedData} - expected := "Linode image: packer-foobar (private/42)" - - 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/linode/builder.go b/builder/linode/builder.go deleted file mode 100644 index 2efe7d132..000000000 --- a/builder/linode/builder.go +++ /dev/null @@ -1,117 +0,0 @@ -// The linode package contains a packersdk.Builder implementation -// that builds Linode images. -package linode - -import ( - "context" - "errors" - "fmt" - "log" - - "github.com/hashicorp/hcl/v2/hcldec" - "github.com/linode/linodego" - - "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" -) - -// The unique ID for this builder. -const BuilderID = "packer.linode" - -// Builder represents a Packer Builder. -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, nil, nil -} - -func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (ret packersdk.Artifact, err error) { - ui.Say("Running builder ...") - - client := newLinodeClient(b.config.PersonalAccessToken) - - if err != nil { - ui.Error(err.Error()) - return nil, err - } - - 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("linode_%s.pem", b.config.PackerBuildName), - }, - &stepCreateLinode{client}, - &communicator.StepConnect{ - Config: &b.config.Comm, - Host: commHost(b.config.Comm.Host()), - SSHConfig: b.config.Comm.SSHConfigFunc(), - }, - &commonsteps.StepProvision{}, - &commonsteps.StepCleanupTempKeys{ - Comm: &b.config.Comm, - }, - &stepShutdownLinode{client}, - &stepCreateImage{client}, - } - - 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) - } - - // If we were interrupted or cancelled, then just exit. - if _, ok := state.GetOk(multistep.StateCancelled); ok { - return nil, errors.New("Build was cancelled.") - } - - if _, ok := state.GetOk(multistep.StateHalted); ok { - return nil, errors.New("Build was halted.") - } - - if _, ok := state.GetOk("image"); !ok { - return nil, errors.New("Cannot find image in state.") - } - - image := state.Get("image").(*linodego.Image) - artifact := Artifact{ - ImageLabel: image.Label, - ImageID: image.ID, - Driver: &client, - StateData: map[string]interface{}{"generated_data": state.Get("generated_data")}, - } - - return artifact, nil -} - -func commHost(host string) func(multistep.StateBag) (string, error) { - return func(state multistep.StateBag) (string, error) { - if host != "" { - log.Printf("Using host value: %s", host) - return host, nil - } - - instance := state.Get("instance").(*linodego.Instance) - if len(instance.IPv4) == 0 { - return "", fmt.Errorf("Linode instance %d has no IPv4 addresses!", instance.ID) - } - return instance.IPv4[0].String(), nil - } -} diff --git a/builder/linode/builder_acc_test.go b/builder/linode/builder_acc_test.go deleted file mode 100644 index 74acf48e9..000000000 --- a/builder/linode/builder_acc_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package linode - -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("LINODE_TOKEN"); v == "" { - t.Fatal("LINODE_TOKEN must be set for acceptance tests") - } -} - -const testBuilderAccBasic = ` -{ - "builders": [{ - "type": "test", - "region": "us-east", - "instance_type": "g6-nanode-1", - "image": "linode/alpine3.9", - "ssh_username": "root" - }] -} -` diff --git a/builder/linode/builder_test.go b/builder/linode/builder_test.go deleted file mode 100644 index 856ed03fb..000000000 --- a/builder/linode/builder_test.go +++ /dev/null @@ -1,291 +0,0 @@ -package linode - -import ( - "strconv" - "testing" - "time" - - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -func testConfig() map[string]interface{} { - return map[string]interface{}{ - "linode_token": "bar", - "region": "us-east", - "instance_type": "g6-nanode-1", - "ssh_username": "root", - "image": "linode/alpine3.9", - } -} - -func TestBuilder_ImplementsBuilder(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{}{ - "linode_token": []string{}, - } - - _, warnings, err := b.Prepare(c) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err == nil { - t.Fatalf("prepare should fail") - } -} - -func TestBuilderPrepare_InvalidKey(t *testing.T) { - var b Builder - config := testConfig() - - // Add a random key - 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") - } -} - -func TestBuilderPrepare_Region(t *testing.T) { - var b Builder - config := testConfig() - - // Test default - delete(config, "region") - _, warnings, err := b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err == nil { - t.Fatalf("should error") - } - - expected := "us-east" - - // Test set - config["region"] = expected - b = Builder{} - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - if b.config.Region != expected { - t.Errorf("found %s, expected %s", b.config.Region, expected) - } -} - -func TestBuilderPrepare_Size(t *testing.T) { - var b Builder - config := testConfig() - - // Test default - delete(config, "instance_type") - _, warnings, err := b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err == nil { - t.Fatalf("should error") - } - - expected := "g6-nanode-1" - - // Test set - config["instance_type"] = expected - b = Builder{} - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - if b.config.InstanceType != expected { - t.Errorf("found %s, expected %s", b.config.InstanceType, expected) - } -} - -func TestBuilderPrepare_Image(t *testing.T) { - var b Builder - config := testConfig() - - // Test default - delete(config, "image") - _, warnings, err := b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err == nil { - t.Fatal("should error") - } - - expected := "linode/alpine3.9" - - // Test set - config["image"] = expected - b = Builder{} - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - if b.config.Image != expected { - t.Errorf("found %s, expected %s", b.config.Image, expected) - } -} - -func TestBuilderPrepare_ImageLabel(t *testing.T) { - var b Builder - config := testConfig() - - // Test default - _, warnings, err := b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - if b.config.ImageLabel == "" { - t.Errorf("invalid: %s", b.config.ImageLabel) - } - - // Test set - config["image_label"] = "foobarbaz" - b = Builder{} - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - // Test set with template - config["image_label"] = "{{timestamp}}" - b = Builder{} - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - _, err = strconv.ParseInt(b.config.ImageLabel, 0, 0) - if err != nil { - t.Fatalf("failed to parse int in template: %s", err) - } - -} - -func TestBuilderPrepare_Label(t *testing.T) { - var b Builder - config := testConfig() - - // Test default - _, warnings, err := b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - if b.config.Label == "" { - t.Errorf("invalid: %s", b.config.Label) - } - - // Test normal set - config["instance_label"] = "foobar" - b = Builder{} - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - // Test with template - config["instance_label"] = "foobar-{{timestamp}}" - b = Builder{} - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - // Test with bad template - config["instance_label"] = "foobar-{{" - b = Builder{} - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err == nil { - t.Fatal("should have error") - } - -} - -func TestBuilderPrepare_StateTimeout(t *testing.T) { - var b Builder - config := testConfig() - - // Test default - _, warnings, err := b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - if b.config.StateTimeout != 5*time.Minute { - t.Errorf("invalid: %s", b.config.StateTimeout) - } - - // Test set - config["state_timeout"] = "5m" - b = Builder{} - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - // Test bad - config["state_timeout"] = "tubes" - b = Builder{} - _, 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/linode/config.go b/builder/linode/config.go deleted file mode 100644 index f72a498b4..000000000 --- a/builder/linode/config.go +++ /dev/null @@ -1,148 +0,0 @@ -//go:generate packer-sdc mapstructure-to-hcl2 -type Config - -package linode - -import ( - "crypto/rand" - "encoding/base64" - "errors" - "fmt" - "os" - "regexp" - "time" - - "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" -) - -type Config struct { - common.PackerConfig `mapstructure:",squash"` - ctx interpolate.Context - Comm communicator.Config `mapstructure:",squash"` - - PersonalAccessToken string `mapstructure:"linode_token"` - - Region string `mapstructure:"region"` - InstanceType string `mapstructure:"instance_type"` - Label string `mapstructure:"instance_label"` - Tags []string `mapstructure:"instance_tags"` - Image string `mapstructure:"image"` - SwapSize int `mapstructure:"swap_size"` - RootPass string `mapstructure:"root_pass"` - RootSSHKey string `mapstructure:"root_ssh_key"` - ImageLabel string `mapstructure:"image_label"` - Description string `mapstructure:"image_description"` - StateTimeout time.Duration `mapstructure:"state_timeout" required:"false"` -} - -func createRandomRootPassword() (string, error) { - rawRootPass := make([]byte, 50) - _, err := rand.Read(rawRootPass) - if err != nil { - return "", fmt.Errorf("Failed to generate random password") - } - rootPass := base64.StdEncoding.EncodeToString(rawRootPass) - return rootPass, nil -} - -func (c *Config) Prepare(raws ...interface{}) ([]string, error) { - - if err := config.Decode(c, &config.DecodeOpts{ - Interpolate: true, - InterpolateContext: &c.ctx, - InterpolateFilter: &interpolate.RenderFilter{ - Exclude: []string{ - "run_command", - }, - }, - }, raws...); err != nil { - return nil, err - } - - var errs *packersdk.MultiError - - // Defaults - - if c.PersonalAccessToken == "" { - // Default to environment variable for linode_token, if it exists - c.PersonalAccessToken = os.Getenv("LINODE_TOKEN") - } - - if c.ImageLabel == "" { - if def, err := interpolate.Render("packer-{{timestamp}}", nil); err == nil { - c.ImageLabel = def - } else { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("Unable to render image name: %s", err)) - } - } - - if c.Label == "" { - // Default to packer-[time-ordered-uuid] - if def, err := interpolate.Render("packer-{{timestamp}}", nil); err == nil { - c.Label = def - } else { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("Unable to render Linode label: %s", err)) - } - } - - if c.RootPass == "" { - var err error - c.RootPass, err = createRandomRootPassword() - if err != nil { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("Unable to generate root_pass: %s", err)) - } - } - - if c.StateTimeout == 0 { - // Default to 5 minute timeouts waiting for state change - c.StateTimeout = 5 * time.Minute - } - - if es := c.Comm.Prepare(&c.ctx); len(es) > 0 { - errs = packersdk.MultiErrorAppend(errs, es...) - } - - c.Comm.SSHPassword = c.RootPass - - if c.PersonalAccessToken == "" { - // Required configurations that will display errors if not set - errs = packersdk.MultiErrorAppend( - errs, errors.New("linode_token is required")) - } - - if c.Region == "" { - errs = packersdk.MultiErrorAppend( - errs, errors.New("region is required")) - } - - if c.InstanceType == "" { - errs = packersdk.MultiErrorAppend( - errs, errors.New("instance_type is required")) - } - - if c.Image == "" { - errs = packersdk.MultiErrorAppend( - errs, errors.New("image is required")) - } - - if c.Tags == nil { - c.Tags = make([]string, 0) - } - tagRe := regexp.MustCompile("^[[:alnum:]:_-]{1,255}$") - - for _, t := range c.Tags { - if !tagRe.MatchString(t) { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("invalid tag: %s", t)) - } - } - - if errs != nil && len(errs.Errors) > 0 { - return nil, errs - } - - packersdk.LogSecretFilter.Set(c.PersonalAccessToken) - return nil, nil -} diff --git a/builder/linode/config.hcl2spec.go b/builder/linode/config.hcl2spec.go deleted file mode 100644 index 747b5f514..000000000 --- a/builder/linode/config.hcl2spec.go +++ /dev/null @@ -1,167 +0,0 @@ -// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT. - -package linode - -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"` - PersonalAccessToken *string `mapstructure:"linode_token" cty:"linode_token" hcl:"linode_token"` - Region *string `mapstructure:"region" cty:"region" hcl:"region"` - InstanceType *string `mapstructure:"instance_type" cty:"instance_type" hcl:"instance_type"` - Label *string `mapstructure:"instance_label" cty:"instance_label" hcl:"instance_label"` - Tags []string `mapstructure:"instance_tags" cty:"instance_tags" hcl:"instance_tags"` - Image *string `mapstructure:"image" cty:"image" hcl:"image"` - SwapSize *int `mapstructure:"swap_size" cty:"swap_size" hcl:"swap_size"` - RootPass *string `mapstructure:"root_pass" cty:"root_pass" hcl:"root_pass"` - RootSSHKey *string `mapstructure:"root_ssh_key" cty:"root_ssh_key" hcl:"root_ssh_key"` - ImageLabel *string `mapstructure:"image_label" cty:"image_label" hcl:"image_label"` - Description *string `mapstructure:"image_description" cty:"image_description" hcl:"image_description"` - StateTimeout *string `mapstructure:"state_timeout" required:"false" cty:"state_timeout" hcl:"state_timeout"` -} - -// 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}, - "linode_token": &hcldec.AttrSpec{Name: "linode_token", Type: cty.String, Required: false}, - "region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false}, - "instance_type": &hcldec.AttrSpec{Name: "instance_type", Type: cty.String, Required: false}, - "instance_label": &hcldec.AttrSpec{Name: "instance_label", Type: cty.String, Required: false}, - "instance_tags": &hcldec.AttrSpec{Name: "instance_tags", Type: cty.List(cty.String), Required: false}, - "image": &hcldec.AttrSpec{Name: "image", Type: cty.String, Required: false}, - "swap_size": &hcldec.AttrSpec{Name: "swap_size", Type: cty.Number, Required: false}, - "root_pass": &hcldec.AttrSpec{Name: "root_pass", Type: cty.String, Required: false}, - "root_ssh_key": &hcldec.AttrSpec{Name: "root_ssh_key", Type: cty.String, Required: false}, - "image_label": &hcldec.AttrSpec{Name: "image_label", Type: cty.String, Required: false}, - "image_description": &hcldec.AttrSpec{Name: "image_description", Type: cty.String, Required: false}, - "state_timeout": &hcldec.AttrSpec{Name: "state_timeout", Type: cty.String, Required: false}, - } - return s -} diff --git a/builder/linode/linode.go b/builder/linode/linode.go deleted file mode 100644 index c274960a9..000000000 --- a/builder/linode/linode.go +++ /dev/null @@ -1,30 +0,0 @@ -package linode - -import ( - "fmt" - "net/http" - - "github.com/hashicorp/packer/builder/linode/version" - "github.com/linode/linodego" - "golang.org/x/oauth2" -) - -func newLinodeClient(pat string) linodego.Client { - tokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: pat}) - - oauthTransport := &oauth2.Transport{ - Source: tokenSource, - } - oauth2Client := &http.Client{ - Transport: oauthTransport, - } - - client := linodego.NewClient(oauth2Client) - - projectURL := "https://www.packer.io" - userAgent := fmt.Sprintf("Packer/%s (+%s) linodego/%s", - version.LinodePluginVersion.FormattedVersion(), projectURL, linodego.Version) - - client.SetUserAgent(userAgent) - return client -} diff --git a/builder/linode/step_create_image.go b/builder/linode/step_create_image.go deleted file mode 100644 index 5edf92ec6..000000000 --- a/builder/linode/step_create_image.go +++ /dev/null @@ -1,48 +0,0 @@ -package linode - -import ( - "context" - "errors" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/linode/linodego" -) - -type stepCreateImage struct { - client linodego.Client -} - -func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - c := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - disk := state.Get("disk").(*linodego.InstanceDisk) - instance := state.Get("instance").(*linodego.Instance) - - ui.Say("Creating image...") - image, err := s.client.CreateImage(ctx, linodego.ImageCreateOptions{ - DiskID: disk.ID, - Label: c.ImageLabel, - Description: c.Description, - }) - - if err == nil { - _, err = s.client.WaitForInstanceDiskStatus(ctx, instance.ID, disk.ID, linodego.DiskReady, 600) - } - - if err == nil { - image, err = s.client.GetImage(ctx, image.ID) - } - - if err != nil { - err = errors.New("Error creating image: " + err.Error()) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - state.Put("image", image) - return multistep.ActionContinue -} - -func (s *stepCreateImage) Cleanup(state multistep.StateBag) {} diff --git a/builder/linode/step_create_linode.go b/builder/linode/step_create_linode.go deleted file mode 100644 index 8089a28f9..000000000 --- a/builder/linode/step_create_linode.go +++ /dev/null @@ -1,97 +0,0 @@ -package linode - -import ( - "context" - "errors" - "time" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/linode/linodego" -) - -type stepCreateLinode struct { - client linodego.Client -} - -func (s *stepCreateLinode) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - c := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - - ui.Say("Creating Linode...") - - createOpts := linodego.InstanceCreateOptions{ - RootPass: c.Comm.Password(), - AuthorizedKeys: []string{string(c.Comm.SSHPublicKey)}, - Region: c.Region, - Type: c.InstanceType, - Label: c.Label, - Image: c.Image, - SwapSize: &c.SwapSize, - } - - instance, err := s.client.CreateInstance(ctx, createOpts) - if err != nil { - err = errors.New("Error creating Linode: " + err.Error()) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - state.Put("instance", instance) - - // wait until instance is running - for instance.Status != linodego.InstanceRunning { - time.Sleep(2 * time.Second) - if instance, err = s.client.GetInstance(ctx, instance.ID); err != nil { - err = errors.New("Error creating Linode: " + err.Error()) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - state.Put("instance", instance) - // 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", instance.ID) - } - - disk, err := s.findDisk(ctx, instance.ID) - if err != nil { - err = errors.New("Error creating Linode: " + err.Error()) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } else if disk == nil { - err := errors.New("Error creating Linode: no suitable disk was found") - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - state.Put("disk", disk) - return multistep.ActionContinue -} - -func (s *stepCreateLinode) findDisk(ctx context.Context, instanceID int) (*linodego.InstanceDisk, error) { - disks, err := s.client.ListInstanceDisks(ctx, instanceID, nil) - if err != nil { - return nil, err - } - for _, disk := range disks { - if disk.Filesystem != linodego.FilesystemSwap { - return &disk, nil - } - } - return nil, nil -} - -func (s *stepCreateLinode) Cleanup(state multistep.StateBag) { - instance, ok := state.GetOk("instance") - if !ok { - return - } - - ui := state.Get("ui").(packersdk.Ui) - - if err := s.client.DeleteInstance(context.Background(), instance.(*linodego.Instance).ID); err != nil { - ui.Error("Error cleaning up Linode: " + err.Error()) - } -} diff --git a/builder/linode/step_create_ssh_key.go b/builder/linode/step_create_ssh_key.go deleted file mode 100644 index 458421ab3..000000000 --- a/builder/linode/step_create_ssh_key.go +++ /dev/null @@ -1,95 +0,0 @@ -package linode - -import ( - "context" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "fmt" - "io/ioutil" - "os" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "golang.org/x/crypto/ssh" -) - -// StepCreateSSHKey represents a Packer build step that generates SSH key pairs. -type StepCreateSSHKey struct { - Debug bool - DebugKeyPath string -} - -// Run executes the Packer build step that generates SSH key pairs. -// The key pairs are added to the ssh config -func (s *StepCreateSSHKey) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packersdk.Ui) - config := state.Get("config").(*Config) - - if config.Comm.SSHPrivateKeyFile != "" { - ui.Say("Using existing SSH private key") - privateKeyBytes, err := ioutil.ReadFile(config.Comm.SSHPrivateKeyFile) - if err != nil { - state.Put("error", fmt.Errorf( - "Error loading configured private key file: %s", err)) - return multistep.ActionHalt - } - - config.Comm.SSHPrivateKey = privateKeyBytes - config.Comm.SSHPublicKey = nil - - return multistep.ActionContinue - } - - ui.Say("Creating temporary SSH key for instance...") - priv, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - err := fmt.Errorf("Error creating temporary ssh key: %s", err) - state.Put("error", err) - 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 - } - config.Comm.SSHPrivateKey = pem.EncodeToMemory(&priv_blk) - config.Comm.SSHPublicKey = ssh.MarshalAuthorizedKey(pub) - - // Linode has a serious issue with the newline that the ssh package appends to the end of the key. - if config.Comm.SSHPublicKey[len(config.Comm.SSHPublicKey)-1] == '\n' { - config.Comm.SSHPublicKey = config.Comm.SSHPublicKey[:len(config.Comm.SSHPublicKey)-1] - } - - 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 - } - - // Write out the key - err = pem.Encode(f, &priv_blk) - f.Close() - if err != nil { - state.Put("error", fmt.Errorf("Error saving debug key: %s", err)) - return multistep.ActionHalt - } - } - return multistep.ActionContinue -} - -// Nothing to clean up. SSH keys are associated with a single Linode instance. -func (s *StepCreateSSHKey) Cleanup(state multistep.StateBag) {} diff --git a/builder/linode/step_shutdown_linode.go b/builder/linode/step_shutdown_linode.go deleted file mode 100644 index 9e32aaf19..000000000 --- a/builder/linode/step_shutdown_linode.go +++ /dev/null @@ -1,40 +0,0 @@ -package linode - -import ( - "context" - "errors" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/linode/linodego" -) - -type stepShutdownLinode struct { - client linodego.Client -} - -func (s *stepShutdownLinode) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - c := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - instance := state.Get("instance").(*linodego.Instance) - - ui.Say("Shutting down Linode...") - if err := s.client.ShutdownInstance(ctx, instance.ID); err != nil { - err = errors.New("Error shutting down Linode: " + err.Error()) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - _, err := s.client.WaitForInstanceStatus(ctx, instance.ID, linodego.InstanceOffline, int(c.StateTimeout.Seconds())) - if err != nil { - err = errors.New("Error shutting down Linode: " + err.Error()) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - return multistep.ActionContinue -} - -func (s *stepShutdownLinode) Cleanup(state multistep.StateBag) {} diff --git a/builder/linode/version/version.go b/builder/linode/version/version.go deleted file mode 100644 index bb1195568..000000000 --- a/builder/linode/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 LinodePluginVersion *version.PluginVersion - -func init() { - LinodePluginVersion = version.InitializePluginVersion( - packerVersion.Version, packerVersion.VersionPrerelease) -} diff --git a/command/plugin.go b/command/plugin.go index ba502682e..d047a0216 100644 --- a/command/plugin.go +++ b/command/plugin.go @@ -19,8 +19,6 @@ import ( digitaloceanbuilder "github.com/hashicorp/packer/builder/digitalocean" filebuilder "github.com/hashicorp/packer/builder/file" hcloudbuilder "github.com/hashicorp/packer/builder/hcloud" - jdcloudbuilder "github.com/hashicorp/packer/builder/jdcloud" - linodebuilder "github.com/hashicorp/packer/builder/linode" lxcbuilder "github.com/hashicorp/packer/builder/lxc" lxdbuilder "github.com/hashicorp/packer/builder/lxd" nullbuilder "github.com/hashicorp/packer/builder/null" @@ -69,8 +67,6 @@ var Builders = map[string]packersdk.Builder{ "digitalocean": new(digitaloceanbuilder.Builder), "file": new(filebuilder.Builder), "hcloud": new(hcloudbuilder.Builder), - "jdcloud": new(jdcloudbuilder.Builder), - "linode": new(linodebuilder.Builder), "lxc": new(lxcbuilder.Builder), "lxd": new(lxdbuilder.Builder), "null": new(nullbuilder.Builder), diff --git a/command/vendored_plugins.go b/command/vendored_plugins.go index 2a873e45b..11b3ea96a 100644 --- a/command/vendored_plugins.go +++ b/command/vendored_plugins.go @@ -33,6 +33,8 @@ import ( hyperonebuilder "github.com/hashicorp/packer-plugin-hyperone/builder/hyperone" hypervisobuilder "github.com/hashicorp/packer-plugin-hyperv/builder/hyperv/iso" hypervvmcxbuilder "github.com/hashicorp/packer-plugin-hyperv/builder/hyperv/vmcx" + jdcloudbuilder "github.com/hashicorp/packer-plugin-jdcloud/builder/jdcloud" + linodebuilder "github.com/hashicorp/packer-plugin-linode/builder/linode" ncloudbuilder "github.com/hashicorp/packer-plugin-ncloud/builder/ncloud" openstackbuilder "github.com/hashicorp/packer-plugin-openstack/builder/openstack" oscbsubuilder "github.com/hashicorp/packer-plugin-outscale/builder/osc/bsu" @@ -80,6 +82,8 @@ var VendoredBuilders = map[string]packersdk.Builder{ "hyperv-iso": new(hypervisobuilder.Builder), "hyperv-vmcx": new(hypervvmcxbuilder.Builder), "hyperone": new(hyperonebuilder.Builder), + "jdcloud": new(jdcloudbuilder.Builder), + "linode": new(linodebuilder.Builder), "ncloud": new(ncloudbuilder.Builder), "openstack": new(openstackbuilder.Builder), "proxmox": new(proxmoxiso.Builder), diff --git a/go.mod b/go.mod index dbb9cad07..1ac0a633a 100644 --- a/go.mod +++ b/go.mod @@ -46,6 +46,8 @@ require ( github.com/hashicorp/packer-plugin-googlecompute v0.0.1 github.com/hashicorp/packer-plugin-hyperone v0.0.1 github.com/hashicorp/packer-plugin-hyperv v0.0.1 + github.com/hashicorp/packer-plugin-jdcloud v0.0.1 + github.com/hashicorp/packer-plugin-linode v0.0.2 github.com/hashicorp/packer-plugin-ncloud v0.0.2 github.com/hashicorp/packer-plugin-openstack v0.0.2 github.com/hashicorp/packer-plugin-outscale v0.0.1 @@ -59,10 +61,8 @@ require ( github.com/hashicorp/packer-plugin-vmware v0.0.1 github.com/hashicorp/packer-plugin-vsphere v0.0.1 github.com/hetznercloud/hcloud-go v1.15.1 - 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/klauspost/pgzip v0.0.0-20151221113845-47f36e165cec - github.com/linode/linodego v0.14.0 github.com/masterzen/winrm v0.0.0-20201030141608-56ca5c5f2380 github.com/mattn/go-tty v0.0.0-20191112051231-74040eebce08 github.com/mitchellh/cli v1.1.0 diff --git a/go.sum b/go.sum index 7e4c6f1dd..c89bedaa5 100644 --- a/go.sum +++ b/go.sum @@ -83,9 +83,12 @@ github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022/go.mod h1:nu github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6 h1:w0E0fgc1YafGEh5cROhlROMWXiNoZqApk2PDN0M1+Ns= github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.0/go.mod h1:P+3VS0ETiQPyWOx3vB/oeC8J3qd7jnVZLYAFwWgGRt8= github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.2.0 h1:c7GgSBfMt51UGM4SI1F7IFOokOVZO+uxNcJL3Xsmkp4= github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.2.0/go.mod h1:P+3VS0ETiQPyWOx3vB/oeC8J3qd7jnVZLYAFwWgGRt8= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/Telmate/proxmox-api-go v0.0.0-20200715182505-ec97c70ba887/go.mod h1:OGWyIMJ87/k/GCz8CGiWB2HOXsOVDM6Lpe/nFPkC4IQ= @@ -215,6 +218,7 @@ github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TR github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= @@ -222,12 +226,15 @@ github.com/dylanmei/iso8601 v0.1.0 h1:812NGQDBcqquTfH5Yeo7lwR0nzx/cKdsmf3qMjPURU github.com/dylanmei/iso8601 v0.1.0/go.mod h1:w9KhXSgIyROl1DefbMYIE7UVSIvELTbMrCfx+QkYnoQ= github.com/dylanmei/winrmtest v0.0.0-20170819153634-c2fbb09e6c08 h1:0bp6/GrNOrTDtSXe9YYGCwf8jp5Fb/b+4a6MTRm4qzY= github.com/dylanmei/winrmtest v0.0.0-20170819153634-c2fbb09e6c08/go.mod h1:VBVDFSBXCIW8JaHQpI8lldSKfYaLMzP9oyq6IJ4fhzY= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= github.com/exoscale/egoscale v0.43.1 h1:Lhr0UOfg3t3Y56yh1DsYCjQuUHqFvsC8iUVqvub8+0Q= github.com/exoscale/egoscale v0.43.1/go.mod h1:mpEXBpROAa/2i5GC0r33rfxG+TxSEka11g1PIXt9+zc= @@ -241,8 +248,10 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fatih/structtag v1.0.0/go.mod h1:IKitwq45uXL/yqi5mYghiD3w9H6eTOvI9vnk8tXMphA= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/getkin/kin-openapi v0.13.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw= github.com/getkin/kin-openapi v0.37.0/go.mod h1:ZJSfy1PxJv2QQvH9EdBj3nupRTVvV42mkW6zKUlRBwk= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi v1.5.1/go.mod h1:REp24E+25iKvxgeTfHmdUoL5x15kBiDBlnIl5bCwe2k= @@ -253,10 +262,15 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2 github.com/go-ini/ini v1.25.4 h1:Mujh4R/dH6YL8bxuISne3xX2+qcQ9p0IxKAP6ExWoUo= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= github.com/go-resty/resty/v2 v2.3.0 h1:JOOeAvjSlapTT92p8xiS19Zxev1neGikoHsXJeOq8So= @@ -273,10 +287,13 @@ github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4= github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= @@ -289,6 +306,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -331,6 +349,8 @@ github.com/google/go-github/v33 v33.0.1-0.20210113204525-9318e629ec69/go.mod h1: github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -359,6 +379,10 @@ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI= +github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.6.1-0.20191122030953-d8ac278c1c9d/go.mod h1:ozGNgr9KYOVATV5jsgHl/ceCDXGuguqOZAzoQ/2vcNM= github.com/gophercloud/gophercloud v0.12.0 h1:mZrie07npp6ODiwHZolTicr5jV8Ogn43AvAsSMm6Ork= github.com/gophercloud/gophercloud v0.12.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss= @@ -367,6 +391,7 @@ github.com/gophercloud/utils v0.0.0-20200508015959-b0167b94122c/go.mod h1:ehWUbL github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg= github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE= github.com/hako/durafmt v0.0.0-20200710122514-c0fb7b4da026 h1:BpJ2o0OR5FV7vrkDYfXYVJQeMNWa8RhklZOpW2ITAIQ= @@ -482,6 +507,10 @@ github.com/hashicorp/packer-plugin-hyperone v0.0.1 h1:Owp1B5cI0VgFgR3pCyeeQdyKPT github.com/hashicorp/packer-plugin-hyperone v0.0.1/go.mod h1:9DglrxEBIig85Hr8r11YE+uMn3G0u+pt0AZHVP+wnAY= github.com/hashicorp/packer-plugin-hyperv v0.0.1 h1:ZdsJw4X+4zSgRYPzVQbJrx8Az73AkneSWLnmfpojl0k= github.com/hashicorp/packer-plugin-hyperv v0.0.1/go.mod h1:sB9mEZCfaXVjTD6pS+Tt0xMtUD1Ocnl5mZ3i/PG6eB0= +github.com/hashicorp/packer-plugin-jdcloud v0.0.1 h1:MLvAroDOHWimBf6cBa0trlHJpB8nKtO9FPyg2l6Iafw= +github.com/hashicorp/packer-plugin-jdcloud v0.0.1/go.mod h1:bVGtjp3v98rpguEYxJAXQbg8CjllInh5WFqO9a0T4lc= +github.com/hashicorp/packer-plugin-linode v0.0.2 h1:obN0kQKlfCQuFmRwVx6ksQApQZ85gPAcSCtjDd0F30c= +github.com/hashicorp/packer-plugin-linode v0.0.2/go.mod h1:uF8FAE3+PG/lVI1TwjXSaS3AHv4+Wb3/3gsrg0h6IQ0= 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-openstack v0.0.2 h1:wGNE8es3Bn9auuIoX+gqT9chXzYY9GlM55eSpM4uwtU= @@ -532,10 +561,13 @@ github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1 github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hetznercloud/hcloud-go v1.15.1 h1:G8Q+xyAqQ5IUY7yq4HKZgkabFa0S/VXJXq3TGCeT8JM= github.com/hetznercloud/hcloud-go v1.15.1/go.mod h1:8lR3yHBHZWy2uGcUi9Ibt4UOoop2wrVdERJgCtxsF3Q= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hyperonecom/h1-client-go v0.0.0-20191203060043-b46280e4c4a4 h1:mSmyzhwBeQt2TlHbsXYLona9pwjWAvYGwQJ2Cq/k3VE= github.com/hyperonecom/h1-client-go v0.0.0-20191203060043-b46280e4c4a4/go.mod h1:yNUVHSleURKSaYUKq4Wx0i/vjCen2aq7CvPyHd/Vj2Q= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/jarcoal/httpmock v1.0.6/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jarcoal/httpmock v1.0.8 h1:8kI16SoO6LQKgPE7PvQuV+YuD/inwHd7fOOe2zMbo4k= github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= @@ -554,6 +586,7 @@ github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62 h1:JHCT6xuyPUrbbg github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -563,6 +596,7 @@ github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVY github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v0.0.0-20160131094358-f86d2e6d8a77/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= @@ -592,8 +626,10 @@ github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LE github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/labstack/echo/v4 v4.1.17/go.mod h1:Tn2yRQL/UclUalpb5rPdXDevbkJ+lp/2svdyFBg6CHQ= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/linode/linodego v0.14.0 h1:0APKMjiVGyry2TTUVDiok72H6cWpFNMMrFWBFn14aFU= github.com/linode/linodego v0.14.0/go.mod h1:2ce3S00NrDqJfp4i55ZuSlT0U3cKNELNYACWBPI8Tnw= +github.com/linode/linodego v1.0.0 h1:Kq/8oPPk3ui/aVlzEObll5oBewHyzo/eJPnVPYuONVE= +github.com/linode/linodego v1.0.0/go.mod h1:XOWXRHjqeU2uPS84tKLgfWIfTlv3TYzCS0io4GOQzEI= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc= @@ -668,12 +704,19 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/olekukonko/tablewriter v0.0.0-20180105111133-96aac992fc8b/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/oracle/oci-go-sdk v18.0.0+incompatible h1:FLV4KixsVfF3rwyVTMI6Ryp/Q+OSb9sR5TawbfjFLN4= github.com/oracle/oci-go-sdk v18.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= @@ -687,6 +730,7 @@ github.com/packer-community/winrmcp v0.0.0-20180921204643-0fd363d6159a/go.mod h1 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -736,7 +780,10 @@ github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:X github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -811,6 +858,7 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -822,6 +870,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191112222119-e1110fd1c708/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -870,9 +919,11 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -886,6 +937,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -937,11 +989,14 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -960,6 +1015,7 @@ golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1000,6 +1056,7 @@ golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1016,6 +1073,8 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqG golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1197,6 +1256,9 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/cheggaaa/pb.v1 v1.0.27 h1:kJdccidYzt3CaHD1crCFTS1hxyhSi059NhOFUf03YFo= gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1204,6 +1266,7 @@ gopkg.in/jarcoal/httpmock.v1 v1.0.0-20181117152235-275e9df93516 h1:H6trpavCIuipd gopkg.in/jarcoal/httpmock.v1 v1.0.0-20181117152235-275e9df93516/go.mod h1:d3R+NllX3X5e0zlG1Rful3uLvsGC/Q3OHut5464DEQw= gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1222,6 +1285,26 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.18.3 h1:2AJaUQdgUZLoDZHrun21PW2Nx9+ll6cUzvn3IKhSIn0= +k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA= +k8s.io/apimachinery v0.18.3 h1:pOGcbVAhxADgUYnjS08EFXs9QMl8qaH5U4fr5LGUrSk= +k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko= +k8s.io/client-go v0.18.3 h1:QaJzz92tsN67oorwzmoB0a9r9ZVHuD5ryjbCKP0U22k= +k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= +k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= +k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU= +k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= +sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/website/content/docs/builders/jdcloud.mdx b/website/content/docs/builders/jdcloud.mdx deleted file mode 100644 index 7a9eb5bb1..000000000 --- a/website/content/docs/builders/jdcloud.mdx +++ /dev/null @@ -1,88 +0,0 @@ ---- -description: | - The `jdcloud` Packer builder helps you to build instance images - based on an existing image -page_title: JDCloud Image Builder ---- - -# JDCloud Image Builder - -Type: `jdcloud` -Artifact BuilderId: `hashicorp.jdcloud` - -The `jdcloud` Packer builder helps you to build instance images -based on an existing image - -## Configuration Reference - -In order to build a JDCloud instance image, full-fill your configuration file. Necessary attributes -are given below: - -### Required-Parameters: - -- `type` (string) - This parameter tells which cloud-service-provider you are using, in our case, use 'jdcloud' -- `image_id` (string) - New image is generated based on an old one, specify the base-image-id here. -- `access_key` (string) - Your JD Cloud access key. You may set this as an env-variable:`export JDCLOUD_ACCESS_KEY=xxx` -- `secret_key` (string) - Your JD Cloud secret key. You may also set this via env-variable:`export JDCLOUD_SECRET_KEY=xxx` -- `region_id` (string) - Region of your instance, candidates are {"cn-north-1","cn-south-1","cn-east-1","cn-east-2"} -- `az` (string) - Exact availability zone of instance, 'cn-north-1c' for example -- `instance_name` (string) - Name your instance -- `instance_type` (string) - Class of your expected instance -- `image_name` (string) - Name the image you would like to create -- `communicator` (string) - Currently only `ssh` is supported. `winrm` will be added if required - -### Optional-Parameters - -- `subnet_id` (string) - An instance is supposed to exists in an subnet, if not specified , we will create new one for you - -In addition to the above configuration options, a communicator can be configured for this builder: - -### Communicator Configuration - -#### Optional: - -@include 'packer-plugin-sdk/communicator/Config-not-required.mdx' - -@include 'packer-plugin-sdk/communicator/SSH-not-required.mdx' - -@include 'packer-plugin-sdk/communicator/SSHTemporaryKeyPair-not-required.mdx' - -@include 'packer-plugin-sdk/communicator/SSH-Key-Pair-Name-not-required.mdx' - -@include 'packer-plugin-sdk/communicator/SSH-Private-Key-File-not-required.mdx' - -## Examples - -Here is a basic example for JDCloud. - -```json -{ - "builders": [ - { - "type": "jdcloud", - "image_id": "img-h8ly274zg9", - "access_key": "", - "secret_key": "", - "region_id": "cn-north-1", - "az": "cn-north-1c", - "instance_name": "created_by_packer", - "instance_type": "g.n2.medium", - "ssh_password": "/Users/mac/.ssh/id_rsa", - "ssh_keypair_name": "created_by_xiaohan", - "image_name": "packerImage", - "subnet_id": "subnet-jo6e38sdli", - "communicator": "ssh", - "ssh_username": "root" - } - ], - - "provisioners": [ - { - "type": "shell", - "inline": ["sleep 3", "echo 123", "pwd"] - } - ] -} -``` - -[Find more examples](https://github.com/hashicorp/packer/tree/master/builder/jdcloud/examples) diff --git a/website/content/docs/builders/linode.mdx b/website/content/docs/builders/linode.mdx deleted file mode 100644 index 861b44443..000000000 --- a/website/content/docs/builders/linode.mdx +++ /dev/null @@ -1,110 +0,0 @@ ---- -description: > - The linode Packer builder is able to create new images for use with Linode. - The - - builder takes a source image, runs any provisioning necessary on the image - - after launching it, then snapshots it into a reusable image. This reusable - - image can then be used as the foundation of new servers that are launched - - within all Linode regions. -page_title: Linode - Builders ---- - -# Linode Builder - -Type: `linode` -Artifact BuilderId: `packer.linode` - -The `linode` Packer builder is able to create [Linode -Images](https://www.linode.com/docs/platform/disk-images/linode-images/) for -use with [Linode](https://www.linode.com). The builder takes a source image, -runs any provisioning necessary on the image after launching it, then snapshots -it into a reusable image. This reusable image can then be used as the -foundation of new servers that are launched within Linode. - -The builder does _not_ manage images. Once it creates an image, it is up to you -to use it or delete it. - -## 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 - -- `linode_token` (string) - The client TOKEN to use to access your account. - -- `image` (string) - An Image ID to deploy the Disk from. Official Linode - Images start with `linode/`, while user Images start with `private/`. See - [images](https://api.linode.com/v4/images) for more information on the - Images available for use. Examples are `linode/debian9`, `linode/fedora28`, - `linode/ubuntu18.04`, `linode/arch`, and `private/12345`. - -- `region` (string) - The id of the region to launch the Linode instance in. - Images are available in all regions, but there will be less delay when - deploying from the region where the image was taken. Examples are - `us-east`, `us-central`, `us-west`, `ap-south`, `ca-east`, `ap-northeast`, - `eu-central`, and `eu-west`. - -- `instance_type` (string) - The Linode type defines the pricing, CPU, disk, - and RAM specs of the instance. Examples are `g6-nanode-1`, `g6-standard-2`, - `g6-highmem-16`, and `g6-dedicated-16`. - -### Optional - -- `instance_label` (string) - The name assigned to the Linode Instance. - -- `instance_tags` (list) - Tags to apply to the instance when it is created. - -- `swap_size` (int) - The disk size (MiB) allocated for swap space. - -- `image_label` (string) - The name of the resulting image that will appear - in your account. Defaults to `packer-{{timestamp}}` (see [configuration - templates](/docs/templates/legacy_json_templates/engine) for more info). - -- `image_description` (string) - The description of the resulting image that - will appear in your account. Defaults to "". - -- `state_timeout` (string) - The time to wait, as a duration string, for the - Linode instance to enter a desired state (such as "running") before timing - out. The default state timeout is "5m". - -## Basic Example - -Here is a Linode builder example. The `linode_token` should be replaced with an -actual [Linode Personal Access -Token](https://www.linode.com/docs/platform/api/getting-started-with-the-linode-api/#get-an-access-token). - -```json -{ - "type": "linode", - "linode_token": "YOUR API TOKEN", - "image": "linode/debian9", - "region": "us-east", - "instance_type": "g6-nanode-1", - "instance_label": "temporary-linode-{{timestamp}}", - - "image_label": "private-image-{{timestamp}}", - "image_description": "My Private Image", - - "ssh_username": "root" -} -``` diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index b84549af3..f89d9cc90 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -708,10 +708,6 @@ "title": "Hetzner Cloud", "path": "builders/hetzner-cloud" }, - { - "title": "Linode", - "path": "builders/linode" - }, { "title": "LXC", "path": "builders/lxc" @@ -753,10 +749,6 @@ "title": "Tencent Cloud", "path": "builders/tencentcloud-cvm" }, - { - "title": "JDCloud", - "path": "builders/jdcloud" - }, { "title": "Triton", "path": "builders/triton" diff --git a/website/data/docs-remote-plugins.json b/website/data/docs-remote-plugins.json index d42194d15..a6e7cfa7e 100644 --- a/website/data/docs-remote-plugins.json +++ b/website/data/docs-remote-plugins.json @@ -59,6 +59,20 @@ "version": "latest", "pluginTier": "community" }, + { + "title": "JD Cloud", + "path": "jdcloud", + "repo": "hashicorp/packer-plugin-jdcloud", + "pluginTier": "community", + "version": "latest" + }, + { + "title": "Linode", + "path": "linode", + "repo": "hashicorp/packer-plugin-linode", + "pluginTier": "community", + "version": "latest" + }, { "title": "Naver Cloud", "path": "ncloud",