Esempio n. 1
0
 def new_func(ctx, hosted_zone_id, *args, **kwargs):
     """
     :param click.Context ctx:
     """
     if hosted_zone_id is None:
         echo_heading('Trying to find hosted zone for {}.'.format(
             settings.DOMAIN_NAME),
                      marker='-',
                      marker_color='magenta')
         client = boto3.client('route53')
         response = client.list_hosted_zones_by_name(
             DNSName=settings.DOMAIN_NAME)
         if len(response['HostedZones']) == 0:
             click.echo(
                 'Unable to find a Hosted Zone for {}. Please specify it explicitly by passing --hosted-zone-id/-hz.'
             )
             ctx.exit(code=exit_codes.OTHER_FAILURE)
         elif len(response['HostedZones']) > 1:
             click.echo(
                 'Found multiple Hosted Zones for {}. Please specify one explicitly by passing --hosted-zone-id/-hz.'
             )
             ctx.exit(code=exit_codes.OTHER_FAILURE)
         hosted_zone_id = response['HostedZones'][0]['Id'].split('/')[-1]
         click.echo('Done.')
     return ctx.invoke(f, hosted_zone_id=hosted_zone_id, *args, **kwargs)
Esempio n. 2
0
def configure_dns(elastic_ip_id, hosted_zone_id):
    """Configure the DNS of the main TigerHost server.

    This points tigerhost.com (not a subdomain) to the main server
    """
    echo_heading('Creating A record.', marker='-', marker_color='magenta')
    ec2 = boto3.resource('ec2')
    client = boto3.client('route53')
    client.change_resource_record_sets(
        HostedZoneId=hosted_zone_id,
        ChangeBatch={
            'Comment': 'Test comment',
            'Changes': [
                {
                    'Action': 'UPSERT',
                    'ResourceRecordSet': {
                        'Name': settings.DOMAIN_NAME,
                        'Type': 'A',
                        'TTL': 60,
                        'ResourceRecords': [
                            {
                                'Value': ec2.VpcAddress(elastic_ip_id).public_ip
                            },
                        ],
                    }
                },
            ]
        }
    )
    click.echo('Done.')
Esempio n. 3
0
def destroy(name):
    """Destroy the addon server machine.
    """
    echo_heading(
        'Destroying machine {name}.'.format(name=name), marker='-', marker_color='magenta')
    docker_machine.check_call(['rm', '-y', name])
    store.unset('addon__database_container_name')
Esempio n. 4
0
def configure_dns(elastic_ip_id, hosted_zone_id):
    """Configure the DNS of the main TigerHost server.

    This points tigerhost.com (not a subdomain) to the main server
    """
    echo_heading('Creating A record.', marker='-', marker_color='magenta')
    ec2 = boto3.resource('ec2')
    client = boto3.client('route53')
    client.change_resource_record_sets(
        HostedZoneId=hosted_zone_id,
        ChangeBatch={
            'Comment':
            'Test comment',
            'Changes': [
                {
                    'Action': 'UPSERT',
                    'ResourceRecordSet': {
                        'Name':
                        settings.DOMAIN_NAME,
                        'Type':
                        'A',
                        'TTL':
                        60,
                        'ResourceRecords': [
                            {
                                'Value':
                                ec2.VpcAddress(elastic_ip_id).public_ip
                            },
                        ],
                    }
                },
            ]
        })
    click.echo('Done.')
