124
128
err = ioutil.WriteFile(filepath.Join(toolsDir, "tools.tar.gz"), nil, 0644)
125
129
c.Assert(err, jc.ErrorIsNil)
126
130
s.writeDownloadedTools(c, &tools.Tools{Version: current})
132
// Create fake gui.tar.bz2 and downloaded-gui.txt.
133
guiDir := filepath.FromSlash(agenttools.SharedGUIDir(s.dataDir))
134
err = os.MkdirAll(guiDir, 0755)
135
c.Assert(err, jc.ErrorIsNil)
136
err = ioutil.WriteFile(filepath.Join(guiDir, "gui.tar.bz2"), nil, 0644)
137
c.Assert(err, jc.ErrorIsNil)
138
s.writeDownloadedGUI(c, &tools.GUIArchive{
139
Version: version.MustParse("2.0.42"),
129
143
func (s *BootstrapSuite) TearDownTest(c *gc.C) {
141
155
c.Assert(err, jc.ErrorIsNil)
158
func (s *BootstrapSuite) writeDownloadedGUI(c *gc.C, gui *tools.GUIArchive) {
159
guiDir := filepath.FromSlash(agenttools.SharedGUIDir(s.dataDir))
160
err := os.MkdirAll(guiDir, 0755)
161
c.Assert(err, jc.ErrorIsNil)
162
data, err := json.Marshal(gui)
163
c.Assert(err, jc.ErrorIsNil)
164
err = ioutil.WriteFile(filepath.Join(guiDir, "downloaded-gui.txt"), data, 0644)
165
c.Assert(err, jc.ErrorIsNil)
168
func (s *BootstrapSuite) TestGUIArchiveInfoError(c *gc.C) {
169
dir := filepath.FromSlash(agenttools.SharedGUIDir(s.dataDir))
170
info := filepath.Join(dir, "downloaded-gui.txt")
171
err := os.Remove(info)
172
c.Assert(err, jc.ErrorIsNil)
173
_, cmd, err := s.initBootstrapCommand(
174
c, nil, "--model-config", s.b64yamlControllerModelConfig,
175
"--hosted-model-config", s.b64yamlHostedModelConfig,
176
"--instance-id", string(s.instanceId))
177
c.Assert(err, jc.ErrorIsNil)
178
// TODO frankban: this must return an error before the feature branch is
179
// merged into master.
181
c.Assert(err, jc.ErrorIsNil)
184
func (s *BootstrapSuite) TestGUIArchiveError(c *gc.C) {
185
dir := filepath.FromSlash(agenttools.SharedGUIDir(s.dataDir))
186
archive := filepath.Join(dir, "gui.tar.bz2")
187
err := os.Remove(archive)
188
c.Assert(err, jc.ErrorIsNil)
189
_, cmd, err := s.initBootstrapCommand(
190
c, nil, "--model-config", s.b64yamlControllerModelConfig,
191
"--hosted-model-config", s.b64yamlHostedModelConfig,
192
"--instance-id", string(s.instanceId))
193
c.Assert(err, jc.ErrorIsNil)
195
c.Assert(err, gc.ErrorMatches, "cannot read GUI archive: .*")
198
func (s *BootstrapSuite) TestGUIArchiveSuccess(c *gc.C) {
199
_, cmd, err := s.initBootstrapCommand(
200
c, nil, "--model-config", s.b64yamlControllerModelConfig,
201
"--hosted-model-config", s.b64yamlHostedModelConfig,
202
"--instance-id", string(s.instanceId))
203
c.Assert(err, jc.ErrorIsNil)
205
c.Assert(err, jc.ErrorIsNil)
207
// Retrieve the state so that it is possible to access the GUI storage.
208
st, err := state.Open(testing.ModelTag, &mongo.MongoInfo{
210
Addrs: []string{gitjujutesting.MgoServer.Addr()},
211
CACert: testing.CACert,
213
Password: testPassword,
214
}, mongo.DefaultDialOpts(), environs.NewStatePolicy())
215
c.Assert(err, jc.ErrorIsNil)
218
// The GUI archive has been uploaded to the GUI storage.
219
storage, err := st.GUIStorage()
220
c.Assert(err, jc.ErrorIsNil)
221
defer storage.Close()
222
allMeta, err := storage.AllMetadata()
223
c.Assert(err, jc.ErrorIsNil)
224
c.Assert(allMeta, gc.HasLen, 1)
225
c.Assert(allMeta[0].Version, gc.Equals, "2.0.42")
144
228
var testPassword = "my-admin-secret"
146
func testPasswordHash() string {
147
return utils.UserPasswordHash(testPassword, utils.CompatSalt)
150
230
func (s *BootstrapSuite) initBootstrapCommand(c *gc.C, jobs []multiwatcher.MachineJob, args ...string) (machineConf agent.ConfigSetterWriter, cmd *BootstrapCommand, err error) {
151
231
if len(jobs) == 0 {
152
232
// Add default jobs.
199
279
func (s *BootstrapSuite) TestInitializeEnvironment(c *gc.C) {
200
280
hw := instance.MustParseHardware("arch=amd64 mem=8G")
201
machConf, cmd, err := s.initBootstrapCommand(c, nil, "--model-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId), "--hardware", hw.String())
281
machConf, cmd, err := s.initBootstrapCommand(
282
c, nil, "--model-config", s.b64yamlControllerModelConfig,
283
"--hosted-model-config", s.b64yamlHostedModelConfig,
284
"--instance-id", string(s.instanceId), "--hardware", hw.String(),
202
286
c.Assert(err, jc.ErrorIsNil)
203
287
err = cmd.Run(nil)
204
288
c.Assert(err, jc.ErrorIsNil)
263
347
func (s *BootstrapSuite) TestInitializeEnvironmentInvalidOplogSize(c *gc.C) {
264
348
s.mongoOplogSize = "NaN"
265
349
hw := instance.MustParseHardware("arch=amd64 mem=8G")
266
_, cmd, err := s.initBootstrapCommand(c, nil, "--model-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId), "--hardware", hw.String())
350
_, cmd, err := s.initBootstrapCommand(
351
c, nil, "--model-config", s.b64yamlControllerModelConfig,
352
"--hosted-model-config", s.b64yamlHostedModelConfig,
353
"--instance-id", string(s.instanceId), "--hardware", hw.String(),
267
355
c.Assert(err, jc.ErrorIsNil)
268
356
err = cmd.Run(nil)
269
357
c.Assert(err, gc.ErrorMatches, `invalid oplog size: "NaN"`)
275
363
"agent-version": "1.99.1",
277
365
c.Assert(err, jc.ErrorIsNil)
278
b64yamlEnvcfg := b64yaml(envcfg.AllAttrs()).encode()
366
b64yamlControllerModelConfig := b64yaml(envcfg.AllAttrs()).encode()
280
368
hw := instance.MustParseHardware("arch=amd64 mem=8G")
281
_, cmd, err := s.initBootstrapCommand(c, nil, "--model-config", b64yamlEnvcfg, "--instance-id", string(s.instanceId), "--hardware", hw.String())
369
_, cmd, err := s.initBootstrapCommand(
370
c, nil, "--model-config", b64yamlControllerModelConfig,
371
"--hosted-model-config", s.b64yamlHostedModelConfig,
372
"--instance-id", string(s.instanceId), "--hardware", hw.String(),
282
374
c.Assert(err, jc.ErrorIsNil)
283
375
err = cmd.Run(nil)
284
376
c.Assert(err, jc.ErrorIsNil)
303
395
func (s *BootstrapSuite) TestSetConstraints(c *gc.C) {
304
396
bootstrapCons := constraints.Value{Mem: uint64p(4096), CpuCores: uint64p(4)}
305
environCons := constraints.Value{Mem: uint64p(2048), CpuCores: uint64p(2)}
397
modelCons := constraints.Value{Mem: uint64p(2048), CpuCores: uint64p(2)}
306
398
_, cmd, err := s.initBootstrapCommand(c, nil,
307
"--model-config", s.b64yamlEnvcfg,
399
"--model-config", s.b64yamlControllerModelConfig,
400
"--hosted-model-config", s.b64yamlHostedModelConfig,
308
401
"--instance-id", string(s.instanceId),
309
402
"--bootstrap-constraints", bootstrapCons.String(),
310
"--constraints", environCons.String(),
403
"--constraints", modelCons.String(),
312
405
c.Assert(err, jc.ErrorIsNil)
313
406
err = cmd.Run(nil)
318
411
Addrs: []string{gitjujutesting.MgoServer.Addr()},
319
412
CACert: testing.CACert,
321
Password: testPasswordHash(),
414
Password: testPassword,
322
415
}, mongo.DefaultDialOpts(), environs.NewStatePolicy())
323
416
c.Assert(err, jc.ErrorIsNil)
326
419
cons, err := st.ModelConstraints()
327
420
c.Assert(err, jc.ErrorIsNil)
328
c.Assert(cons, gc.DeepEquals, environCons)
421
c.Assert(cons, gc.DeepEquals, modelCons)
330
423
machines, err := st.AllMachines()
331
424
c.Assert(err, jc.ErrorIsNil)
345
438
state.JobHostUnits,
346
439
state.JobManageNetworking,
348
_, cmd, err := s.initBootstrapCommand(c, nil, "--model-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId))
441
_, cmd, err := s.initBootstrapCommand(c, nil,
442
"--model-config", s.b64yamlControllerModelConfig,
443
"--hosted-model-config", s.b64yamlHostedModelConfig,
444
"--instance-id", string(s.instanceId),
349
446
c.Assert(err, jc.ErrorIsNil)
350
447
err = cmd.Run(nil)
351
448
c.Assert(err, jc.ErrorIsNil)
367
464
func (s *BootstrapSuite) TestConfiguredMachineJobs(c *gc.C) {
368
465
jobs := []multiwatcher.MachineJob{multiwatcher.JobManageModel}
369
_, cmd, err := s.initBootstrapCommand(c, jobs, "--model-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId))
466
_, cmd, err := s.initBootstrapCommand(c, jobs,
467
"--model-config", s.b64yamlControllerModelConfig,
468
"--hosted-model-config", s.b64yamlHostedModelConfig,
469
"--instance-id", string(s.instanceId),
370
471
c.Assert(err, jc.ErrorIsNil)
371
472
err = cmd.Run(nil)
372
473
c.Assert(err, jc.ErrorIsNil)
400
501
func (s *BootstrapSuite) TestInitialPassword(c *gc.C) {
401
machineConf, cmd, err := s.initBootstrapCommand(c, nil, "--model-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId))
502
machineConf, cmd, err := s.initBootstrapCommand(c, nil,
503
"--model-config", s.b64yamlControllerModelConfig,
504
"--hosted-model-config", s.b64yamlHostedModelConfig,
505
"--instance-id", string(s.instanceId),
402
507
c.Assert(err, jc.ErrorIsNil)
404
509
err = cmd.Run(nil)
469
574
input: []string{"--model-config", "name: banana\n"},
470
575
err: ".*illegal base64 data at input byte.*",
577
// no value supplied for hosted-model-config
579
"--model-config", base64.StdEncoding.EncodeToString([]byte("name: banana\n")),
581
err: "--hosted-model-config option must be set",
472
583
// no value supplied for instance-id
474
585
"--model-config", base64.StdEncoding.EncodeToString([]byte("name: banana\n")),
586
"--hosted-model-config", base64.StdEncoding.EncodeToString([]byte("name: banana\n")),
476
588
err: "--instance-id option must be set",
478
590
// empty instance-id
480
592
"--model-config", base64.StdEncoding.EncodeToString([]byte("name: banana\n")),
593
"--hosted-model-config", base64.StdEncoding.EncodeToString([]byte("name: banana\n")),
481
594
"--instance-id", "",
483
596
err: "--instance-id option must be set",
486
599
"--model-config", base64.StdEncoding.EncodeToString([]byte("name: banana\n")),
600
"--hosted-model-config", base64.StdEncoding.EncodeToString([]byte("name: banana\n")),
487
601
"--instance-id", "anything",
489
603
expectedInstanceId: "anything",
528
644
func (s *BootstrapSuite) TestInitializeStateArgs(c *gc.C) {
530
initializeState := func(_ names.UserTag, _ agent.ConfigSetter, envCfg *config.Config, machineCfg agent.BootstrapMachineConfig, dialOpts mongo.DialOpts, policy state.Policy) (_ *state.State, _ *state.Machine, resultErr error) {
646
initializeState := func(_ names.UserTag, _ agent.ConfigSetter, envCfg *config.Config, hostedModelConfig map[string]interface{}, machineCfg agentbootstrap.BootstrapMachineConfig, dialOpts mongo.DialOpts, policy state.Policy) (_ *state.State, _ *state.Machine, resultErr error) {
532
648
c.Assert(dialOpts.Direct, jc.IsTrue)
533
649
c.Assert(dialOpts.Timeout, gc.Equals, 30*time.Second)
534
650
c.Assert(dialOpts.SocketTimeout, gc.Equals, 123*time.Second)
651
c.Assert(hostedModelConfig, jc.DeepEquals, map[string]interface{}{
652
"name": "hosted-model",
653
"uuid": s.hostedModelUUID,
535
655
return nil, nil, errors.New("failed to initialize state")
537
657
s.PatchValue(&agentInitializeState, initializeState)
538
_, cmd, err := s.initBootstrapCommand(c, nil, "--model-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId))
658
_, cmd, err := s.initBootstrapCommand(c, nil,
659
"--model-config", s.b64yamlControllerModelConfig,
660
"--hosted-model-config", s.b64yamlHostedModelConfig,
661
"--instance-id", string(s.instanceId),
539
663
c.Assert(err, jc.ErrorIsNil)
540
664
err = cmd.Run(nil)
541
665
c.Assert(err, gc.ErrorMatches, "failed to initialize state")
545
669
func (s *BootstrapSuite) TestInitializeStateMinSocketTimeout(c *gc.C) {
547
initializeState := func(_ names.UserTag, _ agent.ConfigSetter, envCfg *config.Config, machineCfg agent.BootstrapMachineConfig, dialOpts mongo.DialOpts, policy state.Policy) (_ *state.State, _ *state.Machine, resultErr error) {
671
initializeState := func(_ names.UserTag, _ agent.ConfigSetter, envCfg *config.Config, hostedModelConfig map[string]interface{}, machineCfg agentbootstrap.BootstrapMachineConfig, dialOpts mongo.DialOpts, policy state.Policy) (_ *state.State, _ *state.Machine, resultErr error) {
549
673
c.Assert(dialOpts.Direct, jc.IsTrue)
550
674
c.Assert(dialOpts.SocketTimeout, gc.Equals, 1*time.Minute)
555
679
"bootstrap-timeout": "13",
557
681
c.Assert(err, jc.ErrorIsNil)
558
b64yamlEnvcfg := b64yaml(envcfg.AllAttrs()).encode()
682
b64yamlControllerModelConfig := b64yaml(envcfg.AllAttrs()).encode()
560
684
s.PatchValue(&agentInitializeState, initializeState)
561
_, cmd, err := s.initBootstrapCommand(c, nil, "--model-config", b64yamlEnvcfg, "--instance-id", string(s.instanceId))
685
_, cmd, err := s.initBootstrapCommand(c, nil,
686
"--model-config", b64yamlControllerModelConfig,
687
"--hosted-model-config", s.b64yamlHostedModelConfig,
688
"--instance-id", string(s.instanceId),
562
690
c.Assert(err, jc.ErrorIsNil)
563
691
err = cmd.Run(nil)
564
692
c.Assert(err, gc.ErrorMatches, "failed to initialize state")
569
697
_, err := os.Stat(filepath.Join(s.dataDir, agent.SystemIdentity))
570
698
c.Assert(err, jc.Satisfies, os.IsNotExist)
572
_, cmd, err := s.initBootstrapCommand(c, nil, "--model-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId))
700
_, cmd, err := s.initBootstrapCommand(c, nil,
701
"--model-config", s.b64yamlControllerModelConfig,
702
"--hosted-model-config", s.b64yamlHostedModelConfig,
703
"--instance-id", string(s.instanceId),
573
705
c.Assert(err, jc.ErrorIsNil)
574
706
err = cmd.Run(nil)
575
707
c.Assert(err, jc.ErrorIsNil)
600
732
func (s *BootstrapSuite) testToolsMetadata(c *gc.C, exploded bool) {
601
733
envtesting.RemoveFakeToolsMetadata(c, s.toolsStorage)
603
_, cmd, err := s.initBootstrapCommand(c, nil, "--model-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId))
735
_, cmd, err := s.initBootstrapCommand(c, nil,
736
"--model-config", s.b64yamlControllerModelConfig,
737
"--hosted-model-config", s.b64yamlHostedModelConfig,
738
"--instance-id", string(s.instanceId),
604
740
c.Assert(err, jc.ErrorIsNil)
605
741
err = cmd.Run(nil)
606
742
c.Assert(err, jc.ErrorIsNil)
760
897
dir, m, _ := createImageMetadata(c)
761
898
_, cmd, err := s.initBootstrapCommand(
763
"--model-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId),
900
"--model-config", s.b64yamlControllerModelConfig,
901
"--hosted-model-config", s.b64yamlHostedModelConfig,
902
"--instance-id", string(s.instanceId),
764
903
"--image-metadata", dir,
766
905
c.Assert(err, jc.ErrorIsNil)
778
917
dir, _, _ := createImageMetadata(c)
779
918
_, cmd, err := s.initBootstrapCommand(
781
"--model-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId),
920
"--model-config", s.b64yamlControllerModelConfig,
921
"--hosted-model-config", s.b64yamlHostedModelConfig,
922
"--instance-id", string(s.instanceId),
782
923
"--image-metadata", dir,
784
925
c.Assert(err, jc.ErrorIsNil)
829
972
_, cmd, err := s.initBootstrapCommand(
831
"--model-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId),
974
"--model-config", s.b64yamlControllerModelConfig,
975
"--hosted-model-config", s.b64yamlHostedModelConfig,
976
"--instance-id", string(s.instanceId),
832
977
"--image-metadata", metadataDir,
834
979
c.Assert(err, jc.ErrorIsNil)
860
1005
c.Assert(err, jc.ErrorIsNil)
861
1006
provider, err := environs.Provider(cfg.Type())
862
1007
c.Assert(err, jc.ErrorIsNil)
863
env, err := provider.PrepareForBootstrap(nullContext(), environs.PrepareForBootstrapParams{
1008
cfg, err = provider.BootstrapConfig(environs.BootstrapConfigParams{Config: cfg})
1009
c.Assert(err, jc.ErrorIsNil)
1010
env, err := provider.PrepareForBootstrap(nullContext(), cfg)
866
1011
c.Assert(err, jc.ErrorIsNil)
868
1013
s.PatchValue(&juju.JujuPublicKey, sstesting.SignedMetadataPublicKey)
900
1052
func (s *BootstrapSuite) TestDefaultStoragePools(c *gc.C) {
901
_, cmd, err := s.initBootstrapCommand(c, nil, "--model-config", s.b64yamlEnvcfg, "--instance-id", string(s.instanceId))
1053
_, cmd, err := s.initBootstrapCommand(
1054
c, nil, "--model-config", s.b64yamlControllerModelConfig,
1055
"--hosted-model-config", s.b64yamlHostedModelConfig,
1056
"--instance-id", string(s.instanceId),
902
1058
c.Assert(err, jc.ErrorIsNil)
903
1059
err = cmd.Run(nil)
904
1060
c.Assert(err, jc.ErrorIsNil)