github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/provisioner/container_initialisation_test.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package provisioner 5 6 import ( 7 "errors" 8 "sync" 9 10 "github.com/juju/names/v5" 11 jc "github.com/juju/testing/checkers" 12 "github.com/juju/utils/v3" 13 "go.uber.org/mock/gomock" 14 gc "gopkg.in/check.v1" 15 16 "github.com/juju/juju/agent" 17 apiprovisioner "github.com/juju/juju/api/agent/provisioner" 18 provisionermocks "github.com/juju/juju/api/agent/provisioner/mocks" 19 apimocks "github.com/juju/juju/api/base/mocks" 20 "github.com/juju/juju/container" 21 "github.com/juju/juju/container/factory" 22 "github.com/juju/juju/container/testing" 23 "github.com/juju/juju/core/instance" 24 "github.com/juju/juju/core/machinelock" 25 "github.com/juju/juju/core/network" 26 "github.com/juju/juju/rpc/params" 27 coretesting "github.com/juju/juju/testing" 28 jujuversion "github.com/juju/juju/version" 29 ) 30 31 type containerSetupSuite struct { 32 coretesting.BaseSuite 33 34 modelUUID utils.UUID 35 controllerUUID utils.UUID 36 37 initialiser *testing.MockInitialiser 38 facadeCaller *apimocks.MockFacadeCaller 39 machine *provisionermocks.MockMachineProvisioner 40 manager *testing.MockManager 41 42 machineLock *fakeMachineLock 43 } 44 45 func (s *containerSetupSuite) SetUpTest(c *gc.C) { 46 s.BaseSuite.SetUpTest(c) 47 48 s.modelUUID = utils.MustNewUUID() 49 s.controllerUUID = utils.MustNewUUID() 50 51 s.machineLock = &fakeMachineLock{} 52 } 53 54 var _ = gc.Suite(&containerSetupSuite{}) 55 56 func (s *containerSetupSuite) TestInitialiseContainersKVM(c *gc.C) { 57 s.testInitialiseContainers(c, instance.KVM) 58 } 59 60 func (s *containerSetupSuite) TestInitialiseContainersLXD(c *gc.C) { 61 s.testInitialiseContainers(c, instance.LXD) 62 } 63 64 func (s *containerSetupSuite) testInitialiseContainers(c *gc.C, containerType instance.ContainerType) { 65 defer s.patch(c).Finish() 66 67 s.expectContainerManagerConfig(containerType) 68 s.initialiser.EXPECT().Initialise().Return(nil) 69 70 s.PatchValue( 71 &factory.NewContainerManager, 72 func(forType instance.ContainerType, conf container.ManagerConfig) (container.Manager, error) { 73 return s.manager, nil 74 }) 75 76 cs := s.setUpContainerSetup(c, containerType) 77 abort := make(chan struct{}) 78 close(abort) 79 err := cs.initialiseContainers(abort) 80 c.Assert(err, jc.ErrorIsNil) 81 } 82 83 func (s *containerSetupSuite) TestInitialiseContainerProvisionerKVM(c *gc.C) { 84 s.testInitialiseContainers(c, instance.KVM) 85 } 86 87 func (s *containerSetupSuite) TestInitialiseContainerProvisonerLXD(c *gc.C) { 88 s.testInitialiseContainers(c, instance.LXD) 89 } 90 91 func (s *containerSetupSuite) TestContainerManagerConfigError(c *gc.C) { 92 defer s.patch(c).Finish() 93 94 s.facadeCaller.EXPECT().FacadeCall( 95 "ContainerManagerConfig", params.ContainerManagerConfigParams{Type: "lxd"}, gomock.Any()).Return( 96 errors.New("boom")) 97 98 cs := s.setUpContainerSetup(c, instance.LXD) 99 abort := make(chan struct{}) 100 close(abort) 101 err := cs.initialiseContainers(abort) 102 c.Assert(err, gc.ErrorMatches, ".*generating container manager config: boom") 103 } 104 105 func (s *containerSetupSuite) setUpContainerSetup(c *gc.C, containerType instance.ContainerType) *ContainerSetup { 106 pState := apiprovisioner.NewStateFromFacade(s.facadeCaller) 107 108 cfg, err := agent.NewAgentConfig( 109 agent.AgentConfigParams{ 110 Paths: agent.DefaultPaths, 111 Tag: s.machine.MachineTag(), 112 UpgradedToVersion: jujuversion.Current, 113 Password: "password", 114 Nonce: "nonce", 115 APIAddresses: []string{"0.0.0.0:12345"}, 116 CACert: coretesting.CACert, 117 Controller: names.NewControllerTag(s.controllerUUID.String()), 118 Model: names.NewModelTag(s.modelUUID.String()), 119 }) 120 c.Assert(err, jc.ErrorIsNil) 121 122 args := ContainerSetupParams{ 123 Logger: &noOpLogger{}, 124 ContainerType: containerType, 125 MachineZone: s.machine, 126 MTag: s.machine.MachineTag(), 127 Provisioner: pState, 128 Config: cfg, 129 MachineLock: s.machineLock, 130 CredentialAPI: &credentialAPIForTest{}, 131 GetNetConfig: func(_ network.ConfigSource) (network.InterfaceInfos, error) { 132 return nil, nil 133 }, 134 } 135 136 return NewContainerSetup(args) 137 } 138 139 func (s *containerSetupSuite) patch(c *gc.C) *gomock.Controller { 140 ctrl := gomock.NewController(c) 141 142 s.initialiser = testing.NewMockInitialiser(ctrl) 143 s.facadeCaller = apimocks.NewMockFacadeCaller(ctrl) 144 s.machine = provisionermocks.NewMockMachineProvisioner(ctrl) 145 s.manager = testing.NewMockManager(ctrl) 146 147 s.machine.EXPECT().MachineTag().Return(names.NewMachineTag("0")).AnyTimes() 148 149 s.PatchValue(GetContainerInitialiser, func(instance.ContainerType, map[string]string, string) container.Initialiser { 150 return s.initialiser 151 }) 152 153 return ctrl 154 } 155 156 // expectContainerManagerConfig sets up expectations associated with 157 // acquisition and decoration of container manager configuration. 158 func (s *containerSetupSuite) expectContainerManagerConfig(cType instance.ContainerType) { 159 resultSource := params.ContainerManagerConfig{ 160 ManagerConfig: map[string]string{"model-uuid": s.modelUUID.String()}, 161 } 162 s.facadeCaller.EXPECT().FacadeCall( 163 "ContainerManagerConfig", params.ContainerManagerConfigParams{Type: cType}, gomock.Any(), 164 ).SetArg(2, resultSource).MinTimes(1) 165 } 166 167 type credentialAPIForTest struct{} 168 169 func (*credentialAPIForTest) InvalidateModelCredential(reason string) error { 170 return nil 171 } 172 173 type fakeMachineLock struct { 174 mu sync.Mutex 175 } 176 177 func (f *fakeMachineLock) Acquire(spec machinelock.Spec) (func(), error) { 178 f.mu.Lock() 179 return func() { 180 f.mu.Unlock() 181 }, nil 182 } 183 184 func (f *fakeMachineLock) Report(opts ...machinelock.ReportOption) (string, error) { 185 return "", nil 186 } 187 188 type noOpLogger struct { 189 } 190 191 func (noOpLogger) Errorf(format string, values ...interface{}) {} 192 func (noOpLogger) Warningf(format string, values ...interface{}) {} 193 func (noOpLogger) Infof(format string, values ...interface{}) {} 194 func (noOpLogger) Debugf(format string, values ...interface{}) {} 195 func (noOpLogger) Tracef(format string, values ...interface{}) {} 196 func (noOpLogger) IsTraceEnabled() bool { return false }