Chromium Code Reviews| Index: recipe_modules/context/api.py |
| diff --git a/recipe_modules/context/api.py b/recipe_modules/context/api.py |
| index 1e53ce149f24043233733c80b301a333bd9d28ab..5a77154d1d015e81b3da90afde112784bc761ea0 100644 |
| --- a/recipe_modules/context/api.py |
| +++ b/recipe_modules/context/api.py |
| @@ -28,17 +28,16 @@ with api.context(cwd=api.path['start_dir'].join('subdir')): |
| ``` |
| """ |
| - |
| import collections |
| -import os |
| -import types |
| +import copy |
| from contextlib import contextmanager |
| -from recipe_engine import recipe_api |
| from recipe_engine.config_types import Path |
| from recipe_engine.recipe_api import RecipeApi |
| +from libs import luci_context as luci_ctx |
| + |
| def check_type(name, var, expect): |
| if not isinstance(var, expect): # pragma: no cover |
| @@ -55,13 +54,17 @@ class ContextApi(RecipeApi): |
| self._cwd = [None] |
| self._env_prefixes = [{}] |
| self._env = [{}] |
| + if self._test_data.enabled: |
| + self._luci_context = [self._test_data.get('luci_context', {})] |
| + else: # pragma: no cover |
| + self._luci_context = [luci_ctx.read_full()] |
| self._infra_step = [False] |
| self._name_prefix = [''] |
| # this could be a number, but it makes the logic easier to use a stack. |
| self._nest_level = [0] |
| @contextmanager |
| - def __call__(self, cwd=None, env_prefixes=None, env=None, |
| + def __call__(self, cwd=None, env_prefixes=None, env=None, luci_context=None, |
| increment_nest_level=None, infra_steps=None, name_prefix=None): |
| """Allows adjustment of multiple context values in a single call. |
| @@ -72,6 +75,7 @@ class ContextApi(RecipeApi): |
| * env_prefixes (dict) - Environmental variable prefix augmentations. See |
| below for more info. |
| * env (dict) - Environmental variable overrides. See below for more info. |
| + * luci_context (dict) - LUCI_CONTEXT overrides. |
|
iannucci
2017/08/04 18:55:50
"see below for more info"
|
| * increment_nest_level (True) - increment the nest level by 1 in this |
| context. Typically you won't directly interact with this, but should |
| use api.step.nest instead. |
| @@ -117,6 +121,17 @@ class ContextApi(RecipeApi): |
| defined in "env", it will be installed as the last path component if it is |
| not empty. |
| + LUCI_CONTEXT overrides: |
| + |
| + This is advanced stuff. LUCI_CONTEXT is used to pass ambient information |
| + between layers of LUCI stack. 'luci_context' can be used to replace, add or |
| + pop items in the current LUCI_CONTEXT. Unlike 'env', LUCI_CONTEXT contains |
| + structured values, so values of 'luci_context' dict can be anything (not |
| + only strings), and we are not attempting to merge them in any way, e.g |
| + there's no equivalent of %(PATH)s trick. |
|
iannucci
2017/08/04 18:55:50
we're going to delete the %(PATH) trick anyway, so
|
| + |
| + See https://github.com/luci/client-py/blob/master/LUCI_CONTEXT.md. |
| + |
| **TODO(iannucci): combine nest_level and name_prefix** |
| Look at the examples in "examples/" for examples of context module usage. |
| @@ -182,6 +197,20 @@ class ContextApi(RecipeApi): |
| new[k] = v |
| _push(self._env, new) |
| + if luci_context is not None and len(luci_context) > 0: |
| + check_type('luci_context', luci_context, dict) |
| + new = dict(self._luci_context[-1]) |
| + for k, v in luci_context.iteritems(): |
| + k = str(k) |
| + if v is None: |
| + new.pop(k, None) |
| + elif isinstance(v, dict): |
| + new[k] = copy.deepcopy(v) |
|
iannucci
2017/08/04 18:55:51
can we assert that v is serializable to json? Othe
|
| + else: |
| + raise TypeError( |
| + 'Bad type for LUCI_CONTEXT[%r]: %s', k, type(v).__name__) |
| + _push(self._luci_context, new) |
| + |
| try: |
| yield |
| finally: |
| @@ -228,6 +257,20 @@ class ContextApi(RecipeApi): |
| return dict(self._env_prefixes[-1]) |
| @property |
| + def luci_context(self): |
| + """Returns a dict with current state of LUCI_CONTEXT. |
| + |
| + This is advanced stuff. LUCI_CONTEXT is used to pass ambient information |
| + between layers of LUCI stack. Unlike 'env', it MAY be populated with |
| + information about LUCI execution environment when recipe engine starts. |
| + |
| + Do not dump the entirety of LUCI_CONTEXT into logs, it may contain secrets. |
|
iannucci
2017/08/04 18:55:50
s/may contain/contains
make them scared :)
|
| + |
| + See https://github.com/luci/client-py/blob/master/LUCI_CONTEXT.md. |
| + """ |
| + return dict(self._luci_context[-1]) |
| + |
| + @property |
| def infra_step(self): |
| """Returns the current value of the infra_step setting. |