自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何快速刪除 Harbor 鏡像

開(kāi)發(fā) 項(xiàng)目管理
細(xì)問(wèn)之下得知,該項(xiàng)目目前處于調(diào)試階段,每天調(diào)試很多次。既然存儲(chǔ)空間不多了,那就去harbor上刪除掉之前的鏡像標(biāo)簽,保留最近的幾個(gè)就好了。在手動(dòng)刪除的過(guò)程中,發(fā)現(xiàn)幾百個(gè),每頁(yè)才展示十個(gè)。我得先按照推送時(shí)間排序,然后一頁(yè)一頁(yè)的刪除。心想著這種情況經(jīng)歷一次就好了,不要再有下一次。

[[429946]]

本文轉(zhuǎn)載自微信公眾號(hào)「運(yùn)維開(kāi)發(fā)故事」,作者華仔。轉(zhuǎn)載本文請(qǐng)聯(lián)系運(yùn)維開(kāi)發(fā)故事公眾號(hào)。

背景

最近在巡檢過(guò)程中,發(fā)現(xiàn)harbor存儲(chǔ)空間使用率已經(jīng)達(dá)到了80%。于是,去看了一下各項(xiàng)目下的鏡像標(biāo)簽數(shù)。發(fā)現(xiàn)有個(gè)別項(xiàng)目下的鏡像標(biāo)簽數(shù)竟然有好幾百個(gè)。細(xì)問(wèn)之下得知,該項(xiàng)目目前處于調(diào)試階段,每天調(diào)試很多次。既然存儲(chǔ)空間不多了,那就去harbor上刪除掉之前的鏡像標(biāo)簽,保留最近的幾個(gè)就好了。在手動(dòng)刪除的過(guò)程中,發(fā)現(xiàn)幾百個(gè),每頁(yè)才展示十個(gè)。我得先按照推送時(shí)間排序,然后一頁(yè)一頁(yè)的刪除。心想著這種情況經(jīng)歷一次就好了,不要再有下一次。后來(lái),仔細(xì)想想,這個(gè)也是不好控制的,每次巡檢發(fā)現(xiàn)了就得手動(dòng)刪除太麻煩。所以就打算寫(xiě)一個(gè)腳本,每次通過(guò)腳本去刪除鏡像的標(biāo)簽,保留最近的幾個(gè)就好了。剛好最近在學(xué)習(xí)golang,就用它來(lái)寫(xiě)就好了。比較尷尬的是,我腳本寫(xiě)完了,測(cè)試沒(méi)問(wèn)題后,發(fā)現(xiàn)新版本harbor已經(jīng)可以在UI上設(shè)置保留策略了。自我安慰一下,就當(dāng)作是一種練習(xí)、嘗試好了!

目標(biāo)

  1. 通過(guò)命令行能夠查詢當(dāng)前所有的項(xiàng)目、無(wú)論是否公開(kāi)、倉(cāng)庫(kù)數(shù)量
  2. 通過(guò)命令行能夠查詢項(xiàng)目下的倉(cāng)庫(kù)名和鏡像名、拉取次數(shù)
  3. 在命令行能夠指定標(biāo)簽和保留個(gè)數(shù)進(jìn)行刪除鏡像標(biāo)簽
  4. 能夠獲取鏡像的標(biāo)簽數(shù)
  5. 刪除后,不支持立刻垃圾清理,請(qǐng)手動(dòng)進(jìn)行垃圾清理(考慮清理過(guò)程中無(wú)法推拉鏡像)

聲明

該腳本純屬個(gè)人練習(xí)所寫(xiě),不構(gòu)成任何建議

初學(xué)golang,僅僅是為了實(shí)現(xiàn)目標(biāo),代碼質(zhì)量極差,請(qǐng)諒解

本次使用的harbor是v2.3.1

全部代碼請(qǐng)移步至github

實(shí)現(xiàn)

