github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/worker/uniter/runner/flush_test.go (about)

     1  // Copyright 2012-2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package runner_test
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	"github.com/juju/utils"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/network"
    15  )
    16  
    17  type FlushContextSuite struct {
    18  	HookContextSuite
    19  }
    20  
    21  var _ = gc.Suite(&FlushContextSuite{})
    22  
    23  func (s *FlushContextSuite) TestRunHookRelationFlushingError(c *gc.C) {
    24  	uuid, err := utils.NewUUID()
    25  	c.Assert(err, jc.ErrorIsNil)
    26  	ctx := s.getHookContext(c, uuid.String(), -1, "", noProxies)
    27  
    28  	// Mess with multiple relation settings.
    29  	relCtx0, ok := ctx.Relation(0)
    30  	c.Assert(ok, jc.IsTrue)
    31  	node0, err := relCtx0.Settings()
    32  	c.Assert(err, jc.ErrorIsNil)
    33  	node0.Set("foo", "1")
    34  	relCtx1, ok := ctx.Relation(1)
    35  	c.Assert(ok, jc.IsTrue)
    36  	node1, err := relCtx1.Settings()
    37  	c.Assert(err, jc.ErrorIsNil)
    38  	node1.Set("bar", "2")
    39  
    40  	// Flush the context with a failure.
    41  	err = ctx.FlushContext("some badge", errors.New("blam pow"))
    42  	c.Assert(err, gc.ErrorMatches, "blam pow")
    43  
    44  	// Check that the changes have not been written to state.
    45  	settings0, err := s.relunits[0].ReadSettings("u/0")
    46  	c.Assert(err, jc.ErrorIsNil)
    47  	c.Assert(settings0, gc.DeepEquals, map[string]interface{}{"relation-name": "db0"})
    48  	settings1, err := s.relunits[1].ReadSettings("u/0")
    49  	c.Assert(err, jc.ErrorIsNil)
    50  	c.Assert(settings1, gc.DeepEquals, map[string]interface{}{"relation-name": "db1"})
    51  }
    52  
    53  func (s *FlushContextSuite) TestRunHookRelationFlushingSuccess(c *gc.C) {
    54  	// Create a charm with a working hook, and mess with settings again.
    55  	uuid, err := utils.NewUUID()
    56  	c.Assert(err, jc.ErrorIsNil)
    57  	ctx := s.getHookContext(c, uuid.String(), -1, "", noProxies)
    58  
    59  	// Mess with multiple relation settings.
    60  	relCtx0, ok := ctx.Relation(0)
    61  	c.Assert(ok, jc.IsTrue)
    62  	node0, err := relCtx0.Settings()
    63  	c.Assert(err, jc.ErrorIsNil)
    64  	node0.Set("baz", "3")
    65  	relCtx1, ok := ctx.Relation(1)
    66  	c.Assert(ok, jc.IsTrue)
    67  	node1, err := relCtx1.Settings()
    68  	c.Assert(err, jc.ErrorIsNil)
    69  	node1.Set("qux", "4")
    70  
    71  	// Flush the context with a success.
    72  	err = ctx.FlushContext("some badge", nil)
    73  	c.Assert(err, jc.ErrorIsNil)
    74  
    75  	// Check that the changes have been written to state.
    76  	settings0, err := s.relunits[0].ReadSettings("u/0")
    77  	c.Assert(err, jc.ErrorIsNil)
    78  	c.Assert(settings0, gc.DeepEquals, map[string]interface{}{
    79  		"relation-name": "db0",
    80  		"baz":           "3",
    81  	})
    82  	settings1, err := s.relunits[1].ReadSettings("u/0")
    83  	c.Assert(err, jc.ErrorIsNil)
    84  	c.Assert(settings1, gc.DeepEquals, map[string]interface{}{
    85  		"relation-name": "db1",
    86  		"qux":           "4",
    87  	})
    88  }
    89  
    90  func (s *FlushContextSuite) TestRunHookMetricSendingSuccess(c *gc.C) {
    91  	uuid, err := utils.NewUUID()
    92  	c.Assert(err, jc.ErrorIsNil)
    93  	ctx := s.getMeteredHookContext(c, uuid.String(), -1, "", noProxies, true, s.metricsDefinition("pings"))
    94  
    95  	now := time.Now()
    96  	err = ctx.AddMetric("pings", "50", now)
    97  	c.Assert(err, jc.ErrorIsNil)
    98  
    99  	// Flush the context with a success.
   100  	err = ctx.FlushContext("some badge", nil)
   101  	c.Assert(err, jc.ErrorIsNil)
   102  
   103  	metricBatches, err := s.State.MetricBatches()
   104  	c.Assert(err, jc.ErrorIsNil)
   105  	c.Assert(metricBatches, gc.HasLen, 1)
   106  	metrics := metricBatches[0].Metrics()
   107  	c.Assert(metrics, gc.HasLen, 1)
   108  	c.Assert(metrics[0].Key, gc.Equals, "pings")
   109  	c.Assert(metrics[0].Value, gc.Equals, "50")
   110  }
   111  
   112  func (s *FlushContextSuite) TestRunHookNoMetricSendingOnFailure(c *gc.C) {
   113  	uuid, err := utils.NewUUID()
   114  	c.Assert(err, jc.ErrorIsNil)
   115  	ctx := s.getMeteredHookContext(c, uuid.String(), -1, "", noProxies, true, s.metricsDefinition("key"))
   116  
   117  	now := time.Now()
   118  	ctx.AddMetric("key", "50", now)
   119  
   120  	// Flush the context with a success.
   121  	err = ctx.FlushContext("some badge", errors.New("boom squelch"))
   122  	c.Assert(err, gc.ErrorMatches, "boom squelch")
   123  
   124  	metricBatches, err := s.State.MetricBatches()
   125  	c.Assert(err, jc.ErrorIsNil)
   126  	c.Assert(metricBatches, gc.HasLen, 0)
   127  }
   128  
   129  func (s *FlushContextSuite) TestRunHookMetricSendingDisabled(c *gc.C) {
   130  	uuid, err := utils.NewUUID()
   131  	c.Assert(err, jc.ErrorIsNil)
   132  	ctx := s.getMeteredHookContext(c, uuid.String(), -1, "", noProxies, false, s.metricsDefinition("key"))
   133  
   134  	now := time.Now()
   135  	err = ctx.AddMetric("key", "50", now)
   136  	c.Assert(err, gc.ErrorMatches, "metrics disabled")
   137  
   138  	// Flush the context with a success.
   139  	err = ctx.FlushContext("some badge", nil)
   140  	c.Assert(err, jc.ErrorIsNil)
   141  
   142  	metricBatches, err := s.State.MetricBatches()
   143  	c.Assert(err, jc.ErrorIsNil)
   144  	c.Assert(metricBatches, gc.HasLen, 0)
   145  }
   146  
   147  func (s *FlushContextSuite) TestRunHookMetricSendingUndeclared(c *gc.C) {
   148  	uuid, err := utils.NewUUID()
   149  	c.Assert(err, jc.ErrorIsNil)
   150  	ctx := s.getMeteredHookContext(c, uuid.String(), -1, "", noProxies, true, nil)
   151  
   152  	now := time.Now()
   153  	err = ctx.AddMetric("key", "50", now)
   154  	c.Assert(err, gc.ErrorMatches, "metrics disabled")
   155  
   156  	// Flush the context with a success.
   157  	err = ctx.FlushContext("some badge", nil)
   158  	c.Assert(err, jc.ErrorIsNil)
   159  
   160  	metricBatches, err := s.State.MetricBatches()
   161  	c.Assert(err, jc.ErrorIsNil)
   162  	c.Assert(metricBatches, gc.HasLen, 0)
   163  }
   164  
   165  func (s *FlushContextSuite) TestRunHookOpensAndClosesPendingPorts(c *gc.C) {
   166  	// Initially, no port ranges are open on the unit or its machine.
   167  	unitRanges, err := s.unit.OpenedPorts()
   168  	c.Assert(err, jc.ErrorIsNil)
   169  	c.Assert(unitRanges, gc.HasLen, 0)
   170  	machinePorts, err := s.machine.AllPorts()
   171  	c.Assert(err, jc.ErrorIsNil)
   172  	c.Assert(machinePorts, gc.HasLen, 0)
   173  
   174  	// Add another unit on the same machine.
   175  	otherUnit, err := s.service.AddUnit()
   176  	c.Assert(err, jc.ErrorIsNil)
   177  	err = otherUnit.AssignToMachine(s.machine)
   178  	c.Assert(err, jc.ErrorIsNil)
   179  
   180  	// Open some ports on both units.
   181  	err = s.unit.OpenPorts("tcp", 100, 200)
   182  	c.Assert(err, jc.ErrorIsNil)
   183  	err = otherUnit.OpenPorts("udp", 200, 300)
   184  	c.Assert(err, jc.ErrorIsNil)
   185  
   186  	unitRanges, err = s.unit.OpenedPorts()
   187  	c.Assert(err, jc.ErrorIsNil)
   188  	c.Assert(unitRanges, jc.DeepEquals, []network.PortRange{
   189  		{100, 200, "tcp"},
   190  	})
   191  
   192  	// Get the context.
   193  	uuid, err := utils.NewUUID()
   194  	c.Assert(err, jc.ErrorIsNil)
   195  	ctx := s.getHookContext(c, uuid.String(), -1, "", noProxies)
   196  
   197  	// Try opening some ports via the context.
   198  	err = ctx.OpenPorts("tcp", 100, 200)
   199  	c.Assert(err, jc.ErrorIsNil) // duplicates are ignored
   200  	err = ctx.OpenPorts("udp", 200, 300)
   201  	c.Assert(err, gc.ErrorMatches, `cannot open 200-300/udp \(unit "u/0"\): conflicts with existing 200-300/udp \(unit "u/1"\)`)
   202  	err = ctx.OpenPorts("udp", 100, 200)
   203  	c.Assert(err, gc.ErrorMatches, `cannot open 100-200/udp \(unit "u/0"\): conflicts with existing 200-300/udp \(unit "u/1"\)`)
   204  	err = ctx.OpenPorts("udp", 10, 20)
   205  	c.Assert(err, jc.ErrorIsNil)
   206  	err = ctx.OpenPorts("tcp", 50, 100)
   207  	c.Assert(err, gc.ErrorMatches, `cannot open 50-100/tcp \(unit "u/0"\): conflicts with existing 100-200/tcp \(unit "u/0"\)`)
   208  	err = ctx.OpenPorts("tcp", 50, 80)
   209  	c.Assert(err, jc.ErrorIsNil)
   210  	err = ctx.OpenPorts("tcp", 40, 90)
   211  	c.Assert(err, gc.ErrorMatches, `cannot open 40-90/tcp \(unit "u/0"\): conflicts with 50-80/tcp requested earlier`)
   212  
   213  	// Now try closing some ports as well.
   214  	err = ctx.ClosePorts("udp", 8080, 8088)
   215  	c.Assert(err, jc.ErrorIsNil) // not existing -> ignored
   216  	err = ctx.ClosePorts("tcp", 100, 200)
   217  	c.Assert(err, jc.ErrorIsNil)
   218  	err = ctx.ClosePorts("tcp", 100, 200)
   219  	c.Assert(err, jc.ErrorIsNil) // duplicates are ignored
   220  	err = ctx.ClosePorts("udp", 200, 300)
   221  	c.Assert(err, gc.ErrorMatches, `cannot close 200-300/udp \(opened by "u/1"\) from "u/0"`)
   222  	err = ctx.ClosePorts("tcp", 50, 80)
   223  	c.Assert(err, jc.ErrorIsNil) // still pending -> no longer pending
   224  
   225  	// Ensure the ports are not actually changed on the unit yet.
   226  	unitRanges, err = s.unit.OpenedPorts()
   227  	c.Assert(err, jc.ErrorIsNil)
   228  	c.Assert(unitRanges, jc.DeepEquals, []network.PortRange{
   229  		{100, 200, "tcp"},
   230  	})
   231  
   232  	// Flush the context with a success.
   233  	err = ctx.FlushContext("some badge", nil)
   234  	c.Assert(err, jc.ErrorIsNil)
   235  
   236  	// Verify the unit ranges are now open.
   237  	expectUnitRanges := []network.PortRange{
   238  		{FromPort: 10, ToPort: 20, Protocol: "udp"},
   239  	}
   240  	unitRanges, err = s.unit.OpenedPorts()
   241  	c.Assert(err, jc.ErrorIsNil)
   242  	c.Assert(unitRanges, jc.DeepEquals, expectUnitRanges)
   243  }