summaryrefslogtreecommitdiff
path: root/src/buildstream/sandbox/_config.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildstream/sandbox/_config.py')
-rw-r--r--src/buildstream/sandbox/_config.py131
1 files changed, 101 insertions, 30 deletions
diff --git a/src/buildstream/sandbox/_config.py b/src/buildstream/sandbox/_config.py
index 114274190..6f8323453 100644
--- a/src/buildstream/sandbox/_config.py
+++ b/src/buildstream/sandbox/_config.py
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2018 Codethink Limited
+# Copyright (C) 2020 Codethink Limited
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -16,52 +16,123 @@
#
# Authors:
# Jim MacArthur <jim.macarthur@codethink.co.uk>
+# Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>
+#
+from typing import TYPE_CHECKING, Dict, Optional, Union
from .._platform import Platform
+if TYPE_CHECKING:
+ from ..node import Node, MappingNode
+
# SandboxConfig
#
-# A container for sandbox configuration data. We want the internals
-# of this to be opaque, hence putting it in its own private file.
+# The Sandbox configuration parameters, this object carries configuration
+# required to instantiate the correct type of sandbox, and assert that
+# the local or remote worker sandbox has the capabilities required.
+#
+# Args:
+# build_os: The build OS name
+# build_arch: A canonical machine architecture name, as defined by Platform.canonicalize_arch()
+# build_uid: The UID for the sandbox process
+# build_gid: The GID for the sandbox process
+#
+# If the build_uid or build_gid is unspecified, then the underlying sandbox implementation
+# does not guarantee what UID/GID will be used, but generally UID/GID 0 will be used in a
+# sandbox implementation which supports UID/GID control.
+#
+# If the build_uid or build_gid is specified, then the UID/GID is guaranteed to match
+# the specified UID/GID, if the underlying sandbox implementation does not support UID/GID
+# control, then an error will be raised when attempting to configure the sandbox.
+#
class SandboxConfig:
- def __init__(self, sandbox_config, platform):
- host_arch = platform.get_host_arch()
- host_os = platform.get_host_os()
+ def __init__(
+ self, *, build_os: str, build_arch: str, build_uid: Optional[int] = None, build_gid: Optional[int] = None
+ ):
+ self.build_os = build_os
+ self.build_arch = build_arch
+ self.build_uid = build_uid
+ self.build_gid = build_gid
- sandbox_config.validate_keys(["build-uid", "build-gid", "build-os", "build-arch"])
+ # to_dict():
+ #
+ # Represent the SandboxConfig as a dictionary.
+ #
+ # This dictionary will be stored in the corresponding artifact
+ # whenever an artifact is cached. When loading an element from
+ # an artifact, then this dict will be loaded as a MappingNode
+ # and interpreted by SandboxConfig.new_from_node().
+ #
+ # This function is also used to contribute to the owning element's cache key.
+ #
+ # Returns:
+ # A dictionary representation of this SandboxConfig
+ #
+ def to_dict(self) -> Dict[str, Union[str, int]]:
- build_os = sandbox_config.get_str("build-os", default=None)
- if build_os:
- self.build_os = build_os.lower()
- else:
- self.build_os = host_os
+ # Assign mandatory portions of the sandbox configuration
+ #
+ # /!\ No additional mandatory members can ever be added to
+ # the sandbox configuration, as that would result in
+ # breaking cache key stability.
+ #
+ sandbox_dict: Dict[str, Union[str, int]] = {"build-os": self.build_os, "build-arch": self.build_arch}
- build_arch = sandbox_config.get_str("build-arch", default=None)
- if build_arch:
- self.build_arch = Platform.canonicalize_arch(build_arch)
- else:
- self.build_arch = host_arch
+ # Assign optional portions of the sandbox configuration
+ #
+ # /!\ In order to preserve cache key stability, these attributes
+ # are only ever added to the dictionary if they have been
+ # explicitly set, unset values must not affect the dictionary.
+ #
+ if self.build_uid is not None:
+ sandbox_dict["build-uid"] = self.build_uid
+ if self.build_gid is not None:
+ sandbox_dict["build-gid"] = self.build_gid
- self.build_uid = sandbox_config.get_int("build-uid", None)
- self.build_gid = sandbox_config.get_int("build-gid", None)
+ return sandbox_dict
- # get_unique_key():
+ # new_from_node():
+ #
+ # Instantiate a new SandboxConfig from YAML configuration.
#
- # This returns the SandboxConfig's contribution
- # to an element's cache key.
+ # If the Platform is specified, then we expect to be loading
+ # from project definitions, and some defaults will be derived
+ # from the Platform. Otherwise, we expect to be loading from
+ # a cached artifact, and values are expected to exist on the
+ # given node.
+ #
+ # Args:
+ # config: The YAML configuration node
+ # platform: The host Platform instance, or None
#
# Returns:
- # (dict): A dictionary to add to an element's cache key
+ # A new SandboxConfig instance
#
- def get_unique_key(self):
+ @classmethod
+ def new_from_node(cls, config: "MappingNode[Node]", *, platform: Optional[Platform] = None) -> "SandboxConfig":
+ config.validate_keys(["build-uid", "build-gid", "build-os", "build-arch"])
- unique_key = {"os": self.build_os, "arch": self.build_arch}
+ build_os: str
+ build_arch: str
- if self.build_uid is not None:
- unique_key["build-uid"] = self.build_uid
+ if platform:
+ tmp = config.get_str("build-os", None)
+ if tmp:
+ build_os = tmp.lower()
+ else:
+ build_os = platform.get_host_os()
- if self.build_gid is not None:
- unique_key["build-gid"] = self.build_gid
+ tmp = config.get_str("build-arch", None)
+ if tmp:
+ build_arch = Platform.canonicalize_arch(tmp)
+ else:
+ build_arch = platform.get_host_arch()
+ else:
+ build_os = config.get_str("build-os")
+ build_arch = config.get_str("build-arch")
+
+ build_uid = config.get_int("build-uid", None)
+ build_gid = config.get_int("build-gid", None)
- return unique_key
+ return cls(build_os=build_os, build_arch=build_arch, build_uid=build_uid, build_gid=build_gid)