def setup(project_name, template_remote, template_dir, template_vars, allow_missing_vars): mkpath(os.path.join(CWD, HOKUSAI_CONFIG_DIR)) config.create(clean_string(project_name)) ecr = ECR() if ecr.project_repo_exists(): print_green("Project repo %s already exists. Skipping create." % ecr.project_repo) else: ecr.create_project_repo() print_green("Created project repo %s" % ecr.project_repo) scratch_dir = None if template_remote: scratch_dir = tempfile.mkdtemp() git_repo_and_branch = template_remote.split('#', 1) git_repo = git_repo_and_branch[0] if len(git_repo_and_branch) == 2: git_branch = git_repo_and_branch[1] else: git_branch = "master" shout("git clone -b %s --single-branch %s %s" % (git_branch, git_repo, scratch_dir)) custom_template_dir = None if allow_missing_vars: environment_kwargs = {} else: environment_kwargs = {"undefined": StrictUndefined} if scratch_dir and template_dir: custom_template_dir = os.path.join(scratch_dir, os.path.basename(template_dir)) env = Environment(loader=FileSystemLoader( os.path.join(scratch_dir, os.path.basename(template_dir))), **environment_kwargs) elif scratch_dir: custom_template_dir = scratch_dir env = Environment(loader=FileSystemLoader(scratch_dir), **environment_kwargs) elif template_dir: custom_template_dir = os.path.abspath(template_dir) env = Environment(loader=FileSystemLoader( os.path.abspath(template_dir)), **environment_kwargs) else: try: base_path = sys._MEIPASS env = Environment(loader=FileSystemLoader( os.path.join(base_path, 'hokusai', 'templates'))) except: env = Environment(loader=PackageLoader('hokusai', 'templates')) required_templates = [ 'Dockerfile.j2', '.dockerignore.j2', 'hokusai/build.yml.j2', 'hokusai/development.yml.j2', 'hokusai/test.yml.j2', 'hokusai/staging.yml.j2', 'hokusai/production.yml.j2' ] template_context = { "project_name": config.project_name, "project_repo": ecr.project_repo } for s in template_vars: if '=' not in s: raise HokusaiError( "Error: template variables must be of the form 'key=value'") split = s.split('=', 1) template_context[split[0]] = split[1] try: for template in required_templates: if custom_template_dir and not os.path.isfile( os.path.join(custom_template_dir, template)): raise HokusaiError("Could not find required template file %s" % template) with open(os.path.join(CWD, template.rstrip('.j2')), 'w') as f: f.write(env.get_template(template).render(**template_context)) print_green("Created %s" % template.rstrip('.j2')) if custom_template_dir: for root, _, files in os.walk(custom_template_dir): subpath = os.path.relpath(root, custom_template_dir) if subpath is not '.': mkpath(os.path.join(CWD, subpath)) for file in files: if subpath is not '.': file_path = os.path.join(subpath, file) else: file_path = file if file_path in required_templates: continue if file_path.endswith('.j2'): with open(os.path.join(CWD, file_path.rstrip('.j2')), 'w') as f: f.write( env.get_template(file_path).render( **template_context)) else: copyfile(os.path.join(custom_template_dir, file_path), os.path.join(CWD, file_path)) print_green("Created %s" % file_path.rstrip('.j2')) finally: if scratch_dir: rmtree(scratch_dir)
def setup(aws_account_id, project_type, project_name, aws_ecr_region, port, internal): mkpath(os.path.join(os.getcwd(), 'hokusai')) config.create(project_name.lower().replace('_', '-'), aws_account_id, aws_ecr_region) if project_type == 'ruby-rack': dockerfile = env.get_template("Dockerfile-ruby.j2") base_image = 'ruby:latest' run_command = 'bundle exec rackup' development_command = 'bundle exec rackup' test_command = 'bundle exec rake' runtime_environment = { 'development': ["RACK_ENV=development"], 'test': ["RACK_ENV=test"], 'production': [{'name': 'RACK_ENV', 'value': 'production'}] } elif project_type == 'ruby-rails': dockerfile = env.get_template("Dockerfile-rails.j2") base_image = 'ruby:latest' run_command = 'bundle exec rails server' development_command = 'bundle exec rails server' test_command = 'bundle exec rake' runtime_environment = { 'development': ["RAILS_ENV=development"], 'test': ["RAILS_ENV=test"], 'production': [{'name': 'RAILS_ENV', 'value': 'production'}, {'name': 'RAILS_SERVE_STATIC_FILES', 'value': 'true'}, {'name': 'RAILS_LOG_TO_STDOUT', 'value': 'true'}] } elif project_type == 'nodejs': dockerfile = env.get_template("Dockerfile-node.j2") base_image = 'node:latest' run_command = 'node index.js' development_command = 'node index.js' test_command = 'npm test' runtime_environment = { 'development': ["NODE_ENV=development"], 'test': ["NODE_ENV=test"], 'production': [{'name': 'NODE_ENV', 'value': 'production'}] } elif project_type == 'elixir': dockerfile = env.get_template("Dockerfile-elixir.j2") base_image = 'elixir:latest' run_command = 'mix run --no-halt' development_command = 'mix run' test_command = 'mix test' runtime_environment = { 'development': ["MIX_ENV=dev"], 'test': ["MIX_ENV=test"], 'production': [{'name': 'MIX_ENV', 'value': 'prod'}] } elif project_type == 'python-wsgi': dockerfile = env.get_template("Dockerfile-python.j2") base_image = 'python:latest' run_command = "gunicorn -b 0.0.0.0:%s app" % port development_command = "python -m werkzeug.serving -b 0.0.0.0:%s %s" % (port, project_name) test_command = 'python -m unittest discover .' runtime_environment = { 'development': ["CONFIG_FILE=config/development.py"], 'test': ["CONFIG_FILE=config/test.py"], 'production': [{'name': 'CONFIG_FILE', 'value': 'config/production.py'}] } with open(os.path.join(os.getcwd(), 'Dockerfile'), 'w') as f: f.write(dockerfile.render(base_image=base_image, command=run_command, target_port=port)) with open(os.path.join(os.getcwd(), 'hokusai', "common.yml"), 'w') as f: services = { config.project_name: { 'build': { 'context': '../' } } } data = OrderedDict([ ('version', '2'), ('services', services) ]) payload = YAML_HEADER + yaml.safe_dump(data, default_flow_style=False) f.write(payload) for compose_environment in ['development', 'test']: with open(os.path.join(os.getcwd(), 'hokusai', "%s.yml" % compose_environment), 'w') as f: services = { config.project_name: { 'extends': { 'file': 'common.yml', 'service': config.project_name } } } if compose_environment == 'development': services[config.project_name]['command'] = development_command services[config.project_name]['ports'] = ["%s:%s" % (port, port)] services[config.project_name]['volumes'] = ['../:/app'] if compose_environment == 'test': services[config.project_name]['command'] = test_command services[config.project_name]['environment'] = runtime_environment[compose_environment] data = OrderedDict([ ('version', '2'), ('services', services) ]) payload = YAML_HEADER + yaml.safe_dump(data, default_flow_style=False) f.write(payload) for remote_environment in ['staging', 'production']: with open(os.path.join(os.getcwd(), 'hokusai', "%s.yml" % remote_environment), 'w') as f: if remote_environment == 'production': replicas = 2 else: replicas = 1 deployment_data = build_deployment(config.project_name, "%s:%s" % (config.aws_ecr_registry, remote_environment), port, environment=runtime_environment['production'], always_pull=True, replicas=replicas) service_data = build_service(config.project_name, port, target_port=port, internal=internal) remote_environment_yaml = deployment_data + service_data f.write(remote_environment_yaml) print_green("Config created in ./hokusai") ecr = ECR() if ecr.project_repository_exists(): print_green("ECR repository %s found. Skipping creation." % config.project_name) return 0 if ecr.create_project_repository(): print_green("Created ECR repository %s" % config.project_name) return 0 else: raise HokusaiError("Could not create ECR repository %s - check your credentials." % config.project_name)