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 ceeffb4 Saas feature28 (#412)
ceeffb4 is described below
commit ceeffb46ffcdc270ec7ac1b07df192918bd2d374
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Tue Jul 12 17:12:58 2022 -0400
Saas feature28 (#412)
* Set/Remove property
* UI fixes
* Select values from COnfigMap, secrets and services
* Kubernetes resources in Kamelets and Components
---
.../camel/karavan/api/KubernetesResource.java | 33 ++++
.../camel/karavan/service/KubernetesService.java | 42 +++--
karavan-app/src/main/webapp/src/api/KaravanApi.tsx | 37 ++++
.../main/webapp/src/projects/ProjectDashboard.tsx | 21 +--
.../src/main/webapp/src/projects/ProjectHeader.tsx | 3 +-
.../src/main/webapp/src/projects/ProjectPage.tsx | 29 +++-
karavan-core/src/core/api/ComponentApi.ts | 2 -
karavan-designer/src/App.tsx | 3 +-
karavan-designer/src/designer/KaravanDesigner.tsx | 8 +-
.../designer/route/property/DslPropertyField.tsx | 163 ++++++++++++-----
.../route/property/KameletPropertyField.tsx | 141 ++++++++++-----
.../designer/route/property/KubernetesSelector.tsx | 193 +++++++++++++++++++++
karavan-designer/src/designer/utils/CamelUi.tsx | 11 +-
.../src/designer/utils/KubernetesAPI.ts | 19 ++
14 files changed, 576 insertions(+), 129 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 22ee3a5..b97c1e6 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
@@ -139,4 +139,37 @@ public class KubernetesResource {
}
return Response.noContent().build();
}
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("/configmap/{environment}")
+ public Response getConfigMaps(@HeaderParam("username") String username,
@PathParam("environment") String environment) throws Exception {
+ Optional<KaravanConfiguration.Environment> env =
configuration.environments().stream().filter(e ->
e.name().equals(environment)).findFirst();
+ if (env.isPresent()) {
+ return
Response.ok(kubernetesService.getConfigMaps(env.get().namespace())).build();
+ }
+ return Response.noContent().build();
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("/secret/{environment}")
+ public Response getSecrets(@HeaderParam("username") String username,
@PathParam("environment") String environment) throws Exception {
+ Optional<KaravanConfiguration.Environment> env =
configuration.environments().stream().filter(e ->
e.name().equals(environment)).findFirst();
+ if (env.isPresent()) {
+ return
Response.ok(kubernetesService.getSecrets(env.get().namespace())).build();
+ }
+ return Response.noContent().build();
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("/service/{environment}")
+ public Response getServices(@HeaderParam("username") String username,
@PathParam("environment") String environment) throws Exception {
+ Optional<KaravanConfiguration.Environment> env =
configuration.environments().stream().filter(e ->
e.name().equals(environment)).findFirst();
+ if (env.isPresent()) {
+ return
Response.ok(kubernetesService.getServices(env.get().namespace())).build();
+ }
+ return Response.noContent().build();
+ }
}
\ No newline at end of file
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 23a868e..d72abe7 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,8 +20,6 @@ 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;
@@ -34,9 +32,6 @@ 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;
import org.apache.camel.karavan.model.PipelineRunLog;
import org.apache.camel.karavan.model.PodStatus;
@@ -47,8 +42,6 @@ import org.jboss.logging.Logger;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -58,7 +51,7 @@ import java.util.stream.Collectors;
public class KubernetesService {
@ConfigProperty(name = "kubernetes.namespace", defaultValue = "localhost")
- String namespace;
+ String currentNamespace;
@Produces
public KubernetesClient kubernetesClient() {
@@ -220,11 +213,40 @@ public class KubernetesService {
}
}
+ public List<String> getConfigMaps(String namespace) {
+ List<String> result = new ArrayList<>();
+
kubernetesClient().configMaps().inNamespace(namespace).list().getItems().forEach(configMap
-> {
+ System.out.println(configMap.getMetadata().getName());
+ String name = configMap.getMetadata().getName();
+ configMap.getData().keySet().forEach(data -> result.add(name + "/"
+ data));
+ });
+ return result;
+ }
+
+ public List<String> getSecrets(String namespace) {
+ List<String> result = new ArrayList<>();
+
kubernetesClient().secrets().inNamespace(namespace).list().getItems().forEach(secret
-> {
+ String name = secret.getMetadata().getName();
+ secret.getData().keySet().forEach(data -> result.add(name + "/" +
data));
+ });
+ return result;
+ }
+
+ public List<String> getServices(String namespace) {
+ List<String> result = new ArrayList<>();
+
kubernetesClient().services().inNamespace(namespace).list().getItems().forEach(service
-> {
+ String name = service.getMetadata().getName();
+ String host = name + "." + namespace + ".svc.cluster.local";
+ service.getSpec().getPorts().forEach(port -> result.add(name + "|"
+ host + ":" + port.getPort()));
+ });
+ return result;
+ }
+
public Secret getKaravanSecret() {
- return
kubernetesClient().secrets().inNamespace(namespace).withName("karavan").get();
+ return
kubernetesClient().secrets().inNamespace(currentNamespace).withName("karavan").get();
}
public boolean inKubernetes() {
- return !Objects.equals(namespace, "localhost");
+ return !Objects.equals(currentNamespace, "localhost");
}
}
diff --git a/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
b/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
index b1868e7..239d688 100644
--- a/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
+++ b/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
@@ -187,6 +187,43 @@ export const KaravanApi = {
});
},
+ getConfigMaps: async (environment: string, after: (any: []) => void) => {
+ axios.get('/kubernetes/configmap/' + environment,
+ {headers: {'Accept': 'application/json', 'Content-Type':
'application/json', 'username': 'cameleer'}})
+ .then(res => {
+ if (res.status === 200) {
+ after(res.data);
+ }
+ }).catch(err => {
+ console.log(err);
+ });
+ },
+
+ getSecrets: async (environment: string, after: (any: []) => void) => {
+ axios.get('/kubernetes/secret/' + environment,
+ {headers: {'Accept': 'application/json', 'Content-Type':
'application/json', 'username': 'cameleer'}})
+ .then(res => {
+ if (res.status === 200) {
+ after(res.data);
+ }
+ }).catch(err => {
+ console.log(err);
+ });
+ },
+
+ getServices: async (environment: string, after: (any: []) => void) => {
+ axios.get('/kubernetes/service/' + environment,
+ {headers: {'Accept': 'application/json', 'Content-Type':
'application/json', 'username': 'cameleer'}})
+ .then(res => {
+ if (res.status === 200) {
+ after(res.data);
+ }
+ }).catch(err => {
+ console.log(err);
+ });
+ },
+
+
getKameletNames: async (after: (names: []) => void) => {
axios.get('/kamelet',
{headers: {'Accept': 'application/json'}})
diff --git a/karavan-app/src/main/webapp/src/projects/ProjectDashboard.tsx
b/karavan-app/src/main/webapp/src/projects/ProjectDashboard.tsx
index 6f92e77..40e7b6c 100644
--- a/karavan-app/src/main/webapp/src/projects/ProjectDashboard.tsx
+++ b/karavan-app/src/main/webapp/src/projects/ProjectDashboard.tsx
@@ -1,32 +1,25 @@
import React from 'react';
import {
Badge,
- Button,
Text,
- DescriptionList,
- DescriptionListTerm,
- DescriptionListGroup,
- DescriptionListDescription,
Card,
- CardBody, Spinner, Tooltip, Flex, FlexItem, Tabs, Tab, PageSection
+ CardBody, Flex, FlexItem,
} from '@patternfly/react-core';
import '../designer/karavan.css';
import {KaravanApi} from "../api/KaravanApi";
import {Project, ProjectFileTypes, ProjectStatus} from
"../models/ProjectModels";
-import BuildIcon from "@patternfly/react-icons/dist/esm/icons/build-icon";
-import PushIcon from "@patternfly/react-icons/dist/esm/icons/code-branch-icon";
-import {ChartDonut, ChartDonutThreshold, ChartDonutUtilization} from
"@patternfly/react-charts";
+import {ChartDonut} from "@patternfly/react-charts";
interface Props {
project: Project,
config: any,
+ environments: string [],
}
interface State {
project?: Project,
status?: ProjectStatus,
- environments: string[],
- environment: string,
+
key?: string,
}
@@ -34,10 +27,6 @@ export class ProjectDashboard extends React.Component<Props,
State> {
public state: State = {
project: this.props.project,
- 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)
- ? this.props.config.environments[0] : ''
};
interval: any;
@@ -143,7 +132,7 @@ export class ProjectDashboard extends
React.Component<Props, State> {
}
render() {
- const {project, environments, status} = this.state;
+ const { environments } = this.props;
return (
<Flex direction={{default: "column"}}>
{environments.filter(e => e !== undefined)
diff --git a/karavan-app/src/main/webapp/src/projects/ProjectHeader.tsx
b/karavan-app/src/main/webapp/src/projects/ProjectHeader.tsx
index 2391c0e..29880f9 100644
--- a/karavan-app/src/main/webapp/src/projects/ProjectHeader.tsx
+++ b/karavan-app/src/main/webapp/src/projects/ProjectHeader.tsx
@@ -14,6 +14,7 @@ import {ProjectInfo} from "./ProjectInfo";
interface Props {
project: Project,
config: any,
+ environments: string [],
showLog: (type: 'container' | 'pipeline', name: string, environment:
string) => void
deleteEntity: (type: 'pod' | 'deployment', name: string, environment:
string) => void
}
@@ -44,7 +45,7 @@ export class ProjectHeader extends React.Component<Props,
State> {
<FlexItem>
<PageSection padding={{default: "padding"}}>
{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}/>}
+ {tab === 'dashboard' && <ProjectDashboard
environments={this.props.environments} project={this.props.project}
config={this.props.config}/>}
</PageSection>
</FlexItem>
</Flex>
diff --git a/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx
b/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx
index faf732c..a8dcf06 100644
--- a/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx
+++ b/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx
@@ -42,6 +42,7 @@ import {PropertiesEditor} from "./PropertiesEditor";
import {ProjectHeader} from "./ProjectHeader";
import {ProjectModel, ProjectProperty} from
"karavan-core/lib/model/ProjectModel";
import {ProjectModelApi} from "karavan-core/lib/api/ProjectModelApi";
+import {KubernetesAPI} from "../designer/utils/KubernetesAPI";
interface Props {
project: Project,
@@ -60,6 +61,8 @@ interface State {
mode: "design" | "code",
editAdvancedProperties: boolean
key: string
+ environments: string[],
+ environment: string,
}
export class ProjectPage extends React.Component<Props, State> {
@@ -72,7 +75,11 @@ export class ProjectPage extends React.Component<Props,
State> {
files: [],
mode: "design",
editAdvancedProperties: false,
- key: ''
+ key: '',
+ 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)
+ ? this.props.config.environments[0] : ''
};
componentDidMount() {
@@ -91,15 +98,25 @@ export class ProjectPage extends React.Component<Props,
State> {
files: files
})
});
+ KubernetesAPI.inKubernetes = true;
+ KaravanApi.getConfigMaps(this.state.environment, (any: []) => {
+ KubernetesAPI.setConfigMaps(any);
+ });
+ KaravanApi.getSecrets(this.state.environment, (any: []) => {
+ KubernetesAPI.setSecrets(any);
+ });
+ KaravanApi.getServices(this.state.environment, (any: []) => {
+ KubernetesAPI.setServices(any);
+ });
}
}
post = (file: ProjectFile) => {
KaravanApi.postProjectFile(file, res => {
if (res.status === 200) {
- console.log(res) //TODO show notification
+ // console.log(res) //TODO show notification
} else {
- console.log(res) //TODO show notification
+ // console.log(res) //TODO show notification
}
})
}
@@ -418,7 +435,11 @@ 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}
deleteEntity={this.deleteEntity}/>}
+ {<ProjectHeader project={this.props.project}
+ config={this.props.config}
+ environments={this.state.environments}
+ showLog={this.showPipelineLog}
+ deleteEntity={this.deleteEntity}/>}
{this.getProjectFiles()}
</PageSection>}
{showDesigner && this.getDesigner()}
diff --git a/karavan-core/src/core/api/ComponentApi.ts
b/karavan-core/src/core/api/ComponentApi.ts
index 7d199f3..e656978 100644
--- a/karavan-core/src/core/api/ComponentApi.ts
+++ b/karavan-core/src/core/api/ComponentApi.ts
@@ -15,8 +15,6 @@
* limitations under the License.
*/
import {Component, ComponentProperty} from "../model/ComponentModels";
-import {CamelMetadataApi} from "../model/CamelMetadata";
-import {Kamelets} from "./KameletApi";
export const Components: Component[] = [];
diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx
index 2b25490..2b55658 100644
--- a/karavan-designer/src/App.tsx
+++ b/karavan-designer/src/App.tsx
@@ -26,6 +26,7 @@ import {ComponentsPage} from "./components/ComponentsPage";
import {EipPage} from "./eip/EipPage";
import {BuilderPage} from "./builder/BuilderPage";
import {ProjectModel, StepStatus} from "karavan-core/lib/model/ProjectModel";
+import {KubernetesAPI} from "./designer/utils/KubernetesAPI";
interface Props {
page: "designer" | "kamelets" | "components" | "eip" | "builder";
@@ -67,7 +68,6 @@ class App extends React.Component<Props, State> {
};
componentDidMount() {
-
["http-secured-sink.kamelet.yaml",
"timer-source.kamelet.yaml",
"http-secured-source.kamelet.yaml",
@@ -107,7 +107,6 @@ class App extends React.Component<Props, State> {
fetch("components/" + name)
.then((r) => r.text())
.then(value => ComponentApi.saveComponent(value)));
-
}
save(filename: string, yaml: string, propertyOnly: boolean) {
diff --git a/karavan-designer/src/designer/KaravanDesigner.tsx
b/karavan-designer/src/designer/KaravanDesigner.tsx
index 6eb2ff8..20e9f60 100644
--- a/karavan-designer/src/designer/KaravanDesigner.tsx
+++ b/karavan-designer/src/designer/KaravanDesigner.tsx
@@ -139,7 +139,7 @@ export class KaravanDesigner extends React.Component<Props,
State> {
<Tab data-tour="routes" eventKey='routes'
title={this.getTab("Routes", "Integration flows", "routes")}></Tab>
<Tab eventKey='rest' title={this.getTab("REST", "REST
services", "rest")}></Tab>
<Tab eventKey='beans' title={this.getTab("Beans", "Beans
Configuration", "beans")}></Tab>
- <Tab eventKey='dependencies'
title={this.getTab("Dependencies", "Dependencies", "dependencies")}></Tab>
+ {/*<Tab eventKey='dependencies'
title={this.getTab("Dependencies", "Dependencies", "dependencies")}></Tab>*/}
{/*<Tab eventKey='traits' title={this.getTab("Traits",
"traits configuration", "traits")}></Tab>*/}
<Tab eventKey='error' title={this.getTab("Error", "Error
Handler", "error")}></Tab>
<Tab eventKey='exception' title={this.getTab("Exceptions",
"Exception Clauses per type", "exception")}></Tab>
@@ -164,9 +164,9 @@ export class KaravanDesigner extends React.Component<Props,
State> {
{tab === 'exception' && <ExceptionDesigner
integration={this.state.integration}
onSave={(integration, propertyOnly) => this.save(integration, propertyOnly)}
dark={this.props.dark}/>}
- {tab === 'traits' && <TraitsDesigner
integration={this.state.integration}
-
onSave={(integration, propertyOnly) => this.save(integration, propertyOnly)}
-
dark={this.props.dark}/>}
+ {/*{tab === 'traits' && <TraitsDesigner
integration={this.state.integration}*/}
+ {/*
onSave={(integration, propertyOnly) => this.save(integration, propertyOnly)}*/}
+ {/*
dark={this.props.dark}/>}*/}
{this.getHelpWindow()}
</PageSection>
)
diff --git a/karavan-designer/src/designer/route/property/DslPropertyField.tsx
b/karavan-designer/src/designer/route/property/DslPropertyField.tsx
index 6b03100..9141da0 100644
--- a/karavan-designer/src/designer/route/property/DslPropertyField.tsx
+++ b/karavan-designer/src/designer/route/property/DslPropertyField.tsx
@@ -23,7 +23,7 @@ import {
Select,
SelectVariant,
SelectDirection,
- SelectOption, ExpandableSection, TextArea, Chip, TextInputGroup,
TextInputGroupMain, TextInputGroupUtilities, ChipGroup, Button, Text, Tooltip,
Card
+ SelectOption, ExpandableSection, TextArea, Chip, TextInputGroup,
TextInputGroupMain, TextInputGroupUtilities, ChipGroup, Button, Text, Tooltip,
Card, InputGroup, Modal
} from '@patternfly/react-core';
import '../../karavan.css';
import "@patternfly/patternfly/patternfly.css";
@@ -45,6 +45,11 @@ import {CamelDefinitionApi} from
"karavan-core/lib/api/CamelDefinitionApi";
import AddIcon from "@patternfly/react-icons/dist/js/icons/plus-circle-icon";
import {MediaTypes} from "../../utils/MediaTypes";
import {ComponentProperty} from "karavan-core/lib/model/ComponentModels";
+import CompressIcon from "@patternfly/react-icons/dist/js/icons/compress-icon";
+import ExpandIcon from "@patternfly/react-icons/dist/js/icons/expand-icon";
+import KubernetesIcon from
"@patternfly/react-icons/dist/js/icons/openshift-icon";
+import {KubernetesSelector} from "./KubernetesSelector";
+import {KubernetesAPI} from "../../utils/KubernetesAPI";
interface Props {
property: PropertyMeta,
@@ -55,13 +60,16 @@ interface Props {
onParameterChange?: (parameter: string, value: string | number | boolean |
any, pathParameter?: boolean, newRoute?: RouteToCreate) => void,
element?: CamelElement
integration: Integration,
- hideLabel?: boolean
+ hideLabel?: boolean,
}
interface State {
selectStatus: Map<string, boolean>,
- isShowAdvanced: Map<string, boolean>
- arrayValues: Map<string, string>
+ isShowAdvanced: Map<string, boolean>,
+ arrayValues: Map<string, string>,
+ showEditor: boolean
+ showKubernetesSelector: boolean
+ kubernetesSelectorProperty?: string
}
export class DslPropertyField extends React.Component<Props, State> {
@@ -70,7 +78,9 @@ export class DslPropertyField extends React.Component<Props,
State> {
selectStatus: new Map<string, boolean>(),
arrayValues: new Map<string, string>(),
isShowAdvanced: new Map<string, boolean>(),
- }
+ showEditor: false,
+ showKubernetesSelector: false,
+ };
openSelect = (propertyName: string, isExpanded: boolean) => {
this.setState({selectStatus: new Map<string, boolean>([[propertyName,
isExpanded]])});
@@ -140,15 +150,72 @@ export class DslPropertyField extends
React.Component<Props, State> {
return property.name === 'uri' && !['ToDynamicDefinition',
'WireTapDefinition'].includes(dslName)
}
- getTextField = (property: PropertyMeta, value: any) => {
+ selectKubernetes = (value: string) => {
+ const propertyName = this.state.kubernetesSelectorProperty;
+ if (propertyName){
+ if (value.startsWith("config") || value.startsWith("secret"))
value = "{{" + value + "}}";
+ this.propertyChanged(propertyName, value);
+ this.setState({showKubernetesSelector: false,
kubernetesSelectorProperty: undefined})
+ }
+ }
+
+ openKubernetesSelector = (propertyName: string) => {
+ this.setState({kubernetesSelectorProperty: propertyName,
showKubernetesSelector: true});
+ }
+
+ closeKubernetesSelector = () => {
+ this.setState({showKubernetesSelector: false})
+ }
+
+ getKubernetesSelectorModal() {
return (
- <TextInput
+ <Modal
+ title="Select from Kubernetes"
+ width={'50%'}
+ className='dsl-modal'
+ isOpen={this.state.showKubernetesSelector}
+ onClose={() => this.closeKubernetesSelector()}
+ actions={{}}>
+ <KubernetesSelector
+ dark={false}
+ onSelect={this.selectKubernetes}/>
+ </Modal>)
+ }
+
+ getStringInput = (property: PropertyMeta, value: any) => {
+ const showEditor = this.state.showEditor;
+ const inKubernetes = KubernetesAPI.inKubernetes;
+ const noKubeSelectorButton = ["uri", "id", "description",
"group"].includes(property.name);
+ return (<InputGroup>
+ {inKubernetes && !showEditor && !noKubeSelectorButton &&
+ <Tooltip position="bottom-end" content="Select from
Kubernetes">
+ <Button variant="control" onClick={e =>
this.openKubernetesSelector(property.name)}>
+ <KubernetesIcon/>
+ </Button>
+ </Tooltip>}
+ {(!showEditor || property.secret) && <TextInput
className="text-field" isRequired
isReadOnly={this.isUriReadOnly(property)}
type={['integer', 'number'].includes(property.type) ? 'number'
: (property.secret ? "password" : "text")}
id={property.name} name={property.name}
value={value?.toString()}
onChange={e => this.propertyChanged(property.name, ['integer',
'number'].includes(property.type) ? Number(e) : e)}/>
- )
+ }
+ {showEditor && !property.secret && <TextArea
+ autoResize={true}
+ className="text-field" isRequired
isReadOnly={this.isUriReadOnly(property)}
+ type="text"
+ id={property.name} name={property.name}
+ value={value?.toString()}
+ onChange={e => this.propertyChanged(property.name, ['integer',
'number'].includes(property.type) ? Number(e) : e)}/>
+ }
+ {!property.secret &&
+ <Tooltip position="bottom-end" content={showEditor ? "Change
to TextField" : "Change to Text Area"}>
+ <Button variant="control" onClick={e =>
this.setState({showEditor: !showEditor})}>
+ {showEditor ? <CompressIcon/> : <ExpandIcon/>}
+ </Button>
+ </Tooltip>
+ }
+ </InputGroup>)
}
getTextArea = (property: PropertyMeta, value: any) => {
@@ -462,10 +529,10 @@ export class DslPropertyField extends
React.Component<Props, State> {
headerContent={property.displayName}
bodyContent={property.description}
footerContent={
- <div>
- {property.defaultValue !== undefined &&
property.defaultValue.toString().trim().length >0 && <div>{"Default: " +
property.defaultValue}</div>}
- {property.required && <b>Required</b>}
- </div>
+ <div>
+ {property.defaultValue !== undefined &&
property.defaultValue.toString().trim().length >0 && <div>{"Default: " +
property.defaultValue}</div>}
+ {property.required && <b>Required</b>}
+ </div>
}>
<button type="button" aria-label="More info" onClick={e =>
{
e.preventDefault();
@@ -507,41 +574,43 @@ export class DslPropertyField extends
React.Component<Props, State> {
const property: PropertyMeta = this.props.property;
const value = this.props.value;
return (
- <FormGroup
- data-tour={property.name}
- label={this.props.hideLabel ? undefined :
this.getLabel(property, value)}
- isRequired={property.required}
- fieldId={property.name}
- labelIcon={this.getLabelIcon(property)}>
- {value && ["ExpressionDefinition",
"ExpressionSubElementDefinition"].includes(property.type)
- && this.getExpressionField(property, value)}
- {property.isObject && !property.isArray &&
!["ExpressionDefinition",
"ExpressionSubElementDefinition"].includes(property.type)
- && this.getObjectField(property, value)}
- {property.isObject && property.isArray &&
!this.isMultiValueField(property)
- && this.getMultiValueObjectField(property, value)}
- {property.name === 'expression' && property.type === "string"
&& !property.isArray
- && this.getTextArea(property, value)}
- {this.canBeInternalUri(property, this.props.element)
- && this.getInternalUriSelect(property, value)}
- {this.canBeMediaType(property, this.props.element)
- && this.getMediaTypeSelect(property, value)}
- {['string', 'duration', 'integer',
'number'].includes(property.type) && property.name !== 'expression' &&
!property.name.endsWith("Ref")
- && !property.isArray && !property.enumVals
- && !this.canBeInternalUri(property, this.props.element)
- && !this.canBeMediaType(property, this.props.element)
- && this.getTextField(property, value)}
- {['string'].includes(property.type) &&
property.name.endsWith("Ref") && !property.isArray && !property.enumVals
- && this.getSelectBean(property, value)}
- {this.isMultiValueField(property)
- && this.getMultiValueField(property, value)}
- {property.type === 'boolean'
- && this.getSwitch(property, value)}
- {property.enumVals
- && this.getSelect(property, value)}
- {isKamelet && property.name === 'parameters' &&
this.getKameletParameters()}
- {!isKamelet && property.name === 'parameters' &&
this.getComponentParameters(property)}
-
- </FormGroup>
+ <div>
+ <FormGroup
+ data-tour={property.name}
+ label={this.props.hideLabel ? undefined :
this.getLabel(property, value)}
+ isRequired={property.required}
+ fieldId={property.name}
+ labelIcon={this.getLabelIcon(property)}>
+ {value && ["ExpressionDefinition",
"ExpressionSubElementDefinition"].includes(property.type)
+ && this.getExpressionField(property, value)}
+ {property.isObject && !property.isArray &&
!["ExpressionDefinition",
"ExpressionSubElementDefinition"].includes(property.type)
+ && this.getObjectField(property, value)}
+ {property.isObject && property.isArray &&
!this.isMultiValueField(property)
+ && this.getMultiValueObjectField(property, value)}
+ {property.name === 'expression' && property.type ===
"string" && !property.isArray
+ && this.getTextArea(property, value)}
+ {this.canBeInternalUri(property, this.props.element)
+ && this.getInternalUriSelect(property, value)}
+ {this.canBeMediaType(property, this.props.element)
+ && this.getMediaTypeSelect(property, value)}
+ {['string', 'duration', 'integer',
'number'].includes(property.type) && property.name !== 'expression' &&
!property.name.endsWith("Ref")
+ && !property.isArray && !property.enumVals
+ && !this.canBeInternalUri(property, this.props.element)
+ && !this.canBeMediaType(property, this.props.element)
+ && this.getStringInput(property, value)}
+ {['string'].includes(property.type) &&
property.name.endsWith("Ref") && !property.isArray && !property.enumVals
+ && this.getSelectBean(property, value)}
+ {this.isMultiValueField(property)
+ && this.getMultiValueField(property, value)}
+ {property.type === 'boolean'
+ && this.getSwitch(property, value)}
+ {property.enumVals
+ && this.getSelect(property, value)}
+ {isKamelet && property.name === 'parameters' &&
this.getKameletParameters()}
+ {!isKamelet && property.name === 'parameters' &&
this.getComponentParameters(property)}
+ </FormGroup>
+ {this.getKubernetesSelectorModal()}
+ </div>
)
}
}
diff --git
a/karavan-designer/src/designer/route/property/KameletPropertyField.tsx
b/karavan-designer/src/designer/route/property/KameletPropertyField.tsx
index 39ff5d8..e48b23c 100644
--- a/karavan-designer/src/designer/route/property/KameletPropertyField.tsx
+++ b/karavan-designer/src/designer/route/property/KameletPropertyField.tsx
@@ -19,7 +19,7 @@ import {
FormGroup,
TextInput,
Popover,
- Switch, InputGroup, Button, TextArea, Text, Tooltip,
+ Switch, InputGroup, Button, TextArea, Text, Tooltip, Modal,
} from '@patternfly/react-core';
import '../../karavan.css';
import "@patternfly/patternfly/patternfly.css";
@@ -27,6 +27,11 @@ import HelpIcon from
"@patternfly/react-icons/dist/js/icons/help-icon";
import ExpandIcon from "@patternfly/react-icons/dist/js/icons/expand-icon";
import CompressIcon from "@patternfly/react-icons/dist/js/icons/compress-icon";
import {Property} from "karavan-core/lib/model/KameletModels";
+import {KubernetesSelector} from "./KubernetesSelector";
+import {KubernetesAPI} from "../../utils/KubernetesAPI";
+import KubernetesIcon from
"@patternfly/react-icons/dist/js/icons/openshift-icon";
+import ShowIcon from "@patternfly/react-icons/dist/js/icons/eye-icon";
+import HideIcon from "@patternfly/react-icons/dist/js/icons/eye-slash-icon";
interface Props {
property: Property,
@@ -37,6 +42,9 @@ interface Props {
interface State {
selectIsOpen: boolean
showEditor: boolean
+ showPassword: boolean
+ showKubernetesSelector: boolean
+ kubernetesSelectorProperty?: string
}
export class KameletPropertyField extends React.Component<Props, State> {
@@ -44,6 +52,8 @@ export class KameletPropertyField extends
React.Component<Props, State> {
public state: State = {
selectIsOpen: false,
showEditor: false,
+ showPassword: false,
+ showKubernetesSelector: false,
}
openSelect = () => {
@@ -55,17 +65,58 @@ export class KameletPropertyField extends
React.Component<Props, State> {
this.setState({selectIsOpen: false});
}
+ selectKubernetes = (value: string) => {
+ const propertyId = this.state.kubernetesSelectorProperty;
+ if (propertyId){
+ if (value.startsWith("config") || value.startsWith("secret"))
value = "{{" + value + "}}";
+ this.parametersChanged(propertyId, value);
+ this.setState({showKubernetesSelector: false,
kubernetesSelectorProperty: undefined})
+ }
+ }
+
+ openKubernetesSelector = (propertyName: string) => {
+ this.setState({kubernetesSelectorProperty: propertyName,
showKubernetesSelector: true});
+ }
+
+ closeKubernetesSelector = () => {
+ this.setState({showKubernetesSelector: false})
+ }
+
+ getKubernetesSelectorModal() {
+ return (
+ <Modal
+ title="Select from Kubernetes"
+ width={'50%'}
+ className='dsl-modal'
+ isOpen={this.state.showKubernetesSelector}
+ onClose={() => this.closeKubernetesSelector()}
+ actions={{}}>
+ <KubernetesSelector
+ dark={false}
+ onSelect={this.selectKubernetes}/>
+ </Modal>)
+ }
+
getStringInput() {
const showEditor = this.state.showEditor;
+ const showPassword = this.state.showPassword;
const property = this.props.property;
const value = this.props.value;
const prefix = "parameters";
const id = prefix + "-" + property.id;
+ const noKubeSelectorButton = ["uri", "id", "description",
"group"].includes(property.id);
+ const showKubeSelectorButton = KubernetesAPI.inKubernetes &&
!showEditor && !noKubeSelectorButton
return <InputGroup>
+ {showKubeSelectorButton &&
+ <Tooltip position="bottom-end" content="Select from
Kubernetes">
+ <Button variant="control" onClick={e =>
this.openKubernetesSelector(property.id)}>
+ <KubernetesIcon/>
+ </Button>
+ </Tooltip>}
{(!showEditor || property.format === "password") &&
<TextInput
className="text-field" isRequired
- type={property.format ? "password" : "text"}
+ type={property.format && !showPassword ? "password" :
"text"}
id={id} name={id}
value={value}
onChange={e => this.parametersChanged(property.id, e)}/>}
@@ -83,6 +134,13 @@ export class KameletPropertyField extends
React.Component<Props, State> {
</Button>
</Tooltip>
}
+ {property.format === "password" &&
+ <Tooltip position="bottom-end" content={showPassword ? "Hide"
: "Show"}>
+ <Button variant="control" onClick={e =>
this.setState({showPassword: !showPassword})}>
+ {showPassword ? <ShowIcon/> : <HideIcon/>}
+ </Button>
+ </Tooltip>
+ }
</InputGroup>
}
@@ -92,44 +150,47 @@ export class KameletPropertyField extends
React.Component<Props, State> {
const prefix = "parameters";
const id = prefix + "-" + property.id;
return (
- <FormGroup
- data-tour={property.id}
- key={id}
- label={property.title}
- fieldId={id}
- labelIcon={
- <Popover
- position={"left"}
- headerContent={property.title}
- bodyContent={property.description}
- footerContent={
- <div>
- {property.default !== undefined &&
- <div>Default:
{property.default.toString()}</div>}
- {property.example !== undefined &&
<div>Example: {property.example}</div>}
- </div>
- }>
- <button type="button" aria-label="More info"
onClick={e => e.preventDefault()}
- className="pf-c-form__group-label-help">
- <HelpIcon noVerticalAlign/>
- </button>
- </Popover>
- }>
- {property.type === 'string' && this.getStringInput()
- }
- {['integer', 'int', 'number'].includes(property.type) &&
- <TextInput className="text-field" isRequired type='number'
id={id} name={id} value={value}
- onChange={e =>
this.parametersChanged(property.id, Number(e))}
- />
- }
- {property.type === 'boolean' && <Switch
- id={id} name={id}
- value={value?.toString()}
- aria-label={id}
- isChecked={Boolean(value) === true}
- onChange={e => this.parametersChanged(property.id,
!Boolean(value))}/>
- }
- </FormGroup>
+ <div>
+ <FormGroup
+ data-tour={property.id}
+ key={id}
+ label={property.title}
+ fieldId={id}
+ labelIcon={
+ <Popover
+ position={"left"}
+ headerContent={property.title}
+ bodyContent={property.description}
+ footerContent={
+ <div>
+ {property.default !== undefined &&
+ <div>Default:
{property.default.toString()}</div>}
+ {property.example !== undefined &&
<div>Example: {property.example}</div>}
+ </div>
+ }>
+ <button type="button" aria-label="More info"
onClick={e => e.preventDefault()}
+ className="pf-c-form__group-label-help">
+ <HelpIcon noVerticalAlign/>
+ </button>
+ </Popover>
+ }>
+ {property.type === 'string' && this.getStringInput()
+ }
+ {['integer', 'int', 'number'].includes(property.type) &&
+ <TextInput className="text-field" isRequired
type='number' id={id} name={id} value={value}
+ onChange={e =>
this.parametersChanged(property.id, Number(e))}
+ />
+ }
+ {property.type === 'boolean' && <Switch
+ id={id} name={id}
+ value={value?.toString()}
+ aria-label={id}
+ isChecked={Boolean(value) === true}
+ onChange={e => this.parametersChanged(property.id,
!Boolean(value))}/>
+ }
+ </FormGroup>
+ {this.getKubernetesSelectorModal()}
+ </div>
)
}
}
\ No newline at end of file
diff --git
a/karavan-designer/src/designer/route/property/KubernetesSelector.tsx
b/karavan-designer/src/designer/route/property/KubernetesSelector.tsx
new file mode 100644
index 0000000..88c97b7
--- /dev/null
+++ b/karavan-designer/src/designer/route/property/KubernetesSelector.tsx
@@ -0,0 +1,193 @@
+/*
+ * 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 {
+ Badge,
+ Button,
+ Form, FormGroup, PageSection,
+ Tab, Tabs, TabTitleText, TextInput,
+} from '@patternfly/react-core';
+import '../../karavan.css';
+import {TableComposable, Tbody, Td, Th, Thead, Tr} from
"@patternfly/react-table";
+import {KubernetesAPI} from "../../utils/KubernetesAPI";
+
+interface Props {
+ onSelect: (value: string) => void,
+ dark: boolean,
+}
+
+interface State {
+ tabIndex: string | number
+ filter?: string
+ configMaps: string[]
+ secrets: string[]
+ services: string[]
+}
+
+export class KubernetesSelector extends React.Component<Props, State> {
+
+ public state: State = {
+ tabIndex: "configMap",
+ configMaps: KubernetesAPI.configMaps,
+ secrets: KubernetesAPI.secrets,
+ services: KubernetesAPI.services
+ };
+
+ selectTab = (evt: React.MouseEvent<HTMLElement, MouseEvent>, eventKey:
string | number) => {
+ this.setState({tabIndex: eventKey})
+ }
+
+ checkFilter = (name: string): boolean => {
+ if (this.state.filter !== undefined && name) {
+ return name.toLowerCase().includes(this.state.filter.toLowerCase())
+ } else {
+ return true;
+ }
+ }
+
+ searchInput = () => {
+ return (
+ <Form isHorizontal className="search" autoComplete="off">
+ <FormGroup fieldId="search">
+ <TextInput className="text-field" type="text" id="search"
name="search" iconVariant='search'
+ value={this.state.filter}
+ onChange={e => this.setState({filter: e})}/>
+ </FormGroup>
+ </Form>
+ )
+ }
+
+ render() {
+ const configMaps = this.state.configMaps;
+ console.log(configMaps);
+ const secrets = this.state.secrets;
+ const services = this.state.services;
+ console.log(services);
+ return (
+ <PageSection variant={this.props.dark ? "darker" : "light"}>
+ {this.searchInput()}
+ <Tabs data-tour="selector-tabs" style={{overflow: 'hidden'}}
activeKey={this.state.tabIndex} onSelect={this.selectTab}>
+ <Tab eventKey={"configMap"} key={"configMap"}
title={<TabTitleText>ConfigMaps</TabTitleText>}>
+ <TableComposable variant='compact' borders={false}>
+ <Thead>
+ <Tr>
+ <Th/>
+ <Th key='name'>Name</Th>
+ <Th key='data'>Data</Th>
+ </Tr>
+ </Thead>
+ <Tbody>
+ {configMaps
+ .filter(name => this.checkFilter(name))
+ .map((name, idx: number) => {
+ const configMapName =
name.split("/")[0];
+ const data = name.split("/")[1];
+ return (
+ <Tr key={name}>
+ <Td noPadding isActionCell>
+ <Badge>CM</Badge>
+ </Td>
+ <Td noPadding>
+ {configMapName}
+ </Td>
+ <Td noPadding>
+ <Button style={{padding:
'6px'}} variant={"link"} onClick={
+ e =>
this.props.onSelect?.call(this, "configmap:" + name)}>
+ {data}
+ </Button>
+ </Td>
+ </Tr>
+ )
+ })}
+ </Tbody>
+ </TableComposable>
+ </Tab>
+ <Tab eventKey={"secret"} key={"secret"}
title={<TabTitleText>Secrets</TabTitleText>}>
+ <TableComposable variant='compact' borders={false}>
+ <Thead>
+ <Tr>
+ <Th/>
+ <Th key='name'>Name</Th>
+ <Th key='data'>Data</Th>
+ </Tr>
+ </Thead>
+ <Tbody>
+ {secrets
+ .filter(name => this.checkFilter(name))
+ .map((name, idx: number) => {
+ const configMapName =
name.split("/")[0];
+ const data = name.split("/")[1];
+ return (
+ <Tr key={name}>
+ <Td noPadding isActionCell>
+ <Badge>S</Badge>
+ </Td>
+ <Td noPadding>
+ {configMapName}
+ </Td>
+ <Td noPadding>
+ <Button style={{padding:
'6px'}} variant={"link"} onClick={
+ e =>
this.props.onSelect?.call(this, "secret:" + name)}>
+ {data}
+ </Button>
+ </Td>
+ </Tr>
+ )
+ })}
+ </Tbody>
+ </TableComposable>
+ </Tab>
+ <Tab eventKey={"service"} key={"service"}
title={<TabTitleText>Services</TabTitleText>}>
+ <TableComposable variant='compact' borders={false}>
+ <Thead>
+ <Tr>
+ <Th/>
+ <Th key='name'>Name</Th>
+ <Th key='host'>Host:Port</Th>
+ </Tr>
+ </Thead>
+ <Tbody>
+ {services
+ .filter(name => this.checkFilter(name))
+ .map((name, idx: number) => {
+ const serviceName = name.split("|")[0];
+ const hostPort = name.split("|")[1];
+ return (
+ <Tr key={name}>
+ <Td noPadding isActionCell>
+ <Badge>S</Badge>
+ </Td>
+ <Td noPadding>
+ {serviceName}
+ </Td>
+ <Td noPadding>
+ <Button style={{padding:
'6px'}} variant={"link"} onClick={
+ e =>
this.props.onSelect?.call(this, hostPort)}>
+ {hostPort}
+ </Button>
+ </Td>
+ </Tr>
+ )
+ })}
+ </Tbody>
+ </TableComposable>
+ </Tab>
+ </Tabs>
+ </PageSection>
+ );
+ }
+}
\ No newline at end of file
diff --git a/karavan-designer/src/designer/utils/CamelUi.tsx
b/karavan-designer/src/designer/utils/CamelUi.tsx
index c421221..661fb7a 100644
--- a/karavan-designer/src/designer/utils/CamelUi.tsx
+++ b/karavan-designer/src/designer/utils/CamelUi.tsx
@@ -47,10 +47,12 @@ const StepElements: string[] = [
"RecipientListDefinition",
"RemoveHeaderDefinition",
"RemoveHeadersDefinition",
+ "RemovePropertyDefinition",
"ResequenceDefinition",
"SagaDefinition",
"SetBodyDefinition",
"SetHeaderDefinition",
+ "SetPropertyDefinition",
"SortDefinition",
"SplitDefinition",
"ThreadsDefinition",
@@ -373,10 +375,14 @@ export class CamelUi {
return "data:image/svg+xml,%3Csvg width='32' height='32'
xmlns='http://www.w3.org/2000/svg'
xmlns:svg='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cstyle%3E.cls-1 %7B fill:
none; %7D%3C/style%3E%3C/defs%3E%3Cg class='layer'%3E%3Ctitle%3ELayer
1%3C/title%3E%3Cpath
d='m24.08924,9.30736l-1.67194,1.57734l4.23986,3.99986l-5.47865,0a5.92883,5.59337
0 0 0 -4.60981,-4.34899l0,-10.15173l-2.36467,0l0,10.15173a5.91168,5.5772 0 0 0
0,10.92886l0,10.15173l2.36467,0l0,-10.15173a5.92883,5. [...]
case "RemoveHeaderDefinition":
return "data:image/svg+xml,%3Csvg width='32' height='32'
xmlns='http://www.w3.org/2000/svg'
xmlns:svg='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cstyle%3E.cls-1 %7B fill:
none; %7D%3C/style%3E%3C/defs%3E%3Cg class='layer'%3E%3Ctitle%3ELayer
1%3C/title%3E%3Cpath d='m24,30l-20,0a2.0021,2.0021 0 0 1
-2,-2l0,-6a2.0021,2.0021 0 0 1 2,-2l20,0a2.0021,2.0021 0 0 1
2,2l0,6a2.0021,2.0021 0 0 1 -2,2zm-20,-8l-0.0015,0l0.0015,6l20,0l0,-6l-20,0z'
id='svg_1'/%3E%3Cpolygon id='svg_2' poi [...]
+ case "RemovePropertyDefinition":
+ return "data:image/svg+xml,%3Csvg width='32' height='32'
xmlns='http://www.w3.org/2000/svg'
xmlns:svg='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cstyle%3E.cls-1 %7B fill:
none; %7D%3C/style%3E%3C/defs%3E%3Cg class='layer'%3E%3Ctitle%3ELayer
1%3C/title%3E%3Cpath d='m24,30l-20,0a2.0021,2.0021 0 0 1
-2,-2l0,-6a2.0021,2.0021 0 0 1 2,-2l20,0a2.0021,2.0021 0 0 1
2,2l0,6a2.0021,2.0021 0 0 1 -2,2zm-20,-8l-0.0015,0l0.0015,6l20,0l0,-6l-20,0z'
id='svg_1'/%3E%3Cpolygon id='svg_2' poi [...]
case "RemoveHeadersDefinition":
return "data:image/svg+xml,%3Csvg width='32' height='32'
xmlns='http://www.w3.org/2000/svg'
xmlns:svg='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cstyle%3E.cls-1 %7B fill:
none; %7D%3C/style%3E%3C/defs%3E%3Cg class='layer'%3E%3Ctitle%3ELayer
1%3C/title%3E%3Cpolygon id='svg_2' points='32.12467002868652,6.015733242034912
32.12467002868652,4.021692276000977 27.047643661499023,4.021692276000977
27.047643661499023,-1.0553351640701294 25.05360221862793,-1.0553350448608398
25.053 [...]
case "SetHeaderDefinition":
return "data:image/svg+xml,%3Csvg width='32' height='32'
xmlns='http://www.w3.org/2000/svg'
xmlns:svg='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cstyle%3E.cls-1 %7B fill:
none; %7D%3C/style%3E%3C/defs%3E%3Cg class='layer'%3E%3Ctitle%3ELayer
1%3C/title%3E%3Cpath d='m24,30l-20,0a2.0021,2.0021 0 0 1
-2,-2l0,-6a2.0021,2.0021 0 0 1 2,-2l20,0a2.0021,2.0021 0 0 1
2,2l0,6a2.0021,2.0021 0 0 1 -2,2zm-20,-8l-0.0015,0l0.0015,6l20,0l0,-6l-20,0z'
id='svg_1'/%3E%3Cpolygon id='svg_2' poi [...]
+ case "SetPropertyDefinition":
+ return "data:image/svg+xml,%3Csvg width='32' height='32'
xmlns='http://www.w3.org/2000/svg'
xmlns:svg='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cstyle%3E.cls-1 %7B fill:
none; %7D%3C/style%3E%3C/defs%3E%3Cg class='layer'%3E%3Ctitle%3ELayer
1%3C/title%3E%3Cpath d='m24,30l-20,0a2.0021,2.0021 0 0 1
-2,-2l0,-6a2.0021,2.0021 0 0 1 2,-2l20,0a2.0021,2.0021 0 0 1
2,2l0,6a2.0021,2.0021 0 0 1 -2,2zm-20,-8l-0.0015,0l0.0015,6l20,0l0,-6l-20,0z'
id='svg_1'/%3E%3Cpolygon id='svg_2' poi [...]
case "SetBodyDefinition":
return "data:image/svg+xml,%3Csvg width='32px' height='32px'
viewBox='0 0 32 32' id='icon'
xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cstyle%3E .cls-1 %7B fill:
none; %7D %3C/style%3E%3C/defs%3E%3Cpolygon points='30 24 26 24 26 20 24 20 24
24 20 24 20 26 24 26 24 30 26 30 26 26 30 26 30 24'/%3E%3Cpath
d='M16,28H8V4h8v6a2.0058,2.0058,0,0,0,2,2h6v4h2V10a.9092.9092,0,0,0-.3-.7l-7-7A.9087.9087,0,0,0,18,2H8A2.0058,2.0058,0,0,0,6,4V28a2.0058,2.0058,0,0,0,2,2h8ZM18,4.4,23.
[...]
case "MarshalDefinition":
@@ -410,9 +416,9 @@ export class CamelUi {
case "ErrorHandlerBuilderRef":
return "data:image/svg+xml,%3Csvg
xmlns='http://www.w3.org/2000/svg' class='top-icon' width='36px' height='36px'
viewBox='0 0 36 36' version='1.1' preserveAspectRatio='xMidYMid
meet'%3E%3Ccircle class='clr-i-outline clr-i-outline-path-1' cx='18' cy='26.06'
r='1.33'%3E%3C/circle%3E%3Cpath class='clr-i-outline clr-i-outline-path-2'
d='M18,22.61a1,1,0,0,1-1-1v-12a1,1,0,1,1,2,0v12A1,1,0,0,1,18,22.61Z'%3E%3C/path%3E%3Cpath
class='clr-i-outline clr-i-outline-path-3' d='M18,34A1 [...]
case "ThrowExceptionDefinition":
- return "data:image/svg+xml,%0A%3Csvg width='32px'
height='32px' viewBox='0 0 32 32' id='icon'
xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cstyle%3E.cls-1%7Bfill:none;%7D%3C/style%3E%3C/defs%3E%3Ctitle%3Ewarning%3C/title%3E%3Cpath
d='M16,2A14,14,0,1,0,30,16,14,14,0,0,0,16,2Zm0,26A12,12,0,1,1,28,16,12,12,0,0,1,16,28Z'
transform='translate(0 0)'/%3E%3Crect x='15' y='8' width='2'
height='11'/%3E%3Cpath d='M16,22a1.5,1.5,0,1,0,1.5,1.5A1.5,1.5,0,0,0,16,22Z'
transform='tran [...]
+ return "data:image/svg+xml,%3Csvg version='1.1' id='icon'
xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'
x='0px' y='0px' width='32px' height='32px' viewBox='0 0 32 32'
style='enable-background:new 0 0 32 32;' xml:space='preserve'%3E%3Cstyle
type='text/css'%3E .st0%7Bfill:none;%7D
.st1%7Bopacity:0;fill-opacity:0;%7D%0A%3C/style%3E%3Crect
id='_Transparent_Rectangle_' class='st0' width='32' height='32'/%3E%3Cpath
d='M16,2C8.3,2,2,8.3,2,16s6.3,1 [...]
case "OnExceptionDefinition":
- return "data:image/svg+xml,%3Csvg version='1.1' id='icon'
xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'
x='0px' y='0px' width='32px' height='32px' viewBox='0 0 32 32'
style='enable-background:new 0 0 32 32;' xml:space='preserve'%3E%3Cstyle
type='text/css'%3E .st0%7Bfill:none;%7D
.st1%7Bopacity:0;fill-opacity:0;%7D%0A%3C/style%3E%3Crect
id='Transparent_Rectangle' class='st0' width='32' height='32'/%3E%3Cpath
id='Compound_Path' d='M16,2C8.3,2 [...]
+ return "data:image/svg+xml,%3Csvg version='1.1' id='icon'
xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'
x='0px' y='0px' width='32px' height='32px' viewBox='0 0 32 32'
style='enable-background:new 0 0 32 32;' xml:space='preserve'%3E%3Cstyle
type='text/css'%3E
.st0%7Bfill:none;%7D%0A%3C/style%3E%3Ctitle%3Echeckmark%3C/title%3E%3Cpath
d='M16,2C8.2,2,2,8.2,2,16s6.2,14,14,14s14-6.2,14-14S23.8,2,16,2z
M16,28C9.4,28,4,22.6,4,16S9.4,4,16,4s12,5.4,1 [...]
default:
return camelIcon;
}
@@ -444,7 +450,6 @@ export class CamelUi {
static getIconForDslName = (dslName: string):JSX.Element => {
switch (dslName) {
case 'AggregateDefinition': return <AggregateIcon/>;
- case 'AggregateDefinition' :return <AggregateIcon/>;
case 'ChoiceDefinition' :return <ChoiceIcon/>;
case 'SplitDefinition' :return <SplitIcon/>;
case 'SagaDefinition' :return <SagaIcon/>;
diff --git a/karavan-designer/src/designer/utils/KubernetesAPI.ts
b/karavan-designer/src/designer/utils/KubernetesAPI.ts
new file mode 100644
index 0000000..5168bc3
--- /dev/null
+++ b/karavan-designer/src/designer/utils/KubernetesAPI.ts
@@ -0,0 +1,19 @@
+export class KubernetesAPI {
+
+ static inKubernetes: boolean = false;
+ static configMaps: string[] = [];
+ static secrets: string[] = [];
+ static services: string[] = [];
+
+ static setConfigMaps(configMaps: string[]){
+ this.configMaps = configMaps
+ }
+
+ static setSecrets(secrets: string[]){
+ this.secrets = secrets
+ }
+
+ static setServices(services: string[]){
+ this.services = services
+ }
+}
\ No newline at end of file