forked from softprops/serverless-rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
93 lines (83 loc) · 3.15 KB
/
index.js
File metadata and controls
93 lines (83 loc) · 3.15 KB
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
'use strict';
// https://serverless.com/blog/writing-serverless-plugins/
// https://serverless.com/framework/docs/providers/aws/guide/plugins/
const { spawnSync } = require('child_process');
const { removeSync } = require('fs-extra');
const copyFileSync = require('fs-copy-file-sync')
const path = require('path');
const NO_OUTPUT_CAPTURE = { stdio: ['ignore', process.stdout, process.stderr] };
/** assumes docker is on the host's execution path */
class ServerlessPlugin {
constructor(serverless, options) {
this.serverless = serverless;
this.options = options;
this.servicePath = this.serverless.config.servicePath || '';
this.hooks = {
'before:package:createDeploymentArtifacts': this.build.bind(this),
'after:package:createDeploymentArtifacts': this.clean.bind(this),
};
this.custom = Object.assign(
{
cargoFlags: "",
dockerTag: "0.1.0-rust-1.27.2"
},
this.serverless.service.custom && this.serverless.service.custom.rust || {}
);
// By default, Serverless examines node_modules to figure out which
// packages there are from dependencies versus devDependencies of a
// package. While there will always be a node_modules due to Serverless
// and this plugin being installed, it will be excluded anyway.
// Therefore, the filtering can be disabled to speed up (~3.2s) the process.
this.serverless.service.package.excludeDevDependencies = false;
// represented as an object for unique keys
this.artifacts = {};
}
runDocker(funcArgs, captureOutput) {
const defaultArgs = [
'run',
'--rm',
'-t',
`-v`, `${this.servicePath}:/code`,
`-v`, `${process.env['HOME']}/.cargo/registry:/root/.cargo/registry`,
`-v`, `${process.env['HOME']}/.cargo/git:/root/.cargo/git`,
];
const customArgs = [];
const cargoFlags = (funcArgs || {}).cargoFlags || this.custom.cargoFlags;
if (cargoFlags) {
// --features python3-sys, ect
customArgs.push('-e', `CARGO_FLAGS=${cargoFlags}`);
};
const dockerTag = (funcArgs || {}).dockerTag || this.custom.dockerTag;
return spawnSync(
'docker',
[
...defaultArgs,
...customArgs,
`softprops/lambda-rust:${dockerTag}`
],
captureOutput ? {} : NO_OUTPUT_CAPTURE
);
}
build() {
const service = this.serverless.service;
service.getAllFunctions().forEach(funcName => {
const func = service.getFunction(funcName);
const [crate, fn] = func.handler.split('.');
this.serverless.cli.log(`Building native Rust ${func.handler} func...`);
const res = this.runDocker(func.rust);
if (res.error || res.status > 0) {
this.serverless.cli.log(`Dockerized Rust build encountered an error.`);
throw new Error(res.error);
}
const executablePath = path.resolve('target/lambda/release', crate + '.so');
const targetPath = path.resolve(this.servicePath, crate + '.so');
copyFileSync(executablePath, targetPath);
// only the keys matters
this.artifacts[targetPath] = null;
})
}
clean() {
Object.keys(this.artifacts).forEach(removeSync);
}
}
module.exports = ServerlessPlugin;