Skip to content

Commit

Permalink
Fix apache#2271: add support for beans in kamelets
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolaferraro committed Jun 9, 2021
1 parent 2f00e12 commit 9a0caed
Show file tree
Hide file tree
Showing 20 changed files with 275 additions and 89 deletions.
8 changes: 6 additions & 2 deletions config/crd/bases/camel.apache.org_kamelets.yaml
Expand Up @@ -214,8 +214,7 @@ spec:
type: string
type: array
flow:
description: Flow is an unstructured object representing a Camel Flow
in YAML/JSON DSL
description: 'Deprecated: use template'
type: object
x-kubernetes-preserve-unknown-fields: true
sources:
Expand Down Expand Up @@ -262,6 +261,11 @@ spec:
type: string
type: object
type: array
template:
description: Template is an unstructured object representing a Kamelet
template in YAML/JSON DSL
type: object
x-kubernetes-preserve-unknown-fields: true
types:
additionalProperties:
properties:
Expand Down
Expand Up @@ -214,8 +214,7 @@ spec:
type: string
type: array
flow:
description: Flow is an unstructured object representing a Camel Flow
in YAML/JSON DSL
description: 'Deprecated: use template'
type: object
x-kubernetes-preserve-unknown-fields: true
sources:
Expand Down Expand Up @@ -262,6 +261,11 @@ spec:
type: string
type: object
type: array
template:
description: Template is an unstructured object representing a Kamelet
template in YAML/JSON DSL
type: object
x-kubernetes-preserve-unknown-fields: true
types:
additionalProperties:
properties:
Expand Down
6 changes: 3 additions & 3 deletions e2e/knative/knative_platform_test.go
Expand Up @@ -33,7 +33,7 @@ import (

. "github.com/apache/camel-k/e2e/support"
"github.com/apache/camel-k/pkg/apis/camel/v1"
"github.com/apache/camel-k/pkg/util/flow"
"github.com/apache/camel-k/pkg/util/dsl"
"github.com/apache/camel-k/pkg/util/knative"
)

