You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2019/07/02 12:24:25 UTC
[camel-k] 05/12: refactor(controller): simplify integration kit
controller
This is an automated email from the ASF dual-hosted git repository.
lburgazzoli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 87e0bffc248b38648bd34be257ddfd207b994ad1
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Fri Jun 28 15:58:45 2019 +0200
refactor(controller): simplify integration kit controller
---
pkg/controller/integrationkit/action.go | 6 +-
pkg/controller/integrationkit/build.go | 78 +++++++++-------------
pkg/controller/integrationkit/initialize.go | 32 +++------
.../integrationkit/integrationkit_controller.go | 62 ++++++++++++++---
pkg/controller/integrationkit/monitor.go | 15 ++---
5 files changed, 101 insertions(+), 92 deletions(-)
diff --git a/pkg/controller/integrationkit/action.go b/pkg/controller/integrationkit/action.go
index 69691bf..5dd5ecf 100644
--- a/pkg/controller/integrationkit/action.go
+++ b/pkg/controller/integrationkit/action.go
@@ -28,6 +28,7 @@ import (
// Action --
type Action interface {
client.Injectable
+ log.Injectable
// a user friendly name for the action
Name() string
@@ -36,10 +37,7 @@ type Action interface {
CanHandle(kit *v1alpha1.IntegrationKit) bool
// executes the handling function
- Handle(ctx context.Context, kit *v1alpha1.IntegrationKit) error
-
- // Inject integration logger
- InjectLogger(log.Logger)
+ Handle(ctx context.Context, kit *v1alpha1.IntegrationKit) (*v1alpha1.IntegrationKit, error)
}
type baseAction struct {
diff --git a/pkg/controller/integrationkit/build.go b/pkg/controller/integrationkit/build.go
index 97b7caf..4fb448a 100644
--- a/pkg/controller/integrationkit/build.go
+++ b/pkg/controller/integrationkit/build.go
@@ -52,20 +52,20 @@ func (action *buildAction) CanHandle(kit *v1alpha1.IntegrationKit) bool {
kit.Status.Phase == v1alpha1.IntegrationKitPhaseBuildRunning
}
-func (action *buildAction) Handle(ctx context.Context, kit *v1alpha1.IntegrationKit) error {
+func (action *buildAction) Handle(ctx context.Context, kit *v1alpha1.IntegrationKit) (*v1alpha1.IntegrationKit, error) {
if kit.Status.Phase == v1alpha1.IntegrationKitPhaseBuildSubmitted {
return action.handleBuildSubmitted(ctx, kit)
} else if kit.Status.Phase == v1alpha1.IntegrationKitPhaseBuildRunning {
return action.handleBuildRunning(ctx, kit)
}
- return nil
+ return nil, nil
}
-func (action *buildAction) handleBuildSubmitted(ctx context.Context, kit *v1alpha1.IntegrationKit) error {
+func (action *buildAction) handleBuildSubmitted(ctx context.Context, kit *v1alpha1.IntegrationKit) (*v1alpha1.IntegrationKit, error) {
build, err := kubernetes.GetBuild(ctx, action.client, kit.Name, kit.Namespace)
if err != nil && !k8serrors.IsNotFound(err) {
- return err
+ return nil, err
}
if err != nil && k8serrors.IsNotFound(err) ||
@@ -75,11 +75,11 @@ func (action *buildAction) handleBuildSubmitted(ctx context.Context, kit *v1alph
env, err := trait.Apply(ctx, action.client, nil, kit)
if err != nil {
- return err
+ return nil, err
}
if env.CamelCatalog == nil {
- return errors.New("undefined camel catalog")
+ return nil, errors.New("undefined camel catalog")
}
build = &v1alpha1.Build{
@@ -104,97 +104,81 @@ func (action *buildAction) handleBuildSubmitted(ctx context.Context, kit *v1alph
// Set the integration kit instance as the owner and controller
if err := controllerutil.SetControllerReference(kit, build, action.client.GetScheme()); err != nil {
- return err
+ return nil, err
}
err = action.client.Delete(ctx, build)
if err != nil && !k8serrors.IsNotFound(err) {
- return errors.Wrap(err, "cannot delete build")
+ return nil, errors.Wrap(err, "cannot delete build")
}
err = action.client.Create(ctx, build)
if err != nil {
- return errors.Wrap(err, "cannot create build")
+ return nil, errors.Wrap(err, "cannot create build")
}
}
if build.Status.Phase == v1alpha1.BuildPhaseRunning {
- target := kit.DeepCopy()
- target.Status.Phase = v1alpha1.IntegrationKitPhaseBuildRunning
-
- action.L.Info("IntegrationKit state transition", "phase", target.Status.Phase)
-
- return action.client.Status().Update(ctx, target)
+ kit.Status.Phase = v1alpha1.IntegrationKitPhaseBuildRunning
+ return kit, nil
}
- return nil
+ return nil, nil
}
-func (action *buildAction) handleBuildRunning(ctx context.Context, kit *v1alpha1.IntegrationKit) error {
+func (action *buildAction) handleBuildRunning(ctx context.Context, kit *v1alpha1.IntegrationKit) (*v1alpha1.IntegrationKit, error) {
build, err := kubernetes.GetBuild(ctx, action.client, kit.Name, kit.Namespace)
if err != nil {
- return err
+ return nil, err
}
switch build.Status.Phase {
-
case v1alpha1.BuildPhaseRunning:
action.L.Info("Build running")
-
case v1alpha1.BuildPhaseSucceeded:
- target := kit.DeepCopy()
-
// we should ensure that the integration kit is still in the right phase,
// if not there is a chance that the kit has been modified by the user
- if target.Status.Phase != v1alpha1.IntegrationKitPhaseBuildRunning {
- return fmt.Errorf("found kit %s not in the expected phase (expectd=%s, found=%s)",
+ if kit.Status.Phase != v1alpha1.IntegrationKitPhaseBuildRunning {
+ return nil, fmt.Errorf("found kit %s not in the expected phase (expectd=%s, found=%s)",
build.Spec.Meta.Name,
string(v1alpha1.IntegrationKitPhaseBuildRunning),
- string(target.Status.Phase),
+ string(kit.Status.Phase),
)
}
- target.Status.BaseImage = build.Status.BaseImage
- target.Status.Image = build.Status.Image
- target.Status.PublicImage = build.Status.PublicImage
- target.Status.Phase = v1alpha1.IntegrationKitPhaseReady
- target.Status.Artifacts = make([]v1alpha1.Artifact, 0, len(build.Status.Artifacts))
+ kit.Status.BaseImage = build.Status.BaseImage
+ kit.Status.Image = build.Status.Image
+ kit.Status.PublicImage = build.Status.PublicImage
+ kit.Status.Phase = v1alpha1.IntegrationKitPhaseReady
+ kit.Status.Artifacts = make([]v1alpha1.Artifact, 0, len(build.Status.Artifacts))
for _, a := range build.Status.Artifacts {
// do not include artifact location
- target.Status.Artifacts = append(target.Status.Artifacts, v1alpha1.Artifact{
+ kit.Status.Artifacts = append(kit.Status.Artifacts, v1alpha1.Artifact{
ID: a.ID,
Location: "",
Target: a.Target,
})
}
- action.L.Info("IntegrationKit state transition", "phase", target.Status.Phase)
- if err := action.client.Status().Update(ctx, target); err != nil {
- return err
- }
-
+ return kit, err
case v1alpha1.BuildPhaseError, v1alpha1.BuildPhaseInterrupted:
- target := kit.DeepCopy()
-
// we should ensure that the integration kit is still in the right phase,
// if not there is a chance that the kit has been modified by the user
- if target.Status.Phase != v1alpha1.IntegrationKitPhaseBuildRunning {
- return fmt.Errorf("found kit %s not the an expected phase (expectd=%s, found=%s)",
+ if kit.Status.Phase != v1alpha1.IntegrationKitPhaseBuildRunning {
+ return nil, fmt.Errorf("found kit %s not the an expected phase (expectd=%s, found=%s)",
build.Spec.Meta.Name,
string(v1alpha1.IntegrationKitPhaseBuildRunning),
- string(target.Status.Phase),
+ string(kit.Status.Phase),
)
}
// Let's copy the build failure to the integration kit status
- target.Status.Failure = build.Status.Failure
- target.Status.Phase = v1alpha1.IntegrationKitPhaseError
-
- action.L.Error(fmt.Errorf(build.Status.Error), "IntegrationKit state transition", "phase", target.Status.Phase)
+ kit.Status.Failure = build.Status.Failure
+ kit.Status.Phase = v1alpha1.IntegrationKitPhaseError
- return action.client.Status().Update(ctx, target)
+ return kit, nil
}
- return nil
+ return nil, nil
}
diff --git a/pkg/controller/integrationkit/initialize.go b/pkg/controller/integrationkit/initialize.go
index d90076b..9deb30f 100644
--- a/pkg/controller/integrationkit/initialize.go
+++ b/pkg/controller/integrationkit/initialize.go
@@ -23,7 +23,6 @@ import (
"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
"github.com/apache/camel-k/pkg/platform"
"github.com/apache/camel-k/pkg/trait"
- "github.com/apache/camel-k/pkg/util/digest"
)
// NewInitializeAction creates a new initialization handling action for the kit
@@ -43,44 +42,35 @@ func (action *initializeAction) CanHandle(kit *v1alpha1.IntegrationKit) bool {
return kit.Status.Phase == ""
}
-func (action *initializeAction) Handle(ctx context.Context, kit *v1alpha1.IntegrationKit) error {
+func (action *initializeAction) Handle(ctx context.Context, kit *v1alpha1.IntegrationKit) (*v1alpha1.IntegrationKit, error) {
// The integration platform needs to be initialized before starting to create kits
if _, err := platform.GetCurrentPlatform(ctx, action.client, kit.Namespace); err != nil {
action.L.Info("Waiting for the integration platform to be initialized")
- return nil
+ return nil, nil
}
- target := kit.DeepCopy()
-
- _, err := trait.Apply(ctx, action.client, nil, target)
+ _, err := trait.Apply(ctx, action.client, nil, kit)
if err != nil {
- return err
+ return nil, err
}
// Updating the whole integration kit as it may have changed
action.L.Info("Updating IntegrationKit")
- if err := action.client.Update(ctx, target); err != nil {
- return err
+ if err := action.client.Update(ctx, kit); err != nil {
+ return nil, err
}
- if target.Spec.Image == "" {
+ if kit.Spec.Image == "" {
// by default the kit should be built
- target.Status.Phase = v1alpha1.IntegrationKitPhaseBuildSubmitted
+ kit.Status.Phase = v1alpha1.IntegrationKitPhaseBuildSubmitted
} else {
// but in case it has been created from an image, mark the
// kit as ready
- target.Status.Phase = v1alpha1.IntegrationKitPhaseReady
+ kit.Status.Phase = v1alpha1.IntegrationKitPhaseReady
// and set the image to be used
- target.Status.Image = target.Spec.Image
- }
-
- dgst, err := digest.ComputeForIntegrationKit(target)
- if err != nil {
- return err
+ kit.Status.Image = kit.Spec.Image
}
- target.Status.Digest = dgst
- action.L.Info("IntegrationKit state transition", "phase", target.Status.Phase)
- return action.client.Status().Update(ctx, target)
+ return kit, nil
}
diff --git a/pkg/controller/integrationkit/integrationkit_controller.go b/pkg/controller/integrationkit/integrationkit_controller.go
index 57d580a..2d02a2d 100644
--- a/pkg/controller/integrationkit/integrationkit_controller.go
+++ b/pkg/controller/integrationkit/integrationkit_controller.go
@@ -19,6 +19,8 @@ package integrationkit
import (
"context"
+ "github.com/apache/camel-k/pkg/util/digest"
+
"k8s.io/apimachinery/pkg/api/errors"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
@@ -128,8 +130,7 @@ func (r *ReconcileIntegrationKit) Reconcile(request reconcile.Request) (reconcil
var instance v1alpha1.IntegrationKit
// Fetch the IntegrationKit instance
- err := r.client.Get(ctx, request.NamespacedName, &instance)
- if err != nil {
+ if err := r.client.Get(ctx, request.NamespacedName, &instance); err != nil {
if errors.IsNotFound(err) {
// Request object not found, could have been deleted after reconcile request.
// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
@@ -140,26 +141,65 @@ func (r *ReconcileIntegrationKit) Reconcile(request reconcile.Request) (reconcil
return reconcile.Result{}, err
}
- actionPool := []Action{
+ actions := []Action{
NewInitializeAction(),
NewBuildAction(),
NewMonitorAction(),
}
- ilog := rlog.ForIntegrationKit(&instance)
- for _, a := range actionPool {
+ var targetPhase v1alpha1.IntegrationKitPhase
+
+ target := instance.DeepCopy()
+ targetLog := rlog.ForIntegrationKit(target)
+
+ for _, a := range actions {
a.InjectClient(r.client)
- a.InjectLogger(ilog)
- if a.CanHandle(&instance) {
- ilog.Infof("Invoking action %s", a.Name())
- if err := a.Handle(ctx, &instance); err != nil {
- if k8serrors.IsConflict(err) {
- ilog.Error(err, "conflict")
+ a.InjectLogger(targetLog)
+
+ if a.CanHandle(target) {
+ targetLog.Infof("Invoking action %s", a.Name())
+
+ phaseFrom := target.Status.Phase
+ target = target.DeepCopy()
+
+ t, err := a.Handle(ctx, target)
+ if err != nil {
+ return reconcile.Result{
+ Requeue: true,
+ }, nil
+ }
+
+ if t != nil {
+ target = t
+
+ dgst, err := digest.ComputeForIntegrationKit(target)
+ if err != nil {
return reconcile.Result{
Requeue: true,
}, nil
}
+ target.Status.Digest = dgst
+
+ if err := r.client.Status().Update(ctx, target); err != nil {
+ if k8serrors.IsConflict(err) {
+ targetLog.Error(err, "conflict")
+ return reconcile.Result{
+ Requeue: true,
+ }, nil
+ }
+ }
+
+ targetPhase = target.Status.Phase
+
+ if targetPhase != phaseFrom {
+ targetLog.Info(
+ "state transition",
+ "phase-from", phaseFrom,
+ "phase-to", target.Status.Phase,
+ )
+ }
+
return reconcile.Result{}, err
}
}
diff --git a/pkg/controller/integrationkit/monitor.go b/pkg/controller/integrationkit/monitor.go
index 79671e3..a3910b1 100644
--- a/pkg/controller/integrationkit/monitor.go
+++ b/pkg/controller/integrationkit/monitor.go
@@ -41,22 +41,19 @@ func (action *monitorAction) CanHandle(kit *v1alpha1.IntegrationKit) bool {
return kit.Status.Phase == v1alpha1.IntegrationKitPhaseReady || kit.Status.Phase == v1alpha1.IntegrationKitPhaseError
}
-func (action *monitorAction) Handle(ctx context.Context, kit *v1alpha1.IntegrationKit) error {
+func (action *monitorAction) Handle(ctx context.Context, kit *v1alpha1.IntegrationKit) (*v1alpha1.IntegrationKit, error) {
hash, err := digest.ComputeForIntegrationKit(kit)
if err != nil {
- return err
+ return nil, err
}
if hash != kit.Status.Digest {
action.L.Info("IntegrationKit needs a rebuild")
- target := kit.DeepCopy()
- target.Status.Digest = hash
- target.Status.Phase = v1alpha1.IntegrationKitPhaseBuildSubmitted
+ kit.Status.Digest = hash
+ kit.Status.Phase = v1alpha1.IntegrationKitPhaseBuildSubmitted
- action.L.Info("IntegrationKit state transition", "phase", target.Status.Phase)
-
- return action.client.Status().Update(ctx, target)
+ return kit, nil
}
- return nil
+ return nil, nil
}