github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/builder/oracle/oci/config_test.go (about) 1 package oci 2 3 import ( 4 "crypto/rand" 5 "crypto/rsa" 6 "crypto/x509" 7 "encoding/pem" 8 "io/ioutil" 9 "os" 10 "strings" 11 "testing" 12 13 "github.com/go-ini/ini" 14 ) 15 16 func testConfig(accessConfFile *os.File) map[string]interface{} { 17 return map[string]interface{}{ 18 "availability_domain": "aaaa:PHX-AD-3", 19 "access_cfg_file": accessConfFile.Name(), 20 21 // Image 22 "base_image_ocid": "ocd1...", 23 "shape": "VM.Standard1.1", 24 "image_name": "HelloWorld", 25 26 // Networking 27 "subnet_ocid": "ocd1...", 28 29 // Comm 30 "ssh_username": "opc", 31 "use_private_ip": false, 32 } 33 } 34 35 func TestConfig(t *testing.T) { 36 // Shared set-up and defered deletion 37 38 cfg, keyFile, err := baseTestConfigWithTmpKeyFile() 39 if err != nil { 40 t.Fatal(err) 41 } 42 defer os.Remove(keyFile.Name()) 43 44 cfgFile, err := writeTestConfig(cfg) 45 if err != nil { 46 t.Fatal(err) 47 } 48 defer os.Remove(cfgFile.Name()) 49 50 // Temporarily set $HOME to temp directory to bypass default 51 // access config loading. 52 53 tmpHome, err := ioutil.TempDir("", "packer_config_test") 54 if err != nil { 55 t.Fatalf("Unexpected error when creating temporary directory: %+v", err) 56 } 57 defer os.Remove(tmpHome) 58 59 home := os.Getenv("HOME") 60 os.Setenv("HOME", tmpHome) 61 defer os.Setenv("HOME", home) 62 63 // Config tests 64 t.Run("BaseConfig", func(t *testing.T) { 65 raw := testConfig(cfgFile) 66 _, errs := NewConfig(raw) 67 68 if errs != nil { 69 t.Fatalf("Unexpected error in configuration %+v", errs) 70 } 71 }) 72 73 t.Run("NoAccessConfig", func(t *testing.T) { 74 raw := testConfig(cfgFile) 75 delete(raw, "access_cfg_file") 76 77 _, errs := NewConfig(raw) 78 79 expectedErrors := []string{ 80 "'user_ocid'", "'tenancy_ocid'", "'fingerprint'", "'key_file'", 81 } 82 83 s := errs.Error() 84 for _, expected := range expectedErrors { 85 if !strings.Contains(s, expected) { 86 t.Errorf("Expected %q to contain '%s'", s, expected) 87 } 88 } 89 }) 90 91 t.Run("AccessConfigTemplateOnly", func(t *testing.T) { 92 raw := testConfig(cfgFile) 93 delete(raw, "access_cfg_file") 94 raw["user_ocid"] = "ocid1..." 95 raw["tenancy_ocid"] = "ocid1..." 96 raw["fingerprint"] = "00:00..." 97 raw["key_file"] = keyFile.Name() 98 99 _, errs := NewConfig(raw) 100 101 if errs != nil { 102 t.Fatalf("err: %+v", errs) 103 } 104 105 }) 106 107 t.Run("TenancyReadFromAccessCfgFile", func(t *testing.T) { 108 raw := testConfig(cfgFile) 109 c, errs := NewConfig(raw) 110 if errs != nil { 111 t.Fatalf("Unexpected error in configuration %+v", errs) 112 } 113 114 tenancy, err := c.ConfigProvider.TenancyOCID() 115 if err != nil { 116 t.Fatalf("Unexpected error getting tenancy ocid: %v", err) 117 } 118 119 expected := "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 120 if tenancy != expected { 121 t.Errorf("Expected tenancy: %s, got %s.", expected, tenancy) 122 } 123 124 }) 125 126 t.Run("RegionNotDefaultedToPHXWhenSetInOCISettings", func(t *testing.T) { 127 raw := testConfig(cfgFile) 128 c, errs := NewConfig(raw) 129 if errs != nil { 130 t.Fatalf("Unexpected error in configuration %+v", errs) 131 } 132 133 region, err := c.ConfigProvider.Region() 134 if err != nil { 135 t.Fatalf("Unexpected error getting region: %v", err) 136 } 137 138 expected := "us-ashburn-1" 139 if region != expected { 140 t.Errorf("Expected region: %s, got %s.", expected, region) 141 } 142 143 }) 144 145 // Test the correct errors are produced when required template keys are 146 // omitted. 147 requiredKeys := []string{"availability_domain", "base_image_ocid", "shape", "subnet_ocid"} 148 for _, k := range requiredKeys { 149 t.Run(k+"_required", func(t *testing.T) { 150 raw := testConfig(cfgFile) 151 delete(raw, k) 152 153 _, errs := NewConfig(raw) 154 155 if !strings.Contains(errs.Error(), k) { 156 t.Errorf("Expected '%s' to contain '%s'", errs.Error(), k) 157 } 158 }) 159 } 160 161 t.Run("ImageNameDefaultedIfEmpty", func(t *testing.T) { 162 raw := testConfig(cfgFile) 163 delete(raw, "image_name") 164 165 c, errs := NewConfig(raw) 166 if errs != nil { 167 t.Fatalf("Unexpected error in configuration %+v", errs) 168 } 169 170 if !strings.Contains(c.ImageName, "packer-") { 171 t.Errorf("got default ImageName %q, want image name 'packer-{{timestamp}}'", c.ImageName) 172 } 173 }) 174 175 t.Run("user_ocid_overridden", func(t *testing.T) { 176 expected := "override" 177 raw := testConfig(cfgFile) 178 raw["user_ocid"] = expected 179 180 c, errs := NewConfig(raw) 181 if errs != nil { 182 t.Fatalf("Unexpected error in configuration %+v", errs) 183 } 184 185 user, _ := c.ConfigProvider.UserOCID() 186 if user != expected { 187 t.Errorf("Expected ConfigProvider.UserOCID: %s, got %s", expected, user) 188 } 189 }) 190 191 t.Run("tenancy_ocid_overidden", func(t *testing.T) { 192 expected := "override" 193 raw := testConfig(cfgFile) 194 raw["tenancy_ocid"] = expected 195 196 c, errs := NewConfig(raw) 197 if errs != nil { 198 t.Fatalf("Unexpected error in configuration %+v", errs) 199 } 200 201 tenancy, _ := c.ConfigProvider.TenancyOCID() 202 if tenancy != expected { 203 t.Errorf("Expected ConfigProvider.TenancyOCID: %s, got %s", expected, tenancy) 204 } 205 }) 206 207 t.Run("region_overidden", func(t *testing.T) { 208 expected := "override" 209 raw := testConfig(cfgFile) 210 raw["region"] = expected 211 212 c, errs := NewConfig(raw) 213 if errs != nil { 214 t.Fatalf("Unexpected error in configuration %+v", errs) 215 } 216 217 region, _ := c.ConfigProvider.Region() 218 if region != expected { 219 t.Errorf("Expected ConfigProvider.Region: %s, got %s", expected, region) 220 } 221 }) 222 223 t.Run("fingerprint_overidden", func(t *testing.T) { 224 expected := "override" 225 raw := testConfig(cfgFile) 226 raw["fingerprint"] = expected 227 228 c, errs := NewConfig(raw) 229 if errs != nil { 230 t.Fatalf("Unexpected error in configuration: %+v", errs) 231 } 232 233 fingerprint, _ := c.ConfigProvider.KeyFingerprint() 234 if fingerprint != expected { 235 t.Errorf("Expected ConfigProvider.KeyFingerprint: %s, got %s", expected, fingerprint) 236 } 237 }) 238 } 239 240 // BaseTestConfig creates the base (DEFAULT) config including a temporary key 241 // file. 242 // NOTE: Caller is responsible for removing temporary key file. 243 func baseTestConfigWithTmpKeyFile() (*ini.File, *os.File, error) { 244 keyFile, err := generateRSAKeyFile() 245 if err != nil { 246 return nil, keyFile, err 247 } 248 // Build ini 249 cfg := ini.Empty() 250 section, _ := cfg.NewSection("DEFAULT") 251 section.NewKey("region", "us-ashburn-1") 252 section.NewKey("tenancy", "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") 253 section.NewKey("user", "ocid1.user.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") 254 section.NewKey("fingerprint", "70:04:5z:b3:19:ab:90:75:a4:1f:50:d4:c7:c3:33:20") 255 section.NewKey("key_file", keyFile.Name()) 256 257 return cfg, keyFile, nil 258 } 259 260 // WriteTestConfig writes a ini.File to a temporary file for use in unit tests. 261 // NOTE: Caller is responsible for removing temporary file. 262 func writeTestConfig(cfg *ini.File) (*os.File, error) { 263 confFile, err := ioutil.TempFile("", "config_file") 264 if err != nil { 265 return nil, err 266 } 267 268 if _, err := confFile.Write([]byte("[DEFAULT]\n")); err != nil { 269 os.Remove(confFile.Name()) 270 return nil, err 271 } 272 273 if _, err := cfg.WriteTo(confFile); err != nil { 274 os.Remove(confFile.Name()) 275 return nil, err 276 } 277 return confFile, nil 278 } 279 280 // generateRSAKeyFile generates an RSA key file for use in unit tests. 281 // NOTE: The caller is responsible for deleting the temporary file. 282 func generateRSAKeyFile() (*os.File, error) { 283 // Create temporary file for the key 284 f, err := ioutil.TempFile("", "key") 285 if err != nil { 286 return nil, err 287 } 288 289 // Generate key 290 priv, err := rsa.GenerateKey(rand.Reader, 2014) 291 if err != nil { 292 return nil, err 293 } 294 295 // ASN.1 DER encoded form 296 privDer := x509.MarshalPKCS1PrivateKey(priv) 297 privBlk := pem.Block{ 298 Type: "RSA PRIVATE KEY", 299 Headers: nil, 300 Bytes: privDer, 301 } 302 303 // Write the key out 304 if _, err := f.Write(pem.EncodeToMemory(&privBlk)); err != nil { 305 return nil, err 306 } 307 308 return f, nil 309 }