github.com/mwhudson/juju@v0.0.0-20160512215208-90ff01f3497f/cmd/juju/cloud/detectcredentials_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package cloud_test
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"regexp"
    10  	"strings"
    11  
    12  	"github.com/juju/cmd"
    13  	"github.com/juju/errors"
    14  	jc "github.com/juju/testing/checkers"
    15  	gc "gopkg.in/check.v1"
    16  
    17  	jujucloud "github.com/juju/juju/cloud"
    18  	"github.com/juju/juju/cmd/juju/cloud"
    19  	"github.com/juju/juju/environs"
    20  	"github.com/juju/juju/jujuclient/jujuclienttesting"
    21  	"github.com/juju/juju/testing"
    22  )
    23  
    24  type detectCredentialsSuite struct {
    25  	store       *jujuclienttesting.MemStore
    26  	aCredential jujucloud.CloudCredential
    27  }
    28  
    29  var _ = gc.Suite(&detectCredentialsSuite{})
    30  
    31  type mockProvider struct {
    32  	environs.EnvironProvider
    33  	detectedCreds *jujucloud.CloudCredential
    34  	credSchemas   *map[jujucloud.AuthType]jujucloud.CredentialSchema
    35  }
    36  
    37  func (p *mockProvider) DetectCredentials() (*jujucloud.CloudCredential, error) {
    38  	if len(p.detectedCreds.AuthCredentials) == 0 {
    39  		return nil, errors.NotFoundf("credentials")
    40  	}
    41  	return p.detectedCreds, nil
    42  }
    43  
    44  func (p *mockProvider) CredentialSchemas() map[jujucloud.AuthType]jujucloud.CredentialSchema {
    45  	if p.credSchemas == nil {
    46  		return map[jujucloud.AuthType]jujucloud.CredentialSchema{
    47  			jujucloud.AccessKeyAuthType: {
    48  				{
    49  					"access-key", jujucloud.CredentialAttr{},
    50  				}, {
    51  					"secret-key", jujucloud.CredentialAttr{Hidden: true},
    52  				},
    53  			},
    54  			jujucloud.UserPassAuthType: {
    55  				{
    56  					"username", jujucloud.CredentialAttr{},
    57  				}, {
    58  					"password", jujucloud.CredentialAttr{Hidden: true},
    59  				}, {
    60  					"application-password", jujucloud.CredentialAttr{Hidden: true},
    61  				},
    62  			},
    63  			jujucloud.OAuth2AuthType: {
    64  				{
    65  					"client-id", jujucloud.CredentialAttr{},
    66  				}, {
    67  					"client-email", jujucloud.CredentialAttr{},
    68  				}, {
    69  					"private-key", jujucloud.CredentialAttr{Hidden: true},
    70  				}, {
    71  					"project-id", jujucloud.CredentialAttr{},
    72  				},
    73  			},
    74  		}
    75  	}
    76  	return *p.credSchemas
    77  }
    78  
    79  func (s *detectCredentialsSuite) SetUpSuite(c *gc.C) {
    80  	environs.RegisterProvider("mock-provider", &mockProvider{detectedCreds: &s.aCredential})
    81  }
    82  
    83  func (s *detectCredentialsSuite) SetUpTest(c *gc.C) {
    84  	s.store = jujuclienttesting.NewMemStore()
    85  	s.aCredential = jujucloud.CloudCredential{}
    86  }
    87  
    88  func (s *detectCredentialsSuite) run(c *gc.C, stdin io.Reader, clouds map[string]jujucloud.Cloud) (*cmd.Context, error) {
    89  	registeredProvidersFunc := func() []string {
    90  		return []string{"mock-provider"}
    91  	}
    92  	allCloudsFunc := func() (map[string]jujucloud.Cloud, error) {
    93  		return clouds, nil
    94  	}
    95  	cloudByNameFunc := func(cloudName string) (*jujucloud.Cloud, error) {
    96  		if cloud, ok := clouds[cloudName]; ok {
    97  			return &cloud, nil
    98  		}
    99  		return nil, errors.NotFoundf("cloud %s", cloudName)
   100  	}
   101  	command := cloud.NewDetectCredentialsCommandForTest(s.store, registeredProvidersFunc, allCloudsFunc, cloudByNameFunc)
   102  	err := testing.InitCommand(command, nil)
   103  	c.Assert(err, jc.ErrorIsNil)
   104  	ctx := testing.Context(c)
   105  	ctx.Stdin = stdin
   106  	return ctx, command.Run(ctx)
   107  }
   108  
   109  func (s *detectCredentialsSuite) credentialWithLabel(authType jujucloud.AuthType, label string) jujucloud.Credential {
   110  	cred := jujucloud.NewCredential(authType, nil)
   111  	cred.Label = label
   112  	return cred
   113  }
   114  
   115  func (s *detectCredentialsSuite) assertDetectCredential(c *gc.C, cloudName, expectedRegion, errText string) {
   116  	s.aCredential = jujucloud.CloudCredential{
   117  		DefaultRegion: "default region",
   118  		AuthCredentials: map[string]jujucloud.Credential{
   119  			"test": s.credentialWithLabel(jujucloud.AccessKeyAuthType, "credential")},
   120  	}
   121  	clouds := map[string]jujucloud.Cloud{
   122  		"test-cloud": {
   123  			Type: "mock-provider",
   124  		},
   125  		"another-cloud": {
   126  			Type: "another-provider",
   127  		},
   128  	}
   129  
   130  	stdin := strings.NewReader(fmt.Sprintf("1\n%s\nQ\n", cloudName))
   131  	ctx, err := s.run(c, stdin, clouds)
   132  	c.Assert(err, jc.ErrorIsNil)
   133  	if errText == "" {
   134  		if expectedRegion != "" {
   135  			s.aCredential.DefaultRegion = expectedRegion
   136  		}
   137  		c.Assert(s.store.Credentials["test-cloud"], jc.DeepEquals, s.aCredential)
   138  	} else {
   139  		output := strings.Replace(testing.Stderr(ctx), "\n", "", -1)
   140  		c.Assert(output, gc.Matches, ".*"+regexp.QuoteMeta(errText)+".*")
   141  	}
   142  }
   143  
   144  func (s *detectCredentialsSuite) TestDetectNewCredential(c *gc.C) {
   145  	s.assertDetectCredential(c, "test-cloud", "", "")
   146  }
   147  
   148  func (s *detectCredentialsSuite) TestDetectCredentialOverwrites(c *gc.C) {
   149  	s.store.Credentials = map[string]jujucloud.CloudCredential{
   150  		"test-cloud": {
   151  			AuthCredentials: map[string]jujucloud.Credential{
   152  				"test": jujucloud.NewCredential(jujucloud.AccessKeyAuthType, nil),
   153  			},
   154  		},
   155  	}
   156  	s.assertDetectCredential(c, "test-cloud", "", "")
   157  }
   158  
   159  func (s *detectCredentialsSuite) TestDetectCredentialKeepsExistingRegion(c *gc.C) {
   160  	s.store.Credentials = map[string]jujucloud.CloudCredential{
   161  		"test-cloud": {
   162  			DefaultRegion: "west",
   163  			AuthCredentials: map[string]jujucloud.Credential{
   164  				"test": jujucloud.NewCredential(jujucloud.AccessKeyAuthType, nil),
   165  			},
   166  		},
   167  	}
   168  	s.assertDetectCredential(c, "test-cloud", "west", "")
   169  }
   170  
   171  func (s *detectCredentialsSuite) TestDetectCredentialDefaultCloud(c *gc.C) {
   172  	s.assertDetectCredential(c, "", "", "")
   173  }
   174  
   175  func (s *detectCredentialsSuite) TestDetectCredentialUnknownCloud(c *gc.C) {
   176  	s.assertDetectCredential(c, "foo", "", "cloud foo not valid")
   177  }
   178  
   179  func (s *detectCredentialsSuite) TestDetectCredentialInvalidCloud(c *gc.C) {
   180  	s.assertDetectCredential(c, "another-cloud", "", "chosen credentials not compatible with a another-provider cloud")
   181  }
   182  
   183  func (s *detectCredentialsSuite) TestNewDetectCredentialNoneFound(c *gc.C) {
   184  	stdin := strings.NewReader("")
   185  	ctx, err := s.run(c, stdin, nil)
   186  	c.Assert(err, jc.ErrorIsNil)
   187  	output := strings.Replace(testing.Stderr(ctx), "\n", "", -1)
   188  	c.Assert(output, gc.Matches, ".*No cloud credentials found.*")
   189  	c.Assert(s.store.Credentials, gc.HasLen, 0)
   190  }
   191  
   192  func (s *detectCredentialsSuite) TestDetectCredentialInvalidChoice(c *gc.C) {
   193  	s.aCredential = jujucloud.CloudCredential{
   194  		DefaultRegion: "detected region",
   195  		AuthCredentials: map[string]jujucloud.Credential{
   196  			"test":    s.credentialWithLabel(jujucloud.AccessKeyAuthType, "credential 1"),
   197  			"another": s.credentialWithLabel(jujucloud.AccessKeyAuthType, "credential 2")},
   198  	}
   199  
   200  	stdin := strings.NewReader("3\nQ\n")
   201  	ctx, err := s.run(c, stdin, nil)
   202  	c.Assert(err, jc.ErrorIsNil)
   203  	output := strings.Replace(testing.Stderr(ctx), "\n", "", -1)
   204  	c.Assert(output, gc.Matches, ".*Invalid choice, enter a number between 1 and 2.*")
   205  	c.Assert(s.store.Credentials, gc.HasLen, 0)
   206  }