github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/common/machine_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/naturalsort"
     9  	jc "github.com/juju/testing/checkers"
    10  	gc "gopkg.in/check.v1"
    11  
    12  	"github.com/juju/juju/apiserver/common"
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/core/instance"
    15  	"github.com/juju/juju/core/status"
    16  	"github.com/juju/juju/state"
    17  	"github.com/juju/juju/state/multiwatcher"
    18  )
    19  
    20  type machineSuite struct{}
    21  
    22  var _ = gc.Suite(&machineSuite{})
    23  
    24  func (s *machineSuite) TestMachineJobFromParams(c *gc.C) {
    25  	var tests = []struct {
    26  		name multiwatcher.MachineJob
    27  		want state.MachineJob
    28  		err  string
    29  	}{{
    30  		name: multiwatcher.JobHostUnits,
    31  		want: state.JobHostUnits,
    32  	}, {
    33  		name: multiwatcher.JobManageModel,
    34  		want: state.JobManageModel,
    35  	}, {
    36  		name: "invalid",
    37  		want: -1,
    38  		err:  `invalid machine job "invalid"`,
    39  	}}
    40  	for _, test := range tests {
    41  		got, err := common.MachineJobFromParams(test.name)
    42  		if err != nil {
    43  			c.Check(err, gc.ErrorMatches, test.err)
    44  		}
    45  		c.Check(got, gc.Equals, test.want)
    46  	}
    47  }
    48  
    49  func (s *machineSuite) TestDestroyMachines(c *gc.C) {
    50  	st := mockState{
    51  		machines: map[string]*mockMachine{
    52  			"1": {},
    53  			"2": {destroyErr: errors.New("unit exists error")},
    54  			"3": {life: state.Dying},
    55  		},
    56  	}
    57  	err := common.MockableDestroyMachines(&st, false, "1", "2", "3", "4")
    58  
    59  	c.Assert(st.machines["1"].Life(), gc.Equals, state.Dying)
    60  	c.Assert(st.machines["1"].forceDestroyCalled, jc.IsFalse)
    61  
    62  	c.Assert(st.machines["2"].Life(), gc.Equals, state.Alive)
    63  	c.Assert(st.machines["2"].forceDestroyCalled, jc.IsFalse)
    64  
    65  	c.Assert(st.machines["3"].forceDestroyCalled, jc.IsFalse)
    66  	c.Assert(st.machines["3"].destroyCalled, jc.IsFalse)
    67  
    68  	c.Assert(err, gc.ErrorMatches, "some machines were not destroyed: unit exists error; machine 4 does not exist")
    69  }
    70  
    71  func (s *machineSuite) TestForceDestroyMachines(c *gc.C) {
    72  	st := mockState{
    73  		machines: map[string]*mockMachine{
    74  			"1": {},
    75  			"2": {life: state.Dying},
    76  		},
    77  	}
    78  	err := common.MockableDestroyMachines(&st, true, "1", "2")
    79  
    80  	c.Assert(st.machines["1"].Life(), gc.Equals, state.Dying)
    81  	c.Assert(st.machines["1"].forceDestroyCalled, jc.IsTrue)
    82  	c.Assert(st.machines["2"].forceDestroyCalled, jc.IsTrue)
    83  
    84  	c.Assert(err, jc.ErrorIsNil)
    85  }
    86  
    87  func (s *machineSuite) TestMachineHardwareInfo(c *gc.C) {
    88  	one := uint64(1)
    89  	amd64 := "amd64"
    90  	gig := uint64(1024)
    91  	st := mockState{
    92  		machines: map[string]*mockMachine{
    93  			"1": {id: "1", life: state.Alive, containerType: instance.NONE,
    94  				hw: &instance.HardwareCharacteristics{
    95  					Arch:     &amd64,
    96  					Mem:      &gig,
    97  					CpuCores: &one,
    98  					CpuPower: &one,
    99  				}},
   100  			"2": {id: "2", life: state.Alive, containerType: instance.LXD},
   101  			"3": {life: state.Dying},
   102  		},
   103  	}
   104  	info, err := common.ModelMachineInfo(&st)
   105  	c.Assert(err, jc.ErrorIsNil)
   106  	c.Assert(info, jc.DeepEquals, []params.ModelMachineInfo{
   107  		{
   108  			Id:          "1",
   109  			DisplayName: "",
   110  			Hardware: &params.MachineHardware{
   111  				Arch:     &amd64,
   112  				Mem:      &gig,
   113  				Cores:    &one,
   114  				CpuPower: &one,
   115  			},
   116  		}, {
   117  			Id:          "2",
   118  			DisplayName: "",
   119  		},
   120  	})
   121  }
   122  
   123  func (s *machineSuite) TestMachineInstanceInfo(c *gc.C) {
   124  	st := mockState{
   125  		machines: map[string]*mockMachine{
   126  			"1": {
   127  				id:        "1",
   128  				instId:    "123",
   129  				status:    status.Down,
   130  				hasVote:   true,
   131  				wantsVote: true,
   132  			},
   133  			"2": {
   134  				id:          "2",
   135  				instId:      "456",
   136  				displayName: "two",
   137  				status:      status.Allocating,
   138  				hasVote:     false,
   139  				wantsVote:   true,
   140  			},
   141  		},
   142  	}
   143  	info, err := common.ModelMachineInfo(&st)
   144  	c.Assert(err, jc.ErrorIsNil)
   145  	c.Assert(info, jc.DeepEquals, []params.ModelMachineInfo{
   146  		{
   147  			Id:         "1",
   148  			InstanceId: "123",
   149  			Status:     "down",
   150  			HasVote:    true,
   151  			WantsVote:  true,
   152  		},
   153  		{
   154  			Id:          "2",
   155  			InstanceId:  "456",
   156  			DisplayName: "two",
   157  			Status:      "allocating",
   158  			HasVote:     false,
   159  			WantsVote:   true,
   160  		},
   161  	})
   162  }
   163  
   164  func (s *machineSuite) TestMachineInstanceInfoWithEmptyDisplayName(c *gc.C) {
   165  	st := mockState{
   166  		machines: map[string]*mockMachine{
   167  			"1": {
   168  				id:          "1",
   169  				instId:      "123",
   170  				displayName: "",
   171  				status:      status.Down,
   172  				hasVote:     true,
   173  				wantsVote:   true,
   174  			},
   175  		},
   176  	}
   177  	info, err := common.ModelMachineInfo(&st)
   178  	c.Assert(err, jc.ErrorIsNil)
   179  	c.Assert(info, jc.DeepEquals, []params.ModelMachineInfo{
   180  		{
   181  			Id:          "1",
   182  			InstanceId:  "123",
   183  			DisplayName: "",
   184  			Status:      "down",
   185  			HasVote:     true,
   186  			WantsVote:   true,
   187  		},
   188  	})
   189  }
   190  
   191  func (s *machineSuite) TestMachineInstanceInfoWithSetDisplayName(c *gc.C) {
   192  	st := mockState{
   193  		machines: map[string]*mockMachine{
   194  			"1": {
   195  				id:          "1",
   196  				instId:      "123",
   197  				displayName: "snowflake",
   198  				status:      status.Down,
   199  				hasVote:     true,
   200  				wantsVote:   true,
   201  			},
   202  		},
   203  	}
   204  	info, err := common.ModelMachineInfo(&st)
   205  	c.Assert(err, jc.ErrorIsNil)
   206  	c.Assert(info, jc.DeepEquals, []params.ModelMachineInfo{
   207  		{
   208  			Id:          "1",
   209  			InstanceId:  "123",
   210  			DisplayName: "snowflake",
   211  			Status:      "down",
   212  			HasVote:     true,
   213  			WantsVote:   true,
   214  		},
   215  	})
   216  }
   217  
   218  type mockState struct {
   219  	common.ModelManagerBackend
   220  	machines map[string]*mockMachine
   221  }
   222  
   223  func (st *mockState) Machine(id string) (common.Machine, error) {
   224  	if m, ok := st.machines[id]; ok {
   225  		return m, nil
   226  	}
   227  	return nil, errors.Errorf("machine %s does not exist", id)
   228  }
   229  
   230  func (st *mockState) AllMachines() (machines []common.Machine, _ error) {
   231  	// Ensure we get machines in id order.
   232  	var ids []string
   233  	for id := range st.machines {
   234  		ids = append(ids, id)
   235  	}
   236  	naturalsort.Sort(ids)
   237  	for _, id := range ids {
   238  		machines = append(machines, st.machines[id])
   239  	}
   240  	return machines, nil
   241  }
   242  
   243  type mockMachine struct {
   244  	state.Machine
   245  	id                 string
   246  	life               state.Life
   247  	containerType      instance.ContainerType
   248  	hw                 *instance.HardwareCharacteristics
   249  	instId             instance.Id
   250  	displayName        string
   251  	hasVote, wantsVote bool
   252  	status             status.Status
   253  	statusErr          error
   254  	destroyErr         error
   255  	forceDestroyErr    error
   256  	forceDestroyCalled bool
   257  	destroyCalled      bool
   258  	agentDead          bool
   259  	presenceErr        error
   260  }
   261  
   262  func (m *mockMachine) Id() string {
   263  	return m.id
   264  }
   265  
   266  func (m *mockMachine) Life() state.Life {
   267  	return m.life
   268  }
   269  
   270  func (m *mockMachine) InstanceId() (instance.Id, error) {
   271  	return m.instId, nil
   272  }
   273  
   274  func (m *mockMachine) InstanceNames() (instance.Id, string, error) {
   275  	instId, err := m.InstanceId()
   276  	return instId, m.displayName, err
   277  }
   278  
   279  func (m *mockMachine) WantsVote() bool {
   280  	return m.wantsVote
   281  }
   282  
   283  func (m *mockMachine) HasVote() bool {
   284  	return m.hasVote
   285  }
   286  
   287  func (m *mockMachine) Status() (status.StatusInfo, error) {
   288  	return status.StatusInfo{
   289  		Status: m.status,
   290  	}, m.statusErr
   291  }
   292  
   293  func (m *mockMachine) HardwareCharacteristics() (*instance.HardwareCharacteristics, error) {
   294  	return m.hw, nil
   295  }
   296  
   297  func (m *mockMachine) AgentPresence() (bool, error) {
   298  	return !m.agentDead, m.presenceErr
   299  }
   300  
   301  func (m *mockMachine) ForceDestroy() error {
   302  	m.forceDestroyCalled = true
   303  	if m.forceDestroyErr != nil {
   304  		return m.forceDestroyErr
   305  	}
   306  	m.life = state.Dying
   307  	return nil
   308  }
   309  
   310  func (m *mockMachine) Destroy() error {
   311  	m.destroyCalled = true
   312  	if m.destroyErr != nil {
   313  		return m.destroyErr
   314  	}
   315  	m.life = state.Dying
   316  	return nil
   317  }