| /* |
| 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" |
| |
| "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" |
| "github.com/apache/camel-k/pkg/util" |
| "github.com/apache/camel-k/pkg/util/kubernetes" |
| |
| "github.com/pkg/errors" |
| |
| k8sclient "sigs.k8s.io/controller-runtime/pkg/client" |
| ) |
| |
| var allowedLookupLabels = map[string]bool{ |
| v1alpha1.IntegrationKitTypePlatform: true, |
| v1alpha1.IntegrationKitTypeExternal: true, |
| } |
| |
| // LookupKitForIntegration -- |
| func LookupKitForIntegration(ctx context.Context, c k8sclient.Reader, integration *v1alpha1.Integration) (*v1alpha1.IntegrationKit, error) { |
| if integration.Status.Kit != "" { |
| kit, err := kubernetes.GetIntegrationKit(ctx, c, integration.Status.Kit, integration.Namespace) |
| if err != nil { |
| return nil, errors.Wrapf(err, "unable to find integration kit %s, %s", integration.Status.Kit, err) |
| } |
| |
| return kit, nil |
| } |
| |
| ctxList := v1alpha1.NewIntegrationKitList() |
| if err := c.List(ctx, &k8sclient.ListOptions{Namespace: integration.Namespace}, &ctxList); err != nil { |
| return nil, err |
| } |
| |
| for _, ctx := range ctxList.Items { |
| ctx := ctx // pin |
| |
| if ctx.Status.Phase == v1alpha1.IntegrationKitPhaseError { |
| continue |
| } |
| if ctx.Status.CamelVersion != integration.Status.CamelVersion { |
| continue |
| } |
| if ctx.Status.RuntimeVersion != integration.Status.RuntimeVersion { |
| continue |
| } |
| if ctx.Status.Version != integration.Status.Version { |
| continue |
| } |
| |
| if allowed, ok := allowedLookupLabels[ctx.Labels["camel.apache.org/kit.type"]]; ok && allowed { |
| ideps := len(integration.Status.Dependencies) |
| cdeps := len(ctx.Spec.Dependencies) |
| |
| if ideps != cdeps { |
| continue |
| } |
| |
| // |
| // When a platform kit is created it inherits the traits from the integrations and as |
| // some traits may influence the build thus the artifacts present on the container image, |
| // we need to take traits into account when looking up for compatible kits. |
| // |
| // It could also happen that an integration is updated and a trait is modified, if we do |
| // not include traits in the lookup, we may use a kit that does not have all the |
| // characteristics required by the integration. |
| // |
| // A kit can be used only if it contains a subset of the traits and related configurations |
| // declared on integration. |
| // |
| if !HasMatchingTraits(&ctx, integration) { |
| continue |
| } |
| |
| if util.StringSliceContains(ctx.Spec.Dependencies, integration.Status.Dependencies) { |
| return &ctx, nil |
| } |
| } |
| } |
| |
| return nil, nil |
| } |
| |
| // HasMatchingTraits compare traits defined on kit against those defined on integration. |
| func HasMatchingTraits(kit *v1alpha1.IntegrationKit, integration *v1alpha1.Integration) bool { |
| for ctxTraitName, ctxTraitConf := range kit.Spec.Traits { |
| iTraitConf, ok := integration.Spec.Traits[ctxTraitName] |
| if !ok { |
| // skip it because trait configured on kit is not defined on integration. |
| return false |
| } |
| |
| for ck, cv := range ctxTraitConf.Configuration { |
| iv, ok := iTraitConf.Configuration[ck] |
| |
| if !ok { |
| // skip it because trait configured on kit has a value that is not defined |
| // in integration trait |
| return false |
| } |
| if iv != cv { |
| // skip it because trait configured on kit has a value that differs from |
| // the one configured on integration |
| return false |
| } |
| } |
| } |
| |
| return true |
| } |