獲取harbor中所有的項(xiàng)目,API可通過(guò)harbor的 swagger獲取

  1. //根據(jù)harbor swagger測(cè)試出來(lái)的結(jié)果定義要獲取的數(shù)據(jù)結(jié)構(gòu) 
  2. type MetaData struct { 
  3.  Public string `json:"public"
  4. type ProjectData struct { 
  5.  MetaData MetaData `json:"metadata"
  6.  ProjectId int `json:"project_id"
  7.  Name string `json:"name"
  8.  RepoCount int `json:"repo_count"
  9.  
  10. type PData []ProjectData 
  11. // 提供harbor地址獲取project 
  12. func GetProject(url string) []map[string]string { 
  13.  //定義url 
  14.  url = url + "/api/v2.0/projects" 
  15.  //url = url + "/api/projects" 
  16.     // 構(gòu)造請(qǐng)求 
  17.  request, _ := http.NewRequest(http.MethodGet, url,nil) 
  18.     //取消驗(yàn)證 
  19.  tr := &http.Transport{ 
  20.   TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 
  21.  } 
  22.     //定義客戶端 
  23.  client := &http.Client{Timeout: 10 * time.Second, Transport: tr} 
  24.  //client := &http.Client{Timeout: 10 * time.Second
  25.  request.Header.Set("accept""application/json"
  26.     //設(shè)置用戶和密碼 
  27.  request.SetBasicAuth("admin""Harbor12345"
  28.  response, err := client.Do(request) 
  29.  
  30.  if err != nil { 
  31.   fmt.Println("excute failed"
  32.   fmt.Println(err) 
  33.  } 
  34.  // 獲取body 
  35.  body, _ := ioutil.ReadAll(response.Body) 
  36.  defer response.Body.Close() 
  37.  ret := PData{} 
  38.  json.Unmarshal([]byte(string(body)), &ret) 
  39.  var ps = []map[string]string{} 
  40.     // 獲取返回的數(shù)據(jù) 
  41.  for i := 0; i < len(ret); i++ { 
  42.   RData := make(map[string]string) 
  43.   RData["name"] = (ret[i].Name
  44.   RData["project_id"] = strconv.Itoa(ret[i].ProjectId) 
  45.   RData["repo_count"] =strconv.Itoa(ret[i].RepoCount) 
  46.   RData["public"] = ret[i].MetaData.Public 
  47.  
  48.   ps = append(ps, RData) 
  49.  } 
  50.  return ps 

獲取項(xiàng)目下的repo

  1. // 定義要獲取的數(shù)據(jù)結(jié)構(gòu) 
  2. type ReposiData struct { 
  3.  Id int `json:"id"
  4.  Name string `json:"name"
  5.  ProjectId int `json:"project_id"
  6.  PullCount int `json:"pull_count"
  7.  
  8. type RepoData []ReposiData 
  9. //通過(guò)提供harbor地址和對(duì)應(yīng)的項(xiàng)目來(lái)獲取項(xiàng)目下的repo 
  10. func GetRepoData(url string, proj string)  []map[string]string { 
  11.  // /api/v2.0/projects/goharbor/repositories 
  12.  url = url + "/api/v2.0/projects/" + proj +  "/repositories" 
  13.     //構(gòu)造請(qǐng)求 
  14.  request, _ := http.NewRequest(http.MethodGet, url,nil) 
  15.     //忽略認(rèn)證 
  16.  tr := &http.Transport{ 
  17.   TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 
  18.  } 
  19.  client := &http.Client{Timeout: 10 * time.Second, Transport: tr} 
  20.  request.Header.Set("accept""application/json"
  21.     //設(shè)置用戶名和密碼 
  22.  request.SetBasicAuth("admin""Harbor12345"
  23.  response, err := client.Do(request) 
  24.  
  25.  if err != nil { 
  26.   fmt.Println("excute failed"
  27.   fmt.Println(err) 
  28.  } 
  29.  // 獲取body 
  30.  body, _ := ioutil.ReadAll(response.Body) 
  31.  defer response.Body.Close() 
  32.  ret := RepoData{} 
  33.  json.Unmarshal([]byte(string(body)), &ret) 
  34.  var ps = []map[string]string{} 
  35.     // 獲取返回的數(shù)據(jù) 
  36.  for i := 0; i < len(ret); i++ { 
  37.   RData := make(map[string]string) 
  38.   RData["name"] = (ret[i].Name
  39.   pId := strconv.Itoa(ret[i].ProjectId) 
  40.   RData["project_id"] = pId 
  41.   RData["id"] =(strconv.Itoa(ret[i].Id)) 
  42.   RData["pullCount"] = (strconv.Itoa(ret[i].PullCount)) 
  43.   ps = append(ps, RData) 
  44.  } 
  45.  return ps 

鏡像tag操作

  1. //定義要獲取的tag數(shù)據(jù)結(jié)構(gòu) 
  2. type Tag struct { 
  3.  ArtifactId int  `json:"artifact_id"
  4.  Id int `json:"id"
  5.  Name string `json:"name"
  6.  RepositoryId int `json:"repository_id"
  7.  PushTimte string `json:"push_time"
  8.  
  9. type Tag2 struct { 
  10.  ArtifactId string  `json:"artifact_id"
  11.  Id string `json:"id"
  12.  Name string `json:"name"
  13.  RepositoryId string `json:"repository_id"
  14.  PushTimte string `json:"push_time"
  15.  
  16. type Tag2s []Tag2 
  17. // delete tag by specified count,這里通過(guò)count先獲取要?jiǎng)h除的tag列表 
  18. func DeleTagsByCount(tags []map[string]string ,count int) []string { 
  19.  var re []string 
  20.   
  21.  tt := tags[0]["tags"
  22.  ss := Tag2s{} 
  23.  json.Unmarshal([]byte(tt), &ss) 
  24.  
  25.  // have a sort 
  26.  for i := 0; i < len(ss); i++ { 
  27.   for j := i + 1; j < len(ss); j++ { 
  28.             //根據(jù)pushtime進(jìn)行排序 
  29.    if ss[i].PushTimte > ss[j].PushTimte { 
  30.     ss[i], ss[j] = ss[j], ss[i] 
  31.    } 
  32.   } 
  33.  } 
  34.  // get all tags 
  35.  for i := 0; i < len(ss); i++ { 
  36.   re = append(re, ss[i].Name
  37.  } 
  38.  // 返回count個(gè)會(huì)被刪除的tag, 
  39.  return re[0:count
  40.  
  41. // delete tag by specified tag 刪除指定的tag 
  42. func DelTags(url string, project string, repo string, tag string) (int, map[string]interface{})  { 
  43.  url = url + "/api/v2.0/projects/" + project + "/repositories/" + repo + "/artifacts/" + tag + "/tags/" + tag 
  44.  request, _ := http.NewRequest(http.MethodDelete, url,nil) 
  45.  tr := &http.Transport{ 
  46.   TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 
  47.  } 
  48.  client := &http.Client{Timeout: 10 * time.Second, Transport: tr} 
  49.  request.Header.Set("accept""application/json"
  50.  request.SetBasicAuth("admin""Pwd123456"
  51.     // 執(zhí)行刪除tag 
  52.  response,_ := client.Do(request) 
  53.  defer response.Body.Close() 
  54.  
  55.  var result map[string]interface{} 
  56.  bd, err := ioutil.ReadAll(response.Body) 
  57.  if err == nil { 
  58.   err = json.Unmarshal(bd, &result) 
  59.  } 
  60.  return response.StatusCode,result 
  61.  
  62.  
  63.  
  64.  
  65.  
  66. //定義要獲取的tag數(shù)據(jù)結(jié)構(gòu) 
  67. type ArtiData struct { 
  68.  Id int `json:"id"
  69.  ProjectId int `json:"project_id"
  70.  RepositoryId int `json:"repository_id"
  71.  //Digest string `json:"digest"
  72.  Tags []Tag `json:"tags"
  73.  
  74. type AData []ArtiData 
  75. // 根據(jù)harbor地址、project和repo獲取tag數(shù)據(jù) 
  76. func GetTags(url string, project string, repo string) []map[string]string { 
  77.  url = url + "/api/v2.0/projects/" + project + "/repositories/" + repo + "/artifacts" 
  78.  request, _ := http.NewRequest(http.MethodGet, url,nil) 
  79.  tr := &http.Transport{ 
  80.   TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 
  81.  } 
  82.  client := &http.Client{Timeout: 10 * time.Second, Transport: tr} 
  83.  request.Header.Set("accept""application/json"
  84.  request.Header.Set("X-Accept-Vulnerabilities""application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0"
  85.  request.SetBasicAuth("admin""Harbor12345"
  86.     // 獲取tag 
  87.  response, err := client.Do(request) 
  88.  
  89.  if err != nil { 
  90.   fmt.Println("excute failed"
  91.   fmt.Println(err) 
  92.  } 
  93.  
  94.  body, _ := ioutil.ReadAll(response.Body) 
  95.  defer response.Body.Close() 
  96.  ret := AData{} 
  97.  json.Unmarshal([]byte(string(body)),&ret) 
  98.  var ps = []map[string]string{} 
  99.  sum := 0 
  100.  RData := make(map[string]string) 
  101.  RData["name"] = repo 
  102.     // 獲取返回的數(shù)據(jù) 
  103.  for i := 0; i < len(ret); i++ { 
  104.  
  105.   RData["id"] = (strconv.Itoa(ret[i].Id)) 
  106.   RData["project_id"] = (strconv.Itoa(ret[i].ProjectId)) 
  107.   RData["repository_id"] =(strconv.Itoa(ret[i].RepositoryId)) 
  108.   //RData["digest"] = ret[i].Digest 
  109.   var tdata = []map[string]string{} 
  110.   sum = len((ret[i].Tags)) 
  111.         // 獲取tag 
  112.   for j := 0; j < len((ret[i].Tags)); j++ { 
  113.    TagData := make(map[string]string) 
  114.    TagData["artifact_id"] = strconv.Itoa((ret[i].Tags)[j].ArtifactId) 
  115.    TagData["id"] = strconv.Itoa((ret[i].Tags)[j].Id) 
  116.    TagData["name"] = (ret[i].Tags)[j].Name 
  117.    TagData["repository_id"] = strconv.Itoa((ret[i].Tags)[j].RepositoryId) 
  118.    TagData["push_time"] = (ret[i].Tags)[j].PushTimte 
  119.    tdata = append(tdata, TagData) 
  120.   } 
  121.   RData["count"] = strconv.Itoa(sum
  122.   ss, err := json.Marshal(tdata) 
  123.   if err != nil { 
  124.    fmt.Println("failed"
  125.    os.Exit(2) 
  126.   } 
  127.   RData["tags"] = string(ss) 
  128.   ps = append(ps, RData) 
  129.  
  130.  } 
  131.  return ps 

獲取用戶命令行輸入,列出harbor中所有的項(xiàng)目

  1. // 定義獲取harbor中project的相關(guān)命令操作 
  2. var projectCmd = &cobra.Command{ 
  3.  Use: "project"
  4.  Short: "to operator project"
  5.  Run: func(cmd *cobra.Command, args []string) { 
  6.  
  7.   output, err := ExecuteCommand("harbor","project", args...) 
  8.   if err != nil { 
  9.    Error(cmd,args, err) 
  10.   } 
  11.   fmt.Fprint(os.Stdout, output
  12.  }, 
  13. // project list 
  14. var projectLsCmd = &cobra.Command{ 
  15.  Use: "ls"
  16.  Short: "list  all project"
  17.  Run: func(cmd *cobra.Command, args []string) { 
  18.   url, _ := cmd.Flags().GetString("url"
  19.   if len(url) == 0 { 
  20.    fmt.Println("url is null,please specified the harbor url first !!!!"
  21.    os.Exit(2) 
  22.   } 
  23.         // 獲取所有的project 
  24.   output := harbor.GetProject(url) 
  25.   fmt.Println("項(xiàng)目名 訪問(wèn)級(jí)別 倉(cāng)庫(kù)數(shù)量"
  26.   for i := 0; i < len(output); i++ { 
  27.  
  28.    fmt.Println(output[i]["name"], output[i]["public"], output[i]["repo_count"]) 
  29.   } 
  30.  }, 
  31. // init 
  32. func init() { 
  33.     // ./harbor project ls -u https:// 
  34.  rootCmd.AddCommand(projectCmd) 
  35.  projectCmd.AddCommand(projectLsCmd) 
  36.  projectLsCmd.Flags().StringP("url""u""","defaults: [https://127.0.0.1]"

獲取repo列表

  1. // repo command 
  2. var repoCmd = &cobra.Command{ 
  3.  Use: "repo"
  4.  Short: "to operator repository"
  5.  Run: func(cmd *cobra.Command, args []string) { 
  6.  
  7.   output, err := ExecuteCommand("harbor","repo", args...) 
  8.   if err != nil { 
  9.    Error(cmd,args, err) 
  10.   } 
  11.   fmt.Fprint(os.Stdout, output
  12.  }, 
  13. // repo list 
  14. var repoLsCmd = &cobra.Command{ 
  15.  Use: "ls"
  16.  Short: "list  project's repository"
  17.  Run: func(cmd *cobra.Command, args []string) { 
  18.   url, _ := cmd.Flags().GetString("url"
  19.   project, _ := cmd.Flags().GetString("project"
  20.   if len(project) == 0 { 
  21.    fmt.Println("sorry, you must specified the project which you want to show repository !!!"
  22.    os.Exit(2) 
  23.   } 
  24.         // get all repo  
  25.   output := harbor.GetRepoData(url, project) 
  26.         // 展示數(shù)據(jù) 
  27.   fmt.Println("倉(cāng)庫(kù)名----------拉取次數(shù)"
  28.   for i := 0; i < len(output); i++ { 
  29.    fmt.Println(output[i]["name"],output[i]["pullCount"]) 
  30.   } 
  31.  }, 
  32.  
  33. func init() { 
  34.     // ./harbor repo ls -u https:// -p xxx 
  35.  rootCmd.AddCommand(repoCmd) 
  36.  repoCmd.AddCommand(repoLsCmd) 
  37.  repoLsCmd.Flags().StringP("url""u""","defaults: [https://127.0.0.1]"
  38.  repoLsCmd.Flags().StringP("project""p","""the project"

tag操作

  1. // tag command 
  2. var tagCmd = &cobra.Command{ 
  3.  Use: "tag"
  4.  Short: "to operator image"
  5.  Run: func(cmd *cobra.Command, args []string) { 
  6.  
  7.   output, err := ExecuteCommand("harbor","tag", args...) 
  8.   if err != nil { 
  9.    Error(cmd,args, err) 
  10.   } 
  11.   fmt.Fprint(os.Stdout, output
  12.  }, 
  13. // tag ls 
  14. var tagLsCmd = &cobra.Command{ 
  15.  Use: "ls"
  16.  Short: "list  all tags of the repository you have specified which you should specified project at the same time"
  17.  Run: func(cmd *cobra.Command, args []string) { 
  18.   url, _ := cmd.Flags().GetString("url"
  19.   project, _ := cmd.Flags().GetString("project"
  20.   repo, _ := cmd.Flags().GetString("repo"
  21.         // get all tags  
  22.   ss := harbor.GetTags(url, project, repo) 
  23.   for i := 0; i < len(ss); i++ { 
  24.    count, _ := strconv.Atoi((ss[i])["count"]) 
  25.    fmt.Printf("the repo %s has %d images\n", repo, count
  26.   } 
  27.  
  28.  }, 
  29.  
  30. // tag del by tag or the number of image you want to save 
  31. var tagDelCmd = &cobra.Command{ 
  32.  Use: "del"
  33.  Short: "delete the tags of the repository you have specified which you should specified project at the same time"
  34.  Run: func(cmd *cobra.Command, args []string) { 
  35.         // 獲取用戶輸入并轉(zhuǎn)格式 
  36.   url, _ := cmd.Flags().GetString("url"
  37.   project, _ := cmd.Flags().GetString("project"
  38.   repo, _ := cmd.Flags().GetString("repo"
  39.   tag,_ := cmd.Flags().GetString("tag"
  40.   count,_ := cmd.Flags().GetString("count"
  41.   ret,_ := strconv.Atoi(count
  42.   if len(tag) != 0 && ret != 0 { 
  43.     fmt.Println("You can't choose both between count and tag"
  44.     os.Exit(2) 
  45.   } else if len(tag) == 0 && ret != 0 { 
  46.             // get all tags 
  47.    retu := harbor.GetTags(url, project, repo) 
  48.             //delete tag by you hsve specied the number of the images you want to save 
  49.    rTagCount, _ := strconv.Atoi((retu[0])["count"]) 
  50.             // 根據(jù)用戶輸入的count和實(shí)際tag數(shù)進(jìn)行對(duì)比,決定是否去執(zhí)行刪除tag 
  51.    if ret == rTagCount { 
  52.     fmt.Printf("the repository %s of the project %s only have %d tags, so you can't delete tags and we will do nothing!!\n", repo, project,ret) 
  53.    } else if ret > rTagCount { 
  54.     fmt.Printf("the repository %s of the project %s only have %d tags, but you want to delete %d tags, so we suggest you to have a rest and we will do nothing!!\n", repo, project,rTagCount, ret) 
  55.    } else { 
  56.                 // 可以執(zhí)行刪除tag 
  57.     fmt.Printf("we will save the latest %d tags  and delete other %d tags !!!\n", ret, (rTagCount - ret)) 
  58.     tags := harbor.GetTags(url, project, repo) 
  59.     retu := harbor.DeleTagsByCount(tags, (rTagCount - ret)) 
  60.     for i := 0 ; i < len(retu); i++ { 
  61.                     // to delete tag 
  62.      code, msg := harbor.DelTags(url, project, repo, retu[i]) 
  63.      fmt.Printf("the tag %s is deleted,status code is %d, msg is %s\n", retu[i], code, msg) 
  64.     } 
  65.    } 
  66.   } else { 
  67.             // delete tag by you specied tag 
  68.    code, msg := harbor.DelTags(url, project, repo, tag) 
  69.    fmt.Println(code, msg["errors"]) 
  70.   } 
  71.  }, 
  72.  
  73.  
  74.  
  75. func init() { 
  76.     // ./harbor tag ls -u -p -r 
  77.  rootCmd.AddCommand(tagCmd) 
  78.  tagCmd.AddCommand(tagLsCmd) 
  79.  tagLsCmd.Flags().StringP("url""u""","defaults: [https://127.0.0.1]"
  80.  tagLsCmd.Flags().StringP("project""p""","the project"
  81.  tagLsCmd.Flags().StringP("repo""r""","the repository"
  82.  // ./harbor tag del -u -p -r [-t | -c] 
  83.  tagCmd.AddCommand(tagDelCmd) 
  84.  tagDelCmd.Flags().StringP("url""u""","defaults: [https://127.0.0.1]"
  85.  tagDelCmd.Flags().StringP("project""p""","the project which you should specified if you want to delete the tag of any repository "
  86.  tagDelCmd.Flags().StringP("repo""r""","the repository which you should specified if you want to delete the tag"
  87.  tagDelCmd.Flags().StringP("tag""t""","the tag, You can't choose  it with tag together"
  88.  tagDelCmd.Flags().StringP("count""c""","the total number you want to save.for example: you set --count=10, we will save the 10 latest tags by use push_time to sort,can't choose it with tag together"

測(cè)試

  1. //獲取幫助 
  2. harbor % ./harbor -h https://harbor.zaizai.com 
  3. Usage: 
  4.   harbor [flags] 
  5.   harbor [command] 
  6.  
  7. Available Commands: 
  8.   completion  generate the autocompletion script for the specified shell 
  9.   help        Help about any command 
  10.   project     to operator project 
  11.   repo        to operator repository 
  12.   tag         to operator image 
  13.  
  14. Flags: 
  15.   -h, --help   help for harbor 
  16.  
  17. Use "harbor [command] --help" for more information about a command. 
  18.  
  19. //列出所有project 
  20.  harbor % ./harbor  project ls -u https://harbor.zaizai.com 
  21. 項(xiàng)目名 訪問(wèn)級(jí)別 倉(cāng)庫(kù)數(shù)量 
  22. goharbor false 3 
  23. library true 0 
  24. public true 1 
  25.  
  26. //列出所有repo 
  27. harbor % ./harbor  repo  ls -u https://harbor.zaizai.com -p goharbor 
  28. 倉(cāng)庫(kù)名----------拉取次數(shù) 
  29. goharbor/harbor-portal 0 
  30. goharbor/harbor-db 1 
  31. goharbor/prepare 0 
  32.  
  33. //列出tags harbor % ./harbor  tag   ls -u https://harbor.zaizai.com -p goharbor -r harbor-db 
  34. the repo harbor-db has 9 images 
  35.  
  36. // 通過(guò)保留最近20個(gè)鏡像去刪除tag 
  37. harbor % ./harbor  tag   del  -u https://harbor.zaizai.com -p goharbor -r harbor-db -c 20     
  38. the repository harbor-db of the project goharbor only have 9 tags, but you want to delete 20 tags, so we suggest you to have a rest and we will do nothing!! 
  39.  
  40. // 通過(guò)保留最近10個(gè)鏡像去刪除tag 
  41. harbor % ./harbor  tag   del  -u https://harbor.zaizai.com -p goharbor -r harbor-db -c 10 
  42. the repository harbor-db of the project goharbor only have 9 tags, but you want to delete 10 tags, so we suggest you to have a rest and we will do nothing!! 
  43.  
  44. // 通過(guò)保留最近5個(gè)鏡像去刪除tag 
  45. harbor % ./harbor  tag   del  -u https://harbor.zaizai.com -p goharbor -r harbor-db -c 5  
  46. we will save the latest 5 tags  and delete other 4 tags !!! 
  47. the tag v2.3.9 is deleted,status code is 200, msg is map[] 
  48. the tag v2.3.10 is deleted,status code is 200, msg is map[] 
  49. the tag v2.3.8 is deleted,status code is 200, msg is map[] 
  50. the tag v2.3.7 is deleted,status code is 200, msg is map[] 
  51.  
  52. //指定tag進(jìn)行刪除 
  53. caicloud@MacBook-Pro-2 harbor % ./harbor tag   del  -u https://harbor.zaizai.com -p goharbor -r harbor-db  -t v2.3.6 
  54. 200 <nil> 
  55.  
  56. ?。。?! 最后需要手動(dòng)去harbor UI上進(jìn)行垃圾回收?。?! 

參考

https://github.com/spf13/cobra

 

harbor swagger

 

責(zé)任編輯:武曉燕 來(lái)源: 運(yùn)維開(kāi)發(fā)故事
相關(guān)推薦

2022-07-11 07:37:55

HarborContainerd

2022-09-16 10:19:36

HarborContainerd

2024-01-22 09:12:51

2017-03-24 09:24:21

HarborDocker鏡像倉(cāng)庫(kù)

2021-12-22 10:45:56

Docker RegiHarborLinux

2020-11-25 08:57:29

Redis Docke

2023-04-06 10:08:58

2021-02-23 15:05:55

Docker鏡像開(kāi)發(fā)

2021-02-03 10:43:54

Linux系統(tǒng)磁盤(pán)

2010-09-01 17:19:49

SQL刪除TABLE

2010-09-02 11:38:44

SQL刪除

2018-08-29 12:30:45

數(shù)據(jù)庫(kù)MySQLInnodb

2023-04-06 09:53:21

Harbor企業(yè)級(jí)服務(wù)

2023-03-03 00:07:24

2011-05-13 11:05:59

oracle刪除

2019-07-30 16:16:11

Windows 10刪除快速訪問(wèn)

2010-07-02 13:50:11

SQL Server數(shù)

2010-09-16 16:17:03

TRUNCATE TA

2021-09-23 10:30:21

Docker RegiHarborLinux

2022-08-21 16:50:36

Kubeadm?Kubernetes
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)