Skip to content

Commit 1ace7db

Browse files
authored
chore: bump version before release + fixes (#321)
* chore: bump version before release + fixes * fix: reorder apply domains to container * fix: small log message change * fix: prettier diff * test: try to add a sleep to see if it helps * fix: fmt * fix: deprecated auth in tests * fix: fmt * fix: omg it might work * fix: fmt * fix: some more tests * fix: add blabla * fix: change authconfig * Revert "fix: change authconfig" This reverts commit 2823e72. * fix: change authconfig again * fix: oopsie * fix: oopsie again * fix: registryAuth invalid region * fix: change it again
1 parent 16a0fe6 commit 1ace7db

9 files changed

Lines changed: 130 additions & 50 deletions

File tree

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changelog
22

3+
## 0.5.0
4+
5+
### Added
6+
7+
- Implement `buildArgs` parameter for container build
8+
9+
### Changed
10+
11+
- Handle deprecation of `redeploy: false` parameter in `UpdateContainer`
12+
13+
### Fixed
14+
15+
- When pushing a built to the remote registry, use the correct credentials instead of relying on the local docker configuration.
16+
317
## 0.4.18
418

519
### Fixed

deploy/lib/buildAndPushContainers.js

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ module.exports = {
167167
password: this.provider.scwToken,
168168
};
169169

170-
// Used for building: see https://docs.docker.com/engine/api/v1.37/#tag/Image/operation/ImageBuild
171-
const registryAuth = { [`rg.${this.provider.region}.scw.cloud`]: auth };
170+
// Used for building, see https://docs.docker.com/engine/api/v1.37/#tag/Image/operation/ImageBuild
171+
const registryAuth = { [`rg.${this.provider.scwRegion}.scw.cloud`]: auth };
172172

173173
try {
174174
await docker.checkAuth(registryAuth);
@@ -178,21 +178,28 @@ module.exports = {
178178

179179
const { containers } = this.provider.serverless.service.custom;
180180

181-
const buildPromises = Object.keys(containers).map((containerName) => {
182-
const containerConfig = Object.assign(containers[containerName], {
183-
name: containerName,
181+
const buildPromises = Object.keys(containers)
182+
.map((containerName) => {
183+
const containerConfig = {
184+
...containers[containerName],
185+
name: containerName,
186+
};
187+
return containerConfig;
188+
})
189+
// If directory is not specified, the container does not need to be built,
190+
// we can directly create it from the registry image.
191+
.filter((containerConfig) => containerConfig.directory !== undefined)
192+
.map((containerConfig) => {
193+
validateContainerConfigBeforeBuild(containerConfig);
194+
195+
return buildAndPushContainer.call(
196+
this,
197+
registryAuth,
198+
auth,
199+
containerConfig
200+
);
184201
});
185202

186-
validateContainerConfigBeforeBuild(containerConfig);
187-
188-
return buildAndPushContainer.call(
189-
this,
190-
registryAuth,
191-
auth,
192-
containerConfig
193-
);
194-
});
195-
196203
await Promise.all(buildPromises);
197204
},
198205
};

deploy/lib/createContainers.js

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,18 @@ module.exports = {
180180

181181
this.serverless.cli.log(`Creating container ${container.name}...`);
182182

183-
return this.createContainer(params);
183+
return this.createContainer(params).then((createdContainer) => {
184+
return this.deployContainer(createdContainer.id);
185+
});
184186
},
185187

186188
async updateSingleContainer(container, foundContainer) {
189+
// Assign domains to the container before updating it, as it's not possible to manage domains
190+
// while the container is updating or pending, and we already wait for the container
191+
// to be in a final status before updating it.
192+
// => This order of operation is simpler and does not require performing two separate waits.
193+
this.applyDomainsContainer(foundContainer.id, container.custom_domains);
194+
187195
let privateNetworkId = container.privateNetworkId;
188196
const hasToDeletePrivateNetwork =
189197
foundContainer.private_network_id && !container.privateNetworkId;
@@ -192,7 +200,6 @@ module.exports = {
192200
}
193201

194202
const params = {
195-
redeploy: false,
196203
environment_variables: container.env,
197204
secret_environment_variables: await secrets.mergeSecretEnvVars(
198205
foundContainer.secret_environment_variables,
@@ -225,9 +232,22 @@ module.exports = {
225232

226233
this.serverless.cli.log(`Updating container ${container.name}...`);
227234

228-
// assign domains
229-
this.applyDomainsContainer(foundContainer.id, container.custom_domains);
235+
return this.updateContainer(foundContainer.id, params).then(
236+
(updatedContainer) => {
237+
// If the container is updating, no need to do anything, a redeploy is already in progress.
238+
if (
239+
updatedContainer.status === "pending" ||
240+
updatedContainer.status === "updating"
241+
) {
242+
return updatedContainer;
243+
}
230244

231-
return this.updateContainer(foundContainer.id, params);
245+
this.serverless.cli.log(
246+
`Redeploying container ${container.name} to apply changes...`
247+
);
248+
249+
return this.deployContainer(updatedContainer.id);
250+
}
251+
);
232252
},
233253
};

deploy/lib/deployContainers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module.exports = {
1818

1919
this.waitDomainsAreDeployedContainer(container.id).then((domains) => {
2020
domains.forEach((domain) => {
21-
this.serverless.cli.log(`Domain ready : ${domain.hostname}`);
21+
this.serverless.cli.log(`Domain ready: ${domain.hostname}`);
2222
});
2323
});
2424
});

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "serverless-scaleway-functions",
3-
"version": "0.4.18",
3+
"version": "0.5.0",
44
"description": "Provider plugin for the Serverless Framework v3.x which adds support for Scaleway Functions.",
55
"main": "index.js",
66
"author": "scaleway.com",

shared/api/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const axios = require("axios");
22
const https = require("https");
33

4-
const version = "0.4.18";
4+
const version = "0.5.0";
55

66
const invalidArgumentsType = "invalid_arguments";
77

tests/containers/containers.test.js

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -106,32 +106,40 @@ describe("Service Lifecyle Integration Test", () => {
106106
password: scwToken,
107107
};
108108

109-
const regEndpoint = `rg.${scwRegion}.scw.cloud`;
110-
const registryAuth = {};
111-
registryAuth[regEndpoint] = auth;
112-
113-
await docker.checkAuth(registryAuth);
114-
115-
await docker.buildImage(
116-
{
117-
context: path.join(tmpDir, "my-container"),
118-
src: ["Dockerfile", "server.py", "requirements.txt"],
119-
},
120-
{
121-
t: imageName,
122-
registryconfig: registryAuth,
123-
}
124-
);
109+
// Build image and wait for completion
110+
await new Promise((resolve, reject) => {
111+
docker.buildImage(
112+
{
113+
context: path.join(tmpDir, "my-container"),
114+
src: ["Dockerfile", "server.py", "requirements.txt"],
115+
},
116+
// Ensure no credentials are sent to Docker Hub.
117+
{ t: imageName, authconfig: {} },
118+
(err, stream) => {
119+
if (err) return reject(err);
120+
docker.modem.followProgress(stream, (err, res) =>
121+
err ? reject(err) : resolve(res)
122+
);
123+
}
124+
);
125+
});
126+
125127
const image = docker.getImage(imageName);
126-
await image.push(auth);
128+
129+
// Push image and wait for completion
130+
await new Promise((resolve, reject) => {
131+
image.push({ authconfig: auth }, (err, stream) => {
132+
if (err) return reject(err);
133+
docker.modem.followProgress(stream, (err, res) =>
134+
err ? reject(err) : resolve(res)
135+
);
136+
});
137+
});
127138

128139
// registry lag
129140
await sleep(60000);
130141

131-
const params = {
132-
redeploy: false,
133-
registry_image: imageName,
134-
};
142+
const params = { registry_image: imageName };
135143
await api
136144
.updateContainer(namespace.containers[0].id, params)
137145
.catch((err) => console.error(err));
@@ -178,12 +186,20 @@ describe("Service Lifecyle Integration Test", () => {
178186
});
179187

180188
it("should deploy with registry image specified", () => {
189+
// Instead of building the container from the directory, we specify a registry image.
190+
replaceTextInFile(
191+
"serverless.yml",
192+
"directory: my-container",
193+
"# directory: my-container"
194+
);
181195
replaceTextInFile(
182196
"serverless.yml",
183197
'# registryImage: ""',
184198
"registryImage: docker.io/library/nginx:latest"
185199
);
186200
replaceTextInFile("serverless.yml", "# port: 8080", "port: 80");
201+
// Need to change the probe path to / since Nginx doesn't have /health endpoint
202+
replaceTextInFile("serverless.yml", "httpPath: /health", "httpPath: /");
187203
serverlessDeploy(options);
188204
});
189205

tests/containers/containers_private_registry.test.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,30 @@ describe("Build and deploy on container with a base image private", () => {
8585
const pullStream = await docker
8686
.pull(`${originalImageRepo}:${imageTag}`)
8787
.then();
88+
8889
// Wait for pull to finish
8990
await new Promise((res) => docker.modem.followProgress(pullStream, res));
90-
const originalImage = await docker.getImage(
91-
`${originalImageRepo}:${imageTag}`
92-
);
91+
const originalImage = docker.getImage(`${originalImageRepo}:${imageTag}`);
9392
await originalImage.tag({ repo: privateRegistryImageRepo, tag: imageTag });
93+
9494
const privateRegistryImage = docker.getImage(
9595
`${privateRegistryImageRepo}:${imageTag}`
9696
);
97-
await privateRegistryImage.push({
98-
stream: false,
97+
98+
const auth = {
9999
username: "nologin",
100100
password: scwToken,
101+
};
102+
103+
await new Promise((resolve, reject) => {
104+
privateRegistryImage.push({ authconfig: auth }, (err, stream) => {
105+
if (err) return reject(err);
106+
docker.modem.followProgress(stream, (err, res) =>
107+
err ? reject(err) : resolve(res)
108+
);
109+
});
101110
});
111+
102112
await privateRegistryImage.remove();
103113
});
104114

tests/utils/misc/index.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,23 @@ function sleep(ms) {
110110

111111
async function createProject() {
112112
const accountApi = new AccountApi(ACCOUNT_API_URL, secretKey);
113-
return accountApi.createProject({
113+
114+
// Unfortunately, there's a small delay between the creation of a project and its availability for API calls.
115+
// We wait 1 minute to ensure there's no issue with IAM cache.
116+
const project = await accountApi.createProject({
114117
name: `test-slsframework-${crypto.randomBytes(6).toString("hex")}`,
115118
organization_id: organizationId,
116119
});
120+
121+
console.log(
122+
`Project ${project.name} created, waiting for it to be available...`
123+
);
124+
125+
await sleep(60000);
126+
127+
console.log(`Project ${project.name} is now available.`);
128+
129+
return project;
117130
}
118131

119132
module.exports = {

0 commit comments

Comments
 (0)