Merge pull request #20307 from HuKeping/trust

Refactor trust push
This commit is contained in:
David Calavera 2016-02-29 11:12:09 -08:00
commit 1ba0358a10

View file

@ -375,34 +375,57 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string,
defer responseBody.Close()
targets := []target{}
// If it is a trusted push we would like to find the target entry which match the
// tag provided in the function and then do an AddTarget later.
target := &client.Target{}
// Count the times of calling for handleTarget,
// if it is called more that once, that should be considered an error in a trusted push.
cnt := 0
handleTarget := func(aux *json.RawMessage) {
cnt++
if cnt > 1 {
// handleTarget should only be called one. This will be treated as an error.
return
}
var pushResult distribution.PushResult
err := json.Unmarshal(*aux, &pushResult)
if err == nil && pushResult.Tag != "" && pushResult.Digest.Validate() == nil {
targets = append(targets, target{
reference: registry.ParseReference(pushResult.Tag),
digest: pushResult.Digest,
size: int64(pushResult.Size),
})
h, err := hex.DecodeString(pushResult.Digest.Hex())
if err != nil {
target = nil
return
}
target.Name = registry.ParseReference(pushResult.Tag).String()
target.Hashes = data.Hashes{string(pushResult.Digest.Algorithm()): h}
target.Length = int64(pushResult.Size)
}
}
err = jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, handleTarget)
if err != nil {
// We want trust signatures to always take an explicit tag,
// otherwise it will act as an untrusted push.
if tag == "" {
if err = jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, nil); err != nil {
return err
}
fmt.Fprintln(cli.out, "No tag specified, skipping trust metadata push")
return nil
}
if err = jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, handleTarget); err != nil {
return err
}
if tag == "" {
fmt.Fprintf(cli.out, "No tag specified, skipping trust metadata push\n")
return nil
if cnt > 1 {
return fmt.Errorf("internal error: only one call to handleTarget expected")
}
if len(targets) == 0 {
fmt.Fprintf(cli.out, "No targets found, skipping trust metadata push\n")
if target == nil {
fmt.Fprintln(cli.out, "No targets found, please provide a specific tag in order to sign it")
return nil
}
fmt.Fprintf(cli.out, "Signing and pushing trust metadata\n")
fmt.Fprintln(cli.out, "Signing and pushing trust metadata")
repo, err := cli.getNotaryRepository(repoInfo, authConfig, "push", "pull")
if err != nil {
@ -410,25 +433,16 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string,
return err
}
for _, target := range targets {
h, err := hex.DecodeString(target.digest.Hex())
if err != nil {
return err
}
t := &client.Target{
Name: target.reference.String(),
Hashes: data.Hashes{
string(target.digest.Algorithm()): h,
},
Length: int64(target.size),
}
if err := repo.AddTarget(t, releasesRole); err != nil {
return err
}
if err := repo.AddTarget(target, releasesRole); err != nil {
return err
}
err = repo.Publish()
if _, ok := err.(client.ErrRepoNotInitialized); !ok {
if err == nil {
fmt.Fprintf(cli.out, "Successfully signed %q:%s\n", repoInfo.FullName(), tag)
return nil
} else if _, ok := err.(client.ErrRepoNotInitialized); !ok {
fmt.Fprintf(cli.out, "Failed to sign %q:%s - %s\n", repoInfo.FullName(), tag, err.Error())
return notaryError(repoInfo.FullName(), err)
}