github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/agent/uniter/action_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package uniter_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names/v5"
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  
    12  	"github.com/juju/juju/api/agent/uniter"
    13  	basetesting "github.com/juju/juju/api/base/testing"
    14  	"github.com/juju/juju/core/watcher/watchertest"
    15  	"github.com/juju/juju/rpc/params"
    16  	coretesting "github.com/juju/juju/testing"
    17  )
    18  
    19  type actionSuite struct {
    20  	coretesting.BaseSuite
    21  }
    22  
    23  var _ = gc.Suite(&actionSuite{})
    24  
    25  func (s *actionSuite) TestAction(c *gc.C) {
    26  	parallel := true
    27  	group := "group"
    28  	actionResult := params.ActionResult{
    29  		Action: &params.Action{
    30  			Name:           "backup",
    31  			Parameters:     map[string]interface{}{"foo": "bar"},
    32  			Parallel:       &parallel,
    33  			ExecutionGroup: &group,
    34  		},
    35  	}
    36  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
    37  		c.Assert(objType, gc.Equals, "Uniter")
    38  		c.Assert(request, gc.Equals, "Actions")
    39  		c.Assert(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{Tag: "action-666"}}})
    40  		c.Assert(result, gc.FitsTypeOf, &params.ActionResults{})
    41  		*(result.(*params.ActionResults)) = params.ActionResults{
    42  			Results: []params.ActionResult{actionResult},
    43  		}
    44  		return nil
    45  	})
    46  	client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
    47  
    48  	a, err := client.Action(names.NewActionTag("666"))
    49  	c.Assert(err, jc.ErrorIsNil)
    50  	c.Assert(a.ID(), gc.Equals, "666")
    51  	c.Assert(a.Name(), gc.Equals, actionResult.Action.Name)
    52  	c.Assert(a.Params(), jc.DeepEquals, actionResult.Action.Parameters)
    53  	c.Assert(a.Parallel(), jc.IsTrue)
    54  	c.Assert(a.ExecutionGroup(), gc.Equals, "group")
    55  }
    56  
    57  func (s *actionSuite) TestActionError(c *gc.C) {
    58  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
    59  		c.Assert(objType, gc.Equals, "Uniter")
    60  		c.Assert(request, gc.Equals, "Actions")
    61  		c.Assert(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{Tag: "action-666"}}})
    62  		c.Assert(result, gc.FitsTypeOf, &params.ActionResults{})
    63  		*(result.(*params.ActionResults)) = params.ActionResults{
    64  			Results: []params.ActionResult{{
    65  				Error: &params.Error{Message: "boom"},
    66  			}},
    67  		}
    68  		return nil
    69  	})
    70  	client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
    71  
    72  	_, err := client.Action(names.NewActionTag("666"))
    73  	c.Assert(err, gc.ErrorMatches, "boom")
    74  }
    75  
    76  func (s *actionSuite) TestActionBegin(c *gc.C) {
    77  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
    78  		c.Assert(objType, gc.Equals, "Uniter")
    79  		c.Assert(request, gc.Equals, "BeginActions")
    80  		c.Assert(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{Tag: "action-666"}}})
    81  		c.Assert(result, gc.FitsTypeOf, &params.ErrorResults{})
    82  		*(result.(*params.ErrorResults)) = params.ErrorResults{
    83  			Results: []params.ErrorResult{{Error: &params.Error{Message: "boom"}}},
    84  		}
    85  		return nil
    86  	})
    87  	client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
    88  	err := client.ActionBegin(names.NewActionTag("666"))
    89  	c.Assert(err, gc.ErrorMatches, "boom")
    90  }
    91  
    92  func (s *actionSuite) TestActionFinish(c *gc.C) {
    93  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
    94  		c.Assert(objType, gc.Equals, "Uniter")
    95  		c.Assert(request, gc.Equals, "FinishActions")
    96  		c.Assert(arg, gc.DeepEquals, params.ActionExecutionResults{Results: []params.ActionExecutionResult{{
    97  			ActionTag: "action-666",
    98  			Status:    "failed",
    99  			Results:   map[string]interface{}{"foo": "bar"},
   100  			Message:   "oops",
   101  		}}})
   102  		c.Assert(result, gc.FitsTypeOf, &params.ErrorResults{})
   103  		*(result.(*params.ErrorResults)) = params.ErrorResults{
   104  			Results: []params.ErrorResult{{Error: &params.Error{Message: "boom"}}},
   105  		}
   106  		return nil
   107  	})
   108  	client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
   109  	err := client.ActionFinish(names.NewActionTag("666"), "failed", map[string]interface{}{"foo": "bar"}, "oops")
   110  	c.Assert(err, gc.ErrorMatches, "boom")
   111  }
   112  
   113  func (s *actionSuite) TestActionStatus(c *gc.C) {
   114  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   115  		c.Assert(objType, gc.Equals, "Uniter")
   116  		c.Assert(request, gc.Equals, "ActionStatus")
   117  		c.Assert(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{Tag: "action-666"}}})
   118  		c.Assert(result, gc.FitsTypeOf, &params.StringResults{})
   119  		*(result.(*params.StringResults)) = params.StringResults{
   120  			Results: []params.StringResult{{Result: "failed"}},
   121  		}
   122  		return nil
   123  	})
   124  	client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
   125  	status, err := client.ActionStatus(names.NewActionTag("666"))
   126  	c.Assert(err, jc.ErrorIsNil)
   127  	c.Assert(status, gc.Equals, "failed")
   128  }
   129  
   130  func (s *actionSuite) TestLogActionMessage(c *gc.C) {
   131  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   132  		c.Assert(objType, gc.Equals, "Uniter")
   133  		c.Assert(request, gc.Equals, "LogActionsMessages")
   134  		c.Assert(arg, gc.DeepEquals, params.ActionMessageParams{
   135  			Messages: []params.EntityString{{Tag: "action-666", Value: "hello"}},
   136  		})
   137  		c.Assert(result, gc.FitsTypeOf, &params.ErrorResults{})
   138  		*(result.(*params.ErrorResults)) = params.ErrorResults{
   139  			Results: []params.ErrorResult{{&params.Error{Message: "biff"}}},
   140  		}
   141  		return nil
   142  	})
   143  	caller := basetesting.BestVersionCaller{apiCaller, 12}
   144  	client := uniter.NewState(caller, names.NewUnitTag("mysql/0"))
   145  
   146  	unit := uniter.CreateUnit(client, names.NewUnitTag("mysql/0"))
   147  	err := unit.LogActionMessage(names.NewActionTag("666"), "hello")
   148  	c.Assert(err, gc.ErrorMatches, "biff")
   149  }
   150  
   151  func (s *actionSuite) TestWatchActionNotifications(c *gc.C) {
   152  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   153  		if objType == "StringsWatcher" {
   154  			if request != "Next" && request != "Stop" {
   155  				c.Fatalf("unexpected watcher request %q", request)
   156  			}
   157  			return nil
   158  		}
   159  		c.Assert(objType, gc.Equals, "Uniter")
   160  		c.Assert(request, gc.Equals, "WatchActionNotifications")
   161  		c.Assert(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{Tag: "unit-mysql-0"}}})
   162  		c.Assert(result, gc.FitsTypeOf, &params.StringsWatchResults{})
   163  		*(result.(*params.StringsWatchResults)) = params.StringsWatchResults{
   164  			Results: []params.StringsWatchResult{{
   165  				StringsWatcherId: "1",
   166  				Changes:          []string{"666"},
   167  			}},
   168  		}
   169  		return nil
   170  	})
   171  	client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
   172  
   173  	unit := uniter.CreateUnit(client, names.NewUnitTag("mysql/0"))
   174  	w, err := unit.WatchActionNotifications()
   175  	c.Assert(err, jc.ErrorIsNil)
   176  	wc := watchertest.NewStringsWatcherC(c, w)
   177  	defer wc.AssertStops()
   178  
   179  	// Initial event.
   180  	wc.AssertChange("666")
   181  }
   182  
   183  func (s *actionSuite) TestWatchActionNotificationsError(c *gc.C) {
   184  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   185  		return errors.New("boom")
   186  	})
   187  	client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
   188  
   189  	unit := uniter.CreateUnit(client, names.NewUnitTag("mysql/0"))
   190  	_, err := unit.WatchActionNotifications()
   191  	c.Assert(err, gc.ErrorMatches, "boom")
   192  }
   193  
   194  func (s *actionSuite) TestWatchActionNotificationsErrorResults(c *gc.C) {
   195  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   196  		c.Assert(objType, gc.Equals, "Uniter")
   197  		c.Assert(request, gc.Equals, "WatchActionNotifications")
   198  		c.Assert(arg, gc.DeepEquals, params.Entities{Entities: []params.Entity{{Tag: "unit-mysql-0"}}})
   199  		c.Assert(result, gc.FitsTypeOf, &params.StringsWatchResults{})
   200  		*(result.(*params.StringsWatchResults)) = params.StringsWatchResults{
   201  			Results: []params.StringsWatchResult{{
   202  				Error: &params.Error{Message: "boom"},
   203  			}},
   204  		}
   205  		return nil
   206  	})
   207  	client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
   208  
   209  	unit := uniter.CreateUnit(client, names.NewUnitTag("mysql/0"))
   210  	_, err := unit.WatchActionNotifications()
   211  	c.Assert(err, gc.ErrorMatches, "boom")
   212  }
   213  
   214  func (s *actionSuite) TestWatchActionNotificationsNoResults(c *gc.C) {
   215  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   216  		c.Assert(result, gc.FitsTypeOf, &params.StringsWatchResults{})
   217  		*(result.(*params.StringsWatchResults)) = params.StringsWatchResults{}
   218  		return nil
   219  	})
   220  	client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
   221  
   222  	unit := uniter.CreateUnit(client, names.NewUnitTag("mysql/0"))
   223  	_, err := unit.WatchActionNotifications()
   224  	c.Assert(err, gc.ErrorMatches, "expected 1 result, got 0")
   225  }
   226  
   227  func (s *actionSuite) TestWatchActionNotificationsMoreResults(c *gc.C) {
   228  	apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   229  		c.Assert(result, gc.FitsTypeOf, &params.StringsWatchResults{})
   230  		*(result.(*params.StringsWatchResults)) = params.StringsWatchResults{
   231  			Results: []params.StringsWatchResult{{}, {}},
   232  		}
   233  		return nil
   234  	})
   235  	client := uniter.NewState(apiCaller, names.NewUnitTag("mysql/0"))
   236  
   237  	unit := uniter.CreateUnit(client, names.NewUnitTag("mysql/0"))
   238  	_, err := unit.WatchActionNotifications()
   239  	c.Assert(err, gc.ErrorMatches, "expected 1 result, got 2")
   240  }