github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/apiserver/action/run_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package action_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	jc "github.com/juju/testing/checkers"
     9  	gc "gopkg.in/check.v1"
    10  	"gopkg.in/juju/names.v2"
    11  
    12  	"github.com/juju/juju/apiserver/action"
    13  	"github.com/juju/juju/apiserver/common"
    14  	commontesting "github.com/juju/juju/apiserver/common/testing"
    15  	"github.com/juju/juju/apiserver/params"
    16  	apiservertesting "github.com/juju/juju/apiserver/testing"
    17  	jujutesting "github.com/juju/juju/juju/testing"
    18  	"github.com/juju/juju/state"
    19  	"github.com/juju/juju/testing"
    20  )
    21  
    22  type runSuite struct {
    23  	jujutesting.JujuConnSuite
    24  	commontesting.BlockHelper
    25  
    26  	client *action.ActionAPI
    27  }
    28  
    29  var _ = gc.Suite(&runSuite{})
    30  
    31  func (s *runSuite) SetUpTest(c *gc.C) {
    32  	s.JujuConnSuite.SetUpTest(c)
    33  	s.BlockHelper = commontesting.NewBlockHelper(s.APIState)
    34  	s.AddCleanup(func(*gc.C) { s.BlockHelper.Close() })
    35  
    36  	var err error
    37  	auth := apiservertesting.FakeAuthorizer{
    38  		Tag: s.AdminUserTag(c),
    39  	}
    40  	s.client, err = action.NewActionAPI(s.State, nil, auth)
    41  	c.Assert(err, jc.ErrorIsNil)
    42  }
    43  
    44  func (s *runSuite) addMachine(c *gc.C) *state.Machine {
    45  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
    46  	c.Assert(err, jc.ErrorIsNil)
    47  	return machine
    48  }
    49  
    50  func (s *runSuite) addUnit(c *gc.C, service *state.Application) *state.Unit {
    51  	unit, err := service.AddUnit()
    52  	c.Assert(err, jc.ErrorIsNil)
    53  	err = unit.AssignToNewMachine()
    54  	c.Assert(err, jc.ErrorIsNil)
    55  	return unit
    56  }
    57  
    58  func (s *runSuite) TestGetAllUnitNames(c *gc.C) {
    59  	charm := s.AddTestingCharm(c, "dummy")
    60  	magic, err := s.State.AddApplication(state.AddApplicationArgs{Name: "magic", Charm: charm})
    61  	s.addUnit(c, magic)
    62  	s.addUnit(c, magic)
    63  
    64  	notAssigned, err := s.State.AddApplication(state.AddApplicationArgs{Name: "not-assigned", Charm: charm})
    65  	c.Assert(err, jc.ErrorIsNil)
    66  	_, err = notAssigned.AddUnit()
    67  	c.Assert(err, jc.ErrorIsNil)
    68  
    69  	_, err = s.State.AddApplication(state.AddApplicationArgs{Name: "no-units", Charm: charm})
    70  	c.Assert(err, jc.ErrorIsNil)
    71  
    72  	wordpress, err := s.State.AddApplication(state.AddApplicationArgs{Name: "wordpress", Charm: s.AddTestingCharm(c, "wordpress")})
    73  	c.Assert(err, jc.ErrorIsNil)
    74  	wordpress0 := s.addUnit(c, wordpress)
    75  	_, err = s.State.AddApplication(state.AddApplicationArgs{Name: "logging", Charm: s.AddTestingCharm(c, "logging")})
    76  	c.Assert(err, jc.ErrorIsNil)
    77  
    78  	eps, err := s.State.InferEndpoints("logging", "wordpress")
    79  	c.Assert(err, jc.ErrorIsNil)
    80  	rel, err := s.State.AddRelation(eps...)
    81  	c.Assert(err, jc.ErrorIsNil)
    82  	ru, err := rel.Unit(wordpress0)
    83  	c.Assert(err, jc.ErrorIsNil)
    84  	err = ru.EnterScope(nil)
    85  	c.Assert(err, jc.ErrorIsNil)
    86  
    87  	for i, test := range []struct {
    88  		message  string
    89  		expected []string
    90  		units    []string
    91  		services []string
    92  		error    string
    93  	}{{
    94  		message: "no units, expected nil slice",
    95  	}, {
    96  		message:  "asking for an empty string service",
    97  		services: []string{""},
    98  		error:    `"" is not a valid application name`,
    99  	}, {
   100  		message: "asking for an empty string unit",
   101  		units:   []string{""},
   102  		error:   `invalid unit name ""`,
   103  	}, {
   104  		message:  "asking for a service that isn't there",
   105  		services: []string{"foo"},
   106  		error:    `application "foo" not found`,
   107  	}, {
   108  		message:  "service with no units is not really an error",
   109  		services: []string{"no-units"},
   110  	}, {
   111  		message:  "A service with units",
   112  		services: []string{"magic"},
   113  		expected: []string{"magic/0", "magic/1"},
   114  	}, {
   115  		message:  "Asking for just a unit",
   116  		units:    []string{"magic/0"},
   117  		expected: []string{"magic/0"},
   118  	}, {
   119  		message:  "Asking for just a subordinate unit",
   120  		units:    []string{"logging/0"},
   121  		expected: []string{"logging/0"},
   122  	}, {
   123  		message:  "Asking for a unit, and the service",
   124  		services: []string{"magic"},
   125  		units:    []string{"magic/0"},
   126  		expected: []string{"magic/0", "magic/1"},
   127  	}} {
   128  		c.Logf("%v: %s", i, test.message)
   129  		result, err := action.GetAllUnitNames(s.State, test.units, test.services)
   130  		if test.error == "" {
   131  			c.Check(err, jc.ErrorIsNil)
   132  			var units []string
   133  			for _, unit := range result {
   134  				units = append(units, unit.Id())
   135  			}
   136  			c.Check(units, jc.SameContents, test.expected)
   137  		} else {
   138  			c.Check(err, gc.ErrorMatches, test.error)
   139  		}
   140  	}
   141  }
   142  
   143  func (s *runSuite) AssertBlocked(c *gc.C, err error, msg string) {
   144  	c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue, gc.Commentf("error: %#v", err))
   145  	c.Assert(errors.Cause(err), gc.DeepEquals, &params.Error{
   146  		Message: msg,
   147  		Code:    "operation is blocked",
   148  	})
   149  }
   150  
   151  func (s *runSuite) TestBlockRunOnAllMachines(c *gc.C) {
   152  	// block all changes
   153  	s.BlockAllChanges(c, "TestBlockRunOnAllMachines")
   154  	_, err := s.client.RunOnAllMachines(
   155  		params.RunParams{
   156  			Commands: "hostname",
   157  			Timeout:  testing.LongWait,
   158  		})
   159  	s.AssertBlocked(c, err, "TestBlockRunOnAllMachines")
   160  }
   161  
   162  func (s *runSuite) TestBlockRunMachineAndService(c *gc.C) {
   163  	// block all changes
   164  	s.BlockAllChanges(c, "TestBlockRunMachineAndService")
   165  	_, err := s.client.Run(
   166  		params.RunParams{
   167  			Commands:     "hostname",
   168  			Timeout:      testing.LongWait,
   169  			Machines:     []string{"0"},
   170  			Applications: []string{"magic"},
   171  		})
   172  	s.AssertBlocked(c, err, "TestBlockRunMachineAndService")
   173  }
   174  
   175  func (s *runSuite) TestRunMachineAndService(c *gc.C) {
   176  	// We only test that we create the actions correctly
   177  	// There is no need to test anything else at this level.
   178  	expectedPayload := map[string]interface{}{
   179  		"command": "hostname",
   180  		"timeout": int64(0),
   181  	}
   182  	expectedArgs := params.Actions{
   183  		Actions: []params.Action{
   184  			{Receiver: "unit-magic-0", Name: "juju-run", Parameters: expectedPayload},
   185  			{Receiver: "unit-magic-1", Name: "juju-run", Parameters: expectedPayload},
   186  			{Receiver: "machine-0", Name: "juju-run", Parameters: expectedPayload},
   187  		},
   188  	}
   189  	called := false
   190  	s.PatchValue(action.QueueActions, func(client *action.ActionAPI, args params.Actions) (params.ActionResults, error) {
   191  		called = true
   192  		c.Assert(args, jc.DeepEquals, expectedArgs)
   193  		return params.ActionResults{}, nil
   194  	})
   195  
   196  	s.addMachine(c)
   197  
   198  	charm := s.AddTestingCharm(c, "dummy")
   199  	magic, err := s.State.AddApplication(state.AddApplicationArgs{Name: "magic", Charm: charm})
   200  	c.Assert(err, jc.ErrorIsNil)
   201  	s.addUnit(c, magic)
   202  	s.addUnit(c, magic)
   203  
   204  	s.client.Run(
   205  		params.RunParams{
   206  			Commands:     "hostname",
   207  			Machines:     []string{"0"},
   208  			Applications: []string{"magic"},
   209  		})
   210  	c.Assert(called, jc.IsTrue)
   211  }
   212  
   213  func (s *runSuite) TestRunOnAllMachines(c *gc.C) {
   214  	// We only test that we create the actions correctly
   215  	// There is no need to test anything else at this level.
   216  	expectedPayload := map[string]interface{}{
   217  		"command": "hostname",
   218  		"timeout": testing.LongWait.Nanoseconds(),
   219  	}
   220  	expectedArgs := params.Actions{
   221  		Actions: []params.Action{
   222  			{Receiver: "machine-0", Name: "juju-run", Parameters: expectedPayload},
   223  			{Receiver: "machine-1", Name: "juju-run", Parameters: expectedPayload},
   224  			{Receiver: "machine-2", Name: "juju-run", Parameters: expectedPayload},
   225  		},
   226  	}
   227  	called := false
   228  	s.PatchValue(action.QueueActions, func(client *action.ActionAPI, args params.Actions) (params.ActionResults, error) {
   229  		called = true
   230  		c.Assert(args, jc.DeepEquals, expectedArgs)
   231  		return params.ActionResults{}, nil
   232  	})
   233  	// Make three machines.
   234  	s.addMachine(c)
   235  	s.addMachine(c)
   236  	s.addMachine(c)
   237  
   238  	s.client.RunOnAllMachines(
   239  		params.RunParams{
   240  			Commands: "hostname",
   241  			Timeout:  testing.LongWait,
   242  		})
   243  	c.Assert(called, jc.IsTrue)
   244  }
   245  
   246  func (s *runSuite) TestRunRequiresAdmin(c *gc.C) {
   247  	alpha := names.NewUserTag("alpha@bravo")
   248  	auth := apiservertesting.FakeAuthorizer{
   249  		Tag:         alpha,
   250  		HasWriteTag: alpha,
   251  	}
   252  	client, err := action.NewActionAPI(s.State, nil, auth)
   253  	c.Assert(err, jc.ErrorIsNil)
   254  	_, err = client.Run(params.RunParams{})
   255  	c.Assert(errors.Cause(err), gc.Equals, common.ErrPerm)
   256  
   257  	auth.AdminTag = alpha
   258  	client, err = action.NewActionAPI(s.State, nil, auth)
   259  	c.Assert(err, jc.ErrorIsNil)
   260  	_, err = client.Run(params.RunParams{})
   261  	c.Assert(err, jc.ErrorIsNil)
   262  }
   263  
   264  func (s *runSuite) TestRunOnAllMachinesRequiresAdmin(c *gc.C) {
   265  	alpha := names.NewUserTag("alpha@bravo")
   266  	auth := apiservertesting.FakeAuthorizer{
   267  		Tag:         alpha,
   268  		HasWriteTag: alpha,
   269  	}
   270  	client, err := action.NewActionAPI(s.State, nil, auth)
   271  	c.Assert(err, jc.ErrorIsNil)
   272  	_, err = client.RunOnAllMachines(params.RunParams{})
   273  	c.Assert(errors.Cause(err), gc.Equals, common.ErrPerm)
   274  
   275  	auth.AdminTag = alpha
   276  	client, err = action.NewActionAPI(s.State, nil, auth)
   277  	c.Assert(err, jc.ErrorIsNil)
   278  	_, err = client.RunOnAllMachines(params.RunParams{})
   279  	c.Assert(err, jc.ErrorIsNil)
   280  }