github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/cmd/juju/common.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package main
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/errors"
    10  
    11  	"github.com/juju/juju/charm"
    12  	"github.com/juju/juju/cmd"
    13  	"github.com/juju/juju/environs"
    14  	"github.com/juju/juju/environs/config"
    15  	"github.com/juju/juju/environs/configstore"
    16  	"github.com/juju/juju/state/api"
    17  )
    18  
    19  // destroyPreparedEnviron destroys the environment and logs an error if it fails.
    20  func destroyPreparedEnviron(ctx *cmd.Context, env environs.Environ, store configstore.Storage, err *error, action string) {
    21  	if *err == nil {
    22  		return
    23  	}
    24  	ctx.Infof("%s failed, destroying environment", action)
    25  	if err := environs.Destroy(env, store); err != nil {
    26  		logger.Errorf("%s failed, and the environment could not be destroyed: %v", action, err)
    27  	}
    28  }
    29  
    30  // environFromName loads an existing environment or prepares a new one.
    31  func environFromName(
    32  	ctx *cmd.Context, envName string, resultErr *error, action string) (environs.Environ, func(), error) {
    33  
    34  	store, err := configstore.Default()
    35  	if err != nil {
    36  		return nil, nil, err
    37  	}
    38  	var existing bool
    39  	if environInfo, err := store.ReadInfo(envName); !errors.IsNotFound(err) {
    40  		existing = true
    41  		logger.Warningf("ignoring environments.yaml: using bootstrap config in %s", environInfo.Location())
    42  	}
    43  	environ, err := environs.PrepareFromName(envName, ctx, store)
    44  	if err != nil {
    45  		return nil, nil, err
    46  	}
    47  	cleanup := func() {
    48  		if !existing {
    49  			destroyPreparedEnviron(ctx, environ, store, resultErr, action)
    50  		}
    51  	}
    52  	return environ, cleanup, nil
    53  }
    54  
    55  // resolveCharmURL returns a resolved charm URL, given a charm location string.
    56  // If the series is not resolved, the environment default-series is used, or if
    57  // not set, the series is resolved with the state server.
    58  func resolveCharmURL(url string, client *api.Client, conf *config.Config) (*charm.URL, error) {
    59  	ref, series, err := charm.ParseReference(url)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	// If series is not set, use configured default series
    64  	if series == "" {
    65  		if defaultSeries, ok := conf.DefaultSeries(); ok {
    66  			series = defaultSeries
    67  		}
    68  	}
    69  	// Otherwise, look up the best supported series for this charm
    70  	if series == "" {
    71  		if ref.Schema == "local" {
    72  			possibleUrl := &charm.URL{Reference: ref, Series: "precise"}
    73  			logger.Errorf(`The series is not specified in the environment (default-series) or with the charm. Did you mean:
    74  	%s`, possibleUrl.String())
    75  			return nil, fmt.Errorf("cannot resolve series for charm: %q", ref)
    76  		}
    77  		return client.ResolveCharm(ref)
    78  	}
    79  	return &charm.URL{Reference: ref, Series: series}, nil
    80  }