Esempio n. 5
0
def update(name):
    """Update the main TigerHost server. This also updates the documentation.
    """
    echo_heading('Retrieving server config.',
                 marker='-',
                 marker_color='magenta')
    project_path = get_project_path()
    database = store.get('main__database_url')
    secret = store.get('main__django_secret')
    addon_name = store.get('main__addon_name')
    if database is None or secret is None or addon_name is None:
        raise click.exceptions.ClickException(
            'Server config not found. Was a TigerHost server created with `{} main create`?'
            .format(settings.APP_NAME))
    click.echo('Done.')

    echo_heading('Making sure addon machine exists.',
                 marker='-',
                 marker_color='magenta')
    addon_docker_host = docker_machine.get_url(addon_name)
    click.echo('Done.')

    echo_heading('Copying addon machine credentials.',
                 marker='-',
                 marker_color='magenta')
    target_path = os.path.join(project_path, 'web/credentials')
    if not os.path.exists(target_path):
        os.mkdir(target_path)
    docker_machine.retrieve_credentials(addon_name, target_path)
    click.echo('Done.')

    echo_heading('Generating docker-compose file.',
                 marker='-',
                 marker_color='magenta')
    _generate_compose_file(project_path, database, addon_docker_host, secret)
    click.echo('Done.')

    echo_heading('Initializing TigerHost containers.',
                 marker='-',
                 marker_color='magenta')
    env_text = docker_machine.check_output(['env', name])
    env = os.environ.copy()
    env.update(parse_shell_for_exports(env_text))
    subprocess.check_call([
        'docker-compose', '-f',
        os.path.join(get_project_path(), 'docker-compose.prod.yml'), '-p',
        settings.MAIN_COMPOSE_PROJECT_NAME, 'build'
    ],
                          env=env)
    subprocess.check_call([
        'docker-compose', '-f',
        os.path.join(get_project_path(), 'docker-compose.prod.yml'), '-p',
        settings.MAIN_COMPOSE_PROJECT_NAME, 'up', '-d'
    ],
                          env=env)
Esempio n. 6
0
def destroy(name):
    """Destroy the main TigerHost server's machine.
    """
    echo_heading('Destroying machine {name}.'.format(name=name),
                 marker='-',
                 marker_color='magenta')
    docker_machine.check_call(['rm', '-y', name])
    store.unset('main__database_url')
    store.unset('main__django_secret')
    store.unset('main__addon_name')
    store.unset('main__elastic_ip_id')
Esempio n. 7
0
 def new_func(ctx, *args, **kwargs):
     """
     @type ctx: click.Context
     """
     path = path_utils.executable_path(name)
     if not os.path.exists(path):
         echo_heading('Installing {}.'.format(name),
                      marker='-',
                      marker_color='magenta')
         get_executable()
         assert os.path.exists(path)
     return ctx.invoke(f, *args, **kwargs)
Esempio n. 8
0
def destroy_app(ctx):
    """Delete the current application.
    """
    app = ctx.obj['app']
    api_client = ctx.obj['api_client']
    click_extensions.echo_heading('Destroying all addons.', marker_color='magenta')
    addons = api_client.get_application_addons(app)
    for x in addons:
        click.echo('Destroying {name} ({addon}).'.format(name=x['display_name'], addon=x['provider_name']))
        api_client.delete_application_addon(app, x['display_name'])
    click_extensions.echo_heading('Destroying app.', marker_color='magenta')
    api_client.delete_application(app)
    click.echo('App {} destroyed.'.format(app))
Esempio n. 9
0
def destroy_app(ctx):
    """Delete the current application.
    """
    app = ctx.obj['app']
    api_client = ctx.obj['api_client']
    click_extensions.echo_heading('Destroying all addons.',
                                  marker_color='magenta')
    addons = api_client.get_application_addons(app)
    for x in addons:
        click.echo('Destroying {name} ({addon}).'.format(
            name=x['display_name'], addon=x['provider_name']))
        api_client.delete_application_addon(app, x['display_name'])
    click_extensions.echo_heading('Destroying app.', marker_color='magenta')
    api_client.delete_application(app)
    click.echo('App {} destroyed.'.format(app))
Esempio n. 10
0
def create_admin(password, email):
    """Create an admin user on Deis
    """
    echo_heading('Creating admin user.')
    username = '******'
    if password is None:
        password = random_string(length=30)
    deis = path_utils.executable_path('deis')
    subprocess.check_call([deis, 'register',
                           'http://deis.' + settings.DOMAIN_NAME,
                           '--username={}'.format(username), '--email={}'.format(email), '--password={}'.format(password)])
    store.set('deis__username', username)
    store.set('deis__password', password)
    store.set('deis__email', email)
    click.echo('Done.')
Esempio n. 11
0
def create_admin(password, email):
    """Create an admin user on Deis
    """
    echo_heading('Creating admin user.')
    username = '******'
    if password is None:
        password = random_string(length=30)
    deis = path_utils.executable_path('deis')
    subprocess.check_call([
        deis, 'register', 'http://deis.' + settings.DOMAIN_NAME,
        '--username={}'.format(username), '--email={}'.format(email),
        '--password={}'.format(password)
    ])
    store.set('deis__username', username)
    store.set('deis__password', password)
    store.set('deis__email', email)
    click.echo('Done.')
