packer-cn/builder/oracle/classic/config.go

156 lines
4.8 KiB
Go
Raw Normal View History

2018-01-12 17:12:15 -05:00
package classic
import (
"encoding/json"
2018-01-12 17:12:15 -05:00
"fmt"
"io/ioutil"
2018-01-12 18:44:40 -05:00
"net/url"
"os"
2018-03-30 16:01:48 -04:00
"regexp"
"time"
2018-01-12 17:12:15 -05:00
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
2018-01-18 18:52:31 -05:00
"github.com/hashicorp/packer/packer"
2018-01-12 17:12:15 -05:00
"github.com/hashicorp/packer/template/interpolate"
)
type Config struct {
common.PackerConfig `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
attribs map[string]interface{}
2018-01-12 17:12:15 -05:00
// Access config overrides
Username string `mapstructure:"username"`
Password string `mapstructure:"password"`
IdentityDomain string `mapstructure:"identity_domain"`
APIEndpoint string `mapstructure:"api_endpoint"`
2018-01-12 18:44:40 -05:00
apiEndpointURL *url.URL
2018-01-12 17:12:15 -05:00
// Image
ImageName string `mapstructure:"image_name"`
Shape string `mapstructure:"shape"`
SourceImageList string `mapstructure:"source_image_list"`
SnapshotTimeout time.Duration `mapstructure:"snapshot_timeout"`
DestImageList string `mapstructure:"dest_image_list"`
2018-03-13 03:12:16 -04:00
// Attributes and Attributes file are both optional and mutually exclusive.
Attributes string `mapstructure:"attributes"`
AttributesFile string `mapstructure:"attributes_file"`
// Optional; if you don't enter anything, the image list description
// will read "Packer-built image list"
DestImageListDescription string `mapstructure:"image_description"`
// Optional. Describes what computers are allowed to reach your instance
// via SSH. This whitelist must contain the computer you're running Packer
// from. It defaults to public-internet, meaning that you can SSH into your
// instance from anywhere as long as you have the right keys
SSHSourceList string `mapstructure:"ssh_source_list"`
2018-01-12 17:12:15 -05:00
ctx interpolate.Context
}
func NewConfig(raws ...interface{}) (*Config, error) {
c := &Config{}
// Decode from template
err := config.Decode(c, &config.DecodeOpts{
Interpolate: true,
InterpolateContext: &c.ctx,
}, raws...)
if err != nil {
return nil, fmt.Errorf("Failed to mapstructure Config: %+v", err)
}
2018-01-12 18:44:40 -05:00
c.apiEndpointURL, err = url.Parse(c.APIEndpoint)
if err != nil {
return nil, fmt.Errorf("Error parsing API Endpoint: %s", err)
}
2018-01-26 17:28:27 -05:00
// Set default source list
if c.SSHSourceList == "" {
c.SSHSourceList = "seciplist:/oracle/public/public-internet"
}
2018-01-26 17:28:27 -05:00
// Use default oracle username with sudo privileges
if c.Comm.SSHUsername == "" {
c.Comm.SSHUsername = "opc"
}
if c.SnapshotTimeout == 0 {
c.SnapshotTimeout = 20 * time.Minute
}
// Validate that all required fields are present
2018-01-18 18:52:31 -05:00
var errs *packer.MultiError
required := map[string]string{
"username": c.Username,
"password": c.Password,
"api_endpoint": c.APIEndpoint,
"identity_domain": c.IdentityDomain,
"source_image_list": c.SourceImageList,
2018-01-31 13:47:19 -05:00
"dest_image_list": c.DestImageList,
"shape": c.Shape,
}
for k, v := range required {
if v == "" {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("You must specify a %s.", k))
}
}
2018-03-30 16:01:48 -04:00
// Object names can contain only alphanumeric characters, hyphens, underscores, and periods
reValidObject := regexp.MustCompile("^[a-zA-Z0-9-._/]+$")
2018-04-02 14:12:07 -04:00
var objectValidation = []struct {
name string
value string
}{
{"dest_image_list", c.DestImageList},
{"image_name", c.ImageName},
}
for _, ov := range objectValidation {
if !reValidObject.MatchString(ov.value) {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("%s can contain only alphanumeric characters, hyphens, underscores, and periods.", ov.name))
}
2018-03-30 16:01:48 -04:00
}
if c.Attributes != "" && c.AttributesFile != "" {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("Only one of user_data or user_data_file can be specified."))
} else if c.AttributesFile != "" {
if _, err := os.Stat(c.AttributesFile); err != nil {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("attributes_file not found: %s", c.AttributesFile))
}
}
if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
errs = packer.MultiErrorAppend(errs, es...)
}
if errs != nil && len(errs.Errors) > 0 {
return nil, errs
}
// unpack attributes from json into config
var data map[string]interface{}
if c.Attributes != "" {
err := json.Unmarshal([]byte(c.Attributes), &data)
if err != nil {
err = fmt.Errorf("Problem parsing json from attributes: %s", err)
packer.MultiErrorAppend(errs, err)
}
c.attribs = data
} else if c.AttributesFile != "" {
fidata, err := ioutil.ReadFile(c.AttributesFile)
if err != nil {
err = fmt.Errorf("Problem reading attributes_file: %s", err)
packer.MultiErrorAppend(errs, err)
}
err = json.Unmarshal(fidata, &data)
c.attribs = data
if err != nil {
2018-03-13 03:12:16 -04:00
err = fmt.Errorf("Problem parsing json from attributes_file: %s", err)
packer.MultiErrorAppend(errs, err)
}
c.attribs = data
}
2018-01-12 17:12:15 -05:00
return c, nil
}