github.com/shishir-a412ed/docker@v1.3.2-0.20180103180333-fda904911d87/api/server/backend/build/tag.go (about)

     1  package build
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"runtime"
     7  
     8  	"github.com/docker/distribution/reference"
     9  	"github.com/docker/docker/image"
    10  	"github.com/docker/docker/pkg/system"
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  // Tagger is responsible for tagging an image created by a builder
    15  type Tagger struct {
    16  	imageComponent ImageComponent
    17  	stdout         io.Writer
    18  	repoAndTags    []reference.Named
    19  }
    20  
    21  // NewTagger returns a new Tagger for tagging the images of a build.
    22  // If any of the names are invalid tags an error is returned.
    23  func NewTagger(backend ImageComponent, stdout io.Writer, names []string) (*Tagger, error) {
    24  	reposAndTags, err := sanitizeRepoAndTags(names)
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  	return &Tagger{
    29  		imageComponent: backend,
    30  		stdout:         stdout,
    31  		repoAndTags:    reposAndTags,
    32  	}, nil
    33  }
    34  
    35  // TagImages creates image tags for the imageID
    36  func (bt *Tagger) TagImages(imageID image.ID) error {
    37  	for _, rt := range bt.repoAndTags {
    38  		// TODO @jhowardmsft LCOW support. Will need revisiting.
    39  		platform := runtime.GOOS
    40  		if system.LCOWSupported() {
    41  			platform = "linux"
    42  		}
    43  		if err := bt.imageComponent.TagImageWithReference(imageID, platform, rt); err != nil {
    44  			return err
    45  		}
    46  		fmt.Fprintf(bt.stdout, "Successfully tagged %s\n", reference.FamiliarString(rt))
    47  	}
    48  	return nil
    49  }
    50  
    51  // sanitizeRepoAndTags parses the raw "t" parameter received from the client
    52  // to a slice of repoAndTag.
    53  // It also validates each repoName and tag.
    54  func sanitizeRepoAndTags(names []string) ([]reference.Named, error) {
    55  	var (
    56  		repoAndTags []reference.Named
    57  		// This map is used for deduplicating the "-t" parameter.
    58  		uniqNames = make(map[string]struct{})
    59  	)
    60  	for _, repo := range names {
    61  		if repo == "" {
    62  			continue
    63  		}
    64  
    65  		ref, err := reference.ParseNormalizedNamed(repo)
    66  		if err != nil {
    67  			return nil, err
    68  		}
    69  
    70  		if _, isCanonical := ref.(reference.Canonical); isCanonical {
    71  			return nil, errors.New("build tag cannot contain a digest")
    72  		}
    73  
    74  		ref = reference.TagNameOnly(ref)
    75  
    76  		nameWithTag := ref.String()
    77  
    78  		if _, exists := uniqNames[nameWithTag]; !exists {
    79  			uniqNames[nameWithTag] = struct{}{}
    80  			repoAndTags = append(repoAndTags, ref)
    81  		}
    82  	}
    83  	return repoAndTags, nil
    84  }