Skip to content

Commit

Permalink
Fix #1799: implement a global build strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolaferraro committed Mar 3, 2021
1 parent 1a2f871 commit 3526c96
Show file tree
Hide file tree
Showing 25 changed files with 124 additions and 57 deletions.
2 changes: 2 additions & 0 deletions config/crd/bases/camel.apache.org_integrations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ spec:
type: string
platform:
type: string
platformNamespace:
type: string
profile:
description: TraitProfile represents lists of traits that are enabled
for the specific installation/integration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ spec:
type: string
platform:
type: string
platformNamespace:
type: string
profile:
description: TraitProfile represents lists of traits that are enabled
for the specific installation/integration
Expand Down
3 changes: 3 additions & 0 deletions deploy/traits.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,9 @@ traits:
- name: create-default
type: bool
description: To create a default (empty) platform when the platform is missing.
- name: global
type: bool
description: Indicates if the platform should be created globally in the case of global operator (default true).
- name: auto
type: bool
description: To automatically detect from the environment if a default platform can be created (it will be created on OpenShift only).
Expand Down
4 changes: 4 additions & 0 deletions docs/modules/traits/pages/platform.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ The following configuration options are available:
| bool
| To create a default (empty) platform when the platform is missing.

| platform.global
| bool
| Indicates if the platform should be created globally in the case of global operator (default true).

| platform.auto
| bool
| To automatically detect from the environment if a default platform can be created (it will be created on OpenShift only).
Expand Down
2 changes: 2 additions & 0 deletions helm/camel-k/crds/crd-integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ spec:
type: string
platform:
type: string
platformNamespace:
type: string
profile:
description: TraitProfile represents lists of traits that are enabled
for the specific installation/integration
Expand Down
1 change: 1 addition & 0 deletions pkg/apis/camel/v1/integration_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type IntegrationStatus struct {
Dependencies []string `json:"dependencies,omitempty"`
Profile TraitProfile `json:"profile,omitempty"`
Kit string `json:"kit,omitempty"`
PlatformNamespace string `json:"platformNamespace,omitempty"`
Platform string `json:"platform,omitempty"`
GeneratedSources []SourceSpec `json:"generatedSources,omitempty"`
GeneratedResources []ResourceSpec `json:"generatedResources,omitempty"`
Expand Down
13 changes: 11 additions & 2 deletions pkg/apis/camel/v1/integration_types_support.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,8 @@ func (in *Integration) SetIntegrationPlatform(platform *IntegrationPlatform) {
cs = corev1.ConditionFalse
}

in.Status.SetCondition(IntegrationConditionPlatformAvailable, cs, IntegrationConditionPlatformAvailableReason, platform.Name)
in.Status.SetCondition(IntegrationConditionPlatformAvailable, cs, IntegrationConditionPlatformAvailableReason, platform.Namespace+"/"+platform.Name)
in.Status.PlatformNamespace = platform.Namespace
in.Status.Platform = platform.Name
}

Expand All @@ -271,7 +272,7 @@ func (in *Integration) SetIntegrationKit(kit *IntegrationKit) {
if kit.Status.Phase == IntegrationKitPhaseNone {
message = fmt.Sprintf("creating a new integration kit")
} else {
message = fmt.Sprintf("integration kit %s is in state %q", kit.Name, kit.Status.Phase)
message = fmt.Sprintf("integration kit %s/%s is in state %q", kit.Namespace, kit.Name, kit.Status.Phase)
}
}

Expand All @@ -280,6 +281,14 @@ func (in *Integration) SetIntegrationKit(kit *IntegrationKit) {
in.Status.Image = kit.Status.Image
}

// SetIntegrationKit --
func (in *Integration) GetIntegrationKitNamespace() string {
if in.Status.PlatformNamespace != "" {
return in.Status.PlatformNamespace
}
return in.Namespace
}

