github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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  
    11  	"github.com/juju/juju/apiserver/action"
    12  	commontesting "github.com/juju/juju/apiserver/common/testing"
    13  	"github.com/juju/juju/apiserver/params"
    14  	apiservertesting "github.com/juju/juju/apiserver/testing"
    15  	jujutesting "github.com/juju/juju/juju/testing"
    16  	"github.com/juju/juju/state"
    17  	"github.com/juju/juju/testing"
    18  )
    19  
    20  type runSuite struct {
    21  	jujutesting.JujuConnSuite
    22  	commontesting.BlockHelper
    23  
    24  	client *action.ActionAPI
    25  }
    26  
    27  var _ = gc.Suite(&runSuite{})
    28  
    29  func (s *runSuite) SetUpTest(c *gc.C) {
    30  	s.JujuConnSuite.SetUpTest(c)
    31  	s.BlockHelper = commontesting.NewBlockHelper(s.APIState)
    32  	s.AddCleanup(func(*gc.C) { s.BlockHelper.Close() })
    33  
    34  	var err error
    35  	auth := apiservertesting.FakeAuthorizer{
    36  		Tag: s.AdminUserTag(c),
    37  	}
    38  	s.client, err = action.NewActionAPI(s.State, nil, auth)
    39  	c.Assert(err, jc.ErrorIsNil)
    40  }
    41  
    42  func (s *runSuite) addMachine(c *gc.C) *state.Machine {
    43  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
    44  	c.Assert(err, jc.ErrorIsNil)
    45  	return machine
    46  }
    47  
    48  func (s *runSuite) addUnit(c *gc.C, service *state.Service) *state.Unit {
    49  	unit, err := service.AddUnit()
    50  	c.Assert(err, jc.ErrorIsNil)
    51  	err = unit.AssignToNewMachine()
    52  	c.Assert(err, jc.ErrorIsNil)
    53  	return unit
    54  }
    55  
    56  func (s *runSuite) TestGetAllUnitNames(c *gc.C) {
    57  	charm := s.AddTestingCharm(c, "dummy")
    58  	owner := s.AdminUserTag(c)
    59  	magic, err := s.State.AddService(state.AddServiceArgs{Name: "magic", Owner: owner.String(), Charm: charm})
    60  	s.addUnit(c, magic)
    61  	s.addUnit(c, magic)
    62  
    63  	notAssigned, err := s.State.AddService(state.AddServiceArgs{Name: "not-assigned", Owner: owner.String(), Charm: charm})
    64  	c.Assert(err, jc.ErrorIsNil)
    65  	_, err = notAssigned.AddUnit()
    66  	c.Assert(err, jc.ErrorIsNil)
    67  
    68  	_, err = s.State.AddService(state.AddServiceArgs{Name: "no-units", Owner: owner.String(), Charm: charm})
    69  	c.Assert(err, jc.ErrorIsNil)
    70  
    71  	wordpress, err := s.State.AddService(state.AddServiceArgs{Name: "wordpress", Owner: owner.String(), Charm: s.AddTestingCharm(c, "wordpress")})
    72  	c.Assert(err, jc.ErrorIsNil)
    73  	wordpress0 := s.addUnit(c, wordpress)
    74  	_, err = s.State.AddService(state.AddServiceArgs{Name: "logging", Owner: owner.String(), Charm: s.AddTestingCharm(c, "logging")})
    75  	c.Assert(err, jc.ErrorIsNil)
    76  
    77  	eps, err := s.State.InferEndpoints("logging", "wordpress")
    78  	c.Assert(err, jc.ErrorIsNil)
    79  	rel, err := s.State.AddRelation(eps...)
    80  	c.Assert(err, jc.ErrorIsNil)
    81  	ru, err := rel.Unit(wordpress0)
    82  	c.Assert(err, jc.ErrorIsNil)
    83  	err = ru.EnterScope(nil)
    84  	c.Assert(err, jc.ErrorIsNil)
    85  
    86  	for i, test := range []struct {
    87  		message  string
    88  		expected []string
    89  		units    []string
    90  		services []string
    91  		error    string
    92  	}{{
    93  		message: "no units, expected nil slice",
    94  	}, {
    95  		message:  "asking for a service that isn't there",
    96  		services: []string{"foo"},
    97  		error:    `service "foo" not found`,
    98  	}, {
    99  		message:  "service with no units is not really an error",
   100  		services: []string{"no-units"},
   101  	}, {
   102  		message:  "A service with units",
   103  		services: []string{"magic"},
   104  		expected: []string{"magic/0", "magic/1"},
   105  	}, {
   106  		message:  "Asking for just a unit",
   107  		units:    []string{"magic/0"},
   108  		expected: []string{"magic/0"},
   109  	}, {
   110  		message:  "Asking for just a subordinate unit",
   111  		units:    []string{"logging/0"},
   112  		expected: []string{"logging/0"},
   113  	}, {
   114  		message:  "Asking for a unit, and the service",
   115  		services: []string{"magic"},
   116  		units:    []string{"magic/0"},
   117  		expected: []string{"magic/0", "magic/1"},
   118  	}} {
   119  		c.Logf("%v: %s", i, test.message)
   120  		result, err := action.GetAllUnitNames(s.State, test.units, test.services)
   121  		if test.error == "" {
   122  			c.Check(err, jc.ErrorIsNil)
   123  			var units []string
   124  			for _, unit := range result {
   125  				units = append(units, unit.Id())
   126  			}
   127  			c.Check(units, jc.SameContents, test.expected)
   128  		} else {
   129  			c.Check(err, gc.ErrorMatches, test.error)
   130  		}
   131  	}
   132  }
   133  
   134  func (s *runSuite) AssertBlocked(c *gc.C, err error, msg string) {
   135  	c.Assert(params.IsCodeOperationBlocked(err), jc.IsTrue, gc.Commentf("error: %#v", err))
   136  	c.Assert(errors.Cause(err), gc.DeepEquals, &params.Error{
   137  		Message: msg,
   138  		Code:    "operation is blocked",
   139  	})
   140  }
   141  
   142  func (s *runSuite) TestBlockRunOnAllMachines(c *gc.C) {
   143  	// block all changes
   144  	s.BlockAllChanges(c, "TestBlockRunOnAllMachines")
   145  	_, err := s.client.RunOnAllMachines(
   146  		params.RunParams{
   147  			Commands: "hostname",
   148  			Timeout:  testing.LongWait,
   149  		})
   150  	s.AssertBlocked(c, err, "TestBlockRunOnAllMachines")
   151  }
   152  
   153  func (s *runSuite) TestBlockRunMachineAndService(c *gc.C) {
   154  	// block all changes
   155  	s.BlockAllChanges(c, "TestBlockRunMachineAndService")
   156  	_, err := s.client.Run(
   157  		params.RunParams{
   158  			Commands: "hostname",
   159  			Timeout:  testing.LongWait,
   160  			Machines: []string{"0"},
   161  			Services: []string{"magic"},
   162  		})
   163  	s.AssertBlocked(c, err, "TestBlockRunMachineAndService")
   164  }
   165  
   166  func (s *runSuite) TestRunMachineAndService(c *gc.C) {
   167  	// We only test that we create the actions correctly
   168  	// There is no need to test anything else at this level.
   169  	expectedPayload := map[string]interface{}{
   170  		"command": "hostname",
   171  		"timeout": int64(0),
   172  	}
   173  	expectedArgs := params.Actions{
   174  		Actions: []params.Action{
   175  			{Receiver: "unit-magic-0", Name: "juju-run", Parameters: expectedPayload},
   176  			{Receiver: "unit-magic-1", Name: "juju-run", Parameters: expectedPayload},
   177  			{Receiver: "machine-0", Name: "juju-run", Parameters: expectedPayload},
   178  		},
   179  	}
   180  	called := false
   181  	s.PatchValue(action.QueueActions, func(client *action.ActionAPI, args params.Actions) (params.ActionResults, error) {
   182  		called = true
   183  		c.Assert(args, jc.DeepEquals, expectedArgs)
   184  		return params.ActionResults{}, nil
   185  	})
   186  
   187  	s.addMachine(c)
   188  
   189  	charm := s.AddTestingCharm(c, "dummy")
   190  	owner := s.Factory.MakeUser(c, nil).Tag()
   191  	magic, err := s.State.AddService(state.AddServiceArgs{Name: "magic", Owner: owner.String(), Charm: charm})
   192  	c.Assert(err, jc.ErrorIsNil)
   193  	s.addUnit(c, magic)
   194  	s.addUnit(c, magic)
   195  
   196  	s.client.Run(
   197  		params.RunParams{
   198  			Commands: "hostname",
   199  			Machines: []string{"0"},
   200  			Services: []string{"magic"},
   201  		})
   202  	c.Assert(called, jc.IsTrue)
   203  }
   204  
   205  func (s *runSuite) TestRunOnAllMachines(c *gc.C) {
   206  	// We only test that we create the actions correctly
   207  	// There is no need to test anything else at this level.
   208  	expectedPayload := map[string]interface{}{
   209  		"command": "hostname",
   210  		"timeout": testing.LongWait.Nanoseconds(),
   211  	}
   212  	expectedArgs := params.Actions{
   213  		Actions: []params.Action{
   214  			{Receiver: "machine-0", Name: "juju-run", Parameters: expectedPayload},
   215  			{Receiver: "machine-1", Name: "juju-run", Parameters: expectedPayload},
   216  			{Receiver: "machine-2", Name: "juju-run", Parameters: expectedPayload},
   217  		},
   218  	}
   219  	called := false
   220  	s.PatchValue(action.QueueActions, func(client *action.ActionAPI, args params.Actions) (params.ActionResults, error) {
   221  		called = true
   222  		c.Assert(args, jc.DeepEquals, expectedArgs)
   223  		return params.ActionResults{}, nil
   224  	})
   225  	// Make three machines.
   226  	s.addMachine(c)
   227  	s.addMachine(c)
   228  	s.addMachine(c)
   229  
   230  	s.client.RunOnAllMachines(
   231  		params.RunParams{
   232  			Commands: "hostname",
   233  			Timeout:  testing.LongWait,
   234  		})
   235  	c.Assert(called, jc.IsTrue)
   236  }