func (s *BootstrapSuite) TestAutoUploadAfterFailedSync(c *gc.C) { s.PatchValue(&version.Current.Series, config.LatestLtsSeries()) otherSeries := "quantal" env := s.setupAutoUploadTest(c, "1.7.3", otherSeries) // Run command and check for that upload has been run for tools matching the current juju version. opc, errc := runCommand(nullContext(c), new(BootstrapCommand)) c.Assert(<-errc, gc.IsNil) c.Assert((<-opc).(dummy.OpPutFile).Env, gc.Equals, "peckham") list, err := envtools.FindTools(env, version.Current.Major, version.Current.Minor, coretools.Filter{}, false) c.Assert(err, gc.IsNil) c.Logf("found: " + list.String()) urls := list.URLs() // We expect: // supported LTS series precise, trusty, // the specified series (quantal), // and the environment's default series (raring). expectedVers := []version.Binary{ version.MustParseBinary(fmt.Sprintf("1.7.3.1-%s-%s", "quantal", version.Current.Arch)), version.MustParseBinary(fmt.Sprintf("1.7.3.1-%s-%s", "raring", version.Current.Arch)), version.MustParseBinary(fmt.Sprintf("1.7.3.1-%s-%s", "precise", version.Current.Arch)), version.MustParseBinary(fmt.Sprintf("1.7.3.1-%s-%s", "trusty", version.Current.Arch)), } c.Assert(urls, gc.HasLen, len(expectedVers)) for _, vers := range expectedVers { c.Logf("seeking: " + vers.String()) _, found := urls[vers] c.Check(found, gc.Equals, true) } }
func (s *BootstrapSuite) runAllowRetriesTest(c *gc.C, test bootstrapRetryTest) { toolsVersions := envtesting.VAll if test.version != "" { useVersion := strings.Replace(test.version, "%LTS%", config.LatestLtsSeries(), 1) testVersion := version.MustParseBinary(useVersion) s.PatchValue(&version.Current, testVersion) if test.addVersionToSource { toolsVersions = append([]version.Binary{}, toolsVersions...) toolsVersions = append(toolsVersions, testVersion) } } _, fake := makeEmptyFakeHome(c) defer fake.Restore() sourceDir := createToolsSource(c, toolsVersions) s.PatchValue(&envtools.DefaultBaseURL, sourceDir) var findToolsRetryValues []bool mockFindTools := func(cloudInst environs.ConfigGetter, majorVersion, minorVersion int, filter coretools.Filter, allowRetry bool) (list coretools.List, err error) { findToolsRetryValues = append(findToolsRetryValues, allowRetry) return nil, errors.NotFoundf("tools") } restore := envtools.TestingPatchBootstrapFindTools(mockFindTools) defer restore() _, errc := runCommand(nullContext(c), new(BootstrapCommand), test.args...) err := <-errc c.Check(findToolsRetryValues, gc.DeepEquals, test.expectedAllowRetry) stripped := strings.Replace(err.Error(), "\n", "", -1) c.Check(stripped, gc.Matches, test.err) }
func (s *NewAPIClientSuite) TestWithConfigAndNoInfo(c *gc.C) { defer coretesting.MakeSampleHome(c).Restore() store := newConfigStore(coretesting.SampleEnvName, &environInfo{ bootstrapConfig: map[string]interface{}{ "type": "dummy", "name": "myenv", "state-server": true, "authorized-keys": "i-am-a-key", "default-series": config.LatestLtsSeries(), "firewall-mode": config.FwInstance, "development": false, "ssl-hostname-verification": true, "admin-secret": "adminpass", }, }) bootstrapEnv(c, coretesting.SampleEnvName, store) // Verify the cache is empty. info, err := store.ReadInfo("myenv") c.Assert(err, gc.IsNil) c.Assert(info, gc.NotNil) c.Assert(info.APIEndpoint(), jc.DeepEquals, configstore.APIEndpoint{}) c.Assert(info.APICredentials(), jc.DeepEquals, configstore.APICredentials{}) called := 0 expectState := &mockAPIState{} apiOpen := func(apiInfo *api.Info, opts api.DialOpts) (juju.APIState, error) { c.Check(apiInfo.Tag, gc.Equals, "user-admin") c.Check(string(apiInfo.CACert), gc.Not(gc.Equals), "") c.Check(apiInfo.Password, gc.Equals, "adminpass") c.Check(opts, gc.DeepEquals, api.DefaultDialOpts()) called++ return expectState, nil } st, err := juju.NewAPIFromStore("myenv", store, apiOpen) c.Assert(err, gc.IsNil) c.Assert(st, gc.Equals, expectState) c.Assert(called, gc.Equals, 1) // Make sure the cache is updated. info, err = store.ReadInfo("myenv") c.Assert(err, gc.IsNil) c.Assert(info, gc.NotNil) ep := info.APIEndpoint() c.Assert(ep.Addresses, gc.HasLen, 1) c.Check(ep.Addresses[0], gc.Matches, `127\.0\.0\.1:\d+`) c.Check(ep.CACert, gc.Not(gc.Equals), "") creds := info.APICredentials() c.Check(creds.User, gc.Equals, "admin") c.Check(creds.Password, gc.Equals, "adminpass") }
func (s *ImageMetadataSuite) TestImageMetadataFilesLatestLts(c *gc.C) { ctx := testing.Context(c) code := cmd.Main( &ImageMetadataCommand{}, ctx, []string{ "-d", s.dir, "-i", "1234", "-r", "region", "-a", "arch", "-u", "endpoint"}) c.Assert(code, gc.Equals, 0) out := testing.Stdout(ctx) expected := expectedMetadata{ series: config.LatestLtsSeries(), arch: "arch", } s.assertCommandOutput(c, expected, out, defaultIndexFileName, defaultImageFileName) }
// setParams sets parameters based on the environment configuration // for those which have not been explicitly specified. func (c *ImageMetadataCommand) setParams(context *cmd.Context) error { c.privateStorage = "<private storage name>" var environ environs.Environ if store, err := configstore.Default(); err == nil { if environ, err = environs.PrepareFromName(c.EnvName, context, store); err == nil { logger.Infof("creating image metadata for environment %q", environ.Name()) // If the user has not specified region and endpoint, try and get it from the environment. if c.Region == "" || c.Endpoint == "" { var cloudSpec simplestreams.CloudSpec if inst, ok := environ.(simplestreams.HasRegion); ok { if cloudSpec, err = inst.Region(); err != nil { return err } } else { return fmt.Errorf("environment %q cannot provide region and endpoint", environ.Name()) } // If only one of region or endpoint is provided, that is a problem. if cloudSpec.Region != cloudSpec.Endpoint && (cloudSpec.Region == "" || cloudSpec.Endpoint == "") { return fmt.Errorf("cannot generate metadata without a complete cloud configuration") } if c.Region == "" { c.Region = cloudSpec.Region } if c.Endpoint == "" { c.Endpoint = cloudSpec.Endpoint } } cfg := environ.Config() if c.Series == "" { c.Series = config.PreferredSeries(cfg) } if v, ok := cfg.AllAttrs()["control-bucket"]; ok { c.privateStorage = v.(string) } } else { logger.Warningf("environment %q could not be opened: %v", c.EnvName, err) } } if environ == nil { logger.Infof("no environment found, creating image metadata using user supplied data") } if c.Series == "" { c.Series = config.LatestLtsSeries() } if c.ImageId == "" { return fmt.Errorf("image id must be specified") } if c.Region == "" { return fmt.Errorf("image region must be specified") } if c.Endpoint == "" { return fmt.Errorf("cloud endpoint URL must be specified") } if c.Dir == "" { logger.Infof("no destination directory specified, using current directory") var err error if c.Dir, err = os.Getwd(); err != nil { return err } } return nil }
func (t *LiveTests) TestBootstrapAndDeploy(c *gc.C) { if !t.CanOpenState || !t.HasProvisioner { c.Skip(fmt.Sprintf("skipping provisioner test, CanOpenState: %v, HasProvisioner: %v", t.CanOpenState, t.HasProvisioner)) } t.BootstrapOnce(c) // TODO(niemeyer): Stop growing this kitchen sink test and split it into proper parts. c.Logf("opening connection") conn, err := juju.NewConn(t.Env) c.Assert(err, gc.IsNil) defer conn.Close() c.Logf("opening API connection") apiConn, err := juju.NewAPIConn(t.Env, api.DefaultDialOpts()) c.Assert(err, gc.IsNil) defer conn.Close() // Check that the agent version has made it through the // bootstrap process (it's optional in the config.Config) cfg, err := conn.State.EnvironConfig() c.Assert(err, gc.IsNil) agentVersion, ok := cfg.AgentVersion() c.Check(ok, gc.Equals, true) c.Check(agentVersion, gc.Equals, version.Current.Number) // Check that the constraints have been set in the environment. cons, err := conn.State.EnvironConstraints() c.Assert(err, gc.IsNil) c.Assert(cons.String(), gc.Equals, "mem=2048M") // Wait for machine agent to come up on the bootstrap // machine and find the deployed series from that. m0, err := conn.State.Machine("0") c.Assert(err, gc.IsNil) instId0, err := m0.InstanceId() c.Assert(err, gc.IsNil) // Check that the API connection is working. status, err := apiConn.State.Client().Status(nil) c.Assert(err, gc.IsNil) c.Assert(status.Machines["0"].InstanceId, gc.Equals, string(instId0)) mw0 := newMachineToolWaiter(m0) defer mw0.Stop() // If the series has not been specified, we expect the most recent Ubuntu LTS release to be used. expectedVersion := version.Current expectedVersion.Series = config.LatestLtsSeries() mtools0 := waitAgentTools(c, mw0, expectedVersion) // Create a new service and deploy a unit of it. c.Logf("deploying service") repoDir := c.MkDir() url := coretesting.Charms.ClonedURL(repoDir, mtools0.Version.Series, "dummy") sch, err := conn.PutCharm(url, &charm.LocalRepository{Path: repoDir}, false) c.Assert(err, gc.IsNil) svc, err := conn.State.AddService("dummy", "user-admin", sch, nil, nil) c.Assert(err, gc.IsNil) units, err := juju.AddUnits(conn.State, svc, 1, "") c.Assert(err, gc.IsNil) unit := units[0] // Wait for the unit's machine and associated agent to come up // and announce itself. mid1, err := unit.AssignedMachineId() c.Assert(err, gc.IsNil) m1, err := conn.State.Machine(mid1) c.Assert(err, gc.IsNil) mw1 := newMachineToolWaiter(m1) defer mw1.Stop() waitAgentTools(c, mw1, mtools0.Version) err = m1.Refresh() c.Assert(err, gc.IsNil) instId1, err := m1.InstanceId() c.Assert(err, gc.IsNil) uw := newUnitToolWaiter(unit) defer uw.Stop() utools := waitAgentTools(c, uw, expectedVersion) // Check that we can upgrade the environment. newVersion := utools.Version newVersion.Patch++ t.checkUpgrade(c, conn, newVersion, mw0, mw1, uw) // BUG(niemeyer): Logic below is very much wrong. Must be: // // 1. EnsureDying on the unit and EnsureDying on the machine // 2. Unit dies by itself // 3. Machine removes dead unit // 4. Machine dies by itself // 5. Provisioner removes dead machine // // Now remove the unit and its assigned machine and // check that the PA removes it. c.Logf("removing unit") err = unit.Destroy() c.Assert(err, gc.IsNil) // Wait until unit is dead uwatch := unit.Watch() defer uwatch.Stop() for unit.Life() != state.Dead { c.Logf("waiting for unit change") <-uwatch.Changes() err := unit.Refresh() c.Logf("refreshed; err %v", err) if errors.IsNotFound(err) { c.Logf("unit has been removed") break } c.Assert(err, gc.IsNil) } for { c.Logf("destroying machine") err := m1.Destroy() if err == nil { break } c.Assert(err, gc.FitsTypeOf, &state.HasAssignedUnitsError{}) time.Sleep(5 * time.Second) err = m1.Refresh() if errors.IsNotFound(err) { break } c.Assert(err, gc.IsNil) } c.Logf("waiting for instance to be removed") t.assertStopInstance(c, conn.Environ, instId1) }
func (test bootstrapTest) run(c *gc.C) { // Create home with dummy provider and remove all // of its envtools. env, fake := makeEmptyFakeHome(c) defer fake.Restore() if test.version != "" { useVersion := strings.Replace(test.version, "%LTS%", config.LatestLtsSeries(), 1) origVersion := version.Current version.Current = version.MustParseBinary(useVersion) defer func() { version.Current = origVersion }() } if test.hostArch != "" { origVersion := arch.HostArch arch.HostArch = func() string { return test.hostArch } defer func() { arch.HostArch = origVersion }() } uploadCount := len(test.uploads) if uploadCount == 0 { usefulVersion := version.Current usefulVersion.Series = config.PreferredSeries(env.Config()) envtesting.AssertUploadFakeToolsVersions(c, env.Storage(), usefulVersion) } // Run command and check for uploads. opc, errc := runCommand(nullContext(c), new(BootstrapCommand), test.args...) // Check for remaining operations/errors. if test.err != "" { err := <-errc stripped := strings.Replace(err.Error(), "\n", "", -1) c.Check(stripped, gc.Matches, test.err) return } if !c.Check(<-errc, gc.IsNil) { return } if uploadCount > 0 { for i := 0; i < uploadCount; i++ { c.Check((<-opc).(dummy.OpPutFile).Env, gc.Equals, "peckham") } list, err := envtools.FindTools( env, version.Current.Major, version.Current.Minor, coretools.Filter{}, envtools.DoNotAllowRetry) c.Check(err, gc.IsNil) c.Logf("found: " + list.String()) urls := list.URLs() c.Check(urls, gc.HasLen, len(test.uploads)) for _, v := range test.uploads { v := strings.Replace(v, "%LTS%", config.LatestLtsSeries(), 1) c.Logf("seeking: " + v) vers := version.MustParseBinary(v) _, found := urls[vers] c.Check(found, gc.Equals, true) } } if len(test.uploads) > 0 { indexFile := (<-opc).(dummy.OpPutFile) c.Check(indexFile.FileName, gc.Equals, "tools/streams/v1/index.json") productFile := (<-opc).(dummy.OpPutFile) c.Check(productFile.FileName, gc.Equals, "tools/streams/v1/com.ubuntu.juju:released:tools.json") } opPutBootstrapVerifyFile := (<-opc).(dummy.OpPutFile) c.Check(opPutBootstrapVerifyFile.Env, gc.Equals, "peckham") c.Check(opPutBootstrapVerifyFile.FileName, gc.Equals, environs.VerificationFilename) opPutBootstrapInitFile := (<-opc).(dummy.OpPutFile) c.Check(opPutBootstrapInitFile.Env, gc.Equals, "peckham") c.Check(opPutBootstrapInitFile.FileName, gc.Equals, "provider-state") opBootstrap := (<-opc).(dummy.OpBootstrap) c.Check(opBootstrap.Env, gc.Equals, "peckham") c.Check(opBootstrap.Args.Constraints, gc.DeepEquals, test.constraints) c.Check(opBootstrap.Args.Placement, gc.Equals, test.placement) store, err := configstore.Default() c.Assert(err, gc.IsNil) // Check a CA cert/key was generated by reloading the environment. env, err = environs.NewFromName("peckham", store) c.Assert(err, gc.IsNil) _, hasCert := env.Config().CACert() c.Check(hasCert, gc.Equals, true) _, hasKey := env.Config().CAPrivateKey() c.Check(hasKey, gc.Equals, true) }
func (s *UpgradeJujuSuite) TestUpgradeJuju(c *gc.C) { s.PatchValue(&sync.BuildToolsTarball, s.getMockBuildTools(c)) oldVersion := version.Current defer func() { version.Current = oldVersion }() for i, test := range upgradeJujuTests { c.Logf("\ntest %d: %s", i, test.about) s.Reset(c) // Set up apparent CLI version and initialize the command. version.Current = version.MustParseBinary(test.currentVersion) com := &UpgradeJujuCommand{} if err := coretesting.InitCommand(com, test.args); err != nil { if test.expectInitErr != "" { c.Check(err, gc.ErrorMatches, test.expectInitErr) } else { c.Check(err, gc.IsNil) } continue } // Set up state and environ, and run the command. toolsDir := c.MkDir() updateAttrs := map[string]interface{}{ "agent-version": test.agentVersion, "tools-metadata-url": "file://" + toolsDir, } err := s.State.UpdateEnvironConfig(updateAttrs, nil, nil) c.Assert(err, gc.IsNil) versions := make([]version.Binary, len(test.tools)) for i, v := range test.tools { versions[i] = version.MustParseBinary(v) } if len(versions) > 0 { envtesting.MustUploadFakeToolsVersions(s.Conn.Environ.Storage(), versions...) stor, err := filestorage.NewFileStorageWriter(toolsDir) c.Assert(err, gc.IsNil) envtesting.MustUploadFakeToolsVersions(stor, versions...) } err = com.Run(coretesting.Context(c)) if test.expectErr != "" { c.Check(err, gc.ErrorMatches, test.expectErr) continue } else if !c.Check(err, gc.IsNil) { continue } // Check expected changes to environ/state. cfg, err := s.State.EnvironConfig() c.Check(err, gc.IsNil) agentVersion, ok := cfg.AgentVersion() c.Check(ok, gc.Equals, true) c.Check(agentVersion, gc.Equals, version.MustParse(test.expectVersion)) for _, uploaded := range test.expectUploaded { // Substitute latest LTS for placeholder in expected series for uploaded tools uploaded = strings.Replace(uploaded, "%LTS%", config.LatestLtsSeries(), 1) vers := version.MustParseBinary(uploaded) r, err := storage.Get(s.Conn.Environ.Storage(), envtools.StorageName(vers)) if !c.Check(err, gc.IsNil) { continue } data, err := ioutil.ReadAll(r) r.Close() c.Check(err, gc.IsNil) expectContent := version.Current expectContent.Number = agentVersion checkToolsContent(c, data, "jujud contents "+expectContent.String()) } } }