2019-05-31 08:27:41 -04:00
//go:generate struct-markdown
2019-10-14 10:43:59 -04:00
//go:generate mapstructure-to-hcl2 -type Config
2019-05-31 08:27:41 -04:00
2017-04-06 05:19:17 -04:00
package scaleway
import (
"errors"
"fmt"
2018-11-09 11:47:22 -05:00
"log"
2017-04-06 10:37:06 -04:00
"os"
2017-04-06 05:19:17 -04:00
2020-11-09 20:09:32 -05:00
"github.com/hashicorp/packer/builder/scaleway/version"
2020-11-12 17:44:02 -05:00
"github.com/hashicorp/packer/packer-plugin-sdk/common"
2020-12-01 18:30:31 -05:00
"github.com/hashicorp/packer/packer-plugin-sdk/communicator"
2020-11-19 15:07:02 -05:00
packersdk "github.com/hashicorp/packer/packer-plugin-sdk/packer"
2020-11-18 13:34:59 -05:00
"github.com/hashicorp/packer/packer-plugin-sdk/template/config"
2020-11-11 13:21:37 -05:00
"github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate"
2020-11-18 14:40:06 -05:00
"github.com/hashicorp/packer/packer-plugin-sdk/useragent"
2020-11-12 17:44:02 -05:00
"github.com/hashicorp/packer/packer-plugin-sdk/uuid"
2017-04-06 05:19:17 -04:00
"github.com/mitchellh/mapstructure"
2020-09-09 04:27:48 -04:00
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
2017-04-06 05:19:17 -04:00
)
type Config struct {
common . PackerConfig ` mapstructure:",squash" `
Comm communicator . Config ` mapstructure:",squash" `
2020-09-09 04:27:48 -04:00
// The AccessKey corresponding to the secret key.
2020-10-29 12:45:03 -04:00
// Will be fetched first from the [scaleway configuration file](https://github.com/scaleway/scaleway-sdk-go/blob/master/scw/README.md).
2020-09-09 04:27:48 -04:00
// It can also be specified via the environment variable SCW_ACCESS_KEY.
AccessKey string ` mapstructure:"access_key" required:"true" `
// The SecretKey to authenticate against the Scaleway API.
2020-10-29 12:45:03 -04:00
// Will be fetched first from the [scaleway configuration file](https://github.com/scaleway/scaleway-sdk-go/blob/master/scw/README.md).
2020-09-09 04:27:48 -04:00
// It can also be specified via the environment variable SCW_SECRET_KEY.
SecretKey string ` mapstructure:"secret_key" required:"true" `
// The Project ID in which the instances, volumes and snapshots will be created.
2020-10-29 12:45:03 -04:00
// Will be fetched first from the [scaleway configuration file](https://github.com/scaleway/scaleway-sdk-go/blob/master/scw/README.md).
2020-09-09 04:27:48 -04:00
// It can also be specified via the environment variable SCW_DEFAULT_PROJECT_ID.
ProjectID string ` mapstructure:"project_id" required:"true" `
// The Zone in which the instances, volumes and snapshots will be created.
2020-10-29 12:45:03 -04:00
// Will be fetched first from the [scaleway configuration file](https://github.com/scaleway/scaleway-sdk-go/blob/master/scw/README.md).
2020-09-09 04:27:48 -04:00
// It can also be specified via the environment variable SCW_DEFAULT_ZONE
Zone string ` mapstructure:"zone" required:"true" `
// The Scaleway API URL to use
2020-10-29 12:45:03 -04:00
// Will be fetched first from the [scaleway configuration file](https://github.com/scaleway/scaleway-sdk-go/blob/master/scw/README.md).
2020-09-09 04:27:48 -04:00
// It can also be specified via the environment variable SCW_API_URL
APIURL string ` mapstructure:"api_url" `
2019-05-28 11:50:58 -04:00
// The UUID of the base image to use. This is the image
2019-06-06 10:29:25 -04:00
// that will be used to launch a new server and provision it. See
// the images list
// get the complete list of the accepted image UUID.
2020-10-07 10:04:00 -04:00
// The marketplace image label (eg `ubuntu_focal`) also works.
2019-06-06 10:29:25 -04:00
Image string ` mapstructure:"image" required:"true" `
2019-05-28 11:50:58 -04:00
// The name of the server commercial type:
2020-10-07 06:02:08 -04:00
// C1, C2L, C2M, C2S, DEV1-S, DEV1-M, DEV1-L, DEV1-XL,
// GP1-XS, GP1-S, GP1-M, GP1-L, GP1-XL, RENDER-S
2019-05-28 11:50:58 -04:00
CommercialType string ` mapstructure:"commercial_type" required:"true" `
// The name of the resulting snapshot that will
2019-06-06 10:29:25 -04:00
// appear in your account. Default packer-TIMESTAMP
2019-05-28 11:50:58 -04:00
SnapshotName string ` mapstructure:"snapshot_name" required:"false" `
// The name of the resulting image that will appear in
2019-06-06 10:29:25 -04:00
// your account. Default packer-TIMESTAMP
ImageName string ` mapstructure:"image_name" required:"false" `
2019-05-28 11:50:58 -04:00
// The name assigned to the server. Default
2019-06-06 10:29:25 -04:00
// packer-UUID
ServerName string ` mapstructure:"server_name" required:"false" `
2019-05-28 11:50:58 -04:00
// The id of an existing bootscript to use when
2019-06-06 10:29:25 -04:00
// booting the server.
Bootscript string ` mapstructure:"bootscript" required:"false" `
2019-05-28 11:50:58 -04:00
// The type of boot, can be either local or
2019-06-06 10:29:25 -04:00
// bootscript, Default bootscript
BootType string ` mapstructure:"boottype" required:"false" `
2017-04-06 05:19:17 -04:00
2019-07-18 16:42:18 -04:00
RemoveVolume bool ` mapstructure:"remove_volume" `
2020-07-31 11:22:55 -04:00
UserAgent string ` mapstructure-to-hcl2:",skip" `
2017-04-06 05:19:17 -04:00
ctx interpolate . Context
2020-09-09 04:27:48 -04:00
// Deprecated configs
// The token to use to authenticate with your account.
// It can also be specified via environment variable SCALEWAY_API_TOKEN. You
// can see and generate tokens in the "Credentials"
// section of the control panel.
// Deprecated, use SecretKey instead
Token string ` mapstructure:"api_token" required:"false" `
// The organization id to use to identify your
// organization. It can also be specified via environment variable
// SCALEWAY_ORGANIZATION. Your organization id is available in the
// "Account" section of the
// control panel.
// Previously named: api_access_key with environment variable: SCALEWAY_API_ACCESS_KEY
// Deprecated, use ProjectID instead
Organization string ` mapstructure:"organization_id" required:"false" `
// The name of the region to launch the server in (par1
// or ams1). Consequently, this is the region where the snapshot will be
// available.
// Deprecated, use Zone instead
Region string ` mapstructure:"region" required:"false" `
2017-04-06 05:19:17 -04:00
}
2019-12-17 05:25:56 -05:00
func ( c * Config ) Prepare ( raws ... interface { } ) ( [ ] string , error ) {
2017-04-06 05:19:17 -04:00
var md mapstructure . Metadata
err := config . Decode ( c , & config . DecodeOpts {
Metadata : & md ,
2020-10-21 19:07:18 -04:00
PluginType : BuilderId ,
2017-04-06 05:19:17 -04:00
Interpolate : true ,
InterpolateContext : & c . ctx ,
InterpolateFilter : & interpolate . RenderFilter {
Exclude : [ ] string {
"run_command" ,
} ,
} ,
} , raws ... )
if err != nil {
2019-12-17 05:25:56 -05:00
return nil , err
2017-04-06 05:19:17 -04:00
}
2020-09-09 04:27:48 -04:00
var warnings [ ] string
2020-11-09 20:09:32 -05:00
c . UserAgent = useragent . String ( version . ScalewayPluginVersion . FormattedVersion ( ) )
2017-04-06 05:19:17 -04:00
2020-10-28 12:46:40 -04:00
configFile , err := scw . LoadConfig ( )
// If the config file do not exist, don't return an error as we may find config in ENV or flags.
if _ , isNotFoundError := err . ( * scw . ConfigFileNotFoundError ) ; isNotFoundError {
configFile = & scw . Config { }
} else if err != nil {
return nil , err
2017-04-06 10:37:06 -04:00
}
2020-10-28 12:46:40 -04:00
activeProfile , err := configFile . GetActiveProfile ( )
if err != nil {
return nil , err
2020-09-09 04:27:48 -04:00
}
2020-10-28 12:46:40 -04:00
envProfile := scw . LoadEnvProfile ( )
profile := scw . MergeProfiles ( activeProfile , envProfile )
2020-09-09 04:27:48 -04:00
// Deprecated variables
2017-04-06 10:37:06 -04:00
if c . Organization == "" {
2018-11-09 11:47:22 -05:00
if os . Getenv ( "SCALEWAY_ORGANIZATION" ) != "" {
c . Organization = os . Getenv ( "SCALEWAY_ORGANIZATION" )
} else {
log . Printf ( "Deprecation warning: Use SCALEWAY_ORGANIZATION environment variable and organization_id argument instead of api_access_key argument and SCALEWAY_API_ACCESS_KEY environment variable." )
c . Organization = os . Getenv ( "SCALEWAY_API_ACCESS_KEY" )
}
2017-04-06 10:37:06 -04:00
}
2020-09-09 04:27:48 -04:00
if c . Organization != "" {
warnings = append ( warnings , "organization_id is deprecated in favor of project_id" )
c . ProjectID = c . Organization
}
2017-04-06 10:37:06 -04:00
if c . Token == "" {
c . Token = os . Getenv ( "SCALEWAY_API_TOKEN" )
}
2020-09-09 04:27:48 -04:00
if c . Token != "" {
warnings = append ( warnings , "token is deprecated in favor of secret_key" )
c . SecretKey = c . Token
}
if c . Region != "" {
warnings = append ( warnings , "region is deprecated in favor of zone" )
c . Zone = c . Region
}
if c . AccessKey == "" {
2020-10-29 06:09:04 -04:00
if profile . AccessKey != nil {
c . AccessKey = * profile . AccessKey
}
2020-09-09 04:27:48 -04:00
}
if c . SecretKey == "" {
2020-10-29 06:09:04 -04:00
if profile . SecretKey != nil {
c . SecretKey = * profile . SecretKey
}
2020-09-09 04:27:48 -04:00
}
if c . ProjectID == "" {
2020-10-29 06:09:04 -04:00
if profile . DefaultProjectID != nil {
c . ProjectID = * profile . DefaultProjectID
}
2020-09-09 04:27:48 -04:00
}
if c . Zone == "" {
2020-10-29 06:09:04 -04:00
if profile . DefaultZone != nil {
c . Zone = * profile . DefaultZone
}
2020-09-09 04:27:48 -04:00
}
if c . APIURL == "" {
2020-10-29 06:09:04 -04:00
if profile . APIURL != nil {
c . APIURL = * profile . APIURL
}
2020-09-09 04:27:48 -04:00
}
2017-04-06 10:37:06 -04:00
2017-04-06 05:19:17 -04:00
if c . SnapshotName == "" {
2017-04-11 06:19:28 -04:00
def , err := interpolate . Render ( "snapshot-packer-{{timestamp}}" , nil )
2017-04-06 05:19:17 -04:00
if err != nil {
panic ( err )
}
c . SnapshotName = def
}
2017-04-11 06:19:28 -04:00
if c . ImageName == "" {
def , err := interpolate . Render ( "image-packer-{{timestamp}}" , nil )
if err != nil {
panic ( err )
}
c . ImageName = def
}
2017-04-06 05:19:17 -04:00
if c . ServerName == "" {
// Default to packer-[time-ordered-uuid]
c . ServerName = fmt . Sprintf ( "packer-%s" , uuid . TimeOrderedUUID ( ) )
}
2018-09-27 10:27:33 -04:00
if c . BootType == "" {
2020-09-09 04:27:48 -04:00
c . BootType = instance . BootTypeLocal . String ( )
2018-09-27 10:27:33 -04:00
}
2020-11-19 15:07:02 -05:00
var errs * packersdk . MultiError
2017-04-06 05:19:17 -04:00
if es := c . Comm . Prepare ( & c . ctx ) ; len ( es ) > 0 {
2020-11-19 15:07:02 -05:00
errs = packersdk . MultiErrorAppend ( errs , es ... )
2017-04-06 05:19:17 -04:00
}
2020-09-09 04:27:48 -04:00
if c . ProjectID == "" {
2020-11-19 15:07:02 -05:00
errs = packersdk . MultiErrorAppend (
2020-10-29 06:09:04 -04:00
errs , errors . New ( "scaleway Project ID must be specified" ) )
2017-04-06 05:19:17 -04:00
}
2020-09-09 04:27:48 -04:00
if c . SecretKey == "" {
2020-11-19 15:07:02 -05:00
errs = packersdk . MultiErrorAppend (
2020-10-29 06:09:04 -04:00
errs , errors . New ( "scaleway Secret Key must be specified" ) )
2020-09-09 04:27:48 -04:00
}
if c . AccessKey == "" {
warnings = append ( warnings , "access_key will be required in future versions" )
c . AccessKey = "SCWXXXXXXXXXXXXXXXXX"
2017-04-06 05:19:17 -04:00
}
2020-09-09 04:27:48 -04:00
if c . Zone == "" {
2020-11-19 15:07:02 -05:00
errs = packersdk . MultiErrorAppend (
errs , errors . New ( "Scaleway Zone is required" ) )
2017-04-06 05:19:17 -04:00
}
if c . CommercialType == "" {
2020-11-19 15:07:02 -05:00
errs = packersdk . MultiErrorAppend (
2017-04-06 05:19:17 -04:00
errs , errors . New ( "commercial type is required" ) )
}
if c . Image == "" {
2020-11-19 15:07:02 -05:00
errs = packersdk . MultiErrorAppend (
2017-04-06 05:19:17 -04:00
errs , errors . New ( "image is required" ) )
}
if errs != nil && len ( errs . Errors ) > 0 {
2020-09-09 04:27:48 -04:00
return warnings , errs
2017-04-06 05:19:17 -04:00
}
2020-11-19 17:03:11 -05:00
packersdk . LogSecretFilter . Set ( c . Token )
packersdk . LogSecretFilter . Set ( c . SecretKey )
2020-09-09 04:27:48 -04:00
return warnings , nil
2017-04-06 05:19:17 -04:00
}