github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/client/spaces/spaces_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package spaces_test
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  	"gopkg.in/juju/names.v2"
    13  
    14  	"github.com/juju/juju/apiserver/common"
    15  	"github.com/juju/juju/apiserver/facades/client/spaces"
    16  	"github.com/juju/juju/apiserver/params"
    17  	apiservertesting "github.com/juju/juju/apiserver/testing"
    18  	"github.com/juju/juju/environs/context"
    19  	"github.com/juju/juju/network"
    20  	coretesting "github.com/juju/juju/testing"
    21  )
    22  
    23  type SpacesSuite struct {
    24  	coretesting.BaseSuite
    25  	apiservertesting.StubNetwork
    26  
    27  	resources  *common.Resources
    28  	authorizer apiservertesting.FakeAuthorizer
    29  	facade     spaces.API
    30  
    31  	callContext context.ProviderCallContext
    32  }
    33  
    34  var _ = gc.Suite(&SpacesSuite{})
    35  
    36  func (s *SpacesSuite) SetUpSuite(c *gc.C) {
    37  	s.StubNetwork.SetUpSuite(c)
    38  	s.BaseSuite.SetUpSuite(c)
    39  }
    40  
    41  func (s *SpacesSuite) TearDownSuite(c *gc.C) {
    42  	s.BaseSuite.TearDownSuite(c)
    43  }
    44  
    45  func (s *SpacesSuite) SetUpTest(c *gc.C) {
    46  	s.BaseSuite.SetUpTest(c)
    47  	apiservertesting.BackingInstance.SetUp(c, apiservertesting.StubZonedNetworkingEnvironName, apiservertesting.WithZones, apiservertesting.WithSpaces, apiservertesting.WithSubnets)
    48  
    49  	s.resources = common.NewResources()
    50  	s.authorizer = apiservertesting.FakeAuthorizer{
    51  		Tag:        names.NewUserTag("admin"),
    52  		Controller: false,
    53  	}
    54  
    55  	s.callContext = context.NewCloudCallContext()
    56  	var err error
    57  	s.facade, err = spaces.NewAPIWithBacking(
    58  		apiservertesting.BackingInstance,
    59  		s.callContext,
    60  		s.resources, s.authorizer,
    61  	)
    62  	c.Assert(err, jc.ErrorIsNil)
    63  	c.Assert(s.facade, gc.NotNil)
    64  }
    65  
    66  func (s *SpacesSuite) TearDownTest(c *gc.C) {
    67  	if s.resources != nil {
    68  		s.resources.StopAll()
    69  	}
    70  	s.BaseSuite.TearDownTest(c)
    71  }
    72  
    73  func (s *SpacesSuite) TestNewAPIWithBacking(c *gc.C) {
    74  	// Clients are allowed.
    75  	facade, err := spaces.NewAPIWithBacking(
    76  		apiservertesting.BackingInstance,
    77  		s.callContext,
    78  		s.resources, s.authorizer,
    79  	)
    80  	c.Assert(err, jc.ErrorIsNil)
    81  	c.Assert(facade, gc.NotNil)
    82  	// No calls so far.
    83  	apiservertesting.CheckMethodCalls(c, apiservertesting.SharedStub)
    84  
    85  	// Agents are not allowed
    86  	agentAuthorizer := s.authorizer
    87  	agentAuthorizer.Tag = names.NewMachineTag("42")
    88  	facade, err = spaces.NewAPIWithBacking(
    89  		apiservertesting.BackingInstance,
    90  		context.NewCloudCallContext(),
    91  		s.resources,
    92  		agentAuthorizer,
    93  	)
    94  	c.Assert(err, jc.DeepEquals, common.ErrPerm)
    95  	c.Assert(facade, gc.IsNil)
    96  	// No calls so far.
    97  	apiservertesting.CheckMethodCalls(c, apiservertesting.SharedStub)
    98  }
    99  
   100  type checkAddSpacesParams struct {
   101  	Name      string
   102  	Subnets   []string
   103  	Error     string
   104  	MakesCall bool
   105  	Public    bool
   106  }
   107  
   108  func (s *SpacesSuite) checkAddSpaces(c *gc.C, p checkAddSpacesParams) {
   109  	args := params.CreateSpaceParams{}
   110  	if p.Name != "" {
   111  		args.SpaceTag = "space-" + p.Name
   112  	}
   113  	if len(p.Subnets) > 0 {
   114  		for _, cidr := range p.Subnets {
   115  			args.SubnetTags = append(args.SubnetTags, "subnet-"+cidr)
   116  		}
   117  	}
   118  	args.Public = p.Public
   119  
   120  	spaces := params.CreateSpacesParams{}
   121  	spaces.Spaces = append(spaces.Spaces, args)
   122  	results, err := s.facade.CreateSpaces(spaces)
   123  
   124  	c.Assert(len(results.Results), gc.Equals, 1)
   125  	c.Assert(err, gc.IsNil)
   126  	if p.Error == "" {
   127  		c.Assert(results.Results[0].Error, gc.IsNil)
   128  	} else {
   129  		c.Assert(results.Results[0].Error, gc.NotNil)
   130  		c.Assert(results.Results[0].Error, gc.ErrorMatches, p.Error)
   131  	}
   132  
   133  	baseCalls := []apiservertesting.StubMethodCall{
   134  		apiservertesting.BackingCall("ModelConfig"),
   135  		apiservertesting.BackingCall("CloudSpec"),
   136  		apiservertesting.ProviderCall("Open", apiservertesting.BackingInstance.EnvConfig),
   137  		apiservertesting.ZonedNetworkingEnvironCall("SupportsSpaces", s.callContext),
   138  	}
   139  
   140  	// AddSpace from the api always uses an empty ProviderId.
   141  	addSpaceCalls := append(baseCalls, apiservertesting.BackingCall("AddSpace", p.Name, network.Id(""), p.Subnets, p.Public))
   142  
   143  	if p.Error == "" || p.MakesCall {
   144  		apiservertesting.CheckMethodCalls(c, apiservertesting.SharedStub, addSpaceCalls...)
   145  	} else {
   146  		apiservertesting.CheckMethodCalls(c, apiservertesting.SharedStub, baseCalls...)
   147  	}
   148  }
   149  
   150  func (s *SpacesSuite) TestAddSpacesOneSubnet(c *gc.C) {
   151  	p := checkAddSpacesParams{
   152  		Name:    "foo",
   153  		Subnets: []string{"10.0.0.0/24"},
   154  	}
   155  	s.checkAddSpaces(c, p)
   156  }
   157  
   158  func (s *SpacesSuite) TestAddSpacesTwoSubnets(c *gc.C) {
   159  	p := checkAddSpacesParams{
   160  		Name:    "foo",
   161  		Subnets: []string{"10.0.0.0/24", "10.0.1.0/24"},
   162  	}
   163  	s.checkAddSpaces(c, p)
   164  }
   165  
   166  func (s *SpacesSuite) TestAddSpacesManySubnets(c *gc.C) {
   167  	p := checkAddSpacesParams{
   168  		Name: "foo",
   169  		Subnets: []string{"10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24",
   170  			"10.0.3.0/24", "10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"},
   171  	}
   172  	s.checkAddSpaces(c, p)
   173  }
   174  
   175  func (s *SpacesSuite) TestAddSpacesAPIError(c *gc.C) {
   176  	apiservertesting.SharedStub.SetErrors(
   177  		nil,                                // Backing.ModelConfig()
   178  		nil,                                // Backing.CloudSpec()
   179  		nil,                                // Provider.Open()
   180  		nil,                                // ZonedNetworkingEnviron.SupportsSpaces()
   181  		errors.AlreadyExistsf("space-foo"), // Backing.AddSpace()
   182  	)
   183  	p := checkAddSpacesParams{
   184  		Name:      "foo",
   185  		Subnets:   []string{"10.0.0.0/24"},
   186  		MakesCall: true,
   187  		Error:     "space-foo already exists",
   188  	}
   189  	s.checkAddSpaces(c, p)
   190  }
   191  
   192  func (s *SpacesSuite) TestCreateInvalidSpace(c *gc.C) {
   193  	p := checkAddSpacesParams{
   194  		Name:    "-",
   195  		Subnets: []string{"10.0.0.0/24"},
   196  		Error:   `"space--" is not a valid space tag`,
   197  	}
   198  	s.checkAddSpaces(c, p)
   199  }
   200  
   201  func (s *SpacesSuite) TestCreateInvalidSubnet(c *gc.C) {
   202  	p := checkAddSpacesParams{
   203  		Name:    "foo",
   204  		Subnets: []string{"bar"},
   205  		Error:   `"subnet-bar" is not a valid subnet tag`,
   206  	}
   207  	s.checkAddSpaces(c, p)
   208  }
   209  
   210  func (s *SpacesSuite) TestPublic(c *gc.C) {
   211  	p := checkAddSpacesParams{
   212  		Name:    "foo",
   213  		Subnets: []string{"10.0.0.0/24"},
   214  		Public:  true,
   215  	}
   216  	s.checkAddSpaces(c, p)
   217  }
   218  
   219  func (s *SpacesSuite) TestEmptySpaceName(c *gc.C) {
   220  	p := checkAddSpacesParams{
   221  		Subnets: []string{"10.0.0.0/24"},
   222  		Error:   `"" is not a valid tag`,
   223  	}
   224  	s.checkAddSpaces(c, p)
   225  }
   226  
   227  func (s *SpacesSuite) TestNoSubnets(c *gc.C) {
   228  	p := checkAddSpacesParams{
   229  		Name:    "foo",
   230  		Subnets: nil,
   231  	}
   232  	s.checkAddSpaces(c, p)
   233  }
   234  
   235  func (s *SpacesSuite) TestListSpacesDefault(c *gc.C) {
   236  	expected := []params.Space{{
   237  		Name: "default",
   238  		Subnets: []params.Subnet{{
   239  			CIDR:       "192.168.0.0/24",
   240  			ProviderId: "provider-192.168.0.0/24",
   241  			Zones:      []string{"foo"},
   242  			Status:     "in-use",
   243  			SpaceTag:   "space-default",
   244  		}, {
   245  			CIDR:       "192.168.3.0/24",
   246  			ProviderId: "provider-192.168.3.0/24",
   247  			VLANTag:    23,
   248  			Zones:      []string{"bar", "bam"},
   249  			SpaceTag:   "space-default",
   250  		}},
   251  	}, {
   252  		Name: "dmz",
   253  		Subnets: []params.Subnet{{
   254  			CIDR:       "192.168.1.0/24",
   255  			ProviderId: "provider-192.168.1.0/24",
   256  			VLANTag:    23,
   257  			Zones:      []string{"bar", "bam"},
   258  			SpaceTag:   "space-dmz",
   259  		}},
   260  	}, {
   261  		Name: "private",
   262  		Subnets: []params.Subnet{{
   263  			CIDR:       "192.168.2.0/24",
   264  			ProviderId: "provider-192.168.2.0/24",
   265  			Zones:      []string{"foo"},
   266  			Status:     "in-use",
   267  			SpaceTag:   "space-private",
   268  		}},
   269  	}}
   270  	spaces, err := s.facade.ListSpaces()
   271  	c.Assert(err, jc.ErrorIsNil)
   272  	c.Assert(spaces.Results, jc.DeepEquals, expected)
   273  }
   274  
   275  func (s *SpacesSuite) TestListSpacesAllSpacesError(c *gc.C) {
   276  	boom := errors.New("backing boom")
   277  	apiservertesting.BackingInstance.SetErrors(boom)
   278  	_, err := s.facade.ListSpaces()
   279  	c.Assert(err, gc.ErrorMatches, "getting environ: backing boom")
   280  }
   281  
   282  func (s *SpacesSuite) TestListSpacesSubnetsError(c *gc.C) {
   283  	apiservertesting.SharedStub.SetErrors(
   284  		nil,                                 // Backing.ModelConfig()
   285  		nil,                                 // Backing.CloudSpec()
   286  		nil,                                 // Provider.Open()
   287  		nil,                                 // ZonedNetworkingEnviron.SupportsSpaces()
   288  		nil,                                 // Backing.AllSpaces()
   289  		errors.New("space0 subnets failed"), // Space.Subnets()
   290  		errors.New("space1 subnets failed"), // Space.Subnets()
   291  		errors.New("space2 subnets failed"), // Space.Subnets()
   292  	)
   293  
   294  	results, err := s.facade.ListSpaces()
   295  	for i, space := range results.Results {
   296  		errmsg := fmt.Sprintf("fetching subnets: space%d subnets failed", i)
   297  		c.Assert(space.Error, gc.ErrorMatches, errmsg)
   298  	}
   299  	c.Assert(err, jc.ErrorIsNil)
   300  }
   301  
   302  func (s *SpacesSuite) TestListSpacesSubnetsSingleSubnetError(c *gc.C) {
   303  	boom := errors.New("boom")
   304  	apiservertesting.SharedStub.SetErrors(
   305  		nil,  // Backing.ModelConfig()
   306  		nil,  // Backing.CloudSpec()
   307  		nil,  // Provider.Open()
   308  		nil,  // ZonedNetworkingEnviron.SupportsSpaces()
   309  		nil,  // Backing.AllSpaces()
   310  		nil,  // Space.Subnets() (1st no error)
   311  		boom, // Space.Subnets() (2nd with error)
   312  	)
   313  
   314  	results, err := s.facade.ListSpaces()
   315  	for i, space := range results.Results {
   316  		if i == 1 {
   317  			c.Assert(space.Error, gc.ErrorMatches, "fetching subnets: boom")
   318  		} else {
   319  			c.Assert(space.Error, gc.IsNil)
   320  		}
   321  	}
   322  	c.Assert(err, jc.ErrorIsNil)
   323  }
   324  
   325  func (s *SpacesSuite) TestCreateSpacesModelConfigError(c *gc.C) {
   326  	apiservertesting.SharedStub.SetErrors(
   327  		errors.New("boom"), // Backing.ModelConfig()
   328  	)
   329  
   330  	spaces := params.CreateSpacesParams{}
   331  	_, err := s.facade.CreateSpaces(spaces)
   332  	c.Assert(err, gc.ErrorMatches, "getting environ: boom")
   333  }
   334  
   335  func (s *SpacesSuite) TestCreateSpacesProviderOpenError(c *gc.C) {
   336  	apiservertesting.SharedStub.SetErrors(
   337  		nil,                // Backing.ModelConfig()
   338  		nil,                // Backing.CloudSpec()
   339  		errors.New("boom"), // Provider.Open()
   340  	)
   341  
   342  	spaces := params.CreateSpacesParams{}
   343  	_, err := s.facade.CreateSpaces(spaces)
   344  	c.Assert(err, gc.ErrorMatches, "getting environ: boom")
   345  }
   346  
   347  func (s *SpacesSuite) TestCreateSpacesNotSupportedError(c *gc.C) {
   348  	apiservertesting.SharedStub.SetErrors(
   349  		nil,                            // Backing.ModelConfig()
   350  		nil,                            // Backing.CloudSpec()
   351  		nil,                            // Provider.Open()
   352  		errors.NotSupportedf("spaces"), // ZonedNetworkingEnviron.SupportsSpaces()
   353  	)
   354  
   355  	spaces := params.CreateSpacesParams{}
   356  	_, err := s.facade.CreateSpaces(spaces)
   357  	c.Assert(err, gc.ErrorMatches, "spaces not supported")
   358  }
   359  
   360  func (s *SpacesSuite) TestListSpacesNotSupportedError(c *gc.C) {
   361  	apiservertesting.SharedStub.SetErrors(
   362  		nil,                            // Backing.ModelConfig()
   363  		nil,                            // Backing.CloudSpec()
   364  		nil,                            // Provider.Open
   365  		errors.NotSupportedf("spaces"), // ZonedNetworkingEnviron.SupportsSpaces()
   366  	)
   367  
   368  	_, err := s.facade.ListSpaces()
   369  	c.Assert(err, gc.ErrorMatches, "spaces not supported")
   370  }
   371  
   372  func (s *SpacesSuite) TestReloadSpacesNotSupportedError(c *gc.C) {
   373  	apiservertesting.SharedStub.SetErrors(
   374  		nil,                            // Backing.ModelConfig()
   375  		nil,                            // Backing.CloudSpec()
   376  		nil,                            // Provider.Open()
   377  		errors.NotSupportedf("spaces"), // ZonedNetworkingEnviron.SupportsSpaces()
   378  	)
   379  	err := s.facade.ReloadSpaces()
   380  	c.Assert(err, gc.ErrorMatches, "spaces not supported")
   381  }
   382  
   383  func (s *SpacesSuite) TestReloadSpacesUserDenied(c *gc.C) {
   384  	agentAuthorizer := s.authorizer
   385  	agentAuthorizer.Tag = names.NewUserTag("regular")
   386  	facade, err := spaces.NewAPIWithBacking(
   387  		apiservertesting.BackingInstance,
   388  		context.NewCloudCallContext(),
   389  		s.resources, agentAuthorizer,
   390  	)
   391  	c.Assert(err, jc.ErrorIsNil)
   392  	err = facade.ReloadSpaces()
   393  	c.Check(err, gc.ErrorMatches, "permission denied")
   394  	apiservertesting.CheckMethodCalls(c, apiservertesting.SharedStub)
   395  }