示例#1
0
def push(tag, force, overwrite):
  if force is None and shout('git status --porcelain'):
    raise HokusaiError("Working directory is not clean.  Aborting.")

  if force is None and shout('git status --porcelain --ignored'):
    raise HokusaiError("Working directory contains ignored files and/or directories.  Aborting.")

  ecr = ECR()
  if not ecr.project_repository_exists():
    raise HokusaiError("ECR repository %s does not exist... did you run `hokusai setup` for this project?" % config.project_name)

  shout(ecr.get_login())
  if tag is None:
    tag = shout('git rev-parse HEAD').strip()

  if overwrite is None and ecr.tag_exists(tag):
    raise HokusaiError("Tag %s already exists in remote repository.  Aborting." % tag)

  docker_compose_yml = os.path.join(os.getcwd(), 'hokusai/common.yml')
  shout("docker-compose -f %s -p hokusai build" % docker_compose_yml, print_output=True)
  build = "hokusai_%s:latest" % config.project_name

  shout("docker tag %s %s:%s" % (build, config.aws_ecr_registry, tag))
  shout("docker push %s:%s" % (config.aws_ecr_registry, tag), print_output=True)
  print_green("Pushed %s to %s:%s" % (build, config.aws_ecr_registry, tag))

  shout("docker tag %s %s:%s" % (build, config.aws_ecr_registry, 'latest'))
  shout("docker push %s:%s" % (config.aws_ecr_registry, 'latest'), print_output=True)
  print_green("Pushed %s to %s:%s" % (build, config.aws_ecr_registry, 'latest'))
示例#2
0
class TestECR(HokusaiIntegrationTestCase):
  def setUp(self):
    self.ecr = ECR()

  @httpretty.activate
  def test_registry(self):
    httpretty.register_uri(httpretty.POST, "https://ecr.us-east-1.amazonaws.com/",
                            body=open(os.path.join(os.getcwd(), 'test', 'fixtures', 'ecr-repositories-response.json')).read(),
                            content_type="application/x-amz-json-1.1")
    repositories = [str(repo['repositoryName']) for repo in self.ecr.registry()]
    self.assertTrue('foo' in repositories)
    self.assertTrue('bar' in repositories)
    self.assertTrue('baz' in repositories)

  @httpretty.activate
  def test_project_repository_exists(self):
    httpretty.register_uri(httpretty.POST, "https://ecr.us-east-1.amazonaws.com/",
                            body=open(os.path.join(os.getcwd(), 'test', 'fixtures', 'ecr-repositories-response.json')).read(),
                            content_type="application/x-amz-json-1.1")
    self.assertTrue(self.ecr.project_repository_exists())

  @httpretty.activate
  def test_create_project_repository(self):
    httpretty.register_uri(httpretty.POST, "https://ecr.us-east-1.amazonaws.com/",
                            body=open(os.path.join(os.getcwd(), 'test', 'fixtures', 'ecr-create-repository-response.json')).read(),
                            content_type="application/x-amz-json-1.1")
    self.assertTrue(self.ecr.create_project_repository())

  @httpretty.activate
  def test_get_login(self):
    httpretty.register_uri(httpretty.POST, "https://ecr.us-east-1.amazonaws.com/",
                           body=open(os.path.join(os.getcwd(), 'test', 'fixtures', 'ecr-authorization-response.json')).read(),
                           content_type="application/x-amz-json-1.1")
    self.assertEqual(self.ecr.get_login(), 'docker login -u AWS -p 76W8YEUFHDSAE98DFDHSFSDFIUHSDAJKGKSADFGKDF https://123456789012.dkr.ecr.us-east-1.amazonaws.com')

  @httpretty.activate
  def test_get_images(self):
    httpretty.register_uri(httpretty.POST, "https://ecr.us-east-1.amazonaws.com/",
                           body=open(os.path.join(os.getcwd(), 'test', 'fixtures', 'ecr-images-response.json')).read(),
                           content_type="application/x-amz-json-1.1")
    self.assertEqual(self.ecr.get_images()[0]['imageTags'], ['7shdn4f0f34bb8shdkb313cbeccb2fc031808duho', 'latest'])
    self.assertEqual(self.ecr.get_images()[0]['imageDigest'], 'sha256:8sh968hsn205e8bff53ba8ed1006c7f41dacd17db164efdn6d346204f997shdn')
    self.assertEqual(self.ecr.get_images()[0]['registryId'], '123456789012')
    self.assertEqual(self.ecr.get_images()[0]['repositoryName'], 'foo')

  @httpretty.activate
  def test_tag_exists(self):
    httpretty.register_uri(httpretty.POST, "https://ecr.us-east-1.amazonaws.com/",
                           body=open(os.path.join(os.getcwd(), 'test', 'fixtures', 'ecr-images-response.json')).read(),
                           content_type="application/x-amz-json-1.1")
    self.assertTrue(self.ecr.tag_exists('7shdn4f0f34bb8shdkb313cbeccb2fc031808duho'))
    self.assertTrue(self.ecr.tag_exists('latest'))
