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 }