Created
February 9, 2021 16:51
-
-
Save s1moe2/75343cae5df718e08629f8c65c6ad081 to your computer and use it in GitHub Desktop.
Find commit hash tag by "latest" tag on same image
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"encoding/json" | |
"errors" | |
"flag" | |
"fmt" | |
"net/http" | |
"os" | |
"time" | |
) | |
const dockerAPI = "https://hub.docker.com/v2" | |
type Tag struct { | |
Images []struct{ | |
Digest string | |
} | |
Name string | |
} | |
type Tags struct { | |
Next string | |
Results []Tag | |
} | |
// This script's goal is to find the commit hash | |
// corresponding to a docker image tagged with a "latest" Tag. | |
// A "latest" image is supposed to be tagged with 2 tags: commit hash & latest. | |
// The only way to find the commit hash tag is by: | |
// - find image tagged as "latest" | |
// - get image digest | |
// - iterate repositories images to find one with a tag != "latest" & digest same as found | |
func main() { | |
var dockerUser = flag.String("u", "", "Docker Hub username") | |
var dockerPassword = flag.String("p", "", "Docker Hub password") | |
var repository = flag.String("r", "", "Docker repository") | |
var branch = flag.String("t", "", "Docker Image Tag") | |
flag.Parse() | |
token, err := dockerLogin(*dockerUser, *dockerPassword) | |
if err != nil { | |
fmt.Println(err) | |
os.Exit(1) | |
} | |
hash, err := findHashTag(token, *dockerUser, *repository, *branch) | |
if err != nil { | |
fmt.Println(err) | |
os.Exit(1) | |
} | |
fmt.Println(hash) | |
} | |
func dockerLogin(user string, password string) (string, error) { | |
postBody, _ := json.Marshal(map[string]string{ | |
"username": user, | |
"password": password, | |
}) | |
responseBody := bytes.NewBuffer(postBody) | |
url := fmt.Sprintf("%s/users/login", dockerAPI) | |
resp, err := http.Post(url, "application/json", responseBody) | |
if err != nil { | |
return "", err | |
} | |
defer resp.Body.Close() | |
type loginRes struct { | |
Token string | |
} | |
res := &loginRes{} | |
decoder := json.NewDecoder(resp.Body) | |
if err = decoder.Decode(&res); err != nil { | |
return "", err | |
} | |
return res.Token, nil | |
} | |
func findHashTag(token string, user string, repository string, tag string) (string, error) { | |
URL := fmt.Sprintf("%s/repositories/%s/%s/tags?n=500", dockerAPI, user, repository) | |
req, err := http.NewRequest(http.MethodGet, URL, nil) | |
if err != nil { | |
return "", err | |
} | |
req.Header.Set("Accept", "application/json") | |
req.Header.Set("Content-Type", "application/json") | |
req.Header.Set("Authorization", fmt.Sprintf("JWT %s", token)) | |
client := http.Client{ | |
Timeout: 5 * time.Second, | |
} | |
resp, err := client.Do(req) | |
if err != nil { | |
return "", err | |
} | |
defer resp.Body.Close() | |
tags := &Tags{} | |
decoder := json.NewDecoder(resp.Body) | |
if err = decoder.Decode(&tags); err != nil { | |
return "", err | |
} | |
var digest string | |
for _, t := range tags.Results { | |
if t.Name == tag { | |
if len(t.Images) != 1 { | |
return "", errors.New("found Tag but has no images") | |
} | |
digest = t.Images[0].Digest | |
break | |
} | |
} | |
if len(digest) == 0 { | |
return "", errors.New("could not find tag digest") | |
} | |
var hashTag string | |
for _, t := range tags.Results { | |
if t.Name == tag { | |
continue | |
} | |
if len(t.Images) != 1 { | |
return "", errors.New("found Tag but has no images") | |
} | |
if t.Images[0].Digest == digest { | |
hashTag = t.Name | |
break | |
} | |
} | |
if len(hashTag) == 0 { | |
return "", errors.New("could not find hash tag") | |
} | |
return hashTag, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment