狂自私

导航

harbor命令行-python脚本-调用http API

因为生产环境没有UI界面,也没有开放端口资源出来,无法通过web界面来管理harbor,故调用harbor提供的httpAPI来获取harbor信息和使用常用的功能。

import requests
import json
import urllib.parse

my_auth=('admin', 'Lovedan@971220')
harbor_addr="https://127.0.0.1"

def 查询项目信息():
    headers = {'Content-Type': 'application/json',}
    response = requests.get('{}/api/v2.0/projects'.format(harbor_addr), headers=headers, verify=False, auth=my_auth)
    response_json = json.loads(response.text)
    for data in response_json:
        print("项目名:{}\t项目ID:{}\t创建时间:{}\t是否公开:{}".format(data['name'],data['project_id'],data['creation_time'],data['metadata']['public']));
def 新增项目(项目名:str,公开:bool,配额:int):
    '''
    配额:项目可以使用的最大空间,若不想限制,请传递-1
    '''
    headers = {'Content-Type': 'application/json',}
    json_data={"project_name": 项目名,
  "public": 公开,
  "metadata": {
    "public": str(公开).lower(),
    "enable_content_trust": "false",
    "enable_content_trust_cosign": "false",
    "prevent_vul": "false",
    "auto_scan": "false",
    "reuse_sys_cve_allowlist": "false"
  },
  "storage_limit": -1,}
    response = requests.post('{}/api/v2.0/projects'.format(harbor_addr),headers=headers,json=json_data,verify=False,auth=my_auth,)
    if(200 == response.status_code or 201 == response.status_code):
        return True
    else:
        response_json = json.loads(response.text)
        print(response_json['errors'][0]["message"])
        return False;
def 删除项目(项目ID:int)->bool:
    headers = {'Content-Type': 'application/json',}
    response = requests.delete('{}/api/v2.0/projects/{}'.format(harbor_addr,项目ID), headers=headers, verify=False, auth=my_auth)
    if(200 == response.status_code):
        return True
    else:
        response_json = json.loads(response.text)
        print(response_json['errors'][0]["message"])
        return False;
def 获取项目摘要信息(项目id:int):
    headers = {'Content-Type': 'application/json',}
    response = requests.get('{}/api/v2.0/projects/{}/summary'.format(harbor_addr,项目id), headers=headers, verify=False, auth=my_auth)
    data = json.loads(response.text)
    print("镜像数量:{}\n配额大小:{}\n已使用大小:{}".format(data['repo_count'],data["quota"]["hard"]["storage"],友好显示大小(data["quota"]["used"]["storage"])))
def 获取项目的日志(project_name:str,page:int=1,num:int=100):
    '''
    默认获取最新的一百条日志
    日志ID  用户名称    资源名称    标记    操作    时间
    '''
    headers = {'Content-Type': 'application/json',}
    response = requests.get('{}/api/v2.0/projects/{}/logs'.format(harbor_addr,project_name), headers=headers, verify=False, auth=my_auth)
    response_json = json.loads(response.text)
    for data in response_json:
        print("{}\t{}\t{}\t{}\t{}\t{}".format(data['id'],data['username'],data['resource'],data['resource_type'],data['operation'],data['op_time']))
def 获取项目成员信息(项目id:int):
    headers = {'Content-Type': 'application/json',}
    response = requests.get('{}/api/v2.0/projects/{}/members'.format(harbor_addr,项目id), headers=headers, verify=False, auth=my_auth)
    response_json = json.loads(response.text)
    for data in response_json:
        print("项目成员ID:{}\t项目ID:{}\t账号名称:{}\t角色:{}".format(data['id'],data['project_id'],data['entity_name'],data['role_name']))
def 查询harbor健康度()->tuple:
    '''
    7个组件,按照百分比进行计算,返回元组,第一个元素表示健康百分比。第二个元素是详细健康值
    '''
    headers = {'Content-Type': 'application/json',}
    response = requests.get('{}/api/v2.0/health'.format(harbor_addr), headers=headers, verify=False, auth=my_auth)
    response_json = json.loads(response.text)
    #0表示不健康,1表示健康
    status_dict={"core":0,"database":0,"jobservice":0,"portal":0,"redis":0,"registry":0,
    "registryctl":0,}
    healthy_num=0
    for data in response_json['components']:
        if("healthy" == data['status']):
            healthy_num+=1
            status_dict[data['name']]=1
    healthy=healthy_num/len(status_dict)
    print('健康度:{:.2%}'.format(healthy))
    return (healthy,status_dict);
