From 5e11cd43aa21a9d0eb1f5f205f05dc7b14ee4d43 Mon Sep 17 00:00:00 2001 From: Derek McGowan Date: Thu, 3 Sep 2015 20:01:03 -0700 Subject: [PATCH] Ignore ping errors in notary repository setup Notary is capable of acting in offline mode, making use of cache TUF data. When ping is not successful, notary should still be attempted without error. Signed-off-by: Derek McGowan (github: dmcgowan) --- api/client/trust.go | 22 ++++++---- .../docker_cli_pull_trusted_test.go | 41 +++++++++++++++++++ integration-cli/docker_cli_push_test.go | 2 +- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/api/client/trust.go b/api/client/trust.go index 4d984cfa6f..ab29269939 100644 --- a/api/client/trust.go +++ b/api/client/trust.go @@ -144,15 +144,21 @@ func (cli *DockerCli) getNotaryRepository(repoInfo *registry.RepositoryInfo, aut if err != nil { return nil, err } - resp, err := pingClient.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() challengeManager := auth.NewSimpleChallengeManager() - if err := challengeManager.AddResponse(resp); err != nil { - return nil, err + + resp, err := pingClient.Do(req) + if err != nil { + // Ignore error on ping to operate in offline mode + logrus.Debugf("Error pinging notary server %q: %s", endpointStr, err) + } else { + defer resp.Body.Close() + + // Add response to the challenge manager to parse out + // authentication header and register authentication method + if err := challengeManager.AddResponse(resp); err != nil { + return nil, err + } } creds := simpleCredentialStore{auth: authConfig} @@ -248,6 +254,8 @@ func notaryError(err error) error { return fmt.Errorf("remote repository out-of-date: %v", err) case trustmanager.ErrKeyNotFound: return fmt.Errorf("signing keys not found: %v", err) + case *net.OpError: + return fmt.Errorf("error contacting notary server: %v", err) } return err diff --git a/integration-cli/docker_cli_pull_trusted_test.go b/integration-cli/docker_cli_pull_trusted_test.go index d0514573c7..4e796f0e4c 100644 --- a/integration-cli/docker_cli_pull_trusted_test.go +++ b/integration-cli/docker_cli_pull_trusted_test.go @@ -223,3 +223,44 @@ func (s *DockerTrustSuite) TestTrustedPullWithExpiredSnapshot(c *check.C) { } }) } + +func (s *DockerTrustSuite) TestTrustedOfflinePull(c *check.C) { + repoName := s.setupTrustedImage(c, "trusted-offline-pull") + + pullCmd := exec.Command(dockerBinary, "pull", repoName) + s.trustedCmdWithServer(pullCmd, "https://invalidnotaryserver") + out, _, err := runCommandWithOutput(pullCmd) + if err == nil { + c.Fatalf("Expected error pulling with invalid notary server:\n%s", out) + } + + if !strings.Contains(string(out), "error contacting notary server") { + c.Fatalf("Missing expected output on trusted pull:\n%s", out) + } + + // Do valid trusted pull to warm cache + pullCmd = exec.Command(dockerBinary, "pull", repoName) + s.trustedCmd(pullCmd) + out, _, err = runCommandWithOutput(pullCmd) + if err != nil { + c.Fatalf("Error running trusted pull: %s\n%s", err, out) + } + + if !strings.Contains(string(out), "Tagging") { + c.Fatalf("Missing expected output on trusted push:\n%s", out) + } + + dockerCmd(c, "rmi", repoName) + + // Try pull again with invalid notary server, should use cache + pullCmd = exec.Command(dockerBinary, "pull", repoName) + s.trustedCmdWithServer(pullCmd, "https://invalidnotaryserver") + out, _, err = runCommandWithOutput(pullCmd) + if err != nil { + c.Fatalf("Error running trusted pull: %s\n%s", err, out) + } + + if !strings.Contains(string(out), "Tagging") { + c.Fatalf("Missing expected output on trusted push:\n%s", out) + } +} diff --git a/integration-cli/docker_cli_push_test.go b/integration-cli/docker_cli_push_test.go index b5c4b527cb..badc3fd516 100644 --- a/integration-cli/docker_cli_push_test.go +++ b/integration-cli/docker_cli_push_test.go @@ -154,7 +154,7 @@ func (s *DockerTrustSuite) TestTrustedPushWithFaillingServer(c *check.C) { c.Fatalf("Missing error while running trusted push w/ no server") } - if !strings.Contains(string(out), "Error establishing connection to notary repository") { + if !strings.Contains(string(out), "error contacting notary server") { c.Fatalf("Missing expected output on trusted push:\n%s", out) } }