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  }