Skip to content

Commit

Permalink
feat(trait): moved runtime to camel trait
Browse files Browse the repository at this point in the history
* Camel trait is the most suitable to control how properties are managed
* Some refactoring in trait_test.go as the properties configmap is now managed by camel trait

Closes apache#2320
  • Loading branch information
squakez committed Sep 24, 2021
1 parent 35ec5ed commit a181d89
Show file tree
Hide file tree
Showing 13 changed files with 223 additions and 369 deletions.
1 change: 0 additions & 1 deletion docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
** xref:traits:pull-secret.adoc[Pull Secret]
** xref:traits:quarkus.adoc[Quarkus]
** xref:traits:route.adoc[Route]
** xref:traits:runtime.adoc[Runtime]
** xref:traits:service-binding.adoc[Service Binding]
** xref:traits:service.adoc[Service]
** xref:traits:toleration.adoc[Toleration]
Expand Down
4 changes: 4 additions & 0 deletions docs/modules/traits/pages/camel.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ The following configuration options are available:
| string
| The camel-k-runtime version to use for the integration. It overrides the default version set in the Integration Platform.

| camel.properties
| []string
| A list of properties to be provided to the Integration runtime

|===

// End of autogenerated code - DO NOT EDIT! (configuration)
2 changes: 1 addition & 1 deletion docs/modules/traits/pages/istio.adoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
= Istio Trait

// Start of autogenerated code - DO NOT EDIT! (description)
The Istio trait allows to configure properties related to the Istio service mesh,
The Istio trait allows configuring properties related to the Istio service mesh,
such as sidecar injection and outbound IP ranges.


Expand Down
2 changes: 1 addition & 1 deletion e2e/common/cli/duplicate_parameters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ func TestDuplicateParameters(t *testing.T) {
// the command is executed inside GetOutputString function
commOutput := GetOutputString(comm)

outParams := `"traits":{"affinity":{"configuration":{"enabled":true}},"configuration":{"configuration":{"properties":["prop1 = true","prop2 = true","foo = bar"]}},"pull-secret":{"configuration":{"enabled":true}},"tracing":{"configuration":{"enabled":true}}}`
outParams := `"traits":{"affinity":{"configuration":{"enabled":true}},"camel":{"configuration":{"properties":["prop1 = true","prop2 = true","foo = bar"]}},"pull-secret":{"configuration":{"enabled":true}},"tracing":{"configuration":{"enabled":true}}}`
Expect(commOutput).To(ContainSubstring(outParams))
}
2 changes: 1 addition & 1 deletion pkg/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C
}
for _, key := range props.Keys() {
kv := fmt.Sprintf("%s=%s", key, props.GetString(key, ""))
if propsTraits, err := convertToTraitParameter(kv, "runtime.properties"); err != nil {
if propsTraits, err := convertToTraitParameter(kv, "camel.properties"); err != nil {
return nil, err
} else {
o.Traits = append(o.Traits, propsTraits...)
Expand Down
174 changes: 174 additions & 0 deletions pkg/trait/camel.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,18 @@ package trait
import (
"context"
"fmt"
"strconv"
"strings"

"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrl "sigs.k8s.io/controller-runtime/pkg/client"

v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
"github.com/apache/camel-k/pkg/util/camel"
"github.com/apache/camel-k/pkg/util/maven"
"github.com/apache/camel-k/pkg/util/property"
)

// The Camel trait can be used to configure versions of Apache Camel K runtime and related libraries, it cannot be disabled.
Expand All @@ -36,6 +41,8 @@ type camelTrait struct {
BaseTrait `property:",squash"`
// The camel-k-runtime version to use for the integration. It overrides the default version set in the Integration Platform.
RuntimeVersion string `property:"runtime-version" json:"runtimeVersion,omitempty"`
// A list of properties to be provided to the Integration runtime
Properties []string `property:"properties" json:"properties,omitempty"`
}

func newCamelTrait() Trait {
Expand Down Expand Up @@ -73,6 +80,17 @@ func (t *camelTrait) Apply(e *Environment) error {
e.IntegrationKit.Status.RuntimeProvider = e.CamelCatalog.Runtime.Provider
}

if e.InPhase(v1.IntegrationKitPhaseReady, v1.IntegrationPhaseDeploying) ||
e.InPhase(v1.IntegrationKitPhaseReady, v1.IntegrationPhaseRunning) {
// Get all resources
maps := t.computeConfigMaps(e)
if t.Properties != nil {
// Only user.properties
maps = append(maps, t.computeUserProperties(e)...)
}
e.Resources.AddAll(maps)
}

return nil
}

Expand Down Expand Up @@ -152,3 +170,159 @@ func (t *camelTrait) determineRuntimeVersion(e *Environment) string {
func (t *camelTrait) IsPlatformTrait() bool {
return true
}

func (t *camelTrait) computeConfigMaps(e *Environment) []ctrl.Object {
sources := e.Integration.Sources()
maps := make([]ctrl.Object, 0, len(sources)+1)

// combine properties of integration with kit, integration
// properties have the priority
userProperties := ""

for _, prop := range e.collectConfigurationPairs("property") {
// properties in resource configuration are expected to be pre-encoded using properties format
userProperties += fmt.Sprintf("%s=%s\n", prop.Name, prop.Value)
}

if userProperties != "" {
maps = append(
maps,
&corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: e.Integration.Name + "-user-properties",
Namespace: e.Integration.Namespace,
Labels: map[string]string{
v1.IntegrationLabel: e.Integration.Name,
"camel.apache.org/properties.type": "user",
},
},
Data: map[string]string{
"application.properties": userProperties,
},
},
)
}

for i, s := range sources {
if s.ContentRef != "" {
continue
}

cm := corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-source-%03d", e.Integration.Name, i),
Namespace: e.Integration.Namespace,
Labels: map[string]string{
v1.IntegrationLabel: e.Integration.Name,
},
Annotations: map[string]string{
"camel.apache.org/source.language": string(s.InferLanguage()),
"camel.apache.org/source.loader": s.Loader,
"camel.apache.org/source.name": s.Name,
"camel.apache.org/source.compression": strconv.FormatBool(s.Compression),
},
},
Data: map[string]string{
"content": s.Content,
},
}

maps = append(maps, &cm)
}

for i, r := range e.Integration.Spec.Resources {
if r.Type == v1.ResourceTypeOpenAPI {
continue
}
if r.ContentRef != "" {
continue
}

cmKey := "content"
if r.ContentKey != "" {
cmKey = r.ContentKey
}

cm := corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-resource-%03d", e.Integration.Name, i),
Namespace: e.Integration.Namespace,
Labels: map[string]string{
"camel.apache.org/integration": e.Integration.Name,
},
Annotations: map[string]string{
"camel.apache.org/resource.name": r.Name,
"camel.apache.org/resource.compression": strconv.FormatBool(r.Compression),
},
},
}

