如何获取 Harbor 中所有镜像 tag 标签

整理缘由

因自身在处于一个重交付的行业中,镜像的交付显得尤为重要,这样对于版本镜像的交付,因为 Harbor 的原因,需要点击到发版仓库中,然后选择发版镜像,在寻找发版tag,这样一级一级的整理,每次发版都需要耗费大量的时间整理100多个发版镜像,特此整理两个脚本进行批量获取,仅供参考。

也曾参考网上的文章,但脚本写的基本没有上来就能顺利执行的,而且也没有考虑 Harbor API 中给的默认 page_size = 10 ,当仓库数量或者镜像数量超过 10 个,都无法取全,所以花时间整理了一下 shell 脚本,并用 go 进行重写了一个命令,两个脚本都是可以正常执行,go 的执行时间会比 shell 的快一点,按需自取即可。

shell 脚本获取 harbor 镜像标签

#!/bin/bash
Harbor_Schema="http" # Harbor 登录协议,可选 http or https
Harbor_Address="harbor.k8s.local" #Harbor主机地址
Harbor_User="admin" #登录Harbor的用户
Harbor_Passwd=123456 #登录Harbor的用户密码
Images_File=harbor-images-`date '+%Y-%m-%d'`.txt # 镜像清单文件

# 检测是否含有 yq 命令
function check_yq() {
which yq
SINGLE=$?
if [[ $SINGLE -ne 0 ]] ; then
echo -e "本脚本强依赖 yq 命令,脚本会自动下载 yq 安装,如果不能联网,请手动至n https://github.com/mikefarah/yq/releases/tag/v4.27.2 n进行下载, 并上传至系统 PATH 路径下"
wget https://github.com/mikefarah/yq/releases/download/v4.27.2/yq_linux_amd64 -O /usr/bin/yq &&
chmod +x /usr/bin/yq
check_yq
else
echo "yq 命令已安装,正在检测 Harbor 状态..."
fi
}
check_yq
echo -e "正在将内容输出至 $Images_File 文件中,请稍等..."

# 获取Harbor中所有的项目(Projects)
Project_List=$(curl -u ${Harbor_User}:${Harbor_Passwd} -H "Content-Type: application/json" -X GET "${Harbor_Schema}://${Harbor_Address}/api/v2.0/projects?page_size=100" -k -s | yq '.[].name' -)

