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