From ab890a8940f849a5e6df8d120b202449786720be Mon Sep 17 00:00:00 2001 From: Ivan Ilves Date: Wed, 18 Oct 2017 15:52:04 +0200 Subject: [PATCH 1/4] Lots of renaming, moving and code burning for pride and glory! --- .travis.yml | 1 - Makefile | 7 +- auth/auth.go | 1 + auth/basic/basic.go | 5 ++ auth/bearer/bearer.go | 5 ++ auth/none/none.go | 5 ++ docker/docker.go | 30 +++++++ docker/docker_test.go | 65 ++++++++++++++ main.go | 30 +++---- main_test.go | 88 +++---------------- tag/local/local.go | 17 ---- tag/local/local_test.go | 49 ----------- tag/registry/registry_test.go | 28 ------ .../registry.go => remote/remote.go} | 15 +--- tag/tag.go | 16 ++-- tag/tag_test.go | 10 +-- 16 files changed, 152 insertions(+), 220 deletions(-) delete mode 100644 tag/local/local_test.go delete mode 100644 tag/registry/registry_test.go rename tag/{registry/registry.go => remote/remote.go} (95%) diff --git a/.travis.yml b/.travis.yml index 5b12d0d..4b00216 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,6 @@ before_script: - git remote set-url --push origin https://${GITHUB_TOKEN}@github.com/ivanilves/lstags.git script: - - make unit-test - make package-test - make integration-test - make shell-test diff --git a/Makefile b/Makefile index 75cf775..9cf163b 100644 --- a/Makefile +++ b/Makefile @@ -8,10 +8,7 @@ prepare: dep: dep ensure -v -test: unit-test package-test - -unit-test: - go test -v +test: package-test integration-test package-test: @find \ @@ -20,7 +17,7 @@ package-test: | xargs -i sh -c "pushd {}; go test -v || exit 1; popd" integration-test: - go test -integration -v + go test -v env: env diff --git a/auth/auth.go b/auth/auth.go index 3ab832f..da4290b 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -18,6 +18,7 @@ type TokenResponse interface { Method() string Token() string ExpiresIn() int + Header() string } func parseAuthHeader(headers http.Header) (string, string, error) { diff --git a/auth/basic/basic.go b/auth/basic/basic.go index 9f042a1..37000fd 100644 --- a/auth/basic/basic.go +++ b/auth/basic/basic.go @@ -26,6 +26,11 @@ func (tr TokenResponse) ExpiresIn() int { return 0 } +// Header returns contents of the Authorization HTTP header +func (tr TokenResponse) Header() string { + return tr.Method() + " " + tr.Token() +} + func getTokenFromHeader(header string) string { fields := strings.Split(header, " ") diff --git a/auth/bearer/bearer.go b/auth/bearer/bearer.go index 0f85b7c..e248ca7 100644 --- a/auth/bearer/bearer.go +++ b/auth/bearer/bearer.go @@ -28,6 +28,11 @@ func (tr TokenResponse) ExpiresIn() int { return tr.E } +// Header returns contents of the Authorization HTTP header +func (tr TokenResponse) Header() string { + return tr.Method() + " " + tr.Token() +} + func decodeTokenResponse(data io.ReadCloser) (*TokenResponse, error) { tr := TokenResponse{} diff --git a/auth/none/none.go b/auth/none/none.go index e876c56..e11faf6 100644 --- a/auth/none/none.go +++ b/auth/none/none.go @@ -19,6 +19,11 @@ func (tr TokenResponse) ExpiresIn() int { return 0 } +// Header returns contents of the Authorization HTTP header +func (tr TokenResponse) Header() string { + return tr.Method() + " " + tr.Token() +} + // RequestToken does pretty little here... func RequestToken() (*TokenResponse, error) { return &TokenResponse{}, nil diff --git a/docker/docker.go b/docker/docker.go index 7df63f6..4bd7d2d 100644 --- a/docker/docker.go +++ b/docker/docker.go @@ -34,3 +34,33 @@ func isHostname(s string) bool { return false } + +// GetRepoName gets full repository name +func GetRepoName(repository, registry string) string { + if registry == "registry.hub.docker.com" { + if strings.HasPrefix(repository, "library/") { + return strings.Replace(repository, "library/", "", 1) + } + + return repository + } + + if strings.HasPrefix(repository, registry) { + return repository + } + + return registry + "/" + repository +} + +// GetRepoPath gets repository path +func GetRepoPath(repository, registry string) string { + if !strings.Contains(repository, "/") { + return "library/" + repository + } + + if strings.HasPrefix(repository, registry) { + return strings.Replace(repository, registry+"/", "", 1) + } + + return repository +} diff --git a/docker/docker_test.go b/docker/docker_test.go index 7ea1bae..bb28e39 100644 --- a/docker/docker_test.go +++ b/docker/docker_test.go @@ -30,3 +30,68 @@ func TestGetRegistry(t *testing.T) { } } } + +func TestGetRepoNameForDockerHub(t *testing.T) { + examples := map[string]string{ + "library/nginx": "nginx", + "hype/cube": "hype/cube", + } + + for input, expected := range examples { + output := GetRepoName(input, "registry.hub.docker.com") + + if output != expected { + t.Fatalf( + "Got unexpected repo name: %s => %s\n* Expected: %s", + input, + output, + expected, + ) + } + } +} + +func TestGetRepoNameForPrivateRegistry(t *testing.T) { + const registry = "registry.nerd.io" + + examples := map[string]string{ + "empollon/nginx": registry + "/empollon/nginx", + "registry.nerd.io/hype/cube": registry + "/hype/cube", + } + + for input, expected := range examples { + output := GetRepoName(input, registry) + + if output != expected { + t.Fatalf( + "Got unexpected repo name: %s => %s\n* Expected: %s", + input, + output, + expected, + ) + } + } +} + +func TestGetRepoPath(t *testing.T) { + const registry = "registry.nerd.io" + + examples := map[string]string{ + "nginx": "library/nginx", + "registry.nerd.io/hype/cube": "hype/cube", + "observability/metrix": "observability/metrix", + } + + for input, expected := range examples { + output := GetRepoPath(input, registry) + + if output != expected { + t.Fatalf( + "Got unexpected repo path: %s => %s\n* Expected: %s", + input, + output, + expected, + ) + } + } +} diff --git a/main.go b/main.go index 9302860..fa94e2e 100644 --- a/main.go +++ b/main.go @@ -13,7 +13,7 @@ import ( dockerconfig "github.com/ivanilves/lstags/docker/config" "github.com/ivanilves/lstags/tag" "github.com/ivanilves/lstags/tag/local" - "github.com/ivanilves/lstags/tag/registry" + "github.com/ivanilves/lstags/tag/remote" "github.com/ivanilves/lstags/util" ) @@ -65,7 +65,7 @@ func parseFlags() (*Options, error) { o.Pull = true } - registry.TraceRequests = o.TraceRequests + remote.TraceRequests = o.TraceRequests doNotFail = o.DoNotFail @@ -76,10 +76,6 @@ func getVersion() string { return VERSION } -func getAuthorization(t auth.TokenResponse) string { - return t.Method() + " " + t.Token() -} - func main() { o, err := parseFlags() if err != nil { @@ -119,35 +115,33 @@ func main() { suicide(err, true) } - registryName := docker.GetRegistry(repository) + registry := docker.GetRegistry(repository) - repoRegistryName := registry.FormatRepoName(repository, registryName) - repoLocalName := local.FormatRepoName(repository, registryName) + repoPath := docker.GetRepoPath(repository, registry) + repoName := docker.GetRepoName(repository, registry) - username, password, _ := dockerConfig.GetCredentials(registryName) + username, password, _ := dockerConfig.GetCredentials(registry) - tresp, err := auth.NewToken(registryName, repoRegistryName, username, password) + tr, err := auth.NewToken(registry, repoPath, username, password) if err != nil { suicide(err, true) } - authorization := getAuthorization(tresp) - - registryTags, err := registry.FetchTags(registryName, repoRegistryName, authorization, o.ConcurrentRequests) + remoteTags, err := remote.FetchTags(registry, repoPath, tr.Header(), o.ConcurrentRequests) if err != nil { suicide(err, true) } - imageSummaries, err := dc.ListImagesForRepo(repoLocalName) + imageSummaries, err := dc.ListImagesForRepo(repoName) if err != nil { suicide(err, true) } - localTags, err := local.FetchTags(repoLocalName, imageSummaries) + localTags, err := local.FetchTags(repoName, imageSummaries) if err != nil { suicide(err, true) } - sortedKeys, names, joinedTags := tag.Join(registryTags, localTags) + sortedKeys, names, joinedTags := tag.Join(remoteTags, localTags) tags := make([]*tag.Tag, 0) for _, key := range sortedKeys { @@ -167,7 +161,7 @@ func main() { tags = append(tags, tg) } - trc <- tagResult{Tags: tags, Repo: repoLocalName, Path: repoRegistryName, Registry: registryName} + trc <- tagResult{Tags: tags, Repo: repoName, Path: repoPath, Registry: registry} }(r, o, trc) } diff --git a/main_test.go b/main_test.go index e4d9f93..2f0b304 100644 --- a/main_test.go +++ b/main_test.go @@ -1,90 +1,35 @@ +/* + +NB! +NB! "main" package tests are only for integration testing +NB! "main" package is bare and all unit tests are put into packages +NB! + +*/ package main import ( "testing" - "flag" "os" "github.com/ivanilves/lstags/auth" - "github.com/ivanilves/lstags/tag/registry" + "github.com/ivanilves/lstags/tag/remote" ) -var runIntegrationTests = flag.Bool("integration", false, "run integration tests") - const dockerHub = "registry.hub.docker.com" const dockerJSON = "./fixtures/docker/config.json" -func TestGetVersion(t *testing.T) { - flag.Parse() - if *runIntegrationTests { - t.SkipNow() - } - - const expected = "CURRENT" - - version := getVersion() - - if version != expected { - t.Fatalf( - "Unexpected version: '%s' (expected: '%s')", - version, - expected, - ) - } -} - -type MockedTokenResponse struct { -} - -func (tr MockedTokenResponse) Token() string { - return "8c896241e2774507489849ab1981e582" -} - -func (tr MockedTokenResponse) Method() string { - return "Mocked" -} - -func (tr MockedTokenResponse) ExpiresIn() int { - return 0 -} - -func TestGetAuthorization(t *testing.T) { - flag.Parse() - if *runIntegrationTests { - t.SkipNow() - } - - const expected = "Mocked 8c896241e2774507489849ab1981e582" - - authorization := getAuthorization(MockedTokenResponse{}) - - if authorization != expected { - t.Fatalf( - "Unexpected authorization string: '%s' (expected: '%s')", - authorization, - expected, - ) - } -} - func TestDockerHubWithPublicRepo(t *testing.T) { - flag.Parse() - if !*runIntegrationTests { - t.SkipNow() - } - const repo = "library/alpine" - tresp, err := auth.NewToken(dockerHub, repo, "", "") + tr, err := auth.NewToken(dockerHub, repo, "", "") if err != nil { t.Fatalf("Failed to get DockerHub public repo token: %s", err.Error()) } - authorization := getAuthorization(tresp) - - tags, err := registry.FetchTags(dockerHub, repo, authorization, 128) + tags, err := remote.FetchTags(dockerHub, repo, tr.Header(), 128) if err != nil { t.Fatalf("Failed to list DockerHub public repo (%s) tags: %s", repo, err.Error()) } @@ -96,11 +41,6 @@ func TestDockerHubWithPublicRepo(t *testing.T) { } func TestDockerHubWithPrivateRepo(t *testing.T) { - flag.Parse() - if !*runIntegrationTests { - t.SkipNow() - } - if os.Getenv("DOCKERHUB_USERNAME") == "" { t.Skipf("DOCKERHUB_USERNAME environment variable not set!") } @@ -115,14 +55,12 @@ func TestDockerHubWithPrivateRepo(t *testing.T) { pass := os.Getenv("DOCKERHUB_PASSWORD") repo := os.Getenv("DOCKERHUB_PRIVATE_REPO") - tresp, err := auth.NewToken(dockerHub, repo, user, pass) + tr, err := auth.NewToken(dockerHub, repo, user, pass) if err != nil { t.Fatalf("Failed to get DockerHub private repo token: %s", err.Error()) } - authorization := getAuthorization(tresp) - - tags, err := registry.FetchTags(dockerHub, repo, authorization, 128) + tags, err := remote.FetchTags(dockerHub, repo, tr.Header(), 128) if err != nil { t.Fatalf("Failed to list DockerHub private repo (%s) tags: %s", repo, err.Error()) } diff --git a/tag/local/local.go b/tag/local/local.go index e08dbc9..e15e9b9 100644 --- a/tag/local/local.go +++ b/tag/local/local.go @@ -60,20 +60,3 @@ func extractTagNames(repoTags []string, repo string) []string { return tagNames } - -// FormatRepoName formats repository name for use with local Docker daemon -func FormatRepoName(repository, registry string) string { - if registry == "registry.hub.docker.com" { - if strings.HasPrefix(repository, "library/") { - return strings.Replace(repository, "library/", "", 1) - } - - return repository - } - - if strings.HasPrefix(repository, registry) { - return repository - } - - return registry + "/" + repository -} diff --git a/tag/local/local_test.go b/tag/local/local_test.go deleted file mode 100644 index 7fa9557..0000000 --- a/tag/local/local_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package local - -import ( - "testing" -) - -func TestFormatRepoNameForDockerHub(t *testing.T) { - const registry = "registry.hub.docker.com" - - expectations := map[string]string{ - "library/nginx": "nginx", - "hype/cube": "hype/cube", - } - - for input, expected := range expectations { - output := FormatRepoName(input, registry) - - if output != expected { - t.Fatalf( - "Got unexpected local repo name: %s => %s\n* Expected: %s", - input, - output, - expected, - ) - } - } -} - -func TestFormatRepoNameForPrivateRegistry(t *testing.T) { - const registry = "registry.nerd.io" - - expectations := map[string]string{ - "empollon/nginx": "registry.nerd.io/empollon/nginx", - "registry.nerd.io/hype/cube": "registry.nerd.io/hype/cube", - } - - for input, expected := range expectations { - output := FormatRepoName(input, registry) - - if output != expected { - t.Fatalf( - "Got unexpected registry repo name: %s => %s\n* Expected: %s", - input, - output, - expected, - ) - } - } -} diff --git a/tag/registry/registry_test.go b/tag/registry/registry_test.go deleted file mode 100644 index 392ab5c..0000000 --- a/tag/registry/registry_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package registry - -import ( - "testing" -) - -func TestFormatRepoName(t *testing.T) { - const registry = "registry.nerd.io" - - expectations := map[string]string{ - "nginx": "library/nginx", - "registry.nerd.io/hype/cube": "hype/cube", - "observability/metrix": "observability/metrix", - } - - for input, expected := range expectations { - output := FormatRepoName(input, registry) - - if output != expected { - t.Fatalf( - "Got unexpected registry repo name: %s => %s\n* Expected: %s", - input, - output, - expected, - ) - } - } -} diff --git a/tag/registry/registry.go b/tag/remote/remote.go similarity index 95% rename from tag/registry/registry.go rename to tag/remote/remote.go index 55d6d64..26bbfc5 100644 --- a/tag/registry/registry.go +++ b/tag/remote/remote.go @@ -1,4 +1,4 @@ -package registry +package remote import ( "bytes" @@ -315,16 +315,3 @@ func FetchTags(registry, repo, authorization string, concurrentRequests int) (ma return tags, nil } - -// FormatRepoName formats repository name for use with Docker registry -func FormatRepoName(repository, registry string) string { - if !strings.Contains(repository, "/") { - return "library/" + repository - } - - if strings.HasPrefix(repository, registry) { - return strings.Replace(repository, registry+"/", "", 1) - } - - return repository -} diff --git a/tag/tag.go b/tag/tag.go index d9f4eee..33058da 100644 --- a/tag/tag.go +++ b/tag/tag.go @@ -127,8 +127,8 @@ func New(name, digest string) (*Tag, error) { nil } -func calculateState(name string, registryTags, localTags map[string]*Tag) string { - r, definedInRegistry := registryTags[name] +func calculateState(name string, remoteTags, localTags map[string]*Tag) string { + r, definedInRegistry := remoteTags[name] l, definedLocally := localTags[name] if definedInRegistry && !definedLocally { @@ -154,18 +154,18 @@ func calculateState(name string, registryTags, localTags map[string]*Tag) string // * sorted slice of sort keys // * joined map of [sortKey]name // * joined map of [name]*Tag -func Join(registryTags, localTags map[string]*Tag) ([]string, map[string]string, map[string]*Tag) { +func Join(remoteTags, localTags map[string]*Tag) ([]string, map[string]string, map[string]*Tag) { sortedKeys := make([]string, 0) names := make(map[string]string) joinedTags := make(map[string]*Tag) - for name := range registryTags { - sortKey := registryTags[name].SortKey() + for name := range remoteTags { + sortKey := remoteTags[name].SortKey() sortedKeys = append(sortedKeys, sortKey) names[sortKey] = name - joinedTags[name] = registryTags[name] + joinedTags[name] = remoteTags[name] ltg, defined := localTags[name] if defined { @@ -176,7 +176,7 @@ func Join(registryTags, localTags map[string]*Tag) ([]string, map[string]string, } for name := range localTags { - _, defined := registryTags[name] + _, defined := remoteTags[name] if !defined { sortKey := localTags[name].SortKey() @@ -191,7 +191,7 @@ func Join(registryTags, localTags map[string]*Tag) ([]string, map[string]string, jtg.SetState( calculateState( name, - registryTags, + remoteTags, localTags, ), ) diff --git a/tag/tag_test.go b/tag/tag_test.go index 3929531..e47806e 100644 --- a/tag/tag_test.go +++ b/tag/tag_test.go @@ -54,7 +54,7 @@ func TestNewTagWithEmptyDigest(t *testing.T) { } } -func registryTags() map[string]*Tag { +func remoteTags() map[string]*Tag { tags := make(map[string]*Tag, 0) tg1, _ := New( @@ -108,7 +108,7 @@ func localTags() map[string]*Tag { func TestJoinLength(t *testing.T) { const expected = 4 - _, _, tags := Join(registryTags(), localTags()) + _, _, tags := Join(remoteTags(), localTags()) c := len(tags) @@ -129,7 +129,7 @@ func TestJoinDigest(t *testing.T) { "v1.2": "sha256:7f7f94f26d23f7aca80a33732161af068f9f62fbe0e824a58cf3a39d209cfa77", } - _, _, tags := Join(registryTags(), localTags()) + _, _, tags := Join(remoteTags(), localTags()) for name, digest := range expected { if tags[name].GetDigest() != digest { @@ -151,7 +151,7 @@ func TestJoinImageID(t *testing.T) { "v1.2": "4c4ebb9614ef", } - _, _, tags := Join(registryTags(), localTags()) + _, _, tags := Join(remoteTags(), localTags()) for name, imageID := range expected { if tags[name].GetImageID() != imageID { @@ -173,7 +173,7 @@ func TestJoinState(t *testing.T) { "v1.2": "PRESENT", } - _, _, tags := Join(registryTags(), localTags()) + _, _, tags := Join(remoteTags(), localTags()) for name, state := range expected { if tags[name].GetState() != state { From 75609f7c3869fe6e01443db8ff35325c8f677941 Mon Sep 17 00:00:00 2001 From: Ivan Ilves Date: Wed, 18 Oct 2017 21:40:31 +0200 Subject: [PATCH 2/4] Change command line option names ... again :pig: --- main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index fa94e2e..269d648 100644 --- a/main.go +++ b/main.go @@ -20,8 +20,8 @@ import ( // Options represents configuration options we extract from passed command line arguments type Options struct { DockerJSON string `short:"j" long:"docker-json" default:"~/.docker/config.json" description:"JSON file with credentials" env:"DOCKER_JSON"` - Pull bool `short:"P" long:"pull" description:"Pull Docker images matched by filter (will use local Docker deamon)" env:"PULL"` - PushRegistry string `short:"U" long:"push-registry" description:"[Re]Push pulled images to a specified remote registry" env:"PUSH_REGISTRY"` + Pull bool `short:"p" long:"pull" description:"Pull Docker images matched by filter (will use local Docker deamon)" env:"PULL"` + PushRegistry string `short:"r" long:"push-registry" description:"[Re]Push pulled images to a specified remote registry" env:"PUSH_REGISTRY"` PushPrefix string `short:"R" long:"push-prefix" description:"[Re]Push pulled images with a specified repo path prefix" env:"PUSH_PREFIX"` ConcurrentRequests int `short:"c" long:"concurrent-requests" default:"32" description:"Limit of concurrent requests to the registry" env:"CONCURRENT_REQUESTS"` TraceRequests bool `short:"T" long:"trace-requests" description:"Trace Docker registry HTTP requests" env:"TRACE_REQUESTS"` From 3fb2d175aef98d3e87a47ff9bfd153b3a9c13770 Mon Sep 17 00:00:00 2001 From: Ivan Ilves Date: Wed, 18 Oct 2017 22:32:54 +0200 Subject: [PATCH 3/4] Pass data to/from goroutines in a more elegant way :neckbeard: --- main.go | 81 +++++++++++++++++++++++++++--------------------------- tag/tag.go | 8 ++++++ 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/main.go b/main.go index 269d648..d1ffa0a 100644 --- a/main.go +++ b/main.go @@ -87,6 +87,11 @@ func main() { suicide(err, true) } + dc, err := dockerclient.New(dockerConfig) + if err != nil { + suicide(err, true) + } + const format = "%-12s %-45s %-15s %-25s %s\n" fmt.Printf(format, "", "", "<(local) ID>", "", "") @@ -94,23 +99,11 @@ func main() { pullCount := 0 pushCount := 0 - dc, err := dockerclient.New(dockerConfig) - if err != nil { - suicide(err, true) - } - - type tagResult struct { - Tags []*tag.Tag - Repo string - Path string - Registry string - } - - trc := make(chan tagResult, repoCount) + tcc := make(chan tag.Collection, repoCount) - for _, r := range o.Positional.Repositories { - go func(r string, o *Options, trc chan tagResult) { - repository, filter, err := util.SeparateFilterAndRepo(r) + for _, repoWithFilter := range o.Positional.Repositories { + go func(repoWithFilter string, concurrentRequests int, tcc chan tag.Collection) { + repository, filter, err := util.SeparateFilterAndRepo(repoWithFilter) if err != nil { suicide(err, true) } @@ -127,7 +120,7 @@ func main() { suicide(err, true) } - remoteTags, err := remote.FetchTags(registry, repoPath, tr.Header(), o.ConcurrentRequests) + remoteTags, err := remote.FetchTags(registry, repoPath, tr.Header(), concurrentRequests) if err != nil { suicide(err, true) } @@ -161,29 +154,36 @@ func main() { tags = append(tags, tg) } - trc <- tagResult{Tags: tags, Repo: repoName, Path: repoPath, Registry: registry} - }(r, o, trc) + tcc <- tag.Collection{ + Registry: registry, + RepoName: repoName, + RepoPath: repoPath, + Tags: tags, + } + }(repoWithFilter, o.ConcurrentRequests, tcc) } - tagResults := make([]tagResult, repoCount) + tagCollections := make([]tag.Collection, repoCount) repoNumber := 0 - for tr := range trc { + for tc := range tcc { + tagCollections = append(tagCollections, tc) + repoNumber++ - tagResults = append(tagResults, tr) + if repoNumber >= repoCount { - close(trc) + close(tcc) } } - for _, tr := range tagResults { - for _, tg := range tr.Tags { + for _, tc := range tagCollections { + for _, tg := range tc.Tags { fmt.Printf( format, tg.GetState(), tg.GetShortDigest(), tg.GetImageID(), tg.GetCreatedString(), - tr.Repo+":"+tg.GetName(), + tc.RepoName+":"+tg.GetName(), ) } } @@ -191,11 +191,11 @@ func main() { if o.Pull { done := make(chan bool, pullCount) - for _, tr := range tagResults { - go func(tags []*tag.Tag, repo string, done chan bool) { - for _, tg := range tags { + for _, tc := range tagCollections { + go func(tc tag.Collection, done chan bool) { + for _, tg := range tc.Tags { if tg.NeedsPull() { - ref := repo + ":" + tg.GetName() + ref := tc.RepoName + ":" + tg.GetName() fmt.Printf("PULLING %s\n", ref) err := dc.Pull(ref) @@ -207,7 +207,7 @@ func main() { } } - }(tr.Tags, tr.Repo, done) + }(tc, done) } pullNumber := 0 @@ -223,18 +223,17 @@ func main() { } if o.Pull && o.PushRegistry != "" { - done := make(chan bool, pullCount) + done := make(chan bool, pushCount) - for _, tr := range tagResults { - go func(tags []*tag.Tag, repo, path, registry string, done chan bool) { - for _, tg := range tags { - prefix := o.PushPrefix - if prefix == "" { - prefix = util.GeneratePathFromHostname(registry) + for _, tc := range tagCollections { + go func(tc tag.Collection, pushRegistry, pushPrefix string, done chan bool) { + for _, tg := range tc.Tags { + if pushPrefix == "" { + pushPrefix = util.GeneratePathFromHostname(tc.Registry) } - srcRef := repo + ":" + tg.GetName() - dstRef := o.PushRegistry + prefix + "/" + path + ":" + tg.GetName() + srcRef := tc.RepoName + ":" + tg.GetName() + dstRef := pushRegistry + pushPrefix + "/" + tc.RepoPath + ":" + tg.GetName() fmt.Printf("PUSHING %s => %s\n", srcRef, dstRef) @@ -250,7 +249,7 @@ func main() { done <- true } - }(tr.Tags, tr.Repo, tr.Path, tr.Registry, done) + }(tc, o.PushRegistry, o.PushPrefix, done) } pushNumber := 0 diff --git a/tag/tag.go b/tag/tag.go index 33058da..0b60468 100644 --- a/tag/tag.go +++ b/tag/tag.go @@ -201,3 +201,11 @@ func Join(remoteTags, localTags map[string]*Tag) ([]string, map[string]string, m return sortedKeys, names, joinedTags } + +// Collection encapsulates collection of tags received from a registry/repository query +type Collection struct { + Registry string + RepoName string + RepoPath string + Tags []*Tag +} From e2557634ec40c1082fb62fd737200dd0ba0692e6 Mon Sep 17 00:00:00 2001 From: Ivan Ilves Date: Wed, 18 Oct 2017 22:50:45 +0200 Subject: [PATCH 4/4] ... even better naming for function ... --- auth/auth.go | 2 +- auth/basic/basic.go | 4 ++-- auth/bearer/bearer.go | 4 ++-- auth/none/none.go | 4 ++-- main.go | 2 +- main_test.go | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/auth/auth.go b/auth/auth.go index da4290b..24d8c7d 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -18,7 +18,7 @@ type TokenResponse interface { Method() string Token() string ExpiresIn() int - Header() string + AuthHeader() string } func parseAuthHeader(headers http.Header) (string, string, error) { diff --git a/auth/basic/basic.go b/auth/basic/basic.go index 37000fd..df95091 100644 --- a/auth/basic/basic.go +++ b/auth/basic/basic.go @@ -26,8 +26,8 @@ func (tr TokenResponse) ExpiresIn() int { return 0 } -// Header returns contents of the Authorization HTTP header -func (tr TokenResponse) Header() string { +// AuthHeader returns contents of the Authorization HTTP header +func (tr TokenResponse) AuthHeader() string { return tr.Method() + " " + tr.Token() } diff --git a/auth/bearer/bearer.go b/auth/bearer/bearer.go index e248ca7..42fe916 100644 --- a/auth/bearer/bearer.go +++ b/auth/bearer/bearer.go @@ -28,8 +28,8 @@ func (tr TokenResponse) ExpiresIn() int { return tr.E } -// Header returns contents of the Authorization HTTP header -func (tr TokenResponse) Header() string { +// AuthHeader returns contents of the Authorization HTTP header +func (tr TokenResponse) AuthHeader() string { return tr.Method() + " " + tr.Token() } diff --git a/auth/none/none.go b/auth/none/none.go index e11faf6..62a8a35 100644 --- a/auth/none/none.go +++ b/auth/none/none.go @@ -19,8 +19,8 @@ func (tr TokenResponse) ExpiresIn() int { return 0 } -// Header returns contents of the Authorization HTTP header -func (tr TokenResponse) Header() string { +// AuthHeader returns contents of the Authorization HTTP header +func (tr TokenResponse) AuthHeader() string { return tr.Method() + " " + tr.Token() } diff --git a/main.go b/main.go index d1ffa0a..bde1c67 100644 --- a/main.go +++ b/main.go @@ -120,7 +120,7 @@ func main() { suicide(err, true) } - remoteTags, err := remote.FetchTags(registry, repoPath, tr.Header(), concurrentRequests) + remoteTags, err := remote.FetchTags(registry, repoPath, tr.AuthHeader(), concurrentRequests) if err != nil { suicide(err, true) } diff --git a/main_test.go b/main_test.go index 2f0b304..a885508 100644 --- a/main_test.go +++ b/main_test.go @@ -29,7 +29,7 @@ func TestDockerHubWithPublicRepo(t *testing.T) { t.Fatalf("Failed to get DockerHub public repo token: %s", err.Error()) } - tags, err := remote.FetchTags(dockerHub, repo, tr.Header(), 128) + tags, err := remote.FetchTags(dockerHub, repo, tr.AuthHeader(), 128) if err != nil { t.Fatalf("Failed to list DockerHub public repo (%s) tags: %s", repo, err.Error()) } @@ -60,7 +60,7 @@ func TestDockerHubWithPrivateRepo(t *testing.T) { t.Fatalf("Failed to get DockerHub private repo token: %s", err.Error()) } - tags, err := remote.FetchTags(dockerHub, repo, tr.Header(), 128) + tags, err := remote.FetchTags(dockerHub, repo, tr.AuthHeader(), 128) if err != nil { t.Fatalf("Failed to list DockerHub private repo (%s) tags: %s", repo, err.Error()) }