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 }