// DetectRegions implements environs.CloudRegionDetector. func (EnvironProvider) DetectRegions() ([]cloud.Region, error) { // If OS_REGION_NAME and OS_AUTH_URL are both set, // return return a region using them. creds := identity.CredentialsFromEnv() if creds.Region == "" { return nil, errors.NewNotFound(nil, "OS_REGION_NAME environment variable not set") } if creds.URL == "" { return nil, errors.NewNotFound(nil, "OS_AUTH_URL environment variable not set") } return []cloud.Region{{ Name: creds.Region, Endpoint: creds.URL, }}, nil }
func (c OpenstackCredentials) detectCredential() (*cloud.Credential, string, string, error) { creds := identity.CredentialsFromEnv() if creds.TenantName == "" { return nil, "", "", errors.NewNotFound(nil, "OS_TENANT_NAME environment variable not set") } if creds.User == "" { return nil, "", "", errors.NewNotFound(nil, "neither OS_USERNAME nor OS_ACCESS_KEY environment variable not set") } if creds.Secrets == "" { return nil, "", "", errors.NewNotFound(nil, "neither OS_PASSWORD nor OS_SECRET_KEY environment variable not set") } user, err := utils.LocalUsername() if err != nil { return nil, "", "", errors.Trace(err) } // If OS_USERNAME or NOVA_USERNAME is set, assume userpass. var credential cloud.Credential if os.Getenv("OS_USERNAME") != "" || os.Getenv("NOVA_USERNAME") != "" { user = creds.User credential = cloud.NewCredential( cloud.UserPassAuthType, map[string]string{ credAttrUserName: creds.User, credAttrPassword: creds.Secrets, credAttrTenantName: creds.TenantName, credAttrDomainName: creds.DomainName, }, ) } else { credential = cloud.NewCredential( cloud.AccessKeyAuthType, map[string]string{ credAttrAccessKey: creds.User, credAttrSecretKey: creds.Secrets, credAttrTenantName: creds.TenantName, }, ) } region := creds.Region if region == "" { region = "<unspecified>" } credential.Label = fmt.Sprintf("openstack region %q project %q user %q", region, creds.TenantName, user) return &credential, user, creds.Region, nil }
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) }