Esempio n. 12
0
def create(elastic_ip_id, email, rds_database, secret, hosted_zone_id):
    """This is a shortcut to create the Deis cluster, the addons server,
    and the main TigerHost server in that order. This also configures
    the DNS for Deis and the main server.
    """
    if secret is None:
        secret = _get_secret()
    if elastic_ip_id is None:
        if not settings.DEBUG:
            echo_heading('Allocating a new Elastic IP.', marker='-', marker_color='magenta')
            client = boto3.client('ec2')
            elastic_ip_id = client.allocate_address(Domain='vpc')['AllocationId']
            click.echo('Done. Allocation ID: {}'.format(elastic_ip_id))
        else:
            # not used anyways
            elastic_ip_id = 'dummy-ip-id'
    subprocess.check_call([settings.APP_NAME, 'deis', 'create'])
    subprocess.check_call([settings.APP_NAME, 'deis', 'configure-dns', '--hosted-zone-id', hosted_zone_id])

    database_url = None
    addons_ip = None

    if rds_database:
        # TODO implement this
        click.abort()
    else:
        db_container_name = random_string(length=50)
        subprocess.check_call(
            [settings.APP_NAME, 'addons', 'create', '--database', db_container_name])
        addons_ip = docker_machine.check_output(
            ['ip', 'tigerhost-addons-aws']).strip()
        database_url = 'postgres://{name}@{ip}:5432/{name}'.format(
            name=db_container_name,
            ip=addons_ip,
        )

    subprocess.check_call(
        [settings.APP_NAME, 'main', 'create',
         '--database', database_url,
         '--elastic-ip-id', elastic_ip_id,
         '--secret', secret,
         ])

    subprocess.check_call([settings.APP_NAME, 'main', 'configure-dns', '--elastic-ip-id', elastic_ip_id, '--hosted-zone-id', hosted_zone_id])

    subprocess.check_call([settings.APP_NAME, 'deis', 'create-admin', '--email', email])
Esempio n. 13
0
def configure_dns(stack, hosted_zone_id):
    """Configure the DNS of the Deis cluster.

    This points *.tigerhostapp.com to Deis.
    """
    echo_heading('Creating A record.', marker='-', marker_color='magenta')
    cloudformation = boto3.resource('cloudformation')
    stack_instance = cloudformation.Stack(stack)

    dns_name = None
    for x in stack_instance.outputs:
        if x['OutputKey'] == 'DNSName':
            dns_name = x['OutputValue']
    assert dns_name is not None

    # TODO this fails on accounts with more than 400 load balancers
    elb_hosted_zone_id = None
    elb_client = boto3.client('elb')
    for x in elb_client.describe_load_balancers()['LoadBalancerDescriptions']:
        if x['DNSName'] == dns_name:
            elb_hosted_zone_id = x['CanonicalHostedZoneNameID']
    assert elb_hosted_zone_id is not None

    client = boto3.client('route53')
    client.change_resource_record_sets(
        HostedZoneId=hosted_zone_id,
        ChangeBatch={
            'Comment': 'Test comment',
            'Changes': [
                {
                    'Action': 'UPSERT',
                    'ResourceRecordSet': {
                        'Name': '*.' + settings.DOMAIN_NAME,
                        'Type': 'A',
                        'AliasTarget': {
                            'HostedZoneId': elb_hosted_zone_id,
                            'DNSName': dns_name,
                            'EvaluateTargetHealth': False
                        },
                    }
                },
            ]
        }
    )
    click.echo('Done.')