示例#3
0
def environment_create(context):
    kubernetes_yml = os.path.join(os.getcwd(), "hokusai/%s.yml" % context)
    if not os.path.isfile(kubernetes_yml):
        raise HokusaiError("Yaml file %s does not exist for given context." %
                           kubernetes_yml)

    ecr = ECR()
    if not ecr.project_repository_exists():
        raise HokusaiError(
            "ECR repository %s does not exist... did you run `hokusai setup` for this project?"
            % config.project_name)

    if not ecr.tag_exists('latest'):
        raise HokusaiError(
            "Image tag 'latest' does not exist... did you run `hokusai push`?")

    if not ecr.tag_exists(context):
        ecr.retag('latest', context)
        print_green("Updated tag 'latest' -> %s" % context)

    kctl = Kubectl(context)
    shout(kctl.command("create --save-config -f %s" % kubernetes_yml),
          print_output=True)
    print_green("Created remote environment %s" % context)
示例#4
0
def check():
    return_code = 0

    def check_ok(check_item):
        print_green(u'\u2714 ' + check_item + ' found')

    def check_err(check_item):
        print_red(u'\u2718 ' + check_item + ' not found')

    config.check()

    try:
        shout('docker --version')
        check_ok('docker')
    except CalledProcessError:
        check_err('docker')
        return_code += 1

    try:
        shout('docker-compose --version')
        check_ok('docker-compose')
    except CalledProcessError:
        check_err('docker-compose')
        return_code += 1

    try:
        shout('kubectl version')
        check_ok('kubectl')
    except CalledProcessError:
        check_err('kubectl')
        return_code += 1

    try:
        shout('git version')
        check_ok('git')
    except CalledProcessError:
        check_err('git')
        return_code += 1

    if os.environ.get('AWS_ACCESS_KEY_ID') is not None:
        check_ok('$AWS_ACCESS_KEY_ID')
    else:
        check_err('$AWS_ACCESS_KEY_ID')
        return_code += 1

    if os.environ.get('AWS_SECRET_ACCESS_KEY') is not None:
        check_ok('$AWS_SECRET_ACCESS_KEY')
    else:
        check_err('$AWS_SECRET_ACCESS_KEY')
        return_code += 1

    ecr = ECR()
    if ecr.project_repository_exists():
        check_ok("ECR repository '%s'" % config.project_name)
    else:
        check_err("ECR repository '%s'" % config.project_name)
        return_code += 1

    if os.path.isfile(os.path.join(os.getcwd(), 'hokusai/common.yml')):
        check_ok('./hokusai/common.yml')
    else:
        check_err('./hokusai/common.yml')
        return_code += 1

    if os.path.isfile(os.path.join(os.getcwd(), 'hokusai/development.yml')):
        check_ok('./hokusai/development.yml')
    else:
        check_err('./hokusai/development.yml')
        return_code += 1

    if os.path.isfile(os.path.join(os.getcwd(), 'hokusai/test.yml')):
        check_ok('./hokusai/test.yml')
    else:
        check_err('./hokusai/test.yml')
        return_code += 1

    for context in ['staging', 'production']:
        if context in Kubectl('staging').contexts():
            check_ok("kubectl context '%s'" % context)
        else:
            check_err("kubectl context '%s'" % context)
            return_code += 1

        if os.path.isfile(os.path.join(os.getcwd(),
                                       "hokusai/%s.yml" % context)):
            check_ok("./hokusai/%s.yml" % context)
        else:
            check_err("./hokusai/%s.yml" % context)
            return_code += 1

    return return_code
示例#5
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)