github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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  }