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 b7ec6ae Fix #1325: add 3scale addon b7ec6ae is described below commit b7ec6aeb65f19a5aef424167f8b56763907b59a2 Author: Nicola Ferraro <ni.ferr...@gmail.com> AuthorDate: Mon Mar 16 18:48:02 2020 +0100 Fix #1325: add 3scale addon --- addons/register_3scale.go | 27 +++++ addons/threescale/3scale.go | 138 ++++++++++++++++++++++++++ addons/threescale/3scale_test.go | 114 +++++++++++++++++++++ addons/threescale/zz_generated_doc.go | 1 + docs/modules/ROOT/nav.adoc | 3 +- docs/modules/ROOT/pages/traits/3scale.adoc | 52 ++++++++++ docs/modules/ROOT/pages/traits/container.adoc | 59 +++++++++++ docs/modules/ROOT/pages/traits/openapi.adoc | 4 +- docs/modules/ROOT/pages/traits/traits.adoc | 3 +- pkg/cmd/run.go | 2 +- 10 files changed, 398 insertions(+), 5 deletions(-) diff --git a/addons/register_3scale.go b/addons/register_3scale.go new file mode 100644 index 0000000..aaa3cb1 --- /dev/null +++ b/addons/register_3scale.go @@ -0,0 +1,27 @@ +/* +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 addons + +import ( + "github.com/apache/camel-k/addons/threescale" + "github.com/apache/camel-k/pkg/trait" +) + +func init() { + trait.AddToTraits(threescale.NewThreeScaleTrait) +} diff --git a/addons/threescale/3scale.go b/addons/threescale/3scale.go new file mode 100644 index 0000000..fa2250c --- /dev/null +++ b/addons/threescale/3scale.go @@ -0,0 +1,138 @@ +/* +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 threescale + +import ( + "strconv" + + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" + "github.com/apache/camel-k/pkg/trait" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// The 3scale trait can be used to automatically create annotations that allow +// 3scale to discover the generated service and make it available for API management. +// +// The 3scale trait is disabled by default. +// +// +camel-k:trait=3scale +type threeScaleTrait struct { + trait.BaseTrait `property:",squash"` + // Enables automatic configuration of the trait. + Auto *bool `property:"auto"` + // The scheme to use to contact the service (default `http`) + Scheme string `property:"scheme"` + // The path where the API is published (default `/`) + Path string `property:"path"` + // The port where the service is exposed (default `80`) + Port int `property:"port"` + // The path where the Open-API specification is published (default `/api-doc`) + DescriptionPath *string `property:"description-path"` +} + +const ( + // ThreeScaleSchemeAnnotation -- + ThreeScaleSchemeAnnotation = "discovery.3scale.net/scheme" + // ThreeScaleSchemeDefaultValue -- + ThreeScaleSchemeDefaultValue = "http" + + // ThreeScalePortAnnotation -- + ThreeScalePortAnnotation = "discovery.3scale.net/port" + // ThreeScalePortDefaultValue -- + ThreeScalePortDefaultValue = 80 + + // ThreeScalePathAnnotation -- + ThreeScalePathAnnotation = "discovery.3scale.net/path" + // ThreeScalePathDefaultValue -- + ThreeScalePathDefaultValue = "/" + + // ThreeScaleDescriptionPathAnnotation -- + ThreeScaleDescriptionPathAnnotation = "discovery.3scale.net/description-path" + // ThreeScaleDescriptionPathDefaultValue -- + ThreeScaleDescriptionPathDefaultValue = "/api-doc" + + // ThreeScaleDiscoveryLabel -- + ThreeScaleDiscoveryLabel = "discovery.3scale.net" + // ThreeScaleDiscoveryLabelEnabled -- + ThreeScaleDiscoveryLabelEnabled = "true" +) + +// NewThreeScaleTrait -- +func NewThreeScaleTrait() trait.Trait { + return &threeScaleTrait{ + BaseTrait: trait.NewBaseTrait("3scale", trait.TraitOrderPostProcessResources), + } +} + +func (t *threeScaleTrait) Configure(e *trait.Environment) (bool, error) { + if t.Enabled == nil || !*t.Enabled { + // disabled by default + return false, nil + } + + if !e.IntegrationInPhase(v1.IntegrationPhaseDeploying) { + return false, nil + } + + if t.Auto == nil || *t.Auto { + if t.Scheme == "" { + t.Scheme = ThreeScaleSchemeDefaultValue + } + if t.Path == "" { + t.Path = ThreeScalePathDefaultValue + } + if t.Port == 0 { + t.Port = ThreeScalePortDefaultValue + } + if t.DescriptionPath == nil { + openAPI := ThreeScaleDescriptionPathDefaultValue + t.DescriptionPath = &openAPI + } + } + return true, nil +} + +func (t *threeScaleTrait) Apply(e *trait.Environment) error { + if svc := e.Resources.GetServiceForIntegration(e.Integration); svc != nil { + t.addLabelsAndAnnotations(&svc.ObjectMeta) + } + return nil +} + +func (t *threeScaleTrait) addLabelsAndAnnotations(obj *metav1.ObjectMeta) { + if obj.Labels == nil { + obj.Labels = make(map[string]string) + } + obj.Labels[ThreeScaleDiscoveryLabel] = ThreeScaleDiscoveryLabelEnabled + + if obj.Annotations == nil { + obj.Annotations = make(map[string]string) + } + if t.Scheme != "" { + obj.Annotations[ThreeScaleSchemeAnnotation] = t.Scheme + } + if t.Path != "" { + obj.Annotations[ThreeScalePathAnnotation] = t.Path + } + if t.Port != 0 { + obj.Annotations[ThreeScalePortAnnotation] = strconv.Itoa(t.Port) + } + if t.DescriptionPath != nil && *t.DescriptionPath != "" { + obj.Annotations[ThreeScaleDescriptionPathAnnotation] = *t.DescriptionPath + } +} diff --git a/addons/threescale/3scale_test.go b/addons/threescale/3scale_test.go new file mode 100644 index 0000000..2ac8506 --- /dev/null +++ b/addons/threescale/3scale_test.go @@ -0,0 +1,114 @@ +/* +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 threescale + +import ( + "testing" + + v1 "github.com/apache/camel-k/pkg/apis/camel/v1" + "github.com/apache/camel-k/pkg/trait" + "github.com/apache/camel-k/pkg/util/camel" + "github.com/apache/camel-k/pkg/util/kubernetes" + "github.com/stretchr/testify/assert" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestThreeScaleDisabled(t *testing.T) { + catalog, err := camel.DefaultCatalog() + assert.Nil(t, err) + + e := &trait.Environment{ + CamelCatalog: catalog, + } + + threeScale := NewThreeScaleTrait() + enabled, err := threeScale.Configure(e) + assert.Nil(t, err) + assert.False(t, enabled) +} + +func TestThreeScaleInjection(t *testing.T) { + svc, e := createEnvironment(t) + threeScale := NewThreeScaleTrait() + enabled := true + threeScale.(*threeScaleTrait).Enabled = &enabled + ok, err := threeScale.Configure(e) + assert.Nil(t, err) + assert.True(t, ok) + + err = threeScale.Apply(e) + assert.Nil(t, err) + + assert.Equal(t, "true", svc.Labels["discovery.3scale.net"]) + assert.Equal(t, "http", svc.Annotations["discovery.3scale.net/scheme"]) + assert.Equal(t, "/", svc.Annotations["discovery.3scale.net/path"]) + assert.Equal(t, "80", svc.Annotations["discovery.3scale.net/port"]) + assert.Equal(t, "/api-doc", svc.Annotations["discovery.3scale.net/description-path"]) +} + +func TestThreeScaleInjectionNoAPIPath(t *testing.T) { + svc, e := createEnvironment(t) + threeScale := NewThreeScaleTrait() + enabled := true + threeScale.(*threeScaleTrait).Enabled = &enabled + noPath := "" + threeScale.(*threeScaleTrait).DescriptionPath = &noPath + ok, err := threeScale.Configure(e) + assert.Nil(t, err) + assert.True(t, ok) + + err = threeScale.Apply(e) + assert.Nil(t, err) + + assert.Equal(t, "true", svc.Labels["discovery.3scale.net"]) + assert.Equal(t, "http", svc.Annotations["discovery.3scale.net/scheme"]) + assert.Equal(t, "/", svc.Annotations["discovery.3scale.net/path"]) + assert.Equal(t, "80", svc.Annotations["discovery.3scale.net/port"]) + _, p := svc.Annotations["discovery.3scale.net/description-path"] + assert.False(t, p) +} + +func createEnvironment(t *testing.T) (*corev1.Service, *trait.Environment) { + catalog, err := camel.DefaultCatalog() + assert.Nil(t, err) + + e := trait.Environment{ + CamelCatalog: catalog, + } + + svc := corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "camel.apache.org/integration": "test", + }, + }, + } + e.Resources = kubernetes.NewCollection(&svc) + + it := v1.Integration{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Status: v1.IntegrationStatus{ + Phase: v1.IntegrationPhaseDeploying, + }, + } + e.Integration = &it + return &svc, &e +} diff --git a/addons/threescale/zz_generated_doc.go b/addons/threescale/zz_generated_doc.go new file mode 100644 index 0000000..38eec99 --- /dev/null +++ b/addons/threescale/zz_generated_doc.go @@ -0,0 +1 @@ +package threescale diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 9a7f96b..9d9daa5 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -16,6 +16,7 @@ ** xref:configuration/configmap-secret.adoc[ConfigMap/Secret] * xref:traits/traits.adoc[Traits] // Start of autogenerated code - DO NOT EDIT! (trait-nav) +** xref:traits/3scale.adoc[3scale] ** xref:traits/affinity.adoc[Affinity] ** xref:traits/builder.adoc[Builder] ** xref:traits/camel.adoc[Camel] @@ -33,12 +34,12 @@ ** xref:traits/knative-service.adoc[Knative Service] ** xref:traits/knative.adoc[Knative] ** xref:traits/master.adoc[Master] +** xref:traits/openapi.adoc[Openapi] ** xref:traits/owner.adoc[Owner] ** xref:traits/platform.adoc[Platform] ** xref:traits/prometheus.adoc[Prometheus] ** xref:traits/pull-secret.adoc[Pull Secret] ** xref:traits/quarkus.adoc[Quarkus] -** xref:traits/openapi.adoc[Rest Dsl] ** xref:traits/route.adoc[Route] ** xref:traits/service.adoc[Service] // End of autogenerated code - DO NOT EDIT! (trait-nav) diff --git a/docs/modules/ROOT/pages/traits/3scale.adoc b/docs/modules/ROOT/pages/traits/3scale.adoc new file mode 100755 index 0000000..ff11f2c --- /dev/null +++ b/docs/modules/ROOT/pages/traits/3scale.adoc @@ -0,0 +1,52 @@ += 3scale Trait + +// Start of autogenerated code - DO NOT EDIT! (description) +The 3scale trait can be used to automatically create annotations that allow +3scale to discover the generated service and make it available for API management. + +The 3scale trait is disabled by default. + + +This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**. + +// End of autogenerated code - DO NOT EDIT! (description) +// Start of autogenerated code - DO NOT EDIT! (configuration) +== Configuration + +Trait properties can be specified when running any integration with the CLI: +``` +kamel run --trait 3scale.[key]=[value] --trait 3scale.[key2]=[value2] integration.groovy +``` +The following configuration options are available: + +[cols="2,1,5a"] +|=== +|Property | Type | Description + +| 3scale.enabled +| bool +| Can be used to enable or disable a trait. All traits share this common property. + +| 3scale.auto +| bool +| Enables automatic configuration of the trait. + +| 3scale.scheme +| string +| The scheme to use to contact the service (default `http`) + +| 3scale.path +| string +| The path where the API is published (default `/`) + +| 3scale.port +| int +| The port where the service is exposed (default `80`) + +| 3scale.description-path +| string +| The path where the Open-API specification is published (default `/api-doc`) + +|=== + +// End of autogenerated code - DO NOT EDIT! (configuration) diff --git a/docs/modules/ROOT/pages/traits/container.adoc b/docs/modules/ROOT/pages/traits/container.adoc index 1f98244..95edc41 100755 --- a/docs/modules/ROOT/pages/traits/container.adoc +++ b/docs/modules/ROOT/pages/traits/container.adoc @@ -72,6 +72,65 @@ The following configuration options are available: | string | The main container name. It's named `integration` by default. +| container.probes-enabled +| bool +| ProbesEnabled enable/disable probes on the container (default `false`) + +| container.probe-port +| int +| ProbePort configures the port on which the probes are exposed, by default it inhierit the +value from the `http` port configured on the container. Note that the value has no effect for Knative service +as the port should be the same as the port declared by the container. + +| container.probe-path +| string +| Path to access on the probe ( default `/health`). Note that this property is not supported +on quarkus runtime and setting it will result in the integration failing to start. + +| container.liveness-initial-delay +| int32 +| Number of seconds after the container has started before liveness probes are initiated. + +| container.liveness-timeout +| int32 +| Number of seconds after which the probe times out. Applies to the liveness probe. + +| container.liveness-period +| int32 +| How often to perform the probe. Applies to the liveness probe. + +| container.liveness-success-threshold +| int32 +| Minimum consecutive successes for the probe to be considered successful after having failed. +Applies to the liveness probe. + +| container.liveness-failure-threshold +| int32 +| Minimum consecutive failures for the probe to be considered failed after having succeeded. +Applies to the liveness probe. + +| container.readiness-initial-delay +| int32 +| Number of seconds after the container has started before readiness probes are initiated. + +| container.readiness-timeout +| int32 +| Number of seconds after which the probe times out. Applies to the readiness probe. + +| container.readiness-period +| int32 +| How often to perform the probe. Applies to the readiness probe. + +| container.readiness-success-threshold +| int32 +| Minimum consecutive successes for the probe to be considered successful after having failed. +Applies to the readiness probe. + +| container.readiness-failure-threshold +| int32 +| Minimum consecutive failures for the probe to be considered failed after having succeeded. +Applies to the readiness probe. + |=== // End of autogenerated code - DO NOT EDIT! (configuration) diff --git a/docs/modules/ROOT/pages/traits/openapi.adoc b/docs/modules/ROOT/pages/traits/openapi.adoc index e3fe189..b8d919c 100755 --- a/docs/modules/ROOT/pages/traits/openapi.adoc +++ b/docs/modules/ROOT/pages/traits/openapi.adoc @@ -1,7 +1,7 @@ = Rest Dsl Trait // Start of autogenerated code - DO NOT EDIT! (description) -The Rest DSL trait is internally used to allow creating integrations from a OpenAPI specs. +The OpenAPI DSL trait is internally used to allow creating integrations from a OpenAPI specs. This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**. @@ -22,7 +22,7 @@ The following configuration options are available: |=== |Property | Type | Description -| rest-dsl.enabled +| openapi.enabled | bool | Can be used to enable or disable a trait. All traits share this common property. diff --git a/docs/modules/ROOT/pages/traits/traits.adoc b/docs/modules/ROOT/pages/traits/traits.adoc index fac82b1..e2e663c 100644 --- a/docs/modules/ROOT/pages/traits/traits.adoc +++ b/docs/modules/ROOT/pages/traits/traits.adoc @@ -34,6 +34,7 @@ A trait may have additional properties that can be configured by the end user. See the trait description pages for more information on a specific trait: // Start of autogenerated code - DO NOT EDIT! (trait-list) +* xref:traits/3scale.adoc[3scale Trait] * xref:traits/affinity.adoc[Affinity Trait] * xref:traits/builder.adoc[Builder Trait] * xref:traits/camel.adoc[Camel Trait] @@ -51,12 +52,12 @@ See the trait description pages for more information on a specific trait: * xref:traits/knative-service.adoc[Knative Service Trait] * xref:traits/knative.adoc[Knative Trait] * xref:traits/master.adoc[Master Trait] +* xref:traits/openapi.adoc[Openapi Trait] * xref:traits/owner.adoc[Owner Trait] * xref:traits/platform.adoc[Platform Trait] * xref:traits/prometheus.adoc[Prometheus Trait] * xref:traits/pull-secret.adoc[Pull Secret Trait] * xref:traits/quarkus.adoc[Quarkus Trait] -* xref:traits/openapi.adoc[Rest Dsl Trait] * xref:traits/route.adoc[Route Trait] * xref:traits/service.adoc[Service Trait] // End of autogenerated code - DO NOT EDIT! (trait-list) diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index 918c694..5329c0d 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -50,7 +50,7 @@ import ( ) var ( - traitConfigRegexp = regexp.MustCompile(`^([a-z-]+)((?:\.[a-z-]+)+)=(.*)$`) + traitConfigRegexp = regexp.MustCompile(`^([a-z0-9-]+)((?:\.[a-z0-9-]+)+)=(.*)$`) ) func newCmdRun(rootCmdOptions *RootCmdOptions) (*cobra.Command, *runCmdOptions) {