blob: 088786425d722b4ea7fc2753e3c91ef526198d16 [file] [log] [blame]
# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import base64
from google.protobuf import text_format as textpb
from recipe_engine import recipe_api
from PB.go.chromium.org.luci.buildbucket.proto import project_config as bb_pb2
from PB.go.chromium.org.luci.cv.api.config.v2 import config as cv_config_pb2
from PB.go.chromium.org.luci.milo.api.config import project as milo_pb2
class LuciConfigApi(recipe_api.RecipeApi):
"""Module for polling and parsing luci config files via the luci-config API."""
def fetch_config(self, config_name, message_type, project=None, local_dir=None):
"""Fetch a config file from the luci-config API and return it as a proto object.
Args:
config_name (str): The name of the config file to fetch, e.g.
"commit-queue.cfg".
message_type (type): The Python type corresponding to the
config's protobuf message type.
project (str): The name of the LUCI project to fetch the config
from; e.g. "fuchsia". Defaults to the project that the
current Buildbucket build is running in.
local_dir (Path): If specified, assumed to point to a local
directory of files generated by lucicfg. The specified config
file will be read from the corresponding local file rather
than fetching it from the LUCI Config service.
"""
if not project:
project = self.m.buildbucket.build.builder.project
assert project, "buildbucket input has no project set"
if local_dir:
text = self.m.file.read_text(
"read %s %s" % (project, config_name), local_dir.join(config_name)
)
else:
with self.m.step.nest("fetch %s %s" % (project, config_name)):
text = self._fetch_config_textproto(project, config_name)
cfg = message_type()
textpb.Parse(text, cfg)
return cfg
def _fetch_config_textproto(self, project, config_name):
url = (
"https://luci-config.appspot.com/_ah/api/config/v1/config_sets/projects/%s/config/%s"
% (project, config_name)
)
token = self.m.service_account.default().get_access_token()
response = self.m.url.get_json(
url,
step_name="get",
headers={"Authorization": "Bearer %s" % token},
default_test_data={"content": ""},
)
return base64.b64decode(response.output["content"])
def buildbucket(self, **kwargs):
return self.fetch_config("cr-buildbucket.cfg", bb_pb2.BuildbucketCfg, **kwargs)
def commit_queue(self, config_name=None, **kwargs):
# Support loading a CQ config file with a non-default name to support
# projects that don't want a dedicated CQ instance but for which we
# still want to know which tryjobs exist.
config_name = config_name or "commit-queue.cfg"
return self.fetch_config(config_name, cv_config_pb2.Config, **kwargs)
def milo(self, **kwargs):
return self.fetch_config("luci-milo.cfg", milo_pb2.Project, **kwargs)
def get_milo_console(self, console_name, **kwargs):
milo_cfg = self.milo(**kwargs)
for console in milo_cfg.consoles:
if console.id == console_name:
return console
return None