mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-20 09:15:19 +01:00
202 lines
6.7 KiB
Plaintext
202 lines
6.7 KiB
Plaintext
|
#!/usr/bin/env python
|
||
|
|
||
|
from __future__ import print_function, unicode_literals # We require Python 2.6 or later
|
||
|
import sys
|
||
|
import argparse
|
||
|
import io
|
||
|
import os
|
||
|
import random
|
||
|
import re
|
||
|
import string
|
||
|
import subprocess
|
||
|
|
||
|
if sys.version_info[:3][0] == 2:
|
||
|
import ConfigParser as configparser
|
||
|
import StringIO as io
|
||
|
|
||
|
if sys.version_info[:3][0] == 3:
|
||
|
import configparser as configparser
|
||
|
import io as io
|
||
|
|
||
|
|
||
|
# prepare base dir
|
||
|
base_dir = os.path.dirname(os.path.abspath(__file__))
|
||
|
|
||
|
parser = argparse.ArgumentParser(description='Generate *.cm.yaml')
|
||
|
parser.add_argument('-f', default=os.path.join(base_dir, '../harbor.cfg'),
|
||
|
dest='config_file', help='[Optional] path of harbor config file')
|
||
|
parser.add_argument('-k', default='',
|
||
|
dest='private_key', help='[Optional] path of harbor https private key(pem)')
|
||
|
parser.add_argument('-c', default='',
|
||
|
dest='cert', help='[Optional] harbor path of https cert(pem)')
|
||
|
parser.add_argument('-s', default='',
|
||
|
dest='secret_key', help="[Optional] path of harbor secret key(16 characters)")
|
||
|
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
# read config file
|
||
|
config_str = ''
|
||
|
if os.path.isfile(args.config_file):
|
||
|
with open(args.config_file) as conf:
|
||
|
config_str = conf.read()
|
||
|
else:
|
||
|
raise Exception('Error: No such file(' + args.config_file + ')')
|
||
|
|
||
|
config_str = '[harbor]\n' + config_str
|
||
|
fp = io.StringIO()
|
||
|
fp.write(config_str)
|
||
|
fp.seek(0, os.SEEK_SET)
|
||
|
config = configparser.RawConfigParser()
|
||
|
config.readfp(fp)
|
||
|
|
||
|
|
||
|
def get_config(key):
|
||
|
"""get value by key
|
||
|
"""
|
||
|
if config.has_option('harbor', key):
|
||
|
return config.get('harbor', key)
|
||
|
print('Warning: Key(' + key + ') is not existing. Use empty string as default')
|
||
|
return ''
|
||
|
|
||
|
|
||
|
def set_config(key, value):
|
||
|
"""set key & value
|
||
|
"""
|
||
|
config.set('harbor', key, value)
|
||
|
|
||
|
# relative path with config file
|
||
|
def rel_path(p):
|
||
|
if p[0] == '/':
|
||
|
return p
|
||
|
config_path = args.config_file
|
||
|
if config_path[0] != '/':
|
||
|
config_path = os.path.join(os.getcwd(), config_path)
|
||
|
return os.path.join(os.path.dirname(config_path), p)
|
||
|
|
||
|
# path of private key
|
||
|
pk_path = args.private_key
|
||
|
if pk_path == '':
|
||
|
pk_path = get_config('ssl_cert_key')
|
||
|
if pk_path != '':
|
||
|
pk_path = rel_path(pk_path)
|
||
|
|
||
|
# path of cert
|
||
|
cert_path = args.cert
|
||
|
if cert_path == '':
|
||
|
cert_path = get_config('ssl_cert')
|
||
|
if cert_path != '':
|
||
|
cert_path = rel_path(cert_path)
|
||
|
|
||
|
|
||
|
# validate
|
||
|
if get_config('ui_url_protocol') == 'https':
|
||
|
if pk_path == '':
|
||
|
raise Exception("Error: The protocol is https but attribute ssl_cert_key is not set")
|
||
|
if cert_path == '':
|
||
|
raise Exception("Error: The protocol is https but attribute ssl_cert is not set")
|
||
|
else:
|
||
|
pk_path = ''
|
||
|
cert_path = ''
|
||
|
|
||
|
|
||
|
# read secret key
|
||
|
if args.secret_key != '':
|
||
|
if os.path.isfile(args.secret_key):
|
||
|
key = ''
|
||
|
with open(args.secret_key, 'r') as skey:
|
||
|
key = skey.read()
|
||
|
if len(key) != 16:
|
||
|
raise Exception('Error: The length of secret key has to be 16 characters!')
|
||
|
set_config('secret_key', key)
|
||
|
else:
|
||
|
set_config('secret_key', ''.join(random.choice(
|
||
|
string.ascii_letters + string.digits) for i in range(16)))
|
||
|
|
||
|
# read https pkey & cert
|
||
|
if pk_path != '':
|
||
|
if os.path.isfile(pk_path):
|
||
|
with open(pk_path, 'r') as pkey:
|
||
|
set_config('https_pkey', pkey.read())
|
||
|
else:
|
||
|
raise Exception('Error: https private key is not existing')
|
||
|
else:
|
||
|
set_config('https_pkey', 'USE_HTTP')
|
||
|
|
||
|
if cert_path != '':
|
||
|
if os.path.isfile(cert_path):
|
||
|
with open(cert_path, 'r') as cert:
|
||
|
set_config('https_cert', cert.read())
|
||
|
else:
|
||
|
raise Exception('Error: https cert is not existing')
|
||
|
else:
|
||
|
set_config('https_cert', 'USE_HTTP')
|
||
|
|
||
|
|
||
|
# add configs
|
||
|
set_config('ui_url', get_config('ui_url_protocol') +
|
||
|
'://' + get_config('hostname'))
|
||
|
set_config('ui_secret', ''.join(random.choice(
|
||
|
string.ascii_letters + string.digits) for i in range(16)))
|
||
|
|
||
|
# generate auth pkey & cert
|
||
|
with open(os.devnull, 'w') as devnull:
|
||
|
openssl = subprocess.call(['which','openssl'], stdout=devnull, stderr=devnull)
|
||
|
if openssl == 0:
|
||
|
pkey = subprocess.check_output(['openssl','genrsa','4096'], stderr=devnull)
|
||
|
subj = '/C={0}/ST={1}/L={2}/O={3}/OU={4}/CN={5}/emailAddress={6}'.format(get_config('crt_country'),
|
||
|
get_config('crt_state'), get_config('crt_location'), get_config('crt_organization'),
|
||
|
get_config('crt_organizationalunit'), get_config('crt_commonname'), get_config('crt_email'))
|
||
|
openssl = subprocess.Popen(['openssl', 'req', '-new', '-x509', '-key', '/dev/stdin', '-days', '3650', '-subj', subj],
|
||
|
stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=devnull)
|
||
|
cert = openssl.communicate(input=pkey)[0]
|
||
|
set_config('auth_pkey', pkey.decode())
|
||
|
set_config('auth_cert', cert.decode())
|
||
|
else:
|
||
|
set_config('auth_pkey', 'NEED_SET')
|
||
|
set_config('auth_cert', 'NEED_SET')
|
||
|
print('Warning: auth_pkey and auth_cert cannot be generated automatically without openssl. Please set it manually')
|
||
|
|
||
|
|
||
|
|
||
|
variable = re.compile(r'{{.+?}}')
|
||
|
detail = re.compile(r'((\d+) )?([a-zA-Z_0-9-]+)')
|
||
|
def render_template(tmpl):
|
||
|
"""render template
|
||
|
replace {{(number of leading spaces)name}} with config
|
||
|
examples:
|
||
|
config:
|
||
|
hostname='test\ntest'
|
||
|
|
||
|
{{hostname}} -> 'test\ntest'
|
||
|
{{4 hostname}} -> 'test\n test'
|
||
|
"""
|
||
|
matches = variable.findall(tmpl)
|
||
|
for match in matches:
|
||
|
segs = detail.search(match)
|
||
|
if segs.group() == '':
|
||
|
raise Exception('Error: Invalid template item(' + match + ')')
|
||
|
value = get_config(segs.group(3))
|
||
|
spaces = segs.group(2)
|
||
|
if spaces != '' and spaces != None:
|
||
|
leading = ''.join(' ' for i in range(int(spaces)))
|
||
|
value = str(value).replace('\n', '\n' + leading)
|
||
|
tmpl = tmpl.replace(match, value)
|
||
|
return tmpl
|
||
|
|
||
|
|
||
|
def generate_template(tmpl, dest):
|
||
|
"""generate file
|
||
|
"""
|
||
|
with open(tmpl) as tmpl:
|
||
|
with open(dest, 'w') as dest:
|
||
|
dest.write(render_template(tmpl.read()))
|
||
|
|
||
|
|
||
|
template_dir = os.path.join(base_dir, 'templates')
|
||
|
output_dir = base_dir
|
||
|
generate_template(os.path.join(template_dir, 'ui.cm.yaml'), os.path.join(output_dir, 'ui/ui.cm.yaml'))
|
||
|
generate_template(os.path.join(template_dir, 'jobservice.cm.yaml'), os.path.join(output_dir, 'jobservice/jobservice.cm.yaml'))
|
||
|
generate_template(os.path.join(template_dir, 'mysql.cm.yaml'), os.path.join(output_dir, 'mysql/mysql.cm.yaml'))
|
||
|
generate_template(os.path.join(template_dir, 'nginx.cm.yaml'), os.path.join(output_dir, 'nginx/nginx.cm.yaml'))
|
||
|
generate_template(os.path.join(template_dir, 'registry.cm.yaml'), os.path.join(output_dir, 'registry/registry.cm.yaml'))
|