Example #1
0
def submit(ctx, file, annotation, large, public, private):
    """
    For uploading submission files to evalai:
        - Invoked by running 'evalai challenge CHALLENGE phase PHASE submit --file FILE'
        - For large files, add a '--large' option at the end of the command

    For uploading test annotation files to evalai:
        - Invoked by running "evalai challenge CHALLENGE phase PHASE submit --file FILE --annotation"

    Arguments:
        ctx (class click.Context) --  The context object which holds state of the invocation
        file (str) -- the path of the file to be uploaded
        annotations (boolean) -- flag to denote if file is a test annotation file
        large (boolean) -- flag to denote if submission file is large (if large, presigned urls are used for uploads)
        public (boolean) -- flag to denote if submission is public
        private (boolean) -- flag to denote if submission is private
    Returns:
        None
    """
    if public and private:
        message = "\nError: Submission can't be public and private.\nPlease select either --public or --private"
        notify_user(message, color="red")
    else:
        if annotation:
            upload_file_using_presigned_url(ctx.phase_id, file, "annotation")
        else:
            submission_metadata = {}
            if public:
                submission_metadata["is_public"] = json.dumps(True)
            elif private:
                submission_metadata["is_public"] = json.dumps(False)
            else:
                submission_metadata["is_public"] = None
            if click.confirm("Do you want to include the Submission Details?"):
                submission_metadata["method_name"] = click.prompt(
                    style("Method Name", fg="yellow"), type=str, default=""
                )
                submission_metadata["method_description"] = click.prompt(
                    style("Method Description", fg="yellow"), type=str, default=""
                )
                submission_metadata["project_url"] = click.prompt(
                    style("Project URL", fg="yellow"), type=str, default=""
                )
                submission_metadata["publication_url"] = click.prompt(
                    style("Publication URL", fg="yellow"), type=str, default=""
                )
            if large:
                upload_file_using_presigned_url(ctx.phase_id, file, "submission", submission_metadata)
            else:
                make_submission(ctx.challenge_id, ctx.phase_id, file, submission_metadata)
Example #2
0
def participate(ctx, team):
    """
    Participate in a challenge.
    """
    """
    Invoked by running `evalai challenge CHALLENGE participate TEAM`
    """
    terms_and_conditions_page_url = "{}{}".format(get_host_url(), URLS.terms_and_conditions_page.value)
    terms_and_conditions_page_url = terms_and_conditions_page_url.format(ctx.challenge_id)
    message = "Please refer challenge terms and conditions here: {}" \
        "\n\nBy agreeing to participate in the challenge, you are agreeing to terms and conditions." \
        "\n\nDo you accept challenge terms and conditions?".format(terms_and_conditions_page_url)
    if click.confirm(message):
        participate_in_a_challenge(ctx.challenge_id, team)
    else:
        message = "\nYou can't participate in the challenge without accepting terms and conditions"
        notify_user(message, color="red")
