Esempio n. 1
0
File: config.go Progetto: bac/juju
func validateConfig(cfg, old *config.Config) (*environConfig, error) {
	// Check for valid changes for the base config values.
	if err := config.Validate(cfg, old); err != nil {
		return nil, err
	}
	validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults)
	if err != nil {
		return nil, err
	}
	ecfg := &environConfig{cfg, validated}

	if vpcID := ecfg.vpcID(); isVPCIDSetButInvalid(vpcID) {
		return nil, fmt.Errorf("vpc-id: %q is not a valid AWS VPC ID", vpcID)
	} else if !isVPCIDSet(vpcID) && ecfg.forceVPCID() {
		return nil, fmt.Errorf("cannot use vpc-id-force without specifying vpc-id as well")
	}

	if old != nil {
		attrs := old.UnknownAttrs()

		if vpcID, _ := attrs["vpc-id"].(string); vpcID != ecfg.vpcID() {
			return nil, fmt.Errorf("cannot change vpc-id from %q to %q", vpcID, ecfg.vpcID())
		}

		if forceVPCID, _ := attrs["vpc-id-force"].(bool); forceVPCID != ecfg.forceVPCID() {
			return nil, fmt.Errorf("cannot change vpc-id-force from %v to %v", forceVPCID, ecfg.forceVPCID())
		}
	}

	// ssl-hostname-verification cannot be disabled
	if !ecfg.SSLHostnameVerification() {
		return nil, fmt.Errorf("disabling ssh-hostname-verification is not supported")
	}
	return ecfg, nil
}
Esempio n. 2
0
// PrepareForBootstrap is specified in the EnvironProvider interface.
func (prov *azureEnvironProvider) PrepareForBootstrap(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) {
	// Ensure that internal configuration is not specified, and then set
	// what we can now. We only need to do this during bootstrap. Validate
	// will check for changes later.
	unknownAttrs := cfg.UnknownAttrs()
	for _, key := range internalConfigAttributes {
		if _, ok := unknownAttrs[key]; ok {
			return nil, errors.Errorf(`internal config %q must not be specified`, key)
		}
	}

	// Record the UUID that will be used for the controller environment.
	cfg, err := cfg.Apply(map[string]interface{}{
		configAttrControllerResourceGroup: resourceGroupName(cfg),
	})
	if err != nil {
		return nil, errors.Annotate(err, "recording controller-resource-group")
	}

	env, err := prov.Open(cfg)
	if err != nil {
		return nil, errors.Trace(err)
	}
	if ctx.ShouldVerifyCredentials() {
		if err := verifyCredentials(env.(*azureEnviron)); err != nil {
			return nil, errors.Trace(err)
		}
	}
	return env, nil
}
Esempio n. 3
0
File: config.go Progetto: bac/juju
// update applies changes from the provided config to the env config.
// Changes to any immutable attributes result in an error.
func (c *environConfig) update(cfg *config.Config) error {
	// Validate the updates. newValidConfig does not modify the "known"
	// config attributes so it is safe to call Validate here first.
	if err := config.Validate(cfg, c.Config); err != nil {
		return errors.Trace(err)
	}

	updates, err := newValidConfig(cfg, configDefaults)
	if err != nil {
		return errors.Trace(err)
	}

	// Check that no immutable fields have changed.
	attrs := updates.UnknownAttrs()
	for _, field := range configImmutableFields {
		if attrs[field] != c.attrs[field] {
			return errors.Errorf("%s: cannot change from %v to %v", field, c.attrs[field], attrs[field])
		}
	}

	// Apply the updates.
	c.Config = cfg
	c.attrs = cfg.UnknownAttrs()
	return nil
}
Esempio n. 4
0
func (p manualProvider) PrepareForBootstrap(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) {
	if _, ok := cfg.UnknownAttrs()["storage-auth-key"]; !ok {
		uuid, err := utils.NewUUID()
		if err != nil {
			return nil, err
		}
		cfg, err = cfg.Apply(map[string]interface{}{
			"storage-auth-key": uuid.String(),
		})
		if err != nil {
			return nil, err
		}
	}
	if use, ok := cfg.UnknownAttrs()["use-sshstorage"].(bool); ok && !use {
		return nil, fmt.Errorf("use-sshstorage must not be specified")
	}
	envConfig, err := p.validate(cfg, nil)
	if err != nil {
		return nil, err
	}
	cfg, err = cfg.Apply(envConfig.attrs)
	if err != nil {
		return nil, err
	}
	envConfig = newEnvironConfig(cfg, envConfig.attrs)
	if err := ensureBootstrapUbuntuUser(ctx, envConfig); err != nil {
		return nil, err
	}
	return p.open(envConfig)
}
Esempio n. 5
0
// SetConfig is specified in the Environ interface.
func (env *azureEnviron) SetConfig(cfg *config.Config) error {
	env.mu.Lock()
	defer env.mu.Unlock()

	var old *config.Config
	if env.config != nil {
		old = env.config.Config
	}
	ecfg, err := validateConfig(cfg, old)
	if err != nil {
		return err
	}
	env.config = ecfg

	// Initialise clients.
	env.compute = compute.NewWithBaseURI(ecfg.endpoint, env.config.subscriptionId)
	env.resources = resources.NewWithBaseURI(ecfg.endpoint, env.config.subscriptionId)
	env.storage = storage.NewWithBaseURI(ecfg.endpoint, env.config.subscriptionId)
	env.network = network.NewWithBaseURI(ecfg.endpoint, env.config.subscriptionId)
	clients := map[string]*autorest.Client{
		"azure.compute":   &env.compute.Client,
		"azure.resources": &env.resources.Client,
		"azure.storage":   &env.storage.Client,
		"azure.network":   &env.network.Client,
	}
	if env.provider.config.Sender != nil {
		env.config.token.SetSender(env.provider.config.Sender)
	}
	for id, client := range clients {
		client.Authorizer = env.config.token
		logger := loggo.GetLogger(id)
		if env.provider.config.Sender != nil {
			client.Sender = env.provider.config.Sender
		}
		client.ResponseInspector = tracingRespondDecorator(logger)
		client.RequestInspector = tracingPrepareDecorator(logger)
		if env.provider.config.RequestInspector != nil {
			tracer := client.RequestInspector
			inspector := env.provider.config.RequestInspector
			client.RequestInspector = func(p autorest.Preparer) autorest.Preparer {
				p = tracer(p)
				p = inspector(p)
				return p
			}
		}
	}

	// Invalidate instance types when the location changes.
	if old != nil {
		oldLocation := old.UnknownAttrs()["location"].(string)
		if env.config.location != oldLocation {
			env.instanceTypes = nil
		}
	}

	return nil
}
Esempio n. 6
0
// PrepareForCreateEnvironment is specified in the EnvironProvider interface.
func (p maasEnvironProvider) PrepareForCreateEnvironment(cfg *config.Config) (*config.Config, error) {
	attrs := cfg.UnknownAttrs()
	oldName, found := attrs["maas-agent-name"]
	if found && oldName != "" {
		return nil, errAgentNameAlreadySet
	}
	attrs["maas-agent-name"] = cfg.UUID()
	return cfg.Apply(attrs)
}
Esempio n. 7
0
func (e *manualEnviron) SetConfig(cfg *config.Config) error {
	e.mu.Lock()
	defer e.mu.Unlock()
	_, err := manualProvider{}.validate(cfg, e.cfg.Config)
	if err != nil {
		return err
	}
	e.cfg = newModelConfig(cfg, cfg.UnknownAttrs())
	return nil
}
Esempio n. 8
0
// SecretAttrs is specified in the EnvironProvider interface.
func (prov *azureEnvironProvider) SecretAttrs(cfg *config.Config) (map[string]string, error) {
	unknownAttrs := cfg.UnknownAttrs()
	secretAttrs := map[string]string{
		configAttrAppPassword: unknownAttrs[configAttrAppPassword].(string),
	}
	if storageAccountKey, ok := unknownAttrs[configAttrStorageAccountKey].(string); ok {
		secretAttrs[configAttrStorageAccountKey] = storageAccountKey
	}
	return secretAttrs, nil
}
Esempio n. 9
0
// PrepareForBootstrap is specified in the EnvironProvider interface.
func (p manualProvider) PrepareForBootstrap(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) {
	if _, err := p.validate(cfg, nil); err != nil {
		return nil, err
	}
	envConfig := newModelConfig(cfg, cfg.UnknownAttrs())
	if err := ensureBootstrapUbuntuUser(ctx, envConfig); err != nil {
		return nil, err
	}
	return p.open(envConfig)
}
Esempio n. 10
0
func (prov maasEnvironProvider) Validate(cfg, oldCfg *config.Config) (*config.Config, error) {
	// Validate base configuration change before validating MAAS specifics.
	err := config.Validate(cfg, oldCfg)
	if err != nil {
		return nil, err
	}

	validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults)
	if err != nil {
		return nil, err
	}

	// Add MAAS specific defaults.
	providerDefaults := make(map[string]interface{})

	// Storage.
	if _, ok := cfg.StorageDefaultBlockSource(); !ok {
		providerDefaults[config.StorageDefaultBlockSourceKey] = maasStorageProviderType
	}
	if len(providerDefaults) > 0 {
		if cfg, err = cfg.Apply(providerDefaults); err != nil {
			return nil, err
		}
	}

	if oldCfg != nil {
		oldAttrs := oldCfg.UnknownAttrs()
		validMaasAgentName := false
		if oldName, ok := oldAttrs["maas-agent-name"]; !ok || oldName == nil {
			// If maas-agent-name was nil (because the config was
			// generated pre-1.16.2 the only correct value for it is ""
			// See bug #1256179
			validMaasAgentName = (validated["maas-agent-name"] == "")
		} else {
			validMaasAgentName = (validated["maas-agent-name"] == oldName)
		}
		if !validMaasAgentName {
			return nil, fmt.Errorf("cannot change maas-agent-name")
		}
	}
	envCfg := new(maasEnvironConfig)
	envCfg.Config = cfg
	envCfg.attrs = validated
	server := envCfg.maasServer()
	serverURL, err := url.Parse(server)
	if err != nil || serverURL.Scheme == "" || serverURL.Host == "" {
		return nil, fmt.Errorf("malformed maas-server URL '%v': %s", server, err)
	}
	oauth := envCfg.maasOAuth()
	if strings.Count(oauth, ":") != 2 {
		return nil, errMalformedMaasOAuth
	}
	return cfg.Apply(envCfg.attrs)
}
Esempio n. 11
0
func (p manualProvider) Open(cfg *config.Config) (environs.Environ, error) {
	_, err := p.validate(cfg, nil)
	if err != nil {
		return nil, err
	}
	// validate adds missing manual-specific config attributes
	// with their defaults in the result; we don't wnat that in
	// Open.
	envConfig := newEnvironConfig(cfg, cfg.UnknownAttrs())
	return p.open(envConfig)
}
Esempio n. 12
0
// PrepareForCreateEnvironment is specified in the EnvironProvider interface.
func (p environProvider) PrepareForCreateEnvironment(cfg *config.Config) (*config.Config, error) {
	attrs := cfg.UnknownAttrs()
	if _, ok := attrs["control-bucket"]; !ok {
		uuid, err := utils.NewUUID()
		if err != nil {
			return nil, errors.Trace(err)
		}
		attrs["control-bucket"] = fmt.Sprintf("%x", uuid.Raw())
	}
	return cfg.Apply(attrs)
}
Esempio n. 13
0
func (ts configTestSpec) checkAttrs(c *gc.C, attrs map[string]interface{}, cfg *config.Config) {
	for field, expected := range cfg.UnknownAttrs() {
		value := attrs[field]
		if field == "auth-file" && value != nil {
			filename := value.(string)
			if filename != "" {
				value = interface{}(filepath.Join(ts.rootDir, filename))
			}
		}
		c.Check(value, gc.Equals, expected)
	}
}
Esempio n. 14
0
func validateConfig(cfg, old *config.Config) (*environConfig, error) {
	// Check for valid changes for the base config values.
	if err := config.Validate(cfg, old); err != nil {
		return nil, err
	}
	validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults)
	if err != nil {
		return nil, err
	}

	// Add EC2 specific defaults.
	providerDefaults := make(map[string]interface{})

	// Storage.
	if _, ok := cfg.StorageDefaultBlockSource(); !ok {
		providerDefaults[config.StorageDefaultBlockSourceKey] = EBS_ProviderType
	}
	if len(providerDefaults) > 0 {
		if cfg, err = cfg.Apply(providerDefaults); err != nil {
			return nil, err
		}
	}
	ecfg := &environConfig{cfg, validated}

	if ecfg.accessKey() == "" || ecfg.secretKey() == "" {
		auth, err := aws.EnvAuth()
		if err != nil || ecfg.accessKey() != "" || ecfg.secretKey() != "" {
			return nil, fmt.Errorf("environment has no access-key or secret-key")
		}
		ecfg.attrs["access-key"] = auth.AccessKey
		ecfg.attrs["secret-key"] = auth.SecretKey
	}
	if _, ok := aws.Regions[ecfg.region()]; !ok {
		return nil, fmt.Errorf("invalid region name %q", ecfg.region())
	}

	if old != nil {
		attrs := old.UnknownAttrs()
		if region, _ := attrs["region"].(string); ecfg.region() != region {
			return nil, fmt.Errorf("cannot change region from %q to %q", region, ecfg.region())
		}
		if bucket, _ := attrs["control-bucket"].(string); ecfg.controlBucket() != bucket {
			return nil, fmt.Errorf("cannot change control-bucket from %q to %q", bucket, ecfg.controlBucket())
		}
	}

	// ssl-hostname-verification cannot be disabled
	if !ecfg.SSLHostnameVerification() {
		return nil, fmt.Errorf("disabling ssh-hostname-verification is not supported")
	}
	return ecfg, nil
}
Esempio n. 15
0
// PrepareForCreateEnvironment is specified in the EnvironProvider interface.
func (joyentProvider) PrepareForCreateEnvironment(cfg *config.Config) (*config.Config, error) {
	// Turn an incomplete config into a valid one, if possible.
	attrs := cfg.UnknownAttrs()

	if _, ok := attrs["control-dir"]; !ok {
		uuid, err := utils.NewUUID()
		if err != nil {
			return nil, errors.Trace(err)
		}
		attrs["control-dir"] = fmt.Sprintf("%x", uuid.Raw())
	}
	return cfg.Apply(attrs)
}
Esempio n. 16
0
func prepareConfig(cfg *config.Config) (*config.Config, error) {
	// Turn an incomplete config into a valid one, if possible.
	attrs := cfg.UnknownAttrs()

	if _, ok := attrs["control-dir"]; !ok {
		uuid, err := utils.NewUUID()
		if err != nil {
			return nil, err
		}
		attrs["control-dir"] = fmt.Sprintf("%x", uuid.Raw())
	}
	return cfg.Apply(attrs)
}
Esempio n. 17
0
// parseCredentials extracts the OAuth2 info from the config from the
// individual fields (falling back on the JSON file).
func parseCredentials(cfg *config.Config) (*google.Credentials, error) {
	attrs := cfg.UnknownAttrs()
	values := make(map[string]string)
	for _, field := range configAuthFields {
		if existing, ok := attrs[field].(string); ok && existing != "" {
			for key, candidate := range osEnvFields {
				if field == candidate {
					values[key] = existing
					break
				}
			}
		}
	}
	return google.NewCredentials(values)
}
Esempio n. 18
0
func (p maasEnvironProvider) Prepare(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) {
	attrs := cfg.UnknownAttrs()
	oldName, found := attrs["maas-agent-name"]
	if found && oldName != "" {
		return nil, errAgentNameAlreadySet
	}
	uuid, err := utils.NewUUID()
	if err != nil {
		return nil, err
	}
	attrs["maas-agent-name"] = uuid.String()
	cfg, err = cfg.Apply(attrs)
	if err != nil {
		return nil, err
	}
	return p.Open(cfg)
}
Esempio n. 19
0
func (p manualProvider) PrepareForBootstrap(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) {
	if use, ok := cfg.UnknownAttrs()["use-sshstorage"].(bool); ok && !use {
		return nil, fmt.Errorf("use-sshstorage must not be specified")
	}
	envConfig, err := p.validate(cfg, nil)
	if err != nil {
		return nil, err
	}
	cfg, err = cfg.Apply(envConfig.attrs)
	if err != nil {
		return nil, err
	}
	envConfig = newEnvironConfig(cfg, envConfig.attrs)
	if err := ensureBootstrapUbuntuUser(ctx, envConfig); err != nil {
		return nil, err
	}
	return p.open(envConfig)
}
Esempio n. 20
0
// Open implements environs.EnvironProvider.Open.
func (environProvider) Open(cfg *config.Config) (environs.Environ, error) {
	logger.Infof("opening environment %q", cfg.Name())
	if _, ok := cfg.AgentVersion(); !ok {
		newCfg, err := cfg.Apply(map[string]interface{}{
			"agent-version": version.Current.Number.String(),
		})
		if err != nil {
			return nil, err
		}
		cfg = newCfg
	}
	// Set the "namespace" attribute. We do this here, and not in Prepare,
	// for backwards compatibility: older versions did not store the namespace
	// in config.
	if namespace, _ := cfg.UnknownAttrs()["namespace"].(string); namespace == "" {
		username := os.Getenv("USER")
		if username == "" {
			u, err := userCurrent()
			if err != nil {
				return nil, fmt.Errorf("failed to determine username for namespace: %v", err)
			}
			username = u.Username
		}
		var err error
		namespace = fmt.Sprintf("%s-%s", username, cfg.Name())
		cfg, err = cfg.Apply(map[string]interface{}{"namespace": namespace})
		if err != nil {
			return nil, fmt.Errorf("failed to create namespace: %v", err)
		}
	}
	// Do the initial validation on the config.
	localConfig, err := providerInstance.newConfig(cfg)
	if err != nil {
		return nil, err
	}
	if err := VerifyPrerequisites(localConfig.container()); err != nil {
		return nil, fmt.Errorf("failed verification of local provider prerequisites: %v", err)
	}
	environ := &localEnviron{name: cfg.Name()}
	if err := environ.SetConfig(cfg); err != nil {
		return nil, fmt.Errorf("failure setting config: %v", err)
	}
	return environ, nil
}
Esempio n. 21
0
func adjustDefaults(cfg *config.Config, defaults map[string]interface{}) (map[string]interface{}, []string) {
	var unset []string
	updated := make(map[string]interface{})
	for k, v := range defaults {
		updated[k] = v
	}

	// Set the proper default namespace.
	raw := updated[cfgNamespace]
	if raw == nil || raw.(string) == "" {
		raw = cfg.Name()
		updated[cfgNamespace] = raw
	}

	if val, ok := cfg.UnknownAttrs()[cfgNamespace]; ok && val == "" {
		unset = append(unset, cfgNamespace)
	}

	return updated, unset
}
Esempio n. 22
0
// parseCredentials extracts the OAuth2 info from the config from the
// individual fields (falling back on the JSON file).
func parseCredentials(cfg *config.Config) (*google.Credentials, error) {
	attrs := cfg.UnknownAttrs()

	// Try the auth fields first.
	values := make(map[string]string)
	for _, field := range configAuthFields {
		if existing, ok := attrs[field].(string); ok && existing != "" {
			for key, candidate := range osEnvFields {
				if field == candidate {
					values[key] = existing
					break
				}
			}
		}
	}
	if len(values) > 0 {
		creds, err := google.NewCredentials(values)
		if err != nil {
			return nil, errors.Trace(err)
		}
		return creds, nil
	}

	// Fall back to the auth file.
	filename, ok := attrs[cfgAuthFile].(string)
	if !ok || filename == "" {
		// The missing credentials will be caught later.
		return nil, nil
	}
	authFile, err := os.Open(filename)
	if err != nil {
		return nil, errors.Trace(err)
	}
	defer authFile.Close()
	creds, err := google.ParseJSONKey(authFile)
	if err != nil {
		return nil, errors.Trace(err)
	}
	return creds, nil
}
Esempio n. 23
0
func (e *manualEnviron) SetConfig(cfg *config.Config) error {
	e.cfgmutex.Lock()
	defer e.cfgmutex.Unlock()
	_, err := manualProvider{}.validate(cfg, e.cfg.Config)
	if err != nil {
		return err
	}
	envConfig := newEnvironConfig(cfg, cfg.UnknownAttrs())
	// Set storage. If "use-sshstorage" is true then use the SSH storage.
	// Otherwise, use HTTP storage.
	//
	// We don't change storage once it's been set. Storage parameters
	// are fixed at bootstrap time, and it is not possible to change
	// them.
	if e.storage == nil {
		var stor storage.Storage
		if envConfig.useSSHStorage() {
			storageDir := e.StorageDir()
			storageTmpdir := path.Join(agent.DefaultPaths.DataDir, storageTmpSubdir)
			stor, err = newSSHStorage("ubuntu@"+e.cfg.bootstrapHost(), storageDir, storageTmpdir)
			if err != nil {
				return fmt.Errorf("initialising SSH storage failed: %v", err)
			}
		} else {
			caCertPEM, ok := envConfig.CACert()
			if !ok {
				// should not be possible to validate base config
				return fmt.Errorf("ca-cert not set")
			}
			authkey := envConfig.storageAuthKey()
			stor, err = httpstorage.ClientTLS(envConfig.storageAddr(), caCertPEM, authkey)
			if err != nil {
				return fmt.Errorf("initialising HTTPS storage failed: %v", err)
			}
		}
		e.storage = stor
	}
	e.cfg = envConfig
	return nil
}
Esempio n. 24
0
func (p environProvider) Validate(cfg, old *config.Config) (valid *config.Config, err error) {
	// Check for valid changes for the base config values.
	if err := config.Validate(cfg, old); err != nil {
		return nil, err
	}
	validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults)
	if err != nil {
		return nil, err
	}
	ecfg := &environConfig{cfg, validated}
	if ecfg.accessKey() == "" || ecfg.secretKey() == "" {
		auth, err := aws.EnvAuth()
		if err != nil || ecfg.accessKey() != "" || ecfg.secretKey() != "" {
			return nil, fmt.Errorf("environment has no access-key or secret-key")
		}
		ecfg.attrs["access-key"] = auth.AccessKey
		ecfg.attrs["secret-key"] = auth.SecretKey
	}
	if _, ok := aws.Regions[ecfg.region()]; !ok {
		return nil, fmt.Errorf("invalid region name %q", ecfg.region())
	}

	if old != nil {
		attrs := old.UnknownAttrs()
		if region, _ := attrs["region"].(string); ecfg.region() != region {
			return nil, fmt.Errorf("cannot change region from %q to %q", region, ecfg.region())
		}
		if bucket, _ := attrs["control-bucket"].(string); ecfg.controlBucket() != bucket {
			return nil, fmt.Errorf("cannot change control-bucket from %q to %q", bucket, ecfg.controlBucket())
		}
	}

	// ssl-hostname-verification cannot be disabled
	if !ecfg.SSLHostnameVerification() {
		return nil, fmt.Errorf("disabling ssh-hostname-verification is not supported")
	}

	// Apply the coerced unknown values back into the config.
	return cfg.Apply(ecfg.attrs)
}
Esempio n. 25
0
// PrepareForBootstrap implements environs.EnvironProvider.PrepareForBootstrap.
func (p environProvider) PrepareForBootstrap(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) {
	cfg, err := p.PrepareForCreateEnvironment(cfg)
	if err != nil {
		return nil, errors.Trace(err)
	}

	// The user must not set bootstrap-ip; this is determined by the provider,
	// and its presence used to determine whether the environment has yet been
	// bootstrapped.
	if _, ok := cfg.UnknownAttrs()["bootstrap-ip"]; ok {
		return nil, errors.Errorf("bootstrap-ip must not be specified")
	}
	err = checkLocalPort(cfg.StatePort(), "state port")
	if err != nil {
		return nil, errors.Trace(err)
	}
	err = checkLocalPort(cfg.APIPort(), "API port")
	if err != nil {
		return nil, errors.Trace(err)
	}

	return p.Open(cfg)
}
Esempio n. 26
0
func validateConfig(cfg, old *config.Config) (*environConfig, error) {
	// Check for valid changes for the base config values.
	if err := config.Validate(cfg, old); err != nil {
		return nil, err
	}
	validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults)
	if err != nil {
		return nil, err
	}
	ecfg := &environConfig{cfg, validated}

	if ecfg.accessKey() == "" || ecfg.secretKey() == "" {
		auth, err := aws.EnvAuth()
		if err != nil || ecfg.accessKey() != "" || ecfg.secretKey() != "" {
			return nil, fmt.Errorf("model has no access-key or secret-key")
		}
		ecfg.attrs["access-key"] = auth.AccessKey
		ecfg.attrs["secret-key"] = auth.SecretKey
	}
	if _, ok := aws.Regions[ecfg.region()]; !ok {
		return nil, fmt.Errorf("invalid region name %q", ecfg.region())
	}

	if old != nil {
		attrs := old.UnknownAttrs()
		if region, _ := attrs["region"].(string); ecfg.region() != region {
			return nil, fmt.Errorf("cannot change region from %q to %q", region, ecfg.region())
		}
	}

	// ssl-hostname-verification cannot be disabled
	if !ecfg.SSLHostnameVerification() {
		return nil, fmt.Errorf("disabling ssh-hostname-verification is not supported")
	}
	return ecfg, nil
}
Esempio n. 27
0
// update applies changes from the provided config to the env config.
// Changes to any immutable attributes result in an error.
func (c *environConfig) update(cfg *config.Config) error {
	// Validate the updates. newValidConfig does not modify the "known"
	// config attributes so it is safe to call Validate here first.
	if err := config.Validate(cfg, c.Config); err != nil {
		return errors.Trace(err)
	}

	updates, err := newValidConfig(cfg, configDefaults)
	if err != nil {
		return errors.Trace(err)
	}

	// Check that no immutable fields have changed.
	attrs := updates.UnknownAttrs()
	if err := ensureImmutableFields(c.attrs, attrs); err != nil {
		return errors.Trace(err)
	}

	// Apply the updates.
	// TODO(ericsnow) Should updates.Config be set in instead of cfg?
	c.Config = cfg
	c.attrs = cfg.UnknownAttrs()
	return nil
}
Esempio n. 28
0
// PrepareForCreateEnvironment is specified in the EnvironProvider interface.
func (p environProvider) PrepareForCreateEnvironment(cfg *config.Config) (*config.Config, error) {
	attrs := map[string]interface{}{
		// We must not proxy SSH through the API server in a
		// local provider environment. Besides not being useful,
		// it may not work; there is no requirement for sshd to
		// be available on machine-0.
		"proxy-ssh": false,
	}
	if _, ok := cfg.AgentVersion(); !ok {
		attrs["agent-version"] = version.Current.Number.String()
	}
	if namespace, _ := cfg.UnknownAttrs()["namespace"].(string); namespace == "" {
		username := os.Getenv("USER")
		if username == "" {
			u, err := userCurrent()
			if err != nil {
				return nil, errors.Annotate(err, "failed to determine username for namespace")
			}
			username = u.Username
		}
		attrs["namespace"] = fmt.Sprintf("%s-%s", username, cfg.Name())
	}

	setIfNotBlank := func(key, value string) {
		if value != "" {
			attrs[key] = value
		}
	}
	// If the user has specified no values for any of the four normal
	// proxies, then look in the environment and set them.
	logger.Tracef("Look for proxies?")
	if cfg.HttpProxy() == "" &&
		cfg.HttpsProxy() == "" &&
		cfg.FtpProxy() == "" &&
		cfg.NoProxy() == "" {
		proxySettings := proxy.DetectProxies()
		logger.Tracef("Proxies detected %#v", proxySettings)
		setIfNotBlank(config.HttpProxyKey, proxySettings.Http)
		setIfNotBlank(config.HttpsProxyKey, proxySettings.Https)
		setIfNotBlank(config.FtpProxyKey, proxySettings.Ftp)
		setIfNotBlank(config.NoProxyKey, proxySettings.NoProxy)
	}
	if version.Current.OS == version.Ubuntu {
		if cfg.AptHttpProxy() == "" &&
			cfg.AptHttpsProxy() == "" &&
			cfg.AptFtpProxy() == "" {
			proxySettings, err := detectPackageProxies()
			if err != nil {
				return nil, errors.Trace(err)
			}
			setIfNotBlank(config.AptHttpProxyKey, proxySettings.Http)
			setIfNotBlank(config.AptHttpsProxyKey, proxySettings.Https)
			setIfNotBlank(config.AptFtpProxyKey, proxySettings.Ftp)
		}
	}

	cfg, err := cfg.Apply(attrs)
	if err != nil {
		return nil, errors.Trace(err)
	}
	// Make sure everything is valid.
	cfg, err = p.Validate(cfg, nil)
	if err != nil {
		return nil, errors.Trace(err)
	}

	return cfg, nil
}
Esempio n. 29
0
// PrepareForBootstrap implements environs.EnvironProvider.PrepareForBootstrap.
func (p environProvider) PrepareForBootstrap(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) {
	attrs := map[string]interface{}{
		// We must not proxy SSH through the API server in a
		// local provider environment. Besides not being useful,
		// it may not work; there is no requirement for sshd to
		// be available on machine-0.
		"proxy-ssh": false,
	}
	if _, ok := cfg.AgentVersion(); !ok {
		attrs["agent-version"] = version.Current.String()
	}
	if namespace, _ := cfg.UnknownAttrs()["namespace"].(string); namespace == "" {
		username := os.Getenv("USER")
		if username == "" {
			u, err := userCurrent()
			if err != nil {
				return nil, errors.Annotate(err, "failed to determine username for namespace")
			}
			username = u.Username
		}
		attrs["namespace"] = fmt.Sprintf("%s-%s", username, cfg.Name())
	}

	setIfNotBlank := func(key, value string) {
		if value != "" {
			attrs[key] = value
		}
	}
	// If the user has specified no values for any of the four normal
	// proxies, then look in the environment and set them.
	logger.Tracef("Look for proxies?")
	if cfg.HttpProxy() == "" &&
		cfg.HttpsProxy() == "" &&
		cfg.FtpProxy() == "" &&
		cfg.NoProxy() == "" {
		proxySettings := proxy.DetectProxies()
		logger.Tracef("Proxies detected %#v", proxySettings)
		setIfNotBlank(config.HttpProxyKey, proxySettings.Http)
		setIfNotBlank(config.HttpsProxyKey, proxySettings.Https)
		setIfNotBlank(config.FtpProxyKey, proxySettings.Ftp)
		setIfNotBlank(config.NoProxyKey, proxySettings.NoProxy)
	}
	if jujuos.HostOS() == jujuos.Ubuntu {
		if cfg.AptHttpProxy() == "" &&
			cfg.AptHttpsProxy() == "" &&
			cfg.AptFtpProxy() == "" {
			proxySettings, err := detectPackageProxies()
			if err != nil {
				return nil, errors.Trace(err)
			}
			setIfNotBlank(config.AptHttpProxyKey, proxySettings.Http)
			setIfNotBlank(config.AptHttpsProxyKey, proxySettings.Https)
			setIfNotBlank(config.AptFtpProxyKey, proxySettings.Ftp)
		}
	}

	cfg, err := cfg.Apply(attrs)
	if err != nil {
		return nil, errors.Trace(err)
	}
	// Make sure everything is valid.
	cfg, err = p.Validate(cfg, nil)
	if err != nil {
		return nil, errors.Trace(err)
	}

	// The user must not set bootstrap-ip; this is determined by the provider,
	// and its presence used to determine whether the environment has yet been
	// bootstrapped.
	if _, ok := cfg.UnknownAttrs()["bootstrap-ip"]; ok {
		return nil, errors.Errorf("bootstrap-ip must not be specified")
	}
	err = checkLocalPort(cfg.StatePort(), "state port")
	if err != nil {
		return nil, errors.Trace(err)
	}
	err = checkLocalPort(cfg.APIPort(), "API port")
	if err != nil {
		return nil, errors.Trace(err)
	}

	return p.Open(cfg)
}
Esempio n. 30
0
func (ts configTestSpec) checkAttrs(c *gc.C, attrs map[string]interface{}, cfg *config.Config) {
	for field, expected := range cfg.UnknownAttrs() {
		value := attrs[field]
		c.Check(value, gc.Equals, expected)
	}
}