github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/common/cloud.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/loggo"
     9  	"gopkg.in/juju/environschema.v1"
    10  
    11  	jujucloud "github.com/juju/juju/cloud"
    12  	"github.com/juju/juju/environs"
    13  	"github.com/juju/juju/environs/config"
    14  )
    15  
    16  var logger = loggo.GetLogger("juju.cmd.juju.common")
    17  
    18  type chooseCloudRegionError struct {
    19  	error
    20  }
    21  
    22  // IsChooseCloudRegionError reports whether or not the given
    23  // error was returned from ChooseCloudRegion.
    24  func IsChooseCloudRegionError(err error) bool {
    25  	_, ok := errors.Cause(err).(chooseCloudRegionError)
    26  	return ok
    27  }
    28  
    29  // CloudOrProvider finds and returns cloud or provider.
    30  func CloudOrProvider(cloudName string, cloudByNameFunc func(string) (*jujucloud.Cloud, error)) (cloud *jujucloud.Cloud, err error) {
    31  	if cloud, err = cloudByNameFunc(cloudName); err != nil {
    32  		if !errors.IsNotFound(err) {
    33  			return nil, err
    34  		}
    35  		builtInClouds, err := BuiltInClouds()
    36  		if err != nil {
    37  			return nil, errors.Trace(err)
    38  		}
    39  		if builtIn, ok := builtInClouds[cloudName]; !ok {
    40  			return nil, errors.NotValidf("cloud %v", cloudName)
    41  		} else {
    42  			cloud = &builtIn
    43  		}
    44  	}
    45  	return cloud, nil
    46  }
    47  
    48  // ChooseCloudRegion returns the cloud.Region to use, based on the specified
    49  // region name. If no region name is specified, and there is at least one
    50  // region, we use the first region in the list. If there are no regions, then
    51  // we return a region with no name, having the same endpoints as the cloud.
    52  func ChooseCloudRegion(cloud jujucloud.Cloud, regionName string) (jujucloud.Region, error) {
    53  	if regionName != "" {
    54  		region, err := jujucloud.RegionByName(cloud.Regions, regionName)
    55  		if err != nil {
    56  			return jujucloud.Region{}, errors.Trace(chooseCloudRegionError{err})
    57  		}
    58  		return *region, nil
    59  	}
    60  	if len(cloud.Regions) > 0 {
    61  		// No region was specified, use the first region in the list.
    62  		return cloud.Regions[0], nil
    63  	}
    64  	return jujucloud.Region{
    65  		"", // no region name
    66  		cloud.Endpoint,
    67  		cloud.IdentityEndpoint,
    68  		cloud.StorageEndpoint,
    69  	}, nil
    70  }
    71  
    72  // BuiltInClouds returns cloud information for those
    73  // providers which are built in to Juju.
    74  func BuiltInClouds() (map[string]jujucloud.Cloud, error) {
    75  	allClouds := make(map[string]jujucloud.Cloud)
    76  	for _, providerType := range environs.RegisteredProviders() {
    77  		p, err := environs.Provider(providerType)
    78  		if err != nil {
    79  			return nil, errors.Trace(err)
    80  		}
    81  		detector, ok := p.(environs.CloudDetector)
    82  		if !ok {
    83  			continue
    84  		}
    85  		clouds, err := detector.DetectClouds()
    86  		if err != nil {
    87  			return nil, errors.Annotatef(
    88  				err, "detecting clouds for provider %q",
    89  				providerType,
    90  			)
    91  		}
    92  		for _, cloud := range clouds {
    93  			allClouds[cloud.Name] = cloud
    94  		}
    95  	}
    96  	return allClouds, nil
    97  }
    98  
    99  // CloudByName returns a cloud for given name
   100  // regardless of whether it's public, private or builtin cloud.
   101  // Not to be confused with cloud.CloudByName which does not cater
   102  // for built-in clouds like localhost.
   103  func CloudByName(cloudName string) (*jujucloud.Cloud, error) {
   104  	cloud, err := jujucloud.CloudByName(cloudName)
   105  	if err != nil {
   106  		if errors.IsNotFound(err) {
   107  			// Check built in clouds like localhost (lxd).
   108  			builtinClouds, err := BuiltInClouds()
   109  			if err != nil {
   110  				return nil, errors.Trace(err)
   111  			}
   112  			aCloud, found := builtinClouds[cloudName]
   113  			if !found {
   114  				return nil, errors.NotFoundf("cloud %s", cloudName)
   115  			}
   116  			return &aCloud, nil
   117  		}
   118  		return nil, errors.Trace(err)
   119  	}
   120  	return cloud, nil
   121  }
   122  
   123  // CloudSchemaByType returns the Schema for a given cloud type.
   124  // If the ProviderSchema is not implemented for the given cloud
   125  // type, a NotFound error is returned.
   126  func CloudSchemaByType(cloudType string) (environschema.Fields, error) {
   127  	provider, err := environs.Provider(cloudType)
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  	ps, ok := provider.(environs.ProviderSchema)
   132  	if !ok {
   133  		return nil, errors.NotImplementedf("environs.ProviderSchema")
   134  	}
   135  	providerSchema := ps.Schema()
   136  	if providerSchema == nil {
   137  		return nil, errors.New("Failed to retrieve Provider Schema")
   138  	}
   139  	return providerSchema, nil
   140  }
   141  
   142  // ProviderConfigSchemaSourceByType returns a config.ConfigSchemaSource
   143  // for the environ provider, found for the given cloud type, or an error.
   144  func ProviderConfigSchemaSourceByType(cloudType string) (config.ConfigSchemaSource, error) {
   145  	provider, err := environs.Provider(cloudType)
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  	if cs, ok := provider.(config.ConfigSchemaSource); ok {
   150  		return cs, nil
   151  	}
   152  	return nil, errors.NotImplementedf("config.ConfigSource")
   153  }
   154  
   155  // PrintConfigSchema is used to print model configuration schema.
   156  type PrintConfigSchema struct {
   157  	Type        string `yaml:"type,omitempty" json:"type,omitempty"`
   158  	Description string `yaml:"description,omitempty" json:"description,omitempty"`
   159  }