chromium/infra/config/lib/swarming.star

# Copyright 2020 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Library for defining Swarming resources."""

load("//lib/branches.star", "branches")

def root_permissions():
    """Sets up permissions that apply to all Chromium pools.

    Noop on a non-main branch, since Swarming pools are owned by the primary
    Chromium project defined on the main branch.
    """
    if not branches.matches(branches.selector.MAIN):
        return

    # Allow admins to cancel any task, delete bots, etc. in any Chromium pool.
    luci.binding(
        realm = "@root",
        roles = "role/swarming.poolOwner",
        groups = "project-chromium-admins",
    )

    # Allow everyone to see all tasks and bots in Chromium pools.
    luci.binding(
        realm = "@root",
        roles = "role/swarming.poolViewer",
        groups = "all",
    )

def pool_realm(
        *,
        name,
        extends = None,
        user_groups = None,
        user_users = None,
        user_projects = None,
        owner_groups = None):
    """Declares a realm with permissions for a Swarming pool.

    Individual Swarming pools are assigned to this realm in pools.cfg in
    Swarming server-side configs.

    Pools are owned by the main Chromium project and it makes sense to defined
    them only on the main branch. This declaration is noop on a non-main branch.

    Args:
        name: Name of the Swarming pool realm.
        extends: List of names of other realms whose permissions will be copied
            into this realm.
        user_groups: List of groups to give the "swarming.poolUser" role to.
        user_users: List of users to give the "swarming.poolUser" role to.
        user_projects: List of projects to give the "swarming.poolUser" role to.
        owner_groups: List of groups to give the "swarming.poolOwner" role to.
    """
    if not branches.matches(branches.selector.MAIN):
        return
    if not name.startswith("pools/"):
        fail("By convention Swarming pool realm name should start with pools/")

    luci.realm(
        name = name,
        extends = extends,
        bindings = [
            luci.binding(
                roles = "role/swarming.poolUser",
                groups = user_groups,
                users = user_users,
                projects = user_projects,
            ),
            luci.binding(
                roles = "role/swarming.poolOwner",
                groups = owner_groups,
            ),
        ],
    )

def task_accounts(*, realm, groups = None, users = None):
    """Declares what service accounts tasks in a realm can run as.

    Used to declare accounts for isolated tests. There's no need to separately
    declare accounts for Buildbucket builders since luci.builder(...) takes care
    of that itself.
    """
    luci.binding(
        realm = realm,
        roles = "role/swarming.taskServiceAccount",
        groups = groups,
        users = users,
    )

def task_triggerers(*, builder_realm, pool_realm, users = None, groups = None):
    """Declares who can launch arbitrary tasks.

    Used to allow end users to launch LUCI Editor (aka LED) tasks and isolated
    tests from their workstations.

    The given users will be allowed to submit tasks in the `builder_realm` realm
    (e.g. tasks that pretend to be "chromium/try" tasks), running on a Swarming
    pool in some `pool_realm` (e.g. "pools/try" or "pools/tests").

    Pools are owned by the main Chromium project, thus `pool_realm` setting is
    effective only on the main branch where pool realms are defined. It is
    silently skipped on on a non-main branch. Per-milestone projects still have
    builders, so `builder_realm` setting is always effective.
    """

    # Permission to submit tasks to Swarming at all.
    if branches.matches(branches.selector.MAIN):
        luci.binding(
            realm = pool_realm,
            roles = "role/swarming.poolUser",
            users = users,
            groups = groups,
        )

    # Permission to associated tasks with the builder realm.
    luci.binding(
        realm = builder_realm,
        roles = "role/swarming.taskTriggerer",
        users = users,
        groups = groups,
    )

swarming = struct(
    root_permissions = root_permissions,
    pool_realm = pool_realm,
    task_accounts = task_accounts,
    task_triggerers = task_triggerers,
)