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  }