zoukankan      html  css  js  c++  java
  • Harbor 2.0 通过API删除指定Tag镜像

    Harbor 2.0 通过API删除指定Tag镜像

    背景

    希望在发布系统中显示的镜像都是上次发布成功的版本,回滚镜像的时候保证是上次成功过的版本,所以当发布失败的时候,从Harbor仓库中删除掉对应的Tag镜像

    1、Harbor Python SDK

    来源:https://github.com/yangpeng14/harbor_sdk_v2.0

    #!/usr/bin/env python3
    # -*- coding=utf8 -*-
    
    import logging
    import requests
    
    logging.basicConfig(level=logging.INFO)
    
    
    class HarborClient(object):
        def __init__(self, host, user, password, protocol="http"):
            self.host = host
            self.user = user
            self.password = password
            self.protocol = protocol
    
            # 第一次get请求,获取 cookie 信息
            self.cookies, self.headers = self.get_cookie()
    
            # 获取登陆成功 session
            self.session_id = self.login()
    
            # 把登陆成功的 sid值 替换 get_cookie 方法中 cookie sid值,用于 delete 操作
            self.cookies_new = self.cookies
            self.cookies_new.update({'sid': self.session_id})
    
        # def __del__(self):
        #     self.logout()
    
        def get_cookie(self):
            response = requests.get("{0}://{1}/c/login".format(self.protocol, self.host))
            csrf_cookie = response.cookies.get_dict()
            headers = {'X-Harbor-CSRF-Token': csrf_cookie['__csrf']}
            return csrf_cookie, headers
    
        def login(self):
            login_data = requests.post('%s://%s/c/login' %
                                       (self.protocol, self.host),
                                       data={'principal': self.user,
                                             'password': self.password}, cookies=self.cookies, headers=self.headers)
    
            if login_data.status_code == 200:
                session_id = login_data.cookies.get('sid')
    
                logging.debug("Successfully login, session id: {}".format(
                    session_id))
                return session_id
            else:
                logging.error("Fail to login, please try again")
                return None
    
        def logout(self):
            requests.get('%s://%s/c/logout' % (self.protocol, self.host),
                         cookies={'sid': self.session_id})
            logging.debug("Successfully logout")
    
        # GET /projects
        def get_projects(self, project_name=None, is_public=None):
            # TODO: support parameter
            result = []
            page = 1
            page_size = 15
    
            while True:
                path = '%s://%s/api/v2.0/projects?page=%s&page_size=%s' % (self.protocol, self.host, page, page_size)
                response = requests.get(path,
                                        cookies={'sid': self.session_id})
                if response.status_code == 200:
                    logging.debug("Successfully get projects result: {}".format(
                        result))
                    if isinstance(response.json(), list):
                        result.extend(response.json())
                        page += 1
                    else:
                        break
                else:
                    logging.error("Fail to get projects result")
                    result = None
                    break
            return result
    
        # GET /projects/{project_name}/repositories
        def get_repositories(self, project_name, query_string=None):
            # TODO: support parameter
            result = []
            page = 1
            page_size = 15
    
            while True:
                path = '%s://%s/api/v2.0/projects/%s/repositories?page=%s&page_size=%s' % (
                    self.protocol, self.host, project_name, page, page_size)
                response = requests.get(path,
                                        cookies={'sid': self.session_id})
                if response.status_code == 200:
                    logging.debug(
                        "Successfully get repositories with name: {}, result: {}".format(
                            project_name, result))
                    if len(response.json()):
                        result.extend(response.json())
                        page += 1
                    else:
                        break
                else:
                    logging.error("Fail to get repositories result with name: {}".format(
                        project_name))
                    result = None
                    break
            return result
    
        # GET /projects/{project_name}/repositories/{repository_name}/artifacts
        # GET /projects/{project_name}/repositories/{repository_name}/artifacts?with_tag=true&with_scan_overview=true&with_label=true&page_size=15&page=1
        def get_repository_artifacts(self, project_name, repository_name):
            result = []
            page = 1
            page_size = 15
    
            while True:
                path = '%s://%s/api/v2.0/projects/%s/repositories/%s/artifacts?with_tag=true&with_scan_overview=true&with_label=true&page_size=%s&page=%s' % (
                    self.protocol, self.host, project_name, repository_name, page_size, page)
                response = requests.get(path,
                                        cookies={'sid': self.session_id}, timeout=60)
                if response.status_code == 200:
                    logging.debug(
                        "Successfully get repositories artifacts with name: {}, {}, result: {}".format(
                            project_name, repository_name, result))
                    if len(response.json()):
                        result.extend(response.json())
                        page += 1
                    else:
                        break
                else:
                    logging.error("Fail to get repositories artifacts result with name: {}, {}".format(
                        project_name, repository_name))
                    result = None
                    break
            return result
    
        # DELETE /projects/{project_name}/repositories/{repository_name}
        def delete_repository(self, project_name, repository_name, tag=None):
            # TODO: support to check tag
            # TODO: return 200 but the repo is not deleted, need more test
            result = False
            path = '%s://%s/api/v2.0/projects/%s/repositories/%s' % (
                self.protocol, self.host, project_name, repository_name)
            response = requests.delete(path,
                                       cookies=self.cookies_new, headers=self.headers)
            if response.status_code == 200:
                result = True
                print("Delete {} successful!".format(repository_name))
                logging.debug("Successfully delete repository: {}".format(
                    repository_name))
            else:
                logging.error("Fail to delete repository: {}".format(repository_name))
            return result
    
        # Get /projects/{project_name}/repositories/{repository_name}/artifacts/{reference}/tags
        def get_repository_tags(self, project_name, repository_name, reference_hash):
            result = None
            path = '%s://%s/api/v2.0/projects/%s/repositories/%s/artifacts/%s/tags' % (
                self.protocol, self.host, project_name, repository_name, reference_hash)
            response = requests.get(path,
                                    cookies={'sid': self.session_id}, timeout=60)
            if response.status_code == 200:
                result = response.json()
                logging.debug(
                    "Successfully get tag with repository name: {}, result: {}".format(
                        repository_name, result))
            else:
                logging.error("Fail to get tags with repository name: {}".format(
                    repository_name))
            return result
    
        # Del /projects/{project_name}/repositories/{repository_name}/artifacts/{reference}/tags/{tag_name}
        def del_repository_tag(self, project_name, repository_name, reference_hash, tag):
            result = False
            path = '%s://%s/api/v2.0/projects/%s/repositories/%s/artifacts/%s/tags/%s' % (
                self.protocol, self.host, project_name, repository_name, reference_hash, tag)
            response = requests.delete(path, cookies=self.cookies_new, headers=self.headers)
            if response.status_code == 200:
                result = True
                print("Delete {} {} {} {} successful!".format(project_name, repository_name, reference_hash, tag))
                logging.debug(
                    "Successfully delete repository project_name: {}, repository_name: {}, reference_hash: {}, tag: {}".format(
                        project_name, repository_name, reference_hash, tag))
            else:
                logging.error(
                    "Fail to delete repository project_name: {}, repository_name: {}, reference_hash: {}, tag: {}".format(
                        project_name, repository_name, reference_hash, tag))
            return result
    
        # Del /projects/{project_name}/repositories/{repository_name}/artifacts/{reference}
        def del_artifacts_hash(self, project_name, repository_name, reference_hash):
            result = False
            path = '%s://%s/api/v2.0/projects/%s/repositories/%s/artifacts/%s' % (
                self.protocol, self.host, project_name, repository_name, reference_hash)
            response = requests.delete(path, cookies=self.cookies_new, headers=self.headers)
            if response.status_code == 200:
                result = True
                print("Delete artifacts hash {} {} {} successful!".format(project_name, repository_name, reference_hash))
                logging.debug(
                    "Successfully delete repository project_name: {}, repository_name: {}, artifacts hash: {}".format(
                        project_name, repository_name, reference_hash))
            else:
                logging.error("Fail to delete repository project_name: {}, repository_name: {}, artifacts hash: {}".format(
                    project_name, repository_name, reference_hash))
            return result
    

    2、使用

    需要传3个参数,一个是项目名称namespace(我这项目名称对应的是K8s里的命名空间),第二个是repository_name名称,第三个镜像的Tag,这个我是公司发布系统中取到对应的值

    import harborclient_modify_v2_0
    
    import json
    
    import sys
    
    
    class GetHarborApi(object):
        def __init__(self, host, user, password, protocol="http"):
            self.host = host
            self.user = user
            self.password = password
            self.protocol = protocol
            self.client = harborclient_modify_v2_0.HarborClient(self.host, self.user, self.password, self.protocol)
    
        def main(self, project_name,repository_name,tag):
    
            all_info = self.client.get_repository_artifacts(project_name, repository_name=my_repository_name)
            for item in all_info:
                tags_info = item["tags"]
                # 遍历tag信息
                for tags_list in tags_info:
                    if tags_list["name"] == image_tag:
                        # 删除指定镜像tag
                        self.client.del_repository_tag(project_name, repository_name=my_repository_name,
                                                       reference_hash=item["digest"], tag=image_tag)
                        # 删除指定镜像artifacts那一串ID
                        self.client.del_artifacts_hash(project_name, repository_name=my_repository_name,
                                                       reference_hash=item["digest"])
    
    
                        # print(self.client.get_repositories(project_name))
                        # print(self.client.get_projects())
    
    
    if __name__ == '__main__':
        host = "harbor.xxx.com"
        user = "admin"
        password = "not tell you"
        protocol = "https"
        cline_get = GetHarborApi(host, user, password, protocol)
        namespace = sys.argv[1]
        my_repository_name = sys.argv[2]
        image_tag = sys.argv[3]
        cline_get.main(namespace,my_repository_name,image_tag)
    
    天天向上,空杯心态。
  • 相关阅读:
    Atitit oil painting article list sumup s55 C:\Users\Administrator\Desktop\油画技术资料包\Atitit Atitit 图像
    Atitit 缓存实施遇到的问题与解决 s420 attilax 艾提拉总结 Atitit 缓存增加最佳实践与实施流程 1. 业务准确性问题正确性问题 1 1.1. 缓存key正确性问题 1
    Atiitt 流水线停顿问题与解决方法 1. 流水线技术方式分类 1 2. 但在实际中,会出现2种情况使流水线停顿下来或不能启动: 2 2.1. 1、多个任务在同一时间周期内争用同一个流水段 2 2
    Atitit mybatis 配置 redis 集成 attilax总结 艾提拉总结 1.1. setting name="cacheEnabled" v 1 1.2. Mapper文件 1 1.
    Atitit spring cache key的生成 与ken生成规范 1. Good key name meth.params 1 1.1. Use epl 的mode but only clss
    Atitit 获取数据库表主键功能的实现 数据库模块 艾提拉attilax总结 package com.attilax.sql; import java.sql.Connection; im
    atitit 文件搜索 映象文件夹结构模式.docxAtitit 百度网盘 文件 与跨机器 文件 搜索 查询 检索 解决方案 最小化索引法 映象文件夹结构模式. 1. 生成文件夹 结构信息 1
    Atitit 成果艺术 attilax著 艾提拉著 目录 1. 2 2. 理论类 2 2.1. xxx模型 曲线 定律 原则 曲线 2 3. 代码类成果 范例代码项目 代码类库 与代码片段
    Atitit 架构艺术 与架构常见包含的技术 1. 架构的目的是什么??解决的问题 所有的问题都能通过架构解决 2 1.1. 提高可读性 提升可维护性架构 降低技术难度 2 1.2. 提升管理性
    atitti 提升稳定性的艺术之程序代码级别稳定性的艺术 attialx著 艾提拉著 s420.docx 1. 前言 1 2. 为什么会发生稳定性问题 1 2.1. 单点故障(单点故障率较高) 1
  • 原文地址:https://www.cnblogs.com/uglyliu/p/14318990.html
Copyright © 2011-2022 走看看