github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/environs/jujutest/tests.go (about) 1 // Copyright 2011, 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package jujutest 5 6 import ( 7 stdcontext "context" 8 "path/filepath" 9 10 jc "github.com/juju/testing/checkers" 11 "github.com/juju/utils/v3" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/cloud" 15 "github.com/juju/juju/core/instance" 16 "github.com/juju/juju/environs" 17 "github.com/juju/juju/environs/bootstrap" 18 environscloudspec "github.com/juju/juju/environs/cloudspec" 19 "github.com/juju/juju/environs/config" 20 "github.com/juju/juju/environs/context" 21 "github.com/juju/juju/environs/filestorage" 22 "github.com/juju/juju/environs/simplestreams" 23 sstesting "github.com/juju/juju/environs/simplestreams/testing" 24 "github.com/juju/juju/environs/storage" 25 envtesting "github.com/juju/juju/environs/testing" 26 "github.com/juju/juju/juju/testing" 27 "github.com/juju/juju/jujuclient" 28 coretesting "github.com/juju/juju/testing" 29 jujuversion "github.com/juju/juju/version" 30 ) 31 32 // Tests is a gocheck suite containing tests verifying juju functionality 33 // against the environment with the given configuration. The 34 // tests are not designed to be run against a live server - the Environ 35 // is opened once for each test, and some potentially expensive operations 36 // may be executed. 37 type Tests struct { 38 TestConfig coretesting.Attrs 39 Credential cloud.Credential 40 CloudEndpoint string 41 CloudRegion string 42 ControllerUUID string 43 Env environs.Environ 44 envtesting.ToolsFixture 45 sstesting.TestDataSuite 46 47 // ControllerStore holds the controller related information 48 // such as controllers, accounts, etc., used when preparing 49 // the environment. This is initialized by SetUpSuite. 50 ControllerStore jujuclient.ClientStore 51 toolsStorage storage.Storage 52 53 // ProviderCallContext holds the context to be used to make 54 // calls to a cloud provider. 55 ProviderCallContext context.ProviderCallContext 56 57 // BootstrapContext holds the context to bootstrap a test environment. 58 BootstrapContext environs.BootstrapContext 59 } 60 61 // Open opens an instance of the testing environment. 62 func (t *Tests) Open(c *gc.C, ctx stdcontext.Context, cfg *config.Config) environs.Environ { 63 e, err := environs.New(ctx, environs.OpenParams{ 64 Cloud: t.CloudSpec(), 65 Config: cfg, 66 }) 67 c.Assert(err, gc.IsNil, gc.Commentf("opening environ %#v", cfg.AllAttrs())) 68 c.Assert(e, gc.NotNil) 69 return e 70 } 71 72 func (t *Tests) CloudSpec() environscloudspec.CloudSpec { 73 credential := t.Credential 74 if credential.AuthType() == "" { 75 credential = cloud.NewEmptyCredential() 76 } 77 return environscloudspec.CloudSpec{ 78 Type: t.TestConfig["type"].(string), 79 Name: t.TestConfig["type"].(string), 80 Region: t.CloudRegion, 81 Endpoint: t.CloudEndpoint, 82 Credential: &credential, 83 } 84 } 85 86 // PrepareParams returns the environs.PrepareParams that will be used to call 87 // environs.Prepare. 88 func (t *Tests) PrepareParams(c *gc.C) bootstrap.PrepareParams { 89 testConfigCopy := t.TestConfig.Merge(nil) 90 91 return bootstrap.PrepareParams{ 92 ControllerConfig: coretesting.FakeControllerConfig(), 93 ModelConfig: testConfigCopy, 94 Cloud: t.CloudSpec(), 95 ControllerName: t.TestConfig["name"].(string), 96 AdminSecret: AdminSecret, 97 } 98 } 99 100 // Prepare prepares an instance of the testing environment. 101 func (t *Tests) Prepare(c *gc.C) environs.Environ { 102 t.Env = t.PrepareWithParams(c, t.PrepareParams(c)) 103 return t.Env 104 } 105 106 // PrepareWithParams prepares an instance of the testing environment. 107 func (t *Tests) PrepareWithParams(c *gc.C, params bootstrap.PrepareParams) environs.Environ { 108 e, err := bootstrap.PrepareController(false, t.BootstrapContext, t.ControllerStore, params) 109 c.Assert(err, gc.IsNil, gc.Commentf("preparing environ %#v", params.ModelConfig)) 110 c.Assert(e, gc.NotNil) 111 t.Env = e.(environs.Environ) 112 return t.Env 113 } 114 115 func (t *Tests) AssertPrepareFailsWithConfig(c *gc.C, badConfig coretesting.Attrs, errorMatches string) error { 116 args := t.PrepareParams(c) 117 args.ModelConfig = coretesting.Attrs(args.ModelConfig).Merge(badConfig) 118 119 e, err := bootstrap.PrepareController(false, t.BootstrapContext, t.ControllerStore, args) 120 c.Assert(err, gc.ErrorMatches, errorMatches) 121 c.Assert(e, gc.IsNil) 122 return err 123 } 124 125 func (t *Tests) SetUpTest(c *gc.C) { 126 storageDir := c.MkDir() 127 baseURLPath := filepath.Join(storageDir, "tools") 128 t.DefaultBaseURL = utils.MakeFileURL(baseURLPath) 129 t.ToolsFixture.SetUpTest(c) 130 stor, err := filestorage.NewFileStorageWriter(storageDir) 131 c.Assert(err, jc.ErrorIsNil) 132 t.UploadFakeTools(c, stor, "released", "released") 133 t.toolsStorage = stor 134 t.ControllerStore = jujuclient.NewMemStore() 135 t.ControllerUUID = coretesting.FakeControllerConfig().ControllerUUID() 136 137 ss := simplestreams.NewSimpleStreams(sstesting.TestDataSourceFactory()) 138 ctx := stdcontext.WithValue(stdcontext.TODO(), bootstrap.SimplestreamsFetcherContextKey, ss) 139 t.BootstrapContext = envtesting.BootstrapContext(ctx, c) 140 t.ProviderCallContext = context.NewCloudCallContext(ctx) 141 } 142 143 func (t *Tests) TearDownTest(c *gc.C) { 144 t.ToolsFixture.TearDownTest(c) 145 } 146 147 func (t *Tests) TestStartStop(c *gc.C) { 148 e := t.Prepare(c) 149 cfg, err := e.Config().Apply(map[string]interface{}{ 150 "agent-version": jujuversion.Current.String(), 151 }) 152 c.Assert(err, jc.ErrorIsNil) 153 err = e.SetConfig(cfg) 154 c.Assert(err, jc.ErrorIsNil) 155 156 insts, err := e.Instances(t.ProviderCallContext, nil) 157 c.Assert(err, jc.ErrorIsNil) 158 c.Assert(insts, gc.HasLen, 0) 159 160 inst0, hc := testing.AssertStartInstance(c, e, t.ProviderCallContext, t.ControllerUUID, "0") 161 c.Assert(inst0, gc.NotNil) 162 id0 := inst0.Id() 163 // Sanity check for hardware characteristics. 164 c.Assert(hc.Arch, gc.NotNil) 165 c.Assert(hc.Mem, gc.NotNil) 166 c.Assert(hc.CpuCores, gc.NotNil) 167 168 inst1, _ := testing.AssertStartInstance(c, e, t.ProviderCallContext, t.ControllerUUID, "1") 169 c.Assert(inst1, gc.NotNil) 170 id1 := inst1.Id() 171 172 insts, err = e.Instances(t.ProviderCallContext, []instance.Id{id0, id1}) 173 c.Assert(err, jc.ErrorIsNil) 174 c.Assert(insts, gc.HasLen, 2) 175 c.Assert(insts[0].Id(), gc.Equals, id0) 176 c.Assert(insts[1].Id(), gc.Equals, id1) 177 178 // order of results is not specified 179 insts, err = e.AllInstances(t.ProviderCallContext) 180 c.Assert(err, jc.ErrorIsNil) 181 c.Assert(insts, gc.HasLen, 2) 182 c.Assert(insts[0].Id(), gc.Not(gc.Equals), insts[1].Id()) 183 184 err = e.StopInstances(t.ProviderCallContext, inst0.Id()) 185 c.Assert(err, jc.ErrorIsNil) 186 187 insts, err = e.Instances(t.ProviderCallContext, []instance.Id{id0, id1}) 188 c.Assert(err, gc.Equals, environs.ErrPartialInstances) 189 c.Assert(insts[0], gc.IsNil) 190 c.Assert(insts[1].Id(), gc.Equals, id1) 191 192 insts, err = e.AllInstances(t.ProviderCallContext) 193 c.Assert(err, jc.ErrorIsNil) 194 c.Assert(insts[0].Id(), gc.Equals, id1) 195 } 196 197 func (t *Tests) TestBootstrap(c *gc.C) { 198 credential := t.Credential 199 if credential.AuthType() == "" { 200 credential = cloud.NewEmptyCredential() 201 } 202 203 var regions []cloud.Region 204 if t.CloudRegion != "" { 205 regions = []cloud.Region{{ 206 Name: t.CloudRegion, 207 Endpoint: t.CloudEndpoint, 208 }} 209 } 210 211 args := bootstrap.BootstrapParams{ 212 ControllerConfig: coretesting.FakeControllerConfig(), 213 Cloud: cloud.Cloud{ 214 Name: t.TestConfig["type"].(string), 215 Type: t.TestConfig["type"].(string), 216 AuthTypes: []cloud.AuthType{credential.AuthType()}, 217 Regions: regions, 218 Endpoint: t.CloudEndpoint, 219 }, 220 CloudRegion: t.CloudRegion, 221 CloudCredential: &credential, 222 CloudCredentialName: "credential", 223 AdminSecret: AdminSecret, 224 CAPrivateKey: coretesting.CAKey, 225 SupportedBootstrapBases: coretesting.FakeSupportedJujuBases, 226 } 227 228 e := t.Prepare(c) 229 err := bootstrap.Bootstrap(t.BootstrapContext, e, t.ProviderCallContext, args) 230 c.Assert(err, jc.ErrorIsNil) 231 232 controllerInstances, err := e.ControllerInstances(t.ProviderCallContext, t.ControllerUUID) 233 c.Assert(err, jc.ErrorIsNil) 234 c.Assert(controllerInstances, gc.Not(gc.HasLen), 0) 235 236 e2 := t.Open(c, t.BootstrapContext.Context(), e.Config()) 237 controllerInstances2, err := e2.ControllerInstances(t.ProviderCallContext, t.ControllerUUID) 238 c.Assert(err, jc.ErrorIsNil) 239 c.Assert(controllerInstances2, gc.Not(gc.HasLen), 0) 240 c.Assert(controllerInstances2, jc.SameContents, controllerInstances) 241 242 err = environs.Destroy(e2.Config().Name(), e2, t.ProviderCallContext, t.ControllerStore) 243 c.Assert(err, jc.ErrorIsNil) 244 245 // Prepare again because Destroy invalidates old environments. 246 e3 := t.Prepare(c) 247 248 err = bootstrap.Bootstrap(t.BootstrapContext, e3, t.ProviderCallContext, args) 249 c.Assert(err, jc.ErrorIsNil) 250 251 err = environs.Destroy(e3.Config().Name(), e3, t.ProviderCallContext, t.ControllerStore) 252 c.Assert(err, jc.ErrorIsNil) 253 }