github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/provider/manual/provider.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package manual 5 6 import ( 7 "fmt" 8 "strings" 9 10 "github.com/juju/errors" 11 12 "github.com/juju/juju/cloud" 13 "github.com/juju/juju/environs" 14 "github.com/juju/juju/environs/config" 15 "github.com/juju/juju/environs/manual" 16 ) 17 18 type manualProvider struct { 19 environProviderCredentials 20 } 21 22 // Verify that we conform to the interface. 23 var _ environs.EnvironProvider = (*manualProvider)(nil) 24 25 var initUbuntuUser = manual.InitUbuntuUser 26 27 func ensureBootstrapUbuntuUser(ctx environs.BootstrapContext, host, user string, cfg *environConfig) error { 28 err := initUbuntuUser(host, user, cfg.AuthorizedKeys(), ctx.GetStdin(), ctx.GetStdout()) 29 if err != nil { 30 logger.Errorf("initializing ubuntu user: %v", err) 31 return err 32 } 33 logger.Infof("initialized ubuntu user") 34 return nil 35 } 36 37 // DetectRegions is specified in the environs.CloudRegionDetector interface. 38 func (p manualProvider) DetectRegions() ([]cloud.Region, error) { 39 return nil, errors.NotFoundf("regions") 40 } 41 42 // PrepareConfig is specified in the EnvironProvider interface. 43 func (p manualProvider) PrepareConfig(args environs.PrepareConfigParams) (*config.Config, error) { 44 if err := validateCloudSpec(args.Cloud); err != nil { 45 return nil, errors.Trace(err) 46 } 47 envConfig, err := p.validate(args.Config, nil) 48 if err != nil { 49 return nil, err 50 } 51 return args.Config.Apply(envConfig.attrs) 52 } 53 54 func (p manualProvider) Open(args environs.OpenParams) (environs.Environ, error) { 55 if err := validateCloudSpec(args.Cloud); err != nil { 56 return nil, errors.Trace(err) 57 } 58 _, err := p.validate(args.Config, nil) 59 if err != nil { 60 return nil, err 61 } 62 // validate adds missing manual-specific config attributes 63 // with their defaults in the result; we don't wnat that in 64 // Open. 65 envConfig := newModelConfig(args.Config, args.Config.UnknownAttrs()) 66 host, user := args.Cloud.Endpoint, "" 67 if i := strings.IndexRune(host, '@'); i >= 0 { 68 user, host = host[:i], host[i+1:] 69 } 70 return p.open(host, user, envConfig) 71 } 72 73 func validateCloudSpec(spec environs.CloudSpec) error { 74 if spec.Endpoint == "" { 75 return errors.Errorf( 76 "missing address of host to bootstrap: " + 77 `please specify "juju bootstrap manual/[user@]<host>"`, 78 ) 79 } 80 return nil 81 } 82 83 func (p manualProvider) open(host, user string, cfg *environConfig) (environs.Environ, error) { 84 env := &manualEnviron{host: host, user: user, cfg: cfg} 85 // Need to call SetConfig to initialise storage. 86 if err := env.SetConfig(cfg.Config); err != nil { 87 return nil, err 88 } 89 return env, nil 90 } 91 92 func checkImmutableString(cfg, old *environConfig, key string) error { 93 if old.attrs[key] != cfg.attrs[key] { 94 return fmt.Errorf("cannot change %s from %q to %q", key, old.attrs[key], cfg.attrs[key]) 95 } 96 return nil 97 } 98 99 func (p manualProvider) validate(cfg, old *config.Config) (*environConfig, error) { 100 // Check for valid changes for the base config values. 101 if err := config.Validate(cfg, old); err != nil { 102 return nil, err 103 } 104 validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults) 105 if err != nil { 106 return nil, err 107 } 108 envConfig := newModelConfig(cfg, validated) 109 110 // If the user hasn't already specified a value, set it to the 111 // given value. 112 defineIfNot := func(keyName string, value interface{}) { 113 if _, defined := cfg.AllAttrs()[keyName]; !defined { 114 logger.Infof("%s was not defined. Defaulting to %v.", keyName, value) 115 envConfig.attrs[keyName] = value 116 } 117 } 118 119 // If the user hasn't specified a value, refresh the 120 // available updates, but don't upgrade. 121 defineIfNot("enable-os-refresh-update", true) 122 defineIfNot("enable-os-upgrade", false) 123 124 return envConfig, nil 125 } 126 127 func (p manualProvider) Validate(cfg, old *config.Config) (valid *config.Config, err error) { 128 envConfig, err := p.validate(cfg, old) 129 if err != nil { 130 return nil, err 131 } 132 return cfg.Apply(envConfig.attrs) 133 }