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