github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/worker/firewaller/firewaller_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package firewaller_test
     5  
     6  import (
     7  	"reflect"
     8  	stdtesting "testing"
     9  	"time"
    10  
    11  	"github.com/juju/utils"
    12  	gc "launchpad.net/gocheck"
    13  
    14  	"github.com/juju/juju/environs/config"
    15  	"github.com/juju/juju/instance"
    16  	"github.com/juju/juju/juju"
    17  	"github.com/juju/juju/juju/testing"
    18  	"github.com/juju/juju/network"
    19  	"github.com/juju/juju/provider/dummy"
    20  	"github.com/juju/juju/state"
    21  	"github.com/juju/juju/state/api"
    22  	apifirewaller "github.com/juju/juju/state/api/firewaller"
    23  	coretesting "github.com/juju/juju/testing"
    24  	"github.com/juju/juju/worker"
    25  	"github.com/juju/juju/worker/firewaller"
    26  )
    27  
    28  func TestPackage(t *stdtesting.T) {
    29  	coretesting.MgoTestPackage(t)
    30  }
    31  
    32  type FirewallerSuite struct {
    33  	testing.JujuConnSuite
    34  	op    <-chan dummy.Operation
    35  	charm *state.Charm
    36  
    37  	st         *api.State
    38  	firewaller *apifirewaller.State
    39  }
    40  
    41  type FirewallerGlobalModeSuite struct {
    42  	FirewallerSuite
    43  }
    44  
    45  var _ worker.Worker = (*firewaller.Firewaller)(nil)
    46  
    47  // assertPorts retrieves the open ports of the instance and compares them
    48  // to the expected.
    49  func (s *FirewallerSuite) assertPorts(c *gc.C, inst instance.Instance, machineId string, expected []network.Port) {
    50  	s.BackingState.StartSync()
    51  	start := time.Now()
    52  	for {
    53  		got, err := inst.Ports(machineId)
    54  		if err != nil {
    55  			c.Fatal(err)
    56  			return
    57  		}
    58  		network.SortPorts(got)
    59  		network.SortPorts(expected)
    60  		if reflect.DeepEqual(got, expected) {
    61  			c.Succeed()
    62  			return
    63  		}
    64  		if time.Since(start) > coretesting.LongWait {
    65  			c.Fatalf("timed out: expected %q; got %q", expected, got)
    66  			return
    67  		}
    68  		time.Sleep(coretesting.ShortWait)
    69  	}
    70  }
    71  
    72  // assertEnvironPorts retrieves the open ports of environment and compares them
    73  // to the expected.
    74  func (s *FirewallerSuite) assertEnvironPorts(c *gc.C, expected []network.Port) {
    75  	s.BackingState.StartSync()
    76  	start := time.Now()
    77  	for {
    78  		got, err := s.Conn.Environ.Ports()
    79  		if err != nil {
    80  			c.Fatal(err)
    81  			return
    82  		}
    83  		network.SortPorts(got)
    84  		network.SortPorts(expected)
    85  		if reflect.DeepEqual(got, expected) {
    86  			c.Succeed()
    87  			return
    88  		}
    89  		if time.Since(start) > coretesting.LongWait {
    90  			c.Fatalf("timed out: expected %q; got %q", expected, got)
    91  			return
    92  		}
    93  		time.Sleep(coretesting.ShortWait)
    94  	}
    95  }
    96  
    97  var _ = gc.Suite(&FirewallerSuite{})
    98  
    99  func (s FirewallerGlobalModeSuite) SetUpTest(c *gc.C) {
   100  	add := map[string]interface{}{"firewall-mode": config.FwGlobal}
   101  	s.DummyConfig = dummy.SampleConfig().Merge(add).Delete("admin-secret", "ca-private-key")
   102  
   103  	s.FirewallerSuite.SetUpTest(c)
   104  }
   105  
   106  func (s *FirewallerSuite) SetUpTest(c *gc.C) {
   107  	s.JujuConnSuite.SetUpTest(c)
   108  	s.charm = s.AddTestingCharm(c, "dummy")
   109  
   110  	// Create a manager machine and login to the API.
   111  	machine, err := s.State.AddMachine("quantal", state.JobManageEnviron)
   112  	c.Assert(err, gc.IsNil)
   113  	password, err := utils.RandomPassword()
   114  	c.Assert(err, gc.IsNil)
   115  	err = machine.SetPassword(password)
   116  	c.Assert(err, gc.IsNil)
   117  	err = machine.SetProvisioned("i-manager", "fake_nonce", nil)
   118  	c.Assert(err, gc.IsNil)
   119  	s.st = s.OpenAPIAsMachine(c, machine.Tag(), password, "fake_nonce")
   120  	c.Assert(s.st, gc.NotNil)
   121  
   122  	// Create the firewaller API facade.
   123  	s.firewaller = s.st.Firewaller()
   124  	c.Assert(s.firewaller, gc.NotNil)
   125  }
   126  
   127  func (s *FirewallerSuite) TestStartStop(c *gc.C) {
   128  	fw, err := firewaller.NewFirewaller(s.firewaller)
   129  	c.Assert(err, gc.IsNil)
   130  	c.Assert(fw.Stop(), gc.IsNil)
   131  }
   132  
   133  func (s *FirewallerSuite) addUnit(c *gc.C, svc *state.Service) (*state.Unit, *state.Machine) {
   134  	units, err := juju.AddUnits(s.State, svc, 1, "")
   135  	c.Assert(err, gc.IsNil)
   136  	u := units[0]
   137  	id, err := u.AssignedMachineId()
   138  	c.Assert(err, gc.IsNil)
   139  	m, err := s.State.Machine(id)
   140  	c.Assert(err, gc.IsNil)
   141  	return u, m
   142  }
   143  
   144  // startInstance starts a new instance for the given machine.
   145  func (s *FirewallerSuite) startInstance(c *gc.C, m *state.Machine) instance.Instance {
   146  	inst, hc := testing.AssertStartInstance(c, s.Conn.Environ, m.Id())
   147  	err := m.SetProvisioned(inst.Id(), "fake_nonce", hc)
   148  	c.Assert(err, gc.IsNil)
   149  	return inst
   150  }
   151  
   152  func (s *FirewallerSuite) TestNotExposedService(c *gc.C) {
   153  	fw, err := firewaller.NewFirewaller(s.firewaller)
   154  	c.Assert(err, gc.IsNil)
   155  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   156  
   157  	svc := s.AddTestingService(c, "wordpress", s.charm)
   158  	u, m := s.addUnit(c, svc)
   159  	inst := s.startInstance(c, m)
   160  
   161  	err = u.OpenPort("tcp", 80)
   162  	c.Assert(err, gc.IsNil)
   163  	err = u.OpenPort("tcp", 8080)
   164  	c.Assert(err, gc.IsNil)
   165  
   166  	s.assertPorts(c, inst, m.Id(), nil)
   167  
   168  	err = u.ClosePort("tcp", 80)
   169  	c.Assert(err, gc.IsNil)
   170  
   171  	s.assertPorts(c, inst, m.Id(), nil)
   172  }
   173  
   174  func (s *FirewallerSuite) TestExposedService(c *gc.C) {
   175  	fw, err := firewaller.NewFirewaller(s.firewaller)
   176  	c.Assert(err, gc.IsNil)
   177  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   178  
   179  	svc := s.AddTestingService(c, "wordpress", s.charm)
   180  
   181  	err = svc.SetExposed()
   182  	c.Assert(err, gc.IsNil)
   183  	u, m := s.addUnit(c, svc)
   184  	inst := s.startInstance(c, m)
   185  
   186  	err = u.OpenPort("tcp", 80)
   187  	c.Assert(err, gc.IsNil)
   188  	err = u.OpenPort("tcp", 8080)
   189  	c.Assert(err, gc.IsNil)
   190  
   191  	s.assertPorts(c, inst, m.Id(), []network.Port{{"tcp", 80}, {"tcp", 8080}})
   192  
   193  	err = u.ClosePort("tcp", 80)
   194  	c.Assert(err, gc.IsNil)
   195  
   196  	s.assertPorts(c, inst, m.Id(), []network.Port{{"tcp", 8080}})
   197  }
   198  
   199  func (s *FirewallerSuite) TestMultipleExposedServices(c *gc.C) {
   200  	fw, err := firewaller.NewFirewaller(s.firewaller)
   201  	c.Assert(err, gc.IsNil)
   202  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   203  
   204  	svc1 := s.AddTestingService(c, "wordpress", s.charm)
   205  	err = svc1.SetExposed()
   206  	c.Assert(err, gc.IsNil)
   207  
   208  	u1, m1 := s.addUnit(c, svc1)
   209  	inst1 := s.startInstance(c, m1)
   210  	err = u1.OpenPort("tcp", 80)
   211  	c.Assert(err, gc.IsNil)
   212  	err = u1.OpenPort("tcp", 8080)
   213  	c.Assert(err, gc.IsNil)
   214  
   215  	svc2 := s.AddTestingService(c, "mysql", s.charm)
   216  	c.Assert(err, gc.IsNil)
   217  	err = svc2.SetExposed()
   218  	c.Assert(err, gc.IsNil)
   219  
   220  	u2, m2 := s.addUnit(c, svc2)
   221  	inst2 := s.startInstance(c, m2)
   222  	err = u2.OpenPort("tcp", 3306)
   223  	c.Assert(err, gc.IsNil)
   224  
   225  	s.assertPorts(c, inst1, m1.Id(), []network.Port{{"tcp", 80}, {"tcp", 8080}})
   226  	s.assertPorts(c, inst2, m2.Id(), []network.Port{{"tcp", 3306}})
   227  
   228  	err = u1.ClosePort("tcp", 80)
   229  	c.Assert(err, gc.IsNil)
   230  	err = u2.ClosePort("tcp", 3306)
   231  	c.Assert(err, gc.IsNil)
   232  
   233  	s.assertPorts(c, inst1, m1.Id(), []network.Port{{"tcp", 8080}})
   234  	s.assertPorts(c, inst2, m2.Id(), nil)
   235  }
   236  
   237  func (s *FirewallerSuite) TestMachineWithoutInstanceId(c *gc.C) {
   238  	fw, err := firewaller.NewFirewaller(s.firewaller)
   239  	c.Assert(err, gc.IsNil)
   240  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   241  
   242  	svc := s.AddTestingService(c, "wordpress", s.charm)
   243  	err = svc.SetExposed()
   244  	c.Assert(err, gc.IsNil)
   245  	// add a unit but don't start its instance yet.
   246  	u1, m1 := s.addUnit(c, svc)
   247  
   248  	// add another unit and start its instance, so that
   249  	// we're sure the firewaller has seen the first instance.
   250  	u2, m2 := s.addUnit(c, svc)
   251  	inst2 := s.startInstance(c, m2)
   252  	err = u2.OpenPort("tcp", 80)
   253  	c.Assert(err, gc.IsNil)
   254  	s.assertPorts(c, inst2, m2.Id(), []network.Port{{"tcp", 80}})
   255  
   256  	inst1 := s.startInstance(c, m1)
   257  	err = u1.OpenPort("tcp", 8080)
   258  	c.Assert(err, gc.IsNil)
   259  	s.assertPorts(c, inst1, m1.Id(), []network.Port{{"tcp", 8080}})
   260  }
   261  
   262  func (s *FirewallerSuite) TestMultipleUnits(c *gc.C) {
   263  	fw, err := firewaller.NewFirewaller(s.firewaller)
   264  	c.Assert(err, gc.IsNil)
   265  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   266  
   267  	svc := s.AddTestingService(c, "wordpress", s.charm)
   268  	err = svc.SetExposed()
   269  	c.Assert(err, gc.IsNil)
   270  
   271  	u1, m1 := s.addUnit(c, svc)
   272  	inst1 := s.startInstance(c, m1)
   273  	err = u1.OpenPort("tcp", 80)
   274  	c.Assert(err, gc.IsNil)
   275  
   276  	u2, m2 := s.addUnit(c, svc)
   277  	inst2 := s.startInstance(c, m2)
   278  	err = u2.OpenPort("tcp", 80)
   279  	c.Assert(err, gc.IsNil)
   280  
   281  	s.assertPorts(c, inst1, m1.Id(), []network.Port{{"tcp", 80}})
   282  	s.assertPorts(c, inst2, m2.Id(), []network.Port{{"tcp", 80}})
   283  
   284  	err = u1.ClosePort("tcp", 80)
   285  	c.Assert(err, gc.IsNil)
   286  	err = u2.ClosePort("tcp", 80)
   287  	c.Assert(err, gc.IsNil)
   288  
   289  	s.assertPorts(c, inst1, m1.Id(), nil)
   290  	s.assertPorts(c, inst2, m2.Id(), nil)
   291  }
   292  
   293  func (s *FirewallerSuite) TestStartWithState(c *gc.C) {
   294  	svc := s.AddTestingService(c, "wordpress", s.charm)
   295  	err := svc.SetExposed()
   296  	c.Assert(err, gc.IsNil)
   297  	u, m := s.addUnit(c, svc)
   298  	inst := s.startInstance(c, m)
   299  
   300  	err = u.OpenPort("tcp", 80)
   301  	c.Assert(err, gc.IsNil)
   302  	err = u.OpenPort("tcp", 8080)
   303  	c.Assert(err, gc.IsNil)
   304  
   305  	// Nothing open without firewaller.
   306  	s.assertPorts(c, inst, m.Id(), nil)
   307  
   308  	// Starting the firewaller opens the ports.
   309  	fw, err := firewaller.NewFirewaller(s.firewaller)
   310  	c.Assert(err, gc.IsNil)
   311  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   312  
   313  	s.assertPorts(c, inst, m.Id(), []network.Port{{"tcp", 80}, {"tcp", 8080}})
   314  
   315  	err = svc.SetExposed()
   316  	c.Assert(err, gc.IsNil)
   317  }
   318  
   319  func (s *FirewallerSuite) TestStartWithPartialState(c *gc.C) {
   320  	m, err := s.State.AddMachine("quantal", state.JobHostUnits)
   321  	c.Assert(err, gc.IsNil)
   322  	inst := s.startInstance(c, m)
   323  
   324  	svc := s.AddTestingService(c, "wordpress", s.charm)
   325  	err = svc.SetExposed()
   326  	c.Assert(err, gc.IsNil)
   327  
   328  	// Starting the firewaller, no open ports.
   329  	fw, err := firewaller.NewFirewaller(s.firewaller)
   330  	c.Assert(err, gc.IsNil)
   331  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   332  
   333  	s.assertPorts(c, inst, m.Id(), nil)
   334  
   335  	// Complete steps to open port.
   336  	u, err := svc.AddUnit()
   337  	c.Assert(err, gc.IsNil)
   338  	err = u.AssignToMachine(m)
   339  	c.Assert(err, gc.IsNil)
   340  	err = u.OpenPort("tcp", 80)
   341  	c.Assert(err, gc.IsNil)
   342  
   343  	s.assertPorts(c, inst, m.Id(), []network.Port{{"tcp", 80}})
   344  }
   345  
   346  func (s *FirewallerSuite) TestStartWithUnexposedService(c *gc.C) {
   347  	m, err := s.State.AddMachine("quantal", state.JobHostUnits)
   348  	c.Assert(err, gc.IsNil)
   349  	inst := s.startInstance(c, m)
   350  
   351  	svc := s.AddTestingService(c, "wordpress", s.charm)
   352  	u, err := svc.AddUnit()
   353  	c.Assert(err, gc.IsNil)
   354  	err = u.AssignToMachine(m)
   355  	c.Assert(err, gc.IsNil)
   356  	err = u.OpenPort("tcp", 80)
   357  	c.Assert(err, gc.IsNil)
   358  
   359  	// Starting the firewaller, no open ports.
   360  	fw, err := firewaller.NewFirewaller(s.firewaller)
   361  	c.Assert(err, gc.IsNil)
   362  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   363  
   364  	s.assertPorts(c, inst, m.Id(), nil)
   365  
   366  	// Expose service.
   367  	err = svc.SetExposed()
   368  	c.Assert(err, gc.IsNil)
   369  	s.assertPorts(c, inst, m.Id(), []network.Port{{"tcp", 80}})
   370  }
   371  
   372  func (s *FirewallerSuite) TestSetClearExposedService(c *gc.C) {
   373  	fw, err := firewaller.NewFirewaller(s.firewaller)
   374  	c.Assert(err, gc.IsNil)
   375  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   376  
   377  	svc := s.AddTestingService(c, "wordpress", s.charm)
   378  
   379  	u, m := s.addUnit(c, svc)
   380  	inst := s.startInstance(c, m)
   381  	err = u.OpenPort("tcp", 80)
   382  	c.Assert(err, gc.IsNil)
   383  	err = u.OpenPort("tcp", 8080)
   384  	c.Assert(err, gc.IsNil)
   385  
   386  	// Not exposed service, so no open port.
   387  	s.assertPorts(c, inst, m.Id(), nil)
   388  
   389  	// SeExposed opens the ports.
   390  	err = svc.SetExposed()
   391  	c.Assert(err, gc.IsNil)
   392  
   393  	s.assertPorts(c, inst, m.Id(), []network.Port{{"tcp", 80}, {"tcp", 8080}})
   394  
   395  	// ClearExposed closes the ports again.
   396  	err = svc.ClearExposed()
   397  	c.Assert(err, gc.IsNil)
   398  
   399  	s.assertPorts(c, inst, m.Id(), nil)
   400  }
   401  
   402  func (s *FirewallerSuite) TestRemoveUnit(c *gc.C) {
   403  	fw, err := firewaller.NewFirewaller(s.firewaller)
   404  	c.Assert(err, gc.IsNil)
   405  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   406  
   407  	svc := s.AddTestingService(c, "wordpress", s.charm)
   408  	err = svc.SetExposed()
   409  	c.Assert(err, gc.IsNil)
   410  
   411  	u1, m1 := s.addUnit(c, svc)
   412  	inst1 := s.startInstance(c, m1)
   413  	err = u1.OpenPort("tcp", 80)
   414  	c.Assert(err, gc.IsNil)
   415  
   416  	u2, m2 := s.addUnit(c, svc)
   417  	inst2 := s.startInstance(c, m2)
   418  	err = u2.OpenPort("tcp", 80)
   419  	c.Assert(err, gc.IsNil)
   420  
   421  	s.assertPorts(c, inst1, m1.Id(), []network.Port{{"tcp", 80}})
   422  	s.assertPorts(c, inst2, m2.Id(), []network.Port{{"tcp", 80}})
   423  
   424  	// Remove unit.
   425  	err = u1.EnsureDead()
   426  	c.Assert(err, gc.IsNil)
   427  	err = u1.Remove()
   428  	c.Assert(err, gc.IsNil)
   429  
   430  	s.assertPorts(c, inst1, m1.Id(), nil)
   431  	s.assertPorts(c, inst2, m2.Id(), []network.Port{{"tcp", 80}})
   432  }
   433  
   434  func (s *FirewallerSuite) TestRemoveService(c *gc.C) {
   435  	fw, err := firewaller.NewFirewaller(s.firewaller)
   436  	c.Assert(err, gc.IsNil)
   437  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   438  
   439  	svc := s.AddTestingService(c, "wordpress", s.charm)
   440  	err = svc.SetExposed()
   441  	c.Assert(err, gc.IsNil)
   442  
   443  	u, m := s.addUnit(c, svc)
   444  	inst := s.startInstance(c, m)
   445  	err = u.OpenPort("tcp", 80)
   446  	c.Assert(err, gc.IsNil)
   447  
   448  	s.assertPorts(c, inst, m.Id(), []network.Port{{"tcp", 80}})
   449  
   450  	// Remove service.
   451  	err = u.EnsureDead()
   452  	c.Assert(err, gc.IsNil)
   453  	err = u.Remove()
   454  	c.Assert(err, gc.IsNil)
   455  	err = svc.Destroy()
   456  	c.Assert(err, gc.IsNil)
   457  	s.assertPorts(c, inst, m.Id(), nil)
   458  }
   459  
   460  func (s *FirewallerSuite) TestRemoveMultipleServices(c *gc.C) {
   461  	fw, err := firewaller.NewFirewaller(s.firewaller)
   462  	c.Assert(err, gc.IsNil)
   463  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   464  
   465  	svc1 := s.AddTestingService(c, "wordpress", s.charm)
   466  	err = svc1.SetExposed()
   467  	c.Assert(err, gc.IsNil)
   468  
   469  	u1, m1 := s.addUnit(c, svc1)
   470  	inst1 := s.startInstance(c, m1)
   471  	err = u1.OpenPort("tcp", 80)
   472  	c.Assert(err, gc.IsNil)
   473  
   474  	svc2 := s.AddTestingService(c, "mysql", s.charm)
   475  	err = svc2.SetExposed()
   476  	c.Assert(err, gc.IsNil)
   477  
   478  	u2, m2 := s.addUnit(c, svc2)
   479  	inst2 := s.startInstance(c, m2)
   480  	err = u2.OpenPort("tcp", 3306)
   481  	c.Assert(err, gc.IsNil)
   482  
   483  	s.assertPorts(c, inst1, m1.Id(), []network.Port{{"tcp", 80}})
   484  	s.assertPorts(c, inst2, m2.Id(), []network.Port{{"tcp", 3306}})
   485  
   486  	// Remove services.
   487  	err = u2.EnsureDead()
   488  	c.Assert(err, gc.IsNil)
   489  	err = u2.Remove()
   490  	c.Assert(err, gc.IsNil)
   491  	err = svc2.Destroy()
   492  	c.Assert(err, gc.IsNil)
   493  
   494  	err = u1.EnsureDead()
   495  	c.Assert(err, gc.IsNil)
   496  	err = u1.Remove()
   497  	c.Assert(err, gc.IsNil)
   498  	err = svc1.Destroy()
   499  	c.Assert(err, gc.IsNil)
   500  
   501  	s.assertPorts(c, inst1, m1.Id(), nil)
   502  	s.assertPorts(c, inst2, m2.Id(), nil)
   503  }
   504  
   505  func (s *FirewallerSuite) TestDeadMachine(c *gc.C) {
   506  	fw, err := firewaller.NewFirewaller(s.firewaller)
   507  	c.Assert(err, gc.IsNil)
   508  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   509  
   510  	svc := s.AddTestingService(c, "wordpress", s.charm)
   511  	err = svc.SetExposed()
   512  	c.Assert(err, gc.IsNil)
   513  
   514  	u, m := s.addUnit(c, svc)
   515  	inst := s.startInstance(c, m)
   516  	err = u.OpenPort("tcp", 80)
   517  	c.Assert(err, gc.IsNil)
   518  
   519  	s.assertPorts(c, inst, m.Id(), []network.Port{{"tcp", 80}})
   520  
   521  	// Remove unit and service, also tested without. Has no effect.
   522  	err = u.EnsureDead()
   523  	c.Assert(err, gc.IsNil)
   524  	err = u.Remove()
   525  	c.Assert(err, gc.IsNil)
   526  	err = svc.Destroy()
   527  	c.Assert(err, gc.IsNil)
   528  
   529  	// Kill machine.
   530  	err = m.Refresh()
   531  	c.Assert(err, gc.IsNil)
   532  	err = m.EnsureDead()
   533  	c.Assert(err, gc.IsNil)
   534  
   535  	s.assertPorts(c, inst, m.Id(), nil)
   536  }
   537  
   538  func (s *FirewallerSuite) TestRemoveMachine(c *gc.C) {
   539  	fw, err := firewaller.NewFirewaller(s.firewaller)
   540  	c.Assert(err, gc.IsNil)
   541  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   542  
   543  	svc := s.AddTestingService(c, "wordpress", s.charm)
   544  	err = svc.SetExposed()
   545  	c.Assert(err, gc.IsNil)
   546  
   547  	u, m := s.addUnit(c, svc)
   548  	inst := s.startInstance(c, m)
   549  	err = u.OpenPort("tcp", 80)
   550  	c.Assert(err, gc.IsNil)
   551  
   552  	s.assertPorts(c, inst, m.Id(), []network.Port{{"tcp", 80}})
   553  
   554  	// Remove unit.
   555  	err = u.EnsureDead()
   556  	c.Assert(err, gc.IsNil)
   557  	err = u.Remove()
   558  	c.Assert(err, gc.IsNil)
   559  
   560  	// Remove machine. Nothing bad should happen, but can't
   561  	// assert port state since the machine must have been
   562  	// destroyed and we lost its reference.
   563  	err = m.Refresh()
   564  	c.Assert(err, gc.IsNil)
   565  	err = m.EnsureDead()
   566  	c.Assert(err, gc.IsNil)
   567  	err = m.Remove()
   568  	c.Assert(err, gc.IsNil)
   569  }
   570  
   571  func (s *FirewallerGlobalModeSuite) TestGlobalMode(c *gc.C) {
   572  	// Start firewaller and open ports.
   573  	fw, err := firewaller.NewFirewaller(s.firewaller)
   574  	c.Assert(err, gc.IsNil)
   575  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   576  
   577  	svc1 := s.AddTestingService(c, "wordpress", s.charm)
   578  	err = svc1.SetExposed()
   579  	c.Assert(err, gc.IsNil)
   580  
   581  	u1, m1 := s.addUnit(c, svc1)
   582  	s.startInstance(c, m1)
   583  	err = u1.OpenPort("tcp", 80)
   584  	c.Assert(err, gc.IsNil)
   585  	err = u1.OpenPort("tcp", 8080)
   586  	c.Assert(err, gc.IsNil)
   587  
   588  	svc2 := s.AddTestingService(c, "moinmoin", s.charm)
   589  	c.Assert(err, gc.IsNil)
   590  	err = svc2.SetExposed()
   591  	c.Assert(err, gc.IsNil)
   592  
   593  	u2, m2 := s.addUnit(c, svc2)
   594  	s.startInstance(c, m2)
   595  	err = u2.OpenPort("tcp", 80)
   596  	c.Assert(err, gc.IsNil)
   597  
   598  	s.assertEnvironPorts(c, []network.Port{{"tcp", 80}, {"tcp", 8080}})
   599  
   600  	// Closing a port opened by a different unit won't touch the environment.
   601  	err = u1.ClosePort("tcp", 80)
   602  	c.Assert(err, gc.IsNil)
   603  	s.assertEnvironPorts(c, []network.Port{{"tcp", 80}, {"tcp", 8080}})
   604  
   605  	// Closing a port used just once changes the environment.
   606  	err = u1.ClosePort("tcp", 8080)
   607  	c.Assert(err, gc.IsNil)
   608  	s.assertEnvironPorts(c, []network.Port{{"tcp", 80}})
   609  
   610  	// Closing the last port also modifies the environment.
   611  	err = u2.ClosePort("tcp", 80)
   612  	c.Assert(err, gc.IsNil)
   613  	s.assertEnvironPorts(c, nil)
   614  }
   615  
   616  func (s *FirewallerGlobalModeSuite) TestGlobalModeStartWithUnexposedService(c *gc.C) {
   617  	m, err := s.State.AddMachine("quantal", state.JobHostUnits)
   618  	c.Assert(err, gc.IsNil)
   619  	s.startInstance(c, m)
   620  
   621  	svc := s.AddTestingService(c, "wordpress", s.charm)
   622  	u, err := svc.AddUnit()
   623  	c.Assert(err, gc.IsNil)
   624  	err = u.AssignToMachine(m)
   625  	c.Assert(err, gc.IsNil)
   626  	err = u.OpenPort("tcp", 80)
   627  	c.Assert(err, gc.IsNil)
   628  
   629  	// Starting the firewaller, no open ports.
   630  	fw, err := firewaller.NewFirewaller(s.firewaller)
   631  	c.Assert(err, gc.IsNil)
   632  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   633  
   634  	s.assertEnvironPorts(c, nil)
   635  
   636  	// Expose service.
   637  	err = svc.SetExposed()
   638  	c.Assert(err, gc.IsNil)
   639  	s.assertEnvironPorts(c, []network.Port{{"tcp", 80}})
   640  }
   641  
   642  func (s *FirewallerGlobalModeSuite) TestGlobalModeRestart(c *gc.C) {
   643  	// Start firewaller and open ports.
   644  	fw, err := firewaller.NewFirewaller(s.firewaller)
   645  	c.Assert(err, gc.IsNil)
   646  
   647  	svc := s.AddTestingService(c, "wordpress", s.charm)
   648  	err = svc.SetExposed()
   649  	c.Assert(err, gc.IsNil)
   650  
   651  	u, m := s.addUnit(c, svc)
   652  	s.startInstance(c, m)
   653  	err = u.OpenPort("tcp", 80)
   654  	c.Assert(err, gc.IsNil)
   655  	err = u.OpenPort("tcp", 8080)
   656  	c.Assert(err, gc.IsNil)
   657  
   658  	s.assertEnvironPorts(c, []network.Port{{"tcp", 80}, {"tcp", 8080}})
   659  
   660  	// Stop firewaller and close one and open a different port.
   661  	err = fw.Stop()
   662  	c.Assert(err, gc.IsNil)
   663  
   664  	err = u.ClosePort("tcp", 8080)
   665  	c.Assert(err, gc.IsNil)
   666  	err = u.OpenPort("tcp", 8888)
   667  	c.Assert(err, gc.IsNil)
   668  
   669  	// Start firewaller and check port.
   670  	fw, err = firewaller.NewFirewaller(s.firewaller)
   671  	c.Assert(err, gc.IsNil)
   672  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   673  
   674  	s.assertEnvironPorts(c, []network.Port{{"tcp", 80}, {"tcp", 8888}})
   675  }
   676  
   677  func (s *FirewallerGlobalModeSuite) TestGlobalModeRestartUnexposedService(c *gc.C) {
   678  	// Start firewaller and open ports.
   679  	fw, err := firewaller.NewFirewaller(s.firewaller)
   680  	c.Assert(err, gc.IsNil)
   681  
   682  	svc := s.AddTestingService(c, "wordpress", s.charm)
   683  	err = svc.SetExposed()
   684  	c.Assert(err, gc.IsNil)
   685  
   686  	u, m := s.addUnit(c, svc)
   687  	s.startInstance(c, m)
   688  	err = u.OpenPort("tcp", 80)
   689  	c.Assert(err, gc.IsNil)
   690  	err = u.OpenPort("tcp", 8080)
   691  	c.Assert(err, gc.IsNil)
   692  
   693  	s.assertEnvironPorts(c, []network.Port{{"tcp", 80}, {"tcp", 8080}})
   694  
   695  	// Stop firewaller and clear exposed flag on service.
   696  	err = fw.Stop()
   697  	c.Assert(err, gc.IsNil)
   698  
   699  	err = svc.ClearExposed()
   700  	c.Assert(err, gc.IsNil)
   701  
   702  	// Start firewaller and check port.
   703  	fw, err = firewaller.NewFirewaller(s.firewaller)
   704  	c.Assert(err, gc.IsNil)
   705  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   706  
   707  	s.assertEnvironPorts(c, nil)
   708  }
   709  
   710  func (s *FirewallerGlobalModeSuite) TestGlobalModeRestartPortCount(c *gc.C) {
   711  	// Start firewaller and open ports.
   712  	fw, err := firewaller.NewFirewaller(s.firewaller)
   713  	c.Assert(err, gc.IsNil)
   714  
   715  	svc1 := s.AddTestingService(c, "wordpress", s.charm)
   716  	err = svc1.SetExposed()
   717  	c.Assert(err, gc.IsNil)
   718  
   719  	u1, m1 := s.addUnit(c, svc1)
   720  	s.startInstance(c, m1)
   721  	err = u1.OpenPort("tcp", 80)
   722  	c.Assert(err, gc.IsNil)
   723  	err = u1.OpenPort("tcp", 8080)
   724  	c.Assert(err, gc.IsNil)
   725  
   726  	s.assertEnvironPorts(c, []network.Port{{"tcp", 80}, {"tcp", 8080}})
   727  
   728  	// Stop firewaller and add another service using the port.
   729  	err = fw.Stop()
   730  	c.Assert(err, gc.IsNil)
   731  
   732  	svc2 := s.AddTestingService(c, "moinmoin", s.charm)
   733  	err = svc2.SetExposed()
   734  	c.Assert(err, gc.IsNil)
   735  
   736  	u2, m2 := s.addUnit(c, svc2)
   737  	s.startInstance(c, m2)
   738  	err = u2.OpenPort("tcp", 80)
   739  	c.Assert(err, gc.IsNil)
   740  
   741  	// Start firewaller and check port.
   742  	fw, err = firewaller.NewFirewaller(s.firewaller)
   743  	c.Assert(err, gc.IsNil)
   744  	defer func() { c.Assert(fw.Stop(), gc.IsNil) }()
   745  
   746  	s.assertEnvironPorts(c, []network.Port{{"tcp", 80}, {"tcp", 8080}})
   747  
   748  	// Closing a port opened by a different unit won't touch the environment.
   749  	err = u1.ClosePort("tcp", 80)
   750  	c.Assert(err, gc.IsNil)
   751  	s.assertEnvironPorts(c, []network.Port{{"tcp", 80}, {"tcp", 8080}})
   752  
   753  	// Closing a port used just once changes the environment.
   754  	err = u1.ClosePort("tcp", 8080)
   755  	c.Assert(err, gc.IsNil)
   756  	s.assertEnvironPorts(c, []network.Port{{"tcp", 80}})
   757  
   758  	// Closing the last port also modifies the environment.
   759  	err = u2.ClosePort("tcp", 80)
   760  	c.Assert(err, gc.IsNil)
   761  	s.assertEnvironPorts(c, nil)
   762  }