github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cmd/envcmd/environmentcommand_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package envcmd_test
     5  
     6  import (
     7  	"io"
     8  	"os"
     9  
    10  	"github.com/juju/cmd"
    11  	"github.com/juju/cmd/cmdtesting"
    12  	"github.com/juju/errors"
    13  	gitjujutesting "github.com/juju/testing"
    14  	jc "github.com/juju/testing/checkers"
    15  	gc "gopkg.in/check.v1"
    16  
    17  	"github.com/juju/juju/cmd/envcmd"
    18  	"github.com/juju/juju/environs/config"
    19  	"github.com/juju/juju/environs/configstore"
    20  	"github.com/juju/juju/juju/osenv"
    21  	"github.com/juju/juju/testing"
    22  	"github.com/juju/juju/version"
    23  )
    24  
    25  type EnvironmentCommandSuite struct {
    26  	testing.FakeJujuHomeSuite
    27  }
    28  
    29  func (s *EnvironmentCommandSuite) SetUpTest(c *gc.C) {
    30  	s.FakeJujuHomeSuite.SetUpTest(c)
    31  	s.PatchEnvironment("JUJU_CLI_VERSION", "")
    32  }
    33  
    34  var _ = gc.Suite(&EnvironmentCommandSuite{})
    35  
    36  func (s *EnvironmentCommandSuite) TestGetDefaultEnvironment(c *gc.C) {
    37  	env, err := envcmd.GetDefaultEnvironment()
    38  	c.Assert(env, gc.Equals, "erewhemos")
    39  	c.Assert(err, jc.ErrorIsNil)
    40  }
    41  
    42  func (s *EnvironmentCommandSuite) TestGetDefaultEnvironmentNothingSet(c *gc.C) {
    43  	envPath := gitjujutesting.HomePath(".juju", "environments.yaml")
    44  	err := os.Remove(envPath)
    45  	c.Assert(err, jc.ErrorIsNil)
    46  	env, err := envcmd.GetDefaultEnvironment()
    47  	c.Assert(env, gc.Equals, "")
    48  	c.Assert(err, jc.ErrorIsNil)
    49  }
    50  
    51  func (s *EnvironmentCommandSuite) TestGetDefaultEnvironmentCurrentEnvironmentSet(c *gc.C) {
    52  	err := envcmd.WriteCurrentEnvironment("fubar")
    53  	c.Assert(err, jc.ErrorIsNil)
    54  	env, err := envcmd.GetDefaultEnvironment()
    55  	c.Assert(env, gc.Equals, "fubar")
    56  	c.Assert(err, jc.ErrorIsNil)
    57  }
    58  
    59  func (s *EnvironmentCommandSuite) TestGetDefaultEnvironmentJujuEnvSet(c *gc.C) {
    60  	os.Setenv(osenv.JujuEnvEnvKey, "magic")
    61  	env, err := envcmd.GetDefaultEnvironment()
    62  	c.Assert(env, gc.Equals, "magic")
    63  	c.Assert(err, jc.ErrorIsNil)
    64  }
    65  
    66  func (s *EnvironmentCommandSuite) TestGetDefaultEnvironmentBothSet(c *gc.C) {
    67  	os.Setenv(osenv.JujuEnvEnvKey, "magic")
    68  	err := envcmd.WriteCurrentEnvironment("fubar")
    69  	c.Assert(err, jc.ErrorIsNil)
    70  	env, err := envcmd.GetDefaultEnvironment()
    71  	c.Assert(env, gc.Equals, "magic")
    72  	c.Assert(err, jc.ErrorIsNil)
    73  }
    74  
    75  func (s *EnvironmentCommandSuite) TestEnvironCommandInitExplicit(c *gc.C) {
    76  	// Take environment name from command line arg.
    77  	testEnsureEnvName(c, "explicit", "-e", "explicit")
    78  }
    79  
    80  func (s *EnvironmentCommandSuite) TestEnvironCommandInitMultipleConfigs(c *gc.C) {
    81  	// Take environment name from the default.
    82  	testing.WriteEnvironments(c, testing.MultipleEnvConfig)
    83  	testEnsureEnvName(c, testing.SampleEnvName)
    84  }
    85  
    86  func (s *EnvironmentCommandSuite) TestEnvironCommandInitSingleConfig(c *gc.C) {
    87  	// Take environment name from the one and only environment,
    88  	// even if it is not explicitly marked as default.
    89  	testing.WriteEnvironments(c, testing.SingleEnvConfigNoDefault)
    90  	testEnsureEnvName(c, testing.SampleEnvName)
    91  }
    92  
    93  func (s *EnvironmentCommandSuite) TestEnvironCommandInitEnvFile(c *gc.C) {
    94  	// If there is a current-environment file, use that.
    95  	err := envcmd.WriteCurrentEnvironment("fubar")
    96  	c.Assert(err, jc.ErrorIsNil)
    97  	testEnsureEnvName(c, "fubar")
    98  }
    99  
   100  func (s *EnvironmentCommandSuite) TestEnvironCommandInitSystemFile(c *gc.C) {
   101  	// If there is a current-system file, error raised.
   102  	err := envcmd.WriteCurrentSystem("fubar")
   103  	c.Assert(err, jc.ErrorIsNil)
   104  	_, err = initTestCommand(c)
   105  	c.Assert(err, gc.ErrorMatches, `not operating on an environment, using system "fubar"`)
   106  }
   107  
   108  func (s *EnvironmentCommandSuite) TestEnvironCommandInitNoEnvFile(c *gc.C) {
   109  	envPath := gitjujutesting.HomePath(".juju", "environments.yaml")
   110  	err := os.Remove(envPath)
   111  	c.Assert(err, jc.ErrorIsNil)
   112  	testEnsureEnvName(c, "")
   113  }
   114  
   115  func (s *EnvironmentCommandSuite) TestEnvironCommandInitMultipleConfigNoDefault(c *gc.C) {
   116  	// If there are multiple environments but no default, the connection name is empty.
   117  	testing.WriteEnvironments(c, testing.MultipleEnvConfigNoDefault)
   118  	testEnsureEnvName(c, "")
   119  }
   120  
   121  func (s *EnvironmentCommandSuite) TestBootstrapContext(c *gc.C) {
   122  	ctx := envcmd.BootstrapContext(&cmd.Context{})
   123  	c.Assert(ctx.ShouldVerifyCredentials(), jc.IsTrue)
   124  }
   125  
   126  func (s *EnvironmentCommandSuite) TestBootstrapContextNoVerify(c *gc.C) {
   127  	ctx := envcmd.BootstrapContextNoVerify(&cmd.Context{})
   128  	c.Assert(ctx.ShouldVerifyCredentials(), jc.IsFalse)
   129  }
   130  
   131  func (s *EnvironmentCommandSuite) TestCompatVersion(c *gc.C) {
   132  	s.PatchEnvironment(osenv.JujuCLIVersion, "2")
   133  	cmd, err := initTestCommand(c)
   134  	c.Assert(err, jc.ErrorIsNil)
   135  	c.Assert(cmd.CompatVersion(), gc.Equals, 2)
   136  }
   137  
   138  func (s *EnvironmentCommandSuite) TestCompatVersionDefault(c *gc.C) {
   139  	cmd, err := initTestCommand(c)
   140  	c.Assert(err, jc.ErrorIsNil)
   141  	c.Assert(cmd.CompatVersion(), gc.Equals, 1)
   142  }
   143  
   144  func (s *EnvironmentCommandSuite) TestCompatVersionInvalid(c *gc.C) {
   145  	s.PatchEnvironment(osenv.JujuCLIVersion, "invalid")
   146  	cmd, err := initTestCommand(c)
   147  	c.Assert(err, jc.ErrorIsNil)
   148  	c.Assert(cmd.CompatVersion(), gc.Equals, 1)
   149  }
   150  
   151  type testCommand struct {
   152  	envcmd.EnvCommandBase
   153  }
   154  
   155  func (c *testCommand) Info() *cmd.Info {
   156  	panic("should not be called")
   157  }
   158  
   159  func (c *testCommand) Run(ctx *cmd.Context) error {
   160  	panic("should not be called")
   161  }
   162  
   163  func initTestCommand(c *gc.C, args ...string) (*testCommand, error) {
   164  	cmd := new(testCommand)
   165  	wrapped := envcmd.Wrap(cmd)
   166  	return cmd, cmdtesting.InitCommand(wrapped, args)
   167  }
   168  
   169  func testEnsureEnvName(c *gc.C, expect string, args ...string) {
   170  	cmd, err := initTestCommand(c, args...)
   171  	c.Assert(err, jc.ErrorIsNil)
   172  	c.Assert(cmd.ConnectionName(), gc.Equals, expect)
   173  }
   174  
   175  type ConnectionEndpointSuite struct {
   176  	testing.FakeJujuHomeSuite
   177  	store    configstore.Storage
   178  	endpoint configstore.APIEndpoint
   179  }
   180  
   181  var _ = gc.Suite(&ConnectionEndpointSuite{})
   182  
   183  func (s *ConnectionEndpointSuite) SetUpTest(c *gc.C) {
   184  	s.FakeHomeSuite.SetUpTest(c)
   185  	s.store = configstore.NewMem()
   186  	s.PatchValue(envcmd.GetConfigStore, func() (configstore.Storage, error) {
   187  		return s.store, nil
   188  	})
   189  	newInfo := s.store.CreateInfo("env-name")
   190  	newInfo.SetAPICredentials(configstore.APICredentials{
   191  		User:     "foo",
   192  		Password: "foopass",
   193  	})
   194  	s.endpoint = configstore.APIEndpoint{
   195  		Addresses:   []string{"0.1.2.3"},
   196  		Hostnames:   []string{"foo.invalid"},
   197  		CACert:      "certificated",
   198  		EnvironUUID: "fake-uuid",
   199  	}
   200  	newInfo.SetAPIEndpoint(s.endpoint)
   201  	err := newInfo.Write()
   202  	c.Assert(err, jc.ErrorIsNil)
   203  }
   204  
   205  func (s *ConnectionEndpointSuite) TestAPIEndpointInStoreCached(c *gc.C) {
   206  	cmd, err := initTestCommand(c, "-e", "env-name")
   207  	c.Assert(err, jc.ErrorIsNil)
   208  	endpoint, err := cmd.ConnectionEndpoint(false)
   209  	c.Assert(err, jc.ErrorIsNil)
   210  	c.Assert(endpoint, gc.DeepEquals, s.endpoint)
   211  }
   212  
   213  func (s *ConnectionEndpointSuite) TestAPIEndpointForEnvSuchName(c *gc.C) {
   214  	cmd, err := initTestCommand(c, "-e", "no-such-env")
   215  	c.Assert(err, jc.ErrorIsNil)
   216  	_, err = cmd.ConnectionEndpoint(false)
   217  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   218  	c.Assert(err, gc.ErrorMatches, `environment "no-such-env" not found`)
   219  }
   220  
   221  func (s *ConnectionEndpointSuite) TestAPIEndpointRefresh(c *gc.C) {
   222  	newEndpoint := configstore.APIEndpoint{
   223  		Addresses:   []string{"0.1.2.3"},
   224  		Hostnames:   []string{"foo.example.com"},
   225  		CACert:      "certificated",
   226  		EnvironUUID: "fake-uuid",
   227  	}
   228  	s.PatchValue(envcmd.EndpointRefresher, func(_ *envcmd.EnvCommandBase) (io.Closer, error) {
   229  		info, err := s.store.ReadInfo("env-name")
   230  		info.SetAPIEndpoint(newEndpoint)
   231  		err = info.Write()
   232  		c.Assert(err, jc.ErrorIsNil)
   233  		return new(closer), nil
   234  	})
   235  
   236  	cmd, err := initTestCommand(c, "-e", "env-name")
   237  	c.Assert(err, jc.ErrorIsNil)
   238  	endpoint, err := cmd.ConnectionEndpoint(true)
   239  	c.Assert(err, jc.ErrorIsNil)
   240  	c.Assert(endpoint, gc.DeepEquals, newEndpoint)
   241  }
   242  
   243  type closer struct{}
   244  
   245  func (*closer) Close() error {
   246  	return nil
   247  }
   248  
   249  type EnvironmentVersionSuite struct {
   250  	fake *fakeEnvGetter
   251  }
   252  
   253  var _ = gc.Suite(&EnvironmentVersionSuite{})
   254  
   255  type fakeEnvGetter struct {
   256  	agentVersion interface{}
   257  	err          error
   258  	results      map[string]interface{}
   259  	closeCalled  bool
   260  	getCalled    bool
   261  }
   262  
   263  func (g *fakeEnvGetter) EnvironmentGet() (map[string]interface{}, error) {
   264  	g.getCalled = true
   265  	if g.err != nil {
   266  		return nil, g.err
   267  	} else if g.results != nil {
   268  		return g.results, nil
   269  	} else if g.agentVersion == nil {
   270  		return map[string]interface{}{}, nil
   271  	} else {
   272  		return map[string]interface{}{
   273  			"agent-version": g.agentVersion,
   274  		}, nil
   275  	}
   276  }
   277  
   278  func (g *fakeEnvGetter) Close() error {
   279  	g.closeCalled = true
   280  	return nil
   281  }
   282  
   283  func (s *EnvironmentVersionSuite) SetUpTest(*gc.C) {
   284  	s.fake = new(fakeEnvGetter)
   285  }
   286  
   287  func (s *EnvironmentVersionSuite) TestApiCallFails(c *gc.C) {
   288  	s.fake.err = errors.New("boom")
   289  	_, err := envcmd.GetEnvironmentVersion(s.fake)
   290  	c.Assert(err, gc.ErrorMatches, "unable to retrieve environment config: boom")
   291  }
   292  
   293  func (s *EnvironmentVersionSuite) TestNoVersion(c *gc.C) {
   294  	_, err := envcmd.GetEnvironmentVersion(s.fake)
   295  	c.Assert(err, gc.ErrorMatches, "version not found in environment config")
   296  }
   297  
   298  func (s *EnvironmentVersionSuite) TestInvalidVersionType(c *gc.C) {
   299  	s.fake.agentVersion = 99
   300  	_, err := envcmd.GetEnvironmentVersion(s.fake)
   301  	c.Assert(err, gc.ErrorMatches, "invalid environment version type in config")
   302  }
   303  
   304  func (s *EnvironmentVersionSuite) TestInvalidVersion(c *gc.C) {
   305  	s.fake.agentVersion = "a.b.c"
   306  	_, err := envcmd.GetEnvironmentVersion(s.fake)
   307  	c.Assert(err, gc.ErrorMatches, "unable to parse environment version: .+")
   308  }
   309  
   310  func (s *EnvironmentVersionSuite) TestSuccess(c *gc.C) {
   311  	vs := "1.22.1"
   312  	s.fake.agentVersion = vs
   313  	v, err := envcmd.GetEnvironmentVersion(s.fake)
   314  	c.Assert(err, jc.ErrorIsNil)
   315  	c.Assert(v.Compare(version.MustParse(vs)), gc.Equals, 0)
   316  }
   317  
   318  type EnvConfigSuite struct {
   319  	testing.FakeJujuHomeSuite
   320  	client  *fakeEnvGetter
   321  	store   configstore.Storage
   322  	envName string
   323  }
   324  
   325  var _ = gc.Suite(&EnvConfigSuite{})
   326  
   327  func createBootstrapInfo(c *gc.C, name string) map[string]interface{} {
   328  	bootstrapCfg, err := config.New(config.UseDefaults, map[string]interface{}{
   329  		"type":         "dummy",
   330  		"name":         name,
   331  		"state-server": "true",
   332  		"state-id":     "1",
   333  	})
   334  	c.Assert(err, jc.ErrorIsNil)
   335  	return bootstrapCfg.AllAttrs()
   336  }
   337  
   338  func (s *EnvConfigSuite) SetUpTest(c *gc.C) {
   339  	s.FakeJujuHomeSuite.SetUpTest(c)
   340  	s.envName = "test-env"
   341  	s.client = &fakeEnvGetter{results: createBootstrapInfo(c, s.envName)}
   342  
   343  	var err error
   344  	s.store, err = configstore.Default()
   345  	c.Assert(err, jc.ErrorIsNil)
   346  }
   347  
   348  func (s *EnvConfigSuite) writeStore(c *gc.C, bootstrapInfo bool) {
   349  	info := s.store.CreateInfo(s.envName)
   350  	info.SetAPIEndpoint(configstore.APIEndpoint{
   351  		Addresses:   []string{"localhost"},
   352  		CACert:      testing.CACert,
   353  		EnvironUUID: s.envName + "-UUID",
   354  		ServerUUID:  s.envName + "-UUID",
   355  	})
   356  
   357  	if bootstrapInfo {
   358  		info.SetBootstrapConfig(createBootstrapInfo(c, s.envName))
   359  	}
   360  	err := info.Write()
   361  	c.Assert(err, jc.ErrorIsNil)
   362  }
   363  
   364  func (s *EnvConfigSuite) TestConfigWithBootstrapInfo(c *gc.C) {
   365  	cmd := envcmd.NewEnvCommandBase(s.envName, s.client, nil)
   366  	s.writeStore(c, true)
   367  
   368  	cfg, err := cmd.Config(s.store, s.client)
   369  	c.Assert(err, jc.ErrorIsNil)
   370  	c.Check(cfg.Name(), gc.Equals, s.envName)
   371  	c.Check(s.client.getCalled, jc.IsFalse)
   372  	c.Check(s.client.closeCalled, jc.IsFalse)
   373  }
   374  
   375  func (s *EnvConfigSuite) TestConfigWithNoBootstrapWithClient(c *gc.C) {
   376  	cmd := envcmd.NewEnvCommandBase(s.envName, s.client, nil)
   377  	s.writeStore(c, false)
   378  
   379  	cfg, err := cmd.Config(s.store, s.client)
   380  	c.Assert(err, jc.ErrorIsNil)
   381  	c.Check(cfg.Name(), gc.Equals, s.envName)
   382  	c.Check(s.client.getCalled, jc.IsTrue)
   383  	c.Check(s.client.closeCalled, jc.IsFalse)
   384  }
   385  
   386  func (s *EnvConfigSuite) TestConfigWithNoBootstrapNoClient(c *gc.C) {
   387  	cmd := envcmd.NewEnvCommandBase(s.envName, s.client, nil)
   388  	s.writeStore(c, false)
   389  
   390  	cfg, err := cmd.Config(s.store, nil)
   391  	c.Assert(err, jc.ErrorIsNil)
   392  	c.Check(cfg.Name(), gc.Equals, s.envName)
   393  	c.Check(s.client.getCalled, jc.IsTrue)
   394  	c.Check(s.client.closeCalled, jc.IsTrue)
   395  }
   396  
   397  func (s *EnvConfigSuite) TestConfigWithNoBootstrapWithClientErr(c *gc.C) {
   398  	cmd := envcmd.NewEnvCommandBase(s.envName, s.client, errors.New("problem opening connection"))
   399  	s.writeStore(c, false)
   400  
   401  	_, err := cmd.Config(s.store, nil)
   402  	c.Assert(err, gc.ErrorMatches, "problem opening connection")
   403  	c.Check(s.client.getCalled, jc.IsFalse)
   404  	c.Check(s.client.closeCalled, jc.IsFalse)
   405  }
   406  
   407  func (s *EnvConfigSuite) TestConfigWithNoBootstrapWithEnvGetError(c *gc.C) {
   408  	cmd := envcmd.NewEnvCommandBase(s.envName, s.client, nil)
   409  	s.writeStore(c, false)
   410  	s.client.err = errors.New("problem getting environment attributes")
   411  
   412  	_, err := cmd.Config(s.store, nil)
   413  	c.Assert(err, gc.ErrorMatches, "problem getting environment attributes")
   414  	c.Check(s.client.getCalled, jc.IsTrue)
   415  	c.Check(s.client.closeCalled, jc.IsTrue)
   416  }
   417  
   418  func (s *EnvConfigSuite) TestConfigEnvDoesntExist(c *gc.C) {
   419  	cmd := envcmd.NewEnvCommandBase("dummy", s.client, nil)
   420  	s.writeStore(c, false)
   421  
   422  	_, err := cmd.Config(s.store, nil)
   423  	c.Assert(err, jc.Satisfies, errors.IsNotFound)
   424  	c.Check(s.client.getCalled, jc.IsFalse)
   425  	c.Check(s.client.closeCalled, jc.IsFalse)
   426  }