Skip to content

Commit cfe0d69

Browse files
committed
feat: Path Resolver and Validator
- BaseWorkflow provides super simple resolver and a No-op validator - Each Workflow can bring its own path resolver and validator. - workflow's run method is decorated to check for validaton of the language executable path.
1 parent 2d9af16 commit cfe0d69

File tree

8 files changed

+77
-153
lines changed

8 files changed

+77
-153
lines changed

aws_lambda_builders/builder.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import logging
88

99
from aws_lambda_builders.registry import get_workflow, DEFAULT_REGISTRY
10-
from aws_lambda_builders.validate import RuntimeValidator
1110
from aws_lambda_builders.workflow import Capability
1211

1312
LOG = logging.getLogger(__name__)
@@ -91,8 +90,6 @@ def build(self, source_dir, artifacts_dir, scratch_dir, manifest_path,
9190
:param options:
9291
Optional dictionary of options ot pass to build action. **Not supported**.
9392
"""
94-
if runtime:
95-
self._validate_runtime(runtime)
9693

9794
if not os.path.exists(scratch_dir):
9895
os.makedirs(scratch_dir)
@@ -107,16 +104,5 @@ def build(self, source_dir, artifacts_dir, scratch_dir, manifest_path,
107104

108105
return workflow.run()
109106

110-
def _validate_runtime(self, runtime):
111-
"""
112-
validate runtime and local runtime version to make sure they match
113-
114-
:type runtime: str
115-
:param runtime:
116-
String matching a lambda runtime eg: python3.6
117-
"""
118-
RuntimeValidator.validate_runtime(required_language=self.capability.language,
119-
required_runtime=runtime)
120-
121107
def _clear_workflows(self):
122108
DEFAULT_REGISTRY.clear()

aws_lambda_builders/path_resolver.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""
2+
Basic Path Resolver that just looks for the language in the path.
3+
"""
4+
5+
from whichcraft import which
6+
7+
8+
class PathResolver(object):
9+
10+
def __init__(self, runtime):
11+
self.runtime = runtime
12+
13+
@property
14+
def path(self):
15+
return which(self.runtime)

aws_lambda_builders/validate.py

Lines changed: 0 additions & 74 deletions
This file was deleted.

aws_lambda_builders/validator.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
No-op validator that does not validate the runtime_path for a specified language.
3+
"""
4+
5+
import logging
6+
7+
LOG = logging.getLogger(__name__)
8+
9+
10+
class RuntimeValidator(object):
11+
12+
def __init__(self, runtime_path):
13+
self.runtime_path = runtime_path
14+
15+
def validate_runtime(self):
16+
pass

aws_lambda_builders/workflow.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
"""
22
Implementation of a base workflow
33
"""
4-
4+
import functools
55
import os
66
import logging
77

88
from collections import namedtuple
99
import six
1010

11+
from aws_lambda_builders.path_resolver import PathResolver
12+
from aws_lambda_builders.validator import RuntimeValidator
1113
from aws_lambda_builders.registry import DEFAULT_REGISTRY
1214
from aws_lambda_builders.exceptions import WorkflowFailedError, WorkflowUnknownError
1315
from aws_lambda_builders.actions import ActionFailedError
@@ -22,6 +24,22 @@
2224
Capability = namedtuple('Capability', ["language", "dependency_manager", "application_framework"])
2325

2426

27+
# TODO: Move sanitize out to its own class.
28+
def sanitize(func):
29+
"""
30+
sanitize the executable path of the runtime specified by validating it.
31+
:param func: Workflow's run method is sanitized
32+
"""
33+
34+
@functools.wraps(func)
35+
def wrapper(*args, **kwargs):
36+
# NOTE: we need to access workflow object to get the validator.
37+
validator = args[0].get_validator()
38+
validator.validate_runtime()
39+
func(*args, **kwargs)
40+
return wrapper
41+
42+
2543
class _WorkflowMetaClass(type):
2644
"""
2745
A metaclass that maintains the registry of loaded builders
@@ -138,6 +156,19 @@ def is_supported(self):
138156

139157
return True
140158

159+
def get_executable(self):
160+
"""
161+
Non specialized path resolver that just returns the first executable for the runtime on the path.
162+
"""
163+
return PathResolver(runtime=self.runtime).path
164+
165+
def get_validator(self):
166+
"""
167+
No-op validator that does not validate the runtime_path.
168+
"""
169+
return RuntimeValidator(runtime_path=self.get_executable())
170+
171+
@sanitize
141172
def run(self):
142173
"""
143174
Actually perform the build by executing registered actions.

requirements/base.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
six~=1.11
2+
whichcraft~=0.5.2

tests/unit/test_builder.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,17 +115,16 @@ def test_with_mocks(self, scratch_dir_exists, get_workflow_mock, importlib_mock,
115115

116116
get_workflow_mock.return_value = workflow_cls
117117

118-
with patch.object(LambdaBuilder, "_validate_runtime"):
119-
builder = LambdaBuilder(self.lang, self.lang_framework, self.app_framework, supported_workflows=[])
120-
121-
builder.build("source_dir", "artifacts_dir", "scratch_dir", "manifest_path",
122-
runtime="runtime", optimizations="optimizations", options="options")
123-
124-
workflow_cls.assert_called_with("source_dir", "artifacts_dir", "scratch_dir", "manifest_path",
125-
runtime="runtime", optimizations="optimizations", options="options")
126-
workflow_instance.run.assert_called_once()
127-
os_mock.path.exists.assert_called_once_with("scratch_dir")
128-
if scratch_dir_exists:
129-
os_mock.makedirs.not_called()
130-
else:
131-
os_mock.makedirs.assert_called_once_with("scratch_dir")
118+
builder = LambdaBuilder(self.lang, self.lang_framework, self.app_framework, supported_workflows=[])
119+
120+
builder.build("source_dir", "artifacts_dir", "scratch_dir", "manifest_path",
121+
runtime="runtime", optimizations="optimizations", options="options")
122+
123+
workflow_cls.assert_called_with("source_dir", "artifacts_dir", "scratch_dir", "manifest_path",
124+
runtime="runtime", optimizations="optimizations", options="options")
125+
workflow_instance.run.assert_called_once()
126+
os_mock.path.exists.assert_called_once_with("scratch_dir")
127+
if scratch_dir_exists:
128+
os_mock.makedirs.not_called()
129+
else:
130+
os_mock.makedirs.assert_called_once_with("scratch_dir")

tests/unit/test_runtime.py

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)