Skip to content

Commit 3165360

Browse files
Asset results from command & run invoke (#87)
* First spike on command invoke * Implement returning of assets and archives - Differentiate input and output property names. * Add excludes to globbing * Improve globbing to support super-wildcards (**) * Remove local package reference in test * Add assets to local command resource * Add command resource asset coverage to golang test - Add assertions on node simple-run test. * Add comment to help people who shouldn't use run * Add more documentation for globbing and path handling * Rename lambda invoke test * Add lambda TS build example Add required lambda fields Remove lambda extra validation
1 parent a63be40 commit 3165360

File tree

40 files changed

+3489
-24
lines changed

40 files changed

+3489
-24
lines changed

README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,60 @@ const cleanupKubernetesNamespaces = new local.Command("cleanupKubernetesNamespac
276276
});
277277
```
278278

279+
### Working with Assets and Paths
280+
281+
When a local command creates assets as part of its execution, these can be captured by specifying `assetPaths` or `archivePaths`.
282+
283+
```typescript
284+
const lambdaBuild = local.runOutput({
285+
dir: "../my-function",
286+
command: `yarn && yarn build`,
287+
archivePaths: ["dist/**"],
288+
});
289+
290+
new aws.lambda.Function("my-function", {
291+
code: lambdaBuild.archive,
292+
// ...
293+
});
294+
```
295+
296+
When using the `assetPaths` and `archivePaths`, they take a list of 'globs'.
297+
- We only include files not directories for assets and archives.
298+
- Path separators are `/` on all platforms - including Windows.
299+
- Patterns starting with `!` are 'exclude' rules.
300+
- Rules are evaluated in order, so exclude rules should be after inclusion rules.
301+
- `*` matches anything except `/`
302+
- `**` matches anything, _including_ `/`
303+
- All returned paths are relative to the working directory (without leading `./`) e.g. `file.text` or `subfolder/file.txt`.
304+
- For full details of the globbing syntax, see [github.com/gobwas/glob](https://github.com/gobwas/glob)
305+
306+
#### Asset Paths Example
307+
308+
Given the rules:
309+
```yaml
310+
- "assets/**"
311+
- "src/**.js"
312+
- "!**secret.*"
313+
```
314+
315+
When evaluating against this folder:
316+
317+
```yaml
318+
- assets/
319+
- logos/
320+
- logo.svg
321+
- src/
322+
- index.js
323+
- secret.js
324+
```
325+
326+
The following paths will be returned:
327+
328+
```yaml
329+
- assets/logos/logo.svg
330+
- src/index.js
331+
```
332+
279333
## Building
280334
281335
### Dependencies

examples/examples_go_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ func TestStdinGo(t *testing.T) {
3333
out, ok := stack.Outputs["output"].(string)
3434
assert.True(t, ok)
3535
assert.Equal(t, "the quick brown fox", out)
36+
assets, ok := stack.Outputs["assets"].(map[string]interface{})
37+
assert.True(t, ok)
38+
assert.Len(t, assets, 1)
3639
},
3740
})
3841
integration.ProgramTest(t, &test)

examples/examples_nodejs_test.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ func TestRandom(t *testing.T) {
3131
integration.ProgramTest(t, &test)
3232
}
3333

34+
func TestLambdaTs(t *testing.T) {
35+
test := getJSBaseOptions(t).
36+
With(integration.ProgramTestOptions{
37+
Dir: filepath.Join(getCwd(t), "lambda-ts"),
38+
})
39+
integration.ProgramTest(t, &test)
40+
}
41+
3442
func TestStdin(t *testing.T) {
3543
test := getJSBaseOptions(t).
3644
With(integration.ProgramTestOptions{
@@ -102,8 +110,8 @@ func TestSimpleWithUpdate(t *testing.T) {
102110
ExtraRuntimeValidation: func(t *testing.T, stack integration.RuntimeValidationStackInfo) {},
103111
EditDirs: []integration.EditDir{
104112
{
105-
Dir: filepath.Join("simple-with-update", "update-change"),
106-
Additive: true,
113+
Dir: filepath.Join("simple-with-update", "update-change"),
114+
Additive: true,
107115
},
108116
},
109117
})
@@ -151,10 +159,10 @@ func TestEc2RemoteTs(t *testing.T) {
151159
integration.ProgramTest(t, &test)
152160
}
153161

154-
func TestLambda(t *testing.T) {
162+
func TestLambdaInvoke(t *testing.T) {
155163
test := getJSBaseOptions(t).
156164
With(integration.ProgramTestOptions{
157-
Dir: filepath.Join(getCwd(t), "lambda"),
165+
Dir: filepath.Join(getCwd(t), "lambda-invoke"),
158166
ExtraRuntimeValidation: func(t *testing.T, stack integration.RuntimeValidationStackInfo) {
159167
out, ok := stack.Outputs["output"].(string)
160168
assert.True(t, ok)
@@ -164,6 +172,19 @@ func TestLambda(t *testing.T) {
164172
integration.ProgramTest(t, &test)
165173
}
166174

175+
func TestSimpleRun(t *testing.T) {
176+
test := getJSBaseOptions(t).
177+
With(integration.ProgramTestOptions{
178+
Dir: filepath.Join(getCwd(t), "simple-run"),
179+
ExtraRuntimeValidation: func(t *testing.T, stack integration.RuntimeValidationStackInfo) {
180+
assets, ok := stack.Outputs["plainAssets"].(map[string]interface{})
181+
assert.True(t, ok)
182+
assert.Len(t, assets, 1)
183+
},
184+
})
185+
integration.ProgramTest(t, &test)
186+
}
187+
167188
func getJSBaseOptions(t *testing.T) integration.ProgramTestOptions {
168189
base := getBaseOptions(t)
169190
baseJS := base.With(integration.ProgramTestOptions{
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

examples/lambda-ts/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.js
2+
*.js.map
3+
!yarn.lock

examples/lambda-ts/Pulumi.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
name: command-lambda-ts
2+
runtime: nodejs
3+
description: Examples of build Lambdas from Typescript
4+
template:
5+
config:
6+
aws:region:
7+
description: The AWS region to deploy into
8+
default: us-east-2

examples/lambda-ts/README.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
[![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new?template=https://github.com/pulumi/examples/blob/master/aws-ts-lambda-efs/README.md)
2+
3+
# Using Amazon EFS with AWS Lambda
4+
5+
This example shows how to use Amazon EFS with AWS Lambda in Pulumi. See the [Using AWS Lambda with Amazon Elastic File System (EFS)](https://www.pulumi.com/blog/aws-lambda-efs) blog post for a detailed walkthrough of this example.
6+
7+
![Architecture Diagram](./lambdaefs.png)
8+
9+
## Prerequisites
10+
11+
- [Node.js](https://nodejs.org/en/download/)
12+
- [Download and install the Pulumi CLI](https://www.pulumi.com/docs/get-started/install/)
13+
- [Connect Pulumi with your AWS account](https://www.pulumi.com/docs/intro/cloud-providers/aws/setup/) (if your AWS CLI is configured, no further changes are required)
14+
15+
## Running the Example
16+
17+
After cloning this repo, `cd` into it and run these commands:
18+
19+
1. Create a new stack, which is an isolated deployment target for this example:
20+
21+
```bash
22+
$ pulumi stack init dev
23+
```
24+
25+
2. Set your desired AWS region:
26+
27+
```bash
28+
$ pulumi config set aws:region us-east-1 # any valid AWS region will work
29+
```
30+
31+
3. Deploy everything with a single `pulumi up` command. This will show you a preview of changes first, which
32+
includes all of the required AWS resources (clusters, services, and the like). Don't worry if it's more than
33+
you expected -- this is one of the benefits of Pulumi, it configures everything so that so you don't need to!
34+
35+
```bash
36+
$ pulumi up
37+
```
38+
39+
After being prompted and selecting "yes", your deployment will begin. It'll complete in a few minutes:
40+
41+
```
42+
Updating (demo):
43+
Type Name Status
44+
+ pulumi:pulumi:Stack aws-ts-lambda-efs-demo created
45+
+ ├─ awsx:x:ec2:Vpc vpc created
46+
+ │ ├─ aws:ec2:Vpc vpc created
47+
+ │ ├─ awsx:x:ec2:Subnet vpc-public-0 created
48+
+ │ │ ├─ aws:ec2:Subnet vpc-public-0 created
49+
+ │ │ ├─ aws:ec2:RouteTable vpc-public-0 created
50+
+ │ │ ├─ aws:ec2:Route vpc-public-0-ig created
51+
+ │ │ └─ aws:ec2:RouteTableAssociation vpc-public-0 created
52+
+ │ ├─ awsx:x:ec2:Subnet vpc-public-1 created
53+
+ │ │ ├─ aws:ec2:RouteTable vpc-public-1 created
54+
+ │ │ ├─ aws:ec2:Subnet vpc-public-1 created
55+
+ │ │ ├─ aws:ec2:RouteTableAssociation vpc-public-1 created
56+
+ │ │ └─ aws:ec2:Route vpc-public-1-ig created
57+
+ │ ├─ awsx:x:ec2:NatGateway vpc-1 created
58+
+ │ │ ├─ aws:ec2:Eip vpc-1 created
59+
+ │ │ └─ aws:ec2:NatGateway vpc-1 created
60+
+ │ ├─ awsx:x:ec2:Subnet vpc-private-0 created
61+
+ │ │ ├─ aws:ec2:RouteTable vpc-private-0 created
62+
+ │ │ ├─ aws:ec2:Subnet vpc-private-0 created
63+
+ │ │ ├─ aws:ec2:RouteTableAssociation vpc-private-0 created
64+
+ │ │ └─ aws:ec2:Route vpc-private-0-nat-0 created
65+
+ │ ├─ awsx:x:ec2:InternetGateway vpc created
66+
+ │ │ └─ aws:ec2:InternetGateway vpc created
67+
+ │ ├─ awsx:x:ec2:Subnet vpc-private-1 created
68+
+ │ │ ├─ aws:ec2:RouteTable vpc-private-1 created
69+
+ │ │ ├─ aws:ec2:Subnet vpc-private-1 created
70+
+ │ │ ├─ aws:ec2:RouteTableAssociation vpc-private-1 created
71+
+ │ │ └─ aws:ec2:Route vpc-private-1-nat-1 created
72+
+ │ └─ awsx:x:ec2:NatGateway vpc-0 created
73+
+ │ ├─ aws:ec2:Eip vpc-0 created
74+
+ │ └─ aws:ec2:NatGateway vpc-0 created
75+
+ ├─ aws:apigateway:x:API api created
76+
+ │ ├─ aws:apigateway:RestApi api created
77+
+ │ ├─ aws:apigateway:Deployment api created
78+
+ │ ├─ aws:lambda:Permission api-2c087c3e created
79+
+ │ ├─ aws:lambda:Permission api-c171fd88 created
80+
+ │ ├─ aws:lambda:Permission api-7857d17d created
81+
+ │ └─ aws:apigateway:Stage api created
82+
+ ├─ awsx:x:ecs:FargateService nginx created
83+
+ │ └─ aws:ecs:Service nginx created
84+
+ ├─ awsx:x:ecs:FargateTaskDefinition nginx created
85+
+ │ ├─ aws:iam:Role nginx-execution created
86+
+ │ ├─ aws:cloudwatch:LogGroup nginx created
87+
+ │ ├─ aws:iam:Role nginx-task created
88+
+ │ ├─ aws:iam:RolePolicyAttachment nginx-execution-9a42f520 created
89+
+ │ ├─ aws:iam:RolePolicyAttachment nginx-task-32be53a2 created
90+
+ │ ├─ aws:iam:RolePolicyAttachment nginx-task-fd1a00e5 created
91+
+ │ └─ aws:ecs:TaskDefinition nginx created
92+
+ ├─ awsx:x:ec2:SecurityGroup nginx-0 created
93+
+ ├─ awsx:x:ecs:Cluster cluster created
94+
+ │ ├─ aws:ecs:Cluster cluster created
95+
+ │ └─ awsx:x:ec2:SecurityGroup cluster created
96+
+ │ ├─ awsx:x:ec2:IngressSecurityGroupRule cluster-containers created
97+
+ │ │ └─ aws:ec2:SecurityGroupRule cluster-containers created
98+
+ │ ├─ awsx:x:ec2:EgressSecurityGroupRule cluster-egress created
99+
+ │ │ └─ aws:ec2:SecurityGroupRule cluster-egress created
100+
+ │ ├─ awsx:x:ec2:IngressSecurityGroupRule cluster-ssh created
101+
+ │ │ └─ aws:ec2:SecurityGroupRule cluster-ssh created
102+
+ │ └─ aws:ec2:SecurityGroup cluster created
103+
+ ├─ aws:iam:Role getHandler created
104+
+ ├─ aws:iam:Role execHandler created
105+
+ ├─ aws:efs:FileSystem filesystem created
106+
+ ├─ aws:iam:Role uploadHandler created
107+
+ ├─ aws:iam:RolePolicyAttachment execHandler-32be53a2 created
108+
+ ├─ aws:iam:RolePolicyAttachment execHandler-23f1a522 created
109+
+ ├─ aws:iam:RolePolicyAttachment getHandler-32be53a2 created
110+
+ ├─ aws:iam:RolePolicyAttachment getHandler-23f1a522 created
111+
+ ├─ aws:iam:RolePolicyAttachment uploadHandler-32be53a2 created
112+
+ ├─ aws:iam:RolePolicyAttachment uploadHandler-23f1a522 created
113+
+ ├─ aws:efs:MountTarget fs-mount-1 created
114+
+ ├─ aws:efs:MountTarget fs-mount-0 created
115+
+ ├─ aws:efs:AccessPoint ap created
116+
+ ├─ aws:lambda:Function getHandler created
117+
+ ├─ aws:lambda:Function uploadHandler created
118+
+ └─ aws:lambda:Function execHandler created
119+
120+
Outputs:
121+
url: "https://280f2167f1.execute-api.us-east-1.amazonaws.com/stage/"
122+
123+
Resources:
124+
+ 75 created
125+
126+
Duration: 5m52s
127+
```
128+
129+
4. At this point, your app is running! The URL was published so it's easy to interact with:
130+
131+
```bash
132+
$ curl -X POST -d '<h1>Hello world</h1>' $(pulumi stack output url)files/index.html
133+
$ curl -X GET $(pulumi stack output url)files/index.html
134+
<h1>Hello world</h1>
135+
```
136+
137+
5. Once you are done, you can destroy all of the resources, and the stack:
138+
139+
```bash
140+
$ pulumi destroy
141+
$ pulumi stack rm
142+
```

0 commit comments

Comments
 (0)