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