github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/controller/firewaller/firewaller_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package firewaller_test
     5  
     6  import (
     7  	"sort"
     8  
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  	"gopkg.in/juju/names.v2"
    12  
    13  	"github.com/juju/juju/apiserver/common"
    14  	"github.com/juju/juju/apiserver/common/cloudspec"
    15  	commontesting "github.com/juju/juju/apiserver/common/testing"
    16  	"github.com/juju/juju/apiserver/facade"
    17  	"github.com/juju/juju/apiserver/facades/controller/firewaller"
    18  	"github.com/juju/juju/apiserver/params"
    19  	apiservertesting "github.com/juju/juju/apiserver/testing"
    20  	"github.com/juju/juju/state"
    21  	statetesting "github.com/juju/juju/state/testing"
    22  	coretesting "github.com/juju/juju/testing"
    23  )
    24  
    25  type firewallerSuite struct {
    26  	firewallerBaseSuite
    27  	*commontesting.ModelWatcherTest
    28  
    29  	firewaller *firewaller.FirewallerAPIV3
    30  }
    31  
    32  var _ = gc.Suite(&firewallerSuite{})
    33  
    34  func (s *firewallerSuite) SetUpTest(c *gc.C) {
    35  	s.firewallerBaseSuite.setUpTest(c)
    36  
    37  	_, err := s.State.AddSubnet(state.SubnetInfo{CIDR: "10.20.30.0/24"})
    38  	c.Assert(err, jc.ErrorIsNil)
    39  
    40  	cloudSpecAPI := cloudspec.NewCloudSpec(
    41  		cloudspec.MakeCloudSpecGetterForModel(s.State),
    42  		common.AuthFuncForTag(s.Model.ModelTag()),
    43  	)
    44  	// Create a firewaller API for the machine.
    45  	firewallerAPI, err := firewaller.NewFirewallerAPI(
    46  		firewaller.StateShim(s.State, s.Model),
    47  		s.resources,
    48  		s.authorizer,
    49  		cloudSpecAPI,
    50  	)
    51  	c.Assert(err, jc.ErrorIsNil)
    52  	s.firewaller = firewallerAPI
    53  	s.ModelWatcherTest = commontesting.NewModelWatcherTest(s.firewaller, s.State, s.resources)
    54  }
    55  
    56  func (s *firewallerSuite) TestFirewallerFailsWithNonControllerUser(c *gc.C) {
    57  	constructor := func(st *state.State, res facade.Resources, auth facade.Authorizer) error {
    58  		m, err := st.Model()
    59  		c.Assert(err, jc.ErrorIsNil)
    60  
    61  		_, err = firewaller.NewFirewallerAPI(firewaller.StateShim(st, m), res, auth, nil)
    62  		return err
    63  	}
    64  	s.testFirewallerFailsWithNonControllerUser(c, constructor)
    65  }
    66  
    67  func (s *firewallerSuite) TestLife(c *gc.C) {
    68  	s.testLife(c, s.firewaller)
    69  }
    70  
    71  func (s *firewallerSuite) TestInstanceId(c *gc.C) {
    72  	s.testInstanceId(c, s.firewaller)
    73  }
    74  
    75  func (s *firewallerSuite) TestWatchModelMachines(c *gc.C) {
    76  	s.testWatchModelMachines(c, s.firewaller)
    77  }
    78  
    79  func (s *firewallerSuite) TestWatch(c *gc.C) {
    80  	s.testWatch(c, s.firewaller, cannotWatchUnits)
    81  }
    82  
    83  func (s *firewallerSuite) TestWatchUnits(c *gc.C) {
    84  	s.testWatchUnits(c, s.firewaller)
    85  }
    86  
    87  func (s *firewallerSuite) TestGetExposed(c *gc.C) {
    88  	s.testGetExposed(c, s.firewaller)
    89  }
    90  
    91  func (s *firewallerSuite) TestGetAssignedMachine(c *gc.C) {
    92  	s.testGetAssignedMachine(c, s.firewaller)
    93  }
    94  
    95  func (s *firewallerSuite) openPorts(c *gc.C) {
    96  	// Open some ports on the units.
    97  	err := s.units[0].OpenPortsOnSubnet("10.20.30.0/24", "tcp", 1234, 1400)
    98  	c.Assert(err, jc.ErrorIsNil)
    99  	err = s.units[0].OpenPort("tcp", 4321)
   100  	c.Assert(err, jc.ErrorIsNil)
   101  	err = s.units[2].OpenPorts("udp", 1111, 2222)
   102  	c.Assert(err, jc.ErrorIsNil)
   103  }
   104  
   105  func (s *firewallerSuite) TestWatchOpenedPorts(c *gc.C) {
   106  	c.Assert(s.resources.Count(), gc.Equals, 0)
   107  
   108  	s.openPorts(c)
   109  	expectChanges := []string{
   110  		"0:", // empty subnet is ok (until it can be made mandatory)
   111  		"0:10.20.30.0/24",
   112  		"2:",
   113  	}
   114  
   115  	fakeModelTag := names.NewModelTag("deadbeef-deaf-face-feed-0123456789ab")
   116  	args := addFakeEntities(params.Entities{Entities: []params.Entity{
   117  		{Tag: fakeModelTag.String()},
   118  		{Tag: s.machines[0].Tag().String()},
   119  		{Tag: s.application.Tag().String()},
   120  		{Tag: s.units[0].Tag().String()},
   121  	}})
   122  	result, err := s.firewaller.WatchOpenedPorts(args)
   123  	sort.Strings(result.Results[0].Changes)
   124  	c.Assert(err, jc.ErrorIsNil)
   125  	c.Assert(result, jc.DeepEquals, params.StringsWatchResults{
   126  		Results: []params.StringsWatchResult{
   127  			{Changes: expectChanges, StringsWatcherId: "1"},
   128  			{Error: apiservertesting.ErrUnauthorized},
   129  			{Error: apiservertesting.ErrUnauthorized},
   130  			{Error: apiservertesting.ErrUnauthorized},
   131  			{Error: apiservertesting.ErrUnauthorized},
   132  			{Error: apiservertesting.ErrUnauthorized},
   133  			{Error: apiservertesting.ErrUnauthorized},
   134  			{Error: apiservertesting.ErrUnauthorized},
   135  			{Error: apiservertesting.ErrUnauthorized},
   136  			{Error: apiservertesting.ErrUnauthorized},
   137  		},
   138  	})
   139  
   140  	// Verify the resource was registered and stop when done
   141  	c.Assert(s.resources.Count(), gc.Equals, 1)
   142  	c.Assert(result.Results[0].StringsWatcherId, gc.Equals, "1")
   143  	resource := s.resources.Get("1")
   144  	defer statetesting.AssertStop(c, resource)
   145  
   146  	// Check that the Watch has consumed the initial event ("returned" in
   147  	// the Watch call)
   148  	wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher))
   149  	wc.AssertNoChange()
   150  }
   151  
   152  func (s *firewallerSuite) TestGetMachinePorts(c *gc.C) {
   153  	s.openPorts(c)
   154  
   155  	subnetTag := names.NewSubnetTag("10.20.30.0/24").String()
   156  	args := params.MachinePortsParams{
   157  		Params: []params.MachinePorts{
   158  			{MachineTag: s.machines[0].Tag().String(), SubnetTag: ""},
   159  			{MachineTag: s.machines[0].Tag().String(), SubnetTag: subnetTag},
   160  			{MachineTag: s.machines[1].Tag().String(), SubnetTag: ""},
   161  			{MachineTag: s.machines[2].Tag().String(), SubnetTag: ""},
   162  			{MachineTag: s.machines[0].Tag().String(), SubnetTag: "invalid"},
   163  			{MachineTag: "machine-42", SubnetTag: ""},
   164  			{MachineTag: s.machines[0].Tag().String(), SubnetTag: "subnet-bad"},
   165  		},
   166  	}
   167  	unit0Tag := s.units[0].Tag().String()
   168  	expectPortsMachine0NoSubnet := []params.MachinePortRange{
   169  		{UnitTag: unit0Tag, PortRange: params.PortRange{
   170  			FromPort: 4321, ToPort: 4321, Protocol: "tcp",
   171  		}},
   172  	}
   173  	expectPortsMachine0WithSubnet := []params.MachinePortRange{
   174  		{UnitTag: unit0Tag, PortRange: params.PortRange{
   175  			FromPort: 1234, ToPort: 1400, Protocol: "tcp",
   176  		}},
   177  	}
   178  	unit2Tag := s.units[2].Tag().String()
   179  	expectPortsMachine2 := []params.MachinePortRange{
   180  		{UnitTag: unit2Tag, PortRange: params.PortRange{
   181  			FromPort: 1111, ToPort: 2222, Protocol: "udp",
   182  		}},
   183  	}
   184  	result, err := s.firewaller.GetMachinePorts(args)
   185  	c.Assert(err, jc.ErrorIsNil)
   186  	c.Assert(result, jc.DeepEquals, params.MachinePortsResults{
   187  		Results: []params.MachinePortsResult{
   188  			{Ports: expectPortsMachine0NoSubnet},
   189  			{Ports: expectPortsMachine0WithSubnet},
   190  			{Error: nil, Ports: nil},
   191  			{Ports: expectPortsMachine2},
   192  			{Error: apiservertesting.ServerError(`"invalid" is not a valid tag`)},
   193  			{Error: apiservertesting.NotFoundError("machine 42")},
   194  			{Error: apiservertesting.ServerError(`"subnet-bad" is not a valid subnet tag`)},
   195  		},
   196  	})
   197  
   198  }
   199  
   200  func (s *firewallerSuite) TestGetMachineActiveSubnets(c *gc.C) {
   201  	s.openPorts(c)
   202  
   203  	subnetTag := names.NewSubnetTag("10.20.30.0/24").String()
   204  	args := addFakeEntities(params.Entities{Entities: []params.Entity{
   205  		{Tag: s.machines[0].Tag().String()},
   206  		{Tag: s.machines[1].Tag().String()},
   207  		{Tag: s.machines[2].Tag().String()},
   208  		{Tag: s.application.Tag().String()},
   209  		{Tag: s.units[0].Tag().String()},
   210  	}})
   211  	expectResultsMachine0 := []string{subnetTag, ""}
   212  	expectResultsMachine2 := []string{""}
   213  	result, err := s.firewaller.GetMachineActiveSubnets(args)
   214  	c.Assert(err, jc.ErrorIsNil)
   215  	c.Assert(result, jc.DeepEquals, params.StringsResults{
   216  		Results: []params.StringsResult{
   217  			{Result: expectResultsMachine0},
   218  			{Result: nil, Error: nil},
   219  			{Result: expectResultsMachine2},
   220  			{Error: apiservertesting.ServerError(`"application-wordpress" is not a valid machine tag`)},
   221  			{Error: apiservertesting.ServerError(`"unit-wordpress-0" is not a valid machine tag`)},
   222  			{Error: apiservertesting.NotFoundError("machine 42")},
   223  			{Error: apiservertesting.ServerError(`"unit-foo-0" is not a valid machine tag`)},
   224  			{Error: apiservertesting.ServerError(`"application-bar" is not a valid machine tag`)},
   225  			{Error: apiservertesting.ServerError(`"user-foo" is not a valid machine tag`)},
   226  			{Error: apiservertesting.ServerError(`"foo-bar" is not a valid tag`)},
   227  			{Error: apiservertesting.ServerError(`"" is not a valid tag`)},
   228  		},
   229  	})
   230  }
   231  
   232  func (s *firewallerSuite) TestAreManuallyProvisioned(c *gc.C) {
   233  	m, err := s.State.AddOneMachine(state.MachineTemplate{
   234  		Series:     "quantal",
   235  		Jobs:       []state.MachineJob{state.JobHostUnits},
   236  		InstanceId: "2",
   237  		Nonce:      "manual:",
   238  	})
   239  	c.Assert(err, jc.ErrorIsNil)
   240  
   241  	args := addFakeEntities(params.Entities{Entities: []params.Entity{
   242  		{Tag: s.machines[0].Tag().String()},
   243  		{Tag: s.machines[1].Tag().String()},
   244  		{Tag: m.Tag().String()},
   245  		{Tag: s.application.Tag().String()},
   246  		{Tag: s.units[0].Tag().String()},
   247  	}})
   248  
   249  	apiv5 := &firewaller.FirewallerAPIV5{
   250  		&firewaller.FirewallerAPIV4{
   251  			FirewallerAPIV3:     s.firewaller,
   252  			ControllerConfigAPI: common.NewControllerConfig(newMockState(coretesting.ModelTag.Id())),
   253  		}}
   254  
   255  	result, err := apiv5.AreManuallyProvisioned(args)
   256  	c.Assert(err, jc.ErrorIsNil)
   257  	c.Assert(result, jc.DeepEquals, params.BoolResults{
   258  		Results: []params.BoolResult{
   259  			{Result: false, Error: nil},
   260  			{Result: false, Error: nil},
   261  			{Result: true, Error: nil},
   262  			{Result: false, Error: apiservertesting.ServerError(`"application-wordpress" is not a valid machine tag`)},
   263  			{Result: false, Error: apiservertesting.ServerError(`"unit-wordpress-0" is not a valid machine tag`)},
   264  			{Result: false, Error: apiservertesting.NotFoundError("machine 42")},
   265  			{Result: false, Error: apiservertesting.ServerError(`"unit-foo-0" is not a valid machine tag`)},
   266  			{Result: false, Error: apiservertesting.ServerError(`"application-bar" is not a valid machine tag`)},
   267  			{Result: false, Error: apiservertesting.ServerError(`"user-foo" is not a valid machine tag`)},
   268  			{Result: false, Error: apiservertesting.ServerError(`"foo-bar" is not a valid tag`)},
   269  			{Result: false, Error: apiservertesting.ServerError(`"" is not a valid tag`)},
   270  		},
   271  	})
   272  }