github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/environs/cloudspec/cloudspec.go (about) 1 // Copyright 2020 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package cloudspec 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names/v5" 9 10 jujucloud "github.com/juju/juju/cloud" 11 ) 12 13 // CloudSpec describes a specific cloud configuration, for the purpose 14 // of opening an Environ to manage the cloud resources. 15 type CloudSpec struct { 16 // Type is the type of cloud, eg aws, openstack etc. 17 Type string 18 19 // Name is the name of the cloud. 20 Name string 21 22 // Region is the name of the cloud region, if the cloud supports 23 // regions. 24 Region string 25 26 // Endpoint is the endpoint for the cloud (region). 27 Endpoint string 28 29 // IdentityEndpoint is the identity endpoint for the cloud (region). 30 IdentityEndpoint string 31 32 // StorageEndpoint is the storage endpoint for the cloud (region). 33 StorageEndpoint string 34 35 // Credential is the cloud credential to use to authenticate 36 // with the cloud, or nil if the cloud does not require any 37 // credentials. 38 Credential *jujucloud.Credential 39 40 // CACertificates contains an optional list of Certificate 41 // Authority certificates to be used to validate certificates 42 // of cloud infrastructure components 43 // The contents are Base64 encoded x.509 certs. 44 CACertificates []string 45 46 // SkipTLSVerify is true if the client should be asked not to 47 // validate certificates. It is not recommended for production clouds. 48 // It is secure (false) by default. 49 SkipTLSVerify bool 50 51 // IsControllerCloud is true when this is the cloud used by the controller. 52 IsControllerCloud bool 53 } 54 55 // Validate validates that the CloudSpec is well-formed. It does 56 // not ensure that the cloud type and credentials are valid. 57 func (cs CloudSpec) Validate() error { 58 if cs.Type == "" { 59 return errors.NotValidf("empty Type") 60 } 61 if !names.IsValidCloud(cs.Name) { 62 return errors.NotValidf("cloud name %q", cs.Name) 63 } 64 return nil 65 } 66 67 // MakeCloudSpec returns a CloudSpec from the given 68 // Cloud, cloud and region names, and credential. 69 func MakeCloudSpec(cloud jujucloud.Cloud, cloudRegionName string, credential *jujucloud.Credential) (CloudSpec, error) { 70 cloudSpec := CloudSpec{ 71 Type: cloud.Type, 72 Name: cloud.Name, 73 Region: cloudRegionName, 74 Endpoint: cloud.Endpoint, 75 IdentityEndpoint: cloud.IdentityEndpoint, 76 StorageEndpoint: cloud.StorageEndpoint, 77 CACertificates: cloud.CACertificates, 78 SkipTLSVerify: cloud.SkipTLSVerify, 79 Credential: credential, 80 IsControllerCloud: cloud.IsControllerCloud, 81 } 82 if cloudRegionName != "" { 83 cloudRegion, err := jujucloud.RegionByName(cloud.Regions, cloudRegionName) 84 if err != nil { 85 return CloudSpec{}, errors.Annotate(err, "getting cloud region definition") 86 } 87 if !cloudRegion.IsEmpty() { 88 cloudSpec.Endpoint = cloudRegion.Endpoint 89 cloudSpec.IdentityEndpoint = cloudRegion.IdentityEndpoint 90 cloudSpec.StorageEndpoint = cloudRegion.StorageEndpoint 91 } 92 } 93 return cloudSpec, nil 94 } 95 96 // CloudRegionSpec contains the information needed to lookup specific 97 // cloud or cloud region configuration. This is for use in calling 98 // state/modelconfig.(ComposeNewModelConfig) so there is no need to serialize it. 99 type CloudRegionSpec struct { 100 // Cloud is the name of the cloud. 101 Cloud string 102 103 // Region is the name of the cloud region. 104 Region string 105 } 106 107 // NewCloudRegionSpec returns a CloudRegionSpec ensuring cloud arg is not empty. 108 func NewCloudRegionSpec(cloud, region string) (*CloudRegionSpec, error) { 109 if cloud == "" { 110 return nil, errors.New("cloud is required to be non empty") 111 } 112 return &CloudRegionSpec{Cloud: cloud, Region: region}, nil 113 }