Skip to content

Commit dd837e0

Browse files
committed
Address PR feedback
1 parent b767311 commit dd837e0

File tree

16 files changed

+220
-61
lines changed

16 files changed

+220
-61
lines changed

aws_lambda_builders/actions.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,10 @@ class CopySourceAction(BaseAction):
9292

9393
PURPOSE = Purpose.COPY_SOURCE
9494

95-
def __init__(self, source_dir, dest_dir, only=None, excludes=None):
95+
def __init__(self, source_dir, dest_dir, excludes=None):
9696
self.source_dir = source_dir
9797
self.dest_dir = dest_dir
98-
self.only = only
9998
self.excludes = excludes or []
10099

101100
def execute(self):
102-
if self.only:
103-
def ignore(source, names):
104-
return [name for name in names if name not in self.only]
105-
else:
106-
ignore = shutil.ignore_patterns(*self.excludes)
107-
copytree(self.source_dir, self.dest_dir, ignore=ignore)
101+
copytree(self.source_dir, self.dest_dir, ignore=shutil.ignore_patterns(*self.excludes))

aws_lambda_builders/workflows/go_modules/DESIGN.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,13 @@ builds a static binary using standard go tools.
1717

1818
```python
1919
def build(self, source_dir_path, artifacts_dir_path, executable_name):
20-
"""Builds a go project into an artifact directory.
20+
"""Builds a go project onto an output path.
2121
2222
:type source_dir_path: str
2323
:param source_dir_path: Directory with the source files.
2424
25-
:type artifacts_dir_path: str
26-
:param artifacts_dir_path: Directory to write dependencies into.
27-
28-
:type executable_name: str
29-
:param executable_name: Name of the executable to create from the build.
25+
:type output_path: str
26+
:param output_path: Filename to write the executable output to.
3027
```
3128
3229
### Implementation

aws_lambda_builders/workflows/go_modules/actions.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,16 @@ class GoModulesBuildAction(BaseAction):
1212
DESCRIPTION = "Building Go package with Go Modules"
1313
PURPOSE = Purpose.RESOLVE_DEPENDENCIES
1414

15-
def __init__(self, source_dir, artifacts_dir, executable_name, builder):
15+
def __init__(self, source_dir, output_path, builder):
1616
self.source_dir = source_dir
17-
self.artifacts_dir = artifacts_dir
18-
self.executable_name = executable_name
17+
self.output_path = output_path
1918
self.builder = builder
2019

2120
def execute(self):
2221
try:
2322
self.builder.build(
2423
self.source_dir,
25-
self.artifacts_dir,
26-
self.executable_name
24+
self.output_path,
2725
)
2826
except BuilderError as ex:
2927
raise ActionFailedError(str(ex))

aws_lambda_builders/workflows/go_modules/builder.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,32 @@ def __init__(self, **kwargs):
1515

1616

1717
class GoModulesBuilder(object):
18-
def __init__(self, osutils):
18+
def __init__(self, osutils, runtime_path):
1919
"""Initialize a GoModulesBuilder.
2020
2121
:type osutils: :class:`lambda_builders.utils.OSUtils`
2222
:param osutils: A class used for all interactions with the
2323
outside OS.
24+
25+
:type runtime_path: str
26+
:param runtime_path: The path to the go runtime.
2427
"""
2528
self.osutils = osutils
29+
self.runtime_path = runtime_path
2630

27-
def build(self, source_dir_path, artifacts_dir_path, executable_name):
28-
"""Builds a go project into an artifact directory.
31+
def build(self, source_dir_path, output_path):
32+
"""Builds a go project onto an output path.
2933
3034
:type source_dir_path: str
3135
:param source_dir_path: Directory with the source files.
3236
33-
:type artifacts_dir_path: str
34-
:param artifacts_dir_path: Directory to write dependencies into.
35-
36-
:type executable_name: str
37-
:param executable_name: Name of the executable to create from the build.
37+
:type output_path: str
38+
:param output_path: Filename to write the executable output to.
3839
"""
3940
env = {}
4041
env.update(self.osutils.environ)
4142
env.update({"GOOS": "linux", "GOARCH": "amd64"})
42-
cmd = ["go", "build", "-o", self.osutils.joinpath(artifacts_dir_path, executable_name), source_dir_path]
43+
cmd = [self.runtime_path, "build", "-o", output_path, source_dir_path]
4344

4445
p = self.osutils.popen(
4546
cmd,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""
2+
Go Path Resolver that looks for the executable by runtime first, before proceeding to 'go' in PATH.
3+
"""
4+
import whichcraft
5+
6+
7+
class GoPathResolver(object):
8+
9+
def __init__(self, runtime, which=None):
10+
self.language = "go"
11+
self.runtime = runtime
12+
self.executables = [self.language]
13+
self.which = which or whichcraft.which
14+
15+
def _which(self):
16+
for executable in self.executables:
17+
path = self.which(executable)
18+
if path:
19+
return path
20+
raise ValueError("Path resolution for runtime: {} of language: "
21+
"{} was not successful".format(self.runtime, self.language))
22+
23+
@property
24+
def exec_path(self):
25+
return self._which()

