github.phpd.cn/hashicorp/packer@v1.3.2/builder/oracle/classic/config.go (about)

     1  package classic
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"net/url"
     8  	"os"
     9  	"regexp"
    10  	"time"
    11  
    12  	"github.com/hashicorp/packer/common"
    13  	"github.com/hashicorp/packer/helper/communicator"
    14  	"github.com/hashicorp/packer/helper/config"
    15  	"github.com/hashicorp/packer/packer"
    16  	"github.com/hashicorp/packer/template/interpolate"
    17  )
    18  
    19  type Config struct {
    20  	common.PackerConfig `mapstructure:",squash"`
    21  	Comm                communicator.Config `mapstructure:",squash"`
    22  	attribs             map[string]interface{}
    23  
    24  	// Access config overrides
    25  	Username       string `mapstructure:"username"`
    26  	Password       string `mapstructure:"password"`
    27  	IdentityDomain string `mapstructure:"identity_domain"`
    28  	APIEndpoint    string `mapstructure:"api_endpoint"`
    29  	apiEndpointURL *url.URL
    30  
    31  	// Image
    32  	ImageName       string        `mapstructure:"image_name"`
    33  	Shape           string        `mapstructure:"shape"`
    34  	SourceImageList string        `mapstructure:"source_image_list"`
    35  	SnapshotTimeout time.Duration `mapstructure:"snapshot_timeout"`
    36  	DestImageList   string        `mapstructure:"dest_image_list"`
    37  	// Attributes and Attributes file are both optional and mutually exclusive.
    38  	Attributes     string `mapstructure:"attributes"`
    39  	AttributesFile string `mapstructure:"attributes_file"`
    40  	// Optional; if you don't enter anything, the image list description
    41  	// will read "Packer-built image list"
    42  	DestImageListDescription string `mapstructure:"image_description"`
    43  	// Optional. Describes what computers are allowed to reach your instance
    44  	// via SSH. This whitelist must contain the computer you're running Packer
    45  	// from. It defaults to public-internet, meaning that you can SSH into your
    46  	// instance from anywhere as long as you have the right keys
    47  	SSHSourceList string `mapstructure:"ssh_source_list"`
    48  
    49  	ctx interpolate.Context
    50  }
    51  
    52  func NewConfig(raws ...interface{}) (*Config, error) {
    53  	c := &Config{}
    54  
    55  	// Decode from template
    56  	err := config.Decode(c, &config.DecodeOpts{
    57  		Interpolate:        true,
    58  		InterpolateContext: &c.ctx,
    59  	}, raws...)
    60  	if err != nil {
    61  		return nil, fmt.Errorf("Failed to mapstructure Config: %+v", err)
    62  	}
    63  
    64  	c.apiEndpointURL, err = url.Parse(c.APIEndpoint)
    65  	if err != nil {
    66  		return nil, fmt.Errorf("Error parsing API Endpoint: %s", err)
    67  	}
    68  	// Set default source list
    69  	if c.SSHSourceList == "" {
    70  		c.SSHSourceList = "seciplist:/oracle/public/public-internet"
    71  	}
    72  	// Use default oracle username with sudo privileges
    73  	if c.Comm.SSHUsername == "" {
    74  		c.Comm.SSHUsername = "opc"
    75  	}
    76  
    77  	if c.SnapshotTimeout == 0 {
    78  		c.SnapshotTimeout = 20 * time.Minute
    79  	}
    80  
    81  	// Validate that all required fields are present
    82  	var errs *packer.MultiError
    83  	required := map[string]string{
    84  		"username":          c.Username,
    85  		"password":          c.Password,
    86  		"api_endpoint":      c.APIEndpoint,
    87  		"identity_domain":   c.IdentityDomain,
    88  		"source_image_list": c.SourceImageList,
    89  		"dest_image_list":   c.DestImageList,
    90  		"shape":             c.Shape,
    91  	}
    92  	for k, v := range required {
    93  		if v == "" {
    94  			errs = packer.MultiErrorAppend(errs, fmt.Errorf("You must specify a %s.", k))
    95  		}
    96  	}
    97  
    98  	// Object names can contain only alphanumeric characters, hyphens, underscores, and periods
    99  	reValidObject := regexp.MustCompile("^[a-zA-Z0-9-._/]+$")
   100  	var objectValidation = []struct {
   101  		name  string
   102  		value string
   103  	}{
   104  		{"dest_image_list", c.DestImageList},
   105  		{"image_name", c.ImageName},
   106  	}
   107  	for _, ov := range objectValidation {
   108  		if !reValidObject.MatchString(ov.value) {
   109  			errs = packer.MultiErrorAppend(errs, fmt.Errorf("%s can contain only alphanumeric characters, hyphens, underscores, and periods.", ov.name))
   110  		}
   111  	}
   112  
   113  	if c.Attributes != "" && c.AttributesFile != "" {
   114  		errs = packer.MultiErrorAppend(errs, fmt.Errorf("Only one of user_data or user_data_file can be specified."))
   115  	} else if c.AttributesFile != "" {
   116  		if _, err := os.Stat(c.AttributesFile); err != nil {
   117  			errs = packer.MultiErrorAppend(errs, fmt.Errorf("attributes_file not found: %s", c.AttributesFile))
   118  		}
   119  	}
   120  
   121  	if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
   122  		errs = packer.MultiErrorAppend(errs, es...)
   123  	}
   124  
   125  	if errs != nil && len(errs.Errors) > 0 {
   126  		return nil, errs
   127  	}
   128  
   129  	// unpack attributes from json into config
   130  	var data map[string]interface{}
   131  
   132  	if c.Attributes != "" {
   133  		err := json.Unmarshal([]byte(c.Attributes), &data)
   134  		if err != nil {
   135  			err = fmt.Errorf("Problem parsing json from attributes: %s", err)
   136  			packer.MultiErrorAppend(errs, err)
   137  		}
   138  		c.attribs = data
   139  	} else if c.AttributesFile != "" {
   140  		fidata, err := ioutil.ReadFile(c.AttributesFile)
   141  		if err != nil {
   142  			err = fmt.Errorf("Problem reading attributes_file: %s", err)
   143  			packer.MultiErrorAppend(errs, err)
   144  		}
   145  		err = json.Unmarshal(fidata, &data)
   146  		c.attribs = data
   147  		if err != nil {
   148  			err = fmt.Errorf("Problem parsing json from attributes_file: %s", err)
   149  			packer.MultiErrorAppend(errs, err)
   150  		}
   151  		c.attribs = data
   152  	}
   153  
   154  	return c, nil
   155  }