You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2023/12/27 17:12:27 UTC
(camel-karavan) branch main updated: Fix #951
This is an automated email from the ASF dual-hosted git repository.
marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git
The following commit(s) were added to refs/heads/main by this push:
new adac8323 Fix #951
adac8323 is described below
commit adac832308195e5bd8364ee5238c7474f3e51c7d
Author: Marat Gubaidullin <ma...@talismancloud.io>
AuthorDate: Wed Dec 27 12:12:20 2023 -0500
Fix #951
---
.../apache/camel/karavan/api/ProjectResource.java | 25 ++++-
.../src/main/webui/src/api/KaravanApi.tsx | 5 +-
.../src/main/webui/src/api/ProjectService.ts | 4 +-
.../main/webui/src/projects/DeleteProjectModal.tsx | 30 ++---
.../webui/src/templates/CreateProjectModal.tsx | 122 ---------------------
.../webui/src/templates/DeleteProjectModal.tsx | 70 ------------
.../src/main/webui/src/templates/TemplatesPage.tsx | 9 +-
7 files changed, 39 insertions(+), 226 deletions(-)
diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectResource.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectResource.java
index 6acc57f5..29541520 100644
--- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectResource.java
+++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectResource.java
@@ -25,6 +25,7 @@ import org.apache.camel.karavan.git.GitService;
import org.apache.camel.karavan.infinispan.InfinispanService;
import org.apache.camel.karavan.infinispan.model.CamelStatus;
import org.apache.camel.karavan.infinispan.model.CamelStatusValue;
+import org.apache.camel.karavan.infinispan.model.ContainerStatus;
import org.apache.camel.karavan.infinispan.model.Project;
import org.apache.camel.karavan.kubernetes.KubernetesService;
import org.apache.camel.karavan.service.ConfigService;
@@ -53,6 +54,15 @@ public class ProjectResource {
@Inject
GitService gitService;
+ @Inject
+ DevModeResource devModeResource;
+
+ @Inject
+ ContainerResource containerResource;
+
+ @Inject
+ InfrastructureResource infrastructureResource;
+
@Inject
ProjectService projectService;
@@ -88,12 +98,20 @@ public class ProjectResource {
@DELETE
@Produces(MediaType.APPLICATION_JSON)
@Path("/{project}")
- public void delete(@HeaderParam("username") String username,
- @PathParam("project") String project) throws Exception {
+ public void delete(@PathParam("project") String project, @QueryParam("deleteContainers") boolean deleteContainers) throws Exception {
String projectId = URLDecoder.decode(project, StandardCharsets.UTF_8);
+ if (deleteContainers) {
+ LOGGER.info("Deleting containers");
+ Response res1 = devModeResource.deleteDevMode(projectId, true);
+ Response res2 = containerResource.deleteContainer(projectId, ContainerStatus.ContainerType.devmode.name(), projectId);
+ Response res3 = containerResource.deleteContainer(projectId, ContainerStatus.ContainerType.project.name(), projectId);
+ LOGGER.info("Deleting deployments");
+ Response res4 = infrastructureResource.deleteDeployment(null, projectId);
+ }
gitService.deleteProject(projectId, infinispanService.getProjectFiles(projectId));
infinispanService.getProjectFiles(projectId).forEach(file -> infinispanService.deleteProjectFile(projectId, file.getName()));
infinispanService.deleteProject(projectId);
+ LOGGER.info("Project deleted");
}
@POST
@@ -113,8 +131,7 @@ public class ProjectResource {
@DELETE
@Produces(MediaType.APPLICATION_JSON)
@Path("/build/{env}/{buildName}")
- public Response deleteBuild(@HeaderParam("username") String username,
- @PathParam("env") String env, @PathParam("buildName") String buildName) {
+ public Response deleteBuild(@PathParam("env") String env, @PathParam("buildName") String buildName) {
buildName = URLDecoder.decode(buildName, StandardCharsets.UTF_8);
if (ConfigService.inKubernetes()) {
kubernetesService.deletePod(buildName);
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx b/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx
index 0d07f0da..70d34a60 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/api/KaravanApi.tsx
@@ -254,9 +254,8 @@ export class KaravanApi {
});
}
- static async deleteProject(project: Project, after: (res: AxiosResponse<any>) => void) {
- instance.delete('/api/project/' + encodeURI(project.projectId),
- {headers: {'username': 'cameleer'}})
+ static async deleteProject(project: Project, deleteContainers: boolean, after: (res: AxiosResponse<any>) => void) {
+ instance.delete('/api/project/' + encodeURI(project.projectId) + (deleteContainers ? '?deleteContainers=true' : ''))
.then(res => {
after(res);
}).catch(err => {
diff --git a/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts b/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
index 9f64e7f0..6f567937 100644
--- a/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
+++ b/karavan-web/karavan-app/src/main/webui/src/api/ProjectService.ts
@@ -225,8 +225,8 @@ export class ProjectService {
});
}
- public static deleteProject(project: Project) {
- KaravanApi.deleteProject(project, res => {
+ public static deleteProject(project: Project, deleteContainers?: boolean) {
+ KaravanApi.deleteProject(project, deleteContainers === true, res => {
if (res.status === 204) {
EventBus.sendAlert( 'Success', 'Project deleted', 'success');
ProjectService.refreshProjects();
diff --git a/karavan-web/karavan-app/src/main/webui/src/projects/DeleteProjectModal.tsx b/karavan-web/karavan-app/src/main/webui/src/projects/DeleteProjectModal.tsx
index 02bda7b1..574486cb 100644
--- a/karavan-web/karavan-app/src/main/webui/src/projects/DeleteProjectModal.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/projects/DeleteProjectModal.tsx
@@ -15,11 +15,11 @@
* limitations under the License.
*/
-import React from 'react';
+import React, {useState} from 'react';
import {
Button,
Modal,
- ModalVariant,
+ ModalVariant, Switch,
} from '@patternfly/react-core';
import '../designer/karavan.css';
import {useProjectStore} from "../api/ProjectStore";
@@ -28,20 +28,21 @@ import {ProjectService} from "../api/ProjectService";
export function DeleteProjectModal () {
const {project, operation} = useProjectStore();
+ const [deleteContainers, setDeleteContainers] = useState(false);
function closeModal () {
useProjectStore.setState({operation: "none"})
}
function confirmAndCloseModal () {
- ProjectService.deleteProject(project);
+ ProjectService.deleteProject(project, deleteContainers);
useProjectStore.setState({operation: "none"});
}
const isOpen= operation === "delete";
return (
<Modal
- title="Confirmation"
+ title="Project delete confirmation"
variant={ModalVariant.small}
isOpen={isOpen}
onClose={() => closeModal()}
@@ -51,20 +52,13 @@ export function DeleteProjectModal () {
onClick={e => closeModal()}>Cancel</Button>
]}
onEscapePress={e => closeModal()}>
- <div>{"Are you sure you want to delete the project " + project?.projectId + "?"}</div>
+ {/*<div>{"Are you sure you want to delete the project " + project?.projectId + "?"}</div>*/}
+ <Switch
+ label={"Delete container and/or deployments?"}
+ isChecked={deleteContainers}
+ onChange={(_, checked) => setDeleteContainers(checked)}
+ isReversed
+ />
</Modal>
- // }
- // {(this.state.isProjectDeploymentModalOpen === true) && <Modal
- // variant={ModalVariant.small}
- // isOpen={this.state.isProjectDeploymentModalOpen}
- // onClose={() => this.setState({ isProjectDeploymentModalOpen: false })}
- // onEscapePress={e => this.setState({ isProjectDeploymentModalOpen: false })}>
- // <div>
- // <Alert key={this.state.projectToDelete?.projectId} className="main-alert" variant="warning"
- // title={"Deployment is Running!!"} isInline={true} isPlain={true}>
- // {"Delete the deployment (" + this.state.projectToDelete?.projectId + ")" + " first."}
- // </Alert>
- // </div>
- // </Modal>
)
}
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/webui/src/templates/CreateProjectModal.tsx b/karavan-web/karavan-app/src/main/webui/src/templates/CreateProjectModal.tsx
deleted file mode 100644
index b6300be9..00000000
--- a/karavan-web/karavan-app/src/main/webui/src/templates/CreateProjectModal.tsx
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import React, {useState} from 'react';
-import {
- Button, Form, FormGroup, FormHelperText, HelperText, HelperTextItem,
- Modal,
- ModalVariant, TextInput, Text
-} from '@patternfly/react-core';
-import '../designer/karavan.css';
-import {useProjectStore} from "../api/ProjectStore";
-import {ProjectService} from "../api/ProjectService";
-import {Project} from "../api/ProjectModels";
-import {CamelUi} from "../designer/utils/CamelUi";
-import {EventBus} from "../designer/utils/EventBus";
-import {ProjectExistsError} from "../shared/error/ProjectExistsError";
-
-
-export function CreateProjectModal () {
-
- const {project, operation} = useProjectStore();
- const [name, setName] = useState('');
- const [description, setDescription] = useState('');
- const [projectId, setProjectId] = useState('');
- const [isValidationError, setIsValidationError] = useState(false);
-
- function cleanValues() {
- setName("");
- setDescription("");
- setProjectId("");
- }
-
- function closeModal() {
- useProjectStore.setState({operation: "none"});
- cleanValues();
- }
-
- async function handleFormSubmit() {
- setIsValidationError(false);
- const [ err, createdProject ] = operation !== 'copy' ?
- await ProjectService.createProject(new Project({name: name, description: description, projectId: projectId})) :
- await ProjectService.copyProject(project?.projectId, new Project({name: name, description: description, projectId: projectId}));
-
- if (createdProject !== null) {
- EventBus.sendAlert( 'Success', 'Project created', 'success');
- ProjectService.refreshProjectData(project.projectId);
- ProjectService.refreshProjects();
- useProjectStore.setState({operation: "none"});
- cleanValues();
- } else if (err !== null && err instanceof ProjectExistsError) {
- setIsValidationError(true);
- } else {
- operation !== 'copy' ?
- EventBus.sendAlert( 'Warning', 'Error when creating project:' + err?.message, 'warning') :
- EventBus.sendAlert( 'Warning', 'Error when copying project:' + err?.message, 'warning');
- }
- }
-
- function onKeyDown(event: React.KeyboardEvent<HTMLDivElement>): void {
- if (event.key === 'Enter' && name !== undefined && description !== undefined && projectId !== undefined) {
- handleFormSubmit();
- }
- }
-
- const isReady = projectId && name && description && !['templates', 'kamelets'].includes(projectId);
- return (
- <Modal
- title={operation !== 'copy' ? "Create new project" : "Copy project from " + project?.projectId}
- variant={ModalVariant.small}
- isOpen={["create", "copy"].includes(operation)}
- onClose={closeModal}
- onKeyDown={onKeyDown}
- actions={[
- <Button key="confirm" variant="primary" isDisabled={!isReady}
- onClick={handleFormSubmit}>Save</Button>,
- <Button key="cancel" variant="secondary" onClick={closeModal}>Cancel</Button>
- ]}
- className="new-project"
- >
- <Form isHorizontal={true} autoComplete="off">
- <FormGroup label="Name" fieldId="name" isRequired>
- <TextInput className="text-field" type="text" id="name" name="name"
- value={name}
- onChange={(_, e) => setName(e)}/>
- </FormGroup>
- <FormGroup label="Description" fieldId="description" isRequired>
- <TextInput className="text-field" type="text" id="description" name="description"
- value={description}
- onChange={(_, e) => setDescription(e)}/>
- </FormGroup>
- <FormGroup label="Project ID" fieldId="projectId" isRequired>
- <TextInput className="text-field" type="text" id="projectId" name="projectId"
- value={projectId}
- onFocus={e => setProjectId(projectId === '' ? CamelUi.nameFromTitle(name) : projectId)}
- onChange={(_, e) => setProjectId(CamelUi.nameFromTitle(e))}
- validated={isValidationError ? 'error' : 'default'}
- />
- {isValidationError && <Text style={{ color: 'red', fontStyle: 'italic'}}>Project ID must be unique</Text>}
- <FormHelperText>
- <HelperText>
- <HelperTextItem>Unique project name</HelperTextItem>
- </HelperText>
- </FormHelperText>
- </FormGroup>
- </Form>
- </Modal>
- )
-}
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/webui/src/templates/DeleteProjectModal.tsx b/karavan-web/karavan-app/src/main/webui/src/templates/DeleteProjectModal.tsx
deleted file mode 100644
index 02bda7b1..00000000
--- a/karavan-web/karavan-app/src/main/webui/src/templates/DeleteProjectModal.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import React from 'react';
-import {
- Button,
- Modal,
- ModalVariant,
-} from '@patternfly/react-core';
-import '../designer/karavan.css';
-import {useProjectStore} from "../api/ProjectStore";
-import {ProjectService} from "../api/ProjectService";
-
-export function DeleteProjectModal () {
-
- const {project, operation} = useProjectStore();
-
- function closeModal () {
- useProjectStore.setState({operation: "none"})
- }
-
- function confirmAndCloseModal () {
- ProjectService.deleteProject(project);
- useProjectStore.setState({operation: "none"});
- }
-
- const isOpen= operation === "delete";
- return (
- <Modal
- title="Confirmation"
- variant={ModalVariant.small}
- isOpen={isOpen}
- onClose={() => closeModal()}
- actions={[
- <Button key="confirm" variant="primary" onClick={e => confirmAndCloseModal()}>Delete</Button>,
- <Button key="cancel" variant="link"
- onClick={e => closeModal()}>Cancel</Button>
- ]}
- onEscapePress={e => closeModal()}>
- <div>{"Are you sure you want to delete the project " + project?.projectId + "?"}</div>
- </Modal>
- // }
- // {(this.state.isProjectDeploymentModalOpen === true) && <Modal
- // variant={ModalVariant.small}
- // isOpen={this.state.isProjectDeploymentModalOpen}
- // onClose={() => this.setState({ isProjectDeploymentModalOpen: false })}
- // onEscapePress={e => this.setState({ isProjectDeploymentModalOpen: false })}>
- // <div>
- // <Alert key={this.state.projectToDelete?.projectId} className="main-alert" variant="warning"
- // title={"Deployment is Running!!"} isInline={true} isPlain={true}>
- // {"Delete the deployment (" + this.state.projectToDelete?.projectId + ")" + " first."}
- // </Alert>
- // </div>
- // </Modal>
- )
-}
\ No newline at end of file
diff --git a/karavan-web/karavan-app/src/main/webui/src/templates/TemplatesPage.tsx b/karavan-web/karavan-app/src/main/webui/src/templates/TemplatesPage.tsx
index ee6c7063..96588eab 100644
--- a/karavan-web/karavan-app/src/main/webui/src/templates/TemplatesPage.tsx
+++ b/karavan-web/karavan-app/src/main/webui/src/templates/TemplatesPage.tsx
@@ -45,17 +45,14 @@ import {
} from '@patternfly/react-table/deprecated';
import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
import {TemplatesTableRow} from "./TemplatesTableRow";
-import {DeleteProjectModal} from "./DeleteProjectModal";
-import {CreateProjectModal} from "./CreateProjectModal";
-import {useProjectsStore, useProjectStore} from "../api/ProjectStore";
+import {useProjectsStore} from "../api/ProjectStore";
import {MainToolbar} from "../designer/MainToolbar";
-import {Project, ProjectType} from "../api/ProjectModels";
+import {ProjectType} from "../api/ProjectModels";
import {shallow} from "zustand/shallow";
export function TemplatesPage () {
const [projects] = useProjectsStore((state) => [state.projects], shallow)
- const [operation] = useProjectStore((state) => [state.operation], shallow)
const [filter, setFilter] = useState<string>('');
function getTools() {
@@ -126,8 +123,6 @@ export function TemplatesPage () {
<PageSection isFilled className="kamelets-page">
{getProjectsTable()}
</PageSection>
- {["create", "copy"].includes(operation) && <CreateProjectModal/>}
- {["delete"].includes(operation) && <DeleteProjectModal/>}
</PageSection>
)