Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(cmx): do not fail on 5xx errors from api #47

Merged
merged 1 commit into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
60 changes: 42 additions & 18 deletions archive-channel/dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30432,13 +30432,20 @@ async function findChannelDetailsInOutput(channels, { slug, name }) {
"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getClusterVersions = exports.upgradeCluster = exports.removeCluster = exports.getKubeconfig = exports.pollForStatus = exports.createCluster = exports.ClusterVersion = exports.Cluster = void 0;
exports.getClusterVersions = exports.upgradeCluster = exports.removeCluster = exports.getKubeconfig = exports.pollForStatus = exports.createCluster = exports.StatusError = exports.ClusterVersion = exports.Cluster = void 0;
class Cluster {
}
exports.Cluster = Cluster;
class ClusterVersion {
}
exports.ClusterVersion = ClusterVersion;
class StatusError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
}
}
exports.StatusError = StatusError;
async function createCluster(vendorPortalApi, clusterName, k8sDistribution, k8sVersion, clusterTTL, diskGib, nodeCount, instanceType, nodeGroups, tags) {
const http = await vendorPortalApi.client();
const reqBody = {
Expand Down Expand Up @@ -30472,24 +30479,41 @@ async function createCluster(vendorPortalApi, clusterName, k8sDistribution, k8sV
return { name: body.cluster.name, id: body.cluster.id, status: body.cluster.status };
}
exports.createCluster = createCluster;
async function pollForStatus(vendorPortalApi, clusterId, expectedStatus, timeout = 120) {
async function pollForStatus(vendorPortalApi, clusterId, expectedStatus, timeout = 120, sleeptimeMs = 5000) {
// get clusters from the api, look for the status of the id to be ${status}
// if it's not ${status}, sleep for 5 seconds and try again
// if it is ${status}, return the cluster with that status
const sleeptime = 5;
await new Promise(f => setTimeout(f, sleeptime * 1000)); // sleep for 5 seconds before polling as the cluster takes a few seconds to start provisioning
await new Promise(f => setTimeout(f, sleeptimeMs)); // sleep for 5 seconds before polling as the cluster takes a few seconds to start provisioning
// iterate for timeout/sleeptime times
for (let i = 0; i < timeout / sleeptime; i++) {
const clusterDetails = await getClusterDetails(vendorPortalApi, clusterId);
if (clusterDetails.status === expectedStatus) {
return clusterDetails;
const iterations = timeout * 1000 / sleeptimeMs;
for (let i = 0; i < iterations; i++) {
try {
const clusterDetails = await getClusterDetails(vendorPortalApi, clusterId);
if (clusterDetails.status === expectedStatus) {
return clusterDetails;
}
// Once state is "error", it will never change. So we can shortcut polling.
if (clusterDetails.status === "error") {
throw new Error(`Cluster has entered error state.`);
}
console.debug(`Cluster status is ${clusterDetails.status}, sleeping for ${sleeptimeMs / 1000} seconds`);
}
// Once state is "error", it will never change. So we can shortcut polling.
if (clusterDetails.status === "error") {
throw new Error(`Cluster has entered error state.`);
catch (err) {
if (err instanceof StatusError) {
if (err.statusCode >= 500) {
// 5xx errors are likely transient, so we should retry
console.debug(`Got HTTP error with status ${err.statusCode}, sleeping for ${sleeptimeMs / 1000} seconds`);
}
else {
console.debug(`Got HTTP error with status ${err.statusCode}, exiting`);
throw err;
}
}
else {
throw err;
}
}
console.debug(`Cluster status is ${clusterDetails.status}, sleeping for ${sleeptime} seconds`);
await new Promise(f => setTimeout(f, sleeptime * 1000));
await new Promise(f => setTimeout(f, sleeptimeMs));
}
throw new Error(`Cluster did not reach state ${expectedStatus} within ${timeout} seconds`);
}
Expand All @@ -30499,7 +30523,7 @@ async function getClusterDetails(vendorPortalApi, clusterId) {
const uri = `${vendorPortalApi.endpoint}/cluster/${clusterId}`;
const res = await http.get(uri);
if (res.message.statusCode != 200) {
throw new Error(`Failed to get cluster: Server responded with ${res.message.statusCode}`);
throw new StatusError(`Failed to get cluster: Server responded with ${res.message.statusCode}`, res.message.statusCode);
}
const body = JSON.parse(await res.readBody());
return { name: body.cluster.name, id: body.cluster.id, status: body.cluster.status };
Expand All @@ -30509,7 +30533,7 @@ async function getKubeconfig(vendorPortalApi, clusterId) {
const uri = `${vendorPortalApi.endpoint}/cluster/${clusterId}/kubeconfig`;
const res = await http.get(uri);
if (res.message.statusCode != 200) {
throw new Error(`Failed to get kubeconfig: Server responded with ${res.message.statusCode}`);
throw new StatusError(`Failed to get kubeconfig: Server responded with ${res.message.statusCode}`, res.message.statusCode);
}
const body = JSON.parse(await res.readBody());
return atob(body.kubeconfig);
Expand All @@ -30520,7 +30544,7 @@ async function removeCluster(vendorPortalApi, clusterId) {
const uri = `${vendorPortalApi.endpoint}/cluster/${clusterId}`;
const res = await http.del(uri);
if (res.message.statusCode != 200) {
throw new Error(`Failed to remove cluster: Server responded with ${res.message.statusCode}`);
throw new StatusError(`Failed to remove cluster: Server responded with ${res.message.statusCode}`, res.message.statusCode);
}
}
exports.removeCluster = removeCluster;
Expand All @@ -30532,7 +30556,7 @@ async function upgradeCluster(vendorPortalApi, clusterId, k8sVersion) {
const uri = `${vendorPortalApi.endpoint}/cluster/${clusterId}/upgrade`;
const res = await http.post(uri, JSON.stringify(reqBody));
if (res.message.statusCode != 200) {
throw new Error(`Failed to upgrade cluster: Server responded with ${res.message.statusCode}`);
throw new StatusError(`Failed to upgrade cluster: Server responded with ${res.message.statusCode}`, res.message.statusCode);
}
return getClusterDetails(vendorPortalApi, clusterId);
}
Expand All @@ -30542,7 +30566,7 @@ async function getClusterVersions(vendorPortalApi) {
const uri = `${vendorPortalApi.endpoint}/cluster/versions`;
const res = await http.get(uri);
if (res.message.statusCode != 200) {
throw new Error(`Failed to get cluster versions: Server responded with ${res.message.statusCode}`);
throw new StatusError(`Failed to get cluster versions: Server responded with ${res.message.statusCode}`, res.message.statusCode);
}
const body = JSON.parse(await res.readBody());
// 2. Convert body into ClusterVersion[]
Expand Down
2 changes: 1 addition & 1 deletion archive-channel/dist/index.js.map

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions archive-channel/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion archive-channel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"dependencies": {
"@actions/core": "^1.10.0",
"esbuild-jest": "^0.5.0",
"replicated-lib": "^0.0.1-beta.8",
"replicated-lib": "^0.0.1-beta.9",
"ts-node": "^10.9.1"
},
"devDependencies": {
Expand Down
60 changes: 42 additions & 18 deletions archive-customer/dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30431,13 +30431,20 @@ async function findChannelDetailsInOutput(channels, { slug, name }) {
"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getClusterVersions = exports.upgradeCluster = exports.removeCluster = exports.getKubeconfig = exports.pollForStatus = exports.createCluster = exports.ClusterVersion = exports.Cluster = void 0;
exports.getClusterVersions = exports.upgradeCluster = exports.removeCluster = exports.getKubeconfig = exports.pollForStatus = exports.createCluster = exports.StatusError = exports.ClusterVersion = exports.Cluster = void 0;
class Cluster {
}
exports.Cluster = Cluster;
class ClusterVersion {
}
exports.ClusterVersion = ClusterVersion;
class StatusError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
}
}
exports.StatusError = StatusError;
async function createCluster(vendorPortalApi, clusterName, k8sDistribution, k8sVersion, clusterTTL, diskGib, nodeCount, instanceType, nodeGroups, tags) {
const http = await vendorPortalApi.client();
const reqBody = {
Expand Down Expand Up @@ -30471,24 +30478,41 @@ async function createCluster(vendorPortalApi, clusterName, k8sDistribution, k8sV
return { name: body.cluster.name, id: body.cluster.id, status: body.cluster.status };
}
exports.createCluster = createCluster;
async function pollForStatus(vendorPortalApi, clusterId, expectedStatus, timeout = 120) {
async function pollForStatus(vendorPortalApi, clusterId, expectedStatus, timeout = 120, sleeptimeMs = 5000) {
// get clusters from the api, look for the status of the id to be ${status}
// if it's not ${status}, sleep for 5 seconds and try again
// if it is ${status}, return the cluster with that status
const sleeptime = 5;
await new Promise(f => setTimeout(f, sleeptime * 1000)); // sleep for 5 seconds before polling as the cluster takes a few seconds to start provisioning
await new Promise(f => setTimeout(f, sleeptimeMs)); // sleep for 5 seconds before polling as the cluster takes a few seconds to start provisioning
// iterate for timeout/sleeptime times
for (let i = 0; i < timeout / sleeptime; i++) {
const clusterDetails = await getClusterDetails(vendorPortalApi, clusterId);
if (clusterDetails.status === expectedStatus) {
return clusterDetails;
const iterations = timeout * 1000 / sleeptimeMs;
for (let i = 0; i < iterations; i++) {
try {
const clusterDetails = await getClusterDetails(vendorPortalApi, clusterId);
if (clusterDetails.status === expectedStatus) {
return clusterDetails;
}
// Once state is "error", it will never change. So we can shortcut polling.
if (clusterDetails.status === "error") {
throw new Error(`Cluster has entered error state.`);
}
console.debug(`Cluster status is ${clusterDetails.status}, sleeping for ${sleeptimeMs / 1000} seconds`);
}
// Once state is "error", it will never change. So we can shortcut polling.
if (clusterDetails.status === "error") {
throw new Error(`Cluster has entered error state.`);
catch (err) {
if (err instanceof StatusError) {
if (err.statusCode >= 500) {
// 5xx errors are likely transient, so we should retry
console.debug(`Got HTTP error with status ${err.statusCode}, sleeping for ${sleeptimeMs / 1000} seconds`);
}
else {
console.debug(`Got HTTP error with status ${err.statusCode}, exiting`);
throw err;
}
}
else {
throw err;
}
}
console.debug(`Cluster status is ${clusterDetails.status}, sleeping for ${sleeptime} seconds`);
await new Promise(f => setTimeout(f, sleeptime * 1000));
await new Promise(f => setTimeout(f, sleeptimeMs));
}
throw new Error(`Cluster did not reach state ${expectedStatus} within ${timeout} seconds`);
}
Expand All @@ -30498,7 +30522,7 @@ async function getClusterDetails(vendorPortalApi, clusterId) {
const uri = `${vendorPortalApi.endpoint}/cluster/${clusterId}`;
const res = await http.get(uri);
if (res.message.statusCode != 200) {
throw new Error(`Failed to get cluster: Server responded with ${res.message.statusCode}`);
throw new StatusError(`Failed to get cluster: Server responded with ${res.message.statusCode}`, res.message.statusCode);
}
const body = JSON.parse(await res.readBody());
return { name: body.cluster.name, id: body.cluster.id, status: body.cluster.status };
Expand All @@ -30508,7 +30532,7 @@ async function getKubeconfig(vendorPortalApi, clusterId) {
const uri = `${vendorPortalApi.endpoint}/cluster/${clusterId}/kubeconfig`;
const res = await http.get(uri);
if (res.message.statusCode != 200) {
throw new Error(`Failed to get kubeconfig: Server responded with ${res.message.statusCode}`);
throw new StatusError(`Failed to get kubeconfig: Server responded with ${res.message.statusCode}`, res.message.statusCode);
}
const body = JSON.parse(await res.readBody());
return atob(body.kubeconfig);
Expand All @@ -30519,7 +30543,7 @@ async function removeCluster(vendorPortalApi, clusterId) {
const uri = `${vendorPortalApi.endpoint}/cluster/${clusterId}`;
const res = await http.del(uri);
if (res.message.statusCode != 200) {
throw new Error(`Failed to remove cluster: Server responded with ${res.message.statusCode}`);
throw new StatusError(`Failed to remove cluster: Server responded with ${res.message.statusCode}`, res.message.statusCode);
}
}
exports.removeCluster = removeCluster;
Expand All @@ -30531,7 +30555,7 @@ async function upgradeCluster(vendorPortalApi, clusterId, k8sVersion) {
const uri = `${vendorPortalApi.endpoint}/cluster/${clusterId}/upgrade`;
const res = await http.post(uri, JSON.stringify(reqBody));
if (res.message.statusCode != 200) {
throw new Error(`Failed to upgrade cluster: Server responded with ${res.message.statusCode}`);
throw new StatusError(`Failed to upgrade cluster: Server responded with ${res.message.statusCode}`, res.message.statusCode);
}
return getClusterDetails(vendorPortalApi, clusterId);
}
Expand All @@ -30541,7 +30565,7 @@ async function getClusterVersions(vendorPortalApi) {
const uri = `${vendorPortalApi.endpoint}/cluster/versions`;
const res = await http.get(uri);
if (res.message.statusCode != 200) {
throw new Error(`Failed to get cluster versions: Server responded with ${res.message.statusCode}`);
throw new StatusError(`Failed to get cluster versions: Server responded with ${res.message.statusCode}`, res.message.statusCode);
}
const body = JSON.parse(await res.readBody());
// 2. Convert body into ClusterVersion[]
Expand Down
2 changes: 1 addition & 1 deletion archive-customer/dist/index.js.map

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions archive-customer/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion archive-customer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"dependencies": {
"@actions/core": "^1.10.0",
"esbuild-jest": "^0.5.0",
"replicated-lib": "^0.0.1-beta.8",
"replicated-lib": "^0.0.1-beta.9",
"ts-node": "^10.9.1"
},
"devDependencies": {
Expand Down
Loading
Loading