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 bd007b53bbb8161c1a1b488cfa2bd10fdcd21a45 Author: Marat Gubaidullin <ma...@talismancloud.io> AuthorDate: Tue Oct 31 17:01:03 2023 -0400 Fix for #315 --- karavan-core/src/core/api/CamelDefinitionYaml.ts | 10 ++++ karavan-core/src/core/api/CamelUtil.ts | 33 ++++++++--- karavan-core/test/createKamelet.spec.ts | 38 ++++++++++++ karavan-core/test/timer-source.kamelet.yaml | 75 ++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 7 deletions(-) diff --git a/karavan-core/src/core/api/CamelDefinitionYaml.ts b/karavan-core/src/core/api/CamelDefinitionYaml.ts index 7916801a..adc0cd3b 100644 --- a/karavan-core/src/core/api/CamelDefinitionYaml.ts +++ b/karavan-core/src/core/api/CamelDefinitionYaml.ts @@ -41,10 +41,20 @@ export class CamelDefinitionYaml { const route: RouteDefinition = clone.spec.flows.filter((f: any) => f.dslName === 'RouteDefinition')?.[0]; if (route) { template.route = Object.assign(template.route, route); + } else if (clone.spec.template?.route) { + template.route = clone.spec.template.route; + } else if (clone.spec.template?.from) { + template.route = {from: clone.spec.template?.from}; + } + const from: RouteDefinition = clone.spec.flows.filter((f: any) => f.dslName === 'FromDefinition')?.[0]; + if (from) { + template.from = {from: from}; } const beans = clone.spec.flows.filter((f: any) => f.dslName === 'Beans')?.at(0)?.beans; if (beans) { template.beans = beans; + } else if (clone.spec.template?.beans){ + template.beans = clone.spec.template.beans; } clone.spec.template = template; delete clone.spec.flows; diff --git a/karavan-core/src/core/api/CamelUtil.ts b/karavan-core/src/core/api/CamelUtil.ts index 93544263..f98323e2 100644 --- a/karavan-core/src/core/api/CamelUtil.ts +++ b/karavan-core/src/core/api/CamelUtil.ts @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Integration, CamelElement, Beans } from '../model/IntegrationDefinition'; +import { Integration, CamelElement, Beans, MetadataLabels, KameletTypes } from '../model/IntegrationDefinition'; import { CamelDefinitionApi } from './CamelDefinitionApi'; import { KameletDefinition, @@ -29,9 +29,11 @@ import { ComponentApi } from './ComponentApi'; import { CamelMetadataApi } from '../model/CamelMetadata'; import { CamelDefinitionApiExt } from './CamelDefinitionApiExt'; import { v4 as uuidv4 } from 'uuid'; +import { CamelDefinitionYaml } from './CamelDefinitionYaml'; export class CamelUtil { - private constructor() {} + private constructor() { + } static cloneIntegration = (integration: Integration): Integration => { const clone = JSON.parse(JSON.stringify(integration)); @@ -161,7 +163,7 @@ export class CamelUtil { static getKameletProperties = (element: any, requiredOnly: boolean = false): Property[] => { const kamelet = CamelUtil.getKamelet(element); - const props:Property[] = kamelet ? KameletApi.getKameletProperties(kamelet?.metadata.name) : []; + const props: Property[] = kamelet ? KameletApi.getKameletProperties(kamelet?.metadata.name) : []; if (requiredOnly) { const required = kamelet?.spec.definition.required; return props.filter(value => required?.includes(value.id)); @@ -188,9 +190,9 @@ export class CamelUtil { const component = ComponentApi.findByName(name); return component ? ComponentApi.getComponentProperties( - component?.component.name, - element.dslName === 'FromDefinition' ? 'consumer' : 'producer', - ) + component?.component.name, + element.dslName === 'FromDefinition' ? 'consumer' : 'producer', + ) : []; } else { return []; @@ -215,7 +217,7 @@ export class CamelUtil { result[1].push(`${property.displayName} is required`); } else if (property.type === 'ExpressionDefinition') { const expressionMeta = CamelMetadataApi.getCamelModelMetadataByClassName('ExpressionDefinition'); - const expressionCheck = expressionMeta && value!== undefined && expressionMeta?.properties.some(ep => { + const expressionCheck = expressionMeta && value !== undefined && expressionMeta?.properties.some(ep => { const expValue = value[ep.name]; if (expValue) { const checkedExpression = CamelUtil.checkRequired(expValue); @@ -312,4 +314,21 @@ export class CamelUtil { const placeholder = val?.substring(start, end)?.trim(); return [result, placeholder]; }; + + static createNewKameletCode = (kameletName: string, kameletType: KameletTypes, copyFromKameletName?: string): string => { + const integration = Integration.createNew(kameletName, 'kamelet'); + const meta: MetadataLabels = new MetadataLabels({ 'camel.apache.org/kamelet.type': kameletType }); + integration.metadata.labels = meta; + if (copyFromKameletName !== undefined && copyFromKameletName !== '') { + const kamelet = KameletApi.getKamelets().filter(k => k.metadata.name === copyFromKameletName).at(0); + if (kamelet) { + (integration as any).spec = kamelet.spec; + (integration as any).metadata.labels = kamelet.metadata.labels; + (integration as any).metadata.annotations = kamelet.metadata.annotations; + const i = CamelUtil.cloneIntegration(integration); + return CamelDefinitionYaml.integrationToYaml(i); + } + } + return CamelDefinitionYaml.integrationToYaml(integration); + }; } diff --git a/karavan-core/test/createKamelet.spec.ts b/karavan-core/test/createKamelet.spec.ts new file mode 100644 index 00000000..f675aa60 --- /dev/null +++ b/karavan-core/test/createKamelet.spec.ts @@ -0,0 +1,38 @@ +/* + * 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 { expect } from 'chai'; +import * as fs from 'fs'; +import 'mocha'; +import { CamelUtil } from '../src/core/api/CamelUtil'; +import { KameletApi } from '../src/core/api/KameletApi'; + + +describe('Create Kamelet', () => { + + it('Create new Kamelet from existing', () => { + const kamelet = fs.readFileSync('test/timer-source.kamelet.yaml', { encoding: 'utf8', flag: 'r' }); + KameletApi.saveKamelets([kamelet]); + const code = CamelUtil.createNewKameletCode("custom-timer-source.kamelet.yaml", 'source', "timer-source") + console.log(code); + // if (i.spec.flows) { + // expect(i.spec.flows[2].beans[0].name).to.equal('myNested'); + // expect(i.spec.flows[2].beans[0].type).to.equal('${MyBean.class.name}'); + // expect(i.spec.flows[2].beans[0].properties['nested.foo']).to.equal('valueFoo'); + // expect(i.spec.flows[2].beans[1].name).to.equal('myProps'); + // } + }); +}); diff --git a/karavan-core/test/timer-source.kamelet.yaml b/karavan-core/test/timer-source.kamelet.yaml new file mode 100644 index 00000000..e72b6034 --- /dev/null +++ b/karavan-core/test/timer-source.kamelet.yaml @@ -0,0 +1,75 @@ +# --------------------------------------------------------------------------- +# 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. +# --------------------------------------------------------------------------- + +apiVersion: camel.apache.org/v1 +kind: Kamelet +metadata: + name: timer-source + annotations: + camel.apache.org/kamelet.support.level: "Stable" + camel.apache.org/catalog.version: "4.2.0-SNAPSHOT" + camel.apache.org/kamelet.icon: data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gU3ZnIFZlY3RvciBJY29ucyA6IGh0dHA6Ly93d3cub25saW5ld2ViZm9udHMuY29tL2ljb24gLS0+DQo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm9 [...] + camel.apache.org/provider: "Apache Software Foundation" + camel.apache.org/kamelet.group: "Timer" + camel.apache.org/kamelet.namespace: "Scheduling" + labels: + camel.apache.org/kamelet.type: source + camel.apache.org/kamelet.verified: "true" +spec: + definition: + title: Timer Source + description: Produces periodic messages with a custom payload. + required: + - message + type: object + properties: + period: + title: Period + description: "The interval (in milliseconds) to wait between producing the next message." + type: integer + default: 1000 + message: + title: Message + description: The message to generate. + type: string + example: hello world + contentType: + title: Content Type + description: The content type of the generated message. + type: string + default: text/plain + repeatCount: + title: Repeat Count + description: Specifies a maximum limit of number of fires + type: integer + dependencies: + - "camel:core" + - "camel:timer" + - "camel:kamelet" + template: + from: + uri: timer:tick + parameters: + period: "{{period}}" + repeatCount: "{{?repeatCount}}" + steps: + - set-body: + constant: "{{message}}" + - set-header: + name: "Content-Type" + constant: "{{contentType}}" + - to: kamelet:sink \ No newline at end of file