yandex-import: allow set custom API endpoint (#9850)
* Separate Access Config from yandex builder Config * make use of Access Config explicit * Move `MaxRetries` into AccessConfig * NewDriverYC use AccessConfig instead Config * yandex-import PP use common Access Config Now support set custom API Endpoint * yandex-export PP use common Access Config Now support set custom API Endpoint too (as yandex-import) * fix test * Tiny doc updates.
This commit is contained in:
parent
f578b93f7e
commit
804fefef17
|
@ -0,0 +1,67 @@
|
||||||
|
//go:generate struct-markdown
|
||||||
|
|
||||||
|
package yandex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/hashicorp/packer/packer"
|
||||||
|
"github.com/hashicorp/packer/template/interpolate"
|
||||||
|
"github.com/yandex-cloud/go-sdk/iamkey"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultEndpoint = "api.cloud.yandex.net:443"
|
||||||
|
|
||||||
|
// AccessConfig is for common configuration related to Yandex.Cloud API access
|
||||||
|
type AccessConfig struct {
|
||||||
|
// Non standard API endpoint. Default is `api.cloud.yandex.net:443`.
|
||||||
|
Endpoint string `mapstructure:"endpoint" required:"false"`
|
||||||
|
// Path to file with Service Account key in json format. This
|
||||||
|
// is an alternative method to authenticate to Yandex.Cloud. Alternatively you may set environment variable
|
||||||
|
// `YC_SERVICE_ACCOUNT_KEY_FILE`.
|
||||||
|
ServiceAccountKeyFile string `mapstructure:"service_account_key_file" required:"false"`
|
||||||
|
// OAuth token to use to authenticate to Yandex.Cloud. Alternatively you may set
|
||||||
|
// value by environment variable `YC_TOKEN`.
|
||||||
|
Token string `mapstructure:"token" required:"true"`
|
||||||
|
// The maximum number of times an API request is being executed.
|
||||||
|
MaxRetries int `mapstructure:"max_retries"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
|
||||||
|
var errs []error
|
||||||
|
|
||||||
|
if c.Endpoint == "" {
|
||||||
|
c.Endpoint = defaultEndpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
// provision config by OS environment variables
|
||||||
|
if c.Token == "" {
|
||||||
|
c.Token = os.Getenv("YC_TOKEN")
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.ServiceAccountKeyFile == "" {
|
||||||
|
c.ServiceAccountKeyFile = os.Getenv("YC_SERVICE_ACCOUNT_KEY_FILE")
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Token != "" && c.ServiceAccountKeyFile != "" {
|
||||||
|
errs = append(errs, errors.New("one of token or service account key file must be specified, not both"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Token != "" {
|
||||||
|
packer.LogSecretFilter.Set(c.Token)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.ServiceAccountKeyFile != "" {
|
||||||
|
if _, err := iamkey.ReadFromJSONFile(c.ServiceAccountKeyFile); err != nil {
|
||||||
|
errs = append(errs, fmt.Errorf("fail to read service account key file: %s", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return errs
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -50,7 +50,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
|
||||||
// Run executes a yandex Packer build and returns a packer.Artifact
|
// Run executes a yandex Packer build and returns a packer.Artifact
|
||||||
// representing a Yandex.Cloud compute image.
|
// representing a Yandex.Cloud compute image.
|
||||||
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
|
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
|
||||||
driver, err := NewDriverYC(ui, &b.config)
|
driver, err := NewDriverYC(ui, &b.config.AccessConfig)
|
||||||
ctx = requestid.ContextWithClientTraceID(ctx, uuid.New().String())
|
ctx = requestid.ContextWithClientTraceID(ctx, uuid.New().String())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -16,11 +16,8 @@ import (
|
||||||
"github.com/hashicorp/packer/helper/config"
|
"github.com/hashicorp/packer/helper/config"
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
"github.com/hashicorp/packer/template/interpolate"
|
"github.com/hashicorp/packer/template/interpolate"
|
||||||
|
|
||||||
"github.com/yandex-cloud/go-sdk/iamkey"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultEndpoint = "api.cloud.yandex.net:443"
|
|
||||||
const defaultGpuPlatformID = "gpu-standard-v1"
|
const defaultGpuPlatformID = "gpu-standard-v1"
|
||||||
const defaultPlatformID = "standard-v1"
|
const defaultPlatformID = "standard-v1"
|
||||||
const defaultMaxRetries = 3
|
const defaultMaxRetries = 3
|
||||||
|
@ -31,23 +28,15 @@ var reImageFamily = regexp.MustCompile(`^[a-z]([-a-z0-9]{0,61}[a-z0-9])?$`)
|
||||||
type Config struct {
|
type Config struct {
|
||||||
common.PackerConfig `mapstructure:",squash"`
|
common.PackerConfig `mapstructure:",squash"`
|
||||||
Communicator communicator.Config `mapstructure:",squash"`
|
Communicator communicator.Config `mapstructure:",squash"`
|
||||||
|
AccessConfig `mapstructure:",squash"`
|
||||||
|
|
||||||
// Non standard api endpoint URL.
|
|
||||||
Endpoint string `mapstructure:"endpoint" required:"false"`
|
|
||||||
// The folder ID that will be used to launch instances and store images.
|
// The folder ID that will be used to launch instances and store images.
|
||||||
// Alternatively you may set value by environment variable YC_FOLDER_ID.
|
// Alternatively you may set value by environment variable `YC_FOLDER_ID`.
|
||||||
// To use a different folder for looking up the source image or saving the target image to
|
// To use a different folder for looking up the source image or saving the target image to
|
||||||
// check options 'source_image_folder_id' and 'target_image_folder_id'.
|
// check options 'source_image_folder_id' and 'target_image_folder_id'.
|
||||||
FolderID string `mapstructure:"folder_id" required:"true"`
|
FolderID string `mapstructure:"folder_id" required:"true"`
|
||||||
// Path to file with Service Account key in json format. This
|
// Service account identifier to assign to instance.
|
||||||
// is an alternative method to authenticate to Yandex.Cloud. Alternatively you may set environment variable
|
|
||||||
// YC_SERVICE_ACCOUNT_KEY_FILE.
|
|
||||||
ServiceAccountKeyFile string `mapstructure:"service_account_key_file" required:"false"`
|
|
||||||
// Service account identifier to assign to instance
|
|
||||||
ServiceAccountID string `mapstructure:"service_account_id" required:"false"`
|
ServiceAccountID string `mapstructure:"service_account_id" required:"false"`
|
||||||
// OAuth token to use to authenticate to Yandex.Cloud. Alternatively you may set
|
|
||||||
// value by environment variable YC_TOKEN.
|
|
||||||
Token string `mapstructure:"token" required:"true"`
|
|
||||||
// The name of the disk, if unset the instance name
|
// The name of the disk, if unset the instance name
|
||||||
// will be used.
|
// will be used.
|
||||||
DiskName string `mapstructure:"disk_name" required:"false"`
|
DiskName string `mapstructure:"disk_name" required:"false"`
|
||||||
|
@ -59,8 +48,7 @@ type Config struct {
|
||||||
ImageDescription string `mapstructure:"image_description" required:"false"`
|
ImageDescription string `mapstructure:"image_description" required:"false"`
|
||||||
// The family name of the resulting image.
|
// The family name of the resulting image.
|
||||||
ImageFamily string `mapstructure:"image_family" required:"false"`
|
ImageFamily string `mapstructure:"image_family" required:"false"`
|
||||||
// Key/value pair labels to
|
// Key/value pair labels to apply to the created image.
|
||||||
// apply to the created image.
|
|
||||||
ImageLabels map[string]string `mapstructure:"image_labels" required:"false"`
|
ImageLabels map[string]string `mapstructure:"image_labels" required:"false"`
|
||||||
// Minimum size of the disk that will be created from built image, specified in gigabytes.
|
// Minimum size of the disk that will be created from built image, specified in gigabytes.
|
||||||
// Should be more or equal to `disk_size_gb`.
|
// Should be more or equal to `disk_size_gb`.
|
||||||
|
@ -78,16 +66,14 @@ type Config struct {
|
||||||
InstanceMemory int `mapstructure:"instance_mem_gb" required:"false"`
|
InstanceMemory int `mapstructure:"instance_mem_gb" required:"false"`
|
||||||
// The name assigned to the instance.
|
// The name assigned to the instance.
|
||||||
InstanceName string `mapstructure:"instance_name" required:"false"`
|
InstanceName string `mapstructure:"instance_name" required:"false"`
|
||||||
// Key/value pair labels to apply to
|
// Key/value pair labels to apply to the launched instance.
|
||||||
// the launched instance.
|
|
||||||
Labels map[string]string `mapstructure:"labels" required:"false"`
|
Labels map[string]string `mapstructure:"labels" required:"false"`
|
||||||
// Identifier of the hardware platform configuration for the instance. This defaults to `standard-v1`.
|
// Identifier of the hardware platform configuration for the instance. This defaults to `standard-v1`.
|
||||||
PlatformID string `mapstructure:"platform_id" required:"false"`
|
PlatformID string `mapstructure:"platform_id" required:"false"`
|
||||||
// The maximum number of times an API request is being executed
|
|
||||||
MaxRetries int `mapstructure:"max_retries"`
|
|
||||||
// Metadata applied to the launched instance.
|
// Metadata applied to the launched instance.
|
||||||
Metadata map[string]string `mapstructure:"metadata" required:"false"`
|
Metadata map[string]string `mapstructure:"metadata" required:"false"`
|
||||||
// Metadata applied to the launched instance. Value are file paths.
|
// Metadata applied to the launched instance.
|
||||||
|
// The values in this map are the paths to the content files for the corresponding metadata keys.
|
||||||
MetadataFromFile map[string]string `mapstructure:"metadata_from_file"`
|
MetadataFromFile map[string]string `mapstructure:"metadata_from_file"`
|
||||||
// Launch a preemptible instance. This defaults to `false`.
|
// Launch a preemptible instance. This defaults to `false`.
|
||||||
Preemptible bool `mapstructure:"preemptible"`
|
Preemptible bool `mapstructure:"preemptible"`
|
||||||
|
@ -95,12 +81,11 @@ type Config struct {
|
||||||
SerialLogFile string `mapstructure:"serial_log_file" required:"false"`
|
SerialLogFile string `mapstructure:"serial_log_file" required:"false"`
|
||||||
// The source image family to create the new image
|
// The source image family to create the new image
|
||||||
// from. You can also specify source_image_id instead. Just one of a source_image_id or
|
// from. You can also specify source_image_id instead. Just one of a source_image_id or
|
||||||
// source_image_family must be specified. Example: `ubuntu-1804-lts`
|
// source_image_family must be specified. Example: `ubuntu-1804-lts`.
|
||||||
SourceImageFamily string `mapstructure:"source_image_family" required:"true"`
|
SourceImageFamily string `mapstructure:"source_image_family" required:"true"`
|
||||||
// The ID of the folder containing the source image.
|
// The ID of the folder containing the source image.
|
||||||
SourceImageFolderID string `mapstructure:"source_image_folder_id" required:"false"`
|
SourceImageFolderID string `mapstructure:"source_image_folder_id" required:"false"`
|
||||||
// The source image ID to use to create the new image
|
// The source image ID to use to create the new image from.
|
||||||
// from.
|
|
||||||
SourceImageID string `mapstructure:"source_image_id" required:"false"`
|
SourceImageID string `mapstructure:"source_image_id" required:"false"`
|
||||||
// The source image name to use to create the new image
|
// The source image name to use to create the new image
|
||||||
// from. Name will be looked up in `source_image_folder_id`.
|
// from. Name will be looked up in `source_image_folder_id`.
|
||||||
|
@ -142,8 +127,11 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accumulate any errors
|
||||||
var errs *packer.MultiError
|
var errs *packer.MultiError
|
||||||
|
|
||||||
|
errs = packer.MultiErrorAppend(errs, c.AccessConfig.Prepare(&c.ctx)...)
|
||||||
|
|
||||||
if c.SerialLogFile != "" {
|
if c.SerialLogFile != "" {
|
||||||
if _, err := os.Stat(c.SerialLogFile); os.IsExist(err) {
|
if _, err := os.Stat(c.SerialLogFile); os.IsExist(err) {
|
||||||
errs = packer.MultiErrorAppend(errs,
|
errs = packer.MultiErrorAppend(errs,
|
||||||
|
@ -236,10 +224,6 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Endpoint == "" {
|
|
||||||
c.Endpoint = defaultEndpoint
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Zone == "" {
|
if c.Zone == "" {
|
||||||
c.Zone = defaultZone
|
c.Zone = defaultZone
|
||||||
}
|
}
|
||||||
|
@ -248,35 +232,10 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
|
||||||
c.MaxRetries = defaultMaxRetries
|
c.MaxRetries = defaultMaxRetries
|
||||||
}
|
}
|
||||||
|
|
||||||
// provision config by OS environment variables
|
|
||||||
if c.Token == "" {
|
|
||||||
c.Token = os.Getenv("YC_TOKEN")
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ServiceAccountKeyFile == "" {
|
|
||||||
c.ServiceAccountKeyFile = os.Getenv("YC_SERVICE_ACCOUNT_KEY_FILE")
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.FolderID == "" {
|
if c.FolderID == "" {
|
||||||
c.FolderID = os.Getenv("YC_FOLDER_ID")
|
c.FolderID = os.Getenv("YC_FOLDER_ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Token != "" && c.ServiceAccountKeyFile != "" {
|
|
||||||
errs = packer.MultiErrorAppend(
|
|
||||||
errs, errors.New("one of token or service account key file must be specified, not both"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Token != "" {
|
|
||||||
packer.LogSecretFilter.Set(c.Token)
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.ServiceAccountKeyFile != "" {
|
|
||||||
if _, err := iamkey.ReadFromJSONFile(c.ServiceAccountKeyFile); err != nil {
|
|
||||||
errs = packer.MultiErrorAppend(
|
|
||||||
errs, fmt.Errorf("fail to read service account key file: %s", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.FolderID == "" {
|
if c.FolderID == "" {
|
||||||
errs = packer.MultiErrorAppend(
|
errs = packer.MultiErrorAppend(
|
||||||
errs, errors.New("a folder_id must be specified"))
|
errs, errors.New("a folder_id must be specified"))
|
||||||
|
|
|
@ -64,10 +64,11 @@ type FlatConfig struct {
|
||||||
WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"`
|
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"`
|
WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"`
|
||||||
Endpoint *string `mapstructure:"endpoint" required:"false" cty:"endpoint" hcl:"endpoint"`
|
Endpoint *string `mapstructure:"endpoint" required:"false" cty:"endpoint" hcl:"endpoint"`
|
||||||
FolderID *string `mapstructure:"folder_id" required:"true" cty:"folder_id" hcl:"folder_id"`
|
|
||||||
ServiceAccountKeyFile *string `mapstructure:"service_account_key_file" required:"false" cty:"service_account_key_file" hcl:"service_account_key_file"`
|
ServiceAccountKeyFile *string `mapstructure:"service_account_key_file" required:"false" cty:"service_account_key_file" hcl:"service_account_key_file"`
|
||||||
ServiceAccountID *string `mapstructure:"service_account_id" required:"false" cty:"service_account_id" hcl:"service_account_id"`
|
|
||||||
Token *string `mapstructure:"token" required:"true" cty:"token" hcl:"token"`
|
Token *string `mapstructure:"token" required:"true" cty:"token" hcl:"token"`
|
||||||
|
MaxRetries *int `mapstructure:"max_retries" cty:"max_retries" hcl:"max_retries"`
|
||||||
|
FolderID *string `mapstructure:"folder_id" required:"true" cty:"folder_id" hcl:"folder_id"`
|
||||||
|
ServiceAccountID *string `mapstructure:"service_account_id" required:"false" cty:"service_account_id" hcl:"service_account_id"`
|
||||||
DiskName *string `mapstructure:"disk_name" required:"false" cty:"disk_name" hcl:"disk_name"`
|
DiskName *string `mapstructure:"disk_name" required:"false" cty:"disk_name" hcl:"disk_name"`
|
||||||
DiskSizeGb *int `mapstructure:"disk_size_gb" required:"false" cty:"disk_size_gb" hcl:"disk_size_gb"`
|
DiskSizeGb *int `mapstructure:"disk_size_gb" required:"false" cty:"disk_size_gb" hcl:"disk_size_gb"`
|
||||||
DiskType *string `mapstructure:"disk_type" required:"false" cty:"disk_type" hcl:"disk_type"`
|
DiskType *string `mapstructure:"disk_type" required:"false" cty:"disk_type" hcl:"disk_type"`
|
||||||
|
@ -83,7 +84,6 @@ type FlatConfig struct {
|
||||||
InstanceName *string `mapstructure:"instance_name" required:"false" cty:"instance_name" hcl:"instance_name"`
|
InstanceName *string `mapstructure:"instance_name" required:"false" cty:"instance_name" hcl:"instance_name"`
|
||||||
Labels map[string]string `mapstructure:"labels" required:"false" cty:"labels" hcl:"labels"`
|
Labels map[string]string `mapstructure:"labels" required:"false" cty:"labels" hcl:"labels"`
|
||||||
PlatformID *string `mapstructure:"platform_id" required:"false" cty:"platform_id" hcl:"platform_id"`
|
PlatformID *string `mapstructure:"platform_id" required:"false" cty:"platform_id" hcl:"platform_id"`
|
||||||
MaxRetries *int `mapstructure:"max_retries" cty:"max_retries" hcl:"max_retries"`
|
|
||||||
Metadata map[string]string `mapstructure:"metadata" required:"false" cty:"metadata" hcl:"metadata"`
|
Metadata map[string]string `mapstructure:"metadata" required:"false" cty:"metadata" hcl:"metadata"`
|
||||||
MetadataFromFile map[string]string `mapstructure:"metadata_from_file" cty:"metadata_from_file" hcl:"metadata_from_file"`
|
MetadataFromFile map[string]string `mapstructure:"metadata_from_file" cty:"metadata_from_file" hcl:"metadata_from_file"`
|
||||||
Preemptible *bool `mapstructure:"preemptible" cty:"preemptible" hcl:"preemptible"`
|
Preemptible *bool `mapstructure:"preemptible" cty:"preemptible" hcl:"preemptible"`
|
||||||
|
@ -168,10 +168,11 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", 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},
|
"winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false},
|
||||||
"endpoint": &hcldec.AttrSpec{Name: "endpoint", Type: cty.String, Required: false},
|
"endpoint": &hcldec.AttrSpec{Name: "endpoint", Type: cty.String, Required: false},
|
||||||
"folder_id": &hcldec.AttrSpec{Name: "folder_id", Type: cty.String, Required: false},
|
|
||||||
"service_account_key_file": &hcldec.AttrSpec{Name: "service_account_key_file", Type: cty.String, Required: false},
|
"service_account_key_file": &hcldec.AttrSpec{Name: "service_account_key_file", Type: cty.String, Required: false},
|
||||||
"service_account_id": &hcldec.AttrSpec{Name: "service_account_id", Type: cty.String, Required: false},
|
|
||||||
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
||||||
|
"max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false},
|
||||||
|
"folder_id": &hcldec.AttrSpec{Name: "folder_id", Type: cty.String, Required: false},
|
||||||
|
"service_account_id": &hcldec.AttrSpec{Name: "service_account_id", Type: cty.String, Required: false},
|
||||||
"disk_name": &hcldec.AttrSpec{Name: "disk_name", Type: cty.String, Required: false},
|
"disk_name": &hcldec.AttrSpec{Name: "disk_name", Type: cty.String, Required: false},
|
||||||
"disk_size_gb": &hcldec.AttrSpec{Name: "disk_size_gb", Type: cty.Number, Required: false},
|
"disk_size_gb": &hcldec.AttrSpec{Name: "disk_size_gb", Type: cty.Number, Required: false},
|
||||||
"disk_type": &hcldec.AttrSpec{Name: "disk_type", Type: cty.String, Required: false},
|
"disk_type": &hcldec.AttrSpec{Name: "disk_type", Type: cty.String, Required: false},
|
||||||
|
@ -187,7 +188,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"instance_name": &hcldec.AttrSpec{Name: "instance_name", Type: cty.String, Required: false},
|
"instance_name": &hcldec.AttrSpec{Name: "instance_name", Type: cty.String, Required: false},
|
||||||
"labels": &hcldec.AttrSpec{Name: "labels", Type: cty.Map(cty.String), Required: false},
|
"labels": &hcldec.AttrSpec{Name: "labels", Type: cty.Map(cty.String), Required: false},
|
||||||
"platform_id": &hcldec.AttrSpec{Name: "platform_id", Type: cty.String, Required: false},
|
"platform_id": &hcldec.AttrSpec{Name: "platform_id", Type: cty.String, Required: false},
|
||||||
"max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false},
|
|
||||||
"metadata": &hcldec.AttrSpec{Name: "metadata", Type: cty.Map(cty.String), Required: false},
|
"metadata": &hcldec.AttrSpec{Name: "metadata", Type: cty.Map(cty.String), Required: false},
|
||||||
"metadata_from_file": &hcldec.AttrSpec{Name: "metadata_from_file", Type: cty.Map(cty.String), Required: false},
|
"metadata_from_file": &hcldec.AttrSpec{Name: "metadata_from_file", Type: cty.Map(cty.String), Required: false},
|
||||||
"preemptible": &hcldec.AttrSpec{Name: "preemptible", Type: cty.Bool, Required: false},
|
"preemptible": &hcldec.AttrSpec{Name: "preemptible", Type: cty.Bool, Required: false},
|
||||||
|
|
|
@ -33,27 +33,27 @@ type driverYC struct {
|
||||||
ui packer.Ui
|
ui packer.Ui
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDriverYC(ui packer.Ui, config *Config) (Driver, error) {
|
func NewDriverYC(ui packer.Ui, ac *AccessConfig) (Driver, error) {
|
||||||
log.Printf("[INFO] Initialize Yandex.Cloud client...")
|
log.Printf("[INFO] Initialize Yandex.Cloud client...")
|
||||||
|
|
||||||
sdkConfig := ycsdk.Config{}
|
sdkConfig := ycsdk.Config{}
|
||||||
|
|
||||||
if config.Endpoint != "" {
|
if ac.Endpoint != "" {
|
||||||
sdkConfig.Endpoint = config.Endpoint
|
sdkConfig.Endpoint = ac.Endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case config.Token == "" && config.ServiceAccountKeyFile == "":
|
case ac.Token == "" && ac.ServiceAccountKeyFile == "":
|
||||||
log.Printf("[INFO] Use Instance Service Account for authentication")
|
log.Printf("[INFO] Use Instance Service Account for authentication")
|
||||||
sdkConfig.Credentials = ycsdk.InstanceServiceAccount()
|
sdkConfig.Credentials = ycsdk.InstanceServiceAccount()
|
||||||
|
|
||||||
case config.Token != "":
|
case ac.Token != "":
|
||||||
log.Printf("[INFO] Use OAuth token for authentication")
|
log.Printf("[INFO] Use OAuth token for authentication")
|
||||||
sdkConfig.Credentials = ycsdk.OAuthToken(config.Token)
|
sdkConfig.Credentials = ycsdk.OAuthToken(ac.Token)
|
||||||
|
|
||||||
case config.ServiceAccountKeyFile != "":
|
case ac.ServiceAccountKeyFile != "":
|
||||||
log.Printf("[INFO] Use Service Account key file %q for authentication", config.ServiceAccountKeyFile)
|
log.Printf("[INFO] Use Service Account key file %q for authentication", ac.ServiceAccountKeyFile)
|
||||||
key, err := iamkey.ReadFromJSONFile(config.ServiceAccountKeyFile)
|
key, err := iamkey.ReadFromJSONFile(ac.ServiceAccountKeyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ func NewDriverYC(ui packer.Ui, config *Config) (Driver, error) {
|
||||||
requestIDInterceptor := requestid.Interceptor()
|
requestIDInterceptor := requestid.Interceptor()
|
||||||
|
|
||||||
retryInterceptor := retry.Interceptor(
|
retryInterceptor := retry.Interceptor(
|
||||||
retry.WithMax(config.MaxRetries),
|
retry.WithMax(ac.MaxRetries),
|
||||||
retry.WithCodes(codes.Unavailable),
|
retry.WithCodes(codes.Unavailable),
|
||||||
retry.WithAttemptHeader(true),
|
retry.WithAttemptHeader(true),
|
||||||
retry.WithBackoff(retry.BackoffExponentialWithJitter(defaultExponentialBackoffBase, defaultExponentialBackoffCap)))
|
retry.WithBackoff(retry.BackoffExponentialWithJitter(defaultExponentialBackoffBase, defaultExponentialBackoffCap)))
|
||||||
|
|
|
@ -11,8 +11,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/yandex-cloud/go-sdk/iamkey"
|
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/v2/hcldec"
|
"github.com/hashicorp/hcl/v2/hcldec"
|
||||||
"github.com/hashicorp/packer/builder"
|
"github.com/hashicorp/packer/builder"
|
||||||
"github.com/hashicorp/packer/builder/yandex"
|
"github.com/hashicorp/packer/builder/yandex"
|
||||||
|
@ -28,6 +26,7 @@ const defaultStorageEndpoint = "storage.yandexcloud.net"
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
common.PackerConfig `mapstructure:",squash"`
|
common.PackerConfig `mapstructure:",squash"`
|
||||||
|
yandex.AccessConfig `mapstructure:",squash"`
|
||||||
|
|
||||||
// List of paths to Yandex Object Storage where exported image will be uploaded.
|
// List of paths to Yandex Object Storage where exported image will be uploaded.
|
||||||
// Please be aware that use of space char inside path not supported.
|
// Please be aware that use of space char inside path not supported.
|
||||||
|
@ -36,7 +35,7 @@ type Config struct {
|
||||||
// Paths to Yandex Object Storage where exported image will be uploaded.
|
// Paths to Yandex Object Storage where exported image will be uploaded.
|
||||||
Paths []string `mapstructure:"paths" required:"true"`
|
Paths []string `mapstructure:"paths" required:"true"`
|
||||||
// The folder ID that will be used to launch a temporary instance.
|
// The folder ID that will be used to launch a temporary instance.
|
||||||
// Alternatively you may set value by environment variable YC_FOLDER_ID.
|
// Alternatively you may set value by environment variable `YC_FOLDER_ID`.
|
||||||
FolderID string `mapstructure:"folder_id" required:"true"`
|
FolderID string `mapstructure:"folder_id" required:"true"`
|
||||||
// Service Account ID with proper permission to modify an instance, create and attach disk and
|
// Service Account ID with proper permission to modify an instance, create and attach disk and
|
||||||
// make upload to specific Yandex Object Storage paths.
|
// make upload to specific Yandex Object Storage paths.
|
||||||
|
@ -53,13 +52,6 @@ type Config struct {
|
||||||
SubnetID string `mapstructure:"subnet_id" required:"false"`
|
SubnetID string `mapstructure:"subnet_id" required:"false"`
|
||||||
// The name of the zone to launch the instance. This defaults to `ru-central1-a`.
|
// The name of the zone to launch the instance. This defaults to `ru-central1-a`.
|
||||||
Zone string `mapstructure:"zone" required:"false"`
|
Zone string `mapstructure:"zone" required:"false"`
|
||||||
// OAuth token to use to authenticate to Yandex.Cloud. Alternatively you may set
|
|
||||||
// value by environment variable YC_TOKEN.
|
|
||||||
Token string `mapstructure:"token" required:"false"`
|
|
||||||
// Path to file with Service Account key in json format. This
|
|
||||||
// is an alternative method to authenticate to Yandex.Cloud. Alternatively you may set environment variable
|
|
||||||
// YC_SERVICE_ACCOUNT_KEY_FILE.
|
|
||||||
ServiceAccountKeyFile string `mapstructure:"service_account_key_file" required:"false"`
|
|
||||||
|
|
||||||
ctx interpolate.Context
|
ctx interpolate.Context
|
||||||
}
|
}
|
||||||
|
@ -85,7 +77,10 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
errs := new(packer.MultiError)
|
// Accumulate any errors
|
||||||
|
var errs *packer.MultiError
|
||||||
|
|
||||||
|
errs = packer.MultiErrorAppend(errs, p.config.AccessConfig.Prepare(&p.config.ctx)...)
|
||||||
|
|
||||||
if len(p.config.Paths) == 0 {
|
if len(p.config.Paths) == 0 {
|
||||||
errs = packer.MultiErrorAppend(
|
errs = packer.MultiErrorAppend(
|
||||||
|
@ -100,31 +95,6 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// provision config by OS environment variables
|
|
||||||
if p.config.Token == "" {
|
|
||||||
p.config.Token = os.Getenv("YC_TOKEN")
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.config.ServiceAccountKeyFile == "" {
|
|
||||||
p.config.ServiceAccountKeyFile = os.Getenv("YC_SERVICE_ACCOUNT_KEY_FILE")
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.config.Token != "" && p.config.ServiceAccountKeyFile != "" {
|
|
||||||
errs = packer.MultiErrorAppend(
|
|
||||||
errs, fmt.Errorf("one of token or service account key file must be specified, not both"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.config.Token != "" {
|
|
||||||
packer.LogSecretFilter.Set(p.config.Token)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.config.ServiceAccountKeyFile != "" {
|
|
||||||
if _, err := iamkey.ReadFromJSONFile(p.config.ServiceAccountKeyFile); err != nil {
|
|
||||||
errs = packer.MultiErrorAppend(
|
|
||||||
errs, fmt.Errorf("fail to read service account key file: %s", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.config.FolderID == "" {
|
if p.config.FolderID == "" {
|
||||||
p.config.FolderID = os.Getenv("YC_FOLDER_ID")
|
p.config.FolderID = os.Getenv("YC_FOLDER_ID")
|
||||||
}
|
}
|
||||||
|
@ -203,8 +173,6 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
|
||||||
}
|
}
|
||||||
|
|
||||||
yandexConfig := ycSaneDefaults()
|
yandexConfig := ycSaneDefaults()
|
||||||
yandexConfig.Token = p.config.Token
|
|
||||||
yandexConfig.ServiceAccountKeyFile = p.config.ServiceAccountKeyFile
|
|
||||||
yandexConfig.DiskName = exporterName
|
yandexConfig.DiskName = exporterName
|
||||||
yandexConfig.InstanceName = exporterName
|
yandexConfig.InstanceName = exporterName
|
||||||
yandexConfig.DiskSizeGb = p.config.DiskSizeGb
|
yandexConfig.DiskSizeGb = p.config.DiskSizeGb
|
||||||
|
@ -221,7 +189,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
|
||||||
yandexConfig.PlatformID = p.config.PlatformID
|
yandexConfig.PlatformID = p.config.PlatformID
|
||||||
}
|
}
|
||||||
|
|
||||||
driver, err := yandex.NewDriverYC(ui, &yandexConfig)
|
driver, err := yandex.NewDriverYC(ui, &p.config.AccessConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, false, err
|
return nil, false, false, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,10 @@ type FlatConfig struct {
|
||||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
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"`
|
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"`
|
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||||
|
Endpoint *string `mapstructure:"endpoint" required:"false" cty:"endpoint" hcl:"endpoint"`
|
||||||
|
ServiceAccountKeyFile *string `mapstructure:"service_account_key_file" required:"false" cty:"service_account_key_file" hcl:"service_account_key_file"`
|
||||||
|
Token *string `mapstructure:"token" required:"true" cty:"token" hcl:"token"`
|
||||||
|
MaxRetries *int `mapstructure:"max_retries" cty:"max_retries" hcl:"max_retries"`
|
||||||
Paths []string `mapstructure:"paths" required:"true" cty:"paths" hcl:"paths"`
|
Paths []string `mapstructure:"paths" required:"true" cty:"paths" hcl:"paths"`
|
||||||
FolderID *string `mapstructure:"folder_id" required:"true" cty:"folder_id" hcl:"folder_id"`
|
FolderID *string `mapstructure:"folder_id" required:"true" cty:"folder_id" hcl:"folder_id"`
|
||||||
ServiceAccountID *string `mapstructure:"service_account_id" required:"true" cty:"service_account_id" hcl:"service_account_id"`
|
ServiceAccountID *string `mapstructure:"service_account_id" required:"true" cty:"service_account_id" hcl:"service_account_id"`
|
||||||
|
@ -24,8 +28,6 @@ type FlatConfig struct {
|
||||||
PlatformID *string `mapstructure:"platform_id" required:"false" cty:"platform_id" hcl:"platform_id"`
|
PlatformID *string `mapstructure:"platform_id" required:"false" cty:"platform_id" hcl:"platform_id"`
|
||||||
SubnetID *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"`
|
SubnetID *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"`
|
||||||
Zone *string `mapstructure:"zone" required:"false" cty:"zone" hcl:"zone"`
|
Zone *string `mapstructure:"zone" required:"false" cty:"zone" hcl:"zone"`
|
||||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
|
||||||
ServiceAccountKeyFile *string `mapstructure:"service_account_key_file" required:"false" cty:"service_account_key_file" hcl:"service_account_key_file"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlatMapstructure returns a new FlatConfig.
|
// FlatMapstructure returns a new FlatConfig.
|
||||||
|
@ -47,6 +49,10 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, 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_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},
|
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||||
|
"endpoint": &hcldec.AttrSpec{Name: "endpoint", Type: cty.String, Required: false},
|
||||||
|
"service_account_key_file": &hcldec.AttrSpec{Name: "service_account_key_file", Type: cty.String, Required: false},
|
||||||
|
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
||||||
|
"max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false},
|
||||||
"paths": &hcldec.AttrSpec{Name: "paths", Type: cty.List(cty.String), Required: false},
|
"paths": &hcldec.AttrSpec{Name: "paths", Type: cty.List(cty.String), Required: false},
|
||||||
"folder_id": &hcldec.AttrSpec{Name: "folder_id", Type: cty.String, Required: false},
|
"folder_id": &hcldec.AttrSpec{Name: "folder_id", Type: cty.String, Required: false},
|
||||||
"service_account_id": &hcldec.AttrSpec{Name: "service_account_id", Type: cty.String, Required: false},
|
"service_account_id": &hcldec.AttrSpec{Name: "service_account_id", Type: cty.String, Required: false},
|
||||||
|
@ -55,8 +61,6 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"platform_id": &hcldec.AttrSpec{Name: "platform_id", Type: cty.String, Required: false},
|
"platform_id": &hcldec.AttrSpec{Name: "platform_id", Type: cty.String, Required: false},
|
||||||
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
|
"subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false},
|
||||||
"zone": &hcldec.AttrSpec{Name: "zone", Type: cty.String, Required: false},
|
"zone": &hcldec.AttrSpec{Name: "zone", Type: cty.String, Required: false},
|
||||||
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
|
||||||
"service_account_key_file": &hcldec.AttrSpec{Name: "service_account_key_file", Type: cty.String, Required: false},
|
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package yandexexport
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/packer/builder/yandex"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/hashicorp/packer/helper/multistep"
|
"github.com/hashicorp/packer/helper/multistep"
|
||||||
|
@ -26,8 +27,10 @@ func TestPostProcessor_Configure(t *testing.T) {
|
||||||
name: "no one creds",
|
name: "no one creds",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
config: Config{
|
config: Config{
|
||||||
Token: "",
|
AccessConfig: yandex.AccessConfig{
|
||||||
ServiceAccountKeyFile: "",
|
Token: "",
|
||||||
|
ServiceAccountKeyFile: "",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
|
@ -36,8 +39,10 @@ func TestPostProcessor_Configure(t *testing.T) {
|
||||||
name: "both token and sa key file",
|
name: "both token and sa key file",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
config: Config{
|
config: Config{
|
||||||
Token: "some-value",
|
AccessConfig: yandex.AccessConfig{
|
||||||
ServiceAccountKeyFile: "path/not-exist.file",
|
Token: "some-value",
|
||||||
|
ServiceAccountKeyFile: "path/not-exist.file",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
|
@ -46,8 +51,10 @@ func TestPostProcessor_Configure(t *testing.T) {
|
||||||
name: "use sa key file",
|
name: "use sa key file",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
config: Config{
|
config: Config{
|
||||||
Token: "",
|
AccessConfig: yandex.AccessConfig{
|
||||||
ServiceAccountKeyFile: "testdata/fake-sa-key.json",
|
Token: "",
|
||||||
|
ServiceAccountKeyFile: "testdata/fake-sa-key.json",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
|
|
|
@ -19,24 +19,18 @@ import (
|
||||||
yandexexport "github.com/hashicorp/packer/post-processor/yandex-export"
|
yandexexport "github.com/hashicorp/packer/post-processor/yandex-export"
|
||||||
"github.com/hashicorp/packer/template/interpolate"
|
"github.com/hashicorp/packer/template/interpolate"
|
||||||
"github.com/yandex-cloud/go-genproto/yandex/cloud/iam/v1/awscompatibility"
|
"github.com/yandex-cloud/go-genproto/yandex/cloud/iam/v1/awscompatibility"
|
||||||
"github.com/yandex-cloud/go-sdk/iamkey"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
common.PackerConfig `mapstructure:",squash"`
|
common.PackerConfig `mapstructure:",squash"`
|
||||||
|
yandex.AccessConfig `mapstructure:",squash"`
|
||||||
|
|
||||||
// The folder ID that will be used to store imported Image.
|
// The folder ID that will be used to store imported Image.
|
||||||
FolderID string `mapstructure:"folder_id" required:"true"`
|
FolderID string `mapstructure:"folder_id" required:"true"`
|
||||||
// Service Account ID with proper permission to use Storage service
|
// Service Account ID with proper permission to use Storage service
|
||||||
// for operations 'upload' and 'delete' object to `bucket`
|
// for operations 'upload' and 'delete' object to `bucket`.
|
||||||
ServiceAccountID string `mapstructure:"service_account_id" required:"true"`
|
ServiceAccountID string `mapstructure:"service_account_id" required:"true"`
|
||||||
|
|
||||||
// OAuth token to use to authenticate to Yandex.Cloud.
|
|
||||||
Token string `mapstructure:"token" required:"false"`
|
|
||||||
// Path to file with Service Account key in json format. This
|
|
||||||
// is an alternative method to authenticate to Yandex.Cloud.
|
|
||||||
ServiceAccountKeyFile string `mapstructure:"service_account_key_file" required:"false"`
|
|
||||||
|
|
||||||
// The name of the bucket where the qcow2 file will be uploaded to for import.
|
// The name of the bucket where the qcow2 file will be uploaded to for import.
|
||||||
// This bucket must exist when the post-processor is run.
|
// This bucket must exist when the post-processor is run.
|
||||||
//
|
//
|
||||||
|
@ -49,7 +43,7 @@ type Config struct {
|
||||||
ObjectName string `mapstructure:"object_name" required:"false"`
|
ObjectName string `mapstructure:"object_name" required:"false"`
|
||||||
// Whether skip removing the qcow2 file uploaded to Storage
|
// Whether skip removing the qcow2 file uploaded to Storage
|
||||||
// after the import process has completed. Possible values are: `true` to
|
// after the import process has completed. Possible values are: `true` to
|
||||||
// leave it in the bucket, `false` to remove it. (Default: `false`).
|
// leave it in the bucket, `false` to remove it. Default is `false`.
|
||||||
SkipClean bool `mapstructure:"skip_clean" required:"false"`
|
SkipClean bool `mapstructure:"skip_clean" required:"false"`
|
||||||
|
|
||||||
// The name of the image, which contains 1-63 characters and only
|
// The name of the image, which contains 1-63 characters and only
|
||||||
|
@ -85,27 +79,10 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
errs := new(packer.MultiError)
|
// Accumulate any errors
|
||||||
|
var errs *packer.MultiError
|
||||||
|
|
||||||
// provision config by OS environment variables
|
errs = packer.MultiErrorAppend(errs, p.config.AccessConfig.Prepare(&p.config.ctx)...)
|
||||||
if p.config.Token == "" {
|
|
||||||
p.config.Token = os.Getenv("YC_TOKEN")
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.config.ServiceAccountKeyFile == "" {
|
|
||||||
p.config.ServiceAccountKeyFile = os.Getenv("YC_SERVICE_ACCOUNT_KEY_FILE")
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.config.Token != "" {
|
|
||||||
packer.LogSecretFilter.Set(p.config.Token)
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.config.ServiceAccountKeyFile != "" {
|
|
||||||
if _, err := iamkey.ReadFromJSONFile(p.config.ServiceAccountKeyFile); err != nil {
|
|
||||||
errs = packer.MultiErrorAppend(
|
|
||||||
errs, fmt.Errorf("fail to read service account key file: %s", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.config.FolderID == "" {
|
if p.config.FolderID == "" {
|
||||||
p.config.FolderID = os.Getenv("YC_FOLDER_ID")
|
p.config.FolderID = os.Getenv("YC_FOLDER_ID")
|
||||||
|
@ -160,12 +137,8 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
|
||||||
return nil, false, false, fmt.Errorf("error rendering object_name template: %s", err)
|
return nil, false, false, fmt.Errorf("error rendering object_name template: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := &yandex.Config{
|
client, err := yandex.NewDriverYC(ui, &p.config.AccessConfig)
|
||||||
Token: p.config.Token,
|
|
||||||
ServiceAccountKeyFile: p.config.ServiceAccountKeyFile,
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := yandex.NewDriverYC(ui, cfg)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, false, err
|
return nil, false, false, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,12 @@ type FlatConfig struct {
|
||||||
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
|
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"`
|
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"`
|
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
|
||||||
|
Endpoint *string `mapstructure:"endpoint" required:"false" cty:"endpoint" hcl:"endpoint"`
|
||||||
|
ServiceAccountKeyFile *string `mapstructure:"service_account_key_file" required:"false" cty:"service_account_key_file" hcl:"service_account_key_file"`
|
||||||
|
Token *string `mapstructure:"token" required:"true" cty:"token" hcl:"token"`
|
||||||
|
MaxRetries *int `mapstructure:"max_retries" cty:"max_retries" hcl:"max_retries"`
|
||||||
FolderID *string `mapstructure:"folder_id" required:"true" cty:"folder_id" hcl:"folder_id"`
|
FolderID *string `mapstructure:"folder_id" required:"true" cty:"folder_id" hcl:"folder_id"`
|
||||||
ServiceAccountID *string `mapstructure:"service_account_id" required:"true" cty:"service_account_id" hcl:"service_account_id"`
|
ServiceAccountID *string `mapstructure:"service_account_id" required:"true" cty:"service_account_id" hcl:"service_account_id"`
|
||||||
Token *string `mapstructure:"token" required:"false" cty:"token" hcl:"token"`
|
|
||||||
ServiceAccountKeyFile *string `mapstructure:"service_account_key_file" required:"false" cty:"service_account_key_file" hcl:"service_account_key_file"`
|
|
||||||
Bucket *string `mapstructure:"bucket" required:"false" cty:"bucket" hcl:"bucket"`
|
Bucket *string `mapstructure:"bucket" required:"false" cty:"bucket" hcl:"bucket"`
|
||||||
ObjectName *string `mapstructure:"object_name" required:"false" cty:"object_name" hcl:"object_name"`
|
ObjectName *string `mapstructure:"object_name" required:"false" cty:"object_name" hcl:"object_name"`
|
||||||
SkipClean *bool `mapstructure:"skip_clean" required:"false" cty:"skip_clean" hcl:"skip_clean"`
|
SkipClean *bool `mapstructure:"skip_clean" required:"false" cty:"skip_clean" hcl:"skip_clean"`
|
||||||
|
@ -48,10 +50,12 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
|
||||||
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, 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_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},
|
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
|
||||||
|
"endpoint": &hcldec.AttrSpec{Name: "endpoint", Type: cty.String, Required: false},
|
||||||
|
"service_account_key_file": &hcldec.AttrSpec{Name: "service_account_key_file", Type: cty.String, Required: false},
|
||||||
|
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
||||||
|
"max_retries": &hcldec.AttrSpec{Name: "max_retries", Type: cty.Number, Required: false},
|
||||||
"folder_id": &hcldec.AttrSpec{Name: "folder_id", Type: cty.String, Required: false},
|
"folder_id": &hcldec.AttrSpec{Name: "folder_id", Type: cty.String, Required: false},
|
||||||
"service_account_id": &hcldec.AttrSpec{Name: "service_account_id", Type: cty.String, Required: false},
|
"service_account_id": &hcldec.AttrSpec{Name: "service_account_id", Type: cty.String, Required: false},
|
||||||
"token": &hcldec.AttrSpec{Name: "token", Type: cty.String, Required: false},
|
|
||||||
"service_account_key_file": &hcldec.AttrSpec{Name: "service_account_key_file", Type: cty.String, Required: false},
|
|
||||||
"bucket": &hcldec.AttrSpec{Name: "bucket", Type: cty.String, Required: false},
|
"bucket": &hcldec.AttrSpec{Name: "bucket", Type: cty.String, Required: false},
|
||||||
"object_name": &hcldec.AttrSpec{Name: "object_name", Type: cty.String, Required: false},
|
"object_name": &hcldec.AttrSpec{Name: "object_name", Type: cty.String, Required: false},
|
||||||
"skip_clean": &hcldec.AttrSpec{Name: "skip_clean", Type: cty.Bool, Required: false},
|
"skip_clean": &hcldec.AttrSpec{Name: "skip_clean", Type: cty.Bool, Required: false},
|
||||||
|
|
|
@ -67,12 +67,15 @@ can be configured for this builder.
|
||||||
|
|
||||||
### Required:
|
### Required:
|
||||||
|
|
||||||
|
@include 'builder/yandex/AccessConfig-required.mdx'
|
||||||
|
|
||||||
@include 'builder/yandex/Config-required.mdx'
|
@include 'builder/yandex/Config-required.mdx'
|
||||||
|
|
||||||
### Optional:
|
### Optional:
|
||||||
|
|
||||||
@include 'builder/yandex/Config-not-required.mdx'
|
@include 'builder/yandex/AccessConfig-not-required.mdx'
|
||||||
|
|
||||||
|
@include 'builder/yandex/Config-not-required.mdx'
|
||||||
|
|
||||||
## Build template data
|
## Build template data
|
||||||
|
|
||||||
|
|
|
@ -33,10 +33,14 @@ image.
|
||||||
|
|
||||||
### Required:
|
### Required:
|
||||||
|
|
||||||
|
@include 'builder/yandex/AccessConfig-required.mdx'
|
||||||
|
|
||||||
@include 'post-processor/yandex-export/Config-required.mdx'
|
@include 'post-processor/yandex-export/Config-required.mdx'
|
||||||
|
|
||||||
### Optional:
|
### Optional:
|
||||||
|
|
||||||
|
@include 'builder/yandex/AccessConfig-not-required.mdx'
|
||||||
|
|
||||||
@include 'post-processor/yandex-export/Config-not-required.mdx'
|
@include 'post-processor/yandex-export/Config-not-required.mdx'
|
||||||
|
|
||||||
## Basic Example
|
## Basic Example
|
||||||
|
|
|
@ -25,10 +25,14 @@ file.
|
||||||
|
|
||||||
### Required:
|
### Required:
|
||||||
|
|
||||||
|
@include 'builder/yandex/AccessConfig-required.mdx'
|
||||||
|
|
||||||
@include 'post-processor/yandex-import/Config-required.mdx'
|
@include 'post-processor/yandex-import/Config-required.mdx'
|
||||||
|
|
||||||
### Optional:
|
### Optional:
|
||||||
|
|
||||||
|
@include 'builder/yandex/AccessConfig-not-required.mdx'
|
||||||
|
|
||||||
@include 'post-processor/yandex-import/Config-not-required.mdx'
|
@include 'post-processor/yandex-import/Config-not-required.mdx'
|
||||||
|
|
||||||
## Basic Example
|
## Basic Example
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!-- Code generated from the comments of the AccessConfig struct in builder/yandex/access_config.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
|
- `endpoint` (string) - Non standard API endpoint. Default is `api.cloud.yandex.net:443`.
|
||||||
|
|
||||||
|
- `service_account_key_file` (string) - Path to file with Service Account key in json format. This
|
||||||
|
is an alternative method to authenticate to Yandex.Cloud. Alternatively you may set environment variable
|
||||||
|
`YC_SERVICE_ACCOUNT_KEY_FILE`.
|
||||||
|
|
||||||
|
- `max_retries` (int) - The maximum number of times an API request is being executed.
|
|
@ -0,0 +1,4 @@
|
||||||
|
<!-- Code generated from the comments of the AccessConfig struct in builder/yandex/access_config.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
|
- `token` (string) - OAuth token to use to authenticate to Yandex.Cloud. Alternatively you may set
|
||||||
|
value by environment variable `YC_TOKEN`.
|
|
@ -0,0 +1,3 @@
|
||||||
|
<!-- Code generated from the comments of the AccessConfig struct in builder/yandex/access_config.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
|
AccessConfig is for common configuration related to Yandex.Cloud API access
|
|
@ -1,12 +1,6 @@
|
||||||
<!-- Code generated from the comments of the Config struct in builder/yandex/config.go; DO NOT EDIT MANUALLY -->
|
<!-- Code generated from the comments of the Config struct in builder/yandex/config.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
- `endpoint` (string) - Non standard api endpoint URL.
|
- `service_account_id` (string) - Service account identifier to assign to instance.
|
||||||
|
|
||||||
- `service_account_key_file` (string) - Path to file with Service Account key in json format. This
|
|
||||||
is an alternative method to authenticate to Yandex.Cloud. Alternatively you may set environment variable
|
|
||||||
YC_SERVICE_ACCOUNT_KEY_FILE.
|
|
||||||
|
|
||||||
- `service_account_id` (string) - Service account identifier to assign to instance
|
|
||||||
|
|
||||||
- `disk_name` (string) - The name of the disk, if unset the instance name
|
- `disk_name` (string) - The name of the disk, if unset the instance name
|
||||||
will be used.
|
will be used.
|
||||||
|
@ -19,8 +13,7 @@
|
||||||
|
|
||||||
- `image_family` (string) - The family name of the resulting image.
|
- `image_family` (string) - The family name of the resulting image.
|
||||||
|
|
||||||
- `image_labels` (map[string]string) - Key/value pair labels to
|
- `image_labels` (map[string]string) - Key/value pair labels to apply to the created image.
|
||||||
apply to the created image.
|
|
||||||
|
|
||||||
- `image_min_disk_size_gb` (int) - Minimum size of the disk that will be created from built image, specified in gigabytes.
|
- `image_min_disk_size_gb` (int) - Minimum size of the disk that will be created from built image, specified in gigabytes.
|
||||||
Should be more or equal to `disk_size_gb`.
|
Should be more or equal to `disk_size_gb`.
|
||||||
|
@ -38,16 +31,14 @@
|
||||||
|
|
||||||
- `instance_name` (string) - The name assigned to the instance.
|
- `instance_name` (string) - The name assigned to the instance.
|
||||||
|
|
||||||
- `labels` (map[string]string) - Key/value pair labels to apply to
|
- `labels` (map[string]string) - Key/value pair labels to apply to the launched instance.
|
||||||
the launched instance.
|
|
||||||
|
|
||||||
- `platform_id` (string) - Identifier of the hardware platform configuration for the instance. This defaults to `standard-v1`.
|
- `platform_id` (string) - Identifier of the hardware platform configuration for the instance. This defaults to `standard-v1`.
|
||||||
|
|
||||||
- `max_retries` (int) - The maximum number of times an API request is being executed
|
|
||||||
|
|
||||||
- `metadata` (map[string]string) - Metadata applied to the launched instance.
|
- `metadata` (map[string]string) - Metadata applied to the launched instance.
|
||||||
|
|
||||||
- `metadata_from_file` (map[string]string) - Metadata applied to the launched instance. Value are file paths.
|
- `metadata_from_file` (map[string]string) - Metadata applied to the launched instance.
|
||||||
|
The values in this map are the paths to the content files for the corresponding metadata keys.
|
||||||
|
|
||||||
- `preemptible` (bool) - Launch a preemptible instance. This defaults to `false`.
|
- `preemptible` (bool) - Launch a preemptible instance. This defaults to `false`.
|
||||||
|
|
||||||
|
@ -55,8 +46,7 @@
|
||||||
|
|
||||||
- `source_image_folder_id` (string) - The ID of the folder containing the source image.
|
- `source_image_folder_id` (string) - The ID of the folder containing the source image.
|
||||||
|
|
||||||
- `source_image_id` (string) - The source image ID to use to create the new image
|
- `source_image_id` (string) - The source image ID to use to create the new image from.
|
||||||
from.
|
|
||||||
|
|
||||||
- `source_image_name` (string) - The source image name to use to create the new image
|
- `source_image_name` (string) - The source image name to use to create the new image
|
||||||
from. Name will be looked up in `source_image_folder_id`.
|
from. Name will be looked up in `source_image_folder_id`.
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
<!-- Code generated from the comments of the Config struct in builder/yandex/config.go; DO NOT EDIT MANUALLY -->
|
<!-- Code generated from the comments of the Config struct in builder/yandex/config.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
- `folder_id` (string) - The folder ID that will be used to launch instances and store images.
|
- `folder_id` (string) - The folder ID that will be used to launch instances and store images.
|
||||||
Alternatively you may set value by environment variable YC_FOLDER_ID.
|
Alternatively you may set value by environment variable `YC_FOLDER_ID`.
|
||||||
To use a different folder for looking up the source image or saving the target image to
|
To use a different folder for looking up the source image or saving the target image to
|
||||||
check options 'source_image_folder_id' and 'target_image_folder_id'.
|
check options 'source_image_folder_id' and 'target_image_folder_id'.
|
||||||
|
|
||||||
- `token` (string) - OAuth token to use to authenticate to Yandex.Cloud. Alternatively you may set
|
|
||||||
value by environment variable YC_TOKEN.
|
|
||||||
|
|
||||||
- `source_image_family` (string) - The source image family to create the new image
|
- `source_image_family` (string) - The source image family to create the new image
|
||||||
from. You can also specify source_image_id instead. Just one of a source_image_id or
|
from. You can also specify source_image_id instead. Just one of a source_image_id or
|
||||||
source_image_family must be specified. Example: `ubuntu-1804-lts`
|
source_image_family must be specified. Example: `ubuntu-1804-lts`.
|
||||||
|
|
|
@ -11,10 +11,3 @@
|
||||||
zone in which the VM is launched.
|
zone in which the VM is launched.
|
||||||
|
|
||||||
- `zone` (string) - The name of the zone to launch the instance. This defaults to `ru-central1-a`.
|
- `zone` (string) - The name of the zone to launch the instance. This defaults to `ru-central1-a`.
|
||||||
|
|
||||||
- `token` (string) - OAuth token to use to authenticate to Yandex.Cloud. Alternatively you may set
|
|
||||||
value by environment variable YC_TOKEN.
|
|
||||||
|
|
||||||
- `service_account_key_file` (string) - Path to file with Service Account key in json format. This
|
|
||||||
is an alternative method to authenticate to Yandex.Cloud. Alternatively you may set environment variable
|
|
||||||
YC_SERVICE_ACCOUNT_KEY_FILE.
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
Paths to Yandex Object Storage where exported image will be uploaded.
|
Paths to Yandex Object Storage where exported image will be uploaded.
|
||||||
|
|
||||||
- `folder_id` (string) - The folder ID that will be used to launch a temporary instance.
|
- `folder_id` (string) - The folder ID that will be used to launch a temporary instance.
|
||||||
Alternatively you may set value by environment variable YC_FOLDER_ID.
|
Alternatively you may set value by environment variable `YC_FOLDER_ID`.
|
||||||
|
|
||||||
- `service_account_id` (string) - Service Account ID with proper permission to modify an instance, create and attach disk and
|
- `service_account_id` (string) - Service Account ID with proper permission to modify an instance, create and attach disk and
|
||||||
make upload to specific Yandex Object Storage paths.
|
make upload to specific Yandex Object Storage paths.
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
<!-- Code generated from the comments of the Config struct in post-processor/yandex-import/post-processor.go; DO NOT EDIT MANUALLY -->
|
<!-- Code generated from the comments of the Config struct in post-processor/yandex-import/post-processor.go; DO NOT EDIT MANUALLY -->
|
||||||
|
|
||||||
- `token` (string) - OAuth token to use to authenticate to Yandex.Cloud.
|
|
||||||
|
|
||||||
- `service_account_key_file` (string) - Path to file with Service Account key in json format. This
|
|
||||||
is an alternative method to authenticate to Yandex.Cloud.
|
|
||||||
|
|
||||||
- `bucket` (string) - The name of the bucket where the qcow2 file will be uploaded to for import.
|
- `bucket` (string) - The name of the bucket where the qcow2 file will be uploaded to for import.
|
||||||
This bucket must exist when the post-processor is run.
|
This bucket must exist when the post-processor is run.
|
||||||
|
|
||||||
|
@ -17,7 +12,7 @@
|
||||||
|
|
||||||
- `skip_clean` (bool) - Whether skip removing the qcow2 file uploaded to Storage
|
- `skip_clean` (bool) - Whether skip removing the qcow2 file uploaded to Storage
|
||||||
after the import process has completed. Possible values are: `true` to
|
after the import process has completed. Possible values are: `true` to
|
||||||
leave it in the bucket, `false` to remove it. (Default: `false`).
|
leave it in the bucket, `false` to remove it. Default is `false`.
|
||||||
|
|
||||||
- `image_name` (string) - The name of the image, which contains 1-63 characters and only
|
- `image_name` (string) - The name of the image, which contains 1-63 characters and only
|
||||||
supports lowercase English characters, numbers and hyphen.
|
supports lowercase English characters, numbers and hyphen.
|
||||||
|
|
|
@ -3,4 +3,4 @@
|
||||||
- `folder_id` (string) - The folder ID that will be used to store imported Image.
|
- `folder_id` (string) - The folder ID that will be used to store imported Image.
|
||||||
|
|
||||||
- `service_account_id` (string) - Service Account ID with proper permission to use Storage service
|
- `service_account_id` (string) - Service Account ID with proper permission to use Storage service
|
||||||
for operations 'upload' and 'delete' object to `bucket`
|
for operations 'upload' and 'delete' object to `bucket`.
|
||||||
|
|
Loading…
Reference in New Issue