for Project in $Project_List;do
# 循环获取项目下所有的镜像
Image_Names=$(curl -u ${Harbor_User}:${Harbor_Passwd} -H "Content-Type: application/json" -X GET "${Harbor_Schema}://${Harbor_Address}/api/v2.0/projects/$Project/repositories?page_size=100" -k -s | yq '.[].name' -)
for Image in $Image_Names;do
# 循环获取镜像的版本(tag)
Image_Tags=$(curl -u ${Harbor_User}:${Harbor_Passwd} -H "Content-Type: application/json" -X GET ${Harbor_Schema}://${Harbor_Address}/v2/$Image/tags/list -k -s | yq '.tags' | awk -F "[" '{print $2}' | awk -F "]" '{print $1}' | sed 's/,//g')
for Tag in $Image_Tags;do
# 格式化输出镜像信息
echo "$Harbor_Address/$Image:$Tag" >> harbor-images-`date '+%Y-%m-%d'`.txt
done
done
done

echo -e "输出完成,请查看 $Images_File 文件"

执行结果脱敏示例:

如何获取 Harbor 中所有镜像 tag 标签

***@***MacBook-Pro Desktop % cat harbor-images-2022-08-17.txt
harbor.k8s.local/harbor/clickhouse:"22.3.3.44"
harbor.k8s.local/harbor/nginx:"20220719084929-3-main"
harbor.k8s.local/harbor/nginx:"20220719113621-1-main"
harbor.k8s.local/harbor/nginx:"20220727185042-2-main"
harbor.k8s.local/harbor/nginx:"20220727185218-4-main"

通过 GO 获取 harbor 镜像标签

与 shell 脚本唯一的区别就是增加了仓库的选项,shell 默认获取全部仓库,go 重写的可以支持只获取指定仓库的所有镜像的标签,对于有发版独立仓库的来说会比较友好一点。

使用方式

  go run harbor.go -h
-passwd string
harbor password, default 123456 (default "123456")
-repositry string
指定要选中的仓库,默认为 all,全部仓库 (default "all")
-schema string
http or https,default http (default "http")
-url string
harbor Address,deault harbor.k8s.local (default "harbor.k8s.local")
-user string
harbor admin, default admin (default "admin")
go run harbor.go --schema http --url harbor.k8s.local --user admin --passwd 123456 --repositry all

package main

import (
"encoding/json"
"flag"
"fmt"
"github.com/bitly/go-simplejson"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
)

// harbor 信息
type Infomation struct {
Schema string
URL string
User string
Pass string
}

// 镜像 tag
type ImageTag struct {
Name string `json:"name"`
Tags []string `json:"tags"`
}

// 获取 harbor 仓库的信息,返回列表
func (i *Infomation) HarborProject() ([]string, error) {
var rr []map[string]interface{}
u := i.Schema + "://" + i.URL + "/api/v2.0/projects"
req, err := http.NewRequest("GET", u, nil)
if err != nil {
panic(err)
}

params := make(url.Values)
params.Set("page_size", "100")
req.URL.RawQuery = params.Encode()
req.SetBasicAuth(i.User, i.Pass)
r, err := http.DefaultClient.Do(req)
body, err := ioutil.ReadAll(r.Body)

json.Unmarshal(body, &rr)

arrayHarbor := make([]string, 0)
for _, v := range rr {
b, _ := json.Marshal(v)
mapStr, err := simplejson.NewJson(b)
if err != nil {
panic(err)
}

pro_1, _ := mapStr.Get("name").String()
arrayHarbor = append(arrayHarbor, pro_1)
if err != nil {
panic(err)
}
}
return arrayHarbor, err
}

// 根据提供的 harbor 仓库的信息,获取仓库中的镜像信息列表
func (i *Infomation) HarborImage(project []string) ([]string, error) {
arrayimage := make([]string, 0)
var err error
for _, v := range project {
u := i.Schema + "://" + i.URL + "/api/v2.0/projects/" + v + "/repositories"
req, err := http.NewRequest("GET", u, nil)
if err != nil {
panic(err)
}
params := make(url.Values)
params.Set("page_size", "100")
req.URL.RawQuery = params.Encode()
req.SetBasicAuth(i.User, i.Pass)
r, err := http.DefaultClient.Do(req)
body, err := ioutil.ReadAll(r.Body)

var rr []map[string]interface{}
json.Unmarshal(body, &rr)

for _, v := range rr {
b, _ := json.Marshal(v)
mapStr, err := simplejson.NewJson(b)
if err != nil {
panic(err)
}

ime, err := mapStr.Get("name").String()
if err != nil {
panic(err)
}
arrayimage = append(arrayimage, ime)
}
}
return arrayimage, err
}

// 根据镜像信息,找到镜像中的 tag ,并写入至提供的 file 中
func (i *Infomation) HarborTag(ime []string, fileName string) error {
var err error
var imageTag ImageTag
//dstFile, err :=os.OpenFile(fileName, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0666)
dstFile, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
panic(err)
}
defer dstFile.Close()
log.Println("正在输出 harbor image tag 信息!!!n")
for _, v := range ime {
u := i.Schema + "://" + i.URL + "/v2/" + v + "/tags/list"
req, err := http.NewRequest("GET", u, nil)
if err != nil {
panic(err)
}
params := make(url.Values)
params.Set("page_size", "100")
req.URL.RawQuery = params.Encode()
req.SetBasicAuth(i.User, i.Pass)
r, err := http.DefaultClient.Do(req)
body, err := ioutil.ReadAll(r.Body)
json.Unmarshal(body, &imageTag)
for _, t := range imageTag.Tags {
tag := i.URL + "/" + imageTag.Name + ":" + t
fmt.Println(tag)
dstFile.WriteString(tag + "n")
}
}
fmt.Println("")
log.Printf("harbor image 信息输出至 %v 文件中,注意每次执行命令会覆盖之前的结果!!!", fileName)
//return arraytag, err
return err
}

// harbor cmd 的参数信息
func (i *Infomation) HarborCmd(f string) {
var repositry string
flag.StringVar(&i.Schema, "schema", "http", "http or https,default http")
flag.StringVar(&i.URL, "url", "harbor.k8s.local", "harbor Address,deault harbor.k8s.local")
flag.StringVar(&i.User, "user", "admin", "harbor admin, default admin")
flag.StringVar(&i.Pass, "passwd", "123456", "harbor password, default 123456")
flag.StringVar(&repositry, "repositry", "all", "指定要选中的仓库,默认为 all,全部仓库")
flag.Parse()

if flag.NFlag() == 0 {
log.Fatal("此命令必须传入参数, 否则无法执行n -passwd stringn harbor password, default 123456 (default "123456")n -repositry stringn 指定要选中的仓库,默认为 all,全部仓库 (default "all")n http or https,default http (default "http")n -url stringn harbor Address,deault harbor.k8s.local (default "harbor.k8s.local")n -user stringn harbor admin, default admin (default "admin")nn示例:run harbor.go --schema http --url harbor.k8s.local --user admin --passwd 123456 --repositry alln")
}

if repositry == "all" {
project, err := i.HarborProject()
if err != nil {
panic(err)
}

imagelist, err := i.HarborImage(project)
if err != nil {
panic(err)
}

i.HarborTag(imagelist, f)
} else {
imagelist, err := i.HarborImage([]string{repositry})
if err != nil {
panic(err)
}

i.HarborTag(imagelist, f)
}

}

func main() {
var i Infomation
fileName := "./harborImageList.txt"
i.HarborCmd(fileName)
}

示例执行脱敏结果:

***@***MacBook-Pro Desktop % cat harborImageList.txt 
harbor.k8s.local/harbor/clickhouse:22.3.3.44
harbor.k8s.local/harbor/nginx:20220719084929-3-main
harbor.k8s.local/harbor/nginx:20220719113621-1-main
harbor.k8s.local/harbor/nginx:20220727185042-2-main
harbor.k8s.local/harbor/nginx:20220727185218-4-main
发表评论

相关文章