harbor/make/kubernetes/prepare
2017-01-16 12:06:35 +08:00

202 lines
6.7 KiB
Python

#!/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'))