#!/usr/bin/python3

"""
Assign a Pulp content guard to all distributions belonging to a given project.

Copr assigns the content guard from the `pulp_content_guard` configuration
option to distributions at the time they are created. This script is useful for
(re)setting the content guard on distributions of an already existing project,
e.g. after the configuration option is introduced or changed.

Example:

    copr-pulp-set-content-guard @copr/copr \\
        --content-guard /api/pulp/<domain>/api/v3/contentguards/core/composite/<uuid>/

When --content-guard is not specified, the value of the `pulp_content_guard`
option from the backend configuration is used.
"""

import argparse
import sys

from copr_backend.helpers import BackendConfigReader
from copr_backend.pulp import PulpClient


def get_arg_parser():
    """
    CLI argument parser
    """
    parser = argparse.ArgumentParser(
        description="Assign a Pulp content guard to all distributions of a "
                    "given <owner>/<project>")
    parser.add_argument(
        "project",
        help="Project in the <owner>/<project> format")
    parser.add_argument(
        "--content-guard",
        help="The pulp_href of the content guard to assign. When not "
             "specified, the pulp_content_guard backend configuration option "
             "is used.")
    return parser


def main():
    """
    The main function
    """
    parser = get_arg_parser()
    args = parser.parse_args()

    content_guard = args.content_guard
    if not content_guard:
        opts = BackendConfigReader().read()
        content_guard = opts.pulp_content_guard
    if not content_guard:
        print("Error: No content guard specified and pulp_content_guard is "
              "not configured.")
        sys.exit(1)

    client = PulpClient.create_from_config_file()

    # Distributions are named <owner>/<project>/<chroot> (with an optional
    # -devel suffix), so all distributions of a project share this prefix.
    parts = args.project.rstrip("/").split("/")
    if len(parts) != 2 or not all(parts):
        parser.error("project must use the <owner>/<project> format")
    prefix = f"{parts[0]}/{parts[1]}/"

    response = client.list_distributions(prefix)
    response.raise_for_status()
    response_data = response.json()
    if response_data["next"] is not None:
        raise RuntimeError("More than one distribution page exists; "
                           "refusing a partial content-guard update")
    distributions = response_data["results"]

    if not distributions:
        print(f"No distributions found for {args.project}")
        return

    requests = []
    for distribution in distributions:
        print(f"Setting content guard on {distribution['name']}")
        requests.append(client.update_distribution(
            distribution["pulp_href"],
            content_guard=content_guard,
            # Make sure to keep the old values here. Either publication or
            # repository must be set (None values zero out the distribution
            # config; see the callee method).
            publication=distribution["publication"],
            repository=distribution["repository"],
        ))

    client.deliver_and_wait(requests)
    print(f"Done, updated {len(requests)} distribution(s)")


if __name__ == "__main__":
    main()
