Ejemplo n.º 1
0
def visualisation_branch_html_POST(request, gitlab_project, branch_name):
    release_commit = request.POST['release-commit']
    application_template = _application_template(gitlab_project)
    get_spawner(application_template.spawner).retag(
        application_options(application_template),
        f'{application_template.host_basename}--{release_commit}',
        application_template.host_basename,
    )

    try:
        application_instance = ApplicationInstance.objects.get(
            public_host=application_template.host_basename,
            state__in=['RUNNING', 'SPAWNING'],
        )
    except ApplicationInstance.DoesNotExist:
        pass
    else:
        stop_spawner_and_application(application_instance)

    messages.success(request, f'Released commit {release_commit} to production')

    return redirect(
        'visualisations:branch',
        gitlab_project_id=gitlab_project['id'],
        branch_name=branch_name,
    )
Ejemplo n.º 2
0
def application_api_PUT(request, public_host):
    # A transaction is unnecessary: the single_running_or_spawning_integrity
    # key prevents duplicate spawning/running applications at the same
    # public host
    try:
        application_instance = get_api_visible_application_instance_by_public_host(
            public_host)
    except ApplicationInstance.DoesNotExist:
        pass
    else:
        return JsonResponse({"message": "Application instance already exists"},
                            status=409)

    try:
        (
            application_template,
            tag,
            _,
            commit_id,
        ) = application_template_tag_user_commit_from_host(public_host)
    except ApplicationTemplate.DoesNotExist:
        return JsonResponse({"message": "Application template does not exist"},
                            status=400)

    app_type = application_template.application_type

    if app_type == "TOOL":
        tool_configuration = (
            application_template.user_tool_configuration.filter(
                user=request.user).first()
            or UserToolConfiguration.default_config())
        cpu = tool_configuration.size_config.cpu
        memory = tool_configuration.size_config.memory
    else:
        cpu = application_template.default_cpu
        memory = application_template.default_memory

    spawner_options = json.dumps(application_options(application_template))

    try:
        application_instance = ApplicationInstance.objects.create(
            owner=request.user,
            application_template=application_template,
            spawner=application_template.spawner,
            spawner_application_template_options=spawner_options,
            spawner_application_instance_id=json.dumps({}),
            public_host=public_host,
            state="SPAWNING",
            single_running_or_spawning_integrity=public_host,
            cpu=cpu,
            memory=memory,
            commit_id=commit_id,
        )
    except IntegrityError:
        application_instance = get_api_visible_application_instance_by_public_host(
            public_host)
    else:
        spawn.delay(
            application_template.spawner,
            request.user.pk,
            tag,
            application_instance.id,
            spawner_options,
        )

    return JsonResponse(api_application_dict(application_instance), status=200)
Ejemplo n.º 3
0
def application_api_PUT(request, public_host):
    # A transaction is unnecessary: the single_running_or_spawning_integrity
    # key prevents duplicate spawning/running applications at the same
    # public host
    try:
        application_instance = get_api_visible_application_instance_by_public_host(
            public_host)
    except ApplicationInstance.DoesNotExist:
        pass
    else:
        return JsonResponse({'message': 'Application instance already exists'},
                            status=409)

    try:
        (
            application_template,
            tag,
            _,
            commit_id,
        ) = application_template_tag_user_commit_from_host(public_host)
    except ApplicationTemplate.DoesNotExist:
        return JsonResponse({'message': 'Application template does not exist'},
                            status=400)

    app_type = application_template.application_type

    (source_tables, db_role_schema_suffix, db_user) = ((
        source_tables_for_user(request.user),
        db_role_schema_suffix_for_user(request.user),
        postgres_user(request.user.email),
    ) if app_type == 'TOOL' else (
        source_tables_for_app(application_template),
        db_role_schema_suffix_for_app(application_template),
        postgres_user(application_template.host_basename),
    ))

    credentials = new_private_database_credentials(db_role_schema_suffix,
                                                   source_tables, db_user)

    if app_type == 'TOOL':
        # For AppStream to access credentials
        write_credentials_to_bucket(request.user, credentials)

    try:
        memory, cpu = request.GET['__memory_cpu'].split('_')
    except KeyError:
        memory = None
        cpu = None

    spawner_options = json.dumps(application_options(application_template))

    try:
        application_instance = ApplicationInstance.objects.create(
            owner=request.user,
            application_template=application_template,
            spawner=application_template.spawner,
            spawner_application_template_options=spawner_options,
            spawner_application_instance_id=json.dumps({}),
            public_host=public_host,
            state='SPAWNING',
            single_running_or_spawning_integrity=public_host,
            cpu=cpu,
            memory=memory,
            commit_id=commit_id,
        )
    except IntegrityError:
        application_instance = get_api_visible_application_instance_by_public_host(
            public_host)
    else:
        # The database users are stored so when the database users are cleaned up,
        # we know _not_ to delete any users used by running or spawning apps
        for creds in credentials:
            ApplicationInstanceDbUsers.objects.create(
                application_instance=application_instance,
                db_id=creds['db_id'],
                db_username=creds['db_user'],
            )

        app_schema = f'{USER_SCHEMA_STEM}{db_role_schema_suffix}'

        spawn.delay(
            application_template.spawner,
            request.user.email,
            str(request.user.profile.sso_id),
            tag,
            application_instance.id,
            spawner_options,
            credentials,
            app_schema,
        )

    return JsonResponse(api_application_dict(application_instance), status=200)
