#!/usr/bin/env python3
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Custom swarming trigger script for ChromeOS device tests.

CrOS device tests are unique in that the device OS they prefer to run on is
continuously changing. The LKGM file, checked into src at
//chromeos/CHROMEOS_LKGM, represents the ChromeOS version Chrome's ToT aims
to be compatible with. Therefore, a CrOS test for Chrome ideally targets a
device running the LKGM.

Since the LKGM file gets updated frequently (~daily), we can't reasonably
hardcode the LKGM in the test specs. So this special trigger script will read
the current LKGM (at the time of trigger) and append that to the task's
dimensions. If such a device isn't available in time, the task will fallback
to one running any OS.
"""

import argparse
import os
import re
import sys

import base_test_triggerer

SRC_DIR = os.path.dirname(
    os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
LKGM_FILE_PATH = os.path.join(SRC_DIR, 'chromeos', 'CHROMEOS_LKGM')
# Should match something that looks like "12345.0.0".
LKGM_RE = re.compile(r'\d+\.\d+\.\d+')
PRIMARY_SLICE_EXPIRATION_S = 300


def read_current_lkgm():
    if not os.path.exists(LKGM_FILE_PATH):
        sys.stderr.write('LKGM file not present at %s\n' % LKGM_FILE_PATH)
        return None

    with open(LKGM_FILE_PATH) as f:
        lkgm = f.read().strip()

    if not LKGM_RE.match(lkgm):
        sys.stderr.write('Unknown format of LKGM: %s\n' % lkgm)
        return None

    # Just the major version should be sufficient.
    return lkgm.split('.')[0]


def parse_args(triggerer):
    # This script will do nothing but inspect and tweak the dimension args to
    # `swarming.py trigger`. So let's pull just those out.
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument(
        '-d',
        '--dimension',
        default=[],
        action='append',
        nargs=2,
        dest='dimensions',
        help=
        'Dimensions to filter on. Duplicated from the `swarming.py trigger` '
        'command. Parsed here to ensure `device_os` is not added.')
    parser.add_argument(
        '--optional-dimension',
        default=[],
        action='append',
        nargs=3,
        dest='optional_dimensions',
        help='Optional dimensions which will result in additional task slices. '
        'Duplicated from the `swarming.py trigger` command.')
    base_test_triggerer.BaseTestTriggerer.setup_parser_contract(parser)
    args, additional_args = parser.parse_known_args()
    additional_args = triggerer.modify_args(additional_args, 0,
                                            args.shard_index, args.shards,
                                            args.dump_json)

    if additional_args[0] != 'trigger':
        parser.error(
            'This script is only supported for `swarming.py trigger`'
            ' invocations.'
        )

    for k, _ in args.dimensions:
        if k == 'device_os':
            parser.error(
                'Must not specify the device_os dimension when using this'
                ' script. (It will be added automatically.)')

    # It might be a valid use-case to include optional-dimensions in the initial
    # invocation. But it'd be difficult to integrate them into what we're doing
    # here. So let's just ensure there aren't any.
    if args.optional_dimensions:
        parser.error(
            'Must not specify optional dimensions when using this script.')

    return args, additional_args


def main():
    triggerer = base_test_triggerer.BaseTestTriggerer()
    args, additional_args = parse_args(triggerer)

    current_lkgm = read_current_lkgm()
    if not current_lkgm:
        return 1

    new_args = additional_args[:1]
    # Insert our modified dimension args in between the 1st and 2nd args of the
    # initial `swarming.py` invocation. This avoids the presence of the special
    # `--` arg from causing swarming.py to ignore them.
    needs_device_status = True
    for k, v in args.dimensions:
        new_args.extend(['--dimension', k, v])
        if k == 'device_status':
            needs_device_status = False

    # Only CrOS device bots with a device_status dimension of "available" should
    # run tests. So target those explicitly if we aren't already.
    if needs_device_status:
        new_args.extend(['--dimension', 'device_status', 'available'])

    new_args.extend([
        '-optional-dimension',
        'device_os=%s:%d' % (current_lkgm, PRIMARY_SLICE_EXPIRATION_S),
    ])
    new_args += additional_args[1:]

    return triggerer.run_swarming_go(new_args, args.dump_json,
                                     args.shard_index or 0, args.shards)


if __name__ == '__main__':
    sys.exit(main())
