Skip to content

Commit

Permalink
notary delete CLI command and integration test
Browse files Browse the repository at this point in the history
Signed-off-by: Riyaz Faizullabhoy <[email protected]>
  • Loading branch information
riyazdf committed Aug 3, 2016
1 parent 49462f6 commit 569ad0a
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 0 deletions.
149 changes: 149 additions & 0 deletions cmd/notary/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import (
"github.com/Sirupsen/logrus"
ctxu "github.com/docker/distribution/context"
"github.com/docker/notary"
"github.com/docker/notary/client"
"github.com/docker/notary/cryptoservice"
"github.com/docker/notary/passphrase"
"github.com/docker/notary/server"
"github.com/docker/notary/server/storage"
notaryStorage "github.com/docker/notary/storage"
"github.com/docker/notary/trustmanager"
"github.com/docker/notary/tuf/data"
"github.com/docker/notary/tuf/utils"
Expand Down Expand Up @@ -245,6 +247,153 @@ func TestClientTUFInteraction(t *testing.T) {
require.False(t, strings.Contains(string(output), target))
}

func TestClientDeleteTUFInteraction(t *testing.T) {
// -- setup --
setUp(t)

tempDir := tempDirWithConfig(t, "{}")
defer os.RemoveAll(tempDir)

server := setupServer()
defer server.Close()

tempFile, err := ioutil.TempFile("", "targetfile")
require.NoError(t, err)
tempFile.Close()
defer os.Remove(tempFile.Name())

// Setup certificate
certFile, err := ioutil.TempFile("", "pemfile")
require.NoError(t, err)

privKey, err := utils.GenerateECDSAKey(rand.Reader)
startTime := time.Now()
endTime := startTime.AddDate(10, 0, 0)
cert, err := cryptoservice.GenerateCertificate(privKey, "gun", startTime, endTime)
require.NoError(t, err)

_, err = certFile.Write(utils.CertToPEM(cert))
require.NoError(t, err)
tempFile.Close()
defer os.Remove(certFile.Name())

var (
output string
target = "helloIamanotarytarget"
)
// -- tests --

// init repo
_, err = runCommand(t, tempDir, "-s", server.URL, "init", "gun")
require.NoError(t, err)

// add a target
_, err = runCommand(t, tempDir, "add", "gun", target, tempFile.Name())
require.NoError(t, err)

// check status - see target
output, err = runCommand(t, tempDir, "status", "gun")
require.NoError(t, err)
require.True(t, strings.Contains(output, target))

// publish repo
_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
require.NoError(t, err)

// list repo - see target
output, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun")
require.NoError(t, err)
require.True(t, strings.Contains(string(output), target))

// add a delegation and publish
output, err = runCommand(t, tempDir, "delegation", "add", "gun", "targets/delegation", certFile.Name())
require.NoError(t, err)
_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
require.NoError(t, err)

// list delegations - see role
output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
require.NoError(t, err)
require.True(t, strings.Contains(string(output), "targets/delegation"))

// Delete the repo metadata locally, so no need for server URL
output, err = runCommand(t, tempDir, "delete", "gun")
require.NoError(t, err)
assertNoMetadataForGun(t, tempDir, "gun")

// list repo - see target still because remote data exists
output, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun")
require.NoError(t, err)
require.True(t, strings.Contains(string(output), target))

// list delegations - see role because remote data still exists
output, err = runCommand(t, tempDir, "-s", server.URL, "delegation", "list", "gun")
require.NoError(t, err)
require.True(t, strings.Contains(string(output), "targets/delegation"))

// Trying to delete the repo with the remote flag fails if it can't connect to the server
output, err = runCommand(t, tempDir, "-s", "https://invalidurl:4443", "delete", "gun", "--remote")
require.Error(t, err)
require.IsType(t, notaryStorage.ErrOffline{}, err)

// Delete the repo remotely and locally, pointing to the correct server
output, err = runCommand(t, tempDir, "-s", server.URL, "delete", "gun", "--remote")
require.NoError(t, err)
assertNoMetadataForGun(t, tempDir, "gun")
_, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun")
require.Error(t, err)
require.IsType(t, client.ErrRepositoryNotExist{}, err)

// Silent success on extraneous deletes
output, err = runCommand(t, tempDir, "-s", server.URL, "delete", "gun", "--remote")
require.NoError(t, err)
assertNoMetadataForGun(t, tempDir, "gun")
_, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun")
require.Error(t, err)
require.IsType(t, client.ErrRepositoryNotExist{}, err)

// Now check that we can re-publish the same repo
// init repo
_, err = runCommand(t, tempDir, "-s", server.URL, "init", "gun")
require.NoError(t, err)

// add a target
_, err = runCommand(t, tempDir, "add", "gun", target, tempFile.Name())
require.NoError(t, err)

// check status - see target
output, err = runCommand(t, tempDir, "status", "gun")
require.NoError(t, err)
require.True(t, strings.Contains(output, target))

// publish repo
_, err = runCommand(t, tempDir, "-s", server.URL, "publish", "gun")
require.NoError(t, err)

// list repo - see target
output, err = runCommand(t, tempDir, "-s", server.URL, "list", "gun")
require.NoError(t, err)
require.True(t, strings.Contains(string(output), target))
}

func assertNoMetadataForGun(t *testing.T, configDir, gun string) {
fileInfo, err := os.Stat(filepath.Join(configDir, "tuf", gun, "root.json"))
require.Error(t, err)
require.Nil(t, fileInfo)
fileInfo, err = os.Stat(filepath.Join(configDir, "tuf", gun, "targets.json"))
require.Error(t, err)
require.Nil(t, fileInfo)
fileInfo, err = os.Stat(filepath.Join(configDir, "tuf", gun, "snapshot.json"))
require.Error(t, err)
require.Nil(t, fileInfo)
fileInfo, err = os.Stat(filepath.Join(configDir, "tuf", gun, "timestamp.json"))
require.Error(t, err)
require.Nil(t, fileInfo)
fileInfo, err = os.Stat(filepath.Join(configDir, "tuf", gun, "targets"))
require.Error(t, err)
require.Nil(t, fileInfo)
}

// Initializes a repo, adds a target, publishes the target by hash, lists the target,
// verifies the target, and then removes the target.
func TestClientTUFAddByHashInteraction(t *testing.T) {
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 @@ -165,6 +165,7 @@ var exampleValidCommands = []string{
"delegation list repo",
"delegation add repo targets/releases path/to/pem/file.pem",
"delegation remove repo targets/releases",
"delete repo",
}

// config parsing bugs are propagated in all commands
Expand Down
47 changes: 47 additions & 0 deletions cmd/notary/tuf.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ var cmdTUFVerifyTemplate = usageTemplate{
Long: "Verifies if the data passed in STDIN is included in the remote trusted collection identified by the Globally Unique Name.",
}

var cmdTUFDeleteTemplate = usageTemplate{
Use: "delete [ GUN ]",
Short: "Deletes all content for a trusted collection",
Long: "Deletes all content for a trusted collection identified by the Globally Unique Name, can delete both local and remote data based on flags.",
}

type tufCommander struct {
// these need to be set
configGetter func() (*viper.Viper, error)
Expand All @@ -101,6 +107,8 @@ type tufCommander struct {
deleteIdx []int
reset bool
archiveChangelist string

deleteRemote bool
}

func (t *tufCommander) AddToCommand(cmd *cobra.Command) {
Expand Down Expand Up @@ -140,6 +148,10 @@ func (t *tufCommander) AddToCommand(cmd *cobra.Command) {
cmdTUFVerify.Flags().StringVarP(&t.output, "output", "o", "", "Write to a file, instead of STDOUT")
cmdTUFVerify.Flags().BoolVarP(&t.quiet, "quiet", "q", false, "No output except for errors")
cmd.AddCommand(cmdTUFVerify)

cmdTUFDeleteGUN := cmdTUFDeleteTemplate.ToCommand(t.tufDeleteGUN)
cmdTUFDeleteGUN.Flags().BoolVar(&t.deleteRemote, "remote", false, "Delete remote data for GUN in addition to local cache")
cmd.AddCommand(cmdTUFDeleteGUN)
}

func (t *tufCommander) tufAddByHash(cmd *cobra.Command, args []string) error {
Expand Down Expand Up @@ -255,6 +267,41 @@ func (t *tufCommander) tufAdd(cmd *cobra.Command, args []string) error {
return nil
}

func (t *tufCommander) tufDeleteGUN(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
cmd.Usage()
return fmt.Errorf("Must specify a GUN")
}
config, err := t.configGetter()
if err != nil {
return err
}

gun := args[0]

trustPin, err := getTrustPinning(config)

// Only initialize a roundtripper if we get the remote flag
var rt http.RoundTripper
if t.deleteRemote {
rt, err = getTransport(config, gun, admin)
if err != nil {
return err
}
}

nRepo, err := notaryclient.NewNotaryRepository(
config.GetString("trust_dir"), gun, getRemoteTrustServer(config), rt, t.retriever, trustPin)

if err != nil {
return err
}

cmd.Printf("Deleting trust data for repository %s.\n", gun)

return nRepo.DeleteTrustData(t.deleteRemote)
}

func (t *tufCommander) tufInit(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
cmd.Usage()
Expand Down

0 comments on commit 569ad0a

Please sign in to comment.