github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/api/deployer/deployer_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package deployer_test
     5  
     6  import (
     7  	stdtesting "testing"
     8  
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  	"gopkg.in/juju/names.v2"
    12  
    13  	"github.com/juju/juju/api"
    14  	"github.com/juju/juju/api/deployer"
    15  	apitesting "github.com/juju/juju/api/testing"
    16  	"github.com/juju/juju/apiserver/params"
    17  	"github.com/juju/juju/juju/testing"
    18  	"github.com/juju/juju/network"
    19  	"github.com/juju/juju/state"
    20  	"github.com/juju/juju/status"
    21  	coretesting "github.com/juju/juju/testing"
    22  	"github.com/juju/juju/watcher/watchertest"
    23  )
    24  
    25  func TestAll(t *stdtesting.T) {
    26  	coretesting.MgoTestPackage(t)
    27  }
    28  
    29  type deployerSuite struct {
    30  	testing.JujuConnSuite
    31  	*apitesting.APIAddresserTests
    32  
    33  	stateAPI api.Connection
    34  
    35  	// These are raw State objects. Use them for setup and assertions, but
    36  	// should never be touched by the API calls themselves
    37  	machine     *state.Machine
    38  	service0    *state.Application
    39  	service1    *state.Application
    40  	principal   *state.Unit
    41  	subordinate *state.Unit
    42  
    43  	st *deployer.State
    44  }
    45  
    46  var _ = gc.Suite(&deployerSuite{})
    47  
    48  func (s *deployerSuite) SetUpTest(c *gc.C) {
    49  	s.JujuConnSuite.SetUpTest(c)
    50  	s.stateAPI, s.machine = s.OpenAPIAsNewMachine(c, state.JobManageModel, state.JobHostUnits)
    51  	err := s.machine.SetProviderAddresses(network.NewAddress("0.1.2.3"))
    52  	c.Assert(err, jc.ErrorIsNil)
    53  
    54  	// Create the needed services and relate them.
    55  	s.service0 = s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
    56  	s.service1 = s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging"))
    57  	eps, err := s.State.InferEndpoints("mysql", "logging")
    58  	c.Assert(err, jc.ErrorIsNil)
    59  	rel, err := s.State.AddRelation(eps...)
    60  	c.Assert(err, jc.ErrorIsNil)
    61  
    62  	// Create principal and subordinate units and assign them.
    63  	s.principal, err = s.service0.AddUnit()
    64  	c.Assert(err, jc.ErrorIsNil)
    65  	err = s.principal.AssignToMachine(s.machine)
    66  	c.Assert(err, jc.ErrorIsNil)
    67  	relUnit, err := rel.Unit(s.principal)
    68  	c.Assert(err, jc.ErrorIsNil)
    69  	err = relUnit.EnterScope(nil)
    70  	c.Assert(err, jc.ErrorIsNil)
    71  	s.subordinate, err = s.State.Unit("logging/0")
    72  	c.Assert(err, jc.ErrorIsNil)
    73  
    74  	// Create the deployer facade.
    75  	s.st = deployer.NewState(s.stateAPI)
    76  	c.Assert(s.st, gc.NotNil)
    77  
    78  	s.APIAddresserTests = apitesting.NewAPIAddresserTests(s.st, s.BackingState)
    79  }
    80  
    81  // Note: This is really meant as a unit-test, this isn't a test that
    82  // should need all of the setup we have for this test suite
    83  func (s *deployerSuite) TestNew(c *gc.C) {
    84  	deployer := deployer.NewState(s.stateAPI)
    85  	c.Assert(deployer, gc.NotNil)
    86  }
    87  
    88  func (s *deployerSuite) assertUnauthorized(c *gc.C, err error) {
    89  	c.Assert(err, gc.ErrorMatches, "permission denied")
    90  	c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized)
    91  }
    92  
    93  func (s *deployerSuite) TestWatchUnitsWrongMachine(c *gc.C) {
    94  	// Try with a non-existent machine tag.
    95  	machine, err := s.st.Machine(names.NewMachineTag("42"))
    96  	c.Assert(err, jc.ErrorIsNil)
    97  	w, err := machine.WatchUnits()
    98  	s.assertUnauthorized(c, err)
    99  	c.Assert(w, gc.IsNil)
   100  }
   101  
   102  func (s *deployerSuite) TestWatchUnits(c *gc.C) {
   103  	// TODO(dfc) fix state.Machine to return a MachineTag
   104  	machine, err := s.st.Machine(s.machine.Tag().(names.MachineTag))
   105  	c.Assert(err, jc.ErrorIsNil)
   106  	w, err := machine.WatchUnits()
   107  	c.Assert(err, jc.ErrorIsNil)
   108  	wc := watchertest.NewStringsWatcherC(c, w, s.BackingState.StartSync)
   109  	defer wc.AssertStops()
   110  
   111  	// Initial event.
   112  	wc.AssertChange("mysql/0", "logging/0")
   113  	wc.AssertNoChange()
   114  
   115  	// Change something other than the lifecycle and make sure it's
   116  	// not detected.
   117  	err = s.subordinate.SetPassword("foo")
   118  	c.Assert(err, gc.ErrorMatches, "password is only 3 bytes long, and is not a valid Agent password")
   119  	wc.AssertNoChange()
   120  
   121  	err = s.subordinate.SetPassword("foo-12345678901234567890")
   122  	c.Assert(err, jc.ErrorIsNil)
   123  	wc.AssertNoChange()
   124  
   125  	// Make the subordinate dead and check it's detected.
   126  	err = s.subordinate.EnsureDead()
   127  	c.Assert(err, jc.ErrorIsNil)
   128  	wc.AssertChange("logging/0")
   129  	wc.AssertNoChange()
   130  }
   131  
   132  func (s *deployerSuite) TestUnit(c *gc.C) {
   133  	// Try getting a missing unit and an invalid tag.
   134  	unit, err := s.st.Unit(names.NewUnitTag("foo/42"))
   135  	s.assertUnauthorized(c, err)
   136  	c.Assert(unit, gc.IsNil)
   137  
   138  	// Try getting a unit we're not responsible for.
   139  	// First create a new machine and deploy another unit there.
   140  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   141  	c.Assert(err, jc.ErrorIsNil)
   142  	principal1, err := s.service0.AddUnit()
   143  	c.Assert(err, jc.ErrorIsNil)
   144  	err = principal1.AssignToMachine(machine)
   145  	c.Assert(err, jc.ErrorIsNil)
   146  	unit, err = s.st.Unit(principal1.Tag().(names.UnitTag))
   147  	s.assertUnauthorized(c, err)
   148  	c.Assert(unit, gc.IsNil)
   149  
   150  	// Get the principal and subordinate we're responsible for.
   151  	unit, err = s.st.Unit(s.principal.Tag().(names.UnitTag))
   152  	c.Assert(err, jc.ErrorIsNil)
   153  	c.Assert(unit.Name(), gc.Equals, "mysql/0")
   154  	unit, err = s.st.Unit(s.subordinate.Tag().(names.UnitTag))
   155  	c.Assert(err, jc.ErrorIsNil)
   156  	c.Assert(unit.Name(), gc.Equals, "logging/0")
   157  }
   158  
   159  func (s *deployerSuite) TestUnitLifeRefresh(c *gc.C) {
   160  	unit, err := s.st.Unit(s.subordinate.Tag().(names.UnitTag))
   161  	c.Assert(err, jc.ErrorIsNil)
   162  
   163  	c.Assert(unit.Life(), gc.Equals, params.Alive)
   164  
   165  	// Now make it dead and check again, then refresh and check.
   166  	err = s.subordinate.EnsureDead()
   167  	c.Assert(err, jc.ErrorIsNil)
   168  	err = s.subordinate.Refresh()
   169  	c.Assert(err, jc.ErrorIsNil)
   170  	c.Assert(s.subordinate.Life(), gc.Equals, state.Dead)
   171  	c.Assert(unit.Life(), gc.Equals, params.Alive)
   172  	err = unit.Refresh()
   173  	c.Assert(err, jc.ErrorIsNil)
   174  	c.Assert(unit.Life(), gc.Equals, params.Dead)
   175  }
   176  
   177  func (s *deployerSuite) TestUnitRemove(c *gc.C) {
   178  	unit, err := s.st.Unit(s.principal.Tag().(names.UnitTag))
   179  	c.Assert(err, jc.ErrorIsNil)
   180  
   181  	// It fails because the entity is still alive.
   182  	// And EnsureDead will fail because there is a subordinate.
   183  	err = unit.Remove()
   184  	c.Assert(err, gc.ErrorMatches, `cannot remove entity "unit-mysql-0": still alive`)
   185  	c.Assert(params.ErrCode(err), gc.Equals, "")
   186  
   187  	// With the subordinate it also fails due to it being alive.
   188  	unit, err = s.st.Unit(s.subordinate.Tag().(names.UnitTag))
   189  	c.Assert(err, jc.ErrorIsNil)
   190  	err = unit.Remove()
   191  	c.Assert(err, gc.ErrorMatches, `cannot remove entity "unit-logging-0": still alive`)
   192  	c.Assert(params.ErrCode(err), gc.Equals, "")
   193  
   194  	// Make it dead first and try again.
   195  	err = s.subordinate.EnsureDead()
   196  	c.Assert(err, jc.ErrorIsNil)
   197  	err = unit.Remove()
   198  	c.Assert(err, jc.ErrorIsNil)
   199  
   200  	// Verify it's gone.
   201  	err = unit.Refresh()
   202  	s.assertUnauthorized(c, err)
   203  	unit, err = s.st.Unit(s.subordinate.Tag().(names.UnitTag))
   204  	s.assertUnauthorized(c, err)
   205  	c.Assert(unit, gc.IsNil)
   206  }
   207  
   208  func (s *deployerSuite) TestUnitSetPassword(c *gc.C) {
   209  	unit, err := s.st.Unit(s.principal.Tag().(names.UnitTag))
   210  	c.Assert(err, jc.ErrorIsNil)
   211  
   212  	// Change the principal's password and verify.
   213  	err = unit.SetPassword("foobar-12345678901234567890")
   214  	c.Assert(err, jc.ErrorIsNil)
   215  	err = s.principal.Refresh()
   216  	c.Assert(err, jc.ErrorIsNil)
   217  	c.Assert(s.principal.PasswordValid("foobar-12345678901234567890"), jc.IsTrue)
   218  
   219  	// Then the subordinate.
   220  	unit, err = s.st.Unit(s.subordinate.Tag().(names.UnitTag))
   221  	c.Assert(err, jc.ErrorIsNil)
   222  	err = unit.SetPassword("phony-12345678901234567890")
   223  	c.Assert(err, jc.ErrorIsNil)
   224  	err = s.subordinate.Refresh()
   225  	c.Assert(err, jc.ErrorIsNil)
   226  	c.Assert(s.subordinate.PasswordValid("phony-12345678901234567890"), jc.IsTrue)
   227  }
   228  
   229  func (s *deployerSuite) TestStateAddresses(c *gc.C) {
   230  	err := s.machine.SetProviderAddresses(network.NewAddress("0.1.2.3"))
   231  	c.Assert(err, jc.ErrorIsNil)
   232  
   233  	stateAddresses, err := s.State.Addresses()
   234  	c.Assert(err, jc.ErrorIsNil)
   235  	c.Assert(len(stateAddresses), gc.Equals, 1)
   236  
   237  	addresses, err := s.st.StateAddresses()
   238  	c.Assert(err, jc.ErrorIsNil)
   239  	c.Assert(addresses, gc.DeepEquals, stateAddresses)
   240  }
   241  
   242  func (s *deployerSuite) TestUnitSetStatus(c *gc.C) {
   243  	unit, err := s.st.Unit(s.principal.Tag().(names.UnitTag))
   244  	c.Assert(err, jc.ErrorIsNil)
   245  	err = unit.SetStatus(status.Blocked, "waiting", map[string]interface{}{"foo": "bar"})
   246  	c.Assert(err, jc.ErrorIsNil)
   247  
   248  	stateUnit, err := s.BackingState.Unit(unit.Name())
   249  	c.Assert(err, jc.ErrorIsNil)
   250  	sInfo, err := stateUnit.Status()
   251  	c.Assert(err, jc.ErrorIsNil)
   252  	sInfo.Since = nil
   253  	c.Assert(sInfo, jc.DeepEquals, status.StatusInfo{
   254  		Status:  status.Blocked,
   255  		Message: "waiting",
   256  		Data:    map[string]interface{}{"foo": "bar"},
   257  	})
   258  }