github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/apiserver/environmentmanager/environmentmanager_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package environmentmanager_test
     5  
     6  import (
     7  	"github.com/juju/loggo"
     8  	"github.com/juju/names"
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  
    12  	"github.com/juju/juju/apiserver/common"
    13  	"github.com/juju/juju/apiserver/environmentmanager"
    14  	"github.com/juju/juju/apiserver/params"
    15  	apiservertesting "github.com/juju/juju/apiserver/testing"
    16  	jujutesting "github.com/juju/juju/juju/testing"
    17  	"github.com/juju/juju/state"
    18  	coretesting "github.com/juju/juju/testing"
    19  	"github.com/juju/juju/version"
    20  
    21  	// Register the providers for the field check test
    22  	_ "github.com/juju/juju/provider/azure"
    23  	_ "github.com/juju/juju/provider/ec2"
    24  	_ "github.com/juju/juju/provider/joyent"
    25  	_ "github.com/juju/juju/provider/local"
    26  	_ "github.com/juju/juju/provider/maas"
    27  	_ "github.com/juju/juju/provider/openstack"
    28  )
    29  
    30  type envManagerSuite struct {
    31  	jujutesting.JujuConnSuite
    32  
    33  	envmanager *environmentmanager.EnvironmentManagerAPI
    34  	resources  *common.Resources
    35  	authoriser apiservertesting.FakeAuthorizer
    36  }
    37  
    38  var _ = gc.Suite(&envManagerSuite{})
    39  
    40  func (s *envManagerSuite) SetUpTest(c *gc.C) {
    41  	s.JujuConnSuite.SetUpTest(c)
    42  	s.resources = common.NewResources()
    43  	s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() })
    44  
    45  	s.authoriser = apiservertesting.FakeAuthorizer{
    46  		Tag: s.AdminUserTag(c),
    47  	}
    48  
    49  	loggo.GetLogger("juju.apiserver.environmentmanager").SetLogLevel(loggo.TRACE)
    50  }
    51  
    52  func (s *envManagerSuite) TestNewAPIAcceptsClient(c *gc.C) {
    53  	anAuthoriser := s.authoriser
    54  	anAuthoriser.Tag = names.NewUserTag("external@remote")
    55  	endPoint, err := environmentmanager.NewEnvironmentManagerAPI(s.State, s.resources, anAuthoriser)
    56  	c.Assert(err, jc.ErrorIsNil)
    57  	c.Assert(endPoint, gc.NotNil)
    58  }
    59  
    60  func (s *envManagerSuite) TestNewAPIRefusesNonClient(c *gc.C) {
    61  	anAuthoriser := s.authoriser
    62  	anAuthoriser.Tag = names.NewUnitTag("mysql/0")
    63  	endPoint, err := environmentmanager.NewEnvironmentManagerAPI(s.State, s.resources, anAuthoriser)
    64  	c.Assert(endPoint, gc.IsNil)
    65  	c.Assert(err, gc.ErrorMatches, "permission denied")
    66  }
    67  
    68  func (s *envManagerSuite) createArgs(c *gc.C, owner names.UserTag) params.EnvironmentCreateArgs {
    69  	return params.EnvironmentCreateArgs{
    70  		OwnerTag: owner.String(),
    71  		Account:  make(map[string]interface{}),
    72  		Config: map[string]interface{}{
    73  			"name":            "test-env",
    74  			"authorized-keys": "ssh-key",
    75  			// And to make it a valid dummy config
    76  			"state-server": false,
    77  		},
    78  	}
    79  }
    80  
    81  func (s *envManagerSuite) createArgsForVersion(c *gc.C, owner names.UserTag, ver interface{}) params.EnvironmentCreateArgs {
    82  	params := s.createArgs(c, owner)
    83  	params.Config["agent-version"] = ver
    84  	return params
    85  }
    86  
    87  func (s *envManagerSuite) setAPIUser(c *gc.C, user names.UserTag) {
    88  	s.authoriser.Tag = user
    89  	envmanager, err := environmentmanager.NewEnvironmentManagerAPI(s.State, s.resources, s.authoriser)
    90  	c.Assert(err, jc.ErrorIsNil)
    91  	s.envmanager = envmanager
    92  }
    93  
    94  func (s *envManagerSuite) TestUserCanCreateEnvironment(c *gc.C) {
    95  	owner := names.NewUserTag("external@remote")
    96  	s.setAPIUser(c, owner)
    97  	env, err := s.envmanager.CreateEnvironment(s.createArgs(c, owner))
    98  	c.Assert(err, jc.ErrorIsNil)
    99  	c.Assert(env.OwnerTag, gc.Equals, owner.String())
   100  	c.Assert(env.Name, gc.Equals, "test-env")
   101  }
   102  
   103  func (s *envManagerSuite) TestAdminCanCreateEnvironmentForSomeoneElse(c *gc.C) {
   104  	s.setAPIUser(c, s.AdminUserTag(c))
   105  	owner := names.NewUserTag("external@remote")
   106  	env, err := s.envmanager.CreateEnvironment(s.createArgs(c, owner))
   107  	c.Assert(err, jc.ErrorIsNil)
   108  	c.Assert(env.OwnerTag, gc.Equals, owner.String())
   109  	c.Assert(env.Name, gc.Equals, "test-env")
   110  }
   111  
   112  func (s *envManagerSuite) TestNonAdminCannotCreateEnvironmentForSomeoneElse(c *gc.C) {
   113  	s.setAPIUser(c, names.NewUserTag("non-admin@remote"))
   114  	owner := names.NewUserTag("external@remote")
   115  	_, err := s.envmanager.CreateEnvironment(s.createArgs(c, owner))
   116  	c.Assert(err, gc.ErrorMatches, "permission denied")
   117  }
   118  
   119  func (s *envManagerSuite) TestRestrictedProviderFields(c *gc.C) {
   120  	s.setAPIUser(c, names.NewUserTag("non-admin@remote"))
   121  	for i, test := range []struct {
   122  		provider string
   123  		expected []string
   124  	}{
   125  		{
   126  			provider: "azure",
   127  			expected: []string{
   128  				"type", "ca-cert", "state-port", "api-port", "syslog-port", "rsyslog-ca-cert",
   129  				"location"},
   130  		}, {
   131  			provider: "dummy",
   132  			expected: []string{
   133  				"type", "ca-cert", "state-port", "api-port", "syslog-port", "rsyslog-ca-cert"},
   134  		}, {
   135  			provider: "joyent",
   136  			expected: []string{
   137  				"type", "ca-cert", "state-port", "api-port", "syslog-port", "rsyslog-ca-cert"},
   138  		}, {
   139  			provider: "local",
   140  			expected: []string{
   141  				"type", "ca-cert", "state-port", "api-port", "syslog-port", "rsyslog-ca-cert",
   142  				"container", "network-bridge", "root-dir"},
   143  		}, {
   144  			provider: "maas",
   145  			expected: []string{
   146  				"type", "ca-cert", "state-port", "api-port", "syslog-port", "rsyslog-ca-cert",
   147  				"maas-server"},
   148  		}, {
   149  			provider: "openstack",
   150  			expected: []string{
   151  				"type", "ca-cert", "state-port", "api-port", "syslog-port", "rsyslog-ca-cert",
   152  				"region", "auth-url", "auth-mode"},
   153  		},
   154  	} {
   155  		c.Logf("%d: %s provider", i, test.provider)
   156  		fields, err := environmentmanager.RestrictedProviderFields(s.envmanager, test.provider)
   157  		c.Check(err, jc.ErrorIsNil)
   158  		c.Check(fields, jc.SameContents, test.expected)
   159  	}
   160  }
   161  
   162  func (s *envManagerSuite) TestConfigSkeleton(c *gc.C) {
   163  	s.setAPIUser(c, names.NewUserTag("non-admin@remote"))
   164  
   165  	_, err := s.envmanager.ConfigSkeleton(
   166  		params.EnvironmentSkeletonConfigArgs{Provider: "ec2"})
   167  	c.Check(err, gc.ErrorMatches, `provider value "ec2" not valid`)
   168  	_, err = s.envmanager.ConfigSkeleton(
   169  		params.EnvironmentSkeletonConfigArgs{Region: "the sun"})
   170  	c.Check(err, gc.ErrorMatches, `region value "the sun" not valid`)
   171  
   172  	skeleton, err := s.envmanager.ConfigSkeleton(params.EnvironmentSkeletonConfigArgs{})
   173  	c.Assert(err, jc.ErrorIsNil)
   174  
   175  	// The apiPort changes every test run as the dummy provider
   176  	// looks for a random open port.
   177  	apiPort := s.Environ.Config().APIPort()
   178  
   179  	c.Assert(skeleton.Config, jc.DeepEquals, params.EnvironConfig{
   180  		"type":        "dummy",
   181  		"ca-cert":     coretesting.CACert,
   182  		"state-port":  1234,
   183  		"api-port":    apiPort,
   184  		"syslog-port": 2345,
   185  	})
   186  }
   187  
   188  func (s *envManagerSuite) TestCreateEnvironmentValidatesConfig(c *gc.C) {
   189  	admin := s.AdminUserTag(c)
   190  	s.setAPIUser(c, admin)
   191  	args := s.createArgs(c, admin)
   192  	delete(args.Config, "state-server")
   193  	_, err := s.envmanager.CreateEnvironment(args)
   194  	c.Assert(err, gc.ErrorMatches, "state-server: expected bool, got nothing")
   195  }
   196  
   197  func (s *envManagerSuite) TestCreateEnvironmentBadConfig(c *gc.C) {
   198  	owner := names.NewUserTag("external@remote")
   199  	s.setAPIUser(c, owner)
   200  	for i, test := range []struct {
   201  		key      string
   202  		value    interface{}
   203  		errMatch string
   204  	}{
   205  		{
   206  			key:      "uuid",
   207  			value:    "anything",
   208  			errMatch: `uuid is generated, you cannot specify one`,
   209  		}, {
   210  			key:      "type",
   211  			value:    "other",
   212  			errMatch: `specified type "other" does not match apiserver "dummy"`,
   213  		}, {
   214  			key:      "ca-cert",
   215  			value:    "some-cert",
   216  			errMatch: `(?s)specified ca-cert "some-cert" does not match apiserver ".*"`,
   217  		}, {
   218  			key:      "state-port",
   219  			value:    9876,
   220  			errMatch: `specified state-port "9876" does not match apiserver "1234"`,
   221  		}, {
   222  			// The api-port is dynamic, but always in user-space, so > 1024.
   223  			key:      "api-port",
   224  			value:    123,
   225  			errMatch: `specified api-port "123" does not match apiserver ".*"`,
   226  		}, {
   227  			key:      "syslog-port",
   228  			value:    1234,
   229  			errMatch: `specified syslog-port "1234" does not match apiserver "2345"`,
   230  		}, {
   231  			key:      "rsyslog-ca-cert",
   232  			value:    "some-cert",
   233  			errMatch: `specified rsyslog-ca-cert "some-cert" does not match apiserver ".*"`,
   234  		},
   235  	} {
   236  		c.Logf("%d: %s", i, test.key)
   237  		args := s.createArgs(c, owner)
   238  		args.Config[test.key] = test.value
   239  		_, err := s.envmanager.CreateEnvironment(args)
   240  		c.Assert(err, gc.ErrorMatches, test.errMatch)
   241  
   242  	}
   243  }
   244  
   245  func (s *envManagerSuite) TestCreateEnvironmentSameAgentVersion(c *gc.C) {
   246  	admin := s.AdminUserTag(c)
   247  	s.setAPIUser(c, admin)
   248  	args := s.createArgsForVersion(c, admin, version.Current.Number.String())
   249  	_, err := s.envmanager.CreateEnvironment(args)
   250  	c.Assert(err, jc.ErrorIsNil)
   251  }
   252  
   253  func (s *envManagerSuite) TestCreateEnvironmentBadAgentVersion(c *gc.C) {
   254  	admin := s.AdminUserTag(c)
   255  	s.setAPIUser(c, admin)
   256  
   257  	bigger := version.Current.Number
   258  	bigger.Minor += 1
   259  
   260  	smaller := version.Current.Number
   261  	smaller.Minor -= 1
   262  
   263  	for i, test := range []struct {
   264  		value    interface{}
   265  		errMatch string
   266  	}{
   267  		{
   268  			value:    42,
   269  			errMatch: "agent-version must be a string but has type 'int'",
   270  		}, {
   271  			value:    "not a number",
   272  			errMatch: `invalid version "not a number"`,
   273  		}, {
   274  			value:    bigger.String(),
   275  			errMatch: "agent-version cannot be greater than the server: .*",
   276  		}, {
   277  			value:    smaller.String(),
   278  			errMatch: "no tools found for version .*",
   279  		},
   280  	} {
   281  		c.Logf("test %d", i)
   282  		args := s.createArgsForVersion(c, admin, test.value)
   283  		_, err := s.envmanager.CreateEnvironment(args)
   284  		c.Check(err, gc.ErrorMatches, test.errMatch)
   285  	}
   286  }
   287  
   288  func (s *envManagerSuite) TestListEnvironmentsForSelf(c *gc.C) {
   289  	user := names.NewUserTag("external@remote")
   290  	s.setAPIUser(c, user)
   291  	result, err := s.envmanager.ListEnvironments(params.Entity{user.String()})
   292  	c.Assert(err, jc.ErrorIsNil)
   293  	c.Assert(result.Environments, gc.HasLen, 0)
   294  }
   295  
   296  func (s *envManagerSuite) checkEnvironmentMatches(c *gc.C, env params.Environment, expected *state.Environment) {
   297  	c.Check(env.Name, gc.Equals, expected.Name())
   298  	c.Check(env.UUID, gc.Equals, expected.UUID())
   299  	c.Check(env.OwnerTag, gc.Equals, expected.Owner().String())
   300  }
   301  
   302  func (s *envManagerSuite) TestListEnvironmentsAdminSelf(c *gc.C) {
   303  	user := s.AdminUserTag(c)
   304  	s.setAPIUser(c, user)
   305  	result, err := s.envmanager.ListEnvironments(params.Entity{user.String()})
   306  	c.Assert(err, jc.ErrorIsNil)
   307  	c.Assert(result.Environments, gc.HasLen, 1)
   308  	expected, err := s.State.Environment()
   309  	c.Assert(err, jc.ErrorIsNil)
   310  	s.checkEnvironmentMatches(c, result.Environments[0], expected)
   311  }
   312  
   313  func (s *envManagerSuite) TestListEnvironmentsAdminListsOther(c *gc.C) {
   314  	user := s.AdminUserTag(c)
   315  	s.setAPIUser(c, user)
   316  	other := names.NewUserTag("external@remote")
   317  	result, err := s.envmanager.ListEnvironments(params.Entity{other.String()})
   318  	c.Assert(err, jc.ErrorIsNil)
   319  	c.Assert(result.Environments, gc.HasLen, 0)
   320  }
   321  
   322  func (s *envManagerSuite) TestListEnvironmentsDenied(c *gc.C) {
   323  	user := names.NewUserTag("external@remote")
   324  	s.setAPIUser(c, user)
   325  	other := names.NewUserTag("other@remote")
   326  	_, err := s.envmanager.ListEnvironments(params.Entity{other.String()})
   327  	c.Assert(err, gc.ErrorMatches, "permission denied")
   328  }