// GetCondition returns the condition with the provided type.
func (in *IntegrationStatus) GetCondition(condType IntegrationConditionType) *IntegrationCondition {
for i := range in.Conditions {
Expand Down
2 changes: 1 addition & 1 deletion pkg/builder/spectrum/publisher.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func publisher(ctx *builder.Context) error {
return err
}

pl, err := platform.GetCurrentPlatform(ctx.C, ctx, ctx.Namespace)
pl, err := platform.GetCurrent(ctx.C, ctx, ctx.Namespace)
if err != nil {
return err
}
Expand Down
12 changes: 4 additions & 8 deletions pkg/cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,14 +369,10 @@ func (o *installCmdOptions) install(cobraCmd *cobra.Command, _ []string) error {
platform.Spec.Build.KanikoBuildCache = &o.KanikoBuildCache
}

// Do not create an integration platform in global mode as platforms are expected
// to be created in other namespaces.
// In OLM mode, the operator is installed in an external namespace, so it's ok to install the platform locally.
if !o.Global || installViaOLM {
err = install.RuntimeObjectOrCollect(o.Context, c, namespace, collection, o.Force, platform)
if err != nil {
return err
}
// Always create a platform in the namespace where the operator is located
err = install.RuntimeObjectOrCollect(o.Context, c, namespace, collection, o.Force, platform)
if err != nil {
return err
}

if o.ExampleSetup {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/build/build_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func (r *reconcileBuild) Reconcile(request reconcile.Request) (reconcile.Result,
target := instance.DeepCopy()
targetLog := rlog.ForBuild(target)

pl, err := platform.GetOrLookupCurrent(ctx, r.client, target.Namespace, target.Status.Platform)
pl, err := platform.GetOrFind(ctx, r.client, target.Namespace, target.Status.Platform, true)
if target.Status.Phase == v1.BuildPhaseNone || target.Status.Phase == v1.BuildPhaseWaitingForPlatform {
if err != nil || pl.Status.Phase != v1.IntegrationPlatformPhaseReady {
target.Status.Phase = v1.BuildPhaseWaitingForPlatform
Expand Down
15 changes: 8 additions & 7 deletions pkg/controller/integration/build_kit.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,18 @@ func (action *buildKitAction) Handle(ctx context.Context, integration *v1.Integr
}

platformKitName := fmt.Sprintf("kit-%s", xid.New())
platformKit := v1.NewIntegrationKit(integration.Namespace, platformKitName)
platformKit := v1.NewIntegrationKit(integration.GetIntegrationKitNamespace(), 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),
"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.namespace": integration.Namespace,
"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
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/integration/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (action *deployAction) Handle(ctx context.Context, integration *v1.Integrat
return nil, errors.Errorf("no kit set on integration %s", integration.Name)
}

kit, err := kubernetes.GetIntegrationKit(ctx, action.client, integration.Status.Kit, integration.Namespace)
kit, err := kubernetes.GetIntegrationKit(ctx, action.client, integration.Status.Kit, integration.GetIntegrationKitNamespace())
if err != nil {
return nil, errors.Wrapf(err, "unable to find integration kit %s, %s", integration.Status.Kit, err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/integration/initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (action *initializeAction) Handle(ctx context.Context, integration *v1.Inte
return nil, err
}

kit := v1.NewIntegrationKit(integration.Namespace, integration.Spec.Kit)
kit := v1.NewIntegrationKit(integration.GetIntegrationKitNamespace(), integration.Spec.Kit)

integration.Status.Phase = v1.IntegrationPhaseBuildingKit
integration.SetIntegrationKit(&kit)
Expand Down
9 changes: 8 additions & 1 deletion pkg/controller/integration/integration_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,13 @@ func add(mgr manager.Manager, r reconcile.Reconciler, c client.Client) error {
if kit.Status.Phase == v1.IntegrationKitPhaseReady || kit.Status.Phase == v1.IntegrationKitPhaseError {
list := &v1.IntegrationList{}

if err := mgr.GetClient().List(context.TODO(), list, k8sclient.InNamespace(kit.Namespace)); err != nil {
// Do global search in case of global operator (it may be using a global platform)
var opts []k8sclient.ListOption
if !platform.IsCurrentOperatorGlobal() {
opts = append(opts, k8sclient.InNamespace(kit.Namespace))
}

if err := mgr.GetClient().List(context.TODO(), list, opts...); err != nil {
log.Error(err, "Failed to retrieve integration list")
return requests
}
Expand All @@ -130,6 +136,7 @@ func add(mgr manager.Manager, r reconcile.Reconciler, c client.Client) error {
})
}
}

}

return requests
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/integration/platform_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (action *platformSetupAction) Handle(ctx context.Context, integration *v1.I
return nil, err
}

pl, err := platform.GetCurrentPlatform(ctx, action.client, integration.Namespace)
pl, err := platform.GetCurrent(ctx, action.client, integration.Namespace)
if err != nil && !k8serrors.IsNotFound(err) {
return nil, err
} else if pl != nil {
Expand Down
6 changes: 3 additions & 3 deletions pkg/controller/integration/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,16 @@ import (
// LookupKitForIntegration --
func LookupKitForIntegration(ctx context.Context, c k8sclient.Reader, integration *v1.Integration) (*v1.IntegrationKit, error) {
if integration.Status.Kit != "" {
kit, err := kubernetes.GetIntegrationKit(ctx, c, integration.Status.Kit, integration.Namespace)
kit, err := kubernetes.GetIntegrationKit(ctx, c, integration.Status.Kit, integration.GetIntegrationKitNamespace())
if err != nil {
return nil, errors.Wrapf(err, "unable to find integration kit %s, %s", integration.Status.Kit, err)
return nil, errors.Wrapf(err, "unable to find integration kit %s/%s, %s", integration.GetIntegrationKitNamespace(), integration.Status.Kit, err)
}

return kit, nil
}

options := []k8sclient.ListOption{
k8sclient.InNamespace(integration.Namespace),
k8sclient.InNamespace(integration.GetIntegrationKitNamespace()),
k8sclient.MatchingLabels{
"camel.apache.org/runtime.version": integration.Status.RuntimeVersion,
"camel.apache.org/runtime.provider": string(integration.Status.RuntimeProvider),
Expand Down
3 changes: 2 additions & 1 deletion pkg/controller/integrationkit/integrationkit_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ func (r *reconcileIntegrationKit) Reconcile(request reconcile.Request) (reconcil
targetLog := rlog.ForIntegrationKit(target)

if target.Status.Phase == v1.IntegrationKitPhaseNone || target.Status.Phase == v1.IntegrationKitPhaseWaitingForPlatform {
pl, err := platform.GetOrLookupCurrent(ctx, r.client, target.Namespace, target.Status.Platform)
// TODO.... here local...
pl, err := platform.GetOrFindLocal(ctx, r.client, target.Namespace, target.Status.Platform, true)
if err != nil || pl.Status.Phase != v1.IntegrationPlatformPhaseReady {
target.Status.Phase = v1.IntegrationKitPhaseWaitingForPlatform
} else {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/kameletbinding/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func determineProfile(ctx context.Context, c client.Client, binding *v1alpha1.Ka
if binding.Spec.Integration != nil && binding.Spec.Integration.Profile != "" {
return binding.Spec.Integration.Profile, nil
}
pl, err := platform.GetCurrentPlatform(ctx, c, binding.Namespace)
pl, err := platform.GetCurrent(ctx, c, binding.Namespace)
if err != nil && !k8serrors.IsNotFound(err) {
return "", errors.Wrap(err, "error while retrieving the integration platform")
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/platform/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ func IsOperatorAllowedOnNamespace(ctx context.Context, c client.Client, namespac
if !IsCurrentOperatorGlobal() {
return true, nil
}
operatorNamespace := GetOperatorNamespace()
if operatorNamespace == namespace {
// Global operator is allowed on its own namespace
return true, nil
}
alreadyOwned, err := IsNamespaceLocked(ctx, c, namespace)
if err != nil {
return false, err
Expand Down
51 changes: 35 additions & 16 deletions pkg/platform/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,36 +31,55 @@ const (
DefaultPlatformName = "camel-k"
)

// GetOrLookupCurrent --
func GetOrLookupCurrent(ctx context.Context, c k8sclient.Reader, namespace string, name string) (*v1.IntegrationPlatform, error) {
// GetCurrent returns the currently installed platform (local or global)
func GetCurrent(ctx context.Context, c k8sclient.Reader, namespace string) (*v1.IntegrationPlatform, error) {
return find(ctx, c, namespace, true)
}

// GetOrFind returns the named platform or any other platform in the local namespace or the global one
func GetOrFind(ctx context.Context, c k8sclient.Reader, namespace string, name string, active bool) (*v1.IntegrationPlatform, error) {
if name != "" {
return Get(ctx, c, namespace, name)
return get(ctx, c, namespace, name)
}

return GetCurrentPlatform(ctx, c, namespace)
return find(ctx, c, namespace, active)
}

// GetOrLookupAny returns the named platform or any other platform in the namespace
func GetOrLookupAny(ctx context.Context, c k8sclient.Reader, namespace string, name string) (*v1.IntegrationPlatform, error) {
// GetOrFindLocal returns the named platform or any other platform in the local namespace
func GetOrFindLocal(ctx context.Context, c k8sclient.Reader, namespace string, name string, active bool) (*v1.IntegrationPlatform, error) {
if name != "" {
return Get(ctx, c, namespace, name)
return kubernetes.GetIntegrationPlatform(ctx, c, name, namespace)
}

return getAnyPlatform(ctx, c, namespace, false)
return findLocal(ctx, c, namespace, active)
}

// Get returns the currently installed platform
func Get(ctx context.Context, c k8sclient.Reader, namespace string, name string) (*v1.IntegrationPlatform, error) {
return kubernetes.GetIntegrationPlatform(ctx, c, name, namespace)
// get returns the given platform in the given namespace or the global one
func get(ctx context.Context, c k8sclient.Reader, namespace string, name string) (*v1.IntegrationPlatform, error) {
p, err := kubernetes.GetIntegrationPlatform(ctx, c, name, namespace)
if err != nil && k8serrors.IsNotFound(err) {
operatorNamespace := GetOperatorNamespace()
if operatorNamespace != "" && operatorNamespace != namespace {
p, err = kubernetes.GetIntegrationPlatform(ctx, c, name, operatorNamespace)
}
}
return p, err
}

// GetCurrentPlatform returns the currently installed platform
func GetCurrentPlatform(ctx context.Context, c k8sclient.Reader, namespace string) (*v1.IntegrationPlatform, error) {
return getAnyPlatform(ctx, c, namespace, true)
// find returns the currently installed platform or any platform existing in local or operator namespace
func find(ctx context.Context, c k8sclient.Reader, namespace string, active bool) (*v1.IntegrationPlatform, error) {
p, err := findLocal(ctx, c, namespace, active)
if err != nil && k8serrors.IsNotFound(err) {
operatorNamespace := GetOperatorNamespace()
if operatorNamespace != "" && operatorNamespace != namespace {
p, err = findLocal(ctx, c, operatorNamespace, active)
}
}
return p, err
}

// getAnyPlatform returns the currently installed platform or any platform existing in the namespace
func getAnyPlatform(ctx context.Context, c k8sclient.Reader, namespace string, active bool) (*v1.IntegrationPlatform, error) {
// findLocal returns the currently installed platform or any platform existing in local namespace
func findLocal(ctx context.Context, c k8sclient.Reader, namespace string, active bool) (*v1.IntegrationPlatform, error) {
lst, err := ListPlatforms(ctx, c, namespace)
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion pkg/trait/camel.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func (t *camelTrait) loadOrCreateCatalog(e *Environment, runtimeVersion string)
// the required versions (camel and runtime) are not expressed as
// semver constraints
if exactVersionRegexp.MatchString(runtimeVersion) {
catalog, err = camel.GenerateCatalog(e.C, e.Client, ns, e.Platform.Status.Build.Maven, runtime, []maven.Dependency{})
catalog, err = camel.GenerateCatalog(e.C, e.Client, e.Platform.Namespace, e.Platform.Status.Build.Maven, runtime, []maven.Dependency{})
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/trait/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ func (t *openAPITrait) createNewOpenAPIConfigMap(e *Environment, resource v1.Res
mc.AddArgument("-Dopenapi.spec=" + in)
mc.AddArgument("-Ddsl.out=" + out)

settings, err := kubernetes.ResolveValueSource(e.C, e.Client, e.Integration.Namespace, &e.Platform.Status.Build.Maven.Settings)
settings, err := kubernetes.ResolveValueSource(e.C, e.Client, e.Platform.Namespace, &e.Platform.Status.Build.Maven.Settings)
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit 3526c96

Please sign in to comment.