Skip to content

Commit

Permalink
Merge pull request #959 from docker/notary-reset-cmd
Browse files Browse the repository at this point in the history
Introduce `notary reset` command from `notary status` flags
  • Loading branch information
endophage authored Sep 16, 2016
2 parents 06e14b3 + 360c691 commit 7ab58e5
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 30 deletions.
4 changes: 2 additions & 2 deletions cmd/notary/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1600,7 +1600,7 @@ func TestWitness(t *testing.T) {
// 12. check non-targets base roles all fail
for _, role := range []string{data.CanonicalRootRole, data.CanonicalSnapshotRole, data.CanonicalTimestampRole} {
// clear any pending changes to ensure errors are only related to the specific role we're trying to witness
_, err = runCommand(t, tempDir, "status", "gun", "--reset")
_, err = runCommand(t, tempDir, "reset", "gun", "--all")
require.NoError(t, err)

_, err = runCommand(t, tempDir, "witness", "gun", role)
Expand All @@ -1613,7 +1613,7 @@ func TestWitness(t *testing.T) {
// 13. test auto-publish functionality (just for witness)

// purge the old staged witness
_, err = runCommand(t, tempDir, "status", "gun", "--reset")
_, err = runCommand(t, tempDir, "reset", "gun", "--all")
require.NoError(t, err)

// remove key2 and add back key1
Expand Down
1 change: 1 addition & 0 deletions cmd/notary/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ var exampleValidCommands = []string{
"init repo",
"list repo",
"status repo",
"reset repo --all",
"publish repo",
"add repo v1 somefile",
"addhash repo targetv1 --sha256 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 10",
Expand Down
64 changes: 51 additions & 13 deletions cmd/notary/tuf.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ var cmdTUFStatusTemplate = usageTemplate{
Long: "Displays status of unpublished changes to the local trusted collection identified by the Globally Unique Name.",
}

var cmdTUFResetTemplate = usageTemplate{
Use: "reset [ GUN ]",
Short: "Resets unpublished changes for the local trusted collection.",
Long: "Resets unpublished changes for the local trusted collection identified by the Globally Unique Name.",
}

var cmdTUFVerifyTemplate = usageTemplate{
Use: "verify [ GUN ] <target>",
Short: "Verifies if the content is included in the remote trusted collection",
Expand Down Expand Up @@ -110,8 +116,8 @@ type tufCommander struct {
output string
quiet bool

resetAll bool
deleteIdx []int
reset bool
archiveChangelist string

deleteRemote bool
Expand All @@ -125,10 +131,12 @@ func (t *tufCommander) AddToCommand(cmd *cobra.Command) {
cmdTUFInit.Flags().BoolVarP(&t.autoPublish, "publish", "p", false, htAutoPublish)
cmd.AddCommand(cmdTUFInit)

cmdStatus := cmdTUFStatusTemplate.ToCommand(t.tufStatus)
cmdStatus.Flags().IntSliceVarP(&t.deleteIdx, "unstage", "u", nil, "Numbers of changes to delete, as shown in status list")
cmdStatus.Flags().BoolVar(&t.reset, "reset", false, "Reset the changelist for the GUN by deleting all pending changes")
cmd.AddCommand(cmdStatus)
cmd.AddCommand(cmdTUFStatusTemplate.ToCommand(t.tufStatus))

cmdReset := cmdTUFResetTemplate.ToCommand(t.tufReset)
cmdReset.Flags().IntSliceVarP(&t.deleteIdx, "number", "n", nil, "Numbers of specific changes to exclusively reset, as shown in status list")
cmdReset.Flags().BoolVar(&t.resetAll, "all", false, "Reset all changes shown in the status list")
cmd.AddCommand(cmdReset)

cmd.AddCommand(cmdTUFPublishTemplate.ToCommand(t.tufPublish))
cmd.AddCommand(cmdTUFLookupTemplate.ToCommand(t.tufLookup))
Expand Down Expand Up @@ -553,14 +561,6 @@ func (t *tufCommander) tufStatus(cmd *cobra.Command, args []string) error {
return err
}

if t.reset {
return cl.Clear(t.archiveChangelist)
}

if len(t.deleteIdx) > 0 {
return cl.Remove(t.deleteIdx)
}

if len(cl.List()) == 0 {
cmd.Printf("No unpublished changes for %s\n", gun)
return nil
Expand All @@ -586,6 +586,44 @@ func (t *tufCommander) tufStatus(cmd *cobra.Command, args []string) error {
return nil
}

func (t *tufCommander) tufReset(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
cmd.Usage()
return fmt.Errorf("Must specify a GUN")
}
if !t.resetAll && len(t.deleteIdx) < 1 {
cmd.Usage()
return fmt.Errorf("Must specify changes to reset with -n or the --all flag")
}

config, err := t.configGetter()
if err != nil {
return err
}
gun := args[0]

trustPin, err := getTrustPinning(config)
if err != nil {
return err
}

nRepo, err := notaryclient.NewNotaryRepository(
config.GetString("trust_dir"), gun, getRemoteTrustServer(config), nil, t.retriever, trustPin)
if err != nil {
return err
}

cl, err := nRepo.GetChangelist()
if err != nil {
return err
}

if t.resetAll {
return cl.Clear(t.archiveChangelist)
}
return cl.Remove(t.deleteIdx)
}

func (t *tufCommander) tufPublish(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
cmd.Usage()
Expand Down
11 changes: 6 additions & 5 deletions cmd/notary/tuf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,9 @@ func TestStatusUnstageAndReset(t *testing.T) {
},
}

tc.reset = true

// run a reset with an empty changelist and make sure it succeeds
err := tc.tufStatus(&cobra.Command{}, []string{"gun"})
tc.resetAll = true
err := tc.tufReset(&cobra.Command{}, []string{"gun"})
require.NoError(t, err)

// add some targets
Expand All @@ -163,7 +162,7 @@ func TestStatusUnstageAndReset(t *testing.T) {
require.Contains(t, out, "test3")
require.Contains(t, out, "test4")

_, err = runCommand(t, tempBaseDir, "status", "gun", "--unstage", "-1,1,3,10")
_, err = runCommand(t, tempBaseDir, "reset", "gun", "-n", "-1,1,3,10")
require.NoError(t, err)

out, err = runCommand(t, tempBaseDir, "status", "gun")
Expand All @@ -173,7 +172,7 @@ func TestStatusUnstageAndReset(t *testing.T) {
require.Contains(t, out, "test3")
require.NotContains(t, out, "test4")

_, err = runCommand(t, tempBaseDir, "status", "gun", "--reset")
_, err = runCommand(t, tempBaseDir, "reset", "gun", "--all")
require.NoError(t, err)

out, err = runCommand(t, tempBaseDir, "status", "gun")
Expand Down Expand Up @@ -206,6 +205,8 @@ func TestGetTrustPinningErrors(t *testing.T) {
},
}
require.Error(t, tc.tufStatus(&cobra.Command{}, []string{"gun"}))
tc.resetAll = true
require.Error(t, tc.tufReset(&cobra.Command{}, []string{"gun"}))
require.Error(t, tc.tufDeleteGUN(&cobra.Command{}, []string{"gun"}))
require.Error(t, tc.tufInit(&cobra.Command{}, []string{"gun"}))
require.Error(t, tc.tufPublish(&cobra.Command{}, []string{"gun"}))
Expand Down
8 changes: 4 additions & 4 deletions docs/command_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,17 @@ $ notary publish <GUN>
The Notary CLI client stages changes before publishing them to the server.
These changes are staged locally in files such that the client can request the latest updates from the notary server, attempt to apply the staged changes on top of the new updates (like a `git rebase`), and then finally publish if the changes are still valid.
You can manage the changes that are staged by running:
You can view staged changes with `notary status` and unstage them with `notary reset`:
```bash
# Check what changes are staged
$ notary status <GUN>
# Unstage a specific change
$ notary status <GUN> --unstage 0
$ notary reset <GUN> -n 0
# Alternatively, unstage all changes
$ notary status <GUN> --reset
# Alternatively, reset all changes
$ notary reset <GUN> --all
```
When you're ready to publish your changes to the Notary server, run:
Expand Down
13 changes: 7 additions & 6 deletions docs/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ $ notary -s https://notary.docker.io -d ~/.docker/trust publish docker.io/libra

Note that each row in the status has a number associated with it, found in the first
column. This number can be used to remove individual changes from the changelist if
they are no longer desired. This is done using the `--unstage` flag:
they are no longer desired. This is done using the `reset` command:

```
$ notary -d ~/.docker/trust status docker.io/library/alpine
Expand All @@ -154,7 +154,8 @@ Unpublished changes for docker.io/library/alpine:
\- ------ ----- ---- ----
0 delete targets target 2.6
1 create targets target 3.0
$ notary -d ~/.docker/trust status docker.io/library/alpine --unstage 0
$ notary -d ~/.docker/trust reset docker.io/library/alpine -n 0
$ notary -d ~/.docker/trust status docker.io/library/alpine
Unpublished changes for docker.io/library/alpine:
Expand All @@ -164,13 +165,13 @@ Unpublished changes for docker.io/library/alpine:
```

Pay close attention to how the indices are updated as changes are removed. You may
pass multiple `--unstage` flags with multiple indices in a single invocation of the
`status` subcommand and they will all be handled correctly within that invocation. Between
pass multiple `-n` flags with multiple indices in a single invocation of the
`reset` subcommand and they will all be handled correctly within that invocation. Between
invocations however, you should list the changes again to check which indices you want
to remove.

It is also possible to completely clear all pending changes by passing the `--reset`
to the `status` subcommand. This deletes all pending changes for the specified GUN.
It is also possible to completely clear all pending changes by passing the `--all` flag
to the `reset` subcommand. This deletes all pending changes for the specified GUN.

## Configure the client

Expand Down

0 comments on commit 7ab58e5

Please sign in to comment.