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 }