def 查询普通用户列表():
    headers = {'Content-Type': 'application/json',}
    response = requests.get('{}/api/v2.0/users'.format(harbor_addr), headers=headers, verify=False, auth=my_auth)
    response_json = json.loads(response.text)
    for data in response_json:
        print("账户名称:{}\t用户全名:{}\t创建时间:{}\t邮箱:{}\t用户ID:{}\t管理员:{}\t备注:{}".format(data['username'],data['realname'],data['creation_time'],data['email'],data['user_id'],data['sysadmin_flag'],data['comment']))
def 创建普通用户(用户信息:dict)->bool:
    '''
    用户信息 = {账号名称:"",密码:"",用户全名:"",邮箱:"",备注:""}
    '''
    json_data = {
    'email': 用户信息['邮箱'],
    'realname': 用户信息['用户全名'],
    'comment': 用户信息['备注'],
    'password': 用户信息['密码'],
    'username': 用户信息['账号名称'],
    }
    headers = {
    'Content-Type': 'application/json',
    }
    response = requests.post('{}/api/v2.0/users'.format(harbor_addr),headers=headers,json=json_data,verify=False,auth=my_auth,)
    if(200 == response.status_code or 201 == response.status_code):
        return True
    else:
        response_json = json.loads(response.text)
        print(response_json['errors'][0]["message"])
        return False;
def 删除普通用户(账号id:int)->bool:
    headers = {'Content-Type': 'application/json',}
    response = requests.delete('{}/api/v2.0/users/{}'.format(harbor_addr,账号id), headers=headers, verify=False, auth=my_auth)
    if(200 == response.status_code):
        return True
    else:
        response_json = json.loads(response.text)
        print(response_json['errors'][0]["message"])
        return False;
def 设置用户管理权限(user_id:int,sysadmin_flag:bool):
    '''
    sysadmin_flag:将用户切换为管理员或不切换为管理员
    '''
    json_data = {"sysadmin_flag": sysadmin_flag}
    headers = {'Content-Type': 'application/json',}
    response = requests.put('{}/api/v2.0/users/{}/sysadmin'.format(harbor_addr,user_id),headers=headers,json=json_data,verify=False,auth=my_auth,)
    if(200 == response.status_code or 201 == response.status_code):
        return True
    else:
        response_json = json.loads(response.text)
        print(response_json['errors'][0]["message"])
        return False;
def 修改用户密码(user_id:int,pw:str):
    json_data = {"new_password": pw}
    headers = {'Content-Type': 'application/json',}
    response = requests.put('{}/api/v2.0/users/{}/password'.format(harbor_addr,user_id),headers=headers,json=json_data,verify=False,auth=my_auth,)
    if(200 == response.status_code or 201 == response.status_code):
        return True
    else:
        response_json = json.loads(response.text)
        print(response_json['errors'][0]["message"])
        return False;
def 项目和存储库的统计():
    headers = {'Content-Type': 'application/json',}
    response = requests.get('{}/api/v2.0/statistics'.format(harbor_addr), headers=headers, verify=False, auth=my_auth)
    response_json = json.loads(response.text)
    print("私有项目数量:{}\n私有镜像数量:{}\n公开项目数量:{}\n公开镜像数量:{}\n项目总计数量:{}\n镜像总计数量:{}\n已用存储:{}\n".format(response_json['private_project_count'],response_json['private_repo_count'],response_json['public_project_count'],response_json['public_repo_count'],response_json['total_project_count'],response_json['total_repo_count'],友好显示大小(response_json['total_storage_consumption'])))
def 友好显示大小(size:int)->str:
    '''
    给定正整数,默认以字节为单位,来计算最佳的单位显示,返回的结果中仅保留两位小数
    '''
    if(size<1024):
        return "{}B".format(size)
    elif(size<1048576):
        return "{:.2f}KB".format(size/1024)
    elif(size<1073741824):
        return "{:.2f}MB".format(size/1024/1024)
    elif(size<1099511627776):
        return "{:.2f}GB".format(size/1024/1024/1024)
    elif(size<(1024*1024*1024*1024*1024)):
        return "{:.2f}TB".format(size/1024/1024/1024/1024)
    else:
        return "{}B".format(size)
def 获取项目下的镜像列表(项目名称:str):
    headers = {'Content-Type': 'application/json',}
    response = requests.get('{}/api/v2.0/projects/{}/repositories'.format(harbor_addr,项目名称), headers=headers, verify=False, auth=my_auth)
    response_json = json.loads(response.text)
    for data in response_json:
        print('镜像ID:{}\n项目ID:{}\n镜像名称:{}\n拉取次数:{}\n创建时间:{}\n更新时间:{}\n版本数量:{}\n'.format(data['id'],data['project_id'],data['name'],data['pull_count'],data['creation_time'],data['update_time'],data['artifact_count']))
