Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions cmd/notation/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,16 @@ func runLogin(ctx context.Context, opts *loginOpts) error {
cred := opts.Credential()
credsStore, err := auth.NewCredentialsStore()
if err != nil {
return fmt.Errorf("failed to get credentials store: %v", err)
return fmt.Errorf("failed to get credentials store: %w", err)
}
registry, err := getRegistryLoginClient(ctx, &opts.SecureFlagOpts, serverAddress)
if err != nil {
return fmt.Errorf("failed to get registry client: %v", err)
return fmt.Errorf("failed to get registry client: %w", err)
}
if err := credentials.Login(ctx, credsStore, registry, cred); err != nil {
registryName := registry.Reference.Registry
if !errors.Is(err, credentials.ErrPlaintextPutDisabled) {
return fmt.Errorf("failed to log in to %s: %v", registryName, err)
return fmt.Errorf("failed to log in to %s: %w", registryName, err)
}

// ErrPlaintextPutDisabled returned by Login() indicates that the
Expand Down
59 changes: 59 additions & 0 deletions cmd/notation/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@
package main

import (
"context"
"errors"
"os"
"path/filepath"
"testing"

"github.com/notaryproject/notation-go/dir"
"github.com/notaryproject/notation/v2/cmd/notation/internal/flag"
)

Expand Down Expand Up @@ -102,3 +106,58 @@ func TestLoginCommand_MissingArgs(t *testing.T) {
t.Fatal("Parse Args expected error, but ok")
}
}

// setTestConfigDir points the notation config directory to a temporary directory
// with the given config.json content.
func setTestConfigDir(t *testing.T, config string) {
t.Helper()
oldConfigDir := dir.UserConfigDir
t.Cleanup(func() { dir.UserConfigDir = oldConfigDir })
dir.UserConfigDir = t.TempDir()
if err := os.WriteFile(filepath.Join(dir.UserConfigDir, dir.PathConfigFile), []byte(config), 0o600); err != nil {
t.Fatalf("failed to write config file: %v", err)
}
}

// The errors returned by runLogin have to wrap the underlying error so that
// callers can inspect it with errors.Is and errors.As.
func TestRunLogin_WrapsErrors(t *testing.T) {
tests := []struct {
name string
config string
server string
}{
{
name: "invalid credentials store config",
config: "{",
server: "registry.example.com",
},
{
name: "invalid registry",
config: "{}",
server: "invalid host name",
},
{
// nothing listens on port 1, so the connection is refused
name: "registry not reachable",
config: "{}",
server: "localhost:1",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
setTestConfigDir(t, tt.config)
opts := &loginOpts{server: tt.server}
opts.Username = "user"
opts.Password = "password"

err := runLogin(context.Background(), opts)
if err == nil {
t.Fatal("runLogin() expected an error, but got nil")
}
if errors.Unwrap(err) == nil {
t.Fatalf("runLogin() error does not wrap the underlying error: %v", err)
}
})
}
}
4 changes: 2 additions & 2 deletions cmd/notation/logout.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ func runLogout(ctx context.Context, opts *logoutOpts) error {
ctx = opts.LoggingFlagOpts.InitializeLogger(ctx)
credsStore, err := auth.NewCredentialsStore()
if err != nil {
return fmt.Errorf("failed to get credentials store: %v", err)
return fmt.Errorf("failed to get credentials store: %w", err)
}
if err := credentials.Logout(ctx, credsStore, opts.server); err != nil {
return fmt.Errorf("failed to log out of %s: %v", opts.server, err)
return fmt.Errorf("failed to log out of %s: %w", opts.server, err)
}

fmt.Println("Logout Succeeded")
Expand Down
34 changes: 33 additions & 1 deletion cmd/notation/logout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@

package main

import "testing"
import (
"context"
"errors"
"testing"
)

func TestLogoutCommand_BasicArgs(t *testing.T) {
opts := &logoutOpts{}
Expand Down Expand Up @@ -43,3 +47,31 @@ func TestLogOutCommand_MissingArgs(t *testing.T) {
t.Fatal("Parse Args expected error, but ok")
}
}

// The errors returned by runLogout have to wrap the underlying error so that
// callers can inspect it with errors.Is and errors.As.
func TestRunLogout_WrapsErrors(t *testing.T) {
t.Run("invalid credentials store config", func(t *testing.T) {
setTestConfigDir(t, "{")

err := runLogout(context.Background(), &logoutOpts{server: "registry.example.com"})
if err == nil {
t.Fatal("runLogout() expected an error, but got nil")
}
if errors.Unwrap(err) == nil {
t.Fatalf("runLogout() error does not wrap the underlying error: %v", err)
}
})

t.Run("credentials not found", func(t *testing.T) {
setTestConfigDir(t, "{}")

err := runLogout(context.Background(), &logoutOpts{server: "registry.example.com"})
if err == nil {
t.Skip("logging out of an unknown registry does not fail on this platform")
}
if errors.Unwrap(err) == nil {
t.Fatalf("runLogout() error does not wrap the underlying error: %v", err)
}
})
}
Loading