github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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/ssh"
    13  	gc "gopkg.in/check.v1"
    14  
    15  	"github.com/juju/juju/cloud"
    16  	"github.com/juju/juju/environs"
    17  	"github.com/juju/juju/environs/config"
    18  	jp "github.com/juju/juju/provider/joyent"
    19  	coretesting "github.com/juju/juju/testing"
    20  )
    21  
    22  func newConfig(c *gc.C, attrs coretesting.Attrs) *config.Config {
    23  	attrs = coretesting.FakeConfig().Merge(attrs)
    24  	cfg, err := config.New(config.UseDefaults, attrs)
    25  	c.Assert(err, jc.ErrorIsNil)
    26  	return cfg
    27  }
    28  
    29  func validAttrs() coretesting.Attrs {
    30  	return coretesting.FakeConfig().Merge(coretesting.Attrs{
    31  		"type":        "joyent",
    32  		"sdc-user":    "test",
    33  		"sdc-key-id":  "00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff",
    34  		"sdc-url":     "test://test.api.joyentcloud.com",
    35  		"private-key": testPrivateKey,
    36  		"algorithm":   "rsa-sha256",
    37  	})
    38  }
    39  
    40  type ConfigSuite struct {
    41  	coretesting.FakeJujuXDGDataHomeSuite
    42  	originalValues map[string]testing.Restorer
    43  	privateKeyData string
    44  }
    45  
    46  var _ = gc.Suite(&ConfigSuite{})
    47  
    48  func (s *ConfigSuite) SetUpSuite(c *gc.C) {
    49  	s.FakeJujuXDGDataHomeSuite.SetUpSuite(c)
    50  	restoreSdcAccount := testing.PatchEnvironment(jp.SdcAccount, "tester")
    51  	s.AddCleanup(func(*gc.C) { restoreSdcAccount() })
    52  	restoreSdcKeyId := testing.PatchEnvironment(jp.SdcKeyId, "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00")
    53  	s.AddCleanup(func(*gc.C) { restoreSdcKeyId() })
    54  	s.privateKeyData = generatePrivateKey(c)
    55  	jp.RegisterMachinesEndpoint()
    56  	s.AddCleanup(func(*gc.C) { jp.UnregisterMachinesEndpoint() })
    57  }
    58  
    59  func generatePrivateKey(c *gc.C) string {
    60  	oldBits := ssh.KeyBits
    61  	defer func() {
    62  		ssh.KeyBits = oldBits
    63  	}()
    64  	ssh.KeyBits = 32
    65  	private, _, err := ssh.GenerateKey("test-client")
    66  	c.Assert(err, jc.ErrorIsNil)
    67  	return private
    68  }
    69  
    70  func (s *ConfigSuite) SetUpTest(c *gc.C) {
    71  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
    72  	for _, envVar := range jp.EnvironmentVariables {
    73  		s.PatchEnvironment(envVar, "")
    74  	}
    75  }
    76  
    77  type configtest struct {
    78  	info    string
    79  	insert  coretesting.Attrs
    80  	remove  []string
    81  	envVars map[string]string
    82  	expect  coretesting.Attrs
    83  	err     string
    84  }
    85  
    86  var newConfigTests = []configtest{{
    87  	info:   "sdc-user is required",
    88  	remove: []string{"sdc-user"},
    89  	err:    ".* cannot get sdc-user value from environment variable .*",
    90  }, {
    91  	info:   "sdc-user cannot be empty",
    92  	insert: coretesting.Attrs{"sdc-user": ""},
    93  	err:    ".* cannot get sdc-user value from environment variable .*",
    94  }, {
    95  	info:   "can get sdc-user from environment variable",
    96  	insert: coretesting.Attrs{"sdc-user": ""},
    97  	expect: coretesting.Attrs{"sdc-user": "tester"},
    98  	envVars: map[string]string{
    99  		"SDC_ACCOUNT": "tester",
   100  	},
   101  }, {
   102  	info:   "can get sdc-user from environment variable, missing from config",
   103  	remove: []string{"sdc-user"},
   104  	expect: coretesting.Attrs{"sdc-user": "tester"},
   105  	envVars: map[string]string{
   106  		"SDC_ACCOUNT": "tester",
   107  	},
   108  }, {
   109  	info:   "sdc-key-id is required",
   110  	remove: []string{"sdc-key-id"},
   111  	err:    ".* cannot get sdc-key-id value from environment variable .*",
   112  }, {
   113  	info:   "sdc-key-id cannot be empty",
   114  	insert: coretesting.Attrs{"sdc-key-id": ""},
   115  	err:    ".* cannot get sdc-key-id value from environment variable .*",
   116  }, {
   117  	info:   "can get sdc-key-id from environment variable",
   118  	insert: coretesting.Attrs{"sdc-key-id": ""},
   119  	expect: coretesting.Attrs{"sdc-key-id": "key"},
   120  	envVars: map[string]string{
   121  		"SDC_KEY_ID": "key",
   122  	},
   123  }, {
   124  	info:   "can get sdc-key-id from environment variable, missing from config",
   125  	remove: []string{"sdc-key-id"},
   126  	expect: coretesting.Attrs{"sdc-key-id": "key"},
   127  	envVars: map[string]string{
   128  		"SDC_KEY_ID": "key",
   129  	},
   130  }, {
   131  	info:   "sdc-url is inserted if missing",
   132  	expect: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"},
   133  }, {
   134  	info:   "sdc-url cannot be empty",
   135  	insert: coretesting.Attrs{"sdc-url": ""},
   136  	err:    ".* cannot get sdc-url value from environment variable .*",
   137  }, {
   138  	info:   "sdc-url is untouched if present",
   139  	insert: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"},
   140  	expect: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"},
   141  }, {
   142  	info:   "algorithm is inserted if missing",
   143  	expect: coretesting.Attrs{"algorithm": "rsa-sha256"},
   144  }, {
   145  	info:   "algorithm cannot be empty",
   146  	insert: coretesting.Attrs{"algorithm": ""},
   147  	err:    ".* algorithm: must not be empty",
   148  }, {
   149  	info:   "unknown field is not touched",
   150  	insert: coretesting.Attrs{"unknown-field": 12345},
   151  	expect: coretesting.Attrs{"unknown-field": 12345},
   152  }}
   153  
   154  func (s *ConfigSuite) TestNewModelConfig(c *gc.C) {
   155  	for i, test := range newConfigTests {
   156  		doTest(s, i, test, c)
   157  	}
   158  }
   159  
   160  func doTest(s *ConfigSuite, i int, test configtest, c *gc.C) {
   161  	c.Logf("test %d: %s", i, test.info)
   162  	for k, v := range test.envVars {
   163  		os.Setenv(k, v)
   164  		defer os.Setenv(k, "")
   165  	}
   166  	attrs := validAttrs().Merge(test.insert).Delete(test.remove...)
   167  	attrs["private-key"] = s.privateKeyData
   168  	testConfig := newConfig(c, attrs)
   169  	environ, err := environs.New(testConfig)
   170  	if test.err == "" {
   171  		c.Check(err, jc.ErrorIsNil)
   172  		if err != nil {
   173  			return
   174  		}
   175  		attrs := environ.Config().AllAttrs()
   176  		for field, value := range test.expect {
   177  			c.Check(attrs[field], gc.Equals, value)
   178  		}
   179  	} else {
   180  		c.Check(environ, gc.IsNil)
   181  		c.Check(err, gc.ErrorMatches, test.err)
   182  	}
   183  }
   184  
   185  var changeConfigTests = []struct {
   186  	info   string
   187  	insert coretesting.Attrs
   188  	remove []string
   189  	expect coretesting.Attrs
   190  	err    string
   191  }{{
   192  	info:   "no change, no error",
   193  	expect: validAttrs(),
   194  }, {
   195  	info:   "can change sdc-user",
   196  	insert: coretesting.Attrs{"sdc-user": "joyent_user"},
   197  	expect: coretesting.Attrs{"sdc-user": "joyent_user"},
   198  }, {
   199  	info:   "can change sdc-key-id",
   200  	insert: coretesting.Attrs{"sdc-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"},
   201  	expect: coretesting.Attrs{"sdc-key-id": "ff:ee:dd:cc:bb:aa:99:88:77:66:55:44:33:22:11:00"},
   202  }, {
   203  	info:   "can change sdc-url",
   204  	insert: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"},
   205  	expect: coretesting.Attrs{"sdc-url": "test://test.api.joyentcloud.com"},
   206  }, {
   207  	info:   "can insert unknown field",
   208  	insert: coretesting.Attrs{"unknown": "ignoti"},
   209  	expect: coretesting.Attrs{"unknown": "ignoti"},
   210  }}
   211  
   212  func (s *ConfigSuite) TestValidateChange(c *gc.C) {
   213  	attrs := validAttrs()
   214  	baseConfig := newConfig(c, attrs)
   215  	for i, test := range changeConfigTests {
   216  		c.Logf("test %d: %s", i, test.info)
   217  		attrs := validAttrs().Merge(test.insert).Delete(test.remove...)
   218  		testConfig := newConfig(c, attrs)
   219  		validatedConfig, err := jp.Provider.Validate(testConfig, baseConfig)
   220  		if test.err == "" {
   221  			c.Check(err, jc.ErrorIsNil)
   222  			if err != nil {
   223  				continue
   224  			}
   225  			attrs := validatedConfig.AllAttrs()
   226  			for field, value := range test.expect {
   227  				c.Check(attrs[field], gc.Equals, value)
   228  			}
   229  		} else {
   230  			c.Check(validatedConfig, gc.IsNil)
   231  			c.Check(err, gc.ErrorMatches, "invalid config change: "+test.err)
   232  		}
   233  	}
   234  }
   235  
   236  func (s *ConfigSuite) TestSetConfig(c *gc.C) {
   237  	baseConfig := newConfig(c, validAttrs())
   238  	for i, test := range changeConfigTests {
   239  		c.Logf("test %d: %s", i, test.info)
   240  		environ, err := environs.New(baseConfig)
   241  		c.Assert(err, jc.ErrorIsNil)
   242  		attrs := validAttrs().Merge(test.insert).Delete(test.remove...)
   243  		testConfig := newConfig(c, attrs)
   244  		err = environ.SetConfig(testConfig)
   245  		newAttrs := environ.Config().AllAttrs()
   246  		if test.err == "" {
   247  			c.Check(err, jc.ErrorIsNil)
   248  			for field, value := range test.expect {
   249  				c.Check(newAttrs[field], gc.Equals, value)
   250  			}
   251  		} else {
   252  			c.Check(err, gc.ErrorMatches, test.err)
   253  			for field, value := range baseConfig.UnknownAttrs() {
   254  				c.Check(newAttrs[field], gc.Equals, value)
   255  			}
   256  		}
   257  	}
   258  }
   259  
   260  // TODO(wallyworld) - add tests for cloud endpoint passed in via bootstrap args
   261  var bootstrapConfigTests = []struct {
   262  	info   string
   263  	insert coretesting.Attrs
   264  	remove []string
   265  	expect coretesting.Attrs
   266  	err    string
   267  }{{
   268  	info:   "All value provided, nothing to do",
   269  	expect: validAttrs(),
   270  }}
   271  
   272  func (s *ConfigSuite) TestBootstrapConfig(c *gc.C) {
   273  	for i, test := range bootstrapConfigTests {
   274  		c.Logf("test %d: %s", i, test.info)
   275  		attrs := validAttrs().Merge(test.insert).Delete(test.remove...)
   276  		credentialAttrs := make(map[string]string, len(attrs))
   277  		for k, v := range attrs.Delete("type") {
   278  			credentialAttrs[k] = fmt.Sprintf("%v", v)
   279  		}
   280  		testConfig := newConfig(c, attrs)
   281  		preparedConfig, err := jp.Provider.BootstrapConfig(environs.BootstrapConfigParams{
   282  			Config: testConfig,
   283  			Credentials: cloud.NewCredential(
   284  				cloud.UserPassAuthType,
   285  				credentialAttrs,
   286  			),
   287  		})
   288  		if test.err == "" {
   289  			c.Check(err, jc.ErrorIsNil)
   290  			attrs := preparedConfig.AllAttrs()
   291  			for field, value := range test.expect {
   292  				c.Check(attrs[field], gc.Equals, value)
   293  			}
   294  		} else {
   295  			c.Check(preparedConfig, gc.IsNil)
   296  			c.Check(err, gc.ErrorMatches, test.err)
   297  		}
   298  	}
   299  }