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 a26b5660eacddfd4bd2b547f7bfad957b437b70d Author: Marat Gubaidullin <marat.gubaidul...@gmail.com> AuthorDate: Sat Jul 22 20:54:17 2023 -0400 Working prototype #817 --- .github/workflows/app.yml | 17 +++++-- .../workflows/{builder.yml => docker-builder.yml} | 0 .../workflows/{runner.yml => docker-devmode.yml} | 2 +- .github/workflows/headless.yml | 56 ++++++++++++++++++++++ .../apache/camel/karavan/api/DevModeResource.java | 10 ++-- .../apache/camel/karavan/api/KameletResources.java | 14 +++--- .../camel/karavan/docker/DockerEventListener.java | 5 +- .../apache/camel/karavan/docker/DockerService.java | 2 +- .../karavan/kubernetes/KubernetesService.java | 4 +- .../apache/camel/karavan/service/EventService.java | 31 +----------- .../camel/karavan/service/KaravanService.java | 37 ++++++++++++-- .../org/apache/camel/karavan/shared/EventType.java | 3 -- .../karavan-app/src/main/webui/src/Main.tsx | 4 +- .../src/main/webui/src/api/KaravanApi.tsx | 6 +-- .../src/main/webui/src/api/ProjectModels.ts | 12 +++-- .../src/main/webui/src/api/ProjectService.ts | 10 ++-- .../src/main/webui/src/api/ProjectStore.ts | 6 +-- .../src/main/webui/src/project/DevModeToolbar.tsx | 22 +++++++-- .../webui/src/project/dashboard/DashboardTab.tsx | 8 ++-- .../dashboard/{InfoPod.tsx => InfoContainer.tsx} | 23 ++++----- .../webui/src/project/pipeline/ProjectStatus.tsx | 18 +++---- .../src/main/webui/src/project/trace/TraceTab.tsx | 1 + .../camel/karavan/headless/CamelService.java | 2 +- .../camel/karavan/headless/EventService.java | 6 --- .../karavan/infinispan/InfinispanService.java | 2 + .../karavan/infinispan/model/ContainerStatus.java | 4 +- 26 files changed, 191 insertions(+), 114 deletions(-) diff --git a/.github/workflows/app.yml b/.github/workflows/app.yml index 5eb961ae..ee3361ee 100644 --- a/.github/workflows/app.yml +++ b/.github/workflows/app.yml @@ -1,9 +1,9 @@ -name: cloud-native app +name: web app on: push: branches: [ main ] - paths: ['karavan-web/karavan-app/**', 'karavan-core/**', 'karavan-designer/**'] + paths: ['karavan-web/karavan-app/**', 'karavan-web/karavan-infinispan/**', 'karavan-core/**', 'karavan-designer/**'] workflow_dispatch: pull_request: branches: [ main ] @@ -51,7 +51,14 @@ jobs: working-directory: ./karavan/karavan-core run: npm ci - # Build Karavan cloud app with public access + # Build Karavan infinispan module + - name: Build infinispan module + working-directory: ./karavan/karavan-web/karavan-infinispan + run: | + mvn package + if: ${{ github.ref == 'refs/heads/main' }} + + # Build Karavan web app with public access - name: Build application public working-directory: ./karavan/karavan-web/karavan-app run: | @@ -64,7 +71,7 @@ jobs: -Dquarkus.container-image.password=${{ secrets.GITHUB_TOKEN }} if: ${{ github.ref == 'refs/heads/main' }} - # Build Karavan cloud app with basic authorization + # Build Karavan web app with basic authorization - name: Build application basic auth working-directory: ./karavan/karavan-web/karavan-app run: | @@ -77,7 +84,7 @@ jobs: -Dquarkus.container-image.password=${{ secrets.GITHUB_TOKEN }} if: ${{ github.ref == 'refs/heads/main' }} - # Build Karavan cloud app with oidc authorization + # Build Karavan web app with oidc authorization - name: Build application oidc working-directory: ./karavan/karavan-web/karavan-app run: | diff --git a/.github/workflows/builder.yml b/.github/workflows/docker-builder.yml similarity index 100% rename from .github/workflows/builder.yml rename to .github/workflows/docker-builder.yml diff --git a/.github/workflows/runner.yml b/.github/workflows/docker-devmode.yml similarity index 97% rename from .github/workflows/runner.yml rename to .github/workflows/docker-devmode.yml index af8d4a80..695bdacc 100644 --- a/.github/workflows/runner.yml +++ b/.github/workflows/docker-devmode.yml @@ -1,4 +1,4 @@ -name: runner image +name: DevMode image on: push: diff --git a/.github/workflows/headless.yml b/.github/workflows/headless.yml new file mode 100644 index 00000000..66bc013c --- /dev/null +++ b/.github/workflows/headless.yml @@ -0,0 +1,56 @@ +name: headless service + +on: + push: + branches: [ main ] + paths: ['karavan-web/karavan-headless/**', 'karavan-web/karavan-infinispan/**'] + workflow_dispatch: + pull_request: + branches: [ main ] + +env: + TAG: 3.21.1-SNAPSHOT + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout Karavan + uses: actions/checkout@v3 + with: + path: karavan + + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + distribution: adopt + java-version: 11 + + - name: Cache local Maven repository + uses: actions/cache@v3 + with: + path: | + ~/.m2/repository + !~/.m2/repository/org/apache/camel/karavan + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-maven- + + # Build Karavan infinispan module + - name: Build infinispan module + working-directory: ./karavan/karavan-web/karavan-infinispan + run: | + mvn package + if: ${{ github.ref == 'refs/heads/main' }} + + # Build Karavan headless + - name: Build headless service + working-directory: ./karavan/karavan-web/karavan-headless + run: | + mvn package -DskipTests \ + -Dquarkus.container-image.build=true \ + -Dquarkus.container-image.push=true \ + -Dquarkus.container-image.image=ghcr.io/${GITHUB_REPOSITORY}-headless:${{ env.TAG }} \ + -Dquarkus.container-image.username=${{ github.actor }} \ + -Dquarkus.container-image.password=${{ secrets.GITHUB_TOKEN }} + if: ${{ github.ref == 'refs/heads/main' }} + diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/DevModeResource.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/DevModeResource.java index c3d6184c..13edee0e 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/DevModeResource.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/DevModeResource.java @@ -127,9 +127,13 @@ public class DevModeResource { @Produces(MediaType.APPLICATION_JSON) @Path("/status/{projectId}/{statusName}") public Response getCamelStatusByProjectAndEnv(@PathParam("projectId") String projectId, @PathParam("statusName") String statusName) { - CamelStatus status = infinispanService.getCamelStatus(projectId, environment, statusName); - if (status != null) { - return Response.ok(status).build(); + if (infinispanService.isReady()) { + CamelStatus status = infinispanService.getCamelStatus(projectId, environment, statusName); + if (status != null) { + return Response.ok(status).build(); + } else { + return Response.noContent().build(); + } } else { return Response.noContent().build(); } diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/KameletResources.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/KameletResources.java index ba8ccab1..ac2b8a67 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/KameletResources.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/api/KameletResources.java @@ -45,12 +45,14 @@ public class KameletResources { @Produces(MediaType.TEXT_PLAIN) public String getKamelets() { StringBuilder kamelets = new StringBuilder(codeService.getResourceFile("/kamelets/kamelets.yaml")); - List<ProjectFile> custom = infinispanService.getProjectFiles(Project.Type.kamelets.name()); - if (custom.size() > 0) { - kamelets.append("\n---\n"); - kamelets.append(custom.stream() - .map(ProjectFile::getCode) - .collect(Collectors.joining("\n---\n"))); + if (infinispanService.isReady()) { + List<ProjectFile> custom = infinispanService.getProjectFiles(Project.Type.kamelets.name()); + if (custom.size() > 0) { + kamelets.append("\n---\n"); + kamelets.append(custom.stream() + .map(ProjectFile::getCode) + .collect(Collectors.joining("\n---\n"))); + } } return kamelets.toString(); } diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java index 4a9bd265..0ee8000a 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerEventListener.java @@ -16,6 +16,7 @@ import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import java.io.Closeable; import java.io.IOException; +import java.time.Instant; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -92,14 +93,16 @@ public class DockerEventListener implements ResultCallback<Event> { List<Integer> ports = Arrays.stream(container.getPorts()).map(ContainerPort::getPrivatePort).filter(Objects::nonNull).collect(Collectors.toList()); ContainerStatus.Lifecycle lc = event.getStatus().equals("create") ? ContainerStatus.Lifecycle.init : ContainerStatus.Lifecycle.ready; ContainerStatus.CType type = getCtype(container.getLabels()); + String created = Instant.ofEpochSecond(container.getCreated()).toString(); ContainerStatus ci = infinispanService.getContainerStatus(name, environment, name); if (ci == null) { - ci = ContainerStatus.createWithId(name, environment, container.getId(), ports, type, lc); + ci = ContainerStatus.createWithId(name, environment, container.getId(), ports, type, lc, created); } else { ci.setContainerId(container.getId()); ci.setPorts(ports); ci.setType(type); ci.setLifeCycle(lc); + ci.setCreated(created); } infinispanService.saveContainerStatus(ci); } diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java index 76ed2c62..3b380749 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/docker/DockerService.java @@ -171,7 +171,7 @@ public class DockerService { .withDriver("bridge") .withInternal(false) .withAttachable(true).exec(); - LOGGER.info("Network created: {}" + res); + LOGGER.info("Network created: " + NETWORK_NAME); } else { LOGGER.info("Network already exists with name: " + NETWORK_NAME); } diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java index e1f231b2..92971460 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/kubernetes/KubernetesService.java @@ -95,7 +95,7 @@ public class KubernetesService implements HealthCheck { public void startInformers(String data) { try { - stopInformers(null); + stopInformers(); LOGGER.info("Starting Kubernetes Informers"); SharedIndexInformer<Deployment> deploymentInformer = kubernetesClient().apps().deployments().inNamespace(getNamespace()) @@ -138,7 +138,7 @@ public class KubernetesService implements HealthCheck { } } - public void stopInformers(String data) { + public void stopInformers() { LOGGER.info("Stop Kubernetes Informers"); informers.forEach(SharedIndexInformer::close); informers.clear(); diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/EventService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/EventService.java index 06888997..fe48ad1c 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/EventService.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/EventService.java @@ -21,7 +21,6 @@ import static org.apache.camel.karavan.shared.EventType.*; public class EventService { private static final Logger LOGGER = Logger.getLogger(EventService.class.getName()); - private static final String HEALTHY = "healthy"; @Inject InfinispanService infinispanService; @@ -44,27 +43,9 @@ public class EventService { @Inject EventBus bus; - @ConsumeEvent(value = START_KARAVAN, blocking = true, ordered = true) - void startKaravan(String data) { - if (!ConfigService.inKubernetes()) { - if (ConfigService.isHeadless()) { - LOGGER.info("Starting Karavan Headless in Docker"); - } else { - LOGGER.info("Starting Karavan with Docker"); - dockerService.createNetwork(); - dockerService.startListeners(); - dockerService.startInfinispan(); - dockerService.checkInfinispanHealth(); - } - } else { - LOGGER.info("Starting Karavan in " + (kubernetesService.isOpenshift() ? "OpenShift" : "Kubernetes")); - startServices(HEALTHY); - } - } - @ConsumeEvent(value = INFINISPAN_STARTED, blocking = true, ordered = true) void startServices(String infinispanHealth) { - if (infinispanHealth.equals(HEALTHY)) { + if (infinispanHealth.equals(InfinispanService.HEALTHY_STATUS)) { infinispanService.start(false); infinispanService.clearAllStatuses(); if (!ConfigService.inKubernetes()) { @@ -87,16 +68,6 @@ public class EventService { } } - @ConsumeEvent(value = STOP_INFRASTRUCTURE_LISTENERS, blocking = true) - void stopInfrastructureListeners(String data) throws IOException { - LOGGER.info("Stop Infrastructure Listeners"); - if (ConfigService.inKubernetes()) { - kubernetesService.stopInformers(data); - } else { - dockerService.stopListeners(); - } - } - @ConsumeEvent(value = IMPORT_PROJECTS, blocking = true) public void importProjects(String data) { projectService.importProjects(data); diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java index 12a1c409..2f5aa7ad 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/service/KaravanService.java @@ -19,31 +19,58 @@ package org.apache.camel.karavan.service; import io.quarkus.runtime.ShutdownEvent; import io.quarkus.runtime.StartupEvent; import io.vertx.core.eventbus.EventBus; +import org.apache.camel.karavan.docker.DockerService; +import org.apache.camel.karavan.infinispan.InfinispanService; +import org.apache.camel.karavan.kubernetes.KubernetesService; +import org.apache.camel.karavan.shared.ConfigService; import org.apache.camel.karavan.shared.EventType; import org.jboss.logging.Logger; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; import javax.inject.Inject; - -import static org.apache.camel.karavan.shared.EventType.START_KARAVAN; +import java.io.IOException; @ApplicationScoped public class KaravanService { private static final Logger LOGGER = Logger.getLogger(KaravanService.class.getName()); + @Inject + KubernetesService kubernetesService; + + @Inject + DockerService dockerService; + @Inject EventBus bus; void onStart(@Observes StartupEvent ev) { LOGGER.info("Starting Karavan"); - bus.publish(START_KARAVAN, ""); + if (!ConfigService.inKubernetes()) { + if (ConfigService.isHeadless()) { + LOGGER.info("Starting Karavan Headless in Docker"); + } else { + LOGGER.info("Starting Karavan with Docker"); + dockerService.createNetwork(); + dockerService.startListeners(); + dockerService.startInfinispan(); + dockerService.checkInfinispanHealth(); + } + } else { + LOGGER.info("Starting Karavan in " + (kubernetesService.isOpenshift() ? "OpenShift" : "Kubernetes")); + bus.publish(EventType.INFINISPAN_STARTED, InfinispanService.HEALTHY_STATUS); + } } - void onStop(@Observes ShutdownEvent ev) { + void onStop(@Observes ShutdownEvent ev) throws IOException { + LOGGER.info("Stop Listeners"); + if (ConfigService.inKubernetes()) { + kubernetesService.stopInformers(); + } else { + dockerService.stopListeners(); + } LOGGER.info("Stop Karavan"); - bus.publish(EventType.STOP_INFRASTRUCTURE_LISTENERS, ""); } } diff --git a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/shared/EventType.java b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/shared/EventType.java index 37bdf5d3..ac89a948 100644 --- a/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/shared/EventType.java +++ b/karavan-web/karavan-app/src/main/java/org/apache/camel/karavan/shared/EventType.java @@ -2,11 +2,8 @@ package org.apache.camel.karavan.shared; public class EventType { - public static final String START_KARAVAN = "START_KARAVAN"; - // Start Kubernetes or Docker event Listeners public static final String START_INFRASTRUCTURE_LISTENERS = "START_INFRASTRUCTURE_LISTENERS"; - public static final String STOP_INFRASTRUCTURE_LISTENERS = "STOP_INFRASTRUCTURE_LISTENERS"; // Import projects from Git repository public static final String IMPORT_PROJECTS = "IMPORT_PROJECTS"; diff --git a/karavan-web/karavan-app/src/main/webui/src/Main.tsx b/karavan-web/karavan-app/src/main/webui/src/Main.tsx index a5a14a9b..a9f46911 100644 --- a/karavan-web/karavan-app/src/main/webui/src/Main.tsx +++ b/karavan-web/karavan-app/src/main/webui/src/Main.tsx @@ -26,7 +26,7 @@ import {MainLogin} from "./MainLogin"; import {DashboardPage} from "./dashboard/DashboardPage"; import {Subscription} from "rxjs"; import {ProjectEventBus} from "./api/ProjectEventBus"; -import {AppConfig, PodStatus, Project, ToastMessage} from "./api/ProjectModels"; +import {AppConfig, ContainerStatus, Project, ToastMessage} from "./api/ProjectModels"; import {ProjectPage} from "./project/ProjectPage"; import {useAppConfigStore, useDevModeStore, useFileStore, useProjectStore} from "./api/ProjectStore"; import {Notification} from "./Notification"; @@ -179,7 +179,7 @@ export class Main extends React.Component<Props, State> { onClick={event => { useFileStore.setState({operation:'none', file: undefined}) useDevModeStore.setState({podName: undefined, status: "none"}) - useProjectStore.setState({podStatus: new PodStatus({}), }) + useProjectStore.setState({containerStatus: new ContainerStatus({}), }) this.setState({pageId: page.pageId}); }} /> 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 d9290f72..6515e83a 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 @@ -4,7 +4,7 @@ import { CamelStatus, DeploymentStatus, PipelineStatus, - PodStatus, + ContainerStatus, Project, ProjectFile, ProjectType, ServiceStatus } from "./ProjectModels"; @@ -303,7 +303,7 @@ export class KaravanApi { }); } - static async getDevModePodStatus(projectId: string, after: (res: AxiosResponse<PodStatus>) => void) { + static async getDevModePodStatus(projectId: string, after: (res: AxiosResponse<ContainerStatus>) => void) { instance.get('/api/devmode/pod/' + projectId) .then(res => { after(res); @@ -441,7 +441,7 @@ export class KaravanApi { }); } - static async getProjectPodStatuses(project: string, env: string, after: (statuses: PodStatus[]) => void) { + static async getProjectPodStatuses(project: string, env: string, after: (statuses: ContainerStatus[]) => void) { instance.get('/api/infrastructure/pod/' + project + "/" + env) .then(res => { if (res.status === 200) { diff --git a/karavan-web/karavan-app/src/main/webui/src/api/ProjectModels.ts b/karavan-web/karavan-app/src/main/webui/src/api/ProjectModels.ts index 3c758d3e..73be3256 100644 --- a/karavan-web/karavan-app/src/main/webui/src/api/ProjectModels.ts +++ b/karavan-web/karavan-app/src/main/webui/src/api/ProjectModels.ts @@ -67,18 +67,20 @@ export class ServiceStatus { type: string = ''; } -export class PodStatus { - name: string = ''; - ready: boolean = false; +export class ContainerStatus { + containerName: string = ''; + lifeCycle: string = ''; deployment: string = ''; projectId: string = ''; env: string = ''; - inDevMode: boolean = false; + type: string = ''; memoryInfo: string = ''; cpuInfo: string = ''; created: string = ''; + image: string = ''; + ports: [] = []; - public constructor(init?: Partial<PodStatus>) { + public constructor(init?: Partial<ContainerStatus>) { Object.assign(this, init); } } 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 a83e8327..4e6621cc 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 @@ -1,5 +1,5 @@ import {KaravanApi} from "./KaravanApi"; -import {DeploymentStatus, PodStatus, Project, ProjectFile, ToastMessage} from "./ProjectModels"; +import {DeploymentStatus, ContainerStatus, Project, ProjectFile, ToastMessage} from "./ProjectModels"; import {TemplateApi} from "karavan-core/lib/api/TemplateApi"; import {InfrastructureAPI} from "../designer/utils/InfrastructureAPI"; import {unstable_batchedUpdates} from 'react-dom' @@ -57,20 +57,20 @@ export class ProjectService { if (res.status === 200) { unstable_batchedUpdates(() => { const podStatus = res.data; - if (useDevModeStore.getState().podName !== podStatus.name){ - useDevModeStore.setState({podName: podStatus.name}) + if (useDevModeStore.getState().podName !== podStatus.containerName){ + useDevModeStore.setState({podName: podStatus.containerName}) } if (useDevModeStore.getState().status !== "running"){ useDevModeStore.setState({status: "running"}) useLogStore.setState({isRunning: true}) } - useProjectStore.setState({podStatus: res.data}); + useProjectStore.setState({containerStatus: res.data}); }) } else { unstable_batchedUpdates(() => { if (useDevModeStore.getState().status !== 'none') { useDevModeStore.setState({status: "none", podName: undefined}) - useProjectStore.setState({podStatus: new PodStatus()}); + useProjectStore.setState({containerStatus: new ContainerStatus()}); } }) } diff --git a/karavan-web/karavan-app/src/main/webui/src/api/ProjectStore.ts b/karavan-web/karavan-app/src/main/webui/src/api/ProjectStore.ts index d04fa3c2..9a891b3e 100644 --- a/karavan-web/karavan-app/src/main/webui/src/api/ProjectStore.ts +++ b/karavan-web/karavan-app/src/main/webui/src/api/ProjectStore.ts @@ -16,7 +16,7 @@ */ import {create} from 'zustand' -import {AppConfig, DeploymentStatus, PodStatus, Project, ProjectFile, ToastMessage} from "./ProjectModels"; +import {AppConfig, DeploymentStatus, ContainerStatus, Project, ProjectFile, ToastMessage} from "./ProjectModels"; import {ProjectEventBus} from "./ProjectEventBus"; import {unstable_batchedUpdates} from "react-dom"; import {bottom} from "@patternfly/react-core/helpers/Popper/thirdparty/popper-core"; @@ -60,7 +60,7 @@ interface ProjectState { project: Project; isPushing: boolean, isRunning: boolean, - podStatus: PodStatus, + containerStatus: ContainerStatus, operation: "create" | "select" | "delete" | "none" | "copy"; setProject: (project: Project, operation: "create" | "select" | "delete"| "none" | "copy") => void; setOperation: (o: "create" | "select" | "delete"| "none" | "copy") => void; @@ -71,7 +71,7 @@ export const useProjectStore = create<ProjectState>((set) => ({ operation: "none", isPushing: false, isRunning: false, - podStatus: new PodStatus(), + containerStatus: new ContainerStatus(), setProject: (project: Project, operation: "create" | "select" | "delete"| "none" | "copy") => { set((state: ProjectState) => ({ project: project, diff --git a/karavan-web/karavan-app/src/main/webui/src/project/DevModeToolbar.tsx b/karavan-web/karavan-app/src/main/webui/src/project/DevModeToolbar.tsx index 99bff60e..4f202b92 100644 --- a/karavan-web/karavan-app/src/main/webui/src/project/DevModeToolbar.tsx +++ b/karavan-web/karavan-app/src/main/webui/src/project/DevModeToolbar.tsx @@ -8,6 +8,7 @@ import {useDevModeStore, useLogStore, useProjectStore} from "../api/ProjectStore import {ProjectService} from "../api/ProjectService"; import {shallow} from "zustand/shallow"; 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"; interface Props { @@ -17,21 +18,34 @@ interface Props { export const DevModeToolbar = (props: Props) => { const [status] = useDevModeStore((state) => [state.status], shallow) - const [project,podStatus ] = useProjectStore((state) => [state.project, state.podStatus], shallow) + const [project,containerStatus ] = useProjectStore((state) => [state.project, state.containerStatus], shallow) const [verbose, setVerbose] = useState(false); + + function getColor() { + return getRunning() ? "green" : "grey"; + } + + function getRunning(): boolean { + return containerStatus.lifeCycle === 'ready'; + } + + function getIcon() { + return (getRunning() ? <UpIcon/> : <DownIcon/>) + } + const isRunning = status === "running"; const isStartingPod = status === "starting"; const isReloadingPod = status === "reloading"; const isDeletingPod = status === "deleting"; return (<Flex className="toolbar" direction={{default: "row"}} alignItems={{default: "alignItemsCenter"}}> {isRunning && <FlexItem> - <Label icon={<UpIcon/>} color={"green"}> + <Label icon={getIcon()} color={getColor()}> <Tooltip content={"Show log"} position={TooltipPosition.bottom}> <Button variant="link" onClick={e => - useLogStore.setState({showLog: true, type: 'container', podName: podStatus.name})}> - {podStatus.name} + useLogStore.setState({showLog: true, type: 'container', podName: containerStatus.containerName})}> + {containerStatus.containerName} </Button> </Tooltip> </Label> diff --git a/karavan-web/karavan-app/src/main/webui/src/project/dashboard/DashboardTab.tsx b/karavan-web/karavan-app/src/main/webui/src/project/dashboard/DashboardTab.tsx index 1831dd65..9aa0a0f8 100644 --- a/karavan-web/karavan-app/src/main/webui/src/project/dashboard/DashboardTab.tsx +++ b/karavan-web/karavan-app/src/main/webui/src/project/dashboard/DashboardTab.tsx @@ -20,7 +20,7 @@ import { CardBody, Flex, FlexItem, Divider, PageSection } from '@patternfly/react-core'; import '../../designer/karavan.css'; -import {InfoPod} from "./InfoPod"; +import {InfoContainer} from "./InfoContainer"; import {InfoContext} from "./InfoContext"; import {InfoMemory} from "./InfoMemory"; import {KaravanApi} from "../../api/KaravanApi"; @@ -28,7 +28,7 @@ import {useProjectStore} from "../../api/ProjectStore"; export const DashboardTab = () => { - const {project, podStatus} = useProjectStore(); + const {project, containerStatus} = useProjectStore(); const [memory, setMemory] = useState({}); const [jvm, setJvm] = useState({}); const [context, setContext] = useState({}); @@ -68,7 +68,7 @@ export const DashboardTab = () => { } function showConsole(): boolean { - return podStatus.ready; + return containerStatus.lifeCycle === 'ready'; } return ( @@ -78,7 +78,7 @@ export const DashboardTab = () => { <Flex direction={{default: "row"}} justifyContent={{default: "justifyContentSpaceBetween"}}> <FlexItem flex={{default: "flex_1"}}> - <InfoPod podStatus={podStatus}/> + <InfoContainer containerStatus={containerStatus}/> </FlexItem> <Divider orientation={{default: "vertical"}}/> <FlexItem flex={{default: "flex_1"}}> diff --git a/karavan-web/karavan-app/src/main/webui/src/project/dashboard/InfoPod.tsx b/karavan-web/karavan-app/src/main/webui/src/project/dashboard/InfoContainer.tsx similarity index 77% rename from karavan-web/karavan-app/src/main/webui/src/project/dashboard/InfoPod.tsx rename to karavan-web/karavan-app/src/main/webui/src/project/dashboard/InfoContainer.tsx index 5e544ac1..03bc5f9e 100644 --- a/karavan-web/karavan-app/src/main/webui/src/project/dashboard/InfoPod.tsx +++ b/karavan-web/karavan-app/src/main/webui/src/project/dashboard/InfoContainer.tsx @@ -1,25 +1,22 @@ import React from 'react'; import { - Button, DescriptionList, DescriptionListDescription, DescriptionListGroup, DescriptionListTerm, Label, - Tooltip } from '@patternfly/react-core'; import '../../designer/karavan.css'; import DownIcon from "@patternfly/react-icons/dist/esm/icons/error-circle-o-icon"; import UpIcon from "@patternfly/react-icons/dist/esm/icons/check-circle-icon"; -import {PodStatus} from "../../api/ProjectModels"; -import {useLogStore} from "../../api/ProjectStore"; +import {ContainerStatus} from "../../api/ProjectModels"; interface Props { - podStatus: PodStatus, + containerStatus: ContainerStatus, } -export const InfoPod = (props: Props) => { +export const InfoContainer = (props: Props) => { function getPodInfoLabel(info: string) { return ( @@ -38,40 +35,40 @@ export const InfoPod = (props: Props) => { } function getRunning(): boolean { - return props.podStatus.ready; + return props.containerStatus.lifeCycle === 'ready'; } - const podStatus = props.podStatus; + const containerStatus = props.containerStatus; return ( <DescriptionList isHorizontal> <DescriptionListGroup> <DescriptionListTerm>Pod</DescriptionListTerm> <DescriptionListDescription> - {getPodInfoLabel(podStatus.name)} + {getPodInfoLabel(containerStatus.containerName)} </DescriptionListDescription> </DescriptionListGroup> <DescriptionListGroup> <DescriptionListTerm>Status</DescriptionListTerm> <DescriptionListDescription> - {getPodInfoLabel(podStatus.ready ? "Ready" : "Not Ready")} + {getPodInfoLabel(containerStatus.lifeCycle)} </DescriptionListDescription> </DescriptionListGroup> <DescriptionListGroup> <DescriptionListTerm>CPU</DescriptionListTerm> <DescriptionListDescription> - {getPodInfoLabel(podStatus.cpuInfo)} + {getPodInfoLabel(containerStatus.cpuInfo)} </DescriptionListDescription> </DescriptionListGroup> <DescriptionListGroup> <DescriptionListTerm>Memory</DescriptionListTerm> <DescriptionListDescription> - {getPodInfoLabel(podStatus.memoryInfo)} + {getPodInfoLabel(containerStatus.memoryInfo)} </DescriptionListDescription> </DescriptionListGroup> <DescriptionListGroup> <DescriptionListTerm>Created</DescriptionListTerm> <DescriptionListDescription> - {getPodInfoLabel(podStatus.created)} + {getPodInfoLabel(containerStatus.created)} </DescriptionListDescription> </DescriptionListGroup> </DescriptionList> diff --git a/karavan-web/karavan-app/src/main/webui/src/project/pipeline/ProjectStatus.tsx b/karavan-web/karavan-app/src/main/webui/src/project/pipeline/ProjectStatus.tsx index 29e2b8a4..491a2b80 100644 --- a/karavan-web/karavan-app/src/main/webui/src/project/pipeline/ProjectStatus.tsx +++ b/karavan-web/karavan-app/src/main/webui/src/project/pipeline/ProjectStatus.tsx @@ -14,7 +14,7 @@ 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"; -import {CamelStatus, DeploymentStatus, PipelineStatus, PodStatus, Project} from "../../api/ProjectModels"; +import {CamelStatus, DeploymentStatus, PipelineStatus, ContainerStatus, Project} from "../../api/ProjectModels"; import {useLogStore} from "../../api/ProjectStore"; interface Props { @@ -26,7 +26,7 @@ interface Props { interface State { pipelineStatus?: PipelineStatus, deploymentStatus?: DeploymentStatus, - podStatuses: PodStatus[], + podStatuses: ContainerStatus[], camelStatus?: CamelStatus, isPushing: boolean, isBuilding: boolean, @@ -67,7 +67,7 @@ export class ProjectStatus extends React.Component<Props, State> { this.setState({deploymentStatus: status}); // console.log(status); }); - KaravanApi.getProjectPodStatuses(projectId, env, (statuses: PodStatus[]) => { + KaravanApi.getProjectPodStatuses(projectId, env, (statuses: ContainerStatus[]) => { this.setState({podStatuses: statuses}); // console.log(status); }); @@ -193,7 +193,7 @@ export class ProjectStatus extends React.Component<Props, State> { ) } - getPodsPanel(env: string, podStatuses: PodStatus[]) { + getPodsPanel(env: string, podStatuses: ContainerStatus[]) { return ( <Flex justifyContent={{default: "justifyContentSpaceBetween"}} alignItems={{default: "alignItemsFlexStart"}}> @@ -201,27 +201,27 @@ export class ProjectStatus extends React.Component<Props, State> { {podStatuses.length === 0 && <Label icon={<DownIcon/>} color={"grey"}>No pods</Label>} <LabelGroup numLabels={2} isVertical> {podStatuses.map(pod => { - const ready = pod.ready; + const ready = pod.lifeCycle === 'ready'; return ( - <Tooltip key={pod.name} content={ready ? "Ready" : "Not ready"}> + <Tooltip key={pod.containerName} content={pod.lifeCycle}> <Label icon={ready ? <UpIcon/> : <DownIcon/>} color={ready ? "green" : "red"}> <Button variant="link" onClick={e => { useLogStore.setState({ showLog: true, type: 'container', - podName: pod.name, + podName: pod.containerName, isRunning: true }); }}> - {pod.name} + {pod.containerName} </Button> <Tooltip content={"Delete Pod"}> <Button icon={<DeleteIcon/>} variant="link" onClick={e => this.setState({ showDeleteConfirmation: true, deleteEntity: "pod", deleteEntityEnv: env, - deleteEntityName: pod.name + deleteEntityName: pod.containerName })}></Button> </Tooltip> </Label> diff --git a/karavan-web/karavan-app/src/main/webui/src/project/trace/TraceTab.tsx b/karavan-web/karavan-app/src/main/webui/src/project/trace/TraceTab.tsx index f10bf0ab..7363832a 100644 --- a/karavan-web/karavan-app/src/main/webui/src/project/trace/TraceTab.tsx +++ b/karavan-web/karavan-app/src/main/webui/src/project/trace/TraceTab.tsx @@ -57,6 +57,7 @@ export const TraceTab = () => { if (refreshTrace) { KaravanApi.getDevModeStatus(projectId, "trace", res => { if (res.status === 200) { + console.log(JSON.parse(res.data.status)) setTrace(JSON.parse(res.data.status)); } else { setTrace({}); diff --git a/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/CamelService.java b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/CamelService.java index 84621337..41aa5838 100644 --- a/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/CamelService.java +++ b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/CamelService.java @@ -109,7 +109,7 @@ public class CamelService { .filter(status -> status.getType().equals(ContainerStatus.CType.devmode) || status.getType().equals(ContainerStatus.CType.project)) .forEach(status -> { CamelStatusRequest csr = new CamelStatusRequest(status.getProjectId(), status.getContainerName()); - eventBus.publish(CMD_COLLECT_CAMEL_STATUSES, JsonObject.mapFrom(csr)); + eventBus.publish(CMD_COLLECT_CAMEL_STATUS, JsonObject.mapFrom(csr)); }); } } diff --git a/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/EventService.java b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/EventService.java index d21cf33d..acc2513e 100644 --- a/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/EventService.java +++ b/karavan-web/karavan-headless/src/main/java/org/apache/camel/karavan/headless/EventService.java @@ -26,17 +26,11 @@ import javax.inject.Inject; @ApplicationScoped public class EventService { - public static final String CMD_COLLECT_CAMEL_STATUSES = "collect-camel-statuses"; public static final String CMD_COLLECT_CAMEL_STATUS = "collect-camel-status"; @Inject CamelService camelService; - @ConsumeEvent(value = CMD_COLLECT_CAMEL_STATUSES, blocking = true) - public void collectCamelStatuses(JsonObject data) { - camelService.collectCamelStatuses(); - } - @ConsumeEvent(value = CMD_COLLECT_CAMEL_STATUS, blocking = true) public void collectCamelStatus(JsonObject data) { camelService.collectCamelStatus(data); diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java index 7b0e92e2..9192e0ce 100644 --- a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java +++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/InfinispanService.java @@ -50,6 +50,8 @@ import static org.infinispan.query.remote.client.ProtobufMetadataManagerConstant @ApplicationScoped public class InfinispanService { + public static final String HEALTHY_STATUS = "healthy"; + @ConfigProperty(name ="infinispan.hosts") String infinispanHosts; @ConfigProperty(name ="infinispan.username") diff --git a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java index b994df0d..66d983d8 100644 --- a/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java +++ b/karavan-web/karavan-infinispan/src/main/java/org/apache/camel/karavan/infinispan/model/ContainerStatus.java @@ -92,9 +92,9 @@ public class ContainerStatus { return new ContainerStatus(projectId, projectId, null, null, null, env, CType.devmode, null, null, null, Lifecycle.init, false, false); } - public static ContainerStatus createWithId(String name, String env, String containerId, List<Integer> ports, CType type, Lifecycle lifeCycle) { + public static ContainerStatus createWithId(String name, String env, String containerId, List<Integer> ports, CType type, Lifecycle lifeCycle, String created) { return new ContainerStatus(name, name, containerId, null, ports, env, type, - null, null, null, lifeCycle, false, false); + null, null, created, lifeCycle, false, false); } public ContainerStatus() {