Example #3
0
def submit(ctx, file, annotation, large, public, private):
    """
    For uploading submission files to evalai:
        - Invoked by running 'evalai challenge CHALLENGE phase PHASE submit --file FILE'
        - For large files, add a '--large' option at the end of the command

    For uploading test annotation files to evalai:
        - Invoked by running "evalai challenge CHALLENGE phase PHASE submit --file FILE --annotation"

    Arguments:
        ctx (class click.Context) --  The context object which holds state of the invocation
        file (str) -- the path of the file to be uploaded
        annotations (boolean) -- flag to denote if file is a test annotation file
        large (boolean) -- flag to denote if submission file is large (if large, presigned urls are used for uploads)
        public (boolean) -- flag to denote if submission is public
        private (boolean) -- flag to denote if submission is private
    Returns:
        None
    """
    if public and private:
        message = "\nError: Submission can't be public and private.\nPlease select either --public or --private"
        notify_user(message, color="red")
    else:
        if annotation:
            upload_file_using_presigned_url(ctx.phase_id, file, "annotation")
        else:
            submission_metadata = {}
            if public:
                submission_metadata["is_public"] = json.dumps(True)
            elif private:
                submission_metadata["is_public"] = json.dumps(False)
            else:
                submission_metadata["is_public"] = None
            if click.confirm("Do you want to include the Submission Details?"):
                submission_metadata["method_name"] = click.prompt(style(
                    "Method Name", fg="yellow"),
                                                                  type=str,
                                                                  default="")
                submission_metadata["method_description"] = click.prompt(
                    style("Method Description", fg="yellow"),
                    type=str,
                    default="",
                )
                submission_metadata["project_url"] = click.prompt(style(
                    "Project URL", fg="yellow"),
                                                                  type=str,
                                                                  default="")
                submission_metadata["publication_url"] = click.prompt(
                    style("Publication URL", fg="yellow"),
                    type=str,
                    default="")
            submission_meta_attributes = get_submission_meta_attributes(
                ctx.challenge_id, ctx.phase_id)
            submission_attribute_metadata = []
            if (submission_meta_attributes
                    and len(submission_meta_attributes) > 0):
                if click.confirm(
                        "Do you want to include the Submission Metadata?"):
                    for attribute in submission_meta_attributes:
                        attribute_type = attribute["type"]
                        attribute_name = attribute["name"]
                        attribute_description = attribute["description"]
                        attribute_required = attribute.get("required")
                        if attribute_required:
                            attribute_name = attribute_name + '*'
                        value = None
                        message = "{} ({})".format(attribute_name,
                                                   attribute_description)
                        if attribute_type == "text":
                            while True:
                                value = click.prompt(
                                    style(message, fg="yellow"),
                                    type=str,
                                    default="",
                                )
                                if not attribute_required or value != "":
                                    break
                                echo("Error: {} is a required field".format(
                                    attribute["name"]))
                        if attribute_type == "boolean":
                            while True:
                                value = click.prompt(style(message,
                                                           fg="yellow"),
                                                     type=bool,
                                                     default="")
                                if not attribute_required or value != "":
                                    break
                                echo("Error: {} is a required field".format(
                                    attribute["name"]))
                        if attribute_type == "radio":
                            while True:
                                value = click.prompt(style(
                                    "{}:\nChoices:{}".format(
                                        message, attribute["options"]),
                                    fg="yellow",
                                ),
                                                     type=click.Choice(
                                                         attribute["options"]),
                                                     default="")
                                if not attribute_required or value != "":
                                    break
                                echo("Error: {} is a required field".format(
                                    attribute["name"]))
                        if attribute_type == "checkbox":
                            option_chosen = True
                            while option_chosen:
                                value = []
                                choices = click.prompt(style(
                                    "{}:\nChoices(separated by comma):{}".
                                    format(message, attribute["options"]),
                                    fg="yellow",
                                ),
                                                       type=str,
                                                       show_default=False,
                                                       default="")
                                if choices != "":
                                    choices = [
                                        choice.strip(" ")
                                        for choice in choices.split(",")
                                    ]
                                else:
                                    choices = []
                                    option_chosen = False
                                if attribute_required and len(choices) == 0:
                                    echo(
                                        "Error: {} is a required field. Please select atleast one option"
                                        .format(attribute["name"]))
                                    option_chosen = True
                                for choice in choices:
                                    if choice in attribute["options"]:
                                        value.append(choice)
                                        option_chosen = False
                                    else:
                                        echo(
                                            "Error: Choose correct value(s) from the given options only"
                                        )
                                        option_chosen = True
                                        break
                        submission_attribute_metadata.append(
                            {attribute_name: value})
            if large:
                upload_file_using_presigned_url(ctx.phase_id, file,
                                                "submission",
                                                submission_metadata)
            else:
                make_submission(
                    ctx.challenge_id,
                    ctx.phase_id,
                    file,
                    submission_metadata,
                    submission_attribute_metadata,
                )
