github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/caasoperator/action_test.go (about)

     1  // Copyright 2019 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package caasoperator_test
     5  
     6  import (
     7  	"bytes"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	"github.com/juju/errors"
    12  	"github.com/juju/loggo"
    13  	"github.com/juju/names/v5"
    14  	jc "github.com/juju/testing/checkers"
    15  	"github.com/juju/utils/v3"
    16  	utilexec "github.com/juju/utils/v3/exec"
    17  	"go.uber.org/mock/gomock"
    18  	gc "gopkg.in/check.v1"
    19  	k8sexec "k8s.io/client-go/util/exec"
    20  
    21  	"github.com/juju/juju/caas/kubernetes/provider/exec"
    22  	"github.com/juju/juju/testing"
    23  	"github.com/juju/juju/worker/caasoperator"
    24  	"github.com/juju/juju/worker/caasoperator/mocks"
    25  	"github.com/juju/juju/worker/uniter"
    26  	"github.com/juju/juju/worker/uniter/runner"
    27  )
    28  
    29  type actionSuite struct {
    30  	testing.BaseSuite
    31  
    32  	executor *mocks.MockExecutor
    33  	unitAPI  *mocks.MockProviderIDGetter
    34  }
    35  
    36  var _ = gc.Suite(&actionSuite{})
    37  
    38  func (s *actionSuite) setupExecClient(c *gc.C) *gomock.Controller {
    39  	ctrl := gomock.NewController(c)
    40  	s.executor = mocks.NewMockExecutor(ctrl)
    41  	s.unitAPI = mocks.NewMockProviderIDGetter(ctrl)
    42  	return ctrl
    43  }
    44  
    45  func (s *actionSuite) TestRunnerExecFunc(c *gc.C) {
    46  	s.assertRunnerExecFunc(c, "")
    47  }
    48  
    49  func (s *actionSuite) TestRunnerExecFuncWithError(c *gc.C) {
    50  	s.assertRunnerExecFunc(c, "boom")
    51  }
    52  
    53  func (s *actionSuite) assertRunnerExecFunc(c *gc.C, errMsg string) {
    54  	ctrl := s.setupExecClient(c)
    55  	defer ctrl.Finish()
    56  
    57  	baseDir := c.MkDir()
    58  	operatorPaths := caasoperator.NewPaths(baseDir, names.NewApplicationTag("gitlab-k8s"))
    59  	unitPaths := uniter.NewPaths(baseDir, names.NewUnitTag("gitlab-k8s/0"), &uniter.SocketConfig{})
    60  	for _, p := range []string{
    61  		operatorPaths.GetCharmDir(),
    62  		unitPaths.GetCharmDir(),
    63  
    64  		operatorPaths.GetToolsDir(),
    65  		unitPaths.GetToolsDir(),
    66  	} {
    67  		err := os.MkdirAll(p, 0700)
    68  		c.Check(err, jc.ErrorIsNil)
    69  	}
    70  	err := utils.AtomicWriteFile(filepath.Join(operatorPaths.GetToolsDir(), "jujud"), []byte(""), 0600)
    71  	c.Assert(err, jc.ErrorIsNil)
    72  
    73  	logger := loggo.GetLogger("test")
    74  	runnerExecFunc := caasoperator.GetNewRunnerExecutor(logger, s.executor)(s.unitAPI, unitPaths)
    75  	cancel := make(<-chan struct{}, 1)
    76  	stdout := bytes.NewBufferString("")
    77  	stderr := bytes.NewBufferString("")
    78  	expectedCode := 0
    79  	var exitErr error
    80  	if errMsg != "" {
    81  		exitErr = errors.Trace(k8sexec.CodeExitError{Code: 3, Err: errors.New(errMsg)})
    82  		expectedCode = 3
    83  	}
    84  	gomock.InOrder(
    85  		s.unitAPI.EXPECT().Refresh().Return(nil),
    86  		s.unitAPI.EXPECT().ProviderID().Return("gitlab-xxxx"),
    87  		s.unitAPI.EXPECT().Name().Return("gitlab-k8s/0"),
    88  		s.executor.EXPECT().Exec(
    89  			exec.ExecParams{
    90  				PodName:  "gitlab-xxxx",
    91  				Commands: []string{"storage-list"},
    92  				Env:      []string{"AAAA=1111"},
    93  				Stdout:   stdout,
    94  				Stderr:   stderr,
    95  			}, cancel,
    96  		).DoAndReturn(func(exec.ExecParams, <-chan struct{}) error {
    97  			stdout.WriteString("some message")
    98  			stderr.WriteString("some err message")
    99  			return exitErr
   100  		}),
   101  	)
   102  
   103  	outLogger := &mockHookLogger{}
   104  	errLogger := &mockHookLogger{}
   105  	result, err := runnerExecFunc(
   106  		runner.ExecParams{
   107  			Commands:     []string{"storage-list"},
   108  			Env:          []string{"AAAA=1111"},
   109  			Stdout:       stdout,
   110  			StdoutLogger: outLogger,
   111  			Stderr:       stdout,
   112  			StderrLogger: errLogger,
   113  			Cancel:       cancel,
   114  		},
   115  	)
   116  	c.Assert(outLogger.stopped, jc.IsTrue)
   117  	c.Assert(errLogger.stopped, jc.IsTrue)
   118  	c.Assert(result, jc.DeepEquals, &utilexec.ExecResponse{
   119  		Code:   expectedCode,
   120  		Stdout: []byte("some message"),
   121  	})
   122  	if exitErr == nil {
   123  		c.Assert(err, jc.ErrorIsNil)
   124  	} else {
   125  		c.Assert(err, gc.ErrorMatches, "boom")
   126  	}
   127  }
   128  
   129  type exitError struct {
   130  	code int
   131  	err  string
   132  }
   133  
   134  var _ exec.ExitError = exitError{}
   135  
   136  func (e exitError) String() string {
   137  	return e.err
   138  }
   139  
   140  func (e exitError) Error() string {
   141  	return e.err
   142  }
   143  
   144  func (e exitError) ExitStatus() int {
   145  	return e.code
   146  }