github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/state/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 "launchpad.net/gocheck"
    11  
    12  	"github.com/juju/juju/juju/testing"
    13  	"github.com/juju/juju/network"
    14  	"github.com/juju/juju/state"
    15  	"github.com/juju/juju/state/api"
    16  	"github.com/juju/juju/state/api/deployer"
    17  	"github.com/juju/juju/state/api/params"
    18  	apitesting "github.com/juju/juju/state/api/testing"
    19  	statetesting "github.com/juju/juju/state/testing"
    20  	coretesting "github.com/juju/juju/testing"
    21  )
    22  
    23  func TestAll(t *stdtesting.T) {
    24  	coretesting.MgoTestPackage(t)
    25  }
    26  
    27  type deployerSuite struct {
    28  	testing.JujuConnSuite
    29  	*apitesting.APIAddresserTests
    30  
    31  	stateAPI *api.State
    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  	service0    *state.Service
    37  	service1    *state.Service
    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.JobManageEnviron, state.JobHostUnits)
    49  	err := s.machine.SetAddresses(network.NewAddress("0.1.2.3", network.ScopeUnknown))
    50  	c.Assert(err, gc.IsNil)
    51  
    52  	// Create the needed services and relate them.
    53  	s.service0 = s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql"))
    54  	s.service1 = s.AddTestingService(c, "logging", s.AddTestingCharm(c, "logging"))
    55  	eps, err := s.State.InferEndpoints([]string{"mysql", "logging"})
    56  	c.Assert(err, gc.IsNil)
    57  	rel, err := s.State.AddRelation(eps...)
    58  	c.Assert(err, gc.IsNil)
    59  
    60  	// Create principal and subordinate units and assign them.
    61  	s.principal, err = s.service0.AddUnit()
    62  	c.Assert(err, gc.IsNil)
    63  	err = s.principal.AssignToMachine(s.machine)
    64  	c.Assert(err, gc.IsNil)
    65  	relUnit, err := rel.Unit(s.principal)
    66  	c.Assert(err, gc.IsNil)
    67  	err = relUnit.EnterScope(nil)
    68  	c.Assert(err, gc.IsNil)
    69  	s.subordinate, err = s.service1.Unit("logging/0")
    70  	c.Assert(err, gc.IsNil)
    71  
    72  	// Create the deployer facade.
    73  	s.st = s.stateAPI.Deployer()
    74  	c.Assert(s.st, gc.NotNil)
    75  
    76  	s.APIAddresserTests = apitesting.NewAPIAddresserTests(s.st, s.BackingState)
    77  }
    78  
    79  // Note: This is really meant as a unit-test, this isn't a test that
    80  // should need all of the setup we have for this test suite
    81  func (s *deployerSuite) TestNew(c *gc.C) {
    82  	deployer := deployer.NewState(s.stateAPI)
    83  	c.Assert(deployer, gc.NotNil)
    84  }
    85  
    86  func (s *deployerSuite) assertUnauthorized(c *gc.C, err error) {
    87  	c.Assert(err, gc.ErrorMatches, "permission denied")
    88  	c.Assert(err, jc.Satisfies, params.IsCodeUnauthorized)
    89  }
    90  
    91  func (s *deployerSuite) TestWatchUnitsWrongMachine(c *gc.C) {
    92  	// Try with a non-existent machine tag.
    93  	machine, err := s.st.Machine("machine-42")
    94  	c.Assert(err, gc.IsNil)
    95  	w, err := machine.WatchUnits()
    96  	s.assertUnauthorized(c, err)
    97  	c.Assert(w, gc.IsNil)
    98  
    99  	// Try it with an invalid tag format.
   100  	machine, err = s.st.Machine("foo")
   101  	c.Assert(err, gc.IsNil)
   102  	w, err = machine.WatchUnits()
   103  	s.assertUnauthorized(c, err)
   104  	c.Assert(w, gc.IsNil)
   105  }
   106  
   107  func (s *deployerSuite) TestWatchUnits(c *gc.C) {
   108  	machine, err := s.st.Machine(s.machine.Tag())
   109  	c.Assert(err, gc.IsNil)
   110  	w, err := machine.WatchUnits()
   111  	c.Assert(err, gc.IsNil)
   112  	defer statetesting.AssertStop(c, w)
   113  	wc := statetesting.NewStringsWatcherC(c, s.BackingState, w)
   114  
   115  	// Initial event.
   116  	wc.AssertChange("mysql/0", "logging/0")
   117  	wc.AssertNoChange()
   118  
   119  	// Change something other than the lifecycle and make sure it's
   120  	// not detected.
   121  	err = s.subordinate.SetPassword("foo")
   122  	c.Assert(err, gc.ErrorMatches, "password is only 3 bytes long, and is not a valid Agent password")
   123  	wc.AssertNoChange()
   124  
   125  	err = s.subordinate.SetPassword("foo-12345678901234567890")
   126  	c.Assert(err, gc.IsNil)
   127  	wc.AssertNoChange()
   128  
   129  	// Make the subordinate dead and check it's detected.
   130  	err = s.subordinate.EnsureDead()
   131  	c.Assert(err, gc.IsNil)
   132  	wc.AssertChange("logging/0")
   133  	wc.AssertNoChange()
   134  
   135  	statetesting.AssertStop(c, w)
   136  	wc.AssertClosed()
   137  }
   138  
   139  func (s *deployerSuite) TestUnit(c *gc.C) {
   140  	// Try getting a missing unit and an invalid tag.
   141  	unit, err := s.st.Unit("unit-foo-42")
   142  	s.assertUnauthorized(c, err)
   143  	c.Assert(unit, gc.IsNil)
   144  	unit, err = s.st.Unit("42")
   145  	s.assertUnauthorized(c, err)
   146  	c.Assert(unit, gc.IsNil)
   147  
   148  	// Try getting a unit we're not responsible for.
   149  	// First create a new machine and deploy another unit there.
   150  	machine, err := s.State.AddMachine("quantal", state.JobHostUnits)
   151  	c.Assert(err, gc.IsNil)
   152  	principal1, err := s.service0.AddUnit()
   153  	c.Assert(err, gc.IsNil)
   154  	err = principal1.AssignToMachine(machine)
   155  	c.Assert(err, gc.IsNil)
   156  	unit, err = s.st.Unit(principal1.Tag())
   157  	s.assertUnauthorized(c, err)
   158  	c.Assert(unit, gc.IsNil)
   159  
   160  	// Get the principal and subordinate we're responsible for.
   161  	unit, err = s.st.Unit(s.principal.Tag())
   162  	c.Assert(err, gc.IsNil)
   163  	c.Assert(unit.Name(), gc.Equals, "mysql/0")
   164  	unit, err = s.st.Unit(s.subordinate.Tag())
   165  	c.Assert(err, gc.IsNil)
   166  	c.Assert(unit.Name(), gc.Equals, "logging/0")
   167  }
   168  
   169  func (s *deployerSuite) TestUnitLifeRefresh(c *gc.C) {
   170  	unit, err := s.st.Unit(s.subordinate.Tag())
   171  	c.Assert(err, gc.IsNil)
   172  
   173  	c.Assert(unit.Life(), gc.Equals, params.Alive)
   174  
   175  	// Now make it dead and check again, then refresh and check.
   176  	err = s.subordinate.EnsureDead()
   177  	c.Assert(err, gc.IsNil)
   178  	err = s.subordinate.Refresh()
   179  	c.Assert(err, gc.IsNil)
   180  	c.Assert(s.subordinate.Life(), gc.Equals, state.Dead)
   181  	c.Assert(unit.Life(), gc.Equals, params.Alive)
   182  	err = unit.Refresh()
   183  	c.Assert(err, gc.IsNil)
   184  	c.Assert(unit.Life(), gc.Equals, params.Dead)
   185  }
   186  
   187  func (s *deployerSuite) TestUnitRemove(c *gc.C) {
   188  	unit, err := s.st.Unit(s.principal.Tag())
   189  	c.Assert(err, gc.IsNil)
   190  
   191  	// It fails because the entity is still alive.
   192  	// And EnsureDead will fail because there is a subordinate.
   193  	err = unit.Remove()
   194  	c.Assert(err, gc.ErrorMatches, `cannot remove entity "unit-mysql-0": still alive`)
   195  	c.Assert(params.ErrCode(err), gc.Equals, "")
   196  
   197  	// With the subordinate it also fails due to it being alive.
   198  	unit, err = s.st.Unit(s.subordinate.Tag())
   199  	c.Assert(err, gc.IsNil)
   200  	err = unit.Remove()
   201  	c.Assert(err, gc.ErrorMatches, `cannot remove entity "unit-logging-0": still alive`)
   202  	c.Assert(params.ErrCode(err), gc.Equals, "")
   203  
   204  	// Make it dead first and try again.
   205  	err = s.subordinate.EnsureDead()
   206  	c.Assert(err, gc.IsNil)
   207  	err = unit.Remove()
   208  	c.Assert(err, gc.IsNil)
   209  
   210  	// Verify it's gone.
   211  	err = unit.Refresh()
   212  	s.assertUnauthorized(c, err)
   213  	unit, err = s.st.Unit(s.subordinate.Tag())
   214  	s.assertUnauthorized(c, err)
   215  	c.Assert(unit, gc.IsNil)
   216  }
   217  
   218  func (s *deployerSuite) TestUnitSetPassword(c *gc.C) {
   219  	unit, err := s.st.Unit(s.principal.Tag())
   220  	c.Assert(err, gc.IsNil)
   221  
   222  	// Change the principal's password and verify.
   223  	err = unit.SetPassword("foobar-12345678901234567890")
   224  	c.Assert(err, gc.IsNil)
   225  	err = s.principal.Refresh()
   226  	c.Assert(err, gc.IsNil)
   227  	c.Assert(s.principal.PasswordValid("foobar-12345678901234567890"), gc.Equals, true)
   228  
   229  	// Then the subordinate.
   230  	unit, err = s.st.Unit(s.subordinate.Tag())
   231  	c.Assert(err, gc.IsNil)
   232  	err = unit.SetPassword("phony-12345678901234567890")
   233  	c.Assert(err, gc.IsNil)
   234  	err = s.subordinate.Refresh()
   235  	c.Assert(err, gc.IsNil)
   236  	c.Assert(s.subordinate.PasswordValid("phony-12345678901234567890"), gc.Equals, true)
   237  }
   238  
   239  func (s *deployerSuite) TestStateAddresses(c *gc.C) {
   240  	err := s.machine.SetAddresses(network.NewAddress("0.1.2.3", network.ScopeUnknown))
   241  	c.Assert(err, gc.IsNil)
   242  
   243  	stateAddresses, err := s.State.Addresses()
   244  	c.Assert(err, gc.IsNil)
   245  	c.Assert(len(stateAddresses), gc.Equals, 1)
   246  
   247  	addresses, err := s.st.StateAddresses()
   248  	c.Assert(err, gc.IsNil)
   249  	c.Assert(addresses, gc.DeepEquals, stateAddresses)
   250  }