// defaultStoragePool returns the default storage pool for the environment. // The default pool is either user specified, or one that is registered by the provider itself. func defaultStoragePool(cfg *config.Config, kind storage.StorageKind, cons StorageConstraints) (string, error) { switch kind { case storage.StorageKindBlock: loopPool := string(provider.LoopProviderType) emptyConstraints := StorageConstraints{} if cons == emptyConstraints { // No constraints at all: use loop. return loopPool, nil } // Either size or count specified, use env default. defaultPool, ok := cfg.StorageDefaultBlockSource() if !ok { defaultPool = loopPool } return defaultPool, nil case storage.StorageKindFilesystem: rootfsPool := string(provider.RootfsProviderType) emptyConstraints := StorageConstraints{} if cons == emptyConstraints { return rootfsPool, nil } // TODO(axw) add env configuration for default // filesystem source, prefer that. defaultPool, ok := cfg.StorageDefaultBlockSource() if !ok { defaultPool = rootfsPool } return defaultPool, nil } return "", ErrNoDefaultStoragePool }
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) }
func configWithDefaults(cfg *config.Config) (*config.Config, error) { defaults := make(map[string]interface{}) if _, ok := cfg.StorageDefaultBlockSource(); !ok { // Set the default block source. defaults[config.StorageDefaultBlockSourceKey] = storageProviderType } if len(defaults) == 0 { return cfg, nil } return cfg.Apply(defaults) }
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 }
// Validate ensures that config is a valid configuration for this // provider like specified in the EnvironProvider interface. func (prov azureEnvironProvider) Validate(cfg, oldCfg *config.Config) (*config.Config, error) { // Validate base configuration change before validating Azure specifics. err := config.Validate(cfg, oldCfg) if err != nil { return nil, err } // User cannot change availability-sets-enabled after environment is prepared. if oldCfg != nil { if oldCfg.AllAttrs()["availability-sets-enabled"] != cfg.AllAttrs()["availability-sets-enabled"] { return nil, fmt.Errorf("cannot change availability-sets-enabled") } } validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults) if err != nil { return nil, err } envCfg := new(azureEnvironConfig) envCfg.Config = cfg envCfg.attrs = validated if _, ok := cfg.StorageDefaultBlockSource(); !ok { // Default volume source not specified; set // it to the azure storage provider. envCfg.attrs[config.StorageDefaultBlockSourceKey] = storageProviderType } cert := envCfg.managementCertificate() if cert == "" { certPath := envCfg.attrs["management-certificate-path"].(string) pemData, err := readPEMFile(certPath) if err != nil { return nil, fmt.Errorf("invalid management-certificate-path: %s", err) } envCfg.attrs["management-certificate"] = string(pemData) } else { if block, _ := pem.Decode([]byte(cert)); block == nil { return nil, fmt.Errorf("invalid management-certificate: not a PEM encoded certificate") } } delete(envCfg.attrs, "management-certificate-path") if envCfg.location() == "" { return nil, fmt.Errorf("environment has no location; you need to set one. E.g. 'West US'") } return cfg.Apply(envCfg.attrs) }
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, p.Configurator.GetConfigDefaults()) if err != nil { return nil, err } // Add Openstack specific defaults. providerDefaults := map[string]interface{}{} // Storage. if _, ok := cfg.StorageDefaultBlockSource(); !ok { providerDefaults[config.StorageDefaultBlockSourceKey] = CinderProviderType } if len(providerDefaults) > 0 { if cfg, err = cfg.Apply(providerDefaults); err != nil { return nil, err } } ecfg := &environConfig{cfg, validated} if ecfg.authURL() != "" { parts, err := url.Parse(ecfg.authURL()) if err != nil || parts.Host == "" || parts.Scheme == "" { return nil, fmt.Errorf("invalid auth-url value %q", ecfg.authURL()) } } cred := identity.CredentialsFromEnv() format := "required model variable not set for credentials attribute: %s" switch ecfg.authMode() { case AuthUserPass, AuthLegacy: if ecfg.username() == "" { if cred.User == "" { return nil, fmt.Errorf(format, "User") } ecfg.attrs["username"] = cred.User } if ecfg.password() == "" { if cred.Secrets == "" { return nil, fmt.Errorf(format, "Secrets") } ecfg.attrs["password"] = cred.Secrets } case AuthKeyPair: if ecfg.accessKey() == "" { if cred.User == "" { return nil, fmt.Errorf(format, "User") } ecfg.attrs["access-key"] = cred.User } if ecfg.secretKey() == "" { if cred.Secrets == "" { return nil, fmt.Errorf(format, "Secrets") } ecfg.attrs["secret-key"] = cred.Secrets } default: return nil, fmt.Errorf("unexpected authentication mode %q", ecfg.authMode()) } if ecfg.authURL() == "" { if cred.URL == "" { return nil, fmt.Errorf(format, "URL") } ecfg.attrs["auth-url"] = cred.URL } if ecfg.tenantName() == "" { if cred.TenantName == "" { return nil, fmt.Errorf(format, "TenantName") } ecfg.attrs["tenant-name"] = cred.TenantName } if ecfg.region() == "" { if cred.Region == "" { return nil, fmt.Errorf(format, "Region") } ecfg.attrs["region"] = cred.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()) } } // Check for deprecated fields and log a warning. We also print to stderr to ensure the user sees the message // even if they are not running with --debug. cfgAttrs := cfg.AllAttrs() if defaultImageId := cfgAttrs["default-image-id"]; defaultImageId != nil && defaultImageId.(string) != "" { msg := fmt.Sprintf( "Config attribute %q (%v) is deprecated and ignored.\n"+ "Your cloud provider should have set up image metadata to provide the correct image id\n"+ "for your chosen series and archietcure. If this is a private Openstack deployment without\n"+ "existing image metadata, please run 'juju-metadata help' to see how suitable image"+ "metadata can be generated.", "default-image-id", defaultImageId) logger.Warningf(msg) } if defaultInstanceType := cfgAttrs["default-instance-type"]; defaultInstanceType != nil && defaultInstanceType.(string) != "" { msg := fmt.Sprintf( "Config attribute %q (%v) is deprecated and ignored.\n"+ "The correct instance flavor is determined using constraints, globally specified\n"+ "when an model is bootstrapped, or individually when a charm is deployed.\n"+ "See 'juju help bootstrap' or 'juju help deploy'.", "default-instance-type", defaultInstanceType) logger.Warningf(msg) } // Construct a new config with the deprecated attributes removed. for _, attr := range []string{"default-image-id", "default-instance-type"} { delete(cfgAttrs, attr) delete(ecfg.attrs, attr) } for k, v := range ecfg.attrs { cfgAttrs[k] = v } return config.New(config.NoDefaults, cfgAttrs) }