Example #4
0
def push(image, phase, url, public, private):
    """
    Push docker image to a particular challenge phase.
    """
    """
    Invoked by `evalai push IMAGE:TAG -p PHASE_ID`.
    """
    if len(image.split(":")) != 2:
        message = "\nError: Please enter the tag name with image.\n\nFor eg: `evalai push ubuntu:latest --phase 123`"
        notify_user(message, color="red")
        sys.exit(1)

    if public and private:
        message = "\nError: Submission can't be public and private.\nPlease select either --public or --private"
        notify_user(message, color="red")
        sys.exit(1)

    submission_metadata = {}
    if public:
        submission_metadata["is_public"] = json.dumps(True)
    elif private:
        submission_metadata["is_public"] = json.dumps(False)

    tag = str(uuid.uuid4())
    docker_client = docker.from_env()
    try:
        docker_image = docker_client.images.get(image)
    except docker.errors.ImageNotFound:
        message = "\nError: Image not found. Please enter the correct image name and tag."
        notify_user(message, color="red")
        sys.exit(1)

    request_path = URLS.phase_details_using_slug.value
    request_path = request_path.format(phase)
    response = make_request(request_path, "GET")
    challenge_pk = response.get("challenge")
    phase_pk = response.get("id")

    request_path = URLS.challenge_details.value
    request_path = request_path.format(challenge_pk)
    response = make_request(request_path, "GET")
    max_docker_image_size = response.get("max_docker_image_size")

    docker_image_size = docker_image.__dict__.get("attrs").get("VirtualSize")
    if docker_image_size > max_docker_image_size:
        max_docker_image_size = convert_bytes_to(max_docker_image_size, "gb")
        message = "\nError: Image is too large. The maximum image size allowed is {} GB".format(
            max_docker_image_size)
        notify_user(message, color="red")
        sys.exit(1)

    request_path = URLS.get_aws_credentials.value
    request_path = request_path.format(phase_pk)

    response = make_request(request_path, "GET")
    federated_user = response["success"]["federated_user"]
    repository_uri = response["success"]["docker_repository_uri"]

    # Production Environment
    if ENVIRONMENT == "PRODUCTION":
        AWS_ACCOUNT_ID = federated_user["FederatedUser"][
            "FederatedUserId"].split(":")[0]
        AWS_SERVER_PUBLIC_KEY = federated_user["Credentials"]["AccessKeyId"]
        AWS_SERVER_SECRET_KEY = federated_user["Credentials"][
            "SecretAccessKey"]
        SESSION_TOKEN = federated_user["Credentials"]["SessionToken"]

        ecr_client = boto3.client(
            "ecr",
            region_name="us-east-1",
            aws_access_key_id=AWS_SERVER_PUBLIC_KEY,
            aws_secret_access_key=AWS_SERVER_SECRET_KEY,
            aws_session_token=SESSION_TOKEN,
        )

        token = ecr_client.get_authorization_token(
            registryIds=[AWS_ACCOUNT_ID])
        ecr_client = boto3.client("ecr", region_name="us-east-1")
        username, password = (base64.b64decode(
            token["authorizationData"][0]
            ["authorizationToken"]).decode().split(":"))
        registry = token["authorizationData"][0]["proxyEndpoint"]
        docker_client.login(username,
                            password,
                            registry=registry,
                            dockercfg_path=os.getcwd())

    # Development and Test Environment
    else:
        repository_uri = "{0}/{1}".format(url, repository_uri.split("/")[1])

    # Tag and push docker image and create a submission if successfully pushed
    docker_client.images.get(image).tag("{}:{}".format(repository_uri, tag))
    for line in docker_client.images.push(repository_uri,
                                          tag,
                                          stream=True,
                                          decode=True):
        if line.get("status") in ["Pushing", "Pushed"
                                  ] and line.get("progress"):
            print("{id}: {status} {progress}".format(**line))
        elif line.get("errorDetail"):
            error = line.get("error")
            notify_user(error, color="red")
        elif line.get("aux"):
            aux = line.get("aux")
            pushed_image_tag = aux["Tag"]
            submitted_image_uri = "{}:{}".format(repository_uri,
                                                 pushed_image_tag)
            BASE_TEMP_DIR = tempfile.mkdtemp()
            data = {"submitted_image_uri": submitted_image_uri}
            submission_file_path = os.path.join(BASE_TEMP_DIR,
                                                "submission.json")
            with open(submission_file_path, "w") as outfile:
                json.dump(data, outfile)
            request_path = URLS.make_submission.value
            request_path = request_path.format(challenge_pk, phase_pk)
            response = make_request(request_path,
                                    "POST",
                                    submission_file_path,
                                    data=submission_metadata)
            shutil.rmtree(BASE_TEMP_DIR)
        else:
            print(" ".join("{}: {}".format(k, v) for k, v in line.items()
                           if k != "progressDetail"))
