// validateCloudRegion validates the given region name against the // provided Cloud definition, and returns a txn.Op to include in a // transaction to assert the same. func validateCloudRegion(cloud jujucloud.Cloud, cloudName, regionName string) (txn.Op, error) { // Ensure that the cloud region is valid, or if one is not specified, // that the cloud does not support regions. assertCloudRegionOp := txn.Op{ C: cloudsC, Id: cloudName, } if regionName != "" { region, err := jujucloud.RegionByName(cloud.Regions, regionName) if err != nil { return txn.Op{}, errors.Trace(err) } assertCloudRegionOp.Assert = bson.D{ {"regions." + region.Name, bson.D{{"$exists", true}}}, } } else { if len(cloud.Regions) > 0 { return txn.Op{}, errors.NotValidf("missing CloudRegion") } assertCloudRegionOp.Assert = bson.D{ {"regions", bson.D{{"$exists", false}}}, } } return assertCloudRegionOp, nil }
// getRegion returns the cloud.Region to use, based on the specified // region name. If no region name is specified, and there is at least // one region, we use the first region in the list. func getRegion(cloud *jujucloud.Cloud, cloudName, regionName string) (jujucloud.Region, error) { if regionName != "" { region, err := jujucloud.RegionByName(cloud.Regions, regionName) if err != nil { return jujucloud.Region{}, errors.Trace(err) } return *region, nil } if len(cloud.Regions) > 0 { // No region was specified, use the first region in the list. return cloud.Regions[0], nil } return jujucloud.Region{ "", // no region name cloud.Endpoint, cloud.IdentityEndpoint, cloud.StorageEndpoint, }, nil }
// MakeCloudSpec returns a CloudSpec from the given // Cloud, cloud and region names, and credential. func MakeCloudSpec(cloud jujucloud.Cloud, cloudName, cloudRegionName string, credential *jujucloud.Credential) (CloudSpec, error) { cloudSpec := CloudSpec{ Type: cloud.Type, Name: cloudName, Region: cloudRegionName, Endpoint: cloud.Endpoint, IdentityEndpoint: cloud.IdentityEndpoint, StorageEndpoint: cloud.StorageEndpoint, Credential: credential, } if cloudRegionName != "" { cloudRegion, err := jujucloud.RegionByName(cloud.Regions, cloudRegionName) if err != nil { return CloudSpec{}, errors.Annotate(err, "getting cloud region definition") } cloudSpec.Endpoint = cloudRegion.Endpoint cloudSpec.IdentityEndpoint = cloudRegion.IdentityEndpoint cloudSpec.StorageEndpoint = cloudRegion.StorageEndpoint } return cloudSpec, nil }
func (c *addModelCommand) getCloudRegion(cloudClient CloudAPI) (cloudTag names.CloudTag, cloud jujucloud.Cloud, cloudRegion string, err error) { var cloudName string sep := strings.IndexRune(c.CloudRegion, '/') if sep >= 0 { // User specified "cloud/region". cloudName, cloudRegion = c.CloudRegion[:sep], c.CloudRegion[sep+1:] if !names.IsValidCloud(cloudName) { return names.CloudTag{}, jujucloud.Cloud{}, "", errors.NotValidf("cloud name %q", cloudName) } cloudTag = names.NewCloudTag(cloudName) if cloud, err = cloudClient.Cloud(cloudTag); err != nil { return names.CloudTag{}, jujucloud.Cloud{}, "", errors.Trace(err) } } else { // User specified "cloud" or "region". We'll try first // for cloud (check if it's a valid cloud name, and // whether there is a cloud by that name), and then // as a region within the default cloud. if names.IsValidCloud(c.CloudRegion) { cloudName = c.CloudRegion } else { cloudRegion = c.CloudRegion } if cloudName != "" { cloudTag = names.NewCloudTag(cloudName) cloud, err = cloudClient.Cloud(cloudTag) if params.IsCodeNotFound(err) { // No such cloud with the specified name, // so we'll try the name as a region in // the default cloud. cloudRegion, cloudName = cloudName, "" } else if err != nil { return names.CloudTag{}, jujucloud.Cloud{}, "", errors.Trace(err) } } if cloudName == "" { cloudTag, cloud, err = defaultCloud(cloudClient) if err != nil && !errors.IsNotFound(err) { return names.CloudTag{}, jujucloud.Cloud{}, "", errors.Trace(err) } } } if cloudRegion != "" { // A region has been specified, make sure it exists. if _, err := jujucloud.RegionByName(cloud.Regions, cloudRegion); err != nil { if cloudRegion == c.CloudRegion { // The string is not in the format cloud/region, // so we should tell that the user that it is // neither a cloud nor a region in the default // cloud (or that there is no default cloud). err := c.unsupportedCloudOrRegionError(cloudClient, cloudTag) return names.CloudTag{}, jujucloud.Cloud{}, "", errors.Trace(err) } return names.CloudTag{}, jujucloud.Cloud{}, "", errors.Trace(err) } } else if len(cloud.Regions) > 0 { // The first region in the list is the default. cloudRegion = cloud.Regions[0].Name } return cloudTag, cloud, cloudRegion, nil }
// GetCredentials returns a curated set of credential values for a given cloud. // The credential key values are read from the credentials store and the provider // finalises the values to resolve things like json files. // If region is not specified, the default credential region is used. func GetCredentials( ctx *cmd.Context, store jujuclient.CredentialGetter, args GetCredentialsParams, ) (_ *cloud.Credential, chosenCredentialName, regionName string, _ error) { credential, credentialName, defaultRegion, err := credentialByName( store, args.CloudName, args.CredentialName, ) if err != nil { return nil, "", "", errors.Trace(err) } regionName = args.CloudRegion if regionName == "" { regionName = defaultRegion if regionName == "" && len(args.Cloud.Regions) > 0 { // No region was specified, use the first region // in the list. regionName = args.Cloud.Regions[0].Name } } cloudEndpoint := args.Cloud.Endpoint cloudIdentityEndpoint := args.Cloud.IdentityEndpoint if regionName != "" { region, err := cloud.RegionByName(args.Cloud.Regions, regionName) if err != nil { return nil, "", "", errors.Trace(err) } cloudEndpoint = region.Endpoint cloudIdentityEndpoint = region.IdentityEndpoint } readFile := func(f string) ([]byte, error) { f, err := utils.NormalizePath(f) if err != nil { return nil, errors.Trace(err) } return ioutil.ReadFile(f) } // Finalize credential against schemas supported by the provider. provider, err := environs.Provider(args.Cloud.Type) if err != nil { return nil, "", "", errors.Trace(err) } credential, err = cloud.FinalizeCredential( *credential, provider.CredentialSchemas(), readFile, ) if err != nil { return nil, "", "", errors.Annotatef( err, "finalizing %q credential for cloud %q", credentialName, args.CloudName, ) } credential, err = provider.FinalizeCredential( ctx, environs.FinalizeCredentialParams{ Credential: *credential, CloudEndpoint: cloudEndpoint, CloudIdentityEndpoint: cloudIdentityEndpoint, }, ) if err != nil { return nil, "", "", errors.Annotatef( err, "finalizing %q credential for cloud %q", credentialName, args.CloudName, ) } return credential, credentialName, regionName, nil }