Esempio n. 14
0
def create(ctx, name, instance_type, database):
    """Create machine for the addon server.
    """
    # TODO verify that database is [a-zA-Z0-9_]
    echo_heading('Creating machine {name} with type {type}.'.format(
        name=name, type=instance_type),
                 marker='-',
                 marker_color='magenta')
    if settings.DEBUG:
        docker_machine.check_call(['create', '--driver', 'virtualbox', name])
    else:
        docker_machine.check_call([
            'create', '--driver', 'amazonec2', '--amazonec2-instance-type',
            instance_type, name
        ])
        utils.set_aws_security_group_ingress_rule('docker-machine', 0, 65535,
                                                  '0.0.0.0/0')

    project_path = get_project_path()

    echo_heading('Generating docker-compose file.',
                 marker='-',
                 marker_color='magenta')
    _generate_compose_file(project_path, database)

    echo_heading('Instantiating addons proxy.',
                 marker='-',
                 marker_color='magenta')
    env_text = docker_machine.check_output(['env', name])
    env = os.environ.copy()
    env.update(utils.parse_shell_for_exports(env_text))

    subprocess.check_call([
        'docker-compose', '-f',
        os.path.join(project_path, 'proxy/docker-compose.prod.yml'), '-p',
        settings.ADDONS_COMPOSE_PROJECT_NAME, 'up', '-d'
    ],
                          env=env)

    store.set('addon__database_container_name', database)
Esempio n. 15
0
def update(name):
    """Update the addon server.
    """
    echo_heading('Retrieving addons config.', marker='-', marker_color='magenta')
    database = store.get('addon__database_container_name', default=False)
    if database is False:
        raise click.exceptions.ClickException('Addons config not found. Was an addon server created with `{} addons create`?'.format(settings.APP_NAME))
    click.echo('Done.')

    project_path = get_project_path()
    echo_heading('Generating docker-compose file.', marker='-', marker_color='magenta')
    _generate_compose_file(project_path, database)
    click.echo('Done.')

    echo_heading('Updating addons proxy.', marker='-', marker_color='magenta')
    env_text = docker_machine.check_output(['env', name])
    env = os.environ.copy()
    env.update(utils.parse_shell_for_exports(env_text))

    subprocess.check_call(['docker-compose', '-f', os.path.join(
        project_path, 'proxy/docker-compose.prod.yml'), '-p', settings.ADDONS_COMPOSE_PROJECT_NAME, 'build'], env=env)
    subprocess.check_call(['docker-compose', '-f', os.path.join(
        project_path, 'proxy/docker-compose.prod.yml'), '-p', settings.ADDONS_COMPOSE_PROJECT_NAME, 'up', '-d'], env=env)
Esempio n. 16
0
def update(name):
    """Update the addon server.
    """
    echo_heading('Retrieving addons config.',
                 marker='-',
                 marker_color='magenta')
    database = store.get('addon__database_container_name', default=False)
    if database is False:
        raise click.exceptions.ClickException(
            'Addons config not found. Was an addon server created with `{} addons create`?'
            .format(settings.APP_NAME))
    click.echo('Done.')

    project_path = get_project_path()
    echo_heading('Generating docker-compose file.',
                 marker='-',
                 marker_color='magenta')
    _generate_compose_file(project_path, database)
    click.echo('Done.')

    echo_heading('Updating addons proxy.', marker='-', marker_color='magenta')
    env_text = docker_machine.check_output(['env', name])
    env = os.environ.copy()
    env.update(utils.parse_shell_for_exports(env_text))

    subprocess.check_call([
        'docker-compose', '-f',
        os.path.join(project_path, 'proxy/docker-compose.prod.yml'), '-p',
        settings.ADDONS_COMPOSE_PROJECT_NAME, 'build'
    ],
                          env=env)
    subprocess.check_call([
        'docker-compose', '-f',
        os.path.join(project_path, 'proxy/docker-compose.prod.yml'), '-p',
        settings.ADDONS_COMPOSE_PROJECT_NAME, 'up', '-d'
    ],
                          env=env)
