You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2019/03/05 10:29:21 UTC

[camel-k] branch master updated: Adding Probes to Knative services #511

This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git


The following commit(s) were added to refs/heads/master by this push:
     new 660a190  Adding Probes to Knative services #511
660a190 is described below

commit 660a190a33aab902223ed0d2110c47ed69dfd301
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Fri Mar 1 01:09:05 2019 +0100

    Adding Probes to Knative services #511
---
 pkg/trait/probes.go        |  93 +++++++++++++++++++++++++++++++
 pkg/trait/probes_test.go   | 134 +++++++++++++++++++++++++++++++++++++++++++++
 pkg/trait/trait_catalog.go |   6 ++
 3 files changed, 233 insertions(+)

diff --git a/pkg/trait/probes.go b/pkg/trait/probes.go
new file mode 100644
index 0000000..fbc0e33
--- /dev/null
+++ b/pkg/trait/probes.go
@@ -0,0 +1,93 @@
+/*
+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 trait
+
+import (
+	"sort"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util"
+	"k8s.io/apimachinery/pkg/util/intstr"
+
+	serving "github.com/knative/serving/pkg/apis/serving/v1alpha1"
+	appsv1 "k8s.io/api/apps/v1"
+	corev1 "k8s.io/api/core/v1"
+)
+
+type probesTrait struct {
+	BaseTrait `property:",squash"`
+
+	BindHost string `property:"bind-host"`
+	BindPort int    `property:"bind-port"`
+	Path     string `property:"path"`
+}
+
+func newProbesTrait() *probesTrait {
+	return &probesTrait{
+		BaseTrait: newBaseTrait("probes"),
+		BindHost:  "0.0.0.0",
+		BindPort:  8081,
+		Path:      "/health",
+	}
+}
+
+func (t *probesTrait) Configure(e *Environment) (bool, error) {
+	if t.Enabled != nil && *t.Enabled {
+		return e.IntegrationInPhase(v1alpha1.IntegrationPhaseInitial) || e.IntegrationInPhase(v1alpha1.IntegrationPhaseDeploying), nil
+	}
+
+	return false, nil
+}
+
+func (t *probesTrait) Apply(e *Environment) error {
+	if e.IntegrationInPhase(v1alpha1.IntegrationPhaseInitial) {
+		util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, "runtime:health")
+
+		// sort the dependencies to get always the same list if they don't change
+		sort.Strings(e.Integration.Status.Dependencies)
+	}
+
+	if e.IntegrationInPhase(v1alpha1.IntegrationPhaseDeploying) {
+		e.Resources.VisitDeployment(func(deployment *appsv1.Deployment) {
+			if len(deployment.Spec.Template.Spec.Containers) != 1 {
+				return
+			}
+
+			deployment.Spec.Template.Spec.Containers[0].LivenessProbe = t.newProbe()
+			deployment.Spec.Template.Spec.Containers[0].ReadinessProbe = t.newProbe()
+		})
+
+		e.Resources.VisitKnativeService(func(service *serving.Service) {
+			service.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.LivenessProbe = t.newProbe()
+			service.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.ReadinessProbe = t.newProbe()
+		})
+	}
+
+	return nil
+}
+
+func (t *probesTrait) newProbe() *corev1.Probe {
+	return &corev1.Probe{
+		Handler: corev1.Handler{
+			HTTPGet: &corev1.HTTPGetAction{
+				Port: intstr.FromInt(t.BindPort),
+				Path: t.Path,
+			},
+		},
+	}
+}
diff --git a/pkg/trait/probes_test.go b/pkg/trait/probes_test.go
new file mode 100644
index 0000000..88a2a45
--- /dev/null
+++ b/pkg/trait/probes_test.go
@@ -0,0 +1,134 @@
+/*
+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 trait
+
+import (
+	"testing"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
+
+	"github.com/stretchr/testify/assert"
+
+	serving "github.com/knative/serving/pkg/apis/serving/v1alpha1"
+	appsv1 "k8s.io/api/apps/v1"
+	corev1 "k8s.io/api/core/v1"
+)
+
+func TestProbesDeps(t *testing.T) {
+	e := Environment{
+		Integration: &v1alpha1.Integration{
+			Status: v1alpha1.IntegrationStatus{
+				Phase: v1alpha1.IntegrationPhaseInitial,
+			},
+		},
+	}
+
+	enabled := true
+
+	tr := newProbesTrait()
+	tr.Enabled = &enabled
+	tr.BindPort = 9191
+
+	ok, err := tr.Configure(&e)
+	assert.Nil(t, err)
+	assert.True(t, ok)
+
+	err = tr.Apply(&e)
+	assert.Nil(t, err)
+	assert.Contains(t, e.Integration.Status.Dependencies, "runtime:health")
+}
+
+func TestProbesOnDeployment(t *testing.T) {
+	target := appsv1.Deployment{
+		Spec: appsv1.DeploymentSpec{
+			Template: corev1.PodTemplateSpec{
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{},
+					},
+				},
+			},
+		},
+	}
+
+	e := Environment{
+		Resources: kubernetes.NewCollection(&target),
+		Integration: &v1alpha1.Integration{
+			Status: v1alpha1.IntegrationStatus{
+				Phase: v1alpha1.IntegrationPhaseDeploying,
+			},
+		},
+	}
+
+	enabled := true
+
+	tr := newProbesTrait()
+	tr.Enabled = &enabled
+	tr.BindPort = 9191
+
+	ok, err := tr.Configure(&e)
+	assert.Nil(t, err)
+	assert.True(t, ok)
+
+	err = tr.Apply(&e)
+	assert.Nil(t, err)
+	//assert.Contains(t, e.Integration.Status.Dependencies, "runtime:health")
+	assert.Equal(t, "", target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Host)
+	assert.Equal(t, int32(9191), target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Port.IntVal)
+	assert.Equal(t, "/health", target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Path)
+	assert.Equal(t, "", target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Host)
+	assert.Equal(t, int32(9191), target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Port.IntVal)
+	assert.Equal(t, "/health", target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Path)
+}
+
+func TestProbesOnKnativeService(t *testing.T) {
+	target := serving.Service{
+		Spec: serving.ServiceSpec{
+			RunLatest: &serving.RunLatestType{},
+		},
+	}
+
+	e := Environment{
+		Resources: kubernetes.NewCollection(&target),
+		Integration: &v1alpha1.Integration{
+			Status: v1alpha1.IntegrationStatus{
+				Phase: v1alpha1.IntegrationPhaseDeploying,
+			},
+		},
+	}
+
+	enabled := true
+
+	tr := newProbesTrait()
+	tr.Enabled = &enabled
+	tr.BindPort = 9191
+
+	ok, err := tr.Configure(&e)
+	assert.Nil(t, err)
+	assert.True(t, ok)
+
+	err = tr.Apply(&e)
+	assert.Nil(t, err)
+	assert.Equal(t, "", target.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.LivenessProbe.HTTPGet.Host)
+	assert.Equal(t, int32(9191), target.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.LivenessProbe.HTTPGet.Port.IntVal)
+	assert.Equal(t, "/health", target.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.LivenessProbe.HTTPGet.Path)
+	assert.Equal(t, "", target.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.ReadinessProbe.HTTPGet.Host)
+	assert.Equal(t, int32(9191), target.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.ReadinessProbe.HTTPGet.Port.IntVal)
+	assert.Equal(t, "/health", target.Spec.RunLatest.Configuration.RevisionTemplate.Spec.Container.ReadinessProbe.HTTPGet.Path)
+}
diff --git a/pkg/trait/trait_catalog.go b/pkg/trait/trait_catalog.go
index 9c5c9c2..b2e2e60 100644
--- a/pkg/trait/trait_catalog.go
+++ b/pkg/trait/trait_catalog.go
@@ -52,6 +52,7 @@ type Catalog struct {
 	tEnvironment      Trait
 	tClasspath        Trait
 	tRestDsl          Trait
+	tProbes           Trait
 }
 
 // NewCatalog creates a new trait Catalog
@@ -79,6 +80,7 @@ func NewCatalog(ctx context.Context, c client.Client) *Catalog {
 		tIstio:            newIstioTrait(),
 		tEnvironment:      newEnvironmentTrait(),
 		tClasspath:        newClasspathTrait(),
+		tProbes:           newProbesTrait(),
 	}
 
 	for _, t := range catalog.allTraits() {
@@ -115,6 +117,7 @@ func (c *Catalog) allTraits() []Trait {
 		c.tIstio,
 		c.tEnvironment,
 		c.tClasspath,
+		c.tProbes,
 	}
 }
 
@@ -138,6 +141,7 @@ func (c *Catalog) traitsFor(environment *Environment) []Trait {
 			c.tPrometheus,
 			c.tDeployer,
 			c.tDeployment,
+			c.tProbes,
 			c.tService,
 			c.tRoute,
 			c.tOwner,
@@ -158,6 +162,7 @@ func (c *Catalog) traitsFor(environment *Environment) []Trait {
 			c.tPrometheus,
 			c.tDeployer,
 			c.tDeployment,
+			c.tProbes,
 			c.tService,
 			c.tIngress,
 			c.tOwner,
@@ -178,6 +183,7 @@ func (c *Catalog) traitsFor(environment *Environment) []Trait {
 			c.tDeployer,
 			c.tDeployment,
 			c.tKnativeService,
+			c.tProbes,
 			c.tIstio,
 			c.tOwner,
 		}