def 获取镜像详情(项目名称:str,镜像名称:str,是否输出镜像元数据:bool=False,输出路径:str=None):
    '''
    镜像名称中,不需要包含项目名前缀,比如说通过函数《获取项目下的镜像列表》输出的镜像名称中就带有项目名前缀,本函数中不需要此前缀。否则将会获取不到结果。
    倘若函数《获取项目下的镜像列表》输出的镜像名称为【k8s/kube-apiserver】,那么应该本函数的形参【镜像名称】值应该为kube-apiserver
    示例调用:获取镜像详情('k8s','mysql',True,r'/root/mysql_docker_元数据.txt')
    '''
    if('/' in 镜像名称):
        镜像名称 = urllib.parse.quote(urllib.parse.quote(镜像名称,'utf-8'),'utf-8')
    headers = {'Content-Type': 'application/json',}
    response = requests.get('{}/api/v2.0/projects/{}/repositories/{}/artifacts'.format(harbor_addr,项目名称,镜像名称), headers=headers, verify=False, auth=my_auth)
    response_json = json.loads(response.text)
    total_size=0
    for data in response_json:
        print("摘要ID:{}\n标签:{}\n大小:{}".format(data['digest'],data['tags'][0]['name'],友好显示大小(data['size'])))
        total_size+=data['size']
    print('总大小:{}'.format(友好显示大小(total_size)))
    if(是否输出镜像元数据):
        with open(输出路径,'w',encoding='utf-8')as out:
            for data in response_json:
                tag = data['tags'][0]['name']
                str_=json.dumps(data['extra_attrs'],indent='\t')
                print("{}:{}\n{}".format(镜像名称,tag,str_),file=out);
def 删除特定版本的镜像(项目名称:str,镜像名称:str,摘要ID:str=None,标签:str=None):
    '''
    摘要ID、标签 可以根据函数《获取镜像详情》获取得到
    摘要id和标签二者传递一个即可,若是都传递,优先使用摘要ID
    '''
    if('/' in 镜像名称):
        镜像名称 = urllib.parse.quote(urllib.parse.quote(镜像名称,'utf-8'),'utf-8')
    headers = {'Content-Type': 'application/json',}
    if None != 摘要ID:
        reference=摘要ID
    else:
        reference=标签
    response = requests.delete('{}/api/v2.0/projects/{}/repositories/{}/artifacts/{}'.format(harbor_addr,项目名称,镜像名称,reference), headers=headers, verify=False, auth=my_auth)
    if(200 == response.status_code):
        return True
    else:
        response_json = json.loads(response.text)
        print(response_json['errors'][0]["message"])
        return False;
def 删除镜像(项目名称:str,镜像名称:str):
    '''
    删除给定名称的镜像,将该镜像的所有版本都一并删除
    '''
    if('/' in 镜像名称):
        镜像名称 = urllib.parse.quote(urllib.parse.quote(镜像名称,'utf-8'),'utf-8')
    headers = {'Content-Type': 'application/json',}
    response = requests.delete('{}/api/v2.0/projects/{}/repositories/{}'.format(harbor_addr,项目名称,镜像名称), headers=headers, verify=False, auth=my_auth)
    if(200 == response.status_code):
        return True
    else:
        response_json = json.loads(response.text)
        print(response_json['errors'][0]["message"])
        return False;
def 获取系统磁盘信息():
    '''此函数输出的时整个主机的harbor所在磁盘分区使用情况,并非表示harbor的使用情况'''
    headers = {'Content-Type': 'application/json',}
    response = requests.get('{}/api/v2.0/systeminfo/volumes'.format(harbor_addr), headers=headers, verify=False, auth=my_auth)
    response_json = json.loads(response.text)
    total = response_json['storage'][0]["total"]
    free=response_json['storage'][0]["free"]
    print("总的可用大小:{}\n已使用大小:{}\n使用率:{:.2%}".format(友好显示大小(total),友好显示大小(total-free),(total-free)/total))
def 获取常规系统信息():
    headers = {'Content-Type': 'application/json',}
    response = requests.get('{}/api/v2.0/systeminfo'.format(harbor_addr), headers=headers, verify=False, auth=my_auth)
    response_json = json.loads(response.text)
    print(json.dumps(response_json,indent='\t'))
    
print(查询harbor健康度())
# 查询项目信息()
# 创建普通用户({'邮箱':'1946549044@qq.com','密码':"Lovedan@971220",'用户全名':'test','账号名称':'test','备注':'ceshi'})
View Code

 

posted on 2024-03-17 14:04  狂自私  阅读(22)  评论(0编辑  收藏  举报