github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/user/logincontroller_test.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package user_test
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"net/http"
    10  	"net/http/httptest"
    11  	"os"
    12  	"strings"
    13  
    14  	"github.com/juju/cmd"
    15  	"github.com/juju/errors"
    16  	jc "github.com/juju/testing/checkers"
    17  	gc "gopkg.in/check.v1"
    18  	"gopkg.in/juju/names.v2"
    19  
    20  	"github.com/juju/juju/api"
    21  	"github.com/juju/juju/cmd/juju/user"
    22  	"github.com/juju/juju/cmd/modelcmd"
    23  	"github.com/juju/juju/jujuclient"
    24  	"github.com/juju/juju/testing"
    25  )
    26  
    27  func (s *LoginCommandSuite) TestLoginFromDirectory(c *gc.C) {
    28  	dirSrv := serveDirectory(map[string]string{
    29  		"bighost": "bighost.jujucharms.com:443",
    30  	})
    31  	defer dirSrv.Close()
    32  	os.Setenv("JUJU_DIRECTORY", dirSrv.URL)
    33  	s.apiConnection.authTag = names.NewUserTag("bob@external")
    34  	s.apiConnection.controllerAccess = "login"
    35  	stdout, stderr, code := s.run(c, "bighost")
    36  	c.Check(stderr, gc.Equals, `
    37  Welcome, bob@external. You are now logged into "bighost".
    38  `[1:]+user.NoModelsMessage)
    39  	c.Check(stdout, gc.Equals, "")
    40  	c.Assert(code, gc.Equals, 0)
    41  
    42  	// The controller and account details should be recorded with
    43  	// the specified controller name and user
    44  	// name from the auth tag.
    45  
    46  	controller, err := s.store.ControllerByName("bighost")
    47  	c.Assert(err, jc.ErrorIsNil)
    48  	c.Assert(controller, jc.DeepEquals, &jujuclient.ControllerDetails{
    49  		ControllerUUID: mockControllerUUID,
    50  		APIEndpoints:   []string{"bighost.jujucharms.com:443"},
    51  	})
    52  	account, err := s.store.AccountDetails("bighost")
    53  	c.Assert(err, jc.ErrorIsNil)
    54  	c.Assert(account, jc.DeepEquals, &jujuclient.AccountDetails{
    55  		User:            "bob@external",
    56  		LastKnownAccess: "login",
    57  	})
    58  
    59  	// Test that we can run the same command again and it works.
    60  	stdout, stderr, code = s.run(c, "bighost")
    61  	c.Check(code, gc.Equals, 0)
    62  	c.Check(stdout, gc.Equals, "")
    63  	c.Check(stderr, gc.Equals, "")
    64  }
    65  
    66  func (s *LoginCommandSuite) TestLoginPublicDNSName(c *gc.C) {
    67  	s.apiConnection.authTag = names.NewUserTag("bob@external")
    68  	s.apiConnection.controllerAccess = "login"
    69  	stdout, stderr, code := s.run(c, "0.1.2.3")
    70  	c.Check(stderr, gc.Equals, `
    71  Welcome, bob@external. You are now logged into "0.1.2.3".
    72  `[1:]+user.NoModelsMessage)
    73  	c.Check(stdout, gc.Equals, "")
    74  	c.Assert(code, gc.Equals, 0)
    75  
    76  	// The controller and account details should be recorded with
    77  	// the specified controller name and user
    78  	// name from the auth tag.
    79  	controller, err := s.store.ControllerByName("0.1.2.3")
    80  	c.Assert(err, jc.ErrorIsNil)
    81  	c.Assert(controller, jc.DeepEquals, &jujuclient.ControllerDetails{
    82  		ControllerUUID: mockControllerUUID,
    83  		APIEndpoints:   []string{"0.1.2.3:443"},
    84  	})
    85  	account, err := s.store.AccountDetails("0.1.2.3")
    86  	c.Assert(err, jc.ErrorIsNil)
    87  	c.Assert(account, jc.DeepEquals, &jujuclient.AccountDetails{
    88  		User:            "bob@external",
    89  		LastKnownAccess: "login",
    90  	})
    91  }
    92  
    93  func (s *LoginCommandSuite) TestRegisterPublicDNSNameWithPort(c *gc.C) {
    94  	s.apiConnection.authTag = names.NewUserTag("bob@external")
    95  	s.apiConnection.controllerAccess = "login"
    96  	stdout, stderr, code := s.run(c, "0.1.2.3:5678")
    97  	c.Check(stdout, gc.Equals, "")
    98  	c.Check(stderr, gc.Equals, "ERROR cannot use \"0.1.2.3:5678\" as a controller name - use -c option to choose a different one\n")
    99  	c.Check(code, gc.Equals, 1)
   100  }
   101  
   102  func (s *LoginCommandSuite) TestRegisterPublicDNSNameWithPortAndControllerFlag(c *gc.C) {
   103  	s.apiConnection.authTag = names.NewUserTag("bob@external")
   104  	s.apiConnection.controllerAccess = "login"
   105  	stdout, stderr, code := s.run(c, "-c", "foo", "0.1.2.3:5678")
   106  	c.Check(stdout, gc.Equals, "")
   107  	c.Check(stderr, gc.Equals, `
   108  Welcome, bob@external. You are now logged into "foo".
   109  `[1:]+user.NoModelsMessage)
   110  	c.Check(stdout, gc.Equals, "")
   111  	c.Assert(code, gc.Equals, 0)
   112  
   113  	// The controller and account details should be recorded with
   114  	// the specified controller name and user
   115  	// name from the auth tag.
   116  	controller, err := s.store.ControllerByName("foo")
   117  	c.Assert(err, jc.ErrorIsNil)
   118  	c.Assert(controller, jc.DeepEquals, &jujuclient.ControllerDetails{
   119  		ControllerUUID: mockControllerUUID,
   120  		APIEndpoints:   []string{"0.1.2.3:5678"},
   121  	})
   122  }
   123  
   124  func (s *LoginCommandSuite) TestRegisterPublicAPIOpenError(c *gc.C) {
   125  	srv := serveDirectory(map[string]string{"bighost": "https://0.1.2.3/directory"})
   126  	defer srv.Close()
   127  	os.Setenv("JUJU_DIRECTORY", srv.URL)
   128  	*user.APIOpen = func(c *modelcmd.CommandBase, info *api.Info, opts api.DialOpts) (api.Connection, error) {
   129  		return nil, errors.New("open failed")
   130  	}
   131  	stdout, stderr, code := s.run(c, "bighost")
   132  	c.Check(stdout, gc.Equals, "")
   133  	c.Check(stderr, gc.Matches, `ERROR cannot log into "bighost": open failed\n`)
   134  	c.Check(code, gc.Equals, 1)
   135  }
   136  
   137  func (s *LoginCommandSuite) TestRegisterPublicControllerMismatch(c *gc.C) {
   138  	srv := serveDirectory(map[string]string{"bighost": "https://0.1.2.3/directory"})
   139  	defer srv.Close()
   140  	os.Setenv("JUJU_DIRECTORY", srv.URL)
   141  	s.store.Controllers["other"] = jujuclient.ControllerDetails{
   142  		APIEndpoints:   []string{"0.1.2.3:123"},
   143  		CACert:         testing.CACert,
   144  		ControllerUUID: "00000000-1111-2222-3333-444444444444",
   145  	}
   146  	stdout, stderr, code := s.run(c, "-c", "other", "bighost")
   147  	c.Check(stdout, gc.Equals, "")
   148  	c.Check(stderr, gc.Matches, `
   149  ERROR controller at "bighost" does not match existing controller.
   150  Please choose a different controller name with the -c option, or
   151  use "juju unregister other" to remove the existing controller\.
   152  `[1:])
   153  	c.Check(code, gc.Equals, 1)
   154  }
   155  
   156  func (s *LoginCommandSuite) run(c *gc.C, args ...string) (stdout, stderr string, errCode int) {
   157  	var stdoutBuf, stderrBuf bytes.Buffer
   158  	ctxt := &cmd.Context{
   159  		Dir:    c.MkDir(),
   160  		Stdin:  strings.NewReader(""),
   161  		Stdout: &stdoutBuf,
   162  		Stderr: &stderrBuf,
   163  	}
   164  	exitCode := cmd.Main(user.NewLoginCommand(), ctxt, args)
   165  	return stdoutBuf.String(), stderrBuf.String(), exitCode
   166  }
   167  
   168  // loginMockAPIConnection implements just enough of the api.Connection interface
   169  // to satisfy the methods used by the login command.
   170  type loginMockAPI struct {
   171  	// This will be nil - it's just there to satisfy the api.Connection
   172  	// interface methods not explicitly defined by loginMockAPIConnection.
   173  	api.Connection
   174  
   175  	// controllerTag is returned by ControllerTag.
   176  	controllerTag names.ControllerTag
   177  
   178  	// authTag is returned by AuthTag.
   179  	authTag names.Tag
   180  
   181  	// controllerAccess is returned by ControllerAccess.
   182  	controllerAccess string
   183  }
   184  
   185  func (*loginMockAPI) Close() error {
   186  	return nil
   187  }
   188  
   189  func (m *loginMockAPI) ControllerTag() names.ControllerTag {
   190  	return m.controllerTag
   191  }
   192  
   193  func (m *loginMockAPI) AuthTag() names.Tag {
   194  	return m.authTag
   195  }
   196  
   197  func (m *loginMockAPI) ControllerAccess() string {
   198  	return m.controllerAccess
   199  }
   200  
   201  const mockControllerUUID = "df136476-12e9-11e4-8a70-b2227cce2b54"
   202  
   203  func serveDirectory(dir map[string]string) *httptest.Server {
   204  	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
   205  		name := strings.TrimPrefix(req.URL.Path, "/v1/controller/")
   206  		if name == req.URL.Path || dir[name] == "" {
   207  			http.NotFound(w, req)
   208  			return
   209  		}
   210  		w.Header().Set("Content-Type", "application/json")
   211  		fmt.Fprintf(w, `{"host":%q}`, dir[name])
   212  	}))
   213  }