目录
前提条件
部署flask 程序
harbor1:
harbor2:
同步脚本
配置定时任务
前提条件
首先部署两个harbor,一个为主节点一个为从节点
部署flask 程序
废话不说直接上干货
harbor1:
系统自带的python2.7启动即可,需要安装一些依赖包。
文件名:harbor_api.py
#! /usr/bin/env python
#coding=utf-8
from flask import Flask,jsonify,request
import commands
import requests,json
import logging
app = Flask(__name__)
logtxt="/var/log/harbor_api.log"
def console_out(logFilename,log):
# Define a Handler and set a format which output to file
logging.basicConfig(
level=logging.DEBUG, # 定义输出到文件的log级别,大于此级别的都被输出
format='%(asctime)s %(filename)s : %(levelname)s %(message)s', # 定义输出log的格式
datefmt='%Y-%m-%d %A %H:%M:%S', # 时间
filename=logFilename, # log文件名
filemode='a') # 写入模式“w”或“
console = logging.StreamHandler() # 定义console handler
console.setLevel(logging.INFO) # 定义该handler级别
formatter = logging.Formatter('%(asctime)s %(filename)s : %(levelname)s %(message)s') # 定义该handler格式
console.setFormatter(formatter)
logging.getLogger().addHandler(console) # 实例化添加handler
logging.debug(log)
def get_project_id(name): #获取project_id
# print name
#status,result = commands.getstatusoutput('curl -sq -k -u "admin:Xxxxx" -X GET -H "Content-Type: application/json" "https://harbor.xxx-inc.com/api/search?q=%s"' % name)
#get_data = json.loads(result)
project_id = 0
status,result = commands.getstatusoutput('curl -sq -k -u "admin:Xxxxx" -X GET -H "Content-Type: application/json" "https://harbor.xxx-inc.com/api/projects"')
get_data = json.loads(result)
for i in range(len(get_data)):
if get_data[i]['name'] == name:
project_id = get_data[i]['project_id']
return project_id
@app.route('/api_ops/get_project_id',methods=['GET','POST'])
def get_projectid(): #获取项目id
result=[]
project_name = request.args.get("project_name")
if project_name is None or project_name.strip()=='':
url="https://harbor.xxx-inc.com/api/projects"
r = requests.get(url,auth=('admin','Xxxxx'),verify=False)
get_data = r.json()
for i in range(len(get_data)):
result2 = {'name':get_data[i]['name'],'project_id':get_data[i]['project_id']}
result.append(result2)
else:
project_id=get_project_id(project_name)
result2={'name':project_name,'project_id':project_id}
result.append(result2)
return json.dumps(result)
@app.route('/api_ops/get_item',methods=['GET','POST'])
def get_item(): #获取项目
project_name = request.args.get("project_name")
if project_name is None:
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X GET -H \"Content-Type: application/json\" \"https://harbor.xxx-inc.com/api/projects?project_name=guest\""
else:
project_id=get_project_id(project_name)
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X GET -H \"Content-Type: application/json\" \"https://harbor.xxx-inc.com/api/projects/%s\"" % project_id
status,result = commands.getstatusoutput(harbor_url)
#result = json.dumps(result)
console_out(logtxt,result)
return result
@app.route('/api_ops/add_item',methods=['GET','POST']) #增加项目
def add_item():
project_name = request.args.get("project_name")
public = request.args.get("public")
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X POST -H \"Content-Type: application/json\" \"https://harbor.xxx-inc.com/api/projects\" -d '{\"project_name\": \"%s\",\"public\": %s}'" % (project_name,public)
#add_user_url = "curl -sq -k -u \"admin:Xxxxx\" -X POST -H \"Content-Type: application/json\" \"https://harbor.xxx-inc.com/api/projects/%s/members/\" -d '{\"role_id\": 1,\"member_user\": {\"username\": \"wanglei\"}}'" % project_id
status,result = commands.getstatusoutput(harbor_url)
console_out(logtxt,result)
return result
@app.route('/api_ops/add_user',methods=['GET','POST']) #项目添加用户
def add_user():
project_name = request.args.get("project_name")
username = request.args.get("username")
role_id = request.args.get("role_id")
project_id=get_project_id(project_name)
print project_id
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X POST -H \"Content-Type: application/json\" \"https://harbor.xxx-inc.com/api/projects/%s/members/\" -d '{\"role_id\": %s,\"member_user\": {\"username\": \"%s\"}}'" % (project_id,role_id,username)
status,result = commands.getstatusoutput(harbor_url)
console_out(logtxt,result)
return result
@app.route('/api_ops/del_item',methods=['GET','POST']) #按照项目名删除项目
def del_item():
project_name = request.args.get("project_name")
project_id=get_project_id(project_name)
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X DELETE -H \"Content-Type: application/json\" \"https://harbor.xxx-inc.com/api/projects/%s\"" % project_id
status,result = commands.getstatusoutput(harbor_url)
return result
@app.route('/api_ops/get_images',methods=['GET','POST'])#查询项目下有哪些镜像和查询具体镜像
def get_images():
project_name = request.args.get("project_name")
images_name = request.args.get("images_name")
project_id=get_project_id(project_name)
if images_name is None:
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X GET -H \"Content-Type: application/json\" \"https://harbor.xxx-inc.com/api/repositories?project_id=%s\"" % project_id
else:
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X GET -H \"Content-Type: application/json\" \"https://harbor.xxx-inc.com/api/repositories?project_id=%s&q=%s\"" % (project_id,images_name)
status,result = commands.getstatusoutput(harbor_url)
return result
if __name__ == '__main__':
app.run(host='10.126.156.27',port=12121,debug=True)
启动服务:
nohup python /home/sunwenbo/harbor_api.py &
harbor2:
几乎同样的代码,改掉对应的链接和密码即可
文件名:harbor_api.py
#/usr/bin.env python
#coding=utf-8
from flask import Flask,jsonify,request
import commands
import requests,json
import logging
app = Flask(__name__)
logtxt="/var/log/harbor_api.log"
def console_out(logFilename,log):
# Define a Handler and set a format which output to file
logging.basicConfig(
level=logging.DEBUG, # 定义输出到文件的log级别,大于此级别的都被输出
format='%(asctime)s %(filename)s : %(levelname)s %(message)s', # 定义输出log的格式
datefmt='%Y-%m-%d %A %H:%M:%S', # 时间
filename=logFilename, # log文件名
filemode='a') # 写入模式“w”或“
console = logging.StreamHandler() # 定义console handler
console.setLevel(logging.INFO) # 定义该handler级别
formatter = logging.Formatter('%(asctime)s %(filename)s : %(levelname)s %(message)s') # 定义该handler格式
console.setFormatter(formatter)
logging.getLogger().addHandler(console) # 实例化添加handler
logging.debug(log)
def get_project_id(name): #获取project_id
#status,result = commands.getstatusoutput('curl -sq -k -u "admin:Xxxxx" -X GET -H "Content-Type: application/json" "https://harbor2.xxx-inc.com/api/search?q=%s"' % name)
#get_data = json.loads(result)
project_id = 0
status,result = commands.getstatusoutput('curl -sq -k -u "admin:Xxxxx" -X GET -H "Content-Type: application/json" "https://harbor2.xxx-inc.com/api/projects"')
get_data = json.loads(result)
for i in range(len(get_data)):
if get_data[i]['name'] == name:
project_id = get_data[i]['project_id']
return project_id
@app.route('/api_ops/get_project_id',methods=['GET','POST'])
def get_projectid(): #获取项目id
result=[]
project_name = request.args.get("project_name")
if project_name is None or project_name.strip()=='':
url="https://harbor2.xxx-inc.com/api/projects"
r = requests.get(url,auth=('admin','Xxxxx'),verify=False)
get_data = r.json()
for i in range(len(get_data)):
result2 = {'name':get_data[i]['name'],"project_id": get_data[i]['project_id']}
result.append(result2)
else:
project_id=get_project_id(project_name)
result2={'name':project_name,'project_id':project_id}
result.append(result2)
return json.dumps(result)
@app.route('/api_ops/get_item',methods=['GET','POST'])
def get_item(): #获取项目
project_name = request.args.get("project_name")
if project_name is None or project_name.strip()=='':
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X GET -H \"Content-Type: application/json\" \"https://harbor2.xxx-inc.com/api/projects?project_name=guest\""
else:
project_id=get_project_id(project_name)
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X GET -H \"Content-Type: application/json\" \"https://harbor2.xxx-inc.com/api/projects/%s\"" % project_id
status,result = commands.getstatusoutput(harbor_url)
#result = json.dumps(result)
console_out(logtxt,result)
return result
@app.route('/api_ops/add_item',methods=['GET','POST']) #增加项目
def add_item():
project_name = request.args.get("project_name")
public = request.args.get("public")
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X POST -H \"Content-Type: application/json\" \"https://harbor2.xxx-inc.com/api/projects\" -d '{\"project_name\": \"%s\",\"public\": %s}'" % (project_name,public)
#add_user_url = "curl -sq -k -u \"admin:Xxxxx\" -X POST -H \"Content-Type: application/json\" \"https://harbor2.xxx-inc.com/api/projects/%s/members/\" -d '{\"role_id\": 1,\"member_user\": {\"username\": \"wanglei\"}}'" % project_id
status,result = commands.getstatusoutput(harbor_url)
console_out(logtxt,result)
return result
@app.route('/api_ops/add_user',methods=['GET','POST']) #项目添加用户
def add_user():
project_name = request.args.get("project_name")
username = request.args.get("username")
role_id = request.args.get("role_id")
project_id=get_project_id(project_name)
print project_id
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X POST -H \"Content-Type: application/json\" \"https://harbor2.xxx-inc.com/api/projects/%s/members/\" -d '{\"role_id\": %s,\"member_user\": {\"username\": \"%s\"}}'" % (project_id,role_id,username)
status,result = commands.getstatusoutput(harbor_url)
console_out(logtxt,result)
return result
@app.route('/api_ops/del_item',methods=['GET','POST']) #按照项目名删除项目
def del_item():
project_name = request.args.get("project_name")
project_id=get_project_id(project_name)
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X DELETE -H \"Content-Type: application/json\" \"https://harbor2.xxx-inc.com/api/projects/%s\"" % project_id
status,result = commands.getstatusoutput(harbor_url)
return result
@app.route('/api_ops/get_images',methods=['GET','POST'])#查询项目下有哪些镜像和查询具体镜像
def get_images():
project_name = request.args.get("project_name")
images_name = request.args.get("images_name")
project_id=get_project_id(project_name)
if images_name is None:
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X GET -H \"Content-Type: application/json\" \"https://harbor2.xxx-inc.com/api/repositories?project_id=%s\"" % project_id
else:
harbor_url = "curl -sq -k -u \"admin:Xxxxx\" -X GET -H \"Content-Type: application/json\" \"https://harbor2.xxx-inc.com/api/repositories?project_id=%s&q=%s\"" % (project_id,images_name)
status,result = commands.getstatusoutput(harbor_url)
return result
if __name__ == '__main__':
app.run(host='10.126.156.2',port=12121,debug=True)
启动服务:
nohup python /home/sunwenbo/harbor_api.py &
同步脚本
在harbor2 节点部署同步镜像脚本
文件名:harbor_replication.py
import json,requests,time,subprocess
import logging,datetime
from requests.packages.urllib3.exceptions import InsecureRequestWarning
from logging import handlers
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
class Logger(object):
level_relations = {
'debug':logging.DEBUG,
'info':logging.INFO,
'warning':logging.WARNING,
'error':logging.ERROR,
'crit':logging.CRITICAL
}#日志级别关系映射
def __init__(self,filename,level='info',when='D',backCount=3,fmt='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'):
self.logger = logging.getLogger(filename)
format_str = logging.Formatter(fmt)#设置日志格式
self.logger.setLevel(self.level_relations.get(level))#设置日志级别
sh = logging.StreamHandler()#往屏幕上输出
sh.setFormatter(format_str) #设置屏幕上显示的格式
th = handlers.TimedRotatingFileHandler(filename=filename,when=when,backupCount=backCount,encoding='utf-8')#往文件里写入#指定间隔时间自动生成文件的处理器
#实例化TimedRotatingFileHandler
#interval是时间间隔,backupCount是备份文件的个数,如果超过这个个数,就会自动删除,when是间隔的时间单位,单位有以下几种:
# S 秒
# M 分
# H 小时、
# D 天、
# W 每星期(interval==0时代表星期一)
# midnight 每天凌晨
th.setFormatter(format_str)#设置文件里写入的格式
self.logger.addHandler(sh) #把对象加到logger里
self.logger.addHandler(th)
def get_project_id(name): #获取project_id
project_id = 0
status,result = subprocess.getstatusoutput('curl -sq -k -u "admin:Xxxxx" -X GET -H "Content-Type: application/json" "https://harbor.xxx-inc.com/api/projects"')
get_data = json.loads(result)
for i in range(len(get_data)):
if get_data[i]['name'] == name:
project_id = get_data[i]['project_id']
return project_id
def get_project(url): #获取有哪些项目
harbor_result = requests.get(url)
result = harbor_result.json()
project = []
for i in range(len(result)):
project.append(result[i]['name'])
return project
def add_replication(*diff_project): #增加复制规则
for name in diff_project:
#console_out(logtxt,name)
replication_name = name
project_name = name
project_id = get_project_id(name)
url = "https://harbor.xxx-inc.com/api/policies/replication"
payload = {
"name": "content-process-cpp-component-server",
"description": "",
"trigger": {
"kind": "Immediate"
},
"replicate_existing_image_now": True,
"replicate_deletion": True,
"filters": [],
"projects": [
{
"project_id": 27,
"owner_id": 1,
"name": "content-process-cpp-component-server",
"creation_time": "2022-12-02T03:16:38Z",
"update_time": "2022-12-02T03:16:38Z",
"deleted": False,
"owner_name": "",
"togglable": False,
"current_user_role_id": 0,
"repo_count": 0,
"chart_count": 0,
"metadata": {
"auto_scan": "false",
"enable_content_trust": "false",
"prevent_vul": "false",
"public": "true",
"severity": "low"
}
}
],
"targets": [
{
"id": 2,
"endpoint": "https://harbor2.xxx-inc.com",
"name": "harbor2.xxx-inc.com",
"username": "admin",
"password": "",
"type": 0,
"insecure": True,
"creation_time": "2022-12-01T02:26:31.923545Z",
"update_time": "2022-12-02T16:43:21.755517Z"
}
]
}
now_time = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ')
payload["name"] = project_name
payload["projects"][0]["project_id"] = project_id
payload["projects"][0]["name"] = replication_name
payload["projects"][0]["name"] = replication_name
payload["projects"][0]["creation_time"] = now_time
payload["projects"][0]["update_time"] = now_time
payload = json.dumps(payload)
headers = {
'accept': 'application/json',
'Content-Type': 'application/json',
'X-Content-Type-Options': 'nosniff',
'Authorization': 'Basic YWRtaW46T3BzMTIzNDU=',
'Cookie': 'sid=b111caf0872f37009a9e0d36439581ef'
}
response = requests.request("POST", url, headers=headers, data=payload, verify=False)
if response.status_code == 201:
log.logger.info("%s project add replication successful. status_code: %d" % (project_name,response.status_code))
time.sleep(5)
elif response.status_code == 409:
log.logger.warning("%s The mirror repository is empty. status_code: %d" % (project_name,response.status_code))
else:
log.logger.error("%s project add replication failure. status_code: %d" % (project_name,response.status_code))
harbor1_url = "http://10.126.156.27:12121/api_ops/get_item"
harbor2_url = "http://10.126.156.2:12121/api_ops/get_item"
harbor1_project = get_project(harbor1_url)
harbor2_project = get_project(harbor2_url)
log = Logger('/var/log/harbor/harbor_replication.log', level='debug')
# harbor1_project中有而harbor2_project中没有的,
diff_project = tuple(set(harbor1_project).difference(set(harbor2_project)))
add_replication(*diff_project)
配置定时任务
harbor2节点增加定时任务,每三十分钟执行一次
*/30 * * * * /bin/python3 /home/sunwenbo/harbor_replication.py