Harbor同步仓库镜像到另一个仓库

文章目录

  • Harbor同步仓库镜像到另一个仓库
    • 清单文件-示例
    • 同步脚本-示例
    • 使用Python获取清单文件的示例

Harbor同步仓库镜像到另一个仓库

  • 因为近期有业务需求需要将一个Harbor仓库的所有镜像同步到另一个仓库,所以写了点脚本来处理

清单文件-示例

  • 提前准备镜像清单(CSV文件头“项目, artifact, tag, 哈希值”)
custom-images,docker-image-tmp,test-20220211171020,sha256:8ea34c3291aa5a28ef7b8de188023037f8ccc3a31287bd5a80d6e58be3714bc7
custom-images,imagetmp,test-20211230154117,sha256:05dbe98097d2a6b489a4b7095a416c838004246b6ebdf33d8389df47bc451d58
custom-images,flaskweb,test-20220510162600,sha256:5e3451fea2a66ba82887f8be8d0d1f421438e5b7cc435aac8475204b02fa8c50
custom-images,flaskweb,test-20211223164921,sha256:31e69778c25ff51bd5d29ad6cfb340a46d86a07212c8f6f4813f557598ac2e8e
  • 可以不要最后的哈希值
  • 生成该列表的Python样例脚本见文末

同步脚本-示例

  • Shell 脚本 transformer.sh
#! /bin/bash

# 镜像清单。CSV格式,头:项目,artifact,Tag,哈希值
images_list_file=image_list.csv

# Harbor镜像源仓库和推送的目标仓库
src_harbor=harbor.myai.com
tgt_harbor=harbor-internal.myai.com:44104
docker login -u admin -p NFW3xDVVa1ki ${src_harbor}
docker login -u aaas -p EML3G0zcV2Pv ${tgt_harbor}

# 本地单独备份镜像的目录,不想保存的话请注释掉下面docker save部分的代码
output_dir=/data/ai/harbor-images

# 开始处理
echo -e "\e[34m Start transmission: ${src_harbor} => ${tgt_harbor} \e[0m"

