github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/provider/joyent/config_test.go (about)

     1  // Copyright 2013 Joyent Inc.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package joyent_test
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  
    10  	"github.com/juju/testing"
    11  	jc "github.com/juju/testing/checkers"
    12  	"github.com/juju/utils"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/environs"
    16  	"github.com/juju/juju/environs/config"
    17  	envtesting "github.com/juju/juju/environs/testing"
    18  	jp "github.com/juju/juju/provider/joyent"
    19  	coretesting "github.com/juju/juju/testing"
    20  	"github.com/juju/juju/utils/ssh"
    21  )
    22  
    23  func newConfig(c *gc.C, attrs coretesting.Attrs) *config.Config {
    24  	attrs = coretesting.FakeConfig().Merge(attrs)
    25  	cfg, err := config.New(config.UseDefaults, attrs)
    26  	c.Assert(err, jc.ErrorIsNil)
    27  	return cfg
    28  }
    29  
    30  func validAttrs() coretesting.Attrs {
    31  	return coretesting.FakeConfig().Merge(coretesting.Attrs{
    32  		"type":             "joyent",
    33  		"sdc-user":         "test",
    34  		"sdc-key-id":       "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff",
    35  		"sdc-url":          "test://test.api.joyentcloud.com",
    36  		"manta-user":       "test",
    37  		"manta-key-id":     "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff",
    38  		"manta-url":        "test://test.manta.joyent.com",
    39  		"private-key-path": "~/.ssh/provider_id_rsa",
    40  		"algorithm":        "rsa-sha256",
    41  		"control-dir":      "juju-test",
    42  	})
    43  }
    44  
    45  type ConfigSuite struct {
    46  	coretesting.FakeJujuHomeSuite
    47  	originalValues map[string]testing.Restorer
    48  	privateKeyData string
    49  }
    50  
    51  var _ = gc.Suite(&ConfigSuite{})
    52  
    53  func (s *ConfigSuite) SetUpSuite(c *gc.C) {
    54  	s.FakeJujuHomeSuite.SetUpSuite(c)
    55  	restoreSdcAccount := testing.PatchEnvironment(jp.SdcAccount, "tester")
    56  	s.AddSuiteCleanup(func(*gc.C) { restoreSdcAccount() })
    57  	restoreSdcKeyId := testing.PatchEnvironment(jp.SdcKeyId, "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00")
    58  	s.AddSuiteCleanup(func(*gc.C) { restoreSdcKeyId() })
    59  	restoreMantaUser := testing.PatchEnvironment(jp.MantaUser, "tester")
    60  	s.AddSuiteCleanup(func(*gc.C) { restoreMantaUser() })
    61  	restoreMantaKeyId := testing.PatchEnvironment(jp.MantaKeyId, "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00")
    62  	s.AddSuiteCleanup(func(*gc.C) { restoreMantaKeyId() })
    63  	s.privateKeyData = generatePrivateKey(c)
    64  	jp.RegisterMachinesEndpoint()
    65  	s.AddSuiteCleanup(func(*gc.C) { jp.UnregisterMachinesEndpoint() })
    66  }
    67  
    68  func generatePrivateKey(c *gc.C) string {
    69  	oldBits := ssh.KeyBits
    70  	defer func() {
    71  		ssh.KeyBits = oldBits
    72  	}()
    73  	ssh.KeyBits = 32
    74  	private, _, err := ssh.GenerateKey("test-client")
    75  	c.Assert(err, jc.ErrorIsNil)
    76  	return private
    77  }
    78  
    79  func (s *ConfigSuite) SetUpTest(c *gc.C) {
    80  	s.FakeJujuHomeSuite.SetUpTest(c)
    81  	s.AddCleanup(CreateTestKey(c))
    82  	for _, envVar := range jp.EnvironmentVariables {
    83  		s.PatchEnvironment(envVar, "")
    84  	}
    85  }
    86  
    87  type configtest struct {
    88  	info    string
    89  	insert  coretesting.Attrs
    90  	remove  []string
    91  	envVars map[string]string
    92  	expect  coretesting.Attrs
    93  	err     string
    94  }
    95  
    96  var newConfigTests = []configtest{{
    97  	info:   "sdc-user is required",
    98  	remove: []string{"sdc-user"},
    99  	err:    ".* cannot get sdc-user value from environment variable .*",
   100  }, {
   101  	info:   "sdc-user cannot be empty",
   102  	insert: coretesting.Attrs{"sdc-user": ""},
   103  	err:    ".* cannot get sdc-user value from environment variable .*",
   104  }, {
   105  	info:   "can get sdc-user from env variable",
   106  	insert: coretesting.Attrs{"sdc-user": ""},
   107  	expect: coretesting.Attrs{"sdc-user": "tester"},
   108  	envVars: map[string]string{
   109  		"SDC_ACCOUNT": "tester",
   110  	},
   111  }, {
   112  	info:   "can get sdc-user from env variable, missing from config",
   113  	remove: []string{"sdc-user"},
   114  	expect: coretesting.Attrs{"sdc-user": "tester"},
   115  	envVars: map[string]string{
   116  		"SDC_ACCOUNT": "tester",
   117  	},
   118  }, {
   119  	info:   "sdc-key-id is required",
   120  	remove: []string{"sdc-key-id"},
   121  	err:    ".* cannot get sdc-key-id value from environment variable .*",
   122  }, {
   123  	info:   "sdc-key-id cannot be empty",
   124  	insert: coretesting.Attrs{"sdc-key-id": ""},
   125  	err:    ".* cannot get sdc-key-id value from environment variable .*",
   126  }, {
   127  	info:   "can get sdc-key-id from env variable",
   128  	insert: coretesting.Attrs{"sdc-key-id": ""},
   129  	expect: coretesting.Attrs{"sdc-key-id": "key"},
   130  	envVars: map[string]string{
   131  		"SDC_KEY_ID": "key",
   132  	},
   133  }, {
   134  	info:   "can get sdc-key-id from env variable, missing from config",
   135  	remove: []string{"sdc-key-id"},
   136  	expect: coretesting.Attrs{"sdc-key-id": "key"},
   137  	envVars: map[string]string{
   138  		"SDC_KEY_ID": "key",
   139  	},
   140  }, {
   141  	info:   "sdc-url is inserted if missing",
   142  	expect: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"},
   143  }, {
   144  	info:   "sdc-url cannot be empty",
   145  	insert: coretesting.Attrs{"sdc-url": ""},
   146  	err:    ".* cannot get sdc-url value from environment variable .*",
   147  }, {
   148  	info:   "sdc-url is untouched if present",
   149  	insert: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"},
   150  	expect: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"},
   151  }, {
   152  	info:   "manta-user is required",
   153  	remove: []string{"manta-user"},
   154  	err:    ".* cannot get manta-user value from environment variable .*",
   155  }, {
   156  	info:   "manta-user cannot be empty",
   157  	insert: coretesting.Attrs{"manta-user": ""},
   158  	err:    ".* cannot get manta-user value from environment variable .*",
   159  }, {
   160  	info:   "can get manta-user from env variable",
   161  	insert: coretesting.Attrs{"manta-user": ""},
   162  	expect: coretesting.Attrs{"manta-user": "tester"},
   163  	envVars: map[string]string{
   164  		"MANTA_USER": "tester",
   165  	},
   166  }, {
   167  	info:   "can get manta-user from env variable, missing from config",
   168  	remove: []string{"manta-user"},
   169  	expect: coretesting.Attrs{"manta-user": "tester"},
   170  	envVars: map[string]string{
   171  		"MANTA_USER": "tester",
   172  	},
   173  }, {
   174  	info:   "manta-key-id is required",
   175  	remove: []string{"manta-key-id"},
   176  	err:    ".* cannot get manta-key-id value from environment variable .*",
   177  }, {
   178  	info:   "manta-key-id cannot be empty",
   179  	insert: coretesting.Attrs{"manta-key-id": ""},
   180  	err:    ".* cannot get manta-key-id value from environment variable .*",
   181  }, {
   182  	info:   "can get manta-key-id from env variable",
   183  	insert: coretesting.Attrs{"manta-key-id": ""},
   184  	expect: coretesting.Attrs{"manta-key-id": "key"},
   185  	envVars: map[string]string{
   186  		"MANTA_KEY_ID": "key",
   187  	},
   188  }, {
   189  	info:   "can get manta-key-id from env variable, missing from config",
   190  	remove: []string{"manta-key-id"},
   191  	expect: coretesting.Attrs{"manta-key-id": "key"},
   192  	envVars: map[string]string{
   193  		"MANTA_KEY_ID": "key",
   194  	},
   195  }, {
   196  	info:   "manta-url is inserted if missing",
   197  	expect: coretesting.Attrs{"manta-url": "test://test.manta.joyent.com"},
   198  }, {
   199  	info:   "manta-url cannot be empty",
   200  	insert: coretesting.Attrs{"manta-url": ""},
   201  	err:    ".* cannot get manta-url value from environment variable .*",
   202  }, {
   203  	info:   "manta-url is untouched if present",
   204  	insert: coretesting.Attrs{"manta-url": "test://test.manta.joyent.com"},
   205  	expect: coretesting.Attrs{"manta-url": "test://test.manta.joyent.com"},
   206  }, {
   207  	info:   "can get private-key-path from env variable",
   208  	insert: coretesting.Attrs{"private-key-path": ""},
   209  	expect: coretesting.Attrs{"private-key-path": "some-file"},
   210  	envVars: map[string]string{
   211  		"MANTA_PRIVATE_KEY_FILE": "some-file",
   212  	},
   213  }, {
   214  	info:   "can get private-key-path from env variable, missing from config",
   215  	remove: []string{"private-key-path"},
   216  	expect: coretesting.Attrs{"private-key-path": "some-file"},
   217  	envVars: map[string]string{
   218  		"MANTA_PRIVATE_KEY_FILE": "some-file",
   219  	},
   220  }, {
   221  	info:   "algorithm is inserted if missing",
   222  	expect: coretesting.Attrs{"algorithm": "rsa-sha256"},
   223  }, {
   224  	info:   "algorithm cannot be empty",
   225  	insert: coretesting.Attrs{"algorithm": ""},
   226  	err:    ".* algorithm: must not be empty",
   227  }, {
   228  	info:   "unknown field is not touched",
   229  	insert: coretesting.Attrs{"unknown-field": 12345},
   230  	expect: coretesting.Attrs{"unknown-field": 12345},
   231  }, {
   232  	info:   "can specify just private-key",
   233  	remove: []string{"private-key-path"},
   234  	insert: coretesting.Attrs{"private-key": "foo"},
   235  }}
   236  
   237  func (s *ConfigSuite) TestNewEnvironConfig(c *gc.C) {
   238  	for i, test := range newConfigTests {
   239  		doTest(s, i, test, c)
   240  	}
   241  }
   242  
   243  func doTest(s *ConfigSuite, i int, test configtest, c *gc.C) {
   244  	c.Logf("test %d: %s", i, test.info)
   245  	for k, v := range test.envVars {
   246  		os.Setenv(k, v)
   247  		defer os.Setenv(k, "")
   248  	}
   249  	attrs := validAttrs().Merge(test.insert).Delete(test.remove...)
   250  	attrs["private-key"] = s.privateKeyData
   251  	testConfig := newConfig(c, attrs)
   252  	environ, err := environs.New(testConfig)
   253  	if test.err == "" {
   254  		c.Check(err, jc.ErrorIsNil)
   255  		if err != nil {
   256  			return
   257  		}
   258  		attrs := environ.Config().AllAttrs()
   259  		for field, value := range test.expect {
   260  			c.Check(attrs[field], gc.Equals, value)
   261  		}
   262  	} else {
   263  		c.Check(environ, gc.IsNil)
   264  		c.Check(err, gc.ErrorMatches, test.err)
   265  	}
   266  }
   267  
   268  var changeConfigTests = []struct {
   269  	info   string
   270  	insert coretesting.Attrs
   271  	remove []string
   272  	expect coretesting.Attrs
   273  	err    string
   274  }{{
   275  	info:   "no change, no error",
   276  	expect: validAttrs(),
   277  }, {
   278  	info:   "can change sdc-user",
   279  	insert: coretesting.Attrs{"sdc-user": "joyent_user"},
   280  	expect: coretesting.Attrs{"sdc-user": "joyent_user"},
   281  }, {
   282  	info:   "can change sdc-key-id",
   283  	insert: coretesting.Attrs{"sdc-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"},
   284  	expect: coretesting.Attrs{"sdc-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"},
   285  }, {
   286  	info:   "can change sdc-url",
   287  	insert: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"},
   288  	expect: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"},
   289  }, {
   290  	info:   "can change manta-user",
   291  	insert: coretesting.Attrs{"manta-user": "manta_user"},
   292  	expect: coretesting.Attrs{"manta-user": "manta_user"},
   293  }, {
   294  	info:   "can change manta-key-id",
   295  	insert: coretesting.Attrs{"manta-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"},
   296  	expect: coretesting.Attrs{"manta-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"},
   297  }, {
   298  	info:   "can change manta-url",
   299  	insert: coretesting.Attrs{"manta-url": "test://test.manta.joyent.com"},
   300  	expect: coretesting.Attrs{"manta-url": "test://test.manta.joyent.com"},
   301  }, {
   302  	info:   "can insert unknown field",
   303  	insert: coretesting.Attrs{"unknown": "ignoti"},
   304  	expect: coretesting.Attrs{"unknown": "ignoti"},
   305  }}
   306  
   307  func (s *ConfigSuite) TestValidateChange(c *gc.C) {
   308  	attrs := validAttrs()
   309  	attrs["private-key"] = s.privateKeyData
   310  	baseConfig := newConfig(c, attrs)
   311  	for i, test := range changeConfigTests {
   312  		c.Logf("test %d: %s", i, test.info)
   313  		attrs := validAttrs().Merge(test.insert).Delete(test.remove...)
   314  		attrs["private-key"] = s.privateKeyData
   315  		testConfig := newConfig(c, attrs)
   316  		validatedConfig, err := jp.Provider.Validate(testConfig, baseConfig)
   317  		if test.err == "" {
   318  			c.Check(err, jc.ErrorIsNil)
   319  			if err != nil {
   320  				continue
   321  			}
   322  			attrs := validatedConfig.AllAttrs()
   323  			for field, value := range test.expect {
   324  				c.Check(attrs[field], gc.Equals, value)
   325  			}
   326  		} else {
   327  			c.Check(validatedConfig, gc.IsNil)
   328  			c.Check(err, gc.ErrorMatches, "invalid config change: "+test.err)
   329  		}
   330  	}
   331  }
   332  
   333  func (s *ConfigSuite) TestSetConfig(c *gc.C) {
   334  	baseConfig := newConfig(c, validAttrs())
   335  	for i, test := range changeConfigTests {
   336  		c.Logf("test %d: %s", i, test.info)
   337  		environ, err := environs.New(baseConfig)
   338  		c.Assert(err, jc.ErrorIsNil)
   339  		attrs := validAttrs().Merge(test.insert).Delete(test.remove...)
   340  		testConfig := newConfig(c, attrs)
   341  		err = environ.SetConfig(testConfig)
   342  		newAttrs := environ.Config().AllAttrs()
   343  		if test.err == "" {
   344  			c.Check(err, jc.ErrorIsNil)
   345  			for field, value := range test.expect {
   346  				c.Check(newAttrs[field], gc.Equals, value)
   347  			}
   348  		} else {
   349  			c.Check(err, gc.ErrorMatches, test.err)
   350  			for field, value := range baseConfig.UnknownAttrs() {
   351  				c.Check(newAttrs[field], gc.Equals, value)
   352  			}
   353  		}
   354  	}
   355  }
   356  
   357  func validPrepareAttrs() coretesting.Attrs {
   358  	return validAttrs().Delete("private-key")
   359  }
   360  
   361  var prepareConfigTests = []struct {
   362  	info   string
   363  	insert coretesting.Attrs
   364  	remove []string
   365  	expect coretesting.Attrs
   366  	err    string
   367  }{{
   368  	info:   "All value provided, nothig to do",
   369  	expect: validPrepareAttrs(),
   370  }, {
   371  	info:   "private key is loaded from key file",
   372  	insert: coretesting.Attrs{"private-key-path": fmt.Sprintf("~/.ssh/%s", testKeyFileName)},
   373  	expect: coretesting.Attrs{"private-key": testPrivateKey},
   374  }, {
   375  	info:   "bad private-key-path errors, not panics",
   376  	insert: coretesting.Attrs{"private-key-path": "~/.ssh/no-such-file"},
   377  	err:    "invalid Joyent provider config: open .*: " + utils.NoSuchFileErrRegexp,
   378  }}
   379  
   380  func (s *ConfigSuite) TestPrepareForBootstrap(c *gc.C) {
   381  	ctx := envtesting.BootstrapContext(c)
   382  	for i, test := range prepareConfigTests {
   383  		c.Logf("test %d: %s", i, test.info)
   384  		attrs := validPrepareAttrs().Merge(test.insert).Delete(test.remove...)
   385  		testConfig := newConfig(c, attrs)
   386  		preparedConfig, err := jp.Provider.PrepareForBootstrap(ctx, testConfig)
   387  		if test.err == "" {
   388  			c.Check(err, jc.ErrorIsNil)
   389  			attrs := preparedConfig.Config().AllAttrs()
   390  			for field, value := range test.expect {
   391  				c.Check(attrs[field], gc.Equals, value)
   392  			}
   393  		} else {
   394  			c.Check(preparedConfig, gc.IsNil)
   395  			c.Check(err, gc.ErrorMatches, test.err)
   396  		}
   397  	}
   398  }