def push(image, phase):
    """
    Push docker image to a particular challenge phase.
    """
    """
    Invoked by `evalai push IMAGE:TAG -p PHASE_ID`.
    """
    if len(image.split(":")) != 2:
        message = "\nError: Please enter the tag name with image.\n\nFor eg: `evalai push ubuntu:latest --phase 123`"
        notify_user(message, color="red")
        sys.exit(1)

    tag = image[1]
    docker_client = docker.from_env()
    try:
        docker_image = docker_client.images.get(image)
    except docker.errors.ImageNotFound:
        message = (
            "\nError: Image not found. Please enter the correct image name and tag."
        )
        notify_user(message, color="red")
        sys.exit(1)

    request_path = URLS.challenge_phase_details.value
    request_path = request_path.format(phase)
    response = make_request(request_path, "GET")
    challenge_pk = response.get('challenge')

    request_path = URLS.challenge_details.value
    request_path = request_path.format(challenge_pk)
    response = make_request(request_path, "GET")
    max_docker_image_size = response.get('max_docker_image_size')

    docker_image_size = docker_image.__dict__.get('attrs').get('VirtualSize')
    if docker_image_size > max_docker_image_size:
        max_docker_image_size = convert_bytes_to(max_docker_image_size, 'gb')
        message = (
            "\nError: Image is too large. The maximum image size allowed is {} GB".format(max_docker_image_size)
        )
        notify_user(message, color="red")
        sys.exit(1)

    request_path = URLS.get_aws_credentials.value
    request_path = request_path.format(phase)

    response = make_request(request_path, "GET")
    federated_user = response["success"]["federated_user"]
    repository_uri = response["success"]["docker_repository_uri"]

    AWS_ACCOUNT_ID = federated_user["FederatedUser"]["FederatedUserId"].split(":")[0]
    AWS_SERVER_PUBLIC_KEY = federated_user["Credentials"]["AccessKeyId"]
    AWS_SERVER_SECRET_KEY = federated_user["Credentials"]["SecretAccessKey"]
    SESSION_TOKEN = federated_user["Credentials"]["SessionToken"]

    ecr_client = boto3.client(
        "ecr",
        region_name="us-east-1",
        aws_access_key_id=AWS_SERVER_PUBLIC_KEY,
        aws_secret_access_key=AWS_SERVER_SECRET_KEY,
        aws_session_token=SESSION_TOKEN,
    )

    token = ecr_client.get_authorization_token(registryIds=[AWS_ACCOUNT_ID])
    ecr_client = boto3.client("ecr", region_name="us-east-1")
    username, password = (
        base64.b64decode(token["authorizationData"][0]["authorizationToken"])
        .decode()
        .split(":")
    )
    registry = token["authorizationData"][0]["proxyEndpoint"]
    docker_client.login(username, password, registry=registry, dockercfg_path=os.getcwd())

    # Tag and push docker image and create a submission if successfully pushed
    docker_client.images.get(image).tag("{}:{}".format(repository_uri, tag))
    for line in docker_client.images.push(
        repository_uri, tag, stream=True, decode=True
    ):
        if line.get("status") in ["Pushing", "Pushed"] and line.get("progress"):
            print("{id}: {status} {progress}".format(**line))
        elif line.get("errorDetail"):
            error = line.get("error")
            notify_user(error, color="red")
        elif line.get('aux'):
            aux = line.get('aux')
            pushed_image_tag = aux['Tag']
            submitted_image_uri = '{}:{}'.format(repository_uri, pushed_image_tag)
            BASE_TEMP_DIR = tempfile.mkdtemp()
            data = {
                "submitted_image_uri": submitted_image_uri
            }
            submission_file_path = os.path.join(BASE_TEMP_DIR, 'submission.json')
            with open(submission_file_path, 'w') as outfile:
                json.dump(data, outfile)
            request_path = URLS.make_submission.value
            request_path = request_path.format(challenge_pk, phase)
            response = make_request(request_path, "POST", submission_file_path)
            shutil.rmtree(BASE_TEMP_DIR)
        else:
            print(
                " ".join(
                    "{}: {}".format(k, v)
                    for k, v in line.items()
                    if k != "progressDetail"
                )
            )