while read line
do
    # 按行读取文本,开始解析
    echo -e "\e[34m Transfer ===> ${line} \e[0m"
    array=(${line//,/ })
    project=${array[0]}
    artifact=${array[1]}
    tag=${array[2]}
    # digest=${array[3]}

    # 拉取,保存,推送,清理
    image_url="${project}/${artifact}:${tag}"
    docker pull "${src_harbor}/${image_url}"
    docker save "${src_harbor}/${image_url}" -o "${output_dir}/${project}.${artifact}.${tag}.tar"
    docker tag "${src_harbor}/${image_url}" "${tgt_harbor}/${image_url}"
    docker push "${tgt_harbor}/${image_url}"
    docker rmi "${src_harbor}/${image_url}"
    docker rmi "${tgt_harbor}/${image_url}"

done < $images_list_file

# 结束处理
echo -e "\e[34m End transmission: ${src_harbor} => ${tgt_harbor} \e[0m"
  • 直接执行 $ bash transformer.sh
  • 后台执行 $ nohup ./transformer.sh 1>run.log 2>&1 &

使用Python获取清单文件的示例

  • 替换domain_urlcookie 后,直接执行该Python代码即可
import requests
import json

domain_url = "http://1.1.1.1"
cookie = "rem-username=admin; _gorilla_csrf=MTcxxTA0NDI0N3xJbWcxY2tkREt2Vk1Wa3hIZG5sS01WWmhWVzR5YUU0MWVGQjNVMmtyYldaUWJYcEtWSGhaTkZaUFJsazlJZ289fHY6Uw-UXyL3iCnO_E4zkDoAgYj3QsEki0-dr0wmqb2i; sid=96e1f91f4c157a6f51489ca6962e2eb7"
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0"

def req_root_list():
    url = f"{domain_url}/api/v2.0/projects"
    querystring = {"page": "1", "page_size": "25"}
    headers = {
        "cookie": cookie,
        "user-agent": user_agent,
        "accept": "application/json",
        "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
        "cache-control": "no-cache",
        "connection": "keep-alive",
        "content-type": "application/json"
    }
    response = requests.request("GET", url, headers=headers, params=querystring)

    if response.status_code == 200:
        return json.loads(response.text)
    else:
        raise Exception("Error get_root_list")


def req_project_list(project_name: str):
    url = f"{domain_url}/api/v2.0/projects/{project_name}/repositories"
    querystring = {"page_size": "15", "page": "1"}
    headers = {
        "cookie": cookie,
        "user-agent": user_agent,
        "accept": "application/json, text/plain, */*",
        "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
        "connection": "keep-alive",
    }
    response = requests.request("GET", url, headers=headers, params=querystring)

    if response.status_code == 200:
        return json.loads(response.text)
    else:
        raise Exception("Error get_project_list")


def req_artifacts_list(project_name: str, artifacts_name: str):
    url = f"{domain_url}/api/v2.0/projects/{project_name}/repositories/{artifacts_name}/artifacts"
    querystring = {
        "with_tag": "false",
        "with_scan_overview": "true",
        "with_label": "true",
        "page_size": "15",
        "page": "1",
    }
    headers = {
        "cookie": cookie,
        "user-agent": user_agent,
        "accept": "application/json, text/plain, */*",
        "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
        "connection": "keep-alive",
        "x-accept-vulnerabilities": "application/vnd.security.vulnerability.report; version=1.1, application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0",
    }
    response = requests.request("GET", url, headers=headers, params=querystring)

    if response.status_code == 200:
        return json.loads(response.text)
    else:
        raise Exception("Error get_artifacts_list")


def req_tags_by_digest(project_name: str, artifacts_name: str, digest: str):
    url = f"{domain_url}/api/v2.0/projects/{project_name}/repositories/{artifacts_name}/artifacts/{digest}/tags"
    querystring = {
        "with_signature": "true",
        "with_immutable_status": "true",
        "page_size": "8",
        "page": "1",
    }
    headers = {
        "cookie": cookie,
        "user-agent": user_agent,
        "accept": "application/json, text/plain, */*",
        "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
        "connection": "keep-alive",
    }

    response = requests.request("GET", url, headers=headers, params=querystring)

    if response.status_code == 200:
        return json.loads(response.text)
    else:
        raise Exception("Error get_tag_by_digest")


if __name__ == "__main__":
    # 获取Harbor根列表
    root_list = req_root_list()
    for r_item in root_list:
        project_name = r_item["name"]
        # 获取Harbor根下的项目内的列表
        project_list = req_project_list(project_name)
        for p_item in project_list:
            artifacts_name = p_item["name"].split("/")[1]
            # print(artifacts_name)
            artifacts_list = req_artifacts_list(project_name, artifacts_name)
            for a_item in artifacts_list:
                digest = a_item["digest"]
                tags = req_tags_by_digest(project_name, artifacts_name, digest)
                for tag in tags:
                    tag_name = tag["name"]
                    print(project_name + "/" + artifacts_name + ", " + tag_name + ", " + digest)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/605392.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

每日一题——力扣面试题 17.04. 消失的数字

题目链接&#xff1a;https://leetcode.cn/problems/missing-number-lcci/description/ 菜鸡做法&#xff1a; #include <stdlib.h> // 包含标准库头文件&#xff0c;用于内存分配等功能// 函数定义&#xff1a;寻找缺失的数字 int missingNumber(int* nums, int numsSi…

从离线到实时:无锡锡商银行基于 Apache Doris 的数据仓库演进实践

作者&#xff1a;武基鹏&#xff0c;无锡锡商银行 大数据技术经理 编辑整理&#xff1a;SelectDB 技术团队 导读&#xff1a;为实现数据资产的价值转化以及全面数字化、智能化的风险管理&#xff0c;无锡锡商银行大数据平台经历从 Hive 离线数据仓库到 Apache Doris 实时数据仓…

Hive SQL-DQL-Select查询语句用法详解

HQL Select用法详解 1.基础语法 &#xff08;1&#xff09;select_exp &#xff08;2&#xff09;ALL、DISTINCT &#xff08;3&#xff09;WHERE &#xff08;4&#xff09;分区查询、分区裁剪 &#xff08;5&#xff09;GROUP BY &#xff08;6&#xff09;HAVING &#xff0…

hadoop学习---基于Hive的教育平台数据仓库分析案例(三)

衔接第一部分&#xff0c;第一部分请点击&#xff1a;基于Hive的教育平台数据仓库分析案例&#xff08;一) 衔接第二部分&#xff0c;第二部分请点击&#xff1a;基于Hive的教育平台数据仓库分析案例&#xff08;二) 学生出勤模块&#xff08;全量分析&#xff09;&#xff1a…

Densenet+SE

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊# 前言 前言 这周开始学习关于经典模型的改进如加注意力机制&#xff0c;这周学习Densenet加通道注意力即SE注意力机制。 ##SE注意力机制简介 SE&#xff08;…

自定义shell

1、首先我们的程序要打印出命令行 命令行》用户名【主机名】当前路劲$:命令字符串 用户名、主机名、当前路径可以通过系统调用函数getenv()得到&#xff1a; 2、获取命令字符串 把输入的命令字符串放到一个指针数组中 但是我们发现用scanf函数输入的话&#xff0c;遇到空…

【数据结构】-- 链表专题

链表的分类 前面我们实现了单链表&#xff0c;单链表只是链表的一种。可以根据以下几个标准来判断链表的类型&#xff1a; 1.单向或者双向 如图所示&#xff0c;单向链表中一个节点的指针域只储存了下一个节点的指针&#xff0c;能通过前一个节点访问后一个节点&#xff0c;无…

Vue 3.3 编译宏 vue3.3新增了一些语法糖和宏,包括泛型组件、defineSlots、defineEmits、defineOptions

Vue 3.3新增了一些语法糖和宏&#xff0c;包括泛型组件、defineSlots、defineEmits、defineOptions defineProps 父组件传参 <template><Child name"my"></Child> </template> <script setup lang"ts"> import Child fro…

使用Docker安装Yapi接口管理工具

简介&#xff1a; YAPI 是由去哪儿网移动架构组开发的一款可视化接口管理工具。它具有可视化管理、高效易用、功能强大等特点。它提供了便捷的接口创建、发布和维护方式&#xff0c;开发人员可以通过简单的操作实现接口管理。 YAPI 还支持类似 postman 的接口调试&#xff0c;对…

06-数组

1. 为什么需要数组 一个养鸡场有6只鸡&#xff0c;它们的体重分别是3kg&#xff0c;4kg&#xff0c;1kg&#xff0c;2kg&#xff0c;6kg&#xff0c;3kg。 没有数组&#xff0c;就需要定义六个变量&#xff0c;一个变量代表一只鸡的体重。 使用数组&#xff0c;就可以定义一…

TypeScript学习日志-第二十三天(装饰器Decorator)

装饰器Decorator 一、类装饰器 ClassDecorator 其中返回的 target 是 Http 的构造函数&#xff0c;有了构造函数就不会去破坏其自身原有的结构&#xff0c;当我们 Http 里面有多个属性或者方法的&#xff0c;当是我们不想看或者改变它&#xff0c;这时候可以在构造函数中增加即…

【Mybatis操作数据库】入门(一)

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【MyBatis框架】 本专栏旨在分享MyBatis框架的学习笔记&#xff0c;如有错误定当洗耳恭听&#xff0c;欢迎大家在评论区交流讨论&#x1f…

59岁前TVB男拳王内地登台疑黑面 被批耍大牌

现年59岁的郭政鸿在2015年离巢TVB后转往内地发展&#xff0c;密密拍剧、登台及直播带货&#xff0c;短短几年就已经储够钱&#xff0c;斥资过千万买楼&#xff0c;成功上车做业主&#xff0c;可见收入丰厚。 早前郭政鸿现身顺德&#xff0c;在酒吧登台唱歌&#xff0c;有网民上…

《铁路出行更便捷:火车票预定审批系统的设计与应用》

在现代化的铁路交通管理中&#xff0c;火车票预定审批系统扮演着至关重要的角色。它不仅能够有效管理员工出差、培训等需要乘坐火车的行程&#xff0c;还能够提高审批效率&#xff0c;减少人力成本&#xff0c;确保出行安全。本文将探讨火车票预定审批系统的设计原则和应用场景…

计算机毕业设计Python+Spark知识图谱医生推荐系统 医生门诊预测系统 医生数据分析 医生可视化 医疗数据分析 医生爬虫 大数据毕业设计 机器学习

摘 要 随着我国社会经济发展水平的不断提高&#xff0c;人们的物质生活水平也有了很大的改善&#xff0c;越来越多的人不满足于当前的医疗服务质量&#xff0c;由于地域和空间的限制&#xff0c;医疗资源不平衡&#xff0c;无法实现全民共享。针对当今社会中存在的求医难的问题…

智能家居2 -- 实现网络控制模块

这一模块的思路和前面的语言控制模块很相似&#xff0c;差别只是调用TCP 去控制 废话少说&#xff0c;放码过来 增添/修改代码 socket_interface.c #include <pthread.h>#include "socket_interface.h" #include "control.h" #include "socke…

【教程】超简单!如何将“在VSCode中打开”添加到右键菜单中

按照以下步骤进行操作&#xff1a; 打开注册表编辑器&#xff1a; 按下 Win R 组合键打开运行对话框。输入 regedit 并按下 Enter 键打开注册表编辑器。 导航到适当的注册表项&#xff1a; 转到以下注册表项&#xff1a;HKEY_CLASSES_ROOT\Directory\Background\shell 创建…

26版SPSS操作教程(高级教程第十九章)

目录 前言 粉丝及官方意见说明 第十九章一些学习笔记 第十九章一些操作方法 树模型、随机森林与最近邻元素法 树模型 数据准备 具体操作 结果解释 对案例的进一步分析 结果解释 考虑应用模型时的成本与收益 保存新数据 在选项中看错误分类成本和利润 结果解释…

【管理篇】如何管理情绪?

目录标题 为什么要特别关注激动和愤怒两种情绪呢&#xff1f;管理自己的情绪大致的步骤三层脑结构爬行脑情绪脑视觉脑 大家说的情绪管理&#xff0c;基本上都是对于情绪激动、生气甚至是愤怒的管理&#xff1b;日常所说的情绪化&#xff0c;一般也是指某个人特别容易情绪激动&a…

Gitlab自动化测试的配置

1. 代码分支命名规范检测 Setting → Repository → Push rules → Branch name&#xff0c;添加分支命名规范对应的正则表达式。如&#xff1a; ^(Release|Tag|Develop|Feature)_._.|Main$ 表示分支名只能以以下关键字之一开头&#xff1a;Release、Tag、Develop和Feature。 …
最新文章