Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,13 @@ custom:
custom_domains:
- my-container.some.domain.com

# Health check configuration
healthCheck:
type: http # Or tcp if you only want to check that the port is open
httpPath: /health
interval: 10s
failureThreshold: 3

# List of events to trigger the container
events:
- schedule:
Expand Down
22 changes: 22 additions & 0 deletions deploy/lib/createContainers.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@ const singleSource = require("../../shared/singleSource");
const secrets = require("../../shared/secrets");
const domainUtils = require("../../shared/domains");

function adaptHealthCheckToAPI(healthCheck) {
if (!healthCheck) {
return null;
}

// We need to find the type of the health check (tcp, http, ...)
// If httpPath is provided, we default to http, otherwise we default to tcp
let type = healthCheck.httpPath ? "http" : "tcp";
if (healthCheck.type) {
type = healthCheck.type;
}

return {
failure_threshold: healthCheck.failureThreshold,
interval: healthCheck.interval,
...(type === "http" && { http: { path: healthCheck.httpPath || "/" } }),
...(type === "tcp" && { tcp: {} }),
};
}

module.exports = {
createContainers() {
return BbPromise.bind(this)
Expand Down Expand Up @@ -104,6 +124,7 @@ module.exports = {
port: container.port,
http_option: container.httpOption,
sandbox: container.sandbox,
health_check: adaptHealthCheckToAPI(container.healthCheck),
};

// checking if there is custom_domains set on container creation.
Expand Down Expand Up @@ -143,6 +164,7 @@ module.exports = {
privacy: container.privacy,
port: container.port,
http_option: container.httpOption,
health_check: adaptHealthCheckToAPI(container.healthCheck),
};

this.serverless.cli.log(`Updating container ${container.name}...`);
Expand Down
2 changes: 1 addition & 1 deletion examples/container/my-container/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Flask
flask~=3.1.0
17 changes: 11 additions & 6 deletions examples/container/my-container/server.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from flask import Flask
from flask import Flask, jsonify
import os
import json

DEFAULT_PORT = "8080"
MESSAGE = "Hello, World from Scaleway Container !"
Expand All @@ -9,12 +8,18 @@

@app.route("/")
def root():
return json.dumps({
return jsonify({
"message": MESSAGE
})

@app.route("/health")
def health():
# You could add more complex logic here, for example checking the health of a database...
return jsonify({
"status": "UP"
})

if __name__ == "__main__":
# Scaleway's system will inject a PORT environment variable on which your application should start the server.
port_env = os.getenv("PORT", DEFAULT_PORT)
port = int(port_env)
app.run(debug=True, host="0.0.0.0", port=port)
port = os.getenv("PORT", DEFAULT_PORT)
app.run(host="0.0.0.0", port=int(port))
4 changes: 4 additions & 0 deletions examples/container/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ custom:
# Local environment variables - used only in given function
env:
local: local
healthCheck:
httpPath: /health
interval: 10s
failureThreshold: 3
19 changes: 1 addition & 18 deletions shared/api/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
const https = require("https");
const axios = require("axios");

const { getApiManager } = require("./utils");
const accountApi = require("./account");
const domainApi = require("./domain");
const namespacesApi = require("./namespaces");
Expand All @@ -14,21 +12,6 @@ const runtimesApi = require("./runtimes");
// Registry
const RegistryApi = require("./registry");

const version = "0.4.13";

function getApiManager(apiUrl, token) {
return axios.create({
baseURL: apiUrl,
headers: {
"User-Agent": `serverless-scaleway-functions/${version}`,
"X-Auth-Token": token,
},
httpsAgent: new https.Agent({
rejectUnauthorized: false,
}),
});
}

class AccountApi {
constructor(apiUrl, token) {
this.apiManager = getApiManager(apiUrl, token);
Expand Down
2 changes: 1 addition & 1 deletion shared/api/registry.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";

const { getApiManager } = require("./index");
const { getApiManager } = require("./utils");
const { manageError } = require("./utils");

class RegistryApi {
Expand Down
34 changes: 33 additions & 1 deletion shared/api/utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
const axios = require("axios");
const https = require("https");

const version = "0.4.13";

const invalidArgumentsType = "invalid_arguments";

function getApiManager(apiUrl, token) {
return axios.create({
baseURL: apiUrl,
headers: {
"User-Agent": `serverless-scaleway-functions/${version}`,
"X-Auth-Token": token,
},
httpsAgent: new https.Agent({
rejectUnauthorized: false,
}),
});
}

/**
* Custom Error class, to print an error message, and pass the Response if applicable
*/
Expand All @@ -20,13 +40,25 @@ function manageError(err) {
throw new Error(err);
}
if (err.response.data.message) {
throw new CustomError(err.response.data.message, err.response);
let message = err.response.data.message;

// In case the error is an InvalidArgumentsError, provide some extra information
if (err.response.data.type === invalidArgumentsType) {
for (const details of err.response.data.details) {
const argumentName = details.argument_name;
const helpMessage = details.help_message;
message += `\n${argumentName}: ${helpMessage}`;
}
}

throw new CustomError(message, err.response);
} else if (err.response.data.error_message) {
throw new CustomError(err.response.data.error_message, err.response);
}
}

module.exports = {
getApiManager,
manageError,
CustomError,
};
Loading