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
commit 4efc7d34b68ecd91df4f2d3b183e409dd2d0c4c7 Author: Marat Gubaidullin <[email protected]> AuthorDate: Fri May 10 15:26:23 2024 -0400 Fix #1274 --- .../apache/camel/karavan/api/BuildResource.java | 4 - .../apache/camel/karavan/api/ImagesResource.java | 8 +- .../camel/karavan/kubernetes/PodEventHandler.java | 3 + .../camel/karavan/model/ContainerStatus.java | 10 ++ .../org/apache/camel/karavan/shared/Constants.java | 1 + .../src/main/webui/src/api/ProjectModels.ts | 1 + .../main/webui/src/project/builder/BuildPanel.tsx | 11 +- .../webui/src/project/container/ContainerPanel.tsx | 119 ++++++++++++++++----- .../src/project/container/DeploymentPanel.tsx | 1 + .../main/webui/src/project/files/FilesToolbar.tsx | 4 +- karavan-app/src/main/webui/src/util/StringUtils.ts | 4 + 11 files changed, 123 insertions(+), 43 deletions(-) diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/api/BuildResource.java b/karavan-app/src/main/java/org/apache/camel/karavan/api/BuildResource.java index ce865511..03cb30e1 100644 --- a/karavan-app/src/main/java/org/apache/camel/karavan/api/BuildResource.java +++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/BuildResource.java @@ -24,7 +24,6 @@ import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.apache.camel.karavan.service.KaravanCacheService; -import org.apache.camel.karavan.code.CodeService; import org.apache.camel.karavan.kubernetes.KubernetesService; @Path("/ui/build") @@ -36,9 +35,6 @@ public class BuildResource { @Inject KubernetesService kubernetesService; - @Inject - CodeService codeService; - @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/api/ImagesResource.java b/karavan-app/src/main/java/org/apache/camel/karavan/api/ImagesResource.java index dc4ab97d..e39c9728 100644 --- a/karavan-app/src/main/java/org/apache/camel/karavan/api/ImagesResource.java +++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/ImagesResource.java @@ -46,14 +46,12 @@ public class ImagesResource { @GET @Produces(MediaType.APPLICATION_JSON) @Path("/{projectId}") - public List<String> getImagesForProject(@HeaderParam("username") String username, - @PathParam("projectId") String projectId) { - - RegistryConfig registryConfig = registryService.getRegistryConfig(); - String pattern = registryConfig.getGroup() + "/" + projectId; + public List<String> getImagesForProject(@PathParam("projectId") String projectId) { if (ConfigService.inKubernetes()) { return List.of(); } else { + RegistryConfig registryConfig = registryService.getRegistryConfig(); + String pattern = registryConfig.getGroup() + "/" + projectId; return dockerService.getImages() .stream().filter(s -> s.contains(pattern)).sorted(Comparator.reverseOrder()).toList(); } diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/PodEventHandler.java b/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/PodEventHandler.java index c59a3eb1..54ff7016 100644 --- a/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/PodEventHandler.java +++ b/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/PodEventHandler.java @@ -96,6 +96,7 @@ public class PodEventHandler implements ResourceEventHandler<Pod> { String camel = deployment != null ? deployment : pod.getMetadata().getLabels().get(LABEL_KUBERNETES_RUNTIME); String runtime = deployment != null ? deployment : pod.getMetadata().getLabels().get(LABEL_CAMEL_RUNTIME); String type = pod.getMetadata().getLabels().get(LABEL_TYPE); + String commit = pod.getMetadata().getAnnotations().get(ANNOTATION_COMMIT); ContainerStatus.ContainerType containerType = deployment != null ? ContainerStatus.ContainerType.project : (type != null ? ContainerStatus.ContainerType.valueOf(type) : ContainerStatus.ContainerType.unknown); @@ -123,6 +124,8 @@ public class PodEventHandler implements ResourceEventHandler<Pod> { requestMemory + " / " + limitMemory, requestCpu + " / " + limitCpu, creationTimestamp); + status.setImage(pod.getSpec().getContainers().get(0).getImage()); + status.setCommit(commit); status.setContainerId(pod.getMetadata().getName()); status.setPhase(pod.getStatus().getPhase()); status.setPodIP(pod.getStatus().getPodIP()); diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/model/ContainerStatus.java b/karavan-app/src/main/java/org/apache/camel/karavan/model/ContainerStatus.java index 13b578f8..ec8620fb 100644 --- a/karavan-app/src/main/java/org/apache/camel/karavan/model/ContainerStatus.java +++ b/karavan-app/src/main/java/org/apache/camel/karavan/model/ContainerStatus.java @@ -72,6 +72,7 @@ public class ContainerStatus implements Serializable { String initDate; String podIP; String camelRuntime; + String commit; public ContainerStatus(String projectId, String containerName, String containerId, String image, List<ContainerPort> ports, String env, ContainerType type, String memoryInfo, String cpuInfo, String created, String finished, List<Command> commands, String state, String phase, Boolean codeLoaded, Boolean inTransit, String initDate, String podIP, String camelRuntime) { this.projectId = projectId; @@ -325,6 +326,14 @@ public class ContainerStatus implements Serializable { this.camelRuntime = camelRuntime; } + public String getCommit() { + return commit; + } + + public void setCommit(String commit) { + this.commit = commit; + } + @Override public String toString() { return "ContainerStatus{" + @@ -346,6 +355,7 @@ public class ContainerStatus implements Serializable { ", inTransit=" + inTransit + ", initDate='" + initDate + '\'' + ", podIP='" + podIP + '\'' + + ", commit='" + commit + '\'' + '}'; } } diff --git a/karavan-app/src/main/java/org/apache/camel/karavan/shared/Constants.java b/karavan-app/src/main/java/org/apache/camel/karavan/shared/Constants.java index ff6152d9..c2b9c1ac 100644 --- a/karavan-app/src/main/java/org/apache/camel/karavan/shared/Constants.java +++ b/karavan-app/src/main/java/org/apache/camel/karavan/shared/Constants.java @@ -27,6 +27,7 @@ public class Constants { public static final String LABEL_CAMEL_RUNTIME = "org.apache.camel.karavan/runtime"; public static final String LABEL_KUBERNETES_RUNTIME = "app.kubernetes.io/runtime"; public static final String LABEL_TAG = "org.apache.camel.karavan/tag"; + public static final String ANNOTATION_COMMIT = "jkube.eclipse.org/git-commit"; public static final String BUILDER_SUFFIX = "-builder"; diff --git a/karavan-app/src/main/webui/src/api/ProjectModels.ts b/karavan-app/src/main/webui/src/api/ProjectModels.ts index 6b701562..569b191d 100644 --- a/karavan-app/src/main/webui/src/api/ProjectModels.ts +++ b/karavan-app/src/main/webui/src/api/ProjectModels.ts @@ -100,6 +100,7 @@ export class ContainerStatus { created: string = ''; finished: string = ''; image: string = ''; + commit: string = ''; ports: ContainerPort [] = []; commands: string [] = []; inTransit: boolean = false; diff --git a/karavan-app/src/main/webui/src/project/builder/BuildPanel.tsx b/karavan-app/src/main/webui/src/project/builder/BuildPanel.tsx index 4d931115..0acc40ea 100644 --- a/karavan-app/src/main/webui/src/project/builder/BuildPanel.tsx +++ b/karavan-app/src/main/webui/src/project/builder/BuildPanel.tsx @@ -15,7 +15,7 @@ * limitations under the License. */ -import React, {useEffect, useState} from 'react'; +import React, {useState} from 'react'; import { Button, DescriptionList, @@ -31,13 +31,13 @@ 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 TagIcon from "@patternfly/react-icons/dist/esm/icons/tag-icon"; import DeleteIcon from "@patternfly/react-icons/dist/esm/icons/times-circle-icon"; -import {useAppConfigStore, useLogStore, useProjectStore, useStatusesStore} from "../../api/ProjectStore"; +import { useLogStore, useProjectStore, useStatusesStore} from "../../api/ProjectStore"; import {shallow} from "zustand/shallow"; import {EventBus} from "../../designer/utils/EventBus"; +import {getShortCommit} from "../../util/StringUtils"; export function BuildPanel () { - const [config] = useAppConfigStore((state) => [state.config], shallow) const [project] = useProjectStore((s) => [s.project], shallow); const [setShowLog] = useLogStore((s) => [s.setShowLog], shallow); const [containers, deployments, camels] = @@ -46,7 +46,7 @@ export function BuildPanel () { const [isBuilding, setIsBuilding] = useState<boolean>(false); const [showDeleteConfirmation, setShowDeleteConfirmation] = useState<boolean>(false); const [deleteEntityName, setDeleteEntityName] = useState<string>(); - const [tag, setTag] = useState<string>('dev'); + const [tag, setTag] = useState<string>(getShortCommit(project.lastCommit)); function deleteEntity() { const buildName = getBuildName(); @@ -78,7 +78,7 @@ export function BuildPanel () { <Button isLoading={isBuilding ? true : undefined} isDisabled={isBuilding || isRunning || isPushing} size="sm" - variant="secondary" + variant="primary" className="project-button dev-action-button" icon={!isBuilding ? <BuildIcon/> : <div></div>} onClick={e => build()}> @@ -127,6 +127,7 @@ export function BuildPanel () { : "No builder"} {status !== undefined && <Tooltip content={"Delete build"}> <Button + isDanger icon={<DeleteIcon/>} className="labeled-button dev-action-button" variant="link" onClick={e => { diff --git a/karavan-app/src/main/webui/src/project/container/ContainerPanel.tsx b/karavan-app/src/main/webui/src/project/container/ContainerPanel.tsx index 05a2505d..fa7cf101 100644 --- a/karavan-app/src/main/webui/src/project/container/ContainerPanel.tsx +++ b/karavan-app/src/main/webui/src/project/container/ContainerPanel.tsx @@ -6,7 +6,7 @@ * (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 + * 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, @@ -19,10 +19,13 @@ import React, {useState} from 'react'; import { Badge, Button, + Card, + CardBody, + CardHeader, Flex, FlexItem, Label, - LabelGroup, Modal, + Modal, ClipboardCopy, } from '@patternfly/react-core'; import '../../designer/karavan.css'; import UpIcon from "@patternfly/react-icons/dist/esm/icons/running-icon"; @@ -32,14 +35,17 @@ import {shallow} from "zustand/shallow"; import {ContainerStatus} from "../../api/ProjectModels"; import {ContainerButtons} from "./ContainerButtons"; import DeleteIcon from "@patternfly/react-icons/dist/esm/icons/times-circle-icon"; +import ImageIcon from "@patternfly/react-icons/dist/esm/icons/cube-icon"; +import CommitIcon from "@patternfly/react-icons/dist/esm/icons/code-branch-icon"; import {KaravanApi} from "../../api/KaravanApi"; import {EventBus} from "../../designer/utils/EventBus"; +import {getShortCommit} from "../../util/StringUtils"; interface Props { env: string, } -export function ContainerPanel (props: Props) { +export function ContainerPanel(props: Props) { const {config} = useAppConfigStore(); const [project] = useProjectStore((s) => [s.project], shallow); @@ -80,10 +86,8 @@ export function ContainerPanel (props: Props) { </Modal>) } - function getBadge(cs: ContainerStatus) { - return config.infrastructure === 'kubernetes' - ? <Badge isRead>{cs.phase}</Badge> - : <Badge isRead>{cs.state}</Badge> + function getStatusBadge(cs: ContainerStatus) { + return config.infrastructure === 'kubernetes' ? cs.phase : cs.state } const env = props.env; @@ -95,32 +99,93 @@ export function ContainerPanel (props: Props) { alignItems={{default: "alignItemsFlexStart"}}> <FlexItem> {conts.length === 0 && <Label icon={<DownIcon/>} color={"grey"}>No pods</Label>} - <LabelGroup numLabels={10} isVertical> - {conts.map((cs: ContainerStatus) => { + <Flex direction={{default: 'column'}}> + {conts.map((cs: ContainerStatus, index) => { const ready = cs.state === 'running'; return ( - <Label icon={ready ? <UpIcon/> : <DownIcon/>} color={ready ? "green" : "grey"}> - <Button variant="link" className="dev-action-button labeled-button" - onClick={e => { - setShowLog(true, 'container', cs.containerName); - }}> - {cs.containerName} - </Button> - {getBadge(cs)} - <Button - icon={<DeleteIcon/>} - className="labeled-button" - variant="link" onClick={e => { - setShowDeleteConfirmation(true); - setDeleteEntityName(cs.containerName); - }}></Button> - </Label> + <Card isCompact isRounded isFlat isPlain> + <CardBody> + <Flex justifyContent={{default: 'justifyContentSpaceBetween'}}> + <Label icon={ready ? <UpIcon/> : <DownIcon/>} color={ready ? "green" : "grey"}> + <Button variant="link" className="dev-action-button labeled-button" + onClick={e => { + setShowLog(true, 'container', cs.containerName); + }}> + {cs.containerName} + </Button> + <Badge isRead>{cs.type}</Badge> + </Label> + <Label icon={ready ? <UpIcon/> : <DownIcon/>} color={ready ? "green" : "grey"}> + {getStatusBadge(cs)} + </Label> + <Label icon={<ImageIcon/>} color={ready ? "green" : "grey"} variant='outline'> + Image: + <ClipboardCopy hoverTip="Copy" clickTip="Copied" variant="inline-compact" style={{backgroundColor: 'transparent'}}> + {cs.image} + </ClipboardCopy> + </Label> + <Label icon={<CommitIcon/>} color={ready ? "green" : "grey"} variant='outline'> + Commit: + <ClipboardCopy hoverTip="Copy" clickTip="Copied" variant="inline-compact" style={{backgroundColor: 'transparent'}}> + {getShortCommit(cs.commit)} + </ClipboardCopy> + </Label> + <Button + isDanger + icon={<DeleteIcon/>} + className="labeled-button" + variant="link" onClick={e => { + setShowDeleteConfirmation(true); + setDeleteEntityName(cs.containerName); + }}></Button> + </Flex> + </CardBody> + </Card> + + // <Flex> + // <Label icon={ready ? <UpIcon/> : <DownIcon/>} color={ready ? "green" : "grey"}> + // <Button variant="link" className="dev-action-button labeled-button" + // onClick={e => { + // setShowLog(true, 'container', cs.containerName); + // }}> + // {cs.containerName} + // </Button> + // <Label icon=<ImageIcon/> isCompact> + // <Button variant="link" className="dev-action-button labeled-button" + // onClick={e => { + // setShowLog(true, 'container', cs.containerName); + // }}> + // Image: {cs.image} + // </Button> + // </Label> + // {getBadge(cs)} + // <Button + // icon={<DeleteIcon/>} + // className="labeled-button" + // variant="link" onClick={e => { + // setShowDeleteConfirmation(true); + // setDeleteEntityName(cs.containerName); + // }} + // > + // </Button> + // </Label> + // <Label icon=<ImageIcon/> color={ready ? "green" : "grey"}> + // <Button variant="link" className="dev-action-button labeled-button" + // onClick={e => { + // setShowLog(true, 'container', cs.containerName); + // }}> + // {cs.image} + // </Button> + // </Label> + // </Flex> ) } )} - </LabelGroup> + </Flex> + </FlexItem> + <FlexItem> + {env === "dev" && config.infrastructure !== 'kubernetes' && <ContainerButtons env={env}/>} </FlexItem> - <FlexItem>{env === "dev" && config.infrastructure !== 'kubernetes' && <ContainerButtons env={env}/>}</FlexItem> {showDeleteConfirmation && getDeleteConfirmation()} </Flex> ) diff --git a/karavan-app/src/main/webui/src/project/container/DeploymentPanel.tsx b/karavan-app/src/main/webui/src/project/container/DeploymentPanel.tsx index 61c1e2b3..53367bd0 100644 --- a/karavan-app/src/main/webui/src/project/container/DeploymentPanel.tsx +++ b/karavan-app/src/main/webui/src/project/container/DeploymentPanel.tsx @@ -140,6 +140,7 @@ export function DeploymentPanel (props: Props) { </Tooltip> } <Button + isDanger icon={<DeleteIcon/>} className="labeled-button" variant="link" onClick={e => { diff --git a/karavan-app/src/main/webui/src/project/files/FilesToolbar.tsx b/karavan-app/src/main/webui/src/project/files/FilesToolbar.tsx index 7f50fa10..28f0855c 100644 --- a/karavan-app/src/main/webui/src/project/files/FilesToolbar.tsx +++ b/karavan-app/src/main/webui/src/project/files/FilesToolbar.tsx @@ -37,7 +37,7 @@ import {useFilesStore, useFileStore, useProjectStore} from "../../api/ProjectSto import {shallow} from "zustand/shallow"; import {ProjectService} from "../../api/ProjectService"; import PushIcon from "@patternfly/react-icons/dist/esm/icons/code-branch-icon"; -import {isEmpty} from "../../util/StringUtils"; +import {getShortCommit, isEmpty} from "../../util/StringUtils"; export function FileToolbar () { @@ -157,7 +157,7 @@ export function FileToolbar () { <FlexItem> <Tooltip content={commit} position={TooltipPosition.bottom}> <Label - color={color}>{commit ? commit?.substring(0, 18) : "-"}</Label> + color={color}>{getShortCommit(commit)}</Label> </Tooltip> </FlexItem>} </Flex> diff --git a/karavan-app/src/main/webui/src/util/StringUtils.ts b/karavan-app/src/main/webui/src/util/StringUtils.ts index 3aef90ab..ced025d4 100644 --- a/karavan-app/src/main/webui/src/util/StringUtils.ts +++ b/karavan-app/src/main/webui/src/util/StringUtils.ts @@ -19,4 +19,8 @@ export function splitByBraces(input: string): string[] { export function getPathParams(input: string): string[] { return splitByBraces(input).filter(p => p.startsWith('{')).map(p => p.replace('{', '').replace('}', '')); +} + +export function getShortCommit(commitId: string): string { + return commitId ? commitId?.substring(0, 7) : "-"; } \ No newline at end of file