Esempio n. 17
0
def create(name, instance_type, database, addon_name, secret, elastic_ip_id):
    """Create a new machine for the main TigerHost server.

    The addon servers machine must already be created.
    """
    project_path = get_project_path()

    # get url, ensures addon machine exists
    echo_heading('Making sure addon machine exists.', marker='-', marker_color='magenta')
    addon_docker_host = docker_machine.get_url(addon_name)
    click.echo('Done.')

    echo_heading('Copying addon machine credentials.', marker='-', marker_color='magenta')
    target_path = os.path.join(project_path, 'web/credentials')
    if not os.path.exists(target_path):
        os.mkdir(target_path)
    docker_machine.retrieve_credentials(addon_name, target_path)
    click.echo('Done.')

    echo_heading('Creating machine {name} with type {type}.'.format(
        name=name, type=instance_type), marker='-', marker_color='magenta')
    if settings.DEBUG:
        docker_machine.check_call(['create', '--driver',
                                   'virtualbox', name])
    else:
        docker_machine.check_call(['create', '--driver',
                                   'amazonec2', '--amazonec2-instance-type', instance_type, name])
        set_aws_security_group_ingress_rule(
            'docker-machine', 0, 65535, '0.0.0.0/0')

        echo_heading(
            'Associating Elastic IP.'.format(name), marker='-', marker_color='magenta')
        click.echo('Done.')
        new_ip = _associate_elastic_ip(name, elastic_ip_id)

        echo_heading(
            'Saving IP {} to docker-machine.'.format(new_ip), marker='-', marker_color='magenta')
        _update_docker_machine_ip(name, new_ip)

    echo_heading('Generating docker-compose file.', marker='-', marker_color='magenta')
    _generate_compose_file(project_path, database, addon_docker_host, secret)
    click.echo('Done.')

    echo_heading('Initializing TigerHost containers.', marker='-', marker_color='magenta')
    env_text = docker_machine.check_output(['env', name])
    env = os.environ.copy()
    env.update(parse_shell_for_exports(env_text))
    subprocess.check_call(['docker-compose', '-f', os.path.join(
        get_project_path(), 'docker-compose.prod.yml'), '-p', settings.MAIN_COMPOSE_PROJECT_NAME, 'up', '-d'], env=env)
    store.set('main__database_url', database)
    store.set('main__django_secret', secret)
    store.set('main__addon_name', addon_name)
    store.set('main__elastic_ip_id', elastic_ip_id)
Esempio n. 18
0
def create(name, instance_type, database, addon_name, secret, elastic_ip_id):
    """Create a new machine for the main TigerHost server.

    The addon servers machine must already be created.
    """
    project_path = get_project_path()

    # get url, ensures addon machine exists
    echo_heading('Making sure addon machine exists.',
                 marker='-',
                 marker_color='magenta')
    addon_docker_host = docker_machine.get_url(addon_name)
    click.echo('Done.')

    echo_heading('Copying addon machine credentials.',
                 marker='-',
                 marker_color='magenta')
    target_path = os.path.join(project_path, 'web/credentials')
    if not os.path.exists(target_path):
        os.mkdir(target_path)
    docker_machine.retrieve_credentials(addon_name, target_path)
    click.echo('Done.')

    echo_heading('Creating machine {name} with type {type}.'.format(
        name=name, type=instance_type),
                 marker='-',
                 marker_color='magenta')
    if settings.DEBUG:
        docker_machine.check_call(['create', '--driver', 'virtualbox', name])
    else:
        docker_machine.check_call([
            'create', '--driver', 'amazonec2', '--amazonec2-instance-type',
            instance_type, name
        ])
        set_aws_security_group_ingress_rule('docker-machine', 0, 65535,
                                            '0.0.0.0/0')

        echo_heading('Associating Elastic IP.'.format(name),
                     marker='-',
                     marker_color='magenta')
        click.echo('Done.')
        new_ip = _associate_elastic_ip(name, elastic_ip_id)

        echo_heading('Saving IP {} to docker-machine.'.format(new_ip),
                     marker='-',
                     marker_color='magenta')
        _update_docker_machine_ip(name, new_ip)

    echo_heading('Generating docker-compose file.',
                 marker='-',
                 marker_color='magenta')
    _generate_compose_file(project_path, database, addon_docker_host, secret)
    click.echo('Done.')

    echo_heading('Initializing TigerHost containers.',
                 marker='-',
                 marker_color='magenta')
    env_text = docker_machine.check_output(['env', name])
    env = os.environ.copy()
    env.update(parse_shell_for_exports(env_text))
    subprocess.check_call([
        'docker-compose', '-f',
        os.path.join(get_project_path(), 'docker-compose.prod.yml'), '-p',
        settings.MAIN_COMPOSE_PROJECT_NAME, 'up', '-d'
    ],
                          env=env)
    store.set('main__database_url', database)
    store.set('main__django_secret', secret)
    store.set('main__addon_name', addon_name)
    store.set('main__elastic_ip_id', elastic_ip_id)