| /* |
| 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 |
| } |