Beispiel #1
0
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), envcmd.Wrap(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)
	}
}
Beispiel #2
0
// resolveCharmStoreEntityURL resolves the given charm or bundle URL string
// by looking it up in the appropriate charm repository.
// If it is a charm store URL, the given csParams will
// be used to access the charm store repository.
// If it is a local charm or bundle URL, the local charm repository at
// the given repoPath will be used. The given configuration
// will be used to add any necessary attributes to the repo
// and to return the charm's supported series if possible.
//
// resolveCharmStoreEntityURL also returns the charm repository holding
// the charm or bundle.
func resolveCharmStoreEntityURL(args resolveCharmStoreEntityParams) (*charm.URL, []string, charmrepo.Interface, error) {
	url, err := charm.ParseURL(args.urlStr)
	if err != nil {
		return nil, nil, nil, errors.Trace(err)
	}
	repo, err := charmrepo.InferRepository(url, args.csParams, args.repoPath)
	if err != nil {
		return nil, nil, nil, errors.Trace(err)
	}
	repo = config.SpecializeCharmRepo(repo, args.conf)

	if url.Schema == "local" && url.Series == "" {
		if defaultSeries, ok := args.conf.DefaultSeries(); ok {
			url.Series = defaultSeries
		}
		if url.Series == "" {
			possibleURL := *url
			possibleURL.Series = config.LatestLtsSeries()
			logger.Errorf("The series is not specified in the model (default-series) or with the charm. Did you mean:\n\t%s", &possibleURL)
			return nil, nil, nil, errors.Errorf("cannot resolve series for charm: %q", url)
		}
	}
	resultUrl, supportedSeries, err := repo.Resolve(url)
	if err != nil {
		return nil, nil, nil, errors.Trace(err)
	}
	return resultUrl, supportedSeries, repo, nil
}
Beispiel #3
0
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)
		}
	}
	resetJujuHome(c)
	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), envcmd.Wrap(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 *ImageMetadataSuite) TestImageMetadataFilesLatestLts(c *gc.C) {
	ec2Config, err := config.New(config.UseDefaults, map[string]interface{}{
		"name":            "ec2-latest-lts",
		"type":            "ec2",
		"uuid":            testing.ModelTag.Id(),
		"controller-uuid": testing.ModelTag.Id(),
		"region":          "us-east-1",
	})
	c.Assert(err, jc.ErrorIsNil)
	s.store.BootstrapConfig["ec2-controller"] = jujuclient.BootstrapConfig{
		Cloud:       "ec2",
		CloudRegion: "us-east-1",
		Config:      ec2Config.AllAttrs(),
	}

	ctx, err := runImageMetadata(c, s.store,
		"-m", "ec2-controller:ec2-latest-lts",
		"-d", s.dir, "-i", "1234", "-r", "region", "-a", "arch", "-u", "endpoint",
	)
	c.Assert(err, jc.ErrorIsNil)
	out := testing.Stdout(ctx)
	expected := expectedMetadata{
		series: config.LatestLtsSeries(),
		arch:   "arch",
	}
	s.assertCommandOutput(c, expected, out, defaultIndexFileName, defaultImageFileName)
}
Beispiel #5
0
func (s *funcSuite) SetUpTest(c *gc.C) {
	s.baseImageMetadataSuite.SetUpTest(c)

	var err error
	s.env, err = environs.Prepare(
		envtesting.BootstrapContext(c),
		jujuclienttesting.NewMemStore(),
		environs.PrepareParams{
			ControllerName: "dummycontroller",
			BaseConfig:     mockConfig(),
			CloudName:      "dummy",
		},
	)
	c.Assert(err, jc.ErrorIsNil)
	s.state = s.constructState(s.env.Config())

	s.expected = cloudimagemetadata.Metadata{
		cloudimagemetadata.MetadataAttributes{
			Stream: "released",
			Source: "custom",
			Series: config.LatestLtsSeries(),
			Arch:   "amd64",
			Region: "dummy_region",
		},
		0,
		"",
	}
}
Beispiel #6
0
func (s *UpgradeJujuSuite) TestUpgradeJuju(c *gc.C) {
	for i, test := range upgradeJujuTests {
		c.Logf("\ntest %d: %s", i, test.about)
		s.Reset(c)
		tools.DefaultBaseURL = ""

		// Set up apparent CLI version and initialize the command.
		s.PatchValue(&version.Current, version.MustParseBinary(test.currentVersion))
		com := &UpgradeJujuCommand{}
		if err := coretesting.InitCommand(envcmd.Wrap(com), test.args); err != nil {
			if test.expectInitErr != "" {
				c.Check(err, gc.ErrorMatches, test.expectInitErr)
			} else {
				c.Check(err, jc.ErrorIsNil)
			}
			continue
		}

		// Set up state and environ, and run the command.
		toolsDir := c.MkDir()
		updateAttrs := map[string]interface{}{
			"agent-version":      test.agentVersion,
			"agent-metadata-url": "file://" + toolsDir + "/tools",
		}
		err := s.State.UpdateEnvironConfig(updateAttrs, nil, nil)
		c.Assert(err, jc.ErrorIsNil)
		versions := make([]version.Binary, len(test.tools))
		for i, v := range test.tools {
			versions[i] = version.MustParseBinary(v)
		}
		if len(versions) > 0 {
			stor, err := filestorage.NewFileStorageWriter(toolsDir)
			c.Assert(err, jc.ErrorIsNil)
			envtesting.MustUploadFakeToolsVersions(stor, s.Environ.Config().AgentStream(), versions...)
		}

		err = com.Run(coretesting.Context(c))
		if test.expectErr != "" {
			c.Check(err, gc.ErrorMatches, test.expectErr)
			continue
		} else if !c.Check(err, jc.ErrorIsNil) {
			continue
		}

		// Check expected changes to environ/state.
		cfg, err := s.State.EnvironConfig()
		c.Check(err, jc.ErrorIsNil)
		agentVersion, ok := cfg.AgentVersion()
		c.Check(ok, jc.IsTrue)
		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)
			s.checkToolsUploaded(c, vers, agentVersion)
		}
	}
}
Beispiel #7
0
func (s *RepoSuite) SetUpTest(c *gc.C) {
	s.JujuConnSuite.SetUpTest(c)
	s.CharmsPath = c.MkDir()
	// Change the environ's config to ensure we're using the one in state.
	updateAttrs := map[string]interface{}{"default-series": config.LatestLtsSeries()}
	err := s.State.UpdateModelConfig(updateAttrs, nil, nil)
	c.Assert(err, jc.ErrorIsNil)
}
Beispiel #8
0
// 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 environ, err := c.prepare(context); err == nil {
		logger.Infof("creating image metadata for model %q", environ.Config().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 errors.Errorf("model %q cannot provide region and endpoint", environ.Config().Name())
			}
			// If only one of region or endpoint is provided, that is a problem.
			if cloudSpec.Region != cloudSpec.Endpoint && (cloudSpec.Region == "" || cloudSpec.Endpoint == "") {
				return errors.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)
		}
	} else {
		logger.Warningf("model could not be opened: %v", err)
	}
	if environ == nil {
		logger.Infof("no model found, creating image metadata using user supplied data")
	}
	if c.Series == "" {
		c.Series = config.LatestLtsSeries()
	}
	if c.ImageId == "" {
		return errors.Errorf("image id must be specified")
	}
	if c.Region == "" {
		return errors.Errorf("image region must be specified")
	}
	if c.Endpoint == "" {
		return errors.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
}
Beispiel #9
0
func (s *NewAPIClientSuite) TestWithConfigAndNoInfo(c *gc.C) {
	coretesting.MakeSampleJujuHome(c)

	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 := mockedAPIState(0)
	apiOpen := func(apiInfo *api.Info, opts api.DialOpts) (juju.APIState, error) {
		c.Check(apiInfo.Tag, gc.Equals, names.NewUserTag("admin"))
		c.Check(string(apiInfo.CACert), gc.Not(gc.Equals), "")
		c.Check(apiInfo.Password, gc.Equals, "adminpass")
		// EnvironTag wasn't in regular Config
		c.Check(apiInfo.EnvironTag, gc.IsNil)
		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, `localhost:\d+`)
	c.Check(ep.CACert, gc.Not(gc.Equals), "")
	// Old servers won't hand back EnvironTag, so it should stay empty in
	// the cache
	c.Check(ep.EnvironUUID, gc.Equals, "")
	creds := info.APICredentials()
	c.Check(creds.User, gc.Equals, "admin")
	c.Check(creds.Password, gc.Equals, "adminpass")
}
Beispiel #10
0
func (s *RepoSuite) SetUpTest(c *gc.C) {
	s.JujuConnSuite.SetUpTest(c)
	s.BaseRepoSuite.SetUpTest(c)
	// Change the environ's config to ensure we're using the one in state,
	// not the one in the local environments.yaml
	updateAttrs := map[string]interface{}{"default-series": config.LatestLtsSeries()}
	err := s.State.UpdateModelConfig(updateAttrs, nil, nil)
	c.Assert(err, jc.ErrorIsNil)
}
Beispiel #11
0
// charmSeries determine what series to use with a charm.
// Order of preference is:
// - user requested or defined by bundle when deploying
// - default from charm metadata supported series
// - model default
// - charm store default
func charmSeries(
	requestedSeries, seriesFromCharm string,
	supportedSeries []string,
	force bool,
	conf *config.Config,
	fromBundle bool,
) (string, string, error) {
	// User has requested a series and we have a new charm with series in metadata.
	if requestedSeries != "" && seriesFromCharm == "" {
		if !force && !isSeriesSupported(requestedSeries, supportedSeries) {
			return "", "", charm.NewUnsupportedSeriesError(requestedSeries, supportedSeries)
		}
		if fromBundle {
			return requestedSeries, msgBundleSeries, nil
		} else {
			return requestedSeries, msgUserRequestedSeries, nil
		}
	}

	// User has requested a series and it's an old charm for a single series.
	if seriesFromCharm != "" {
		if !force && requestedSeries != "" && requestedSeries != seriesFromCharm {
			return "", "", charm.NewUnsupportedSeriesError(requestedSeries, []string{seriesFromCharm})
		}
		if requestedSeries != "" {
			if fromBundle {
				return requestedSeries, msgBundleSeries, nil
			} else {
				return requestedSeries, msgUserRequestedSeries, nil
			}
		}
		return seriesFromCharm, msgSingleCharmSeries, nil
	}

	// Use charm default.
	if len(supportedSeries) > 0 {
		return supportedSeries[0], msgDefaultCharmSeries, nil
	}

	// Use model default supported series.
	if defaultSeries, ok := conf.DefaultSeries(); ok {
		if !force && !isSeriesSupported(defaultSeries, supportedSeries) {
			return "", "", charm.NewUnsupportedSeriesError(defaultSeries, supportedSeries)
		}
		return defaultSeries, msgDefaultModelSeries, nil
	}

	// Use latest LTS.
	latestLtsSeries := config.LatestLtsSeries()
	if !force && !isSeriesSupported(latestLtsSeries, supportedSeries) {
		return "", "", charm.NewUnsupportedSeriesError(latestLtsSeries, supportedSeries)
	}
	return latestLtsSeries, msgLatestLTSSeries, nil
}
Beispiel #12
0
func (s *RepoSuite) SetUpTest(c *gc.C) {
	s.JujuConnSuite.SetUpTest(c)
	// Change the environ's config to ensure we're using the one in state,
	// not the one in the local environments.yaml
	updateAttrs := map[string]interface{}{"default-series": config.LatestLtsSeries()}
	err := s.State.UpdateEnvironConfig(updateAttrs, nil, nil)
	c.Assert(err, jc.ErrorIsNil)
	s.RepoPath = os.Getenv("JUJU_REPOSITORY")
	repoPath := c.MkDir()
	os.Setenv("JUJU_REPOSITORY", repoPath)
	s.SeriesPath = filepath.Join(repoPath, config.LatestLtsSeries())
	err = os.Mkdir(s.SeriesPath, 0777)
	c.Assert(err, jc.ErrorIsNil)
	// Create a symlink "quantal" -> "precise", because most charms
	// and machines are written with hard-coded "quantal" series,
	// hence they interact badly with a local repository that assumes
	// only "precise" charms are available.
	err = symlink.New(s.SeriesPath, filepath.Join(repoPath, "quantal"))
	c.Assert(err, jc.ErrorIsNil)
}
Beispiel #13
0
func (s *AddMachineSuite) TestAddMachine(c *gc.C) {
	context, err := runAddMachine(c)
	c.Assert(err, gc.IsNil)
	c.Assert(testing.Stderr(context), gc.Equals, "created machine 0\n")
	m, err := s.State.Machine("0")
	c.Assert(err, gc.IsNil)
	c.Assert(m.Life(), gc.Equals, state.Alive)
	c.Assert(m.Series(), gc.DeepEquals, config.LatestLtsSeries())
	mcons, err := m.Constraints()
	c.Assert(err, gc.IsNil)
	c.Assert(&mcons, jc.Satisfies, constraints.IsEmpty)
}
Beispiel #14
0
func (s *BootstrapSuite) TestAutoUploadAfterFailedSync(c *gc.C) {
	s.PatchValue(&version.Current.Series, config.LatestLtsSeries())
	s.setupAutoUploadTest(c, "1.7.3", "quantal")
	// Run command and check for that upload has been run for tools matching
	// the current juju version.
	opc, errc := cmdtesting.RunCommand(cmdtesting.NullContext(c), envcmd.Wrap(new(BootstrapCommand)), "-e", "devenv")
	c.Assert(<-errc, gc.IsNil)
	c.Check((<-opc).(dummy.OpBootstrap).Env, gc.Equals, "devenv")
	icfg := (<-opc).(dummy.OpFinalizeBootstrap).InstanceConfig
	c.Assert(icfg, gc.NotNil)
	c.Assert(icfg.Tools.Version.String(), gc.Equals, "1.7.3.1-raring-"+arch.HostArch())
}
Beispiel #15
0
func (s *BootstrapSuite) TestAutoUploadAfterFailedSync(c *gc.C) {
	s.PatchValue(&version.Current.Series, config.LatestLtsSeries())
	s.setupAutoUploadTest(c, "1.7.3", "quantal")
	// Run command and check for that upload has been run for tools matching
	// the current juju version.
	opc, errc := runCommand(nullContext(c), envcmd.Wrap(new(BootstrapCommand)))
	c.Assert(<-errc, gc.IsNil)
	c.Check((<-opc).(dummy.OpPutFile).Env, gc.Equals, "peckham") // verify storage
	c.Check((<-opc).(dummy.OpBootstrap).Env, gc.Equals, "peckham")
	mcfg := (<-opc).(dummy.OpFinalizeBootstrap).MachineConfig
	c.Assert(mcfg, gc.NotNil)
	c.Assert(mcfg.Tools.Version.String(), gc.Equals, "1.7.3.1-raring-"+version.Current.Arch)
}
Beispiel #16
0
func (s *NewAPIClientSuite) TestWithConfigAndNoInfo(c *gc.C) {
	c.Skip("not really possible now that there is no defined admin user")
	s.PatchValue(&version.Current, coretesting.FakeVersionNumber)
	coretesting.MakeSampleJujuHome(c)

	store := newConfigStore(coretesting.SampleModelName, &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",
		},
	})
	s.bootstrapEnv(c, coretesting.SampleModelName, store)

	info, err := store.ReadInfo("myenv")
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(info, gc.NotNil)
	c.Logf("%#v", info.APICredentials())

	called := 0
	expectState := mockedAPIState(0)
	apiOpen := func(apiInfo *api.Info, opts api.DialOpts) (api.Connection, error) {
		c.Check(apiInfo.Tag, gc.Equals, dummy.AdminUserTag())
		c.Check(string(apiInfo.CACert), gc.Not(gc.Equals), "")
		c.Check(apiInfo.Password, gc.Equals, "adminpass")
		// ModelTag wasn't in regular Config
		c.Check(apiInfo.ModelTag.Id(), gc.Equals, "")
		c.Check(opts, gc.DeepEquals, api.DefaultDialOpts())
		called++
		return expectState, nil
	}
	st, err := juju.NewAPIFromStore("myenv", store, apiOpen)
	c.Assert(err, jc.ErrorIsNil)
	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, jc.ErrorIsNil)
	c.Assert(info, gc.NotNil)
	ep := info.APIEndpoint()
	c.Assert(ep.Addresses, gc.HasLen, 1)
	c.Check(ep.Addresses[0], gc.Matches, `localhost:\d+`)
	c.Check(ep.CACert, gc.Not(gc.Equals), "")
}
Beispiel #17
0
func (s *ImageMetadataSuite) TestImageMetadataFilesLatestLts(c *gc.C) {
	envConfig := strings.Replace(metadataTestEnvConfig, "default-series: precise", "", -1)
	testing.WriteEnvironments(c, envConfig)
	ctx := testing.Context(c)
	code := cmd.Main(
		envcmd.Wrap(&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)
}
Beispiel #18
0
func (s *BaseRepoSuite) SetUpTest(c *gc.C) {
	// Set up a local repository.
	s.RepoPath = os.Getenv("JUJU_REPOSITORY")
	repoPath := c.MkDir()
	os.Setenv("JUJU_REPOSITORY", repoPath)
	s.SeriesPath = filepath.Join(repoPath, config.LatestLtsSeries())
	c.Assert(os.Mkdir(s.SeriesPath, 0777), jc.ErrorIsNil)
	// Create a symlink "quantal" -> "precise", because most charms
	// and machines are written with hard-coded "quantal" series,
	// hence they interact badly with a local repository that assumes
	// only "precise" charms are available.
	err := symlink.New(s.SeriesPath, filepath.Join(repoPath, "quantal"))
	c.Assert(err, jc.ErrorIsNil)
	s.BundlesPath = filepath.Join(repoPath, "bundle")
	c.Assert(os.Mkdir(s.BundlesPath, 0777), jc.ErrorIsNil)
}
Beispiel #19
0
func (s *BootstrapSuite) TestAutoUploadAfterFailedSync(c *gc.C) {
	s.PatchValue(&series.HostSeries, func() string { return config.LatestLtsSeries() })
	s.setupAutoUploadTest(c, "1.7.3", "quantal")
	// Run command and check for that upload has been run for tools matching
	// the current juju version.
	opc, errc := cmdtesting.RunCommand(
		cmdtesting.NullContext(c), s.newBootstrapCommand(),
		"devcontroller", "dummy-cloud/region-1",
		"--config", "default-series=raring",
		"--auto-upgrade",
	)
	c.Assert(<-errc, gc.IsNil)
	c.Check((<-opc).(dummy.OpBootstrap).Env, gc.Equals, "admin")
	icfg := (<-opc).(dummy.OpFinalizeBootstrap).InstanceConfig
	c.Assert(icfg, gc.NotNil)
	c.Assert(icfg.Tools.Version.String(), gc.Equals, "1.7.3.1-raring-"+arch.HostArch())
}
Beispiel #20
0
func (s *SetEnvironmentSuite) TestChangeDefaultSeries(c *gc.C) {
	// default-series not set
	stateConfig, err := s.State.EnvironConfig()
	c.Assert(err, gc.IsNil)
	series, ok := stateConfig.DefaultSeries()
	c.Assert(ok, gc.Equals, true)
	c.Assert(series, gc.Equals, config.LatestLtsSeries()) // default-series set in RepoSuite.SetUpTest

	_, err = testing.RunCommand(c, envcmd.Wrap(&SetEnvironmentCommand{}), "default-series=raring")
	c.Assert(err, gc.IsNil)

	stateConfig, err = s.State.EnvironConfig()
	c.Assert(err, gc.IsNil)
	series, ok = stateConfig.DefaultSeries()
	c.Assert(ok, gc.Equals, true)
	c.Assert(series, gc.Equals, "raring")
	c.Assert(config.PreferredSeries(stateConfig), gc.Equals, "raring")
}
Beispiel #21
0
// resolve resolves the given given charm or bundle URL
// string by looking it up in the appropriate charm repository. If it is
// a charm store URL, the given csParams will be used to access the
// charm store repository. If it is a local charm or bundle URL, the
// local charm repository at the given repoPath will be used. The given
// configuration will be used to add any necessary attributes to the
// repo and to return the charm's supported series if possible.
//
// It returns the fully resolved URL, any series supported by the entity,
// and the repository that holds it.
func (r *charmURLResolver) resolve(urlStr string) (*charm.URL, csparams.Channel, []string, charmrepo.Interface, error) {
	var noChannel csparams.Channel
	url, err := charm.ParseURL(urlStr)
	if err != nil {
		return nil, noChannel, nil, nil, errors.Trace(err)
	}
	switch url.Schema {
	case "cs":
		repo := config.SpecializeCharmRepo(r.csRepo, r.conf).(*charmrepo.CharmStore)

		resultUrl, channel, supportedSeries, err := repo.ResolveWithChannel(url)
		if err != nil {
			return nil, noChannel, nil, nil, errors.Trace(err)
		}
		return resultUrl, channel, supportedSeries, repo, nil
	case "local":
		if url.Series == "" {
			if defaultSeries, ok := r.conf.DefaultSeries(); ok {
				url.Series = defaultSeries
			}
		}
		if url.Series == "" {
			possibleURL := *url
			possibleURL.Series = config.LatestLtsSeries()
			logger.Errorf("The series is not specified in the model (default-series) or with the charm. Did you mean:\n\t%s", &possibleURL)
			return nil, noChannel, nil, nil, errors.Errorf("cannot resolve series for charm: %q", url)
		}
		repo, err := charmrepo.NewLocalRepository(r.repoPath)
		if err != nil {
			return nil, noChannel, nil, nil, errors.Mask(err)
		}
		repo = config.SpecializeCharmRepo(repo, r.conf)

		resultUrl, supportedSeries, err := repo.Resolve(url)
		if err != nil {
			return nil, noChannel, nil, nil, errors.Trace(err)
		}
		return resultUrl, noChannel, supportedSeries, repo, nil
	default:
		return nil, noChannel, nil, nil, errors.Errorf("unknown schema for charm reference %q", urlStr)
	}
}
Beispiel #22
0
// SampleConfig() returns an environment configuration with all required
// attributes set.
func SampleConfig() testing.Attrs {
	return testing.Attrs{
		"type":                      "dummy",
		"name":                      "only",
		"uuid":                      testing.ModelTag.Id(),
		"authorized-keys":           testing.FakeAuthKeys,
		"firewall-mode":             config.FwInstance,
		"admin-secret":              testing.DefaultMongoPassword,
		"ca-cert":                   testing.CACert,
		"ca-private-key":            testing.CAKey,
		"ssl-hostname-verification": true,
		"development":               false,
		"state-port":                1234,
		"api-port":                  4321,
		"default-series":            config.LatestLtsSeries(),

		"secret":       "pork",
		"state-server": true,
		"prefer-ipv6":  true,
	}
}
Beispiel #23
0
func (s *funcSuite) SetUpTest(c *gc.C) {
	s.baseImageMetadataSuite.SetUpTest(c)

	cfg, err := config.New(config.NoDefaults, mockConfig())
	c.Assert(err, jc.ErrorIsNil)
	s.env, err = environs.Prepare(cfg, envtesting.BootstrapContext(c), configstore.NewMem())
	c.Assert(err, jc.ErrorIsNil)
	s.state = s.constructState(cfg)

	s.expected = cloudimagemetadata.Metadata{
		cloudimagemetadata.MetadataAttributes{
			Stream: "released",
			Source: "custom",
			Series: config.LatestLtsSeries(),
			Arch:   "amd64",
			Region: "dummy_region",
		},
		0,
		"",
	}
}
Beispiel #24
0
func (s *UpgradeJujuSuite) TestUpgradeJuju(c *gc.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(envcmd.Wrap(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())
		}
	}
}
Beispiel #25
0
func (s *BootstrapSuite) run(c *gc.C, test bootstrapTest) (restore gitjujutesting.Restorer) {
	// Create home with dummy provider and remove all
	// of its envtools.
	env := resetJujuHome(c, "peckham")

	// Although we're testing PrepareEndpointsForCaching interactions
	// separately in the juju package, here we just ensure it gets
	// called with the right arguments.
	prepareCalled := false
	addrConnectedTo := "localhost:17070"
	restore = gitjujutesting.PatchValue(
		&prepareEndpointsForCaching,
		func(info configstore.EnvironInfo, hps [][]network.HostPort, addr network.HostPort) (_, _ []string, _ bool) {
			prepareCalled = true
			addrs, hosts, changed := juju.PrepareEndpointsForCaching(info, hps, addr)
			// Because we're bootstrapping the addresses will always
			// change, as there's no .jenv file saved yet.
			c.Assert(changed, jc.IsTrue)
			return addrs, hosts, changed
		},
	)

	if test.version != "" {
		useVersion := strings.Replace(test.version, "%LTS%", config.LatestLtsSeries(), 1)
		origVersion := version.Current
		version.Current = version.MustParseBinary(useVersion)
		restore = restore.Add(func() {
			version.Current = origVersion
		})
	}

	if test.hostArch != "" {
		origArch := arch.HostArch
		arch.HostArch = func() string {
			return test.hostArch
		}
		restore = restore.Add(func() {
			arch.HostArch = origArch
		})
	}

	// Run command and check for uploads.
	opc, errc := cmdtesting.RunCommand(cmdtesting.NullContext(c), envcmd.Wrap(new(BootstrapCommand)), test.args...)
	// Check for remaining operations/errors.
	if test.err != "" {
		err := <-errc
		c.Assert(err, gc.NotNil)
		stripped := strings.Replace(err.Error(), "\n", "", -1)
		c.Check(stripped, gc.Matches, test.err)
		return restore
	}
	if !c.Check(<-errc, gc.IsNil) {
		return restore
	}

	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)

	opFinalizeBootstrap := (<-opc).(dummy.OpFinalizeBootstrap)
	c.Check(opFinalizeBootstrap.Env, gc.Equals, "peckham")
	c.Check(opFinalizeBootstrap.InstanceConfig.Tools, gc.NotNil)
	if test.upload != "" {
		c.Check(opFinalizeBootstrap.InstanceConfig.Tools.Version.String(), gc.Equals, test.upload)
	}

	store, err := configstore.Default()
	c.Assert(err, jc.ErrorIsNil)
	// Check a CA cert/key was generated by reloading the environment.
	env, err = environs.NewFromName("peckham", store)
	c.Assert(err, jc.ErrorIsNil)
	_, hasCert := env.Config().CACert()
	c.Check(hasCert, jc.IsTrue)
	_, hasKey := env.Config().CAPrivateKey()
	c.Check(hasKey, jc.IsTrue)
	info, err := store.ReadInfo("peckham")
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(info, gc.NotNil)
	c.Assert(prepareCalled, jc.IsTrue)
	c.Assert(info.APIEndpoint().Addresses, gc.DeepEquals, []string{addrConnectedTo})
	return restore
}
Beispiel #26
0
func (test bootstrapTest) run(c *gc.C) {
	// Create home with dummy provider and remove all
	// of its envtools.
	env := resetJujuHome(c)

	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 }()
	}

	if test.upload == "" {
		usefulVersion := version.Current
		usefulVersion.Series = config.PreferredSeries(env.Config())
		envtesting.AssertUploadFakeToolsVersions(c, env.Storage(), usefulVersion)
	}

	// Run command and check for uploads.
	opc, errc := cmdtesting.RunCommand(cmdtesting.NullContext(c), envcmd.Wrap(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
	}

	opPutBootstrapVerifyFile := (<-opc).(dummy.OpPutFile)
	c.Check(opPutBootstrapVerifyFile.Env, gc.Equals, "peckham")
	c.Check(opPutBootstrapVerifyFile.FileName, gc.Equals, environs.VerificationFilename)

	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)
	c.Check(opBootstrap.Args.KeepBroken, gc.Equals, test.keepBroken)

	opFinalizeBootstrap := (<-opc).(dummy.OpFinalizeBootstrap)
	c.Check(opFinalizeBootstrap.Env, gc.Equals, "peckham")
	c.Check(opFinalizeBootstrap.MachineConfig.Tools, gc.NotNil)
	if test.upload != "" {
		c.Check(opFinalizeBootstrap.MachineConfig.Tools.Version.String(), gc.Equals, test.upload)
	}

	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)
	info, err := store.ReadInfo("peckham")
	c.Assert(err, gc.IsNil)
	c.Assert(info, gc.NotNil)
	c.Assert(info.APIEndpoint().Addresses, gc.DeepEquals, []string{"localhost:17070"})
}
Beispiel #27
0
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 state")
	st := t.Env.(testing.GetStater).GetStateInAPIServer()

	c.Logf("opening API connection")
	apiState, err := juju.NewAPIState(t.Env, api.DefaultDialOpts())
	c.Assert(err, gc.IsNil)
	defer apiState.Close()

	// Check that the agent version has made it through the
	// bootstrap process (it's optional in the config.Config)
	cfg, err := st.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 := st.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 := st.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 := apiState.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 := charmtesting.Charms.ClonedURL(repoDir, mtools0.Version.Series, "dummy")
	sch, err := testing.PutCharm(st, url, &charm.LocalRepository{Path: repoDir}, false)
	c.Assert(err, gc.IsNil)
	svc, err := st.AddService("dummy", "user-admin", sch, nil)
	c.Assert(err, gc.IsNil)
	units, err := juju.AddUnits(st, 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 := st.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, st, 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, t.Env, instId1)
}
Beispiel #28
0
func (s *BootstrapSuite) run(c *gc.C, test bootstrapTest) testing.Restorer {
	// Create home with dummy provider and remove all
	// of its envtools.
	resetJujuXDGDataHome(c)
	dummy.Reset(c)

	var restore testing.Restorer = func() {
		s.store = jujuclienttesting.NewMemStore()
	}
	if test.version != "" {
		useVersion := strings.Replace(test.version, "%LTS%", config.LatestLtsSeries(), 1)
		v := version.MustParseBinary(useVersion)
		restore = restore.Add(testing.PatchValue(&jujuversion.Current, v.Number))
		restore = restore.Add(testing.PatchValue(&arch.HostArch, func() string { return v.Arch }))
		restore = restore.Add(testing.PatchValue(&series.HostSeries, func() string { return v.Series }))
	}

	if test.hostArch != "" {
		restore = restore.Add(testing.PatchValue(&arch.HostArch, func() string { return test.hostArch }))
	}

	controllerName := "peckham-controller"
	cloudName := "dummy"

	// Run command and check for uploads.
	args := append([]string{
		controllerName, cloudName,
		"--config", "default-series=raring",
	}, test.args...)
	opc, errc := cmdtesting.RunCommand(cmdtesting.NullContext(c), s.newBootstrapCommand(), args...)
	// Check for remaining operations/errors.
	if test.err != "" {
		err := <-errc
		c.Assert(err, gc.NotNil)
		stripped := strings.Replace(err.Error(), "\n", "", -1)
		c.Check(stripped, gc.Matches, test.err)
		return restore
	}
	if !c.Check(<-errc, gc.IsNil) {
		return restore
	}

	opBootstrap := (<-opc).(dummy.OpBootstrap)
	c.Check(opBootstrap.Env, gc.Equals, "admin")
	c.Check(opBootstrap.Args.ModelConstraints, gc.DeepEquals, test.constraints)
	if test.bootstrapConstraints == (constraints.Value{}) {
		test.bootstrapConstraints = test.constraints
	}
	c.Check(opBootstrap.Args.BootstrapConstraints, gc.DeepEquals, test.bootstrapConstraints)
	c.Check(opBootstrap.Args.Placement, gc.Equals, test.placement)

	opFinalizeBootstrap := (<-opc).(dummy.OpFinalizeBootstrap)
	c.Check(opFinalizeBootstrap.Env, gc.Equals, "admin")
	c.Check(opFinalizeBootstrap.InstanceConfig.Tools, gc.NotNil)
	if test.upload != "" {
		c.Check(opFinalizeBootstrap.InstanceConfig.Tools.Version.String(), gc.Equals, test.upload)
	}

	expectedBootstrappedControllerName := bootstrappedControllerName(controllerName)

	// Check controllers.yaml controller details.
	addrConnectedTo := []string{"localhost:17070"}

	controller, err := s.store.ControllerByName(expectedBootstrappedControllerName)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(controller.CACert, gc.Not(gc.Equals), "")
	c.Assert(controller.UnresolvedAPIEndpoints, gc.DeepEquals, addrConnectedTo)
	c.Assert(controller.APIEndpoints, gc.DeepEquals, addrConnectedTo)
	c.Assert(utils.IsValidUUIDString(controller.ControllerUUID), jc.IsTrue)

	// Controller model should be called "admin".
	controllerModel, err := s.store.ModelByName(expectedBootstrappedControllerName, "admin@local", "admin")
	c.Assert(controllerModel.ModelUUID, gc.Equals, controller.ControllerUUID)
	c.Assert(err, jc.ErrorIsNil)

	// Bootstrap config should have been saved, and should only contain
	// the type, name, and any user-supplied configuration.
	bootstrapConfig, err := s.store.BootstrapConfigForController(expectedBootstrappedControllerName)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(bootstrapConfig.Cloud, gc.Equals, "dummy")
	c.Assert(bootstrapConfig.Credential, gc.Equals, "")
	c.Assert(bootstrapConfig.Config, jc.DeepEquals, map[string]interface{}{
		"name":           "admin",
		"type":           "dummy",
		"default-series": "raring",
	})

	return restore
}
Beispiel #29
0
	}
	return values
}

