github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/environs/open_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package environs_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	jc "github.com/juju/testing/checkers"
     9  	gc "gopkg.in/check.v1"
    10  
    11  	"github.com/juju/juju/cert"
    12  	"github.com/juju/juju/environs"
    13  	"github.com/juju/juju/environs/bootstrap"
    14  	"github.com/juju/juju/environs/config"
    15  	"github.com/juju/juju/environs/configstore"
    16  	"github.com/juju/juju/environs/filestorage"
    17  	envtesting "github.com/juju/juju/environs/testing"
    18  	envtools "github.com/juju/juju/environs/tools"
    19  	"github.com/juju/juju/provider/dummy"
    20  	"github.com/juju/juju/testing"
    21  	"github.com/juju/juju/version"
    22  )
    23  
    24  type OpenSuite struct {
    25  	testing.FakeJujuHomeSuite
    26  	envtesting.ToolsFixture
    27  }
    28  
    29  var _ = gc.Suite(&OpenSuite{})
    30  
    31  func (s *OpenSuite) SetUpTest(c *gc.C) {
    32  	s.FakeJujuHomeSuite.SetUpTest(c)
    33  	testing.WriteEnvironments(c, testing.MultipleEnvConfigNoDefault)
    34  }
    35  
    36  func (s *OpenSuite) TearDownTest(c *gc.C) {
    37  	dummy.Reset()
    38  	s.FakeJujuHomeSuite.TearDownTest(c)
    39  }
    40  
    41  func (s *OpenSuite) TestNewDummyEnviron(c *gc.C) {
    42  	s.PatchValue(&version.Current.Number, testing.FakeVersionNumber)
    43  	// matches *Settings.Map()
    44  	cfg, err := config.New(config.NoDefaults, dummySampleConfig())
    45  	c.Assert(err, jc.ErrorIsNil)
    46  	ctx := envtesting.BootstrapContext(c)
    47  	env, err := environs.Prepare(cfg, ctx, configstore.NewMem())
    48  	c.Assert(err, jc.ErrorIsNil)
    49  
    50  	storageDir := c.MkDir()
    51  	s.PatchValue(&envtools.DefaultBaseURL, storageDir)
    52  	stor, err := filestorage.NewFileStorageWriter(storageDir)
    53  	c.Assert(err, jc.ErrorIsNil)
    54  	envtesting.UploadFakeTools(c, stor, cfg.AgentStream(), cfg.AgentStream())
    55  	err = bootstrap.Bootstrap(ctx, env, bootstrap.BootstrapParams{})
    56  	c.Assert(err, jc.ErrorIsNil)
    57  }
    58  
    59  func (s *OpenSuite) TestUpdateEnvInfo(c *gc.C) {
    60  	store := configstore.NewMem()
    61  	ctx := envtesting.BootstrapContext(c)
    62  	_, err := environs.PrepareFromName("erewhemos", ctx, store)
    63  	c.Assert(err, jc.ErrorIsNil)
    64  
    65  	info, err := store.ReadInfo("erewhemos")
    66  	c.Assert(err, jc.ErrorIsNil)
    67  	c.Assert(info, gc.NotNil)
    68  	c.Assert(info.APIEndpoint().CACert, gc.Not(gc.Equals), "")
    69  	c.Assert(info.APIEndpoint().EnvironUUID, gc.Not(gc.Equals), "")
    70  	c.Assert(info.APICredentials().Password, gc.Not(gc.Equals), "")
    71  	c.Assert(info.APICredentials().User, gc.Equals, "admin")
    72  }
    73  
    74  func (*OpenSuite) TestNewUnknownEnviron(c *gc.C) {
    75  	attrs := dummySampleConfig().Merge(testing.Attrs{
    76  		"type": "wondercloud",
    77  	})
    78  	env, err := environs.NewFromAttrs(attrs)
    79  	c.Assert(err, gc.ErrorMatches, "no registered provider for.*")
    80  	c.Assert(env, gc.IsNil)
    81  }
    82  
    83  func (*OpenSuite) TestNewFromName(c *gc.C) {
    84  	store := configstore.NewMem()
    85  	ctx := envtesting.BootstrapContext(c)
    86  	e, err := environs.PrepareFromName("erewhemos", ctx, store)
    87  	c.Assert(err, jc.ErrorIsNil)
    88  
    89  	e, err = environs.NewFromName("erewhemos", store)
    90  	c.Assert(err, jc.ErrorIsNil)
    91  	c.Assert(e.Config().Name(), gc.Equals, "erewhemos")
    92  }
    93  
    94  func (*OpenSuite) TestNewFromNameWithInvalidInfo(c *gc.C) {
    95  	store := configstore.NewMem()
    96  	cfg, _, err := environs.ConfigForName("erewhemos", store)
    97  	c.Assert(err, jc.ErrorIsNil)
    98  	info := store.CreateInfo("erewhemos")
    99  
   100  	// The configuration from environments.yaml is invalid
   101  	// because it doesn't contain the state-id attribute which
   102  	// the dummy environment adds at Prepare time.
   103  	info.SetBootstrapConfig(cfg.AllAttrs())
   104  	err = info.Write()
   105  	c.Assert(err, jc.ErrorIsNil)
   106  
   107  	e, err := environs.NewFromName("erewhemos", store)
   108  	c.Assert(err, gc.ErrorMatches, "environment is not prepared")
   109  	c.Assert(e, gc.IsNil)
   110  }
   111  
   112  func (*OpenSuite) TestNewFromNameWithInvalidEnvironConfig(c *gc.C) {
   113  	store := configstore.NewMem()
   114  
   115  	e, err := environs.NewFromName("erewhemos", store)
   116  	c.Assert(err, gc.Equals, environs.ErrNotBootstrapped)
   117  	c.Assert(e, gc.IsNil)
   118  }
   119  
   120  func (*OpenSuite) TestPrepareFromName(c *gc.C) {
   121  	ctx := envtesting.BootstrapContext(c)
   122  	e, err := environs.PrepareFromName("erewhemos", ctx, configstore.NewMem())
   123  	c.Assert(err, jc.ErrorIsNil)
   124  	c.Assert(e.Config().Name(), gc.Equals, "erewhemos")
   125  }
   126  
   127  func (*OpenSuite) TestConfigForName(c *gc.C) {
   128  	cfg, source, err := environs.ConfigForName("erewhemos", configstore.NewMem())
   129  	c.Assert(err, jc.ErrorIsNil)
   130  	c.Assert(source, gc.Equals, environs.ConfigFromEnvirons)
   131  	c.Assert(cfg.Name(), gc.Equals, "erewhemos")
   132  }
   133  
   134  func (*OpenSuite) TestConfigForNameNoDefault(c *gc.C) {
   135  	cfg, source, err := environs.ConfigForName("", configstore.NewMem())
   136  	c.Assert(err, gc.ErrorMatches, "no default environment found")
   137  	c.Assert(cfg, gc.IsNil)
   138  	c.Assert(source, gc.Equals, environs.ConfigFromEnvirons)
   139  }
   140  
   141  func (*OpenSuite) TestConfigForNameDefault(c *gc.C) {
   142  	testing.WriteEnvironments(c, testing.SingleEnvConfig)
   143  	cfg, source, err := environs.ConfigForName("", configstore.NewMem())
   144  	c.Assert(err, jc.ErrorIsNil)
   145  	c.Assert(cfg.Name(), gc.Equals, "erewhemos")
   146  	c.Assert(source, gc.Equals, environs.ConfigFromEnvirons)
   147  }
   148  
   149  func (*OpenSuite) TestConfigForNameFromInfo(c *gc.C) {
   150  	testing.WriteEnvironments(c, testing.SingleEnvConfig)
   151  	store := configstore.NewMem()
   152  	cfg, source, err := environs.ConfigForName("", store)
   153  	c.Assert(err, jc.ErrorIsNil)
   154  	c.Assert(source, gc.Equals, environs.ConfigFromEnvirons)
   155  
   156  	info := store.CreateInfo("test-config")
   157  	var attrs testing.Attrs = cfg.AllAttrs()
   158  	attrs = attrs.Merge(testing.Attrs{
   159  		"name": "test-config",
   160  	})
   161  	info.SetBootstrapConfig(attrs)
   162  	err = info.Write()
   163  	c.Assert(err, jc.ErrorIsNil)
   164  
   165  	cfg, source, err = environs.ConfigForName("test-config", store)
   166  	c.Assert(err, jc.ErrorIsNil)
   167  	c.Assert(source, gc.Equals, environs.ConfigFromInfo)
   168  	c.Assert(testing.Attrs(cfg.AllAttrs()), gc.DeepEquals, attrs)
   169  }
   170  
   171  func (*OpenSuite) TestNew(c *gc.C) {
   172  	cfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge(
   173  		testing.Attrs{
   174  			"state-server": false,
   175  			"name":         "erewhemos",
   176  		},
   177  	))
   178  	c.Assert(err, jc.ErrorIsNil)
   179  	e, err := environs.New(cfg)
   180  	c.Assert(err, gc.ErrorMatches, "environment is not prepared")
   181  	c.Assert(e, gc.IsNil)
   182  }
   183  
   184  func (*OpenSuite) TestPrepare(c *gc.C) {
   185  	baselineAttrs := dummy.SampleConfig().Merge(testing.Attrs{
   186  		"state-server": false,
   187  		"name":         "erewhemos",
   188  	}).Delete(
   189  		"ca-cert",
   190  		"ca-private-key",
   191  		"admin-secret",
   192  		"uuid",
   193  	)
   194  	cfg, err := config.New(config.NoDefaults, baselineAttrs)
   195  	c.Assert(err, jc.ErrorIsNil)
   196  	store := configstore.NewMem()
   197  	ctx := envtesting.BootstrapContext(c)
   198  	env, err := environs.Prepare(cfg, ctx, store)
   199  	c.Assert(err, jc.ErrorIsNil)
   200  
   201  	// Check that the environment info file was correctly created.
   202  	info, err := store.ReadInfo("erewhemos")
   203  	c.Assert(err, jc.ErrorIsNil)
   204  	c.Assert(info.Initialized(), jc.IsTrue)
   205  	c.Assert(info.BootstrapConfig(), gc.DeepEquals, env.Config().AllAttrs())
   206  	c.Logf("bootstrap config: %#v", info.BootstrapConfig())
   207  
   208  	// Check that an admin-secret was chosen.
   209  	adminSecret := env.Config().AdminSecret()
   210  	c.Assert(adminSecret, gc.HasLen, 32)
   211  	c.Assert(adminSecret, gc.Matches, "^[0-9a-f]*$")
   212  
   213  	// Check that the CA cert was generated.
   214  	cfgCertPEM, cfgCertOK := env.Config().CACert()
   215  	cfgKeyPEM, cfgKeyOK := env.Config().CAPrivateKey()
   216  	c.Assert(cfgCertOK, jc.IsTrue)
   217  	c.Assert(cfgKeyOK, jc.IsTrue)
   218  
   219  	// Check the common name of the generated cert
   220  	caCert, _, err := cert.ParseCertAndKey(cfgCertPEM, cfgKeyPEM)
   221  	c.Assert(err, jc.ErrorIsNil)
   222  	c.Assert(caCert.Subject.CommonName, gc.Equals, `juju-generated CA for environment "`+testing.SampleEnvName+`"`)
   223  
   224  	// Check that a uuid was chosen.
   225  	uuid, exists := env.Config().UUID()
   226  	c.Assert(exists, jc.IsTrue)
   227  	c.Assert(uuid, gc.Matches, `[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}`)
   228  
   229  	// Check we can call Prepare again.
   230  	env, err = environs.Prepare(cfg, ctx, store)
   231  	c.Assert(err, jc.ErrorIsNil)
   232  	c.Assert(env.Config().AllAttrs(), gc.DeepEquals, info.BootstrapConfig())
   233  }
   234  
   235  func (*OpenSuite) TestPrepareGeneratesDifferentAdminSecrets(c *gc.C) {
   236  	baselineAttrs := dummy.SampleConfig().Merge(testing.Attrs{
   237  		"state-server": false,
   238  		"name":         "erewhemos",
   239  	}).Delete(
   240  		"admin-secret",
   241  	)
   242  	cfg, err := config.New(config.NoDefaults, baselineAttrs)
   243  	c.Assert(err, jc.ErrorIsNil)
   244  
   245  	ctx := envtesting.BootstrapContext(c)
   246  	env0, err := environs.Prepare(cfg, ctx, configstore.NewMem())
   247  	c.Assert(err, jc.ErrorIsNil)
   248  	adminSecret0 := env0.Config().AdminSecret()
   249  	c.Assert(adminSecret0, gc.HasLen, 32)
   250  	c.Assert(adminSecret0, gc.Matches, "^[0-9a-f]*$")
   251  
   252  	env1, err := environs.Prepare(cfg, ctx, configstore.NewMem())
   253  	c.Assert(err, jc.ErrorIsNil)
   254  	adminSecret1 := env1.Config().AdminSecret()
   255  	c.Assert(adminSecret1, gc.HasLen, 32)
   256  	c.Assert(adminSecret1, gc.Matches, "^[0-9a-f]*$")
   257  
   258  	c.Assert(adminSecret1, gc.Not(gc.Equals), adminSecret0)
   259  }
   260  
   261  func (*OpenSuite) TestPrepareWithMissingKey(c *gc.C) {
   262  	cfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Delete("ca-cert", "ca-private-key").Merge(
   263  		testing.Attrs{
   264  			"state-server": false,
   265  			"name":         "erewhemos",
   266  			"ca-cert":      string(testing.CACert),
   267  		},
   268  	))
   269  	c.Assert(err, jc.ErrorIsNil)
   270  	store := configstore.NewMem()
   271  	env, err := environs.Prepare(cfg, envtesting.BootstrapContext(c), store)
   272  	c.Assert(err, gc.ErrorMatches, "cannot ensure CA certificate: environment configuration with a certificate but no CA private key")
   273  	c.Assert(env, gc.IsNil)
   274  	// Ensure that the config storage info is cleaned up.
   275  	_, err = store.ReadInfo(cfg.Name())
   276  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   277  }
   278  
   279  func (*OpenSuite) TestPrepareWithExistingKeyPair(c *gc.C) {
   280  	cfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge(
   281  		testing.Attrs{
   282  			"state-server":   false,
   283  			"name":           "erewhemos",
   284  			"ca-cert":        string(testing.CACert),
   285  			"ca-private-key": string(testing.CAKey),
   286  		},
   287  	))
   288  	c.Assert(err, jc.ErrorIsNil)
   289  	ctx := envtesting.BootstrapContext(c)
   290  	env, err := environs.Prepare(cfg, ctx, configstore.NewMem())
   291  	c.Assert(err, jc.ErrorIsNil)
   292  	cfgCertPEM, cfgCertOK := env.Config().CACert()
   293  	cfgKeyPEM, cfgKeyOK := env.Config().CAPrivateKey()
   294  	c.Assert(cfgCertOK, jc.IsTrue)
   295  	c.Assert(cfgKeyOK, jc.IsTrue)
   296  	c.Assert(string(cfgCertPEM), gc.DeepEquals, testing.CACert)
   297  	c.Assert(string(cfgKeyPEM), gc.DeepEquals, testing.CAKey)
   298  }
   299  
   300  func (*OpenSuite) TestDestroy(c *gc.C) {
   301  	cfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge(
   302  		testing.Attrs{
   303  			"state-server": false,
   304  			"name":         "erewhemos",
   305  		},
   306  	))
   307  	c.Assert(err, jc.ErrorIsNil)
   308  
   309  	store := configstore.NewMem()
   310  	// Prepare the environment and sanity-check that
   311  	// the config storage info has been made.
   312  	ctx := envtesting.BootstrapContext(c)
   313  	e, err := environs.Prepare(cfg, ctx, store)
   314  	c.Assert(err, jc.ErrorIsNil)
   315  	_, err = store.ReadInfo(e.Config().Name())
   316  	c.Assert(err, jc.ErrorIsNil)
   317  
   318  	err = environs.Destroy(e, store)
   319  	c.Assert(err, jc.ErrorIsNil)
   320  
   321  	// Check that the environment has actually been destroyed
   322  	// and that the config info has been destroyed too.
   323  	_, err = e.StateServerInstances()
   324  	c.Assert(err, gc.ErrorMatches, "environment has been destroyed")
   325  	_, err = store.ReadInfo(e.Config().Name())
   326  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   327  }
   328  
   329  func (*OpenSuite) TestNewFromAttrs(c *gc.C) {
   330  	e, err := environs.NewFromAttrs(dummy.SampleConfig().Merge(
   331  		testing.Attrs{
   332  			"state-server": false,
   333  			"name":         "erewhemos",
   334  		},
   335  	))
   336  	c.Assert(err, gc.ErrorMatches, "environment is not prepared")
   337  	c.Assert(e, gc.IsNil)
   338  }