Skip to content

Commit 1b0faae

Browse files
pgrzesikcyclimse
andauthoredJan 14, 2024
feat: Support Scaleway provider (#812)
Co-authored-by: Andy Méry <amery@scaleway.com>
1 parent 16c0e68 commit 1b0faae

File tree

9 files changed

+126
-3
lines changed

9 files changed

+126
-3
lines changed
 

‎README.md

+25
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,31 @@ package:
580580
- '**'
581581
```
582582

583+
## Custom Provider Support
584+
585+
### Scaleway
586+
587+
This plugin is compatible with the [Scaleway Serverless Framework Plugin](https://github.com/scaleway/serverless-scaleway-functions) to package dependencies for Python functions deployed on [Scaleway](https://www.scaleway.com/en/serverless-functions/). To use it, add the following to your `serverless.yml`:
588+
589+
```yaml
590+
provider:
591+
name: scaleway
592+
runtime: python311
593+
594+
plugins:
595+
- serverless-python-requirements
596+
- serverless-scaleway-functions
597+
```
598+
599+
To handle native dependencies, it's recommended to use the Docker builder with the image provided by Scaleway:
600+
601+
```yaml
602+
custom:
603+
pythonRequirements:
604+
# Can use any Python version supported by Scaleway
605+
dockerImage: rg.fr-par.scw.cloud/scwfunctionsruntimes-public/python-dep:3.11
606+
```
607+
583608
## Contributors
584609

585610
- [@dschep](https://github.com/dschep) - Original developer

‎index.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ class ServerlessPythonRequirements {
7272
) {
7373
options.pythonBin = 'python';
7474
}
75-
75+
if (/python3[0-9]+/.test(options.pythonBin)) {
76+
// "google" and "scaleway" providers' runtimes uses python3XX
77+
options.pythonBin = options.pythonBin.replace(/3([0-9]+)/, '3.$1');
78+
}
7679
if (options.dockerizePip === 'non-linux') {
7780
options.dockerizePip = process.platform !== 'linux';
7881
}

‎lib/inject.js

+21-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,16 @@ BbPromise.promisifyAll(fse);
1313
* Inject requirements into packaged application.
1414
* @param {string} requirementsPath requirements folder path
1515
* @param {string} packagePath target package path
16+
* @param {string} injectionRelativePath installation directory in target package
1617
* @param {Object} options our options object
1718
* @return {Promise} the JSZip object constructed.
1819
*/
19-
function injectRequirements(requirementsPath, packagePath, options) {
20+
function injectRequirements(
21+
requirementsPath,
22+
packagePath,
23+
injectionRelativePath,
24+
options
25+
) {
2026
const noDeploy = new Set(options.noDeploy || []);
2127

2228
return fse
@@ -29,7 +35,13 @@ function injectRequirements(requirementsPath, packagePath, options) {
2935
dot: true,
3036
})
3137
)
32-
.map((file) => [file, path.relative(requirementsPath, file)])
38+
.map((file) => [
39+
file,
40+
path.join(
41+
injectionRelativePath,
42+
path.relative(requirementsPath, file)
43+
),
44+
])
3345
.filter(
3446
([file, relativeFile]) =>
3547
!file.endsWith('/') &&
@@ -101,6 +113,11 @@ async function injectAllRequirements(funcArtifact) {
101113
this.serverless.cli.log('Injecting required Python packages to package...');
102114
}
103115

116+
let injectionRelativePath = '.';
117+
if (this.serverless.service.provider.name == 'scaleway') {
118+
injectionRelativePath = 'package';
119+
}
120+
104121
try {
105122
if (this.serverless.service.package.individually) {
106123
await BbPromise.resolve(this.targetFuncs)
@@ -138,13 +155,15 @@ async function injectAllRequirements(funcArtifact) {
138155
: injectRequirements(
139156
path.join('.serverless', func.module, 'requirements'),
140157
func.package.artifact,
158+
injectionRelativePath,
141159
this.options
142160
);
143161
});
144162
} else if (!this.options.zip) {
145163
await injectRequirements(
146164
path.join('.serverless', 'requirements'),
147165
this.serverless.service.package.artifact || funcArtifact,
166+
injectionRelativePath,
148167
this.options
149168
);
150169
}

‎test.js

+17
Original file line numberDiff line numberDiff line change
@@ -1729,3 +1729,20 @@ test('poetry py3.9 only installs optional packages specified in onlyGroups', asy
17291729
t.true(zipfiles.includes(`boto3${sep}__init__.py`), 'boto3 is packaged');
17301730
t.end();
17311731
});
1732+
1733+
test('py3.7 injects dependencies into `package` folder when using scaleway provider', async (t) => {
1734+
process.chdir('tests/scaleway_provider');
1735+
const path = npm(['pack', '../..']);
1736+
npm(['i', path]);
1737+
sls(['package'], { env: {} });
1738+
const zipfiles = await listZipFiles('.serverless/sls-py-req-test.zip');
1739+
t.true(
1740+
zipfiles.includes(`package${sep}flask${sep}__init__.py`),
1741+
'flask is packaged'
1742+
);
1743+
t.true(
1744+
zipfiles.includes(`package${sep}boto3${sep}__init__.py`),
1745+
'boto3 is packaged'
1746+
);
1747+
t.end();
1748+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
slimPatterns:
2+
- '**/__main__.py'

‎tests/scaleway_provider/handler.py

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import requests
2+
3+
4+
def hello(event, context):
5+
return requests.get('https://httpbin.org/get').json()

‎tests/scaleway_provider/package.json

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "example",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "",
10+
"license": "ISC",
11+
"dependencies": {
12+
"serverless-python-requirements": "file:serverless-python-requirements-6.0.0.tgz",
13+
"serverless-scaleway-functions": "^0.4.8"
14+
}
15+
}
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
flask==0.12.5
2+
bottle
3+
boto3
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
service: sls-py-req-test
2+
3+
configValidationMode: off
4+
5+
provider:
6+
name: scaleway
7+
runtime: python39
8+
9+
plugins:
10+
- serverless-python-requirements
11+
- serverless-scaleway-functions
12+
13+
custom:
14+
pythonRequirements:
15+
zip: ${env:zip, self:custom.defaults.zip}
16+
slim: ${env:slim, self:custom.defaults.slim}
17+
slimPatterns: ${file(./slimPatterns.yml):slimPatterns, self:custom.defaults.slimPatterns}
18+
slimPatternsAppendDefaults: ${env:slimPatternsAppendDefaults, self:custom.defaults.slimPatternsAppendDefaults}
19+
dockerizePip: ${env:dockerizePip, self:custom.defaults.dockerizePip}
20+
defaults:
21+
zip: false
22+
slimPatterns: false
23+
slimPatternsAppendDefaults: true
24+
slim: false
25+
dockerizePip: false
26+
27+
package:
28+
patterns:
29+
- '!**/*'
30+
- 'handler.py'
31+
32+
functions:
33+
hello:
34+
handler: handler.hello

0 commit comments

Comments
 (0)
Failed to load comments.