def test_without_project_path_default_exists_abort(runner, fake_git_remote):
    assert get_project_path() is None
    assert not os.system('mkdir {}'.format(default_project_path()))
    with mock.patch('deploy.settings.PROJECT_REMOTE', new=fake_git_remote):
        result = runner.invoke(dummy, input='1\nn\n')
    assert result.exit_code == exit_codes.ABORT
    assert get_project_path() is None
def test_without_project_path_default_exists_file(runner, fake_git_remote):
    assert get_project_path() is None
    assert not os.system('touch {}'.format(default_project_path()))
    with mock.patch('deploy.settings.PROJECT_REMOTE', new=fake_git_remote):
        result = runner.invoke(dummy, input='1\n\n')
    assert result.exit_code == exit_codes.SUCCESS
    assert get_project_path() == path_utils.canonical_path(default_project_path())
def test_without_project_path_default_exists_abort(runner, fake_git_remote):
    assert get_project_path() is None
    assert not os.system('mkdir {}'.format(default_project_path()))
    with mock.patch('deploy.settings.PROJECT_REMOTE', new=fake_git_remote):
        result = runner.invoke(dummy, input='1\nn\n')
    assert result.exit_code == exit_codes.ABORT
    assert get_project_path() is None
def test_without_project_path_default_normal(runner, fake_git_remote):
    assert get_project_path() is None
    with mock.patch('deploy.settings.PROJECT_REMOTE', new=fake_git_remote):
        result = runner.invoke(dummy, input='1\n')
    assert result.exit_code == exit_codes.SUCCESS
    assert get_project_path() == path_utils.canonical_path(
        default_project_path())
def test_without_project_path_default_exists_file(runner, fake_git_remote):
    assert get_project_path() is None
    assert not os.system('touch {}'.format(default_project_path()))
    with mock.patch('deploy.settings.PROJECT_REMOTE', new=fake_git_remote):
        result = runner.invoke(dummy, input='1\n\n')
    assert result.exit_code == exit_codes.SUCCESS
    assert get_project_path() == path_utils.canonical_path(
        default_project_path())
示例#6
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)
示例#7
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)
示例#8
0
def create(stack):
    """Create a new Deis cluster.
    """
    deisctl = path_utils.executable_path('deisctl')
    subprocess.check_call(['ssh-add', path_utils.ssh_path('deis')])
    with contextmanagers.chdir(os.path.join(get_project_path(), 'deis')):
        subprocess.check_call(['make', 'discovery-url'])
        click.echo('Provisioning machines.')
        with contextmanagers.chdir('contrib/aws'):
            subprocess.check_call(['./provision-aws-cluster.sh', stack])
        ec2 = boto3.resource('ec2')
        instances = ec2.instances.filter(Filters=[
            {
                'Name': 'instance-state-name',
                'Values': ['running'],
            },
            {
                'Name': 'tag:aws:cloudformation:stack-name',
                'Values': [stack],
            },
        ]).limit(1)
        ip = None
        for i in instances:
            ip = i.public_ip_address
        assert ip is not None
        click.echo('Machines provisioned. An IP address is {}.'.format(ip))
        env = {'DEISCTL_TUNNEL': ip}
        env.update(os.environ)
        click.echo('Installing Deis.')
        subprocess.check_call([
            deisctl, 'config', 'platform', 'set',
            'sshPrivateKey=' + path_utils.ssh_path('deis')
        ],
                              env=env)
        subprocess.check_call([
            deisctl, 'config', 'platform', 'set',
            'domain=' + settings.DOMAIN_NAME
        ],
                              env=env)
        subprocess.check_call([deisctl, 'refresh-units'], env=env)
        subprocess.check_call([deisctl, 'install', 'platform'], env=env)
        subprocess.check_call([deisctl, 'start', 'platform'], env=env)
示例#9
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)
示例#10
0
 def new_func(ctx, *args, **kwargs):
     """
     :param click.Context ctx:
     """
     if get_project_path() is None:
         click.echo('Config project_path not set.')
         click.echo('You can do one of the following:')
         choice = click_utils.prompt_choices([
             'Clone the repository to {}.'.format(default_project_path()),
             'Specify the path to an existing repo.'
         ])
         if choice == 0:
             path = default_project_path()
             if os.path.exists(path):
                 click.confirm(
                     'Path {} already exists. Continuing will remove this path.'
                     .format(path),
                     default=True,
                     abort=True)
                 if os.path.isdir(path):
                     shutil.rmtree(path)
                 else:
                     os.remove(path)
             click.echo('Cloning to {}...'.format(path), nl=False)
             clone_project()
             click.secho('Done', fg='black', bg='green')
             save_project_path(path)
         else:
             value = click.prompt('Please enter the path to your project',
                                  type=str)
             value = path_utils.canonical_path(value)
             if not os.path.exists(value) or not os.path.isdir(value):
                 click.echo('This directory does not exist.')
                 ctx.exit(code=exit_codes.OTHER_FAILURE)
             click.confirm('Is your project at {}?'.format(value),
                           default=True,
                           abort=True)
             save_project_path(value)
     return ctx.invoke(f, *args, **kwargs)
示例#11
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)
示例#12
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)
def test_without_project_path_default_normal(runner, fake_git_remote):
    assert get_project_path() is None
    with mock.patch('deploy.settings.PROJECT_REMOTE', new=fake_git_remote):
        result = runner.invoke(dummy, input='1\n')
    assert result.exit_code == exit_codes.SUCCESS
    assert get_project_path() == path_utils.canonical_path(default_project_path())
def test_without_project_path_normal(runner):
    assert get_project_path() is None
    result = runner.invoke(dummy, input='2\n.\n\n')
    assert result.exit_code == exit_codes.SUCCESS
    assert get_project_path() == path_utils.canonical_path('.')
示例#15
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)
示例#16
0
def test_project_path():
    assert get_project_path() is None
    save_project_path('/test/../')
    assert get_project_path() == '/'
def test_path_already_exists(runner):
    assert get_project_path() is None
    save_project_path('.')
    result = runner.invoke(dummy)
    assert result.exit_code == exit_codes.SUCCESS
    assert get_project_path() == path_utils.canonical_path('.')
def test_without_project_path_not_confirmed(runner):
    assert get_project_path() is None
    result = runner.invoke(dummy, input='2\n.\nn\n')
    assert result.exit_code == exit_codes.ABORT
    assert get_project_path() is None
def test_without_project_path_nonexist(runner):
    assert get_project_path() is None
    result = runner.invoke(dummy, input='2\n/doesnotexist\n\n')
    assert result.exit_code == exit_codes.OTHER_FAILURE
    assert get_project_path() is None
def test_without_project_path_normal(runner):
    assert get_project_path() is None
    result = runner.invoke(dummy, input='2\n.\n\n')
    assert result.exit_code == exit_codes.SUCCESS
    assert get_project_path() == path_utils.canonical_path('.')
def test_without_project_path_nonexist(runner):
    assert get_project_path() is None
    result = runner.invoke(dummy, input='2\n/doesnotexist\n\n')
    assert result.exit_code == exit_codes.OTHER_FAILURE
    assert get_project_path() is None
def test_without_project_path_not_confirmed(runner):
    assert get_project_path() is None
    result = runner.invoke(dummy, input='2\n.\nn\n')
    assert result.exit_code == exit_codes.ABORT
    assert get_project_path() is None
def test_path_already_exists(runner):
    assert get_project_path() is None
    save_project_path('.')
    result = runner.invoke(dummy)
    assert result.exit_code == exit_codes.SUCCESS
    assert get_project_path() == path_utils.canonical_path('.')