Skip to content

Commit dedc050

Browse files
committed
update to the cli plugin
1 parent 5681923 commit dedc050

File tree

12 files changed

+197
-173
lines changed

12 files changed

+197
-173
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# DEVELOPER PREVIEW (COMMUNITY DRIVEN)
22

3-
We're excited to share our progress with adding new languages to the CloudFormation CLI! This plugin is an early preview prepared by the community, and not ready for production use.
3+
We're excited to share our progress with adding new languages to the CloudFormation CLI!
4+
> This plugin is an early preview prepared by the community, and not ready for production use.
45
56
## AWS CloudFormation Resource Provider TypeScript Plugin
67

@@ -16,6 +17,7 @@ If you are using this package to build resource providers for CloudFormation, in
1617
**Prerequisites**
1718

1819
- Python version 3.6 or above
20+
- [SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)
1921
- Your choice of TypeScript IDE
2022

2123
**Installation**
@@ -28,7 +30,7 @@ pip3 install git+https://github.com/eduardomourar/cloudformation-cli-typescript-
2830

2931
Refer to the [CloudFormation CLI User Guide](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-types.html) for the [CloudFormation CLI](https://github.com/aws-cloudformation/cloudformation-cli) for usage instructions.
3032

31-
** Howto**
33+
**Howto**
3234

3335
Example run:
3436

package-lock.json

Lines changed: 57 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
"test": "tests"
88
},
99
"files": [
10-
"dist",
11-
"global.d.ts"
10+
"dist"
1211
],
1312
"scripts": {
1413
"build": "npx tsc",
14+
"prepack": "npm run build",
1515
"test": "npx jest",
16-
"test:debug": "npx --node-arg=--inspect jest --runInBand"
16+
"test:debug": "npx --node-arg=--inspect jest --runInBand",
17+
"test:ci": "npx jest --ci --collect-coverage"
1718
},
1819
"engines": {
1920
"node": ">=10.0.0",
@@ -30,16 +31,21 @@
3031
},
3132
"homepage": "https://github.com/eduardomourar/cloudformation-cli-typescript-plugin#readme",
3233
"dependencies": {
33-
"aws-sdk": "^2.635.0",
34+
"autobind-decorator": "^2.4.0",
35+
"reflect-metadata": "^0.1.13",
36+
"tombok": "https://github.com/eduardomourar/tombok/releases/download/v0.0.1/tombok-0.0.1.tar.gz",
3437
"uuid": "^7.0.2"
3538
},
3639
"devDependencies": {
40+
"@types/aws-sdk": "^2.7.0",
3741
"@types/jest": "^25.1.0",
3842
"@types/node": "^12.0.0",
3943
"@types/uuid": "^7.0.0",
4044
"jest": "^25.1.0",
41-
"tombok": "git+https://github.com/eduardomourar/tombok.git#feature/basic-implementation",
42-
"ts-jest": "^25.2.1",
45+
"ts-jest": "^25.3.0",
4346
"typescript": "^3.8.3"
47+
},
48+
"optionalDependencies": {
49+
"aws-sdk": "^2.656.0"
4450
}
4551
}

python/rpdk/typescript/codegen.py

Lines changed: 37 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
from subprocess import PIPE, CalledProcessError, run as subprocess_run # nosec
66
from tempfile import TemporaryFile
77

8-
import docker
9-
from docker.errors import APIError, ContainerError, ImageLoadError
108
from requests.exceptions import ConnectionError as RequestsConnectionError
119
from rpdk.core.data_loaders import resource_stream
1210
from rpdk.core.exceptions import DownstreamError, SysExitRecommendedError
@@ -21,6 +19,7 @@
2119

2220
EXECUTABLE = "cfn"
2321
SUPPORT_LIB_NAME = "cfn-rpdk"
22+
MAIN_HANDLER_FUNCTION = "TypeFunction"
2423

2524

