-
Notifications
You must be signed in to change notification settings - Fork 139
/
builder.py
175 lines (140 loc) · 6.43 KB
/
builder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
"""
Entrypoint for the AWS Lambda Builder library
"""
import importlib
import logging
import os
from aws_lambda_builders.architecture import X86_64
from aws_lambda_builders.registry import DEFAULT_REGISTRY, get_workflow
from aws_lambda_builders.workflow import Capability
LOG = logging.getLogger(__name__)
_SUPPORTED_WORKFLOWS = ["aws_lambda_builders.workflows"]
class LambdaBuilder(object):
"""
Helps you build AWS Lambda functions. This class is the primary entry point for this library.
"""
def __init__(self, language, dependency_manager, application_framework, supported_workflows=None):
"""
Initialize the builder.
:type supported_workflows: list
:param supported_workflows:
Optional list of workflow modules that should be loaded. By default we load all the workflows bundled
with this library. This property is primarily used for testing. But in future it could be used to
dynamically load user defined workflows.
If set to None, we will load the default workflow modules.
If set to empty list, we will **not** load any modules. Pass an empty list if the workflows
were already loaded by the time this class is instantiated.
:raises lambda_builders.exceptions.WorkflowNotFoundError: If a workflow for given capabilities is not found
"""
# Load defaults if necessary. We check for `None` explicitly because callers could pass an empty list
# if they do not want to load any modules. This supports the case where workflows are already loaded and
# don't need to be loaded again.
self.supported_workflows = _SUPPORTED_WORKFLOWS if supported_workflows is None else supported_workflows
for workflow_module in self.supported_workflows:
LOG.debug("Loading workflow module '%s'", workflow_module)
# If a module is already loaded, this call is pretty much a no-op. So it is okay to keep loading again.
importlib.import_module(workflow_module)
self.capability = Capability(
language=language, dependency_manager=dependency_manager, application_framework=application_framework
)
self.selected_workflow_cls = get_workflow(self.capability)
LOG.debug("Found workflow '%s' to support capabilities '%s'", self.selected_workflow_cls.NAME, self.capability)
def build(
self,
source_dir,
artifacts_dir,
scratch_dir,
manifest_path,
runtime=None,
unpatched_runtime=None,
optimizations=None,
options=None,
executable_search_paths=None,
mode=None,
download_dependencies=True,
dependencies_dir=None,
combine_dependencies=True,
architecture=X86_64,
is_building_layer=False,
experimental_flags=None,
build_in_source=None,
):
# pylint: disable-msg=too-many-locals
"""
Actually build the code by running workflows
:type source_dir: str
:param source_dir:
Path to a folder containing the source code
:type artifacts_dir: str
:param artifacts_dir:
Path to a folder where the built artifacts should be placed
:type scratch_dir: str
:param scratch_dir:
Path to a directory that the workflow can use as scratch space. Workflows are expected to use this directory
to write temporary files instead of ``/tmp`` or other OS-specific temp directories.
:type manifest_path: str
:param manifest_path:
Path to the dependency manifest
:type runtime: str
:param runtime:
Optional, name of the AWS Lambda runtime that you are building for. This is sent to the builder for
informational purposes.
:type optimizations: dict
:param optimizations:
Optional dictionary of optimization flags to pass to the build action. **Not supported**.
:type options: dict
:param options:
Optional dictionary of options ot pass to build action. **Not supported**.
:type executable_search_paths: list
:param executable_search_paths:
Additional list of paths to search for executables required by the workflow.
:type mode: str
:param mode:
Optional, Mode the build should produce
:type download_dependencies: bool
:param download_dependencies:
Optional, Should download dependencies when building
:type dependencies_dir: str
:param dependencies_dir:
Optional, Path to folder the dependencies should be downloaded to
:type combine_dependencies: bool
:param combine_dependencies:
Optional, This flag will only be used if dependency_folder is specified. False will not copy dependencies
from dependency_folder into build folder
:type architecture: str
:param architecture:
Type of architecture x86_64 and arm64 for Lambda Function
:type is_building_layer: bool
:param is_building_layer:
Boolean flag which will be set True if current build operation is being executed for layers
:type experimental_flags: list
:param experimental_flags:
List of strings, which will indicate enabled experimental flags for the current build session
:type build_in_source: Optional[bool]
:param build_in_source:
Optional, will execute the build operation in the source directory if True.
"""
if not os.path.exists(scratch_dir):
os.makedirs(scratch_dir)
workflow = self.selected_workflow_cls(
source_dir,
artifacts_dir,
scratch_dir,
manifest_path,
runtime=runtime,
unpatched_runtime=unpatched_runtime,
optimizations=optimizations,
options=options,
executable_search_paths=executable_search_paths,
mode=mode,
download_dependencies=download_dependencies,
dependencies_dir=dependencies_dir,
combine_dependencies=combine_dependencies,
architecture=architecture,
is_building_layer=is_building_layer,
experimental_flags=experimental_flags,
build_in_source=build_in_source,
)
return workflow.run()
def _clear_workflows(self):
DEFAULT_REGISTRY.clear()