Skip to content

Commit d2e8cdc

Browse files
committed
start moving toward 0.2
1 parent 3aa615c commit d2e8cdc

File tree

4 files changed

+106
-52
lines changed

4 files changed

+106
-52
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# ⚡ 0.2.0 (unreleased)
2+
3+
* port from `python3.6` runtime to `rust` which runs on the `provided` runtime under the covers
4+
* you can now deploy independent functions with `npx serverless deploy function -f func-name`
5+
* no longer have to be explicit about function binary to include, this plugin generates and configures the artifact (zip) file for you
6+
* no longer have to set default exclusion rules
7+
* can deploy `rust` runtime function side by side with other serverless runtime functions
8+
within the same service
9+
110
# ⚡ 0.1.7
211

312
* bump [lambda-rust](https://hub.docker.com/r/softprops/lambda-rust/) docker version to 0.1.0-rust-1.30.1, to make the new default Rust 1.30.1 (the latest release of Rust at this time)

README.md

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
Install the plugin with npm
99

1010
```bash
11-
$ npm install serverless-rust@0.1.6
11+
$ npm install serverless-rust
1212
```
1313

1414
💡 This serverless plugin assumes you are building Rustlang lambdas using the [lando](https://github.com/softprops/lando) or [crowbar](https://github.com/ilianaw/rust-crowbar) rustlang crates.
@@ -20,27 +20,20 @@ service: demo
2020
provider:
2121
name: aws
2222
# crowbar and lando integrate with aws lambda's python3.6 runtime
23-
runtime: python3.6
23+
runtime: rust
2424
plugins:
2525
# this adds informs servleress to use
2626
# the serverless-rust plugin
2727
- serverless-rust
28-
# the follow is recommended for small deployment sizes
29-
# (faster uploads)
28+
# creates one artifact for each function
3029
package:
3130
individually: true
32-
exclude:
33-
- ./**
3431
functions:
3532
test:
36-
# liblambda.handler is the default function name when
37-
# you follow lando/crowbar conventions
38-
handler: liblambda.handler
39-
# the following limits the function packaging
40-
# to just the resulting binary
41-
package:
42-
include:
43-
- liblambda.so
33+
# handler value syntax is `{cargo-package}.{bin-name}`
34+
# or `{bin-name}` for short when you are building a
35+
# default bin for a given package.
36+
handler: your-crate-name
4437
events:
4538
- http:
4639
path: /test
@@ -56,11 +49,11 @@ a custom section of your serverless.yaml configuration
5649
5750
```yaml
5851
custom:
59-
# this section customizes the default
52+
# this section allows for customization of the default
6053
# serverless-rust plugin settings
6154
rust:
6255
# flags passed to cargo
63-
cargoFlags: '--features lando/python3-sys'
56+
cargoFlags: '--features enable-awesome'
6457
# custom docker tag
6558
dockerTag: 'some-custom-tag'
6659
```
@@ -77,15 +70,11 @@ functions:
7770
test:
7871
rust:
7972
# function specific flags passed to cargo
80-
cargoFlags: '--features ...'
81-
# liblambda.handler is the default function name when
82-
# you follow lando/crowbar conventions
83-
handler: liblambda.handler
84-
# the following limits the function packaging
85-
# to just the resulting binary
86-
package:
87-
include:
88-
- liblambda.so
73+
cargoFlags: '--features enable-awesome'
74+
# handler value syntax is `{cargo-package}.{bin-name}`
75+
# or `{bin-name}` for short when you are building a
76+
# default bin for a given package.
77+
handler: your-crate-name
8978
events:
9079
- http:
9180
path: /test
@@ -95,6 +84,12 @@ functions:
9584
9685
## 🏗️ serverless templates
9786
87+
### 0.2.*
88+
89+
* a minimal echo application - https://github.com/softprops/serverless-aws-rust
90+
91+
### 0.1.*
92+
9893
* lando api gateway application - https://github.com/softprops/serverless-lando
9994
* multi function lando api gateway application - https://github.com/softprops/serverless-multi-lando
10095
* crowbar cloudwatch scheduled lambda application - https://github.com/softprops/serverless-crowbar

index.js

Lines changed: 76 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,34 @@
22

33
// https://serverless.com/blog/writing-serverless-plugins/
44
// https://serverless.com/framework/docs/providers/aws/guide/plugins/
5+
// https://github.com/softprops/lambda-rust/
56

67
const { spawnSync } = require('child_process');
7-
const { removeSync } = require('fs-extra');
8-
const copyFileSync = require('fs-copy-file-sync')
8+
//const { removeSync } = require('fs-extra');
9+
//const copyFileSync = require('fs-copy-file-sync')
910
const path = require('path');
1011

12+
const RUST_RUNTIME = 'rust';
13+
14+
const BASE_RUNTIME = 'provided';
15+
1116
const NO_OUTPUT_CAPTURE = { stdio: ['ignore', process.stdout, process.stderr] };
1217

1318
/** assumes docker is on the host's execution path */
14-
class ServerlessPlugin {
19+
class RustPlugin {
1520
constructor(serverless, options) {
21+
1622
this.serverless = serverless;
1723
this.options = options;
1824
this.servicePath = this.serverless.config.servicePath || '';
1925
this.hooks = {
2026
'before:package:createDeploymentArtifacts': this.build.bind(this),
21-
'after:package:createDeploymentArtifacts': this.clean.bind(this),
27+
'before:deploy:function:packageFunction': this.build.bind(this),
2228
};
2329
this.custom = Object.assign(
2430
{
2531
cargoFlags: "",
26-
dockerTag: "0.1.0-rust-1.30.1"
32+
dockerTag: "0.2.0-rust-1.31.0"
2733
},
2834
this.serverless.service.custom && this.serverless.service.custom.rust || {}
2935
);
@@ -34,12 +40,9 @@ class ServerlessPlugin {
3440
// and this plugin being installed, it will be excluded anyway.
3541
// Therefore, the filtering can be disabled to speed up (~3.2s) the process.
3642
this.serverless.service.package.excludeDevDependencies = false;
37-
38-
// represented as an object for unique keys
39-
this.artifacts = {};
4043
}
4144

42-
runDocker(funcArgs, captureOutput) {
45+
runDocker(funcArgs, cargoPackage) {
4346
const defaultArgs = [
4447
'run',
4548
'--rm',
@@ -49,9 +52,16 @@ class ServerlessPlugin {
4952
`-v`, `${process.env['HOME']}/.cargo/git:/root/.cargo/git`,
5053
];
5154
const customArgs = [];
52-
const cargoFlags = (funcArgs || {}).cargoFlags || this.custom.cargoFlags;
55+
let cargoFlags = (funcArgs || {}).cargoFlags || this.custom.cargoFlags;
56+
if (cargoPackage != undefined) {
57+
if (cargoFlags) {
58+
cargoFlags = `${cargoFlags} -p ${cargoPackage}`
59+
} else {
60+
cargoFlags = ` -p ${cargoPackage}`;
61+
}
62+
}
5363
if (cargoFlags) {
54-
// --features python3-sys, ect
64+
// --features awesome-feature, ect
5565
customArgs.push('-e', `CARGO_FLAGS=${cargoFlags}`);
5666
};
5767
const dockerTag = (funcArgs || {}).dockerTag || this.custom.dockerTag;
@@ -62,32 +72,72 @@ class ServerlessPlugin {
6272
...customArgs,
6373
`softprops/lambda-rust:${dockerTag}`
6474
],
65-
captureOutput ? {} : NO_OUTPUT_CAPTURE
75+
NO_OUTPUT_CAPTURE
6676
);
6777
}
6878

79+
functions() {
80+
if (this.options.function) {
81+
return [this.options.function];
82+
} else {
83+
return this.serverless.service.getAllFunctions();
84+
}
85+
}
86+
6987
build() {
7088
const service = this.serverless.service;
71-
service.getAllFunctions().forEach(funcName => {
89+
if (service.provider.name != 'aws') {
90+
return;
91+
}
92+
let rustFunctionsFound = false
93+
this.functions().forEach(funcName => {
7294
const func = service.getFunction(funcName);
73-
const [crate, fn] = func.handler.split('.');
95+
const runtime = func.runtime || service.provider.runtime;
96+
if (runtime != RUST_RUNTIME) {
97+
// skip functions which don't apply
98+
return;
99+
}
100+
rustFunctionsFound = true;
101+
// reserve `cargoPackage` for future support of cargo workspaces
102+
let [cargoPackage, binary] = func.handler.split('.');
103+
if (binary == undefined) {
104+
binary = cargoPackage;
105+
}
74106
this.serverless.cli.log(`Building native Rust ${func.handler} func...`);
75-
const res = this.runDocker(func.rust);
107+
const res = this.runDocker(func.rust, cargoPackage);
76108
if (res.error || res.status > 0) {
77-
this.serverless.cli.log(`Dockerized Rust build encountered an error.`);
109+
this.serverless.cli.log(`Dockerized Rust build encountered an error: ${res.error} ${res.status}.`);
78110
throw new Error(res.error);
79111
}
80-
const executablePath = path.resolve('target/lambda/release', crate + '.so');
81-
const targetPath = path.resolve(this.servicePath, crate + '.so');
82-
copyFileSync(executablePath, targetPath);
83-
// only the keys matters
84-
this.artifacts[targetPath] = null;
85-
})
86-
}
112+
// If all is well we should now have find a packaged compiled binary under target/lambda/release.
113+
//
114+
// The AWS "provided" lambda runtime requires executables to be named
115+
// "bootstrap" -- https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html
116+
//
117+
// To avoid artifact name conflicts when we potentially have more than one function
118+
// we leverage the ability to declare a package artifact directly
119+
// see https://serverless.com/framework/docs/providers/aws/guide/packaging/
120+
// for more information
121+
const artifactPath = path.join('target/lambda/release', binary + ".zip")
122+
func.package = func.package || {};
123+
func.package.artifact = artifactPath;
87124

88-
clean() {
89-
Object.keys(this.artifacts).forEach(removeSync);
125+
// Ensure the runtime is set to a sane value for other plugins
126+
if (func.runtime == RUST_RUNTIME) {
127+
func.runtime = BASE_RUNTIME
128+
}
129+
})
130+
if (service.provider.runtime === RUST_RUNTIME) {
131+
service.provider.runtime = BASE_RUNTIME;
132+
}
133+
if (!rustFunctionsFound) {
134+
throw new Error(
135+
`Error: no Rust functions found. ` +
136+
`Use 'runtime: ${RUST_RUNTIME}' in global or ` +
137+
`function configuration to use this plugin.`
138+
);
139+
}
90140
}
91141
}
92142

93-
module.exports = ServerlessPlugin;
143+
module.exports = RustPlugin;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "serverless-rust",
3-
"version": "0.1.7",
3+
"version": "0.2.0",
44
"description": "Serverless framework plugin for Rustlang applications",
55
"main": "index.js",
66
"scripts": {

0 commit comments

Comments
 (0)