github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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  	builtin, err := common.BuiltInClouds()
   102  	if err != nil {
   103  		return errors.Trace(err)
   104  	}
   105  	for name := range builtin {
   106  		clouds.builtin = append(clouds.builtin, name)
   107  	}
   108  	for name := range personalClouds {
   109  		clouds.personal = append(clouds.personal, name)
   110  	}
   111  	out, err := formatCloudDetailsTabular(clouds, credStore)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	fmt.Fprintln(ctx.Stdout, string(out))
   116  	credHelpText := `
   117  You will need to have a credential if you want to bootstrap on a cloud, see
   118  ‘juju autoload-credentials’ and ‘juju add-credential’. The first credential
   119  listed is the default. Add more clouds with ‘juju add-cloud’.
   120  `
   121  	fmt.Fprintf(ctx.Stdout, credHelpText[1:])
   122  	return nil
   123  }
   124  
   125  func printCloudRegions(ctx *cmd.Context, cloudName string) error {
   126  	cloud, err := common.CloudByName(cloudName)
   127  	if err != nil {
   128  		return errors.Trace(err)
   129  	}
   130  	fmt.Fprintf(ctx.Stdout, "Showing regions for %s:\n", cloudName)
   131  	for _, region := range cloud.Regions {
   132  		fmt.Fprintln(ctx.Stdout, region.Name)
   133  	}
   134  	return nil
   135  }