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