// machineInfo is the structure used to pass information between the provider
// and the agent running on a node.
// When a node is started, the provider code creates a machineInfo object
// containing information about the node being started and configures
// cloudinit to get a YAML representation of that object written on the node's
// filesystem during its first startup.  That file is then read by the juju
// agent running on the node and converted back into a machineInfo object.
type machineInfo struct {
	Hostname string `yaml:,omitempty`
}

var maasDataDir = paths.MustSucceed(paths.DataDir(config.LatestLtsSeries()))
var _MAASInstanceFilename = path.Join(maasDataDir, "MAASmachine.txt")

// cloudinitRunCmd returns the shell command that, when run, will create the
// "machine info" file containing the hostname of a machine.
// That command is destined to be used by cloudinit.
func (info *machineInfo) cloudinitRunCmd(series string) (string, error) {
	dataDir, err := paths.DataDir(series)
	if err != nil {
		return "", err
	}
	renderer, err := cloudinit.NewRenderer(series)
	if err != nil {
		return "", err
	}
Beispiel #30
0
func (s *DeploySuite) TestCharmSeries(c *gc.C) {
	deploySeriesTests := []struct {
		requestedSeries string
		force           bool
		seriesFromCharm string
		supportedSeries []string
		modelSeries     string
		ltsSeries       string
		expectedSeries  string
		message         string
		err             string
	}{{
		ltsSeries:       "precise",
		modelSeries:     "wily",
		supportedSeries: []string{"trusty", "precise"},
		expectedSeries:  "trusty",
		message:         "with the default charm metadata series %q",
	}, {
		requestedSeries: "trusty",
		seriesFromCharm: "trusty",
		expectedSeries:  "trusty",
		message:         "with the user specified series %q",
	}, {
		requestedSeries: "wily",
		seriesFromCharm: "trusty",
		err:             `series "wily" not supported by charm, supported series are: trusty`,
	}, {
		requestedSeries: "wily",
		supportedSeries: []string{"trusty", "precise"},
		err:             `series "wily" not supported by charm, supported series are: trusty,precise`,
	}, {
		ltsSeries: config.LatestLtsSeries(),
		err:       `series .* not supported by charm, supported series are: .*`,
	}, {
		modelSeries: "xenial",
		err:         `series "xenial" not supported by charm, supported series are: .*`,
	}, {
		requestedSeries: "wily",
		seriesFromCharm: "trusty",
		expectedSeries:  "wily",
		message:         "with the user specified series %q",
		force:           true,
	}, {
		requestedSeries: "wily",
		supportedSeries: []string{"trusty", "precise"},
		expectedSeries:  "wily",
		message:         "with the user specified series %q",
		force:           true,
	}, {
		ltsSeries:      config.LatestLtsSeries(),
		force:          true,
		expectedSeries: config.LatestLtsSeries(),
		message:        "with the latest LTS series %q",
	}, {
		ltsSeries:      "precise",
		modelSeries:    "xenial",
		force:          true,
		expectedSeries: "xenial",
		message:        "with the configured model default series %q",
	}}

	for i, test := range deploySeriesTests {
		c.Logf("test %d", i)
		cfg, err := config.New(config.UseDefaults, map[string]interface{}{
			"name":            "test",
			"type":            "dummy",
			"uuid":            coretesting.ModelTag.Id(),
			"ca-cert":         coretesting.CACert,
			"ca-private-key":  coretesting.CAKey,
			"authorized-keys": coretesting.FakeAuthKeys,
			"default-series":  test.modelSeries,
		})
		c.Assert(err, jc.ErrorIsNil)
		series, msg, err := charmSeries(test.requestedSeries, test.seriesFromCharm, test.supportedSeries, test.force, cfg)
		if test.err != "" {
			c.Check(err, gc.ErrorMatches, test.err)
			continue
		}
		c.Assert(err, jc.ErrorIsNil)
		c.Check(series, gc.Equals, test.expectedSeries)
		c.Check(msg, gc.Matches, test.message)
	}
}