Skip to content

Commit

Permalink
Handle CannotResolveError (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cariad Eccleston authored Dec 8, 2020
1 parent 21b9923 commit 39875d0
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 17 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# wev: run shell commands with environment variables

**This is prerelease software. Don't use it. :)**

`wev` is a command line tool for resolving environment variables then running shell commands.

For example:
Expand Down
8 changes: 8 additions & 0 deletions example.wev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MY_NAME:
plugin:
id: wev-echo
value: Bobby Pringles

[AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN]:
plugin:
id: wev-awsmfa
1 change: 1 addition & 0 deletions wev/mock_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class MockPlugin(PluginBase):
`return_expires_at` will cause resolution to return an expiry date 60
seconds in the future.
"""

def __init__(
self,
values: dict,
Expand Down
15 changes: 9 additions & 6 deletions wev/resolution_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,13 @@ def read_all(self) -> Dict[str, Dict[Tuple[str, ...], Dict[str, Any]]]:
Raises `CacheReadError` if the cache cannot be read.
"""
everything: Dict[str, Dict[Tuple[str, ...], Dict[str, Any]]] = {}
self.logger.debug("Reading cache: %s", self.path)
self.logger.debug("Reading entire cache: %s", self.path)
try:
with open(self.path, "r") as stream:
if content := stream.read().strip():
everything = YAML(typ="safe").load(content)
self.logger.debug("Read cache: %s", everything)
# Don't log the cache; it contains confidential information.
self.logger.debug("Successfully read the entire cache.")
else:
self.logger.debug("Cache is empty: %s", self.path)
except FileNotFoundError:
Expand Down Expand Up @@ -100,10 +101,11 @@ def save(self) -> None:
self.logger.debug("Writing cache: %s", self.path)
everything = self.read_all()
everything[self.context] = self.resolutions
self.logger.debug("Saving entire cache: %s", everything)
# Don't log the cache; it contains confidential information.
self.logger.debug("Saving the entire cache: %s", self.path)
with open(self.path, "w") as stream:
yaml = YAML(typ="safe")
yaml.dump(everything, stream)
YAML(typ="safe").dump(everything, stream)
self.logger.debug("Successfully saved the entire cache.")

def update(self, names: Tuple, resolution: Resolution) -> None:
"""
Expand All @@ -113,5 +115,6 @@ def update(self, names: Tuple, resolution: Resolution) -> None:
var_name: Name of the environment variable.
resolution: Resolution.
"""
self.logger.debug("Updating %s in cache: %s", names, resolution.store)
# Don't log the store; it's confidential.
self.logger.debug("Updating %s in cache.", names)
self.resolutions[names] = resolution.store
17 changes: 13 additions & 4 deletions wev/sdk/resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@
class Resolution:
def __init__(self, store: Dict[str, Any]) -> None:
self.logger = get_logger()
self.logger.debug("Resolution: store=%s", store)

# Don't log the store; it probably contains confidential information.
self.logger.debug("Initialising new Resolution.")

if not isinstance(store, dict):
raise ValueError('"store" is not a dictionary: %s', type(store))
raise ValueError(
'Resolution "store" is not a dictionary: %s',
type(store),
)
self.store = store

def __eq__(self, other: Any) -> bool:
Expand Down Expand Up @@ -48,7 +54,9 @@ def make(
store.update({"values": value})
if expires_at:
store.update({"expires_at": expires_at.isoformat()})
get_logger().debug('"Resolution.make" created store: %s', store)

# Don't log the store; it contains confidential information.
get_logger().debug('"Resolution.make" created a new store.')
return Resolution(store=store)

@property
Expand Down Expand Up @@ -98,7 +106,8 @@ def time_until_expiry(self) -> str:

@property
def values(self) -> Tuple[str, ...]:
self.logger.debug("Reading the resolved value: %s", self.store)
# Don't log the store; it's confidential.
self.logger.debug("Reading the resolved value.")
values = self.store.get("values", [])
if isinstance(values, tuple):
return values
Expand Down
6 changes: 3 additions & 3 deletions wev/state/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ def get_variables(self) -> Iterator[Variable]:
store = self.config[key]

if cached_resolution := self.resolution_cache.get(names):
self.logger.debug(
"Adding cached resolution: %s", cached_resolution.store
)
# Don't log the resolution; the values are probably
# confidential.
self.logger.debug("Adding cached resolution.")
store.update({"resolution": cached_resolution.store})

yield Variable(names=names, store=store)
Expand Down
7 changes: 5 additions & 2 deletions wev/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ class Variable:

def __init__(self, names: Tuple[str, ...], store: Dict[str, Any]) -> None:
self.logger = get_logger()
self.logger.debug('Variable: name="%s" values="%s"', names, store)

# Don't log the values; they're probably confidential.
self.logger.debug('Variable: name="%s"', names)

if "resolution" in store and not isinstance(store["resolution"], dict):
raise ValueError(
'"resolution" is not a dictionary: %s', type(store["resolution"])
'"resolution" is not a dictionary: %s',
type(store["resolution"]),
)

self.names = names
Expand Down

0 comments on commit 39875d0

Please sign in to comment.