debian-mirror-gitlab/app/assets/javascripts/environments/graphql/resolvers.js
2023-07-09 08:55:56 +05:30

303 lines
10 KiB
JavaScript

import { CoreV1Api, Configuration, AppsV1Api, BatchV1Api } from '@gitlab/cluster-client';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
import {
convertObjectPropsToCamelCase,
parseIntPagination,
normalizeHeaders,
} from '~/lib/utils/common_utils';
import pollIntervalQuery from './queries/poll_interval.query.graphql';
import environmentToRollbackQuery from './queries/environment_to_rollback.query.graphql';
import environmentToStopQuery from './queries/environment_to_stop.query.graphql';
import environmentToDeleteQuery from './queries/environment_to_delete.query.graphql';
import environmentToChangeCanaryQuery from './queries/environment_to_change_canary.query.graphql';
import isEnvironmentStoppingQuery from './queries/is_environment_stopping.query.graphql';
import pageInfoQuery from './queries/page_info.query.graphql';
const buildErrors = (errors = []) => ({
errors,
__typename: 'LocalEnvironmentErrors',
});
const mapNestedEnvironment = (env) => ({
...convertObjectPropsToCamelCase(env, { deep: true }),
__typename: 'NestedLocalEnvironment',
});
const mapEnvironment = (env) => ({
...convertObjectPropsToCamelCase(env, { deep: true }),
__typename: 'LocalEnvironment',
});
const mapWorkloadItems = (items, kind) => {
return items.map((item) => {
const updatedItem = {
status: {},
spec: {},
};
switch (kind) {
case 'DeploymentList':
updatedItem.status.conditions = item.status.conditions || [];
break;
case 'DaemonSetList':
updatedItem.status = {
numberMisscheduled: item.status.numberMisscheduled || 0,
numberReady: item.status.numberReady || 0,
desiredNumberScheduled: item.status.desiredNumberScheduled || 0,
};
break;
case 'StatefulSetList':
case 'ReplicaSetList':
updatedItem.status.readyReplicas = item.status.readyReplicas || 0;
updatedItem.spec.replicas = item.spec.replicas || 0;
break;
case 'JobList':
updatedItem.status.failed = item.status.failed || 0;
updatedItem.status.succeeded = item.status.succeeded || 0;
updatedItem.spec.completions = item.spec.completions || 0;
break;
case 'CronJobList':
updatedItem.status.active = item.status.active || 0;
updatedItem.status.lastScheduleTime = item.status.lastScheduleTime || '';
updatedItem.spec.suspend = item.spec.suspend || 0;
break;
default:
updatedItem.status = item?.status;
updatedItem.spec = item?.spec;
break;
}
return updatedItem;
});
};
export const resolvers = (endpoint) => ({
Query: {
environmentApp(_context, { page, scope, search }, { cache }) {
return axios.get(endpoint, { params: { nested: true, page, scope, search } }).then((res) => {
const headers = normalizeHeaders(res.headers);
const interval = headers['POLL-INTERVAL'];
const pageInfo = { ...parseIntPagination(headers), __typename: 'LocalPageInfo' };
if (interval) {
cache.writeQuery({ query: pollIntervalQuery, data: { interval: parseFloat(interval) } });
} else {
cache.writeQuery({ query: pollIntervalQuery, data: { interval: undefined } });
}
cache.writeQuery({
query: pageInfoQuery,
data: { pageInfo },
});
return {
availableCount: res.data.available_count,
environments: res.data.environments.map(mapNestedEnvironment),
reviewApp: {
...convertObjectPropsToCamelCase(res.data.review_app),
__typename: 'ReviewApp',
},
canStopStaleEnvironments: res.data.can_stop_stale_environments,
stoppedCount: res.data.stopped_count,
__typename: 'LocalEnvironmentApp',
};
});
},
folder(_, { environment: { folderPath }, scope, search }) {
return axios.get(folderPath, { params: { scope, search, per_page: 3 } }).then((res) => ({
availableCount: res.data.available_count,
environments: res.data.environments.map(mapEnvironment),
stoppedCount: res.data.stopped_count,
__typename: 'LocalEnvironmentFolder',
}));
},
isLastDeployment(_, { environment }) {
return environment?.lastDeployment?.isLast;
},
k8sPods(_, { configuration, namespace }) {
const coreV1Api = new CoreV1Api(new Configuration(configuration));
const podsApi = namespace
? coreV1Api.listCoreV1NamespacedPod(namespace)
: coreV1Api.listCoreV1PodForAllNamespaces();
return podsApi
.then((res) => res?.data?.items || [])
.catch((err) => {
const error = err?.response?.data?.message ? new Error(err.response.data.message) : err;
throw error;
});
},
k8sServices(_, { configuration }) {
const coreV1Api = new CoreV1Api(new Configuration(configuration));
return coreV1Api
.listCoreV1ServiceForAllNamespaces()
.then((res) => {
const items = res?.data?.items || [];
return items.map((item) => {
const { type, clusterIP, externalIP, ports } = item.spec;
return {
metadata: item.metadata,
spec: {
type,
clusterIP: clusterIP || '-',
externalIP: externalIP || '-',
ports,
},
};
});
})
.catch((err) => {
const error = err?.response?.data?.message ? new Error(err.response.data.message) : err;
throw error;
});
},
k8sWorkloads(_, { configuration, namespace }) {
const appsV1api = new AppsV1Api(configuration);
const batchV1api = new BatchV1Api(configuration);
let promises;
if (namespace) {
promises = [
appsV1api.listAppsV1NamespacedDeployment(namespace),
appsV1api.listAppsV1NamespacedDaemonSet(namespace),
appsV1api.listAppsV1NamespacedStatefulSet(namespace),
appsV1api.listAppsV1NamespacedReplicaSet(namespace),
batchV1api.listBatchV1NamespacedJob(namespace),
batchV1api.listBatchV1NamespacedCronJob(namespace),
];
} else {
promises = [
appsV1api.listAppsV1DeploymentForAllNamespaces(),
appsV1api.listAppsV1DaemonSetForAllNamespaces(),
appsV1api.listAppsV1StatefulSetForAllNamespaces(),
appsV1api.listAppsV1ReplicaSetForAllNamespaces(),
batchV1api.listBatchV1JobForAllNamespaces(),
batchV1api.listBatchV1CronJobForAllNamespaces(),
];
}
const summaryList = {
DeploymentList: [],
DaemonSetList: [],
StatefulSetList: [],
ReplicaSetList: [],
JobList: [],
CronJobList: [],
};
return Promise.allSettled(promises).then((results) => {
if (results.every((res) => res.status === 'rejected')) {
const error = results[0].reason;
const errorMessage = error?.response?.data?.message ?? error;
throw new Error(errorMessage);
}
for (const promiseResult of results) {
if (promiseResult.status === 'fulfilled' && promiseResult?.value?.data) {
const { kind, items } = promiseResult.value.data;
if (items?.length > 0) {
summaryList[kind] = mapWorkloadItems(items, kind);
}
}
}
return summaryList;
});
},
},
Mutation: {
stopEnvironmentREST(_, { environment }, { client }) {
client.writeQuery({
query: isEnvironmentStoppingQuery,
variables: { environment },
data: { isEnvironmentStopping: true },
});
return axios
.post(environment.stopPath)
.then(() => buildErrors())
.catch(() => {
client.writeQuery({
query: isEnvironmentStoppingQuery,
variables: { environment },
data: { isEnvironmentStopping: false },
});
return buildErrors([
s__('Environments|An error occurred while stopping the environment, please try again'),
]);
});
},
deleteEnvironment(_, { environment: { deletePath } }) {
return axios
.delete(deletePath)
.then(() => buildErrors())
.catch(() =>
buildErrors([
s__(
'Environments|An error occurred while deleting the environment. Check if the environment stopped; if not, stop it and try again.',
),
]),
);
},
rollbackEnvironment(_, { environment, isLastDeployment }) {
return axios
.post(environment?.retryUrl)
.then(() => buildErrors())
.catch(() => {
buildErrors([
isLastDeployment
? s__(
'Environments|An error occurred while re-deploying the environment, please try again',
)
: s__(
'Environments|An error occurred while rolling back the environment, please try again',
),
]);
});
},
setEnvironmentToStop(_, { environment }, { client }) {
client.writeQuery({
query: environmentToStopQuery,
data: { environmentToStop: environment },
});
},
action(_, { action: { playPath } }) {
return axios
.post(playPath)
.then(() => buildErrors())
.catch(() =>
buildErrors([s__('Environments|An error occurred while making the request.')]),
);
},
setEnvironmentToDelete(_, { environment }, { client }) {
client.writeQuery({
query: environmentToDeleteQuery,
data: { environmentToDelete: environment },
});
},
setEnvironmentToRollback(_, { environment }, { client }) {
client.writeQuery({
query: environmentToRollbackQuery,
data: { environmentToRollback: environment },
});
},
setEnvironmentToChangeCanary(_, { environment, weight }, { client }) {
client.writeQuery({
query: environmentToChangeCanaryQuery,
data: { environmentToChangeCanary: environment, weight },
});
},
cancelAutoStop(_, { autoStopUrl }) {
return axios
.post(autoStopUrl)
.then(() => buildErrors())
.catch((err) =>
buildErrors([
err?.response?.data?.message ||
s__('Environments|An error occurred while canceling the auto stop, please try again'),
]),
);
},
},
});