diff --git a/e2e/docker/BUILD.bazel b/e2e/docker/BUILD.bazel index 4c49090016f7ed991345903e77320f4743e5fe7f..802fd8e7e36824ca29b6e317dda386d2306ec641 100644 --- a/e2e/docker/BUILD.bazel +++ b/e2e/docker/BUILD.bazel @@ -25,7 +25,6 @@ platform( labgrid_config_toolchain( name = "config", src = "local-ubuntu.16.04-gnu.yaml", - manager = "@rules_labgrid//labgrid/manager:config", state = "accessible", target_compatible_with = [ ":constraint", diff --git a/labgrid/config/BUILD.bazel b/labgrid/config/BUILD.bazel index a131e87a37aaeea36a414c149a834f0fbe5a2304..e618d630b93eedede84c4f48a45cdcba461e9306 100644 --- a/labgrid/config/BUILD.bazel +++ b/labgrid/config/BUILD.bazel @@ -1,21 +1,15 @@ +load(":data.bzl", "data") load(":deps.bzl", "deps") -load(":src.bzl", "src") -load(":state.bzl", "state") +load(":env.bzl", "env") -src( - name = "src", - visibility = ["//visibility:public"], +env( + name = "env", + visibility = ["//:__subpackages__"], ) -alias( - name = "config", - actual = "src", - visibility = ["//visibility:public"], -) - -state( - name = "state", - visibility = ["//visibility:public"], +data( + name = "data", + visibility = ["//:__subpackages__"], ) deps( diff --git a/labgrid/config/EnvironmentInfo.bzl b/labgrid/config/EnvironmentInfo.bzl new file mode 100644 index 0000000000000000000000000000000000000000..f8c10b5022795036fd301d8939a3424cf38a10ea --- /dev/null +++ b/labgrid/config/EnvironmentInfo.bzl @@ -0,0 +1,15 @@ +load("@bazel_skylib//lib:types.bzl", "types") + +visibility("//...") + +def init(environment): + if not types.is_dict(environment): + fail("`EnvironmentInfo.environment` must be a dict: {}".format(environment)) + + return {"environment": environment} + +EnvironmentInfo, _ = provider( + doc = "A map of string keys and values that represent environment variables", + fields = ["environment"], + init = init, +) diff --git a/labgrid/config/state.bzl b/labgrid/config/data.bzl similarity index 62% rename from labgrid/config/state.bzl rename to labgrid/config/data.bzl index 29f75ea653fc4eba241e3bc6d82bbc3d76427d0c..b51aaf69c2e72d2c246e45b913f3f797214b8358 100644 --- a/labgrid/config/state.bzl +++ b/labgrid/config/data.bzl @@ -1,21 +1,20 @@ load("//labgrid/cfg:unstore.bzl", _cfg = "unstore") -load(":providers.bzl", "StateInfo") visibility("//labgrid/config/...") -DOC = "Unpacks the `state` from the `//labgrid/toolchain/config:type` toolchain" +DOC = "Unpacks the `data` from the `//labgrid/toolchain/config:type` toolchain" ATTRS = {} def implementation(ctx): toolchain = ctx.toolchains["//labgrid/toolchain/config:type"] - return StateInfo(value = toolchain.state) + return DefaultInfo(files = toolchain.data) -state = rule( +data = rule( doc = DOC, attrs = ATTRS, implementation = implementation, - provides = [StateInfo], + provides = [DefaultInfo], toolchains = ["//labgrid/toolchain/config:type"], cfg = _cfg, ) diff --git a/labgrid/config/env.bzl b/labgrid/config/env.bzl new file mode 100644 index 0000000000000000000000000000000000000000..4b0e6d19ed81c8bee04d36f644b2ad9ff53bc187 --- /dev/null +++ b/labgrid/config/env.bzl @@ -0,0 +1,21 @@ +load("//labgrid/cfg:unstore.bzl", _cfg = "unstore") +load(":EnvironmentInfo.bzl", "EnvironmentInfo") + +visibility("//labgrid/config/...") + +DOC = "Unpacks the `env` from the `//labgrid/toolchain/config:type` toolchain" + +ATTRS = {} + +def implementation(ctx): + toolchain = ctx.toolchains["//labgrid/toolchain/config:type"] + return EnvironmentInfo(environment = toolchain.env) + +env = rule( + doc = DOC, + attrs = ATTRS, + implementation = implementation, + provides = [EnvironmentInfo], + toolchains = ["//labgrid/toolchain/config:type"], + cfg = _cfg, +) diff --git a/labgrid/config/providers.bzl b/labgrid/config/providers.bzl deleted file mode 100644 index 6b694d3af313855e0469ea8b505c4fd60522b2b3..0000000000000000000000000000000000000000 --- a/labgrid/config/providers.bzl +++ /dev/null @@ -1,6 +0,0 @@ -visibility("//...") - -StateInfo = provider( - doc = "A wrapper around the LabGrid state string value.", - fields = ["value"], -) diff --git a/labgrid/config/rule.bzl b/labgrid/config/rule.bzl index b78a34f5c37bc02c4ad2395448056470c68b61b5..29ab04d652c71294203d77d9ac8e5c8378d858ab 100644 --- a/labgrid/config/rule.bzl +++ b/labgrid/config/rule.bzl @@ -9,7 +9,11 @@ Binds a LabGrid configuration file to the associated data required to setup, loa labgrid_config( name = "config", src = "docker.yaml", - state = "accessible", + env = { + "LG_STATE": "accessible" + "LG_ENV": "$(location :config.yaml)" + }, + data = ["config.yaml"] deps = ["@pip//:docker"], ) @@ -51,14 +55,20 @@ ATTRS = { doc = "The LabGrid configuration YAML.", allow_single_file = [".yml", ".yaml"], ), - "state": attr.string( - doc = "The state to transition the LabGrid strategy to.", - ), "deps": attr.label_list( doc = "LabGrid configuration Python dependencies.", providers = [[DefaultInfo, PyInfo]], cfg = "exec", ), + "env": attr.string_dict( + doc = "The environment variables to set. Subject to `$(location)` substitution.", + ), + "data": attr.label_list( + allow_files = True, + doc = "The data files to use.", + providers = [DefaultInfo], + cfg = "exec", + ), } def _forward(target): @@ -68,11 +78,14 @@ def _flatten(iterable): return [e for x in iterable for e in x] def implementation(ctx): + data = ctx.attr.data + [ctx.attr.src] + env = {k: ctx.expand_location(v, targets = data) for k, v in ctx.attr.env.items()} default = DefaultInfo(files = depset([ctx.file.src])) toolchain = platform_common.ToolchainInfo( src = ctx.file.src, - state = ctx.attr.state, deps = _flatten([_forward(d) for d in ctx.attr.deps]), + env = env, + data = depset(transitive = [d.files for d in data]), ) return [default, toolchain] diff --git a/labgrid/config/src.bzl b/labgrid/config/src.bzl deleted file mode 100644 index 0e0108383b9b9ba91e4bf00d2bace5cb2b66474e..0000000000000000000000000000000000000000 --- a/labgrid/config/src.bzl +++ /dev/null @@ -1,26 +0,0 @@ -load("//labgrid/cfg:unstore.bzl", _cfg = "unstore") -load("@rules_python//python:defs.bzl", "PyInfo") - -visibility("//labgrid/config/...") - -DOC = "Unpacks the `src` from the `//labgrid/toolchain/config:type` toolchain" - -ATTRS = {} - -def implementation(ctx): - toolchain = ctx.toolchains["//labgrid/toolchain/config:type"] - output = ctx.actions.declare_file("{}.yaml".format(ctx.label.name)) - ctx.actions.symlink( - target_file = toolchain.src, - output = output, - is_executable = False, - ) - return DefaultInfo(files = depset([output])) - -src = rule( - doc = DOC, - attrs = ATTRS, - implementation = implementation, - toolchains = ["//labgrid/toolchain/config:type"], - cfg = _cfg, -) diff --git a/labgrid/config/toolchain/macro.bzl b/labgrid/config/toolchain/macro.bzl index 4b6221524967adcf9385195460f120dca303aabb..5eb785bcda5dc96fcd26f49680f567fa80be0d63 100644 --- a/labgrid/config/toolchain/macro.bzl +++ b/labgrid/config/toolchain/macro.bzl @@ -3,12 +3,16 @@ load("@rules_labgrid//labgrid/manager:defs.bzl", "labgrid_manager") visibility("//...") -def labgrid_config_toolchain(*, name, src, state, manager, target_compatible_with, deps = ()): +def labgrid_config_toolchain(*, name, src, state, target_compatible_with, manager = "@rules_labgrid//labgrid/manager:passthrough", deps = ()): + src = native.package_relative_label(src) labgrid_config( name = "{}-config".format(name), - src = native.package_relative_label(src), + src = src, deps = [native.package_relative_label(d) for d in deps], - state = state, + env = { + "LG_ENV": "$(rlocationpath {})".format(src), + "LG_STATE": state, + }, ) labgrid_manager( diff --git a/labgrid/executor/BUILD.bazel b/labgrid/executor/BUILD.bazel index 992d1ac9d92625d251e38103d1d3f5228570cbac..7fbfa4fa2d76d73140a693081cd50fe306c21c03 100644 --- a/labgrid/executor/BUILD.bazel +++ b/labgrid/executor/BUILD.bazel @@ -9,11 +9,13 @@ args( py_binary( name = "executor", srcs = ["executor.py"], + data = ["//labgrid/config:data"], tags = ["manual"], visibility = ["//:__subpackages__"], deps = [ "//bazel/labgrid/executor", "//labgrid/manager", + "@rules_python//python/runfiles", ], ) @@ -34,8 +36,6 @@ py_test( args = [ "--manager", "labgrid.executor.host:manager", - "--state", - "any", "echo", "$${DATA}", ], diff --git a/labgrid/executor/args.bzl b/labgrid/executor/args.bzl index 8cff45354101545142b19c9f22b1f4b05835e12a..730f019b5b6fc68b1a968dfb481880ce02eb5946 100644 --- a/labgrid/executor/args.bzl +++ b/labgrid/executor/args.bzl @@ -1,4 +1,4 @@ -load("//labgrid/config:providers.bzl", "StateInfo") +load("//labgrid/config:EnvironmentInfo.bzl", "EnvironmentInfo") visibility("//labgrid/executor/...") @@ -11,21 +11,20 @@ ATTRS = { default = "//labgrid/manager:src", cfg = "exec", ), - "_state": attr.label( - doc = "The state to transition the LabGrid strategy to", - default = "//labgrid/config:state", + "_env": attr.label( + doc = "The environment variables to set", + default = "//labgrid/config:env", cfg = "exec", ), } def implementation(ctx): output = ctx.actions.declare_file("executor-args.txt") - lines = [ - "--manager", - ctx.file._manager.short_path, - "--state", - ctx.attr._state[StateInfo].value, - ] + + lines = ["--manager", ctx.file._manager.short_path] + for name, value in ctx.attr._env[EnvironmentInfo].environment.items(): + lines.extend(["--env", name, value]) + ctx.actions.write(output, "\n".join(lines)) return DefaultInfo(files = depset([output])) diff --git a/labgrid/executor/executor.py b/labgrid/executor/executor.py index ba2f1c93fcb687261f42718f77d7ad2e6ad95918..b5a0738b70219611165c01eb15b37eca0675dde8 100644 --- a/labgrid/executor/executor.py +++ b/labgrid/executor/executor.py @@ -13,6 +13,7 @@ from shutil import which from subprocess import CalledProcessError, run from sys import argv, stderr +from python.runfiles import Runfiles from bazel.labgrid.executor.manager import Manager @@ -54,8 +55,12 @@ def arguments(prsr: ArgumentParser) -> None: type=load, ) prsr.add_argument( - "--state", - help="The state to transition the LabGrid strategy to.", + "--env", + action="append", + metavar=("NAME", "VALUE"), + nargs=2, + help="An environment variable to set when running the binary. Can be provided multiple times.", + default=[], ) @@ -83,10 +88,8 @@ def main(exe: Path, *args: str) -> int: cmd = (which("sh"), *cmd) with parsed.manager() as data: - env = {k: v for k, v in data.env.items() if k != "RUNFILES_DIR"} - # TODO: Move this to a manager - if parsed.state is not None: - env |= {"LG_STATE": parsed.state} + env = {k: resolve_runfile(v) for k, v in parsed.env} + env |= {k: v for k, v in data.env.items() if k != "RUNFILES_DIR"} try: run(cmd, env=env, check=True) except CalledProcessError as e: @@ -96,6 +99,12 @@ def main(exe: Path, *args: str) -> int: return 0 +def resolve_runfile(value): + r = Runfiles.Create() + location = r.Rlocation(value) + if Path(location).exists(): + return location + return value def entry(): exit(main(Path(argv[0]), *argv[1:])) diff --git a/labgrid/manager/BUILD.bazel b/labgrid/manager/BUILD.bazel index 3be3ebd8754d258bba3798fd24136d79ca9d2aa4..dde0f194c8e7ca7371fc2c6a99b64c28322eac12 100644 --- a/labgrid/manager/BUILD.bazel +++ b/labgrid/manager/BUILD.bazel @@ -2,15 +2,11 @@ load("@rules_python//python:defs.bzl", "py_library") load(":src.bzl", "src") py_library( - name = "config", - srcs = ["config.py"], - data = ["//labgrid/config"], + name = "passthrough", + srcs = ["passthrough.py"], tags = ["manual"], visibility = ["//visibility:public"], - deps = [ - "@rules_labgrid//bazel/labgrid/executor", - "@rules_python//python/runfiles", - ], + deps = ["@rules_labgrid//bazel/labgrid/executor"], ) src( diff --git a/labgrid/manager/config.py b/labgrid/manager/config.py deleted file mode 100644 index a50560ef39989014128d4bc8c595846544ceccd7..0000000000000000000000000000000000000000 --- a/labgrid/manager/config.py +++ /dev/null @@ -1,23 +0,0 @@ -from __future__ import annotations - -from contextlib import contextmanager -from pathlib import Path -from typing import Iterator - -from python.runfiles import Runfiles - -from bazel.labgrid.executor.manager import Data - - -@contextmanager -def manager() -> Iterator[Data]: - """ - A LabGrid context manager that loads the resolved configuration into the `LG_ENV` environment variable. - """ - runfiles = Runfiles.Create() - config = runfiles.Rlocation("rules_labgrid/labgrid/config/src.yaml") - path = Path(config) - if not path.exists(): - raise FileNotFoundError(str(path)) - env = {"LG_ENV": str(path)} - yield Data(env=env) diff --git a/labgrid/manager/passthrough.py b/labgrid/manager/passthrough.py new file mode 100644 index 0000000000000000000000000000000000000000..4f0fe402b935bc13fdd160952a3bcfa83c599bc7 --- /dev/null +++ b/labgrid/manager/passthrough.py @@ -0,0 +1,15 @@ +from __future__ import annotations + +from contextlib import contextmanager +from typing import Iterator + + +from bazel.labgrid.executor.manager import Data + + +@contextmanager +def manager() -> Iterator[Data]: + """ + A passthrough LabGrid context manager + """ + yield Data(env = {})