Example #1
0
File: model.go Project: bac/juju
// 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
}
Example #2
0
// 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
}
Example #3
0
// 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
}
Example #4
0
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
}
Example #5
0
// 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
}