DeploymentStore.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. try {
  63. const marker =
  64. this.deploymentPageMarkers[this.deploymentsPage - 1] ?? null;
  65. const raw = await DeploymentSource.getDeployments({
  66. skipLog: options?.skipLog,
  67. limit: this.deploymentsItemsPerPage + 1,
  68. marker,
  69. });
  70. const hasNextPage = raw.length > this.deploymentsItemsPerPage;
  71. const deployments = hasNextPage
  72. ? raw.slice(0, this.deploymentsItemsPerPage)
  73. : raw;
  74. const nextMarker =
  75. deployments.length > 0 ? deployments[deployments.length - 1].id : null;
  76. runInAction(() => {
  77. this.deployments = deployments;
  78. this.deploymentsHasNextPage = hasNextPage;
  79. if (nextMarker !== null) {
  80. this.deploymentPageMarkers[this.deploymentsPage] = nextMarker;
  81. }
  82. this.loading = false;
  83. this.deploymentsLoaded = true;
  84. });
  85. } catch (ex) {
  86. runInAction(() => {
  87. this.loading = false;
  88. });
  89. throw ex;
  90. }
  91. }
  92. getDefaultSkipOsMorphing(deployment: DeploymentItemDetails | null) {
  93. const tasks = deployment && deployment.tasks;
  94. if (tasks && !tasks.find(t => t.task_type === "OS_MORPHING")) {
  95. return true;
  96. }
  97. return null;
  98. }
  99. @action async recreateFullCopy(deployment: DeploymentItemOptions) {
  100. return DeploymentSource.recreateFullCopy(deployment);
  101. }
  102. @action async recreate(opts: {
  103. deployment: DeploymentItemDetails;
  104. sourceEndpoint: Endpoint;
  105. destEndpoint: Endpoint;
  106. updateData: UpdateData;
  107. defaultStorage: { value: string | null; busType?: string | null };
  108. updatedDefaultStorage:
  109. | { value: string | null; busType?: string | null }
  110. | undefined;
  111. // replicationCount: number | null | undefined;
  112. }): Promise<DeploymentItemDetails> {
  113. const {
  114. deployment,
  115. sourceEndpoint,
  116. destEndpoint,
  117. updateData,
  118. defaultStorage,
  119. updatedDefaultStorage,
  120. // replicationCount,
  121. } = opts;
  122. const deploymentResult = await DeploymentSource.recreate({
  123. sourceEndpoint,
  124. destEndpoint,
  125. deployment,
  126. instanceNames: deployment.instances,
  127. sourceEnv: deployment.source_environment,
  128. updatedSourceEnv: updateData.source,
  129. destEnv: deployment.destination_environment,
  130. updatedDestEnv: updateData.destination,
  131. storageMappings: deployment.storage_mappings,
  132. updatedStorageMappings: updateData.storage,
  133. defaultStorage,
  134. updatedDefaultStorage,
  135. networkMappings: deployment.network_map,
  136. updatedNetworkMappings: updateData.network,
  137. defaultSkipOsMorphing: this.getDefaultSkipOsMorphing(deployment),
  138. // replicationCount,
  139. uploadedScripts: updateData.uploadedScripts,
  140. removedScripts: updateData.removedScripts,
  141. });
  142. return deploymentResult;
  143. }
  144. @action async getDeployment(
  145. deploymentId: string,
  146. options?: {
  147. showLoading?: boolean;
  148. skipLog?: boolean;
  149. includeTaskInfo?: boolean;
  150. },
  151. ) {
  152. if (options && options.showLoading) {
  153. this.detailsLoading = true;
  154. }
  155. try {
  156. const deployment = await DeploymentSource.getDeployment(
  157. deploymentId,
  158. options && options.skipLog,
  159. options && options.includeTaskInfo,
  160. );
  161. runInAction(() => {
  162. this.deploymentDetails = deployment;
  163. this.deployments = this.deployments.map(m =>
  164. m.id === deployment.id ? deployment : m,
  165. );
  166. });
  167. } finally {
  168. runInAction(() => {
  169. this.detailsLoading = false;
  170. });
  171. }
  172. }
  173. @action async cancel(deploymentId: string, force?: boolean | null) {
  174. await DeploymentSource.cancel(deploymentId, force);
  175. }
  176. @action async delete(deploymentId: string) {
  177. await DeploymentSource.delete(deploymentId);
  178. runInAction(() => {
  179. this.deployments = this.deployments.filter(r => r.id !== deploymentId);
  180. });
  181. }
  182. @action async deployTransfer(opts: {
  183. transferId: string;
  184. fields: Field[];
  185. uploadedUserScripts: InstanceScript[];
  186. removedUserScripts: InstanceScript[];
  187. userScriptData: UserScriptData | null | undefined;
  188. minionPoolMappings: { [instance: string]: string };
  189. }) {
  190. const {
  191. transferId: transferId,
  192. fields: options,
  193. uploadedUserScripts,
  194. removedUserScripts,
  195. userScriptData,
  196. minionPoolMappings,
  197. } = opts;
  198. const deployment = await DeploymentSource.deployTransfer({
  199. transferId: transferId,
  200. options,
  201. uploadedUserScripts,
  202. removedUserScripts,
  203. userScriptData,
  204. minionPoolMappings,
  205. });
  206. return deployment;
  207. }
  208. @action cancelDeploymentDetails() {
  209. if (this.deploymentDetails) {
  210. apiCaller.cancelRequests(this.deploymentDetails.id);
  211. }
  212. this.detailsLoading = false;
  213. }
  214. @action clearDetails() {
  215. this.detailsLoading = true;
  216. this.deploymentDetails = null;
  217. }
  218. }
  219. export default new DeploymentStore();