Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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)