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