github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/uniter/runlistener_test.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package uniter_test 5 6 import ( 7 "path/filepath" 8 9 "github.com/juju/loggo" 10 jc "github.com/juju/testing/checkers" 11 "github.com/juju/utils/v3/exec" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/juju/sockets" 15 "github.com/juju/juju/testing" 16 "github.com/juju/juju/worker/uniter" 17 "github.com/juju/juju/worker/uniter/runcommands" 18 ) 19 20 type ListenerSuite struct { 21 testing.BaseSuite 22 socketPath sockets.Socket 23 } 24 25 var _ = gc.Suite(&ListenerSuite{}) 26 27 func sockPath(c *gc.C) sockets.Socket { 28 sockPath := filepath.Join(c.MkDir(), "test.listener") 29 return sockets.Socket{Address: sockPath, Network: "unix"} 30 } 31 32 func (s *ListenerSuite) SetUpTest(c *gc.C) { 33 s.BaseSuite.SetUpTest(c) 34 s.socketPath = sockPath(c) 35 } 36 37 // Mirror the params to uniter.NewRunListener, but add cleanup to close it. 38 func (s *ListenerSuite) NewRunListener(c *gc.C, operator bool) *uniter.RunListener { 39 listener, err := uniter.NewRunListener(s.socketPath, loggo.GetLogger("test")) 40 c.Assert(err, jc.ErrorIsNil) 41 listener.RegisterRunner("test/0", &mockCommandRunner{ 42 c: c, 43 operator: operator, 44 }) 45 s.AddCleanup(func(c *gc.C) { 46 c.Assert(listener.Close(), jc.ErrorIsNil) 47 }) 48 return listener 49 } 50 51 func (s *ListenerSuite) TestNewRunListenerOnExistingSocketRemovesItAndSucceeds(c *gc.C) { 52 s.NewRunListener(c, false) 53 s.NewRunListener(c, false) 54 } 55 56 func (s *ListenerSuite) TestClientCall(c *gc.C) { 57 s.NewRunListener(c, false) 58 59 client, err := sockets.Dial(s.socketPath) 60 c.Assert(err, jc.ErrorIsNil) 61 defer client.Close() 62 63 var result exec.ExecResponse 64 args := uniter.RunCommandsArgs{ 65 Commands: "some-command", 66 RelationId: -1, 67 RemoteUnitName: "", 68 ForceRemoteUnit: false, 69 UnitName: "test/0", 70 } 71 err = client.Call(uniter.JujuExecEndpoint, args, &result) 72 c.Assert(err, jc.ErrorIsNil) 73 74 c.Assert(string(result.Stdout), gc.Equals, "some-command stdout") 75 c.Assert(string(result.Stderr), gc.Equals, "some-command stderr") 76 c.Assert(result.Code, gc.Equals, 42) 77 } 78 79 func (s *ListenerSuite) TestUnregisterRunner(c *gc.C) { 80 listener := s.NewRunListener(c, false) 81 listener.UnregisterRunner("test/0") 82 83 client, err := sockets.Dial(s.socketPath) 84 c.Assert(err, jc.ErrorIsNil) 85 defer client.Close() 86 87 var result exec.ExecResponse 88 args := uniter.RunCommandsArgs{ 89 Commands: "some-command", 90 RelationId: -1, 91 RemoteUnitName: "", 92 ForceRemoteUnit: false, 93 UnitName: "test/0", 94 } 95 err = client.Call(uniter.JujuExecEndpoint, args, &result) 96 c.Assert(err, gc.ErrorMatches, ".*no runner is registered for unit test/0") 97 } 98 99 func (s *ListenerSuite) TestOperatorFlag(c *gc.C) { 100 s.NewRunListener(c, true) 101 102 client, err := sockets.Dial(s.socketPath) 103 c.Assert(err, jc.ErrorIsNil) 104 defer client.Close() 105 106 var result exec.ExecResponse 107 args := uniter.RunCommandsArgs{ 108 Commands: "some-command", 109 RelationId: -1, 110 RemoteUnitName: "", 111 ForceRemoteUnit: false, 112 UnitName: "test/0", 113 Operator: true, 114 } 115 err = client.Call(uniter.JujuExecEndpoint, args, &result) 116 c.Assert(err, jc.ErrorIsNil) 117 118 c.Assert(string(result.Stdout), gc.Equals, "some-command stdout") 119 c.Assert(string(result.Stderr), gc.Equals, "some-command stderr") 120 c.Assert(result.Code, gc.Equals, 42) 121 } 122 123 type ChannelCommandRunnerSuite struct { 124 testing.BaseSuite 125 abort chan struct{} 126 commands runcommands.Commands 127 commandChannel chan string 128 runner *uniter.ChannelCommandRunner 129 } 130 131 var _ = gc.Suite(&ChannelCommandRunnerSuite{}) 132 133 func (s *ChannelCommandRunnerSuite) SetUpTest(c *gc.C) { 134 s.BaseSuite.SetUpTest(c) 135 s.abort = make(chan struct{}, 1) 136 s.commands = runcommands.NewCommands() 137 s.commandChannel = make(chan string, 1) 138 runner, err := uniter.NewChannelCommandRunner(uniter.ChannelCommandRunnerConfig{ 139 Abort: s.abort, 140 Commands: s.commands, 141 CommandChannel: s.commandChannel, 142 }) 143 c.Assert(err, jc.ErrorIsNil) 144 s.runner = runner 145 } 146 147 func (s *ChannelCommandRunnerSuite) TestCommandsAborted(c *gc.C) { 148 close(s.abort) 149 _, err := s.runner.RunCommands(uniter.RunCommandsArgs{ 150 Commands: "some-command", 151 }) 152 c.Assert(err, gc.ErrorMatches, "command execution aborted") 153 } 154 155 type mockCommandRunner struct { 156 c *gc.C 157 operator bool 158 } 159 160 var _ uniter.CommandRunner = (*mockCommandRunner)(nil) 161 162 func (r *mockCommandRunner) RunCommands(args uniter.RunCommandsArgs) (results *exec.ExecResponse, err error) { 163 r.c.Log("mock runner: " + args.Commands) 164 r.c.Assert(args.Operator, gc.Equals, r.operator) 165 return &exec.ExecResponse{ 166 Code: 42, 167 Stdout: []byte(args.Commands + " stdout"), 168 Stderr: []byte(args.Commands + " stderr"), 169 }, nil 170 }