ソースを参照

Refactor trust push

Unlike the untrusted push without an explicit tag will push all
tags for that repo, the trusted push would expect an explicit tag.

So that the code that attempts to do smart logic around signing multiple
tags should be removed.

Signed-off-by: Hu Keping <hukeping@huawei.com>
HuKeping 9 年 前
コミット
5dddf7e98e
1 ファイル変更39 行追加29 行削除
  1. 39 29
      api/client/trust.go

+ 39 - 29
api/client/trust.go

@@ -375,34 +375,57 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string,
 
 
 	defer responseBody.Close()
 	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) {
 	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
 		var pushResult distribution.PushResult
 		err := json.Unmarshal(*aux, &pushResult)
 		err := json.Unmarshal(*aux, &pushResult)
 		if err == nil && pushResult.Tag != "" && pushResult.Digest.Validate() == nil {
 		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
 		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
 		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")
 	repo, err := cli.getNotaryRepository(repoInfo, authConfig, "push", "pull")
 	if err != nil {
 	if err != nil {
@@ -410,21 +433,8 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string,
 		return err
 		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()
 	err = repo.Publish()