DeploymentStore.ts 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. Copyright (C) 2024 Cloudbase Solutions SRL
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. import { observable, action, runInAction } from "mobx";
  15. import type {
  16. UpdateData,
  17. DeploymentItem,
  18. DeploymentItemDetails,
  19. DeploymentItemOptions,
  20. UserScriptData,
  21. } from "@src/@types/MainItem";
  22. import type { Field } from "@src/@types/Field";
  23. import type { Endpoint } from "@src/@types/Endpoint";
  24. import type { InstanceScript } from "@src/@types/Instance";
  25. import DeploymentSource from "@src/sources/DeploymentSource";
  26. import apiCaller from "@src/utils/ApiCaller";
  27. class DeploymentStore {
  28. @observable deployments: DeploymentItem[] = [];
  29. @observable deploymentDetails: DeploymentItemDetails | null = null;
  30. @observable loading = true;
  31. @observable detailsLoading = true;
  32. @observable deploymentsPage = 1;
  33. @observable deploymentsHasNextPage = false;
  34. @observable deploymentsItemsPerPage = 25;
  35. deploymentsLoaded = false;
  36. private deploymentPageMarkers: (string | null)[] = [null];
  37. @action resetDeploymentPagination(): void {
  38. this.deploymentsPage = 1;
  39. this.deploymentsHasNextPage = false;
  40. this.deploymentPageMarkers = [null];
  41. }
  42. @action async setDeploymentsPage(page: number): Promise<void> {
  43. this.deploymentsPage = page;
  44. await this.getDeployments({ showLoading: true });
  45. }
  46. @action async setDeploymentsItemsPerPage(
  47. itemsPerPage: number,
  48. ): Promise<void> {
  49. this.deploymentsItemsPerPage = itemsPerPage;
  50. this.deploymentsPage = 1;
  51. this.deploymentPageMarkers = [null];
  52. this.deploymentsHasNextPage = false;
  53. await this.getDeployments({ showLoading: true });
  54. }
  55. @action async getDeployments(options?: {
  56. showLoading?: boolean;
  57. skipLog?: boolean;
  58. }) {
  59. if ((options && options.showLoading) || !this.deploymentsLoaded) {
  60. this.loading = true;
  61. }
  62. const marker = this.deploymentPageMarkers[this.deploymentsPage - 1] ?? null;
  63. const isPaginationRequest = marker !== null;
  64. try {
  65. const raw = await DeploymentSource.getDeployments({
  66. skipLog: options?.skipLog,
  67. quietError: isPaginationRequest,
  68. limit: this.deploymentsItemsPerPage,
  69. marker,
  70. });
  71. if (isPaginationRequest && raw.length === 0) {
  72. runInAction(() => {
  73. this.deploymentsHasNextPage = false;
  74. this.deploymentsPage = Math.max(1, this.deploymentsPage - 1);
  75. this.loading = false;
  76. });
  77. return;
  78. }
  79. const hasNextPage = raw.length === this.deploymentsItemsPerPage;
  80. const nextMarker = raw.length > 0 ? raw[raw.length - 1].id : null;
  81. runInAction(() => {
  82. this.deployments = raw;
  83. this.deploymentsHasNextPage = hasNextPage;
  84. if (nextMarker !== null) {
  85. this.deploymentPageMarkers[this.deploymentsPage] = nextMarker;
  86. }
  87. this.loading = false;
  88. this.deploymentsLoaded = true;
  89. });
  90. } catch (ex) {
  91. if (isPaginationRequest) {
  92. runInAction(() => {
  93. this.deploymentsHasNextPage = false;
  94. this.deploymentsPage = Math.max(1, this.deploymentsPage - 1);
  95. this.loading = false;
  96. });
  97. return;
  98. }
  99. runInAction(() => {
  100. this.loading = false;
  101. });
  102. throw ex;
  103. }
  104. }
  105. getDefaultSkipOsMorphing(deployment: DeploymentItemDetails | null) {
  106. const tasks = deployment && deployment.tasks;
  107. if (tasks && !tasks.find(t => t.task_type === "OS_MORPHING")) {
  108. return true;
  109. }
  110. return null;
  111. }
  112. @action async recreateFullCopy(deployment: DeploymentItemOptions) {
  113. return DeploymentSource.recreateFullCopy(deployment);
  114. }
  115. @action async recreate(opts: {
  116. deployment: DeploymentItemDetails;
  117. sourceEndpoint: Endpoint;
  118. destEndpoint: Endpoint;
  119. updateData: UpdateData;
  120. defaultStorage: { value: string | null; busType?: string | null };
  121. updatedDefaultStorage:
  122. | { value: string | null; busType?: string | null }
  123. | undefined;
  124. // replicationCount: number | null | undefined;
  125. }): Promise<DeploymentItemDetails> {
  126. const {
  127. deployment,
  128. sourceEndpoint,
  129. destEndpoint,
  130. updateData,
  131. defaultStorage,
  132. updatedDefaultStorage,
  133. // replicationCount,
  134. } = opts;
  135. const deploymentResult = await DeploymentSource.recreate({
  136. sourceEndpoint,
  137. destEndpoint,
  138. deployment,
  139. instanceNames: deployment.instances,
  140. sourceEnv: deployment.source_environment,
  141. updatedSourceEnv: updateData.source,
  142. destEnv: deployment.destination_environment,
  143. updatedDestEnv: updateData.destination,
  144. storageMappings: deployment.storage_mappings,
  145. updatedStorageMappings: updateData.storage,
  146. defaultStorage,
  147. updatedDefaultStorage,
  148. networkMappings: deployment.network_map,
  149. updatedNetworkMappings: updateData.network,
  150. defaultSkipOsMorphing: this.getDefaultSkipOsMorphing(deployment),
  151. // replicationCount,
  152. uploadedScripts: updateData.uploadedScripts,
  153. removedScripts: updateData.removedScripts,
  154. });
  155. return deploymentResult;
  156. }
  157. @action async getDeployment(
  158. deploymentId: string,
  159. options?: {
  160. showLoading?: boolean;
  161. skipLog?: boolean;
  162. includeTaskInfo?: boolean;
  163. },
  164. ) {
  165. if (options && options.showLoading) {
  166. this.detailsLoading = true;
  167. }
  168. try {
  169. const deployment = await DeploymentSource.getDeployment(
  170. deploymentId,
  171. options && options.skipLog,
  172. options && options.includeTaskInfo,
  173. );
  174. runInAction(() => {
  175. this.deploymentDetails = deployment;
  176. this.deployments = this.deployments.map(m =>
  177. m.id === deployment.id ? deployment : m,
  178. );
  179. });
  180. } finally {
  181. runInAction(() => {
  182. this.detailsLoading = false;
  183. });
  184. }
  185. }
  186. @action async cancel(deploymentId: string, force?: boolean | null) {
  187. await DeploymentSource.cancel(deploymentId, force);
  188. }
  189. @action async delete(deploymentId: string) {
  190. await DeploymentSource.delete(deploymentId);
  191. runInAction(() => {
  192. this.deployments = this.deployments.filter(r => r.id !== deploymentId);
  193. });
  194. }
  195. @action async deployTransfer(opts: {
  196. transferId: string;
  197. fields: Field[];
  198. uploadedUserScripts: InstanceScript[];
  199. removedUserScripts: InstanceScript[];
  200. userScriptData: UserScriptData | null | undefined;
  201. minionPoolMappings: { [instance: string]: string };
  202. }) {
  203. const {
  204. transferId: transferId,
  205. fields: options,
  206. uploadedUserScripts,
  207. removedUserScripts,
  208. userScriptData,
  209. minionPoolMappings,
  210. } = opts;
  211. const deployment = await DeploymentSource.deployTransfer({
  212. transferId: transferId,
  213. options,
  214. uploadedUserScripts,
  215. removedUserScripts,
  216. userScriptData,
  217. minionPoolMappings,
  218. });
  219. return deployment;
  220. }
  221. @action cancelDeploymentDetails() {
  222. if (this.deploymentDetails) {
  223. apiCaller.cancelRequests(this.deploymentDetails.id);
  224. }
  225. this.detailsLoading = false;
  226. }
  227. @action clearDetails() {
  228. this.detailsLoading = true;
  229. this.deploymentDetails = null;
  230. }
  231. }
  232. export default new DeploymentStore();