Expand All @@ -57,10 +57,10 @@ func TestKnativePlatform(t *testing.T) {
// Change something in the integration to produce a redeploy
Expect(UpdateIntegration(ns, "yaml", func(it *v1.Integration) {
it.Spec.Profile = ""
content, err := flow.ToYamlDSL(it.Spec.Flows)
content, err := dsl.ToYamlDSL(it.Spec.Flows)
assert.NoError(t, err)
newData := strings.ReplaceAll(string(content), "string!", "string!!!")
newFlows, err := flow.FromYamlDSLString(newData)
newFlows, err := dsl.FromYamlDSLString(newData)
assert.NoError(t, err)
it.Spec.Flows = newFlows
})).To(Succeed())
Expand Down
36 changes: 36 additions & 0 deletions e2e/yaks/common/kamelet-beans/beans-source.kamelet.yaml
@@ -0,0 +1,36 @@
# ---------------------------------------------------------------------------
# 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/v1alpha1
kind: Kamelet
metadata:
name: beans-source
labels:
camel.apache.org/kamelet.type: "source"
spec:
template:
beans:
- name: myBean
type: "#class:java.util.Date"
properties:
time: 0
from:
uri: timer:tick
steps:
- set-body:
simple: "Bean time is ${bean:{{myBean}}?method=getTime}!"
- to: "kamelet:sink"
15 changes: 15 additions & 0 deletions e2e/yaks/common/kamelet-beans/kamelet.feature
@@ -0,0 +1,15 @@
Feature: Kamelets can declare local beans

Background:
Given Disable auto removal of Kamelet resources
Given Disable auto removal of Kubernetes resources
Given Camel-K resource polling configuration
| maxAttempts | 40 |
| delayBetweenAttempts | 3000 |

Scenario: Kamelets templates can use beans
Given bind Kamelet beans-source to uri log:info
When create KameletBinding binding
Then KameletBinding binding should be available
Then Camel-K integration binding should be running
Then Camel-K integration binding should print Bean time is 0!
26 changes: 26 additions & 0 deletions e2e/yaks/common/kamelet-beans/yaks-config.yaml
@@ -0,0 +1,26 @@
# ---------------------------------------------------------------------------
# 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.
# ---------------------------------------------------------------------------

config:
namespace:
temporary: true
pre:
- name: installation
run: |
kamel install -n $YAKS_NAMESPACE
kubectl apply -f beans-source.kamelet.yaml -n $YAKS_NAMESPACE
8 changes: 6 additions & 2 deletions helm/camel-k/crds/crd-kamelet.yaml
Expand Up @@ -214,8 +214,7 @@ spec:
type: string
type: array
flow:
description: Flow is an unstructured object representing a Camel Flow
in YAML/JSON DSL
description: 'Deprecated: use template'
type: object
x-kubernetes-preserve-unknown-fields: true
sources:
Expand Down Expand Up @@ -262,6 +261,11 @@ spec:
type: string
type: object
type: array
template:
description: Template is an unstructured object representing a Kamelet
template in YAML/JSON DSL
type: object
x-kubernetes-preserve-unknown-fields: true
types:
additionalProperties:
properties:
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/camel/v1/common_types.go
Expand Up @@ -162,6 +162,11 @@ type Flow struct {
RawMessage `json:",inline"`
}

// Template is an unstructured object representing a Kamelet template in YAML/JSON DSL
type Template struct {
RawMessage `json:",inline"`
}

// RuntimeProvider --
type RuntimeProvider string

Expand Down
8 changes: 6 additions & 2 deletions pkg/apis/camel/v1alpha1/kamelet_types.go
Expand Up @@ -35,8 +35,10 @@ var (

// KameletSpec defines the desired state of Kamelet
type KameletSpec struct {
Definition *JSONSchemaProps `json:"definition,omitempty"`
Sources []camelv1.SourceSpec `json:"sources,omitempty"`
Definition *JSONSchemaProps `json:"definition,omitempty"`
Sources []camelv1.SourceSpec `json:"sources,omitempty"`
Template *camelv1.Template `json:"template,omitempty"`
// Deprecated: use template
Flow *camelv1.Flow `json:"flow,omitempty"`
Authorization *AuthorizationSpec `json:"authorization,omitempty"`
Types map[EventSlot]EventTypeSpec `json:"types,omitempty"`
Expand Down Expand Up @@ -100,6 +102,8 @@ const (
KameletConditionReasonInvalidName string = "InvalidName"
// KameletConditionReasonInvalidProperty --
KameletConditionReasonInvalidProperty string = "InvalidProperty"
// KameletConditionReasonInvalidTemplate --
KameletConditionReasonInvalidTemplate string = "InvalidTemplate"
)

type KameletPhase string
Expand Down
10 changes: 10 additions & 0 deletions pkg/apis/camel/v1alpha1/kamelet_types_support.go
Expand Up @@ -150,3 +150,13 @@ func ValidKameletProperties(kamelet *Kamelet) bool {
}
return true
}

func ValidKameletTemplate(kamelet *Kamelet) bool {
if kamelet == nil {
return true
}
if kamelet.Spec.Template != nil && kamelet.Spec.Flow != nil {
return false
}
return true
}
4 changes: 2 additions & 2 deletions pkg/cmd/run.go
Expand Up @@ -46,7 +46,7 @@ import (
"github.com/apache/camel-k/pkg/client"
"github.com/apache/camel-k/pkg/trait"
"github.com/apache/camel-k/pkg/util"
"github.com/apache/camel-k/pkg/util/flow"
"github.com/apache/camel-k/pkg/util/dsl"
"github.com/apache/camel-k/pkg/util/kubernetes"
k8slog "github.com/apache/camel-k/pkg/util/kubernetes/log"
"github.com/apache/camel-k/pkg/util/sync"
Expand Down Expand Up @@ -516,7 +516,7 @@ func (o *runCmdOptions) updateIntegrationCode(c client.Client, sources []string,

for _, source := range resolvedSources {
if o.UseFlows && !o.Compression && (strings.HasSuffix(source.Name, ".yaml") || strings.HasSuffix(source.Name, ".yml")) {
flows, err := flow.FromYamlDSLString(source.Content)
flows, err := dsl.FromYamlDSLString(source.Content)
if err != nil {
return nil, err
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/kamelet/initialize.go
Expand Up @@ -49,6 +49,15 @@ func Initialize(kamelet *v1alpha1.Kamelet) (*v1alpha1.Kamelet, error) {
fmt.Sprintf("Kamelet property %q is reserved and cannot be part of the schema", v1alpha1.KameletIDProperty),
)
}
if !v1alpha1.ValidKameletTemplate(kamelet) {
ok = false
target.Status.SetCondition(
v1alpha1.KameletConditionReady,
corev1.ConditionFalse,
v1alpha1.KameletConditionReasonInvalidTemplate,
`Kamelet can only specify one of "flow" or "template"`,
)
}

if !ok {
target.Status.Phase = v1alpha1.KameletPhaseError
Expand Down
4 changes: 2 additions & 2 deletions pkg/trait/init.go
Expand Up @@ -24,7 +24,7 @@ import (

v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
"github.com/apache/camel-k/pkg/util"
"github.com/apache/camel-k/pkg/util/flow"
"github.com/apache/camel-k/pkg/util/dsl"
)

const flowsInternalSourceName = "camel-k-embedded-flow.yaml"
Expand Down Expand Up @@ -53,7 +53,7 @@ func (t *initTrait) Apply(e *Environment) error {

// Flows need to be turned into a generated source
if len(e.Integration.Spec.Flows) > 0 {
content, err := flow.ToYamlDSL(e.Integration.Spec.Flows)
content, err := dsl.ToYamlDSL(e.Integration.Spec.Flows)
if err != nil {
return err
}
Expand Down
33 changes: 12 additions & 21 deletions pkg/trait/kamelets.go
Expand Up @@ -33,7 +33,7 @@ import (
"github.com/apache/camel-k/pkg/platform"
"github.com/apache/camel-k/pkg/util"
"github.com/apache/camel-k/pkg/util/digest"
"github.com/apache/camel-k/pkg/util/flow"
"github.com/apache/camel-k/pkg/util/dsl"
"github.com/apache/camel-k/pkg/util/kubernetes"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -225,28 +225,27 @@ func (t *kameletsTrait) configureApplicationProperties(e *Environment) error {
func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kamelet) error {
sources := make([]v1.SourceSpec, 0)

if kamelet.Spec.Flow != nil {

flowData, err := flow.ToYamlDSL([]v1.Flow{*kamelet.Spec.Flow})
if kamelet.Spec.Template != nil || kamelet.Spec.Flow != nil {
template := kamelet.Spec.Template
if template == nil {
// Backward compatibility with Kamelets using flow
template = &v1.Template{
RawMessage: kamelet.Spec.Flow.RawMessage,
}
}
flowData, err := dsl.TemplateToYamlDSL(*template, kamelet.Name)
if err != nil {
return err
}

propertyNames := make([]string, 0, len(kamelet.Status.Properties))
for _, p := range kamelet.Status.Properties {
propertyNames = append(propertyNames, p.Name)
}

flowSource := v1.SourceSpec{
DataSpec: v1.DataSpec{
Name: fmt.Sprintf("%s.yaml", kamelet.Name),
Content: string(flowData),
},
Language: v1.LanguageYaml,
Type: v1.SourceTypeTemplate,
PropertyNames: propertyNames,
Language: v1.LanguageYaml,
}
flowSource, err = integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-flow", e.Integration.Name, kamelet.Name))
flowSource, err = integrationSourceFromKameletSource(e, kamelet, flowSource, fmt.Sprintf("%s-kamelet-%s-template", e.Integration.Name, kamelet.Name))
if err != nil {
return err
}
Expand All @@ -261,11 +260,7 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kam
sources = append(sources, intSource)
}

kameletCounter := 0
for _, source := range sources {
if source.Type == v1.SourceTypeTemplate {
kameletCounter++
}
replaced := false
for idx, existing := range e.Integration.Status.GeneratedSources {
if existing.Name == source.Name {
Expand All @@ -278,10 +273,6 @@ func (t *kameletsTrait) addKameletAsSource(e *Environment, kamelet *v1alpha1.Kam
}
}

if kameletCounter > 1 {
return fmt.Errorf(`kamelet %s contains %d sources of type "kamelet": at most one is allowed`, kamelet.Name, kameletCounter)
}

return nil
}

Expand Down

0 comments on commit 9a0caed

Please sign in to comment.