github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/provider/cloudsigma/provider.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // Juju provider for CloudSigma 5 6 package cloudsigma 7 8 import ( 9 "fmt" 10 11 "github.com/juju/errors" 12 "github.com/juju/loggo" 13 "github.com/juju/utils" 14 15 "github.com/juju/juju/environs" 16 "github.com/juju/juju/environs/config" 17 "github.com/juju/juju/environs/simplestreams" 18 "github.com/juju/juju/storage/provider/registry" 19 ) 20 21 var logger = loggo.GetLogger("juju.provider.cloudsigma") 22 23 const ( 24 providerType = "cloudsigma" 25 ) 26 27 func getImageSource(env environs.Environ) (simplestreams.DataSource, error) { 28 e, ok := env.(*environ) 29 if !ok { 30 return nil, errors.NotSupportedf("non-cloudsigma environment") 31 } 32 return simplestreams.NewURLDataSource("cloud images", fmt.Sprintf(CloudsigmaCloudImagesURLTemplate, e.ecfg.region()), utils.VerifySSLHostnames), nil 33 } 34 35 type environProvider struct{} 36 37 var providerInstance = environProvider{} 38 39 // check the provider implements environs.EnvironProvider interface 40 var _ environs.EnvironProvider = (*environProvider)(nil) 41 42 func init() { 43 // This will only happen in binaries that actually import this provider 44 // somewhere. To enable a provider, import it in the "providers/all" 45 // package; please do *not* import individual providers anywhere else, 46 // except in direct tests for that provider. 47 environs.RegisterProvider("cloudsigma", providerInstance) 48 environs.RegisterImageDataSourceFunc("cloud sigma image source", getImageSource) 49 registry.RegisterEnvironStorageProviders(providerType) 50 } 51 52 // Boilerplate returns a default configuration for the environment in yaml format. 53 // The text should be a key followed by some number of attributes: 54 // `environName: 55 // type: environTypeName 56 // attr1: val1 57 // ` 58 // The text is used as a template (see the template package) with one extra template 59 // function available, rand, which expands to a random hexadecimal string when invoked. 60 func (environProvider) BoilerplateConfig() string { 61 return boilerplateConfig 62 } 63 64 // Open opens the environment and returns it. 65 // The configuration must have come from a previously 66 // prepared environment. 67 func (environProvider) Open(cfg *config.Config) (environs.Environ, error) { 68 logger.Infof("opening environment %q", cfg.Name()) 69 70 cfg, err := prepareConfig(cfg) 71 if err != nil { 72 return nil, err 73 } 74 75 env := &environ{name: cfg.Name()} 76 if err := env.SetConfig(cfg); err != nil { 77 return nil, err 78 } 79 80 return env, nil 81 } 82 83 // RestrictedConfigAttributes are provider specific attributes stored in 84 // the config that really cannot or should not be changed across 85 // environments running inside a single juju server. 86 func (environProvider) RestrictedConfigAttributes() []string { 87 return []string{"region"} 88 } 89 90 // PrepareForCreateEnvironment prepares an environment for creation. Any 91 // additional configuration attributes are added to the config passed in 92 // and returned. This allows providers to add additional required config 93 // for new environments that may be created in an existing juju server. 94 func (environProvider) PrepareForCreateEnvironment(cfg *config.Config) (*config.Config, error) { 95 // Not even sure if this will ever make sense. 96 return nil, errors.NotImplementedf("PrepareForCreateEnvironment") 97 } 98 99 // Prepare prepares an environment for use. Any additional 100 // configuration attributes in the returned environment should 101 // be saved to be used later. If the environment is already 102 // prepared, this call is equivalent to Open. 103 func (environProvider) PrepareForBootstrap(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) { 104 logger.Infof("preparing environment %q", cfg.Name()) 105 return providerInstance.Open(cfg) 106 } 107 108 // Validate ensures that config is a valid configuration for this 109 // provider, applying changes to it if necessary, and returns the 110 // validated configuration. 111 // If old is not nil, it holds the previous environment configuration 112 // for consideration when validating changes. 113 func (environProvider) Validate(cfg, old *config.Config) (*config.Config, error) { 114 logger.Infof("validating environment %q", cfg.Name()) 115 116 // You should almost certainly not change this method; if you need to change 117 // how configs are validated, you should edit validateConfig itself, to ensure 118 // that your checks are always applied. 119 newEcfg, err := validateConfig(cfg, nil) 120 if err != nil { 121 return nil, errors.Errorf("invalid config: %v", err) 122 } 123 if old != nil { 124 oldEcfg, err := validateConfig(old, nil) 125 if err != nil { 126 return nil, errors.Errorf("invalid base config: %v", err) 127 } 128 if newEcfg, err = validateConfig(cfg, oldEcfg); err != nil { 129 return nil, errors.Errorf("invalid config change: %v", err) 130 } 131 } 132 133 return newEcfg.Config, nil 134 } 135 136 // SecretAttrs filters the supplied configuration returning only values 137 // which are considered sensitive. All of the values of these secret 138 // attributes need to be strings. 139 func (environProvider) SecretAttrs(cfg *config.Config) (map[string]string, error) { 140 logger.Infof("filtering secret attributes for environment %q", cfg.Name()) 141 142 // If you keep configSecretFields up to date, this method should Just Work. 143 ecfg, err := validateConfig(cfg, nil) 144 if err != nil { 145 return nil, err 146 } 147 secretAttrs := map[string]string{} 148 for _, field := range configSecretFields { 149 if value, ok := ecfg.attrs[field]; ok { 150 if stringValue, ok := value.(string); ok { 151 secretAttrs[field] = stringValue 152 } else { 153 // All your secret attributes must be strings at the moment. Sorry. 154 // It's an expedient and hopefully temporary measure that helps us 155 // plug a security hole in the API. 156 return nil, errors.Errorf( 157 "secret %q field must have a string value; got %v", 158 field, value, 159 ) 160 } 161 } 162 } 163 164 return secretAttrs, nil 165 }