aws_lambda_builders/workflows/go_modules/utils.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,11 @@ class OSUtils(object):
1313
"""
1414
@property
1515
def environ(self):
16-
return os.environ
16+
return os.environ.copy()
1717

1818
def joinpath(self, *args):
1919
return os.path.join(*args)
2020

21-
def basename(self, *args):
22-
return os.path.basename(*args)
23-
2421
def popen(self, command, stdout=None, stderr=None, env=None, cwd=None):
2522
p = subprocess.Popen(command, stdout=stdout, stderr=stderr, env=env, cwd=cwd)
2623
return p
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
"""
2+
Go Runtime Validation
3+
"""
4+
5+
import logging
6+
import os
7+
import subprocess
8+
9+
from aws_lambda_builders.exceptions import MisMatchRuntimeError
10+
11+
LOG = logging.getLogger(__name__)
12+
13+
14+
class GoRuntimeValidator(object):
15+
SUPPORTED_RUNTIMES = {
16+
"go1.x"
17+
}
18+
19+
def __init__(self, runtime, runtime_path):
20+
self.language = "go"
21+
self.runtime = runtime
22+
self.runtime_path = runtime_path
23+
24+
def has_runtime(self):
25+
"""
26+
Checks if the runtime is supported.
27+
:param string runtime: Runtime to check
28+
:return bool: True, if the runtime is supported.
29+
"""
30+
return self.runtime in self.SUPPORTED_RUNTIMES
31+
32+
def validate_runtime(self):
33+
"""
34+
Checks if the language supplied matches the required lambda runtime
35+
:param string runtime_path: runtime to check eg: /usr/bin/go
36+
:raises MisMatchRuntimeError: Version mismatch of the language vs the required runtime
37+
"""
38+
if not self.has_runtime():
39+
LOG.warning("'%s' runtime is not "
40+
"a supported runtime", self.runtime_path)
41+
return
42+
43+
expected_major_version = self.runtime.replace(self.language, "").split('.')[0]
44+
45+
p = subprocess.Popen([self.runtime_path, "version"],
46+
cwd=os.getcwd(),
47+
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
48+
out, _ = p.communicate()
49+
50+
mismatched = p.returncode != 0 \
51+
or len(out.split()) < 3 \
52+
or out.split()[2].replace(self.language, "").split('.')[0] != expected_major_version
53+
if mismatched:
54+
raise MisMatchRuntimeError(language=self.language,
55+
found_runtime=self.runtime_path,
56+
required_runtime=self.runtime,
57+
runtime_path=self.runtime_path)

aws_lambda_builders/workflows/go_modules/workflow.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
Go Modules Workflow
33
"""
44
from aws_lambda_builders.workflow import BaseWorkflow, Capability
5-
from aws_lambda_builders.actions import CopySourceAction
65

76
from .actions import GoModulesBuildAction
87
from .builder import GoModulesBuilder
8+
from .path_resolver import GoPathResolver
9+
from .validator import GoRuntimeValidator
910
from .utils import OSUtils
1011

1112

@@ -37,9 +38,18 @@ def __init__(self,
3738
if osutils is None:
3839
osutils = OSUtils()
3940

40-
executable_name = osutils.basename(source_dir)
41-
builder = GoModulesBuilder(osutils)
41+
options = kwargs.get("options") or {}
42+
handler = options.get("handler", None)
43+
44+
output_path = osutils.joinpath(artifacts_dir, handler)
45+
46+
builder = GoModulesBuilder(osutils, runtime_path=self.get_executable())
4247
self.actions = [
43-
GoModulesBuildAction(source_dir, artifacts_dir, executable_name, builder),
44-
CopySourceAction(source_dir, artifacts_dir, only=[executable_name]),
48+
GoModulesBuildAction(source_dir, output_path, builder),
4549
]
50+
51+
def get_executable(self):
52+
return GoPathResolver(runtime=self.runtime).exec_path
53+
54+
def get_validator(self):
55+
return GoRuntimeValidator(runtime=self.runtime, runtime_path=self.get_executable())

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/functional/workflows/go_modules/test_go_utils.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@ def test_joinpath_joins_path_components(self):
1919
result = self.osutils.joinpath('a', 'b', 'c')
2020
self.assertEqual(result, os.path.join('a', 'b', 'c'))
2121

22-
def test_basename_returns_path_basename(self):
23-
result = self.osutils.basename(os.path.dirname(__file__))
24-
self.assertEqual(result, 'go_modules')
25-
2622
def test_popen_runs_a_process_and_returns_outcome(self):
2723
cwd_py = os.path.join(os.path.dirname(__file__), '..', '..', 'testdata', 'cwd.py')
2824
p = self.osutils.popen([sys.executable, cwd_py],

0 commit comments

Comments
 (0)