2625
class StandardDistNotFoundError(SysExitRecommendedError):
@@ -35,9 +34,9 @@ class TypescriptLanguagePlugin(LanguagePlugin):
3534
MODULE_NAME = __name__
3635
NAME = "typescript"
3736
RUNTIME = "nodejs12.x"
38-
ENTRY_POINT = "handlers.resource"
39-
TEST_ENTRY_POINT = "handlers.testEntrypoint"
40-
CODE_URI = "build/"
37+
ENTRY_POINT = "dist/handlers.entrypoint"
38+
TEST_ENTRY_POINT = "dist/handlers.testEntrypoint"
39+
CODE_URI = "./"
4140

4241
def __init__(self):
4342
self.env = self._setup_jinja_env(
@@ -50,12 +49,14 @@ def __init__(self):
5049
self.package_name = None
5150
self.package_root = None
5251
self._use_docker = True
52+
self._build_command = None
5353

5454
def _init_from_project(self, project):
5555
self.namespace = tuple(s.lower() for s in project.type_info)
5656
self.package_name = "-".join(self.namespace)
57-
self._use_docker = project.settings.get("use_docker", True)
57+
self._use_docker = project.settings.get("useDocker", True)
5858
self.package_root = project.root / "src"
59+
self._build_command = project.settings.get("buildCommand", None)
5960

6061
def _prompt_for_use_docker(self, project):
6162
self._use_docker = input_with_validation(
@@ -64,7 +65,7 @@ def _prompt_for_use_docker(self, project):
6465
"This is highly recommended unless you are experienced \n"
6566
"with cross-platform Typescript packaging.",
6667
)
67-
project.settings["use_docker"] = self._use_docker
68+
project.settings["useDocker"] = self._use_docker
6869

6970
def init(self, project):
7071
LOG.debug("Init started")
@@ -102,6 +103,7 @@ def _copy_resource(path, resource_name=None):
102103

103104
# project support files
104105
_copy_resource(project.root / ".gitignore", "typescript.gitignore")
106+
_copy_resource(project.root / ".npmrc", ".npmrc")
105107
_copy_resource(project.root / "tsconfig.json", "tsconfig.json")
106108
_render_template(
107109
project.root / "package.json",
@@ -124,16 +126,17 @@ def _copy_resource(path, resource_name=None):
124126
"Runtime": project.runtime,
125127
"CodeUri": self.CODE_URI,
126128
}
129+
handler_function = {
130+
"TestEntrypoint": {
131+
**handler_params,
132+
"Handler": project.test_entrypoint,
133+
},
134+
}
135+
handler_function[MAIN_HANDLER_FUNCTION] = handler_params
127136
_render_template(
128137
project.root / "template.yml",
129138
resource_type=project.type_name,
130-
functions={
131-
"TypeFunction": handler_params,
132-
"TestEntrypoint": {
133-
**handler_params,
134-
"Handler": project.test_entrypoint,
135-
},
136-
},
139+
functions=handler_function,
137140
)
138141

139142
LOG.debug("Init complete")
@@ -183,9 +186,8 @@ def package(self, project, zip_file):
183186

184187
self._remove_build_artifacts(build_path)
185188
self._build(project.root)
186-
shutil.copytree(str(handler_package_path), str(build_path / self.package_name))
187189

188-
inner_zip = self._pre_package(build_path)
190+
inner_zip = self._pre_package(build_path / MAIN_HANDLER_FUNCTION)
189191
zip_file.writestr("ResourceProvider.zip", inner_zip.read())
190192
self._recursive_relative_write(handler_package_path, project.root, zip_file)
191193

@@ -198,74 +200,33 @@ def _remove_build_artifacts(deps_path):
198200
except FileNotFoundError:
199201
LOG.debug("'%s' not found, skipping removal", deps_path, exc_info=True)
200202

203+
@staticmethod
204+
def _make_build_command(base_path, build_command=None):
205+
command = f"sam build --build-dir {base_path}/build"
206+
if build_command:
207+
command = build_command
208+
return command
209+
201210
def _build(self, base_path):
202211
LOG.debug("Dependencies build started from '%s'", base_path)
203-
if self._use_docker:
204-
self._docker_build(base_path)
205-
else:
206-
self._npm_build(base_path)
207-
LOG.debug("Dependencies build finished")
208212

209-
@staticmethod
210-
def _make_npm_command(base_path):
211-
return [
212-
"npm",
213-
"install",
214-
"--no-optional",
215-
str(base_path),
216-
]
217-
218-
@classmethod
219-
def _docker_build(cls, external_path):
220-
221-
internal_path = PurePosixPath("/project")
222-
command = " ".join(cls._make_npm_command(internal_path))
223-
LOG.debug("command is '%s'", command)
213+
# TODO: We should use the build logic from SAM CLI library, instead:
214+
# https://github.com/awslabs/aws-sam-cli/blob/master/samcli/lib/build/app_builder.py
215+
command = self._make_build_command(base_path, self._build_command)
216+
if self._use_docker:
217+
command = command + " --use-container"
218+
command = command + " " + MAIN_HANDLER_FUNCTION
224219

225-
volumes = {str(external_path): {"bind": str(internal_path), "mode": "rw"}}
226-
image = f"lambci/lambda:build-{cls.RUNTIME}"
227-
LOG.warning(
228-
"Starting Docker build. This may take several minutes if the "
229-
"image '%s' needs to be pulled first.",
230-
image,
231-
)
232-
docker_client = docker.from_env()
233-
try:
234-
logs = docker_client.containers.run(
235-
image=image,
236-
command=command,
237-
auto_remove=True,
238-
volumes=volumes,
239-
stream=True,
240-
)
241-
except RequestsConnectionError as e:
242-
# it seems quite hard to reliably extract the cause from
243-
# ConnectionError. we replace it with a friendlier error message
244-
# and preserve the cause for debug traceback
245-
cause = RequestsConnectionError(
246-
"Could not connect to docker - is it running?"
247-
)
248-
cause.__cause__ = e
249-
raise DownstreamError("Error running docker build") from cause
250-
except (ContainerError, ImageLoadError, APIError) as e:
251-
raise DownstreamError("Error running docker build") from e
252-
LOG.debug("Build running. Output:")
253-
for line in logs:
254-
LOG.debug(line.rstrip(b"\n").decode("utf-8"))
255-
256-
@classmethod
257-
def _npm_build(cls, base_path):
258-
259-
command = cls._make_npm_command(base_path)
260220
LOG.debug("command is '%s'", command)
261221

262-
LOG.warning("Starting npm build.")
222+
LOG.warning("Starting build.")
263223
try:
264224
completed_proc = subprocess_run( # nosec
265-
command, stdout=PIPE, stderr=PIPE, cwd=base_path, check=True
225+
["/bin/bash", "-c", command], stdout=PIPE, stderr=PIPE, cwd=base_path, check=True
266226
)
267227
except (FileNotFoundError, CalledProcessError) as e:
268-
raise DownstreamError("npm build failed") from e
228+
raise DownstreamError("local build failed") from e
269229

270-
LOG.debug("--- npm stdout:\n%s", completed_proc.stdout)
271-
LOG.debug("--- npm stderr:\n%s", completed_proc.stderr)
230+
LOG.debug("--- build stdout:\n%s", completed_proc.stdout)
231+
LOG.debug("--- build stderr:\n%s", completed_proc.stderr)
232+
LOG.debug("Dependencies build finished")

python/rpdk/typescript/data/.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
optional = false

python/rpdk/typescript/data/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"moduleResolution": "node",
99
"allowJs": true,
1010
"experimentalDecorators": true,
11-
"outDir": "build"
11+
"outDir": "dist"
1212
},
1313
"include": ["src/**/*.ts"],
1414
"exclude": ["node_modules"]

0 commit comments

Comments
 (0)