blob: a3e4fe669ccec63043e1687f44469793b99908e8 [file] [log] [blame]
/*
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.
*/
package integration
import (
"context"
"fmt"
v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
"github.com/apache/camel-k/pkg/trait"
"github.com/apache/camel-k/pkg/util"
"github.com/rs/xid"
)
// NewBuildKitAction create an action that handles integration kit build
func NewBuildKitAction() Action {
return &buildKitAction{}
}
type buildKitAction struct {
baseAction
}
func (action *buildKitAction) Name() string {
return "build-kit"
}
func (action *buildKitAction) CanHandle(integration *v1.Integration) bool {
return integration.Status.Phase == v1.IntegrationPhaseBuildingKit ||
integration.Status.Phase == v1.IntegrationPhaseResolvingKit
}
func (action *buildKitAction) Handle(ctx context.Context, integration *v1.Integration) (*v1.Integration, error) {
kit, err := LookupKitForIntegration(ctx, action.client, integration)
if err != nil {
//TODO: we may need to add a wait strategy, i.e give up after some time
return nil, err
}
if kit != nil {
if kit.Labels["camel.apache.org/kit.type"] == v1.IntegrationKitTypePlatform {
// This is a platform kit and as it is auto generated it may get
// out of sync if the integration that has generated it, has been
// amended to add/remove dependencies
versionMatch := kit.Status.Version == integration.Status.Version
//TODO: this is a very simple check, we may need to provide a deps comparison strategy
dependenciesMatch := util.StringSliceContains(kit.Spec.Dependencies, integration.Status.Dependencies)
if !dependenciesMatch || !versionMatch {
// We need to re-generate a kit or search for a new one that
// satisfies integrations needs so let's remove the association
// with a kit
integration.SetIntegrationKit(&v1.IntegrationKit{})
return integration, nil
}
}
if kit.Status.Phase == v1.IntegrationKitPhaseError {
integration.Status.Image = kit.Status.Image
integration.Status.Phase = v1.IntegrationPhaseError
integration.SetIntegrationKit(kit)
return integration, nil
}
if kit.Status.Phase == v1.IntegrationKitPhaseReady {
integration.Status.Image = kit.Status.Image
integration.SetIntegrationKit(kit)
if _, err := trait.Apply(ctx, action.client, integration, kit); err != nil {
return nil, err
}
return integration, nil
}
if integration.Status.Kit == "" {
integration.SetIntegrationKit(kit)
return integration, nil
}
return nil, nil
}
platformKitName := fmt.Sprintf("kit-%s", xid.New())
platformKit := v1.NewIntegrationKit(integration.Namespace, platformKitName)
// Add some information for post-processing, this may need to be refactored
// to a proper data structure
platformKit.Labels = map[string]string{
"camel.apache.org/kit.type": v1.IntegrationKitTypePlatform,
"camel.apache.org/created.by.kind": v1.IntegrationKind,
"camel.apache.org/created.by.name": integration.Name,
"camel.apache.org/created.by.version": integration.ResourceVersion,
"camel.apache.org/runtime.version": integration.Status.RuntimeVersion,
"camel.apache.org/runtime.provider": string(integration.Status.RuntimeProvider),
}
// Set the kit to have the same characteristics as the integrations
platformKit.Spec = v1.IntegrationKitSpec{
Dependencies: integration.Status.Dependencies,
Repositories: integration.Spec.Repositories,
Traits: action.filterKitTraits(ctx, integration.Spec.Traits),
}
if err := action.client.Create(ctx, &platformKit); err != nil {
return nil, err
}
// Set the kit name so the next handle loop, will fall through the
// same path as integration with a user defined kit
integration.SetIntegrationKit(&platformKit)
return integration, nil
}
func (action *buildKitAction) filterKitTraits(ctx context.Context, in map[string]v1.TraitSpec) map[string]v1.TraitSpec {
if len(in) == 0 {
return in
}
catalog := trait.NewCatalog(ctx, action.client)
out := make(map[string]v1.TraitSpec)
for name, conf := range in {
t := catalog.GetTrait(name)
if t != nil && !t.InfluencesKit() {
// We don't store the trait configuration if the trait cannot influence the kit behavior
continue
}
out[name] = conf
}
return out
}