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 7a9c2cb Saas feature24 (#406)
7a9c2cb is described below
commit 7a9c2cb3e46f24d52d2d920cd05b31b36d705761
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Fri Jul 1 14:57:10 2022 -0400
Saas feature24 (#406)
* UI improvements
* Delete pods and deployments
---
.../camel/karavan/api/KubernetesResource.java | 27 ++++
.../apache/camel/karavan/model/KaravanGroup.java | 35 +++++
.../apache/camel/karavan/model/KaravanUser.java | 67 +++++++++
.../camel/karavan/service/KubernetesService.java | 22 +++
.../src/main/resources/application.properties | 3 +
karavan-app/src/main/webapp/src/api/KaravanApi.tsx | 20 +++
karavan-app/src/main/webapp/src/index.css | 22 ++-
.../src/main/webapp/src/projects/ProjectHeader.tsx | 5 +-
.../src/main/webapp/src/projects/ProjectInfo.tsx | 150 +++++++++++++++------
.../src/main/webapp/src/projects/ProjectPage.tsx | 17 ++-
.../main/webapp/src/projects/PropertiesTable.tsx | 1 +
karavan-builder/openshift/karavan-secret.yaml | 2 +
12 files changed, 326 insertions(+), 45 deletions(-)
diff --git
a/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
b/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
index fe36476..22ee3a5 100644
---
a/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
+++
b/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
@@ -24,6 +24,7 @@ import org.jboss.logging.Logger;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
@@ -112,4 +113,30 @@ public class KubernetesResource {
}
return Response.noContent().build();
}
+
+ @DELETE
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/deployment/{environment}/{name}")
+ public Response deleteDeployment(@HeaderParam("username") String username,
@PathParam("environment") String environment, @PathParam("name") String name)
throws Exception {
+ Optional<KaravanConfiguration.Environment> env =
configuration.environments().stream().filter(e ->
e.name().equals(environment)).findFirst();
+ if (env.isPresent()) {
+ kubernetesService.deleteDeployment(name, env.get().namespace());
+ return Response.ok().build();
+ }
+ return Response.noContent().build();
+ }
+
+ @DELETE
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Path("/pod/{environment}/{name}")
+ public Response deletePod(@HeaderParam("username") String username,
@PathParam("environment") String environment, @PathParam("name") String name)
throws Exception {
+ Optional<KaravanConfiguration.Environment> env =
configuration.environments().stream().filter(e ->
e.name().equals(environment)).findFirst();
+ if (env.isPresent()) {
+ kubernetesService.deletePod(name, env.get().namespace());
+ return Response.ok().build();
+ }
+ return Response.noContent().build();
+ }
}
\ No newline at end of file
diff --git
a/karavan-app/src/main/java/org/apache/camel/karavan/model/KaravanGroup.java
b/karavan-app/src/main/java/org/apache/camel/karavan/model/KaravanGroup.java
new file mode 100644
index 0000000..e871a25
--- /dev/null
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/KaravanGroup.java
@@ -0,0 +1,35 @@
+package org.apache.camel.karavan.model;
+
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+
+import java.util.List;
+
+public class KaravanGroup {
+ @ProtoField(number = 1)
+ String name;
+ @ProtoField(number = 2)
+ List<String> users;
+
+ @ProtoFactory
+ public KaravanGroup(String name, List<String> users) {
+ this.name = name;
+ this.users = users;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List<String> getUsers() {
+ return users;
+ }
+
+ public void setUsers(List<String> users) {
+ this.users = users;
+ }
+}
diff --git
a/karavan-app/src/main/java/org/apache/camel/karavan/model/KaravanUser.java
b/karavan-app/src/main/java/org/apache/camel/karavan/model/KaravanUser.java
new file mode 100644
index 0000000..d116ad8
--- /dev/null
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/KaravanUser.java
@@ -0,0 +1,67 @@
+package org.apache.camel.karavan.model;
+
+import org.infinispan.protostream.annotations.ProtoFactory;
+import org.infinispan.protostream.annotations.ProtoField;
+
+public class KaravanUser {
+ @ProtoField(number = 1)
+ String username;
+ @ProtoField(number = 2)
+ String password;
+ @ProtoField(number = 3)
+ String firstName;
+ @ProtoField(number = 4)
+ String lastName;
+ @ProtoField(number = 5)
+ boolean showTour;
+
+
+ @ProtoFactory
+ public KaravanUser(String username, String password, String firstName,
String lastName, boolean showTour) {
+ this.username = username;
+ this.password = password;
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.showTour = showTour;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public boolean isShowTour() {
+ return showTour;
+ }
+
+ public void setShowTour(boolean showTour) {
+ this.showTour = showTour;
+ }
+}
diff --git
a/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
b/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
index dfcda42..23a868e 100644
---
a/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
+++
b/karavan-app/src/main/java/org/apache/camel/karavan/service/KubernetesService.java
@@ -20,6 +20,8 @@ import io.fabric8.kubernetes.api.model.ObjectMeta;
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.api.model.Secret;
+import io.fabric8.kubernetes.client.Config;
+import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.openshift.api.model.DeploymentConfig;
@@ -32,6 +34,7 @@ import io.fabric8.tekton.pipeline.v1beta1.PipelineRun;
import io.fabric8.tekton.pipeline.v1beta1.PipelineRunBuilder;
import io.fabric8.tekton.pipeline.v1beta1.PipelineRunSpec;
import io.fabric8.tekton.pipeline.v1beta1.PipelineRunSpecBuilder;
+import io.quarkus.kubernetes.client.runtime.KubernetesClientBuildConfig;
import io.smallrye.mutiny.tuples.Tuple2;
import io.smallrye.mutiny.tuples.Tuple3;
import org.apache.camel.karavan.model.DeploymentStatus;
@@ -150,6 +153,25 @@ public class KubernetesService {
}
}
+ public void deleteDeployment(String name, String namespace) {
+ try {
+ if (kubernetesClient().isAdaptable(OpenShiftClient.class)) {
+
openshiftClient().deploymentConfigs().inNamespace(namespace).withName(name).delete();
+ } else {
+ // TODO: Implement Deployment for Kubernetes/Minikube
+ }
+ } catch (Exception ex) {
+ LOGGER.error(ex.getMessage());
+ }
+ }
+
+ public void deletePod(String name, String namespace) {
+ try {
+
kubernetesClient().pods().inNamespace(namespace).withName(name).delete();
+ } catch (Exception ex) {
+ LOGGER.error(ex.getMessage());
+ }
+ }
public DeploymentStatus getDeploymentStatus(String name, String namespace)
{
try {
diff --git a/karavan-app/src/main/resources/application.properties
b/karavan-app/src/main/resources/application.properties
index 0c0680a..4808ab5 100644
--- a/karavan-app/src/main/resources/application.properties
+++ b/karavan-app/src/main/resources/application.properties
@@ -67,6 +67,9 @@ quarkus.kubernetes.deployment-target=openshift
quarkus.kubernetes-config.enabled=true
quarkus.kubernetes-config.secrets.enabled=true
+quarkus.kubernetes-client.connection-timeout=2000
+quarkus.kubernetes-client.request-timeout=10000
+
quarkus.openshift.route.expose=true
quarkus.openshift.name=karavan
quarkus.openshift.namespace=karavan
diff --git a/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
b/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
index b834fd7..b1868e7 100644
--- a/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
+++ b/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
@@ -167,6 +167,26 @@ export const KaravanApi = {
});
},
+ deleteDeployment: async (environment: string, name: string, after: (res:
AxiosResponse<any>) => void) => {
+ axios.delete('/kubernetes/deployment/' + environment + '/' + name,
+ {headers: {'Accept': 'application/json', 'Content-Type':
'application/json', 'username': 'cameleer'}})
+ .then(res => {
+ after(res);
+ }).catch(err => {
+ after(err);
+ });
+ },
+
+ deletePod: async (environment: string, name: string, after: (res:
AxiosResponse<any>) => void) => {
+ axios.delete('/kubernetes/pod/' + environment + '/' + name,
+ {headers: {'Accept': 'application/json', 'Content-Type':
'application/json', 'username': 'cameleer'}})
+ .then(res => {
+ after(res);
+ }).catch(err => {
+ after(err);
+ });
+ },
+
getKameletNames: async (after: (names: []) => void) => {
axios.get('/kamelet',
{headers: {'Accept': 'application/json'}})
diff --git a/karavan-app/src/main/webapp/src/index.css
b/karavan-app/src/main/webapp/src/index.css
index c95c4b9..1378930 100644
--- a/karavan-app/src/main/webapp/src/index.css
+++ b/karavan-app/src/main/webapp/src/index.css
@@ -13,6 +13,7 @@
.karavan .pf-c-page__main {
overflow: hidden;
}
+
.logo,
.logo svg {
height: 48px;
@@ -90,18 +91,37 @@
font-weight: initial;
}
+/*Projects*/
+
+.karavan .tools .pf-c-button {
+ font-size: 14px;
+}
+
.karavan .projects-page .icon {
height: 16px;
width: 16px;
margin: auto;
}
+.karavan .projects-page .pf-m-link {
+ font-size: 14px;
+}
+
.karavan .project-page .project-page-section {
background-color: white;
}
-.karavan .project-page .project-details {
+.karavan .project-page .pf-c-description-list__group {
+ min-height: 30px;
+}
+
+.karavan .project-page .pf-c-tabs__link,
+.karavan .project-page .pf-m-link {
+ font-size: 14px;
+}
+.karavan .project-page .pf-c-description-list__text {
+ font-size: 15px;
}
.karavan .project-page .table {
diff --git a/karavan-app/src/main/webapp/src/projects/ProjectHeader.tsx
b/karavan-app/src/main/webapp/src/projects/ProjectHeader.tsx
index 3e26968..2391c0e 100644
--- a/karavan-app/src/main/webapp/src/projects/ProjectHeader.tsx
+++ b/karavan-app/src/main/webapp/src/projects/ProjectHeader.tsx
@@ -7,7 +7,7 @@ import {
PageSection,
} from '@patternfly/react-core';
import '../designer/karavan.css';
-import {Project, ProjectFile, ProjectStatus} from "../models/ProjectModels";
+import {Project, ProjectStatus} from "../models/ProjectModels";
import {ProjectDashboard} from "./ProjectDashboard";
import {ProjectInfo} from "./ProjectInfo";
@@ -15,6 +15,7 @@ interface Props {
project: Project,
config: any,
showLog: (type: 'container' | 'pipeline', name: string, environment:
string) => void
+ deleteEntity: (type: 'pod' | 'deployment', name: string, environment:
string) => void
}
interface State {
@@ -42,7 +43,7 @@ export class ProjectHeader extends React.Component<Props,
State> {
</FlexItem>
<FlexItem>
<PageSection padding={{default: "padding"}}>
- {tab === 'details' && <ProjectInfo
project={this.props.project} config={this.props.config}
showLog={this.props.showLog}/>}
+ {tab === 'details' && <ProjectInfo
project={this.props.project} config={this.props.config}
deleteEntity={this.props.deleteEntity} showLog={this.props.showLog}/>}
{tab === 'dashboard' && <ProjectDashboard
project={this.props.project} config={this.props.config}/>}
</PageSection>
</FlexItem>
diff --git a/karavan-app/src/main/webapp/src/projects/ProjectInfo.tsx
b/karavan-app/src/main/webapp/src/projects/ProjectInfo.tsx
index 97737c8..cbc4820 100644
--- a/karavan-app/src/main/webapp/src/projects/ProjectInfo.tsx
+++ b/karavan-app/src/main/webapp/src/projects/ProjectInfo.tsx
@@ -8,7 +8,7 @@ import {
DescriptionListGroup,
DescriptionListDescription,
Card,
- CardBody, Spinner, Tooltip, Flex, FlexItem, Divider, LabelGroup, Label
+ CardBody, Spinner, Tooltip, Flex, FlexItem, Divider, LabelGroup, Label,
Modal
} from '@patternfly/react-core';
import '../designer/karavan.css';
import {KaravanApi} from "../api/KaravanApi";
@@ -19,11 +19,13 @@ import PushIcon from
"@patternfly/react-icons/dist/esm/icons/code-branch-icon";
import UpIcon from "@patternfly/react-icons/dist/esm/icons/check-circle-icon";
import DownIcon from
"@patternfly/react-icons/dist/esm/icons/error-circle-o-icon";
import ClockIcon from "@patternfly/react-icons/dist/esm/icons/clock-icon";
+import DeleteIcon from
"@patternfly/react-icons/dist/esm/icons/times-circle-icon";
interface Props {
project: Project,
config: any,
showLog: (type: 'container' | 'pipeline', name: string, environment:
string) => void
+ deleteEntity: (type: 'pod' | 'deployment', name: string, environment:
string) => void
}
interface State {
@@ -32,6 +34,10 @@ interface State {
isPushing: boolean,
isBuilding: boolean,
isRolling: boolean,
+ showDeleteConfirmation: boolean,
+ deleteEntity?: 'pod' | 'deployment',
+ deleteEntityName?: string,
+ deleteEntityEnv?: string,
environments: string[],
environment: string,
key?: string,
@@ -44,6 +50,7 @@ export class ProjectInfo extends React.Component<Props,
State> {
isPushing: false,
isBuilding: false,
isRolling: false,
+ showDeleteConfirmation: false,
environments: this.props.config.environments &&
Array.isArray(this.props.config.environments)
? Array.from(this.props.config.environments) : [],
environment: this.props.config.environments &&
Array.isArray(this.props.config.environments)
@@ -160,6 +167,22 @@ export class ProjectInfo extends React.Component<Props,
State> {
</Tooltip>)
}
+ deleteDeploymentButton = (env: string) => {
+ return (<Tooltip content="Delete deployment" position={"left"}>
+ <Button isSmall variant="secondary"
+ className="project-button"
+ icon={<DeleteIcon/>}
+ onClick={e => this.setState({
+ showDeleteConfirmation: true,
+ deleteEntity: "deployment",
+ deleteEntityEnv: env,
+ deleteEntityName: this.state.project?.projectId
+ })}>
+ {"Delete"}
+ </Button>
+ </Tooltip>)
+ }
+
getCommitPanel() {
const {project} = this.state;
return (
@@ -187,9 +210,9 @@ export class ProjectInfo extends React.Component<Props,
State> {
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
- <DescriptionListTerm>Replicas</DescriptionListTerm>
+ <DescriptionListTerm>Deployment</DescriptionListTerm>
<DescriptionListDescription>
- {deploymentStatus &&
this.getReplicasPanel(deploymentStatus)}
+ {deploymentStatus &&
this.getReplicasPanel(deploymentStatus, env)}
</DescriptionListDescription>
</DescriptionListGroup>
<DescriptionListGroup>
@@ -207,50 +230,76 @@ export class ProjectInfo extends React.Component<Props,
State> {
</DescriptionList>)
}
- getReplicasPanel(deploymentStatus: DeploymentStatus) {
+ getReplicasPanel(deploymentStatus: DeploymentStatus, env: string) {
const ok = (deploymentStatus && deploymentStatus?.readyReplicas > 0
&& deploymentStatus.unavailableReplicas === 0
&& deploymentStatus?.replicas === deploymentStatus?.readyReplicas)
return (
+ <Flex justifyContent={{default: "justifyContentSpaceBetween"}}
alignItems={{default: "alignItemsCenter"}}>
+ <FlexItem>
<LabelGroup numLabels={3}>
<Tooltip content={"Ready Replicas / Replicas"}
position={"left"}>
- <Label icon={<UpIcon/>}
- color={ok ? "green" :
"grey"}>{deploymentStatus.readyReplicas + " / " +
deploymentStatus.replicas}</Label>
+ <Label icon={ok ? <UpIcon/> : <DownIcon/>}
+ color={ok ? "green" : "grey"}>{"Replicas: " +
deploymentStatus.readyReplicas + " / " + deploymentStatus.replicas}</Label>
</Tooltip>
{deploymentStatus.unavailableReplicas > 0 &&
<Tooltip content={"Unavailable replicas"}
position={"right"}>
- <Label icon={<UpIcon/>}
color={"red"}>{deploymentStatus.unavailableReplicas}</Label>
+ <Label icon={<DownIcon/>}
color={"red"}>{deploymentStatus.unavailableReplicas}</Label>
</Tooltip>
}
</LabelGroup>
+ </FlexItem>
+ <FlexItem>{env === "dev" &&
this.deleteDeploymentButton(env)}</FlexItem>
+ </Flex>
)
}
getPodsPanel(deploymentStatus: DeploymentStatus, env: string) {
const podStatuses = deploymentStatus.podStatuses;
return (
- <Flex justifyContent={{default: "justifyContentSpaceBetween"}}
alignItems={{default: "alignItemsCenter"}}>
- <FlexItem>
- <LabelGroup numLabels={3}>
- {podStatuses.map(pod => {
- const running = pod.started && pod.ready;
- return (
- <Tooltip content={running ? "Running" :
pod.reason}>
- <Label icon={running ? <UpIcon/> :
<DownIcon/>} color={running ? "green" : "red"} >
- <Button variant="link" onClick={e =>
this.props.showLog?.call(this, 'container', pod.name, env)}>
- {pod.name}
- </Button>
- </Label>
- </Tooltip>
+ <Flex justifyContent={{default: "justifyContentSpaceBetween"}}
alignItems={{default: "alignItemsCenter"}}>
+ <FlexItem>
+ <LabelGroup numLabels={3}>
+ {(podStatuses === undefined || podStatuses.length ===
0) && <Label icon={<DownIcon/>} color={"grey"}>No pods</Label>}
+ {podStatuses.map(pod => {
+ const running = pod.started && pod.ready;
+ return (
+ <Tooltip content={running ? "Running" :
pod.reason}>
+ <Label icon={running ? <UpIcon/> :
<DownIcon/>} color={running ? "green" : "red"}>
+ <Button variant="link"
+ onClick={e =>
this.props.showLog?.call(this, 'container', pod.name, env)}>
+ {pod.name}
+ </Button>
+ <Tooltip content={"Delete Pod"}>
+ <Button icon={<DeleteIcon/>}
variant="link" onClick={e => this.setState({
+ showDeleteConfirmation:
true,
+ deleteEntity: "pod",
+ deleteEntityEnv: env,
+ deleteEntityName: pod.name
+ })}></Button>
+ </Tooltip>
+ </Label>
+ </Tooltip>
+ )
+ }
)}
- )}
- </LabelGroup>
- </FlexItem>
- <FlexItem>{env === "dev" && this.rolloutButton()}</FlexItem>
- </Flex>
+ </LabelGroup>
+ </FlexItem>
+ <FlexItem>{env === "dev" && this.rolloutButton()}</FlexItem>
+ </Flex>
)
}
+ getStatusColor(status?: string) {
+ if (status === 'UP') return 'green';
+ if (status === 'DOWN') return 'red';
+ if (status === 'NA') return 'blue';
+ }
+
+ getStatusIcon(status?: string) {
+ return (status === 'UP' ? <UpIcon/> : <DownIcon/>)
+ }
+
getHealthPanel(env: string) {
const status = this.state.status?.statuses.find(s => s.environment ===
env)
const registryStatus = status?.registryStatus;
@@ -260,11 +309,13 @@ export class ProjectInfo extends React.Component<Props,
State> {
const contextVersion = status?.contextVersion;
return (
<LabelGroup numLabels={5}>
- {contextVersion && <Label icon={<UpIcon/>}
color={contextStatus === "UP" ? "green" : "grey"}>{contextVersion}</Label>}
- <Label icon={<UpIcon/>} color={contextStatus === "UP" ?
"green" : "grey"}>Context</Label>
- <Label icon={<UpIcon/>} color={consumersStatus === "UP" ?
"green" : "grey"}>Consumers</Label>
- <Label icon={<UpIcon/>} color={routesStatus === "UP" ? "green"
: "grey"}>Routes</Label>
- <Label icon={<UpIcon/>} color={registryStatus === "UP" ?
"green" : "grey"}>Registry</Label>
+ {contextVersion &&
+ <Label icon={this.getStatusIcon(contextStatus)}
color={this.getStatusColor(contextStatus)}>{contextVersion}</Label>}
+ <Label icon={this.getStatusIcon(contextStatus)}
color={this.getStatusColor(contextStatus)}>Context</Label>
+ <Label icon={this.getStatusIcon(consumersStatus)}
color={this.getStatusColor(consumersStatus)}>Consumers</Label>
+ <Label icon={this.getStatusIcon(routesStatus)}
color={this.getStatusColor(routesStatus)}>Routes</Label>
+ {registryStatus !== 'NA' &&
+ <Label icon={this.getStatusIcon(registryStatus)}
color={this.getStatusColor(registryStatus)}>Registry</Label>}
</LabelGroup>
)
}
@@ -274,24 +325,25 @@ export class ProjectInfo extends React.Component<Props,
State> {
const pipeline = status?.lastPipelineRun;
const pipelineResult = status?.lastPipelineRunResult;
const lastPipelineRunTime = status?.lastPipelineRunTime;
+ const showTime = lastPipelineRunTime && lastPipelineRunTime > 0;
const isRunning = pipelineResult === 'Running';
const isFailed = pipelineResult === 'Failed';
const isSucceeded = pipelineResult === 'Succeeded';
const color = isSucceeded ? "green" : (isFailed ? "red" : (isRunning ?
"blue" : "grey"))
+ const icon = isSucceeded ? <UpIcon/> : <DownIcon/>
return (
<Flex justifyContent={{default: "justifyContentSpaceBetween"}}
alignItems={{default: "alignItemsCenter"}}>
<FlexItem>
<Tooltip content={pipelineResult} position={"right"}>
<LabelGroup numLabels={2}>
- <Label icon={isRunning ? <Spinner isSVG
diameter="16px"/> : <UpIcon/>} color={color}>
+ <Label icon={isRunning ? <Spinner isSVG
diameter="16px"/> : icon} color={color}>
<Button variant="link" onClick={e => {
if (pipeline)
this.props.showLog?.call(this, 'pipeline', pipeline, env);
}}>
{pipeline ? pipeline : "-"}
</Button>
</Label>
- {lastPipelineRunTime && lastPipelineRunTime > 0 &&
- <Label icon={<ClockIcon/>}
color={color}>{lastPipelineRunTime + "s"}</Label>}
+ {showTime && <Label icon={<ClockIcon/>}
color={color}>{lastPipelineRunTime + "s"}</Label>}
</LabelGroup>
</Tooltip>
</FlexItem>
@@ -300,14 +352,6 @@ export class ProjectInfo extends React.Component<Props,
State> {
)
}
- isUp(env: string): boolean {
- if (this.state.status) {
- return this.state.status.statuses.find(s => s.environment ===
env)?.status === 'UP';
- } else {
- return false;
- }
- }
-
getProjectDescription() {
const {project} = this.state;
return (<DescriptionList isHorizontal>
@@ -332,6 +376,29 @@ export class ProjectInfo extends React.Component<Props,
State> {
</DescriptionList>)
}
+ getDeleteConfirmation() {
+ const {deleteEntity, deleteEntityEnv, deleteEntityName} = this.state;
+ return (<Modal
+ className="modal-delete"
+ title="Confirmation"
+ isOpen={this.state.showDeleteConfirmation}
+ onClose={() => this.setState({showDeleteConfirmation: false})}
+ actions={[
+ <Button key="confirm" variant="primary" onClick={e => {
+ if (deleteEntityEnv && deleteEntityName && deleteEntity) {
+ this.props.deleteEntity?.call(this, deleteEntity,
deleteEntityName, deleteEntityEnv);
+ this.setState({showDeleteConfirmation: false});
+ }
+ }}>Delete
+ </Button>,
+ <Button key="cancel" variant="link"
+ onClick={e => this.setState({showDeleteConfirmation:
false})}>Cancel</Button>
+ ]}
+ onEscapePress={e => this.setState({showDeleteConfirmation:
false})}>
+ <div>{"Delete " + deleteEntity + " " + deleteEntityName +
"?"}</div>
+ </Modal>)
+ }
+
render() {
return (
<Card>
@@ -348,6 +415,7 @@ export class ProjectInfo extends React.Component<Props,
State> {
</FlexItem>
</Flex>
</CardBody>
+ {this.state.showDeleteConfirmation &&
this.getDeleteConfirmation()}
</Card>
)
}
diff --git a/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx
b/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx
index d9386f7..3c9e0c2 100644
--- a/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx
+++ b/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx
@@ -318,6 +318,21 @@ export class ProjectPage extends React.Component<Props,
State> {
}
+ deleteEntity = (type: 'pod' | 'deployment', name: string, environment:
string) => {
+ switch (type) {
+ case "deployment": KaravanApi.deleteDeployment(environment, name,
(res: any) => {
+ if (Array.isArray(res) && Array.from(res).length > 0)
+ this.onRefresh();
+ });
+ break;
+ case "pod": KaravanApi.deletePod(environment, name, (res: any) => {
+ if (Array.isArray(res) && Array.from(res).length > 0)
+ this.onRefresh();
+ });
+ break;
+ }
+ }
+
getLogView = () => {
const file = this.state.file;
return (
@@ -371,7 +386,7 @@ export class ProjectPage extends React.Component<Props,
State> {
{file === undefined &&
<PageSection isFilled className="kamelets-page
project-page-section"
padding={{default: file !== undefined ?
'noPadding' : 'noPadding'}}>
- {<ProjectHeader project={this.props.project}
config={this.props.config} showLog={this.showPipelineLog}/>}
+ {<ProjectHeader project={this.props.project}
config={this.props.config} showLog={this.showPipelineLog}
deleteEntity={this.deleteEntity}/>}
{this.getProjectFiles()}
</PageSection>}
{showDesigner && this.getDesigner()}
diff --git a/karavan-app/src/main/webapp/src/projects/PropertiesTable.tsx
b/karavan-app/src/main/webapp/src/projects/PropertiesTable.tsx
index 199fde7..eaa5b23 100644
--- a/karavan-app/src/main/webapp/src/projects/PropertiesTable.tsx
+++ b/karavan-app/src/main/webapp/src/projects/PropertiesTable.tsx
@@ -129,6 +129,7 @@ export class PropertiesTable extends React.Component<Props,
State> {
)})}
</Tbody>
</TableComposable>}
+ {this.state.showDeleteConfirmation &&
this.getDeleteConfirmation()}
<Panel>
<PanelMain>
<PanelMainBody>
diff --git a/karavan-builder/openshift/karavan-secret.yaml
b/karavan-builder/openshift/karavan-secret.yaml
index 948ed26..ac5a3a6 100644
--- a/karavan-builder/openshift/karavan-secret.yaml
+++ b/karavan-builder/openshift/karavan-secret.yaml
@@ -4,6 +4,8 @@ metadata:
name: karavan
type: Opaque
stringData:
+ master-user: admin
+ master-password: karavan
git-repository: https://github.com/mgubaidullin/karavan-demo.git
git-password: demo
git-username: demo