github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/trust/revoke_test.go (about)

     1  package trust
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"testing"
     7  
     8  	"github.com/docker/cli/cli/trust"
     9  	"github.com/docker/cli/internal/test"
    10  	"github.com/docker/cli/internal/test/notary"
    11  	"github.com/theupdateframework/notary/client"
    12  	"github.com/theupdateframework/notary/passphrase"
    13  	"github.com/theupdateframework/notary/trustpinning"
    14  	"gotest.tools/v3/assert"
    15  	is "gotest.tools/v3/assert/cmp"
    16  	"gotest.tools/v3/golden"
    17  )
    18  
    19  func TestTrustRevokeCommandErrors(t *testing.T) {
    20  	testCases := []struct {
    21  		name          string
    22  		args          []string
    23  		expectedError string
    24  	}{
    25  		{
    26  			name:          "not-enough-args",
    27  			expectedError: "requires exactly 1 argument",
    28  		},
    29  		{
    30  			name:          "too-many-args",
    31  			args:          []string{"remote1", "remote2"},
    32  			expectedError: "requires exactly 1 argument",
    33  		},
    34  		{
    35  			name:          "sha-reference",
    36  			args:          []string{"870d292919d01a0af7e7f056271dc78792c05f55f49b9b9012b6d89725bd9abd"},
    37  			expectedError: "invalid repository name",
    38  		},
    39  		{
    40  			name:          "invalid-img-reference",
    41  			args:          []string{"ALPINE"},
    42  			expectedError: "invalid reference format",
    43  		},
    44  		{
    45  			name:          "digest-reference",
    46  			args:          []string{"ubuntu@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2"},
    47  			expectedError: "cannot use a digest reference for IMAGE:TAG",
    48  		},
    49  	}
    50  	for _, tc := range testCases {
    51  		cmd := newRevokeCommand(
    52  			test.NewFakeCli(&fakeClient{}))
    53  		cmd.SetArgs(tc.args)
    54  		cmd.SetOut(io.Discard)
    55  		assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
    56  	}
    57  }
    58  
    59  func TestTrustRevokeCommand(t *testing.T) {
    60  	revokeCancelledError := "trust revoke has been cancelled"
    61  
    62  	testCases := []struct {
    63  		doc              string
    64  		notaryRepository func(trust.ImageRefAndAuth, []string) (client.Repository, error)
    65  		args             []string
    66  		expectedErr      string
    67  		expectedMessage  string
    68  	}{
    69  		{
    70  			doc:              "OfflineErrors_Confirm",
    71  			notaryRepository: notary.GetOfflineNotaryRepository,
    72  			args:             []string{"reg-name.io/image"},
    73  			expectedMessage:  "Please confirm you would like to delete all signature data for reg-name.io/image? [y/N] ",
    74  			expectedErr:      revokeCancelledError,
    75  		},
    76  		{
    77  			doc:              "OfflineErrors_Offline",
    78  			notaryRepository: notary.GetOfflineNotaryRepository,
    79  			args:             []string{"reg-name.io/image", "-y"},
    80  			expectedErr:      "could not remove signature for reg-name.io/image: client is offline",
    81  		},
    82  		{
    83  			doc:              "OfflineErrors_WithTag_Offline",
    84  			notaryRepository: notary.GetOfflineNotaryRepository,
    85  			args:             []string{"reg-name.io/image:tag"},
    86  			expectedErr:      "could not remove signature for reg-name.io/image:tag: client is offline",
    87  		},
    88  		{
    89  			doc:              "UninitializedErrors_Confirm",
    90  			notaryRepository: notary.GetUninitializedNotaryRepository,
    91  			args:             []string{"reg-name.io/image"},
    92  			expectedMessage:  "Please confirm you would like to delete all signature data for reg-name.io/image? [y/N] ",
    93  			expectedErr:      revokeCancelledError,
    94  		},
    95  		{
    96  			doc:              "UninitializedErrors_NoTrustData",
    97  			notaryRepository: notary.GetUninitializedNotaryRepository,
    98  			args:             []string{"reg-name.io/image", "-y"},
    99  			expectedErr:      "could not remove signature for reg-name.io/image:  does not have trust data for",
   100  		},
   101  		{
   102  			doc:              "UninitializedErrors_WithTag_NoTrustData",
   103  			notaryRepository: notary.GetUninitializedNotaryRepository,
   104  			args:             []string{"reg-name.io/image:tag"},
   105  			expectedErr:      "could not remove signature for reg-name.io/image:tag:  does not have trust data for",
   106  		},
   107  		{
   108  			doc:              "EmptyNotaryRepo_Confirm",
   109  			notaryRepository: notary.GetEmptyTargetsNotaryRepository,
   110  			args:             []string{"reg-name.io/image"},
   111  			expectedMessage:  "Please confirm you would like to delete all signature data for reg-name.io/image? [y/N] ",
   112  			expectedErr:      revokeCancelledError,
   113  		},
   114  		{
   115  			doc:              "EmptyNotaryRepo_NoSignedTags",
   116  			notaryRepository: notary.GetEmptyTargetsNotaryRepository,
   117  			args:             []string{"reg-name.io/image", "-y"},
   118  			expectedErr:      "could not remove signature for reg-name.io/image: no signed tags to remove",
   119  		},
   120  		{
   121  			doc:              "EmptyNotaryRepo_NoValidTrustData",
   122  			notaryRepository: notary.GetEmptyTargetsNotaryRepository,
   123  			args:             []string{"reg-name.io/image:tag"},
   124  			expectedErr:      "could not remove signature for reg-name.io/image:tag: No valid trust data for tag",
   125  		},
   126  		{
   127  			doc:              "AllSigConfirmation",
   128  			notaryRepository: notary.GetEmptyTargetsNotaryRepository,
   129  			args:             []string{"alpine"},
   130  			expectedMessage:  "Please confirm you would like to delete all signature data for alpine? [y/N] ",
   131  			expectedErr:      revokeCancelledError,
   132  		},
   133  	}
   134  
   135  	for _, tc := range testCases {
   136  		t.Run(tc.doc, func(t *testing.T) {
   137  			cli := test.NewFakeCli(&fakeClient{})
   138  			cli.SetNotaryClient(tc.notaryRepository)
   139  			cmd := newRevokeCommand(cli)
   140  			cmd.SetArgs(tc.args)
   141  			cmd.SetOut(io.Discard)
   142  			if tc.expectedErr != "" {
   143  				assert.ErrorContains(t, cmd.Execute(), tc.expectedErr)
   144  			} else {
   145  				assert.NilError(t, cmd.Execute())
   146  			}
   147  			assert.Check(t, is.Contains(cli.OutBuffer().String(), tc.expectedMessage))
   148  		})
   149  	}
   150  }
   151  
   152  func TestGetSignableRolesForTargetAndRemoveError(t *testing.T) {
   153  	notaryRepo, err := client.NewFileCachedRepository(t.TempDir(), "gun", "https://localhost", nil, passphrase.ConstantRetriever("password"), trustpinning.TrustPinConfig{})
   154  	assert.NilError(t, err)
   155  	target := client.Target{}
   156  	err = getSignableRolesForTargetAndRemove(target, notaryRepo)
   157  	assert.Error(t, err, "client is offline")
   158  }
   159  
   160  func TestRevokeTrustPromptTermination(t *testing.T) {
   161  	ctx, cancel := context.WithCancel(context.Background())
   162  	t.Cleanup(cancel)
   163  
   164  	cli := test.NewFakeCli(&fakeClient{})
   165  	cmd := newRevokeCommand(cli)
   166  	cmd.SetArgs([]string{"example/trust-demo"})
   167  	test.TerminatePrompt(ctx, t, cmd, cli)
   168  	golden.Assert(t, cli.OutBuffer().String(), "trust-revoke-prompt-termination.golden")
   169  }