github.com/thajeztah/cli@v0.0.0-20240223162942-dc6bfac81a8b/cli/command/registry/login_test.go (about)

     1  package registry
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"testing"
     8  
     9  	configtypes "github.com/docker/cli/cli/config/types"
    10  	"github.com/docker/cli/internal/test"
    11  	registrytypes "github.com/docker/docker/api/types/registry"
    12  	"github.com/docker/docker/api/types/system"
    13  	"github.com/docker/docker/client"
    14  	"gotest.tools/v3/assert"
    15  	is "gotest.tools/v3/assert/cmp"
    16  	"gotest.tools/v3/fs"
    17  )
    18  
    19  const (
    20  	unknownUser     = "userunknownError"
    21  	errUnknownUser  = "UNKNOWN_ERR"
    22  	expiredPassword = "I_M_EXPIRED"
    23  	useToken        = "I_M_TOKEN"
    24  )
    25  
    26  type fakeClient struct {
    27  	client.Client
    28  }
    29  
    30  func (c fakeClient) Info(context.Context) (system.Info, error) {
    31  	return system.Info{}, nil
    32  }
    33  
    34  func (c fakeClient) RegistryLogin(_ context.Context, auth registrytypes.AuthConfig) (registrytypes.AuthenticateOKBody, error) {
    35  	if auth.Password == expiredPassword {
    36  		return registrytypes.AuthenticateOKBody{}, fmt.Errorf("Invalid Username or Password")
    37  	}
    38  	if auth.Password == useToken {
    39  		return registrytypes.AuthenticateOKBody{
    40  			IdentityToken: auth.Password,
    41  		}, nil
    42  	}
    43  	if auth.Username == unknownUser {
    44  		return registrytypes.AuthenticateOKBody{}, fmt.Errorf(errUnknownUser)
    45  	}
    46  	return registrytypes.AuthenticateOKBody{}, nil
    47  }
    48  
    49  func TestLoginWithCredStoreCreds(t *testing.T) {
    50  	testCases := []struct {
    51  		inputAuthConfig registrytypes.AuthConfig
    52  		expectedMsg     string
    53  		expectedErr     string
    54  	}{
    55  		{
    56  			inputAuthConfig: registrytypes.AuthConfig{},
    57  			expectedMsg:     "Authenticating with existing credentials...\n",
    58  		},
    59  		{
    60  			inputAuthConfig: registrytypes.AuthConfig{
    61  				Username: unknownUser,
    62  			},
    63  			expectedMsg: "Authenticating with existing credentials...\n",
    64  			expectedErr: fmt.Sprintf("Login did not succeed, error: %s\n", errUnknownUser),
    65  		},
    66  	}
    67  	ctx := context.Background()
    68  	for _, tc := range testCases {
    69  		cli := test.NewFakeCli(&fakeClient{})
    70  		errBuf := new(bytes.Buffer)
    71  		cli.SetErr(errBuf)
    72  		loginWithCredStoreCreds(ctx, cli, &tc.inputAuthConfig)
    73  		outputString := cli.OutBuffer().String()
    74  		assert.Check(t, is.Equal(tc.expectedMsg, outputString))
    75  		errorString := errBuf.String()
    76  		assert.Check(t, is.Equal(tc.expectedErr, errorString))
    77  	}
    78  }
    79  
    80  func TestRunLogin(t *testing.T) {
    81  	const (
    82  		storedServerAddress = "reg1"
    83  		validUsername       = "u1"
    84  		validPassword       = "p1"
    85  		validPassword2      = "p2"
    86  	)
    87  
    88  	validAuthConfig := configtypes.AuthConfig{
    89  		ServerAddress: storedServerAddress,
    90  		Username:      validUsername,
    91  		Password:      validPassword,
    92  	}
    93  	expiredAuthConfig := configtypes.AuthConfig{
    94  		ServerAddress: storedServerAddress,
    95  		Username:      validUsername,
    96  		Password:      expiredPassword,
    97  	}
    98  	validIdentityToken := configtypes.AuthConfig{
    99  		ServerAddress: storedServerAddress,
   100  		Username:      validUsername,
   101  		IdentityToken: useToken,
   102  	}
   103  	testCases := []struct {
   104  		doc               string
   105  		inputLoginOption  loginOptions
   106  		inputStoredCred   *configtypes.AuthConfig
   107  		expectedErr       string
   108  		expectedSavedCred configtypes.AuthConfig
   109  	}{
   110  		{
   111  			doc: "valid auth from store",
   112  			inputLoginOption: loginOptions{
   113  				serverAddress: storedServerAddress,
   114  			},
   115  			inputStoredCred:   &validAuthConfig,
   116  			expectedSavedCred: validAuthConfig,
   117  		},
   118  		{
   119  			doc: "expired auth",
   120  			inputLoginOption: loginOptions{
   121  				serverAddress: storedServerAddress,
   122  			},
   123  			inputStoredCred: &expiredAuthConfig,
   124  			expectedErr:     "Error: Cannot perform an interactive login from a non TTY device",
   125  		},
   126  		{
   127  			doc: "valid username and password",
   128  			inputLoginOption: loginOptions{
   129  				serverAddress: storedServerAddress,
   130  				user:          validUsername,
   131  				password:      validPassword2,
   132  			},
   133  			inputStoredCred: &validAuthConfig,
   134  			expectedSavedCred: configtypes.AuthConfig{
   135  				ServerAddress: storedServerAddress,
   136  				Username:      validUsername,
   137  				Password:      validPassword2,
   138  			},
   139  		},
   140  		{
   141  			doc: "unknown user",
   142  			inputLoginOption: loginOptions{
   143  				serverAddress: storedServerAddress,
   144  				user:          unknownUser,
   145  				password:      validPassword,
   146  			},
   147  			inputStoredCred: &validAuthConfig,
   148  			expectedErr:     errUnknownUser,
   149  		},
   150  		{
   151  			doc: "valid token",
   152  			inputLoginOption: loginOptions{
   153  				serverAddress: storedServerAddress,
   154  				user:          validUsername,
   155  				password:      useToken,
   156  			},
   157  			inputStoredCred:   &validIdentityToken,
   158  			expectedSavedCred: validIdentityToken,
   159  		},
   160  	}
   161  	for _, tc := range testCases {
   162  		tc := tc
   163  		t.Run(tc.doc, func(t *testing.T) {
   164  			tmpFile := fs.NewFile(t, "test-run-login")
   165  			defer tmpFile.Remove()
   166  			cli := test.NewFakeCli(&fakeClient{})
   167  			configfile := cli.ConfigFile()
   168  			configfile.Filename = tmpFile.Path()
   169  
   170  			if tc.inputStoredCred != nil {
   171  				cred := *tc.inputStoredCred
   172  				assert.NilError(t, configfile.GetCredentialsStore(cred.ServerAddress).Store(cred))
   173  			}
   174  			loginErr := runLogin(context.Background(), cli, tc.inputLoginOption)
   175  			if tc.expectedErr != "" {
   176  				assert.Error(t, loginErr, tc.expectedErr)
   177  				return
   178  			}
   179  			assert.NilError(t, loginErr)
   180  			savedCred, credStoreErr := configfile.GetCredentialsStore(tc.inputStoredCred.ServerAddress).Get(tc.inputStoredCred.ServerAddress)
   181  			assert.Check(t, credStoreErr)
   182  			assert.DeepEqual(t, tc.expectedSavedCred, savedCred)
   183  		})
   184  	}
   185  }