github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/provider/lxd/environ_instance_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package lxd_test 5 6 import ( 7 "github.com/juju/errors" 8 gitjujutesting "github.com/juju/testing" 9 jc "github.com/juju/testing/checkers" 10 "github.com/juju/version/v2" 11 gc "gopkg.in/check.v1" 12 13 containerlxd "github.com/juju/juju/container/lxd" 14 "github.com/juju/juju/core/instance" 15 "github.com/juju/juju/environs" 16 "github.com/juju/juju/environs/context" 17 "github.com/juju/juju/environs/instances" 18 "github.com/juju/juju/provider/lxd" 19 coretesting "github.com/juju/juju/testing" 20 ) 21 22 type environInstSuite struct { 23 lxd.BaseSuite 24 } 25 26 var _ = gc.Suite(&environInstSuite{}) 27 28 func (s *environInstSuite) TestInstancesOkay(c *gc.C) { 29 ids := []instance.Id{"spam", "eggs", "ham"} 30 var containers []containerlxd.Container 31 var expected []instances.Instance 32 for _, id := range ids { 33 containers = append(containers, *s.NewContainer(c, string(id))) 34 expected = append(expected, s.NewInstance(c, string(id))) 35 } 36 s.Client.Containers = containers 37 38 insts, err := s.Env.Instances(context.NewEmptyCloudCallContext(), ids) 39 c.Assert(err, jc.ErrorIsNil) 40 41 c.Check(insts, jc.DeepEquals, expected) 42 } 43 44 func (s *environInstSuite) TestInstancesAPI(c *gc.C) { 45 ids := []instance.Id{"spam", "eggs", "ham"} 46 s.Env.Instances(context.NewEmptyCloudCallContext(), ids) 47 48 s.Stub.CheckCalls(c, []gitjujutesting.StubCall{{ 49 FuncName: "AliveContainers", 50 Args: []interface{}{ 51 s.Prefix(), 52 }, 53 }}) 54 } 55 56 func (s *environInstSuite) TestInstancesEmptyArg(c *gc.C) { 57 insts, err := s.Env.Instances(context.NewEmptyCloudCallContext(), nil) 58 59 c.Check(insts, gc.HasLen, 0) 60 c.Check(errors.Cause(err), gc.Equals, environs.ErrNoInstances) 61 } 62 63 func (s *environInstSuite) TestInstancesInstancesFailed(c *gc.C) { 64 failure := errors.New("<unknown>") 65 s.Stub.SetErrors(failure) 66 67 ids := []instance.Id{"spam"} 68 insts, err := s.Env.Instances(context.NewEmptyCloudCallContext(), ids) 69 70 c.Check(insts, jc.DeepEquals, []instances.Instance{nil}) 71 c.Check(errors.Cause(err), gc.Equals, failure) 72 } 73 74 func (s *environInstSuite) TestInstancesPartialMatch(c *gc.C) { 75 container := s.NewContainer(c, "spam") 76 expected := s.NewInstance(c, "spam") 77 s.Client.Containers = []containerlxd.Container{*container} 78 79 ids := []instance.Id{"spam", "eggs"} 80 insts, err := s.Env.Instances(context.NewEmptyCloudCallContext(), ids) 81 82 c.Check(insts, jc.DeepEquals, []instances.Instance{expected, nil}) 83 c.Check(errors.Cause(err), gc.Equals, environs.ErrPartialInstances) 84 } 85 86 func (s *environInstSuite) TestInstancesNoMatch(c *gc.C) { 87 container := s.NewContainer(c, "spam") 88 s.Client.Containers = []containerlxd.Container{*container} 89 90 ids := []instance.Id{"eggs"} 91 insts, err := s.Env.Instances(context.NewEmptyCloudCallContext(), ids) 92 93 c.Check(insts, jc.DeepEquals, []instances.Instance{nil}) 94 c.Check(errors.Cause(err), gc.Equals, environs.ErrNoInstances) 95 } 96 97 func (s *environInstSuite) TestInstancesInvalidCredentials(c *gc.C) { 98 var invalidCred = false 99 // allInstances will ultimately return the error. 100 s.Client.Stub.SetErrors(errTestUnAuth) 101 102 ids := []instance.Id{"eggs"} 103 _, err := s.Env.Instances(&context.CloudCallContext{ 104 InvalidateCredentialFunc: func(string) error { 105 invalidCred = true 106 return nil 107 }, 108 }, ids) 109 110 c.Check(err, gc.ErrorMatches, "not authorized") 111 c.Assert(invalidCred, jc.IsTrue) 112 } 113 114 func (s *environInstSuite) TestControllerInstancesOkay(c *gc.C) { 115 s.Client.Containers = []containerlxd.Container{*s.Container} 116 117 ids, err := s.Env.ControllerInstances(context.NewEmptyCloudCallContext(), coretesting.ControllerTag.Id()) 118 c.Assert(err, jc.ErrorIsNil) 119 120 c.Check(ids, jc.DeepEquals, []instance.Id{"spam"}) 121 s.BaseSuite.Client.CheckCallNames(c, "AliveContainers") 122 s.BaseSuite.Client.CheckCall( 123 c, 0, "AliveContainers", "juju-", 124 ) 125 } 126 127 func (s *environInstSuite) TestControllerInstancesNotBootstrapped(c *gc.C) { 128 _, err := s.Env.ControllerInstances(context.NewEmptyCloudCallContext(), "not-used") 129 130 c.Check(err, gc.Equals, environs.ErrNotBootstrapped) 131 } 132 133 func (s *environInstSuite) TestControllerInstancesMixed(c *gc.C) { 134 other := containerlxd.Container{} 135 s.Client.Containers = []containerlxd.Container{*s.Container} 136 s.Client.Containers = []containerlxd.Container{*s.Container, other} 137 138 ids, err := s.Env.ControllerInstances(context.NewEmptyCloudCallContext(), coretesting.ControllerTag.Id()) 139 c.Assert(err, jc.ErrorIsNil) 140 141 c.Check(ids, jc.DeepEquals, []instance.Id{"spam"}) 142 } 143 144 func (s *environInstSuite) TestControllerInvalidCredentials(c *gc.C) { 145 var invalidCred = false 146 // AliveContainers will return an error. 147 s.Client.Stub.SetErrors(errTestUnAuth) 148 149 _, err := s.Env.ControllerInstances( 150 &context.CloudCallContext{ 151 InvalidateCredentialFunc: func(string) error { 152 invalidCred = true 153 return nil 154 }, 155 }, coretesting.ControllerTag.Id()) 156 c.Check(err, gc.ErrorMatches, "not authorized") 157 c.Assert(invalidCred, jc.IsTrue) 158 } 159 160 func (s *environInstSuite) TestAdoptResources(c *gc.C) { 161 one := s.NewContainer(c, "smoosh") 162 two := s.NewContainer(c, "guild-league") 163 three := s.NewContainer(c, "tall-dwarfs") 164 s.Client.Containers = []containerlxd.Container{*one, *two, *three} 165 166 err := s.Env.AdoptResources(context.NewEmptyCloudCallContext(), "target-uuid", version.MustParse("3.4.5")) 167 c.Assert(err, jc.ErrorIsNil) 168 c.Assert(s.BaseSuite.Client.Calls(), gc.HasLen, 4) 169 s.BaseSuite.Client.CheckCall(c, 0, "AliveContainers", "juju-f75cba-") 170 s.BaseSuite.Client.CheckCall( 171 c, 1, "UpdateContainerConfig", "smoosh", map[string]string{"user.juju-controller-uuid": "target-uuid"}) 172 s.BaseSuite.Client.CheckCall( 173 c, 2, "UpdateContainerConfig", "guild-league", map[string]string{"user.juju-controller-uuid": "target-uuid"}) 174 s.BaseSuite.Client.CheckCall( 175 c, 3, "UpdateContainerConfig", "tall-dwarfs", map[string]string{"user.juju-controller-uuid": "target-uuid"}) 176 } 177 178 func (s *environInstSuite) TestAdoptResourcesError(c *gc.C) { 179 one := s.NewContainer(c, "smoosh") 180 two := s.NewContainer(c, "guild-league") 181 three := s.NewContainer(c, "tall-dwarfs") 182 s.Client.Containers = []containerlxd.Container{*one, *two, *three} 183 s.Client.SetErrors(nil, nil, errors.New("blammo")) 184 185 err := s.Env.AdoptResources(context.NewEmptyCloudCallContext(), "target-uuid", version.MustParse("5.3.3")) 186 c.Assert(err, gc.ErrorMatches, `failed to update controller for some instances: \[guild-league\]`) 187 c.Assert(s.BaseSuite.Client.Calls(), gc.HasLen, 4) 188 s.BaseSuite.Client.CheckCall(c, 0, "AliveContainers", "juju-f75cba-") 189 s.BaseSuite.Client.CheckCall( 190 c, 1, "UpdateContainerConfig", "smoosh", map[string]string{"user.juju-controller-uuid": "target-uuid"}) 191 s.BaseSuite.Client.CheckCall( 192 c, 2, "UpdateContainerConfig", "guild-league", map[string]string{"user.juju-controller-uuid": "target-uuid"}) 193 s.BaseSuite.Client.CheckCall( 194 c, 3, "UpdateContainerConfig", "tall-dwarfs", map[string]string{"user.juju-controller-uuid": "target-uuid"}) 195 } 196 197 func (s *environInstSuite) TestAdoptResourcesInvalidResources(c *gc.C) { 198 var invalidCred = false 199 // allInstances will ultimately return the error. 200 s.Client.Stub.SetErrors(errTestUnAuth) 201 202 err := s.Env.AdoptResources(&context.CloudCallContext{ 203 InvalidateCredentialFunc: func(string) error { 204 invalidCred = true 205 return nil 206 }, 207 }, "target-uuid", version.MustParse("3.4.5")) 208 209 c.Check(err, gc.ErrorMatches, ".*not authorized") 210 c.Assert(invalidCred, jc.IsTrue) 211 s.BaseSuite.Client.CheckCall(c, 0, "AliveContainers", "juju-f75cba-") 212 }