Skip to content

Commit

Permalink
Make it possible to define the ocontainer image without IntegrationKit
Browse files Browse the repository at this point in the history
  • Loading branch information
lburgazzoli authored and astefanutti committed Jun 7, 2021
1 parent 764b2d4 commit c37f1f7
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 33 deletions.
42 changes: 22 additions & 20 deletions pkg/controller/integration/initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,30 +55,32 @@ func (action *initializeAction) Handle(ctx context.Context, integration *v1.Inte
return nil, err
}

if integration.Spec.IntegrationKit == nil && integration.Spec.Kit != "" {
// TODO: temporary fallback until deprecated field gets removed
integration.Spec.IntegrationKit = &corev1.ObjectReference{
Name: integration.Spec.Kit,
if integration.Status.IntegrationKit == nil {
if integration.Spec.IntegrationKit == nil && integration.Spec.Kit != "" {
// TODO: temporary fallback until deprecated field gets removed
integration.Spec.IntegrationKit = &corev1.ObjectReference{
Name: integration.Spec.Kit,
}
}
}

if integration.Spec.IntegrationKit != nil && integration.Spec.IntegrationKit.Name != "" {
kitNamespace := integration.Spec.IntegrationKit.Namespace
kitName := integration.Spec.IntegrationKit.Name

if kitNamespace == "" {
pl, err := platform.GetCurrent(ctx, action.client, integration.Namespace)
if err != nil && !k8serrors.IsNotFound(err) {
return nil, err
}
if pl != nil {
kitNamespace = pl.Namespace
if integration.Spec.IntegrationKit != nil && integration.Spec.IntegrationKit.Name != "" {
kitNamespace := integration.Spec.IntegrationKit.Namespace
kitName := integration.Spec.IntegrationKit.Name

if kitNamespace == "" {
pl, err := platform.GetCurrent(ctx, action.client, integration.Namespace)
if err != nil && !k8serrors.IsNotFound(err) {
return nil, err
}
if pl != nil {
kitNamespace = pl.Namespace
}
}
kit := v1.NewIntegrationKit(kitNamespace, kitName)
integration.SetIntegrationKit(&kit)
} else {
integration.Status.IntegrationKit = nil
}
kit := v1.NewIntegrationKit(kitNamespace, kitName)
integration.SetIntegrationKit(&kit)
} else {
integration.Status.IntegrationKit = nil
}

integration.Status.Phase = v1.IntegrationPhaseBuildingKit
Expand Down
5 changes: 5 additions & 0 deletions pkg/controller/integrationkit/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ func (action *monitorAction) Handle(ctx context.Context, kit *v1.IntegrationKit)

return kit, nil
}
if kit.Spec.Image != "" && kit.Spec.Image != kit.Status.Image {
kit.Status.Phase = v1.IntegrationKitPhaseInitialization

return kit, nil
}

return nil, nil
}
4 changes: 2 additions & 2 deletions pkg/resources/resources.go

Large diffs are not rendered by default.

54 changes: 43 additions & 11 deletions pkg/trait/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ type containerTrait struct {

// The main container name. It's named `integration` by default.
Name string `property:"name" json:"name,omitempty"`
// The main container image
Image string `property:"image" json:"image,omitempty"`

// ProbesEnabled enable/disable probes on the container (default `false`)
ProbesEnabled *bool `property:"probes-enabled" json:"probesEnabled,omitempty"`
Expand Down Expand Up @@ -141,7 +143,7 @@ func (t *containerTrait) Configure(e *Environment) (bool, error) {

func (t *containerTrait) Apply(e *Environment) error {
if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
t.configureDependencies(e)
return t.configureDependencies(e)
}

if e.IntegrationInPhase(v1.IntegrationPhaseDeploying, v1.IntegrationPhaseRunning) {
Expand All @@ -156,21 +158,51 @@ func (t *containerTrait) IsPlatformTrait() bool {
return true
}

func (t *containerTrait) configureDependencies(e *Environment) {
if util.IsNilOrFalse(t.ProbesEnabled) {
return
}

func (t *containerTrait) configureDependencies(e *Environment) error {
if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
if capability, ok := e.CamelCatalog.Runtime.Capabilities[v1.CapabilityHealth]; ok {
for _, dependency := range capability.Dependencies {
util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, dependency.GetDependencyID())
if t.Image != "" {
if e.Integration.Spec.IntegrationKit != nil {
return fmt.Errorf(
"unsupported configuration: a container image has been set in conjunction with an IntegrationKit %v",
e.Integration.Spec.IntegrationKit)
}
if e.Integration.Spec.Kit != "" {
return fmt.Errorf(
"unsupported configuration: a container image has been set in conjunction with an IntegrationKit %s",
e.Integration.Spec.Kit)
}

kitName := fmt.Sprintf("kit-%s", e.Integration.Name)
kit := v1.NewIntegrationKit(e.Integration.Namespace, kitName)
kit.Spec.Image = t.Image

// Add some information for post-processing, this may need to be refactored
// to a proper data structure
kit.Labels = map[string]string{
"camel.apache.org/kit.type": v1.IntegrationKitTypeExternal,
"camel.apache.org/created.by.kind": v1.IntegrationKind,
"camel.apache.org/created.by.name": e.Integration.Name,
"camel.apache.org/created.by.namespace": e.Integration.Namespace,
"camel.apache.org/created.by.version": e.Integration.ResourceVersion,
}

// sort the dependencies to get always the same list if they don't change
sort.Strings(e.Integration.Status.Dependencies)
t.L.Infof("image %s", kit.Spec.Image)
e.Resources.Add(&kit)
e.Integration.SetIntegrationKit(&kit)
}
if util.IsTrue(t.ProbesEnabled) {
if capability, ok := e.CamelCatalog.Runtime.Capabilities[v1.CapabilityHealth]; ok {
for _, dependency := range capability.Dependencies {
util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, dependency.GetDependencyID())
}

// sort the dependencies to get always the same list if they don't change
sort.Strings(e.Integration.Status.Dependencies)
}
}
}

return nil
}

// nolint:gocyclo
Expand Down
179 changes: 179 additions & 0 deletions pkg/trait/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@ package trait

import (
"context"
"github.com/google/uuid"
"k8s.io/apimachinery/pkg/types"
"testing"

"github.com/stretchr/testify/assert"

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"
Expand Down Expand Up @@ -148,3 +151,179 @@ func TestContainerWithCustomName(t *testing.T) {
trait := test.TraitSpecToMap(t, environment.Integration.Spec.Traits["container"])
assert.Equal(t, trait["name"], d.Spec.Template.Spec.Containers[0].Name)
}

func TestContainerWithCustomImage(t *testing.T) {
catalog, err := camel.DefaultCatalog()
assert.Nil(t, err)

client, _ := test.NewFakeClient()
traitCatalog := NewCatalog(context.TODO(), nil)

environment := Environment{
C: context.TODO(),
Client: client,
CamelCatalog: catalog,
Catalog: traitCatalog,
Integration: &v1.Integration{
ObjectMeta: metav1.ObjectMeta{
Name: ServiceTestName,
Namespace: "ns",
UID: types.UID(uuid.NewString()),
},
Status: v1.IntegrationStatus{
Phase: v1.IntegrationPhaseInitialization,
},
Spec: v1.IntegrationSpec{
Profile: v1.TraitProfileKubernetes,
Traits: map[string]v1.TraitSpec{
"container": test.TraitSpecFromMap(t, map[string]interface{}{
"image": "foo/bar:1.0.0",
}),
},
},
},
Platform: &v1.IntegrationPlatform{
Spec: v1.IntegrationPlatformSpec{
Cluster: v1.IntegrationPlatformClusterOpenShift,
Build: v1.IntegrationPlatformBuildSpec{
PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyS2I,
Registry: v1.IntegrationPlatformRegistrySpec{Address: "registry"},
},
},
},
EnvVars: make([]corev1.EnvVar, 0),
ExecutedTraits: make([]Trait, 0),
Resources: kubernetes.NewCollection(),
}
environment.Platform.ResyncStatusFullConfig()

err = traitCatalog.apply(&environment)
assert.Nil(t, err)

for _, postAction := range environment.PostActions {
assert.Nil(t, postAction(&environment))
}

assert.NotEmpty(t, environment.ExecutedTraits)
assert.NotNil(t, environment.GetTrait("deployer"))
assert.NotNil(t, environment.GetTrait("container"))
assert.Equal(t, "kit-"+ServiceTestName, environment.Integration.Status.IntegrationKit.Name)

ikt := v1.IntegrationKit{}
key := ctrl.ObjectKey{
Namespace: "ns",
Name: "kit-" + ServiceTestName,
}

err = client.Get(context.TODO(), key, &ikt)
assert.Nil(t, err)
assert.Equal(t, environment.Integration.ObjectMeta.UID, ikt.ObjectMeta.OwnerReferences[0].UID)

trait := test.TraitSpecToMap(t, environment.Integration.Spec.Traits["container"])
assert.Equal(t, trait["image"], ikt.Spec.Image)
}

func TestContainerWithCustomImageAndIntegrationKit(t *testing.T) {
catalog, err := camel.DefaultCatalog()
assert.Nil(t, err)

client, _ := test.NewFakeClient()
traitCatalog := NewCatalog(context.TODO(), nil)

environment := Environment{
C: context.TODO(),
Client: client,
CamelCatalog: catalog,
Catalog: traitCatalog,
Integration: &v1.Integration{
ObjectMeta: metav1.ObjectMeta{
Name: ServiceTestName,
Namespace: "ns",
UID: types.UID(uuid.NewString()),
},
Status: v1.IntegrationStatus{
Phase: v1.IntegrationPhaseInitialization,
},
Spec: v1.IntegrationSpec{
Profile: v1.TraitProfileKubernetes,
Traits: map[string]v1.TraitSpec{
"container": test.TraitSpecFromMap(t, map[string]interface{}{
"image": "foo/bar:1.0.0",
}),
},
IntegrationKit: &corev1.ObjectReference{
Name: "bad-" + ServiceTestName,
Namespace: "ns",
},
},
},
Platform: &v1.IntegrationPlatform{
Spec: v1.IntegrationPlatformSpec{
Cluster: v1.IntegrationPlatformClusterOpenShift,
Build: v1.IntegrationPlatformBuildSpec{
PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyS2I,
Registry: v1.IntegrationPlatformRegistrySpec{Address: "registry"},
},
},
},
EnvVars: make([]corev1.EnvVar, 0),
ExecutedTraits: make([]Trait, 0),
Resources: kubernetes.NewCollection(),
}
environment.Platform.ResyncStatusFullConfig()

err = traitCatalog.apply(&environment)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "unsupported configuration: a container image has been set in conjunction with an IntegrationKit")
}

func TestContainerWithCustomImageAndDeprecatedIntegrationKit(t *testing.T) {
catalog, err := camel.DefaultCatalog()
assert.Nil(t, err)

client, _ := test.NewFakeClient()
traitCatalog := NewCatalog(context.TODO(), nil)

environment := Environment{
C: context.TODO(),
Client: client,
CamelCatalog: catalog,
Catalog: traitCatalog,
Integration: &v1.Integration{
ObjectMeta: metav1.ObjectMeta{
Name: ServiceTestName,
Namespace: "ns",
UID: types.UID(uuid.NewString()),
},
Status: v1.IntegrationStatus{
Phase: v1.IntegrationPhaseInitialization,
},
Spec: v1.IntegrationSpec{
Profile: v1.TraitProfileKubernetes,
Traits: map[string]v1.TraitSpec{
"container": test.TraitSpecFromMap(t, map[string]interface{}{
"image": "foo/bar:1.0.0",
}),
},
Kit: "bad-" + ServiceTestName,
},
},
Platform: &v1.IntegrationPlatform{
Spec: v1.IntegrationPlatformSpec{
Cluster: v1.IntegrationPlatformClusterOpenShift,
Build: v1.IntegrationPlatformBuildSpec{
PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyS2I,
Registry: v1.IntegrationPlatformRegistrySpec{Address: "registry"},
},
},
},
EnvVars: make([]corev1.EnvVar, 0),
ExecutedTraits: make([]Trait, 0),
Resources: kubernetes.NewCollection(),
}
environment.Platform.ResyncStatusFullConfig()

err = traitCatalog.apply(&environment)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "unsupported configuration: a container image has been set in conjunction with an IntegrationKit")
}

0 comments on commit c37f1f7

Please sign in to comment.