if r.ContentType != "" {
cm.Annotations["camel.apache.org/resource.content-type"] = r.ContentType
}

if r.RawContent != nil {
cm.BinaryData = map[string][]byte{
cmKey: r.RawContent,
}
} else {
cm.Data = map[string]string{
cmKey: r.Content,
}
}

maps = append(maps, &cm)
}

return maps
}

func (t *camelTrait) computeUserProperties(e *Environment) []ctrl.Object {
maps := make([]ctrl.Object, 0)

// combine properties of integration with kit, integration
// properties have the priority
userProperties := ""

for _, prop := range t.Properties {
k, v := property.SplitPropertyFileEntry(prop)
userProperties += fmt.Sprintf("%s=%s\n", k, v)
}

if userProperties != "" {
maps = append(
maps,
&corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: e.Integration.Name + "-user-properties",
Namespace: e.Integration.Namespace,
Labels: map[string]string{
v1.IntegrationLabel: e.Integration.Name,
"camel.apache.org/properties.type": "user",
},
},
Data: map[string]string{
"application.properties": userProperties,
},
},
)
}

return maps
}
34 changes: 33 additions & 1 deletion pkg/trait/camel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@ import (
"context"
"testing"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
"github.com/apache/camel-k/pkg/util/camel"
"github.com/apache/camel-k/pkg/util/kubernetes"
"github.com/apache/camel-k/pkg/util/test"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -90,12 +92,42 @@ func createNominalCamelTest() (*camelTrait, *Environment) {
ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace",
},
Spec: v1.IntegrationSpec{
Traits: make(map[string]v1.TraitSpec),
},
Status: v1.IntegrationStatus{
RuntimeVersion: "0.0.1",
Phase: v1.IntegrationPhaseDeploying,
},
},
IntegrationKit: &v1.IntegrationKit{
Status: v1.IntegrationKitStatus{
Phase: v1.IntegrationKitPhaseReady,
},
},
IntegrationKit: &v1.IntegrationKit{},
Platform: &v1.IntegrationPlatform{
ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace",
},
},
Resources: kubernetes.NewCollection(),
ApplicationProperties: make(map[string]string),
}

return trait, environment
}

func TestApplyCamelTraitWithProperties(t *testing.T) {
camelTrait, environment := createNominalCamelTest()
camelTrait.Properties = []string{"a=b", "c=d"}
err := camelTrait.Apply(environment)
assert.Nil(t, err)

userPropertiesCm := environment.Resources.GetConfigMap(func(cm *corev1.ConfigMap) bool {
return cm.Labels["camel.apache.org/properties.type"] == "user"
})
assert.NotNil(t, userPropertiesCm)
assert.Equal(t, map[string]string{
"application.properties": "a=b\nc=d\n",
}, userPropertiesCm.Data)
}
Loading

0 comments on commit a181d89

Please sign in to comment.