Ejemplo n.º 4
0
def visualisation_branch_html_GET(request, gitlab_project, branch_name):
    branches = _visualisation_branches(gitlab_project)

    matching_branches = [branch for branch in branches if branch['name'] == branch_name]
    if len(matching_branches) > 1:
        raise Exception('Too many matching branches')
    if not matching_branches:
        raise Http404

    application_template = _application_template(gitlab_project)
    current_branch = matching_branches[0]
    latest_commit = current_branch['commit']
    latest_commit_link = f'{gitlab_project["web_url"]}/commit/{latest_commit["id"]}'
    latest_commit_preview_link = (
        f'{request.scheme}://{application_template.host_basename}--{latest_commit["short_id"]}'
        f'.{settings.APPLICATION_ROOT_DOMAIN}/'
    )
    latest_commit_date = datetime.datetime.strptime(
        latest_commit['committed_date'], '%Y-%m-%dT%H:%M:%S.%f%z'
    )
    latest_commit_tag_exists = get_spawner(application_template.spawner).tags_for_tag(
        application_options(application_template),
        f'{application_template.host_basename}--{latest_commit["short_id"]}',
    )

    host_basename = application_template.host_basename
    production_link = (
        f'{request.scheme}://{host_basename}.{settings.APPLICATION_ROOT_DOMAIN}/'
    )
    tags = get_spawner(application_template.spawner).tags_for_tag(
        application_options(application_template), application_template.host_basename
    )
    production_commit_id = None
    for tag in tags:
        possible_host_basename, _, host_basename_or_commit_id = tag.rpartition('--')
        if possible_host_basename:
            production_commit_id = host_basename_or_commit_id
            break

    # It might not be good, UI-wise, to force the user to have to preview a
    # commit before it can be released. However, building a Docker image is
    # done via the preview link, so this is the quickest/easiest thing for
    # users to be able to release a new version of the visualisation
    must_preview_latest_commit_to_release = (
        current_branch['name'] == gitlab_project['default_branch']
        and not latest_commit_tag_exists
        and latest_commit['short_id'] != production_commit_id
    )
    can_release_latest_commit = (
        current_branch['name'] == gitlab_project['default_branch']
        and latest_commit_tag_exists
        and latest_commit['short_id'] != production_commit_id
    )
    latest_commit_is_released = latest_commit['short_id'] == production_commit_id

    return _render_visualisation(
        request,
        'visualisation_branch.html',
        gitlab_project,
        application_template,
        branches,
        current_menu_item='branches',
        template_specific_context={
            'production_link': production_link,
            'production_commit_id': production_commit_id,
            'current_branch': current_branch,
            'latest_commit': latest_commit,
            'latest_commit_link': latest_commit_link,
            'latest_commit_preview_link': latest_commit_preview_link,
            'latest_commit_date': latest_commit_date,
            'latest_commit_tag_exists': latest_commit_tag_exists,
            'can_release_latest_commit': can_release_latest_commit,
            'must_preview_latest_commit_to_release': must_preview_latest_commit_to_release,
            'latest_commit_is_released': latest_commit_is_released,
        },
    )