Extract jdcloud (#10946)
* delete jdcloud builder dir, revendor, regenerate, add to vendored_plugins * change website pathing * Extract linode (#10947) * started extracting linode * revendor linode * clean up vendoring
This commit is contained in:
parent
469f033c36
commit
b5666b84cd
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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)
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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...")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
{
|
|
||||||
"builders": [
|
|
||||||
{
|
|
||||||
"type": "jdcloud",
|
|
||||||
"image_id": "<your-base-image-id>",
|
|
||||||
"access_key": "<your-access-key>",
|
|
||||||
"secret_key": "<your-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": "<your-subnet>",
|
|
||||||
"communicator":"ssh",
|
|
||||||
"ssh_username": "root",
|
|
||||||
"ssh_timeout" : "60s"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
"provisioners": [
|
|
||||||
{
|
|
||||||
"type": "shell",
|
|
||||||
"inline": [
|
|
||||||
"sleep 3",
|
|
||||||
"echo 123",
|
|
||||||
"pwd"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
{
|
|
||||||
"builders": [
|
|
||||||
{
|
|
||||||
"type": "jdcloud",
|
|
||||||
"image_id": "<your-image-id>",
|
|
||||||
"access_key": "<your-access-key>",
|
|
||||||
"secret_key": "<your-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": "<your-subnet>",
|
|
||||||
"communicator":"ssh",
|
|
||||||
"ssh_username": "root",
|
|
||||||
"ssh_timeout" : "60s"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
"provisioners": [
|
|
||||||
{
|
|
||||||
"type": "shell",
|
|
||||||
"inline": [
|
|
||||||
"sleep 3",
|
|
||||||
"echo 123",
|
|
||||||
"pwd"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
{
|
|
||||||
"builders": [
|
|
||||||
{
|
|
||||||
"type": "jdcloud",
|
|
||||||
"image_id": "img-h8ly274zg9",
|
|
||||||
"access_key": "<Your access_key>",
|
|
||||||
"secret_key": "<Your 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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
{
|
|
||||||
"builders": [
|
|
||||||
{
|
|
||||||
"type": "jdcloud",
|
|
||||||
"image_id": "img-h8ly274zg9",
|
|
||||||
"access_key": "<Your access_key>",
|
|
||||||
"secret_key": "<Your 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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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 ")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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) {
|
|
||||||
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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) {}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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"
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
`
|
|
|
@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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) {}
|
|
|
@ -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())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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) {}
|
|
|
@ -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) {}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -19,8 +19,6 @@ import (
|
||||||
digitaloceanbuilder "github.com/hashicorp/packer/builder/digitalocean"
|
digitaloceanbuilder "github.com/hashicorp/packer/builder/digitalocean"
|
||||||
filebuilder "github.com/hashicorp/packer/builder/file"
|
filebuilder "github.com/hashicorp/packer/builder/file"
|
||||||
hcloudbuilder "github.com/hashicorp/packer/builder/hcloud"
|
hcloudbuilder "github.com/hashicorp/packer/builder/hcloud"
|
||||||
jdcloudbuilder "github.com/hashicorp/packer/builder/jdcloud"
|
|
||||||
linodebuilder "github.com/hashicorp/packer/builder/linode"
|
|
||||||
lxcbuilder "github.com/hashicorp/packer/builder/lxc"
|
lxcbuilder "github.com/hashicorp/packer/builder/lxc"
|
||||||
lxdbuilder "github.com/hashicorp/packer/builder/lxd"
|
lxdbuilder "github.com/hashicorp/packer/builder/lxd"
|
||||||
nullbuilder "github.com/hashicorp/packer/builder/null"
|
nullbuilder "github.com/hashicorp/packer/builder/null"
|
||||||
|
@ -69,8 +67,6 @@ var Builders = map[string]packersdk.Builder{
|
||||||
"digitalocean": new(digitaloceanbuilder.Builder),
|
"digitalocean": new(digitaloceanbuilder.Builder),
|
||||||
"file": new(filebuilder.Builder),
|
"file": new(filebuilder.Builder),
|
||||||
"hcloud": new(hcloudbuilder.Builder),
|
"hcloud": new(hcloudbuilder.Builder),
|
||||||
"jdcloud": new(jdcloudbuilder.Builder),
|
|
||||||
"linode": new(linodebuilder.Builder),
|
|
||||||
"lxc": new(lxcbuilder.Builder),
|
"lxc": new(lxcbuilder.Builder),
|
||||||
"lxd": new(lxdbuilder.Builder),
|
"lxd": new(lxdbuilder.Builder),
|
||||||
"null": new(nullbuilder.Builder),
|
"null": new(nullbuilder.Builder),
|
||||||
|
|
|
@ -33,6 +33,8 @@ import (
|
||||||
hyperonebuilder "github.com/hashicorp/packer-plugin-hyperone/builder/hyperone"
|
hyperonebuilder "github.com/hashicorp/packer-plugin-hyperone/builder/hyperone"
|
||||||
hypervisobuilder "github.com/hashicorp/packer-plugin-hyperv/builder/hyperv/iso"
|
hypervisobuilder "github.com/hashicorp/packer-plugin-hyperv/builder/hyperv/iso"
|
||||||
hypervvmcxbuilder "github.com/hashicorp/packer-plugin-hyperv/builder/hyperv/vmcx"
|
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"
|
ncloudbuilder "github.com/hashicorp/packer-plugin-ncloud/builder/ncloud"
|
||||||
openstackbuilder "github.com/hashicorp/packer-plugin-openstack/builder/openstack"
|
openstackbuilder "github.com/hashicorp/packer-plugin-openstack/builder/openstack"
|
||||||
oscbsubuilder "github.com/hashicorp/packer-plugin-outscale/builder/osc/bsu"
|
oscbsubuilder "github.com/hashicorp/packer-plugin-outscale/builder/osc/bsu"
|
||||||
|
@ -80,6 +82,8 @@ var VendoredBuilders = map[string]packersdk.Builder{
|
||||||
"hyperv-iso": new(hypervisobuilder.Builder),
|
"hyperv-iso": new(hypervisobuilder.Builder),
|
||||||
"hyperv-vmcx": new(hypervvmcxbuilder.Builder),
|
"hyperv-vmcx": new(hypervvmcxbuilder.Builder),
|
||||||
"hyperone": new(hyperonebuilder.Builder),
|
"hyperone": new(hyperonebuilder.Builder),
|
||||||
|
"jdcloud": new(jdcloudbuilder.Builder),
|
||||||
|
"linode": new(linodebuilder.Builder),
|
||||||
"ncloud": new(ncloudbuilder.Builder),
|
"ncloud": new(ncloudbuilder.Builder),
|
||||||
"openstack": new(openstackbuilder.Builder),
|
"openstack": new(openstackbuilder.Builder),
|
||||||
"proxmox": new(proxmoxiso.Builder),
|
"proxmox": new(proxmoxiso.Builder),
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -46,6 +46,8 @@ require (
|
||||||
github.com/hashicorp/packer-plugin-googlecompute v0.0.1
|
github.com/hashicorp/packer-plugin-googlecompute v0.0.1
|
||||||
github.com/hashicorp/packer-plugin-hyperone v0.0.1
|
github.com/hashicorp/packer-plugin-hyperone v0.0.1
|
||||||
github.com/hashicorp/packer-plugin-hyperv 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-ncloud v0.0.2
|
||||||
github.com/hashicorp/packer-plugin-openstack v0.0.2
|
github.com/hashicorp/packer-plugin-openstack v0.0.2
|
||||||
github.com/hashicorp/packer-plugin-outscale v0.0.1
|
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-vmware v0.0.1
|
||||||
github.com/hashicorp/packer-plugin-vsphere v0.0.1
|
github.com/hashicorp/packer-plugin-vsphere v0.0.1
|
||||||
github.com/hetznercloud/hcloud-go v1.15.1
|
github.com/hetznercloud/hcloud-go v1.15.1
|
||||||
github.com/jdcloud-api/jdcloud-sdk-go v1.9.1-0.20190605102154-3d81a50ca961
|
|
||||||
github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62
|
github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62
|
||||||
github.com/klauspost/pgzip v0.0.0-20151221113845-47f36e165cec
|
github.com/klauspost/pgzip v0.0.0-20151221113845-47f36e165cec
|
||||||
github.com/linode/linodego v0.14.0
|
|
||||||
github.com/masterzen/winrm v0.0.0-20201030141608-56ca5c5f2380
|
github.com/masterzen/winrm v0.0.0-20201030141608-56ca5c5f2380
|
||||||
github.com/mattn/go-tty v0.0.0-20191112051231-74040eebce08
|
github.com/mattn/go-tty v0.0.0-20191112051231-74040eebce08
|
||||||
github.com/mitchellh/cli v1.1.0
|
github.com/mitchellh/cli v1.1.0
|
||||||
|
|
85
go.sum
85
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 h1:w0E0fgc1YafGEh5cROhlROMWXiNoZqApk2PDN0M1+Ns=
|
||||||
github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4=
|
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/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.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 h1:c7GgSBfMt51UGM4SI1F7IFOokOVZO+uxNcJL3Xsmkp4=
|
||||||
github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.2.0/go.mod h1:P+3VS0ETiQPyWOx3vB/oeC8J3qd7jnVZLYAFwWgGRt8=
|
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 h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
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=
|
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/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 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY=
|
||||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
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 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
|
||||||
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
|
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=
|
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/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 h1:0bp6/GrNOrTDtSXe9YYGCwf8jp5Fb/b+4a6MTRm4qzY=
|
||||||
github.com/dylanmei/winrmtest v0.0.0-20170819153634-c2fbb09e6c08/go.mod h1:VBVDFSBXCIW8JaHQpI8lldSKfYaLMzP9oyq6IJ4fhzY=
|
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.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.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.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.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
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/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.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE=
|
||||||
github.com/exoscale/egoscale v0.43.1 h1:Lhr0UOfg3t3Y56yh1DsYCjQuUHqFvsC8iUVqvub8+0Q=
|
github.com/exoscale/egoscale v0.43.1 h1:Lhr0UOfg3t3Y56yh1DsYCjQuUHqFvsC8iUVqvub8+0Q=
|
||||||
github.com/exoscale/egoscale v0.43.1/go.mod h1:mpEXBpROAa/2i5GC0r33rfxG+TxSEka11g1PIXt9+zc=
|
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/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.0.0/go.mod h1:IKitwq45uXL/yqi5mYghiD3w9H6eTOvI9vnk8tXMphA=
|
||||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
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.13.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw=
|
||||||
github.com/getkin/kin-openapi v0.37.0/go.mod h1:ZJSfy1PxJv2QQvH9EdBj3nupRTVvV42mkW6zKUlRBwk=
|
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 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-chi/chi v1.5.1/go.mod h1:REp24E+25iKvxgeTfHmdUoL5x15kBiDBlnIl5bCwe2k=
|
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 h1:Mujh4R/dH6YL8bxuISne3xX2+qcQ9p0IxKAP6ExWoUo=
|
||||||
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
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-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.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 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
|
||||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
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/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-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.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
|
||||||
github.com/go-resty/resty/v2 v2.3.0 h1:JOOeAvjSlapTT92p8xiS19Zxev1neGikoHsXJeOq8So=
|
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 h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
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.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/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 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=
|
||||||
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU=
|
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/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-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-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
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.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.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
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.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.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/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 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
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.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 h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
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=
|
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.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 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
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.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 h1:mZrie07npp6ODiwHZolTicr5jV8Ogn43AvAsSMm6Ork=
|
||||||
github.com/gophercloud/gophercloud v0.12.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss=
|
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-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 h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
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 h1:THDBEeQ9xZ8JEaCLyLQqXMMdRqNr0QAUJTIkQAUtFjg=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.1.0/go.mod h1:f5nM7jw/oeRSadq3xCzHAvxcr8HZnzsqU6ILg/0NiiE=
|
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=
|
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-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 h1:ZdsJw4X+4zSgRYPzVQbJrx8Az73AkneSWLnmfpojl0k=
|
||||||
github.com/hashicorp/packer-plugin-hyperv v0.0.1/go.mod h1:sB9mEZCfaXVjTD6pS+Tt0xMtUD1Ocnl5mZ3i/PG6eB0=
|
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 h1:MGvGkOVfzeosqOSs5dteghLwv9VRcRxTuLoLX1ssUag=
|
||||||
github.com/hashicorp/packer-plugin-ncloud v0.0.2/go.mod h1:Hud2R1pkky96TQy3TPTTrr9Kej4b/4dqC/v+uEE0VDY=
|
github.com/hashicorp/packer-plugin-ncloud v0.0.2/go.mod h1:Hud2R1pkky96TQy3TPTTrr9Kej4b/4dqC/v+uEE0VDY=
|
||||||
github.com/hashicorp/packer-plugin-openstack v0.0.2 h1:wGNE8es3Bn9auuIoX+gqT9chXzYY9GlM55eSpM4uwtU=
|
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/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 h1:G8Q+xyAqQ5IUY7yq4HKZgkabFa0S/VXJXq3TGCeT8JM=
|
||||||
github.com/hetznercloud/hcloud-go v1.15.1/go.mod h1:8lR3yHBHZWy2uGcUi9Ibt4UOoop2wrVdERJgCtxsF3Q=
|
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 h1:mSmyzhwBeQt2TlHbsXYLona9pwjWAvYGwQJ2Cq/k3VE=
|
||||||
github.com/hyperonecom/h1-client-go v0.0.0-20191203060043-b46280e4c4a4/go.mod h1:yNUVHSleURKSaYUKq4Wx0i/vjCen2aq7CvPyHd/Vj2Q=
|
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-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/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.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 h1:8kI16SoO6LQKgPE7PvQuV+YuD/inwHd7fOOe2zMbo4k=
|
||||||
github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
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/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.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.6/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 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
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=
|
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 h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
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.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/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 v0.0.0-20160131094358-f86d2e6d8a77/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
github.com/klauspost/compress v1.4.1/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.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
|
||||||
github.com/labstack/echo/v4 v4.1.17/go.mod h1:Tn2yRQL/UclUalpb5rPdXDevbkJ+lp/2svdyFBg6CHQ=
|
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/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 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-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/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=
|
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 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 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
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 h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
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/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.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 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
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/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 h1:FLV4KixsVfF3rwyVTMI6Ryp/Q+OSb9sR5TawbfjFLN4=
|
||||||
github.com/oracle/oci-go-sdk v18.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
|
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.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
|
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
|
||||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
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 h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
|
||||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
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=
|
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 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 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
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.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/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.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/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=
|
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-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-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-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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
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-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-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-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-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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/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.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=
|
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/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-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-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-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-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-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/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-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-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-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-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-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=
|
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-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 h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
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-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-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-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-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-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-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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
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-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-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-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-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-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/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-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 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
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.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.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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/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-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-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-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-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
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 h1:kJdccidYzt3CaHD1crCFTS1hxyhSi059NhOFUf03YFo=
|
||||||
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
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/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.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
|
||||||
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
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/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 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
|
||||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
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.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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/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-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.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.4/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/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/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
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=
|
||||||
|
|
|
@ -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": "<your access key>",
|
|
||||||
"secret_key": "<your 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)
|
|
|
@ -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'
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Linode.com has DDOS protection that returns 403 for the markdown link checker
|
|
||||||
so the domain has been added to the ignorepatterns in mlc_config.json
|
|
||||||
|
|
||||||
See https://github.com/tcort/markdown-link-check/issues/109
|
|
||||||
-->
|
|
||||||
|
|
||||||
### 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"
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -708,10 +708,6 @@
|
||||||
"title": "Hetzner Cloud",
|
"title": "Hetzner Cloud",
|
||||||
"path": "builders/hetzner-cloud"
|
"path": "builders/hetzner-cloud"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"title": "Linode",
|
|
||||||
"path": "builders/linode"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"title": "LXC",
|
"title": "LXC",
|
||||||
"path": "builders/lxc"
|
"path": "builders/lxc"
|
||||||
|
@ -753,10 +749,6 @@
|
||||||
"title": "Tencent Cloud",
|
"title": "Tencent Cloud",
|
||||||
"path": "builders/tencentcloud-cvm"
|
"path": "builders/tencentcloud-cvm"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"title": "JDCloud",
|
|
||||||
"path": "builders/jdcloud"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"title": "Triton",
|
"title": "Triton",
|
||||||
"path": "builders/triton"
|
"path": "builders/triton"
|
||||||
|
|
|
@ -59,6 +59,20 @@
|
||||||
"version": "latest",
|
"version": "latest",
|
||||||
"pluginTier": "community"
|
"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",
|
"title": "Naver Cloud",
|
||||||
"path": "ncloud",
|
"path": "ncloud",
|
||||||
|
|
Loading…
Reference in New Issue