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  }