github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/commands/bootstrap_clouds.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package commands
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"sort"
    10  	"strings"
    11  	"text/tabwriter"
    12  
    13  	"github.com/juju/cmd"
    14  	"github.com/juju/errors"
    15  
    16  	jujucloud "github.com/juju/juju/cloud"
    17  	"github.com/juju/juju/cmd/juju/common"
    18  	"github.com/juju/juju/jujuclient"
    19  )
    20  
    21  type cloudList struct {
    22  	public   []string
    23  	builtin  []string
    24  	personal []string
    25  }
    26  
    27  func formatCloudDetailsTabular(clouds cloudList, credStore jujuclient.CredentialStore) ([]byte, error) {
    28  	var out bytes.Buffer
    29  	const (
    30  		// To format things into columns.
    31  		minwidth = 0
    32  		tabwidth = 1
    33  		padding  = 2
    34  		padchar  = ' '
    35  		flags    = 0
    36  	)
    37  	tw := tabwriter.NewWriter(&out, minwidth, tabwidth, padding, padchar, flags)
    38  	p := func(values ...string) {
    39  		text := strings.Join(values, "\t")
    40  		fmt.Fprintln(tw, text)
    41  	}
    42  	p("Cloud\tCredentials\tDefault Region")
    43  	printClouds := func(cloudNames []string) error {
    44  		sort.Strings(cloudNames)
    45  		for _, name := range cloudNames {
    46  			cred, err := credStore.CredentialForCloud(name)
    47  			if err != nil && !errors.IsNotFound(err) {
    48  				return errors.Annotatef(err, "error loading credential for cloud %q", name)
    49  			}
    50  			if err != nil || len(cred.AuthCredentials) == 0 {
    51  				p(name, "", "")
    52  				continue
    53  			}
    54  			var sortedCredNames []string
    55  			for credName := range cred.AuthCredentials {
    56  				sortedCredNames = append(sortedCredNames, credName)
    57  			}
    58  			sort.Strings(sortedCredNames)
    59  			for i, credName := range sortedCredNames {
    60  				if i == 0 {
    61  					p(name, credName, cred.DefaultRegion)
    62  				} else {
    63  					p("", credName, "")
    64  				}
    65  				i++
    66  			}
    67  		}
    68  		return nil
    69  	}
    70  	if err := printClouds(clouds.public); err != nil {
    71  		return nil, err
    72  	}
    73  	if err := printClouds(clouds.builtin); err != nil {
    74  		return nil, err
    75  	}
    76  	if err := printClouds(clouds.personal); err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	tw.Flush()
    81  	return out.Bytes(), nil
    82  }
    83  
    84  func printClouds(ctx *cmd.Context, credStore jujuclient.CredentialStore) error {
    85  	publicClouds, _, err := jujucloud.PublicCloudMetadata(jujucloud.JujuPublicCloudsPath())
    86  	if err != nil {
    87  		return err
    88  	}
    89  
    90  	personalClouds, err := jujucloud.PersonalCloudMetadata()
    91  	if err != nil {
    92  		return err
    93  	}
    94  
    95  	fmt.Fprintln(ctx.Stdout, "You can bootstrap on these clouds. See ‘--regions <cloud>’ for all regions.")
    96  	clouds := cloudList{}
    97  	for name := range publicClouds {
    98  		clouds.public = append(clouds.public, name)
    99  	}
   100  	// Add in built in clouds like localhost (lxd).
   101  	for name := range common.BuiltInClouds() {
   102  		clouds.builtin = append(clouds.builtin, name)
   103  	}
   104  	for name := range personalClouds {
   105  		clouds.personal = append(clouds.personal, name)
   106  	}
   107  	out, err := formatCloudDetailsTabular(clouds, credStore)
   108  	if err != nil {
   109  		return err
   110  	}
   111  	fmt.Fprintln(ctx.Stdout, string(out))
   112  	credHelpText := `
   113  You will need to have a credential if you want to bootstrap on a cloud, see
   114  ‘juju autoload-credentials’ and ‘juju add-credential’. The first credential
   115  listed is the default. Add more clouds with ‘juju add-cloud’.
   116  `
   117  	fmt.Fprintf(ctx.Stdout, credHelpText[1:])
   118  	return nil
   119  }
   120  
   121  func printCloudRegions(ctx *cmd.Context, cloudName string) error {
   122  	cloud, err := jujucloud.CloudByName(cloudName)
   123  	if err != nil {
   124  		return err
   125  	}
   126  	fmt.Fprintf(ctx.Stdout, "Showing regions for %s:\n", cloudName)
   127  	for _, region := range cloud.Regions {
   128  		fmt.Fprintln(ctx.Stdout, region.Name)
   129  	}
   130  	return nil
   131  }