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

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


The following commit(s) were added to refs/heads/main by this push:
     new 699810e2b feat(trait): deprecate openapi trait
699810e2b is described below

commit 699810e2bdf3a0cfa7930c4dc6702e54eeb6b8e2
Author: Pasquale Congiusti <[email protected]>
AuthorDate: Tue Oct 15 22:28:25 2024 +0200

    feat(trait): deprecate openapi trait
    
    In favour of contract first openapi Camel feature
    
    Closes #5729
---
 docs/modules/ROOT/partials/apis/camel-k-crds.adoc  |  3 ++
 docs/modules/traits/pages/openapi.adoc             |  4 +++
 .../files/openapi => misc/files}/petstore-api.yaml |  0
 .../files/openapi => misc/files}/petstore.yaml     |  4 +++
 e2e/common/{traits => misc}/openapi_test.go        | 35 ++++++++++++++--------
 e2e/support/test_support.go                        | 20 -------------
 pkg/apis/camel/v1/trait/openapi.go                 |  4 +++
 pkg/apis/camel/v1/trait/service_binding.go         |  2 +-
 pkg/trait/openapi.go                               | 17 +++++++----
 pkg/trait/openapi_test.go                          |  6 +++-
 pkg/util/source/inspector.go                       |  7 +++++
 pkg/util/source/inspector_java_source_test.go      | 19 ++++++++++++
 pkg/util/source/inspector_xml.go                   |  5 ++++
 pkg/util/source/inspector_xml_test.go              | 23 ++++++++++++++
 pkg/util/source/inspector_yaml.go                  | 23 ++++++++++++++
 pkg/util/source/inspector_yaml_test.go             | 28 +++++++++++++++++
 16 files changed, 160 insertions(+), 40 deletions(-)

diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc 
b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
index cae7017d4..c778d4ff4 100644
--- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
+++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
@@ -8047,6 +8047,9 @@ Deprecated: no longer available since version 2.5.
 
 The OpenAPI DSL trait is internally used to allow creating integrations from a 
OpenAPI specs.
 
+WARNING: The Openapi trait is **deprecated** and will removed in future 
release versions:
+use Camel REST contract first instead, 
https://camel.apache.org/manual/rest-dsl-openapi.html
+
 
 [cols="2,2a",options="header"]
 |===
diff --git a/docs/modules/traits/pages/openapi.adoc 
b/docs/modules/traits/pages/openapi.adoc
index 28f985dd6..f4276164e 100755
--- a/docs/modules/traits/pages/openapi.adoc
+++ b/docs/modules/traits/pages/openapi.adoc
@@ -1,10 +1,14 @@
 = Openapi Trait
 
 // Start of autogenerated code - DO NOT EDIT! (badges)
+image:https://img.shields.io/badge/2.5.0-white?label=Deprecated&labelColor=C40C0C&color=gray[Deprecated
 Badge]
 // End of autogenerated code - DO NOT EDIT! (badges)
 // Start of autogenerated code - DO NOT EDIT! (description)
 The OpenAPI DSL trait is internally used to allow creating integrations from a 
OpenAPI specs.
 
+WARNING: The Openapi trait is **deprecated** and will removed in future 
release versions:
+use Camel REST contract first instead, 
https://camel.apache.org/manual/rest-dsl-openapi.html
+
 
 This trait is available in the following profiles: **Kubernetes, Knative, 
OpenShift**.
 
diff --git a/e2e/common/traits/files/openapi/petstore-api.yaml 
b/e2e/common/misc/files/petstore-api.yaml
similarity index 100%
rename from e2e/common/traits/files/openapi/petstore-api.yaml
rename to e2e/common/misc/files/petstore-api.yaml
diff --git a/e2e/common/traits/files/openapi/petstore.yaml 
b/e2e/common/misc/files/petstore.yaml
similarity index 95%
rename from e2e/common/traits/files/openapi/petstore.yaml
rename to e2e/common/misc/files/petstore.yaml
index 72087814f..ca4e483e3 100644
--- a/e2e/common/traits/files/openapi/petstore.yaml
+++ b/e2e/common/misc/files/petstore.yaml
@@ -17,6 +17,10 @@
 # limitations under the License.
 # ---------------------------------------------------------------------------
 
+- rest:
+    openApi:
+      specification: petstore-api.yaml
+
 - from:
     uri: "direct:listPets"
     steps:
diff --git a/e2e/common/traits/openapi_test.go b/e2e/common/misc/openapi_test.go
similarity index 56%
rename from e2e/common/traits/openapi_test.go
rename to e2e/common/misc/openapi_test.go
index 217738d60..e98dd7596 100644
--- a/e2e/common/traits/openapi_test.go
+++ b/e2e/common/misc/openapi_test.go
@@ -24,38 +24,47 @@ package common
 
 import (
        "context"
+       "fmt"
        "os"
        "testing"
+       "time"
 
        . "github.com/onsi/gomega"
+       "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/require"
 
        corev1 "k8s.io/api/core/v1"
 
        . "github.com/apache/camel-k/v2/e2e/support"
+       v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
 )
 
 func TestOpenAPI(t *testing.T) {
        t.Parallel()
        WithNewTestNamespace(t, func(ctx context.Context, g *WithT, ns string) {
-               openapiContent, err := 
os.ReadFile("./files/openapi/petstore-api.yaml")
+               name := RandomizedSuffixName("petstore")
+               openapiContent, err := os.ReadFile("./files/petstore-api.yaml")
                require.NoError(t, err)
                var cmDataProps = make(map[string]string)
                cmDataProps["petstore-api.yaml"] = string(openapiContent)
                CreatePlainTextConfigmap(t, ctx, ns, "my-openapi", cmDataProps)
 
-               g.Expect(KamelRun(t, ctx, ns, "--name", "petstore", 
"--open-api", "configmap:my-openapi", 
"files/openapi/petstore.yaml").Execute()).To(Succeed())
+               g.Expect(KamelRun(t, ctx, ns,
+                       "--name", name, "--resource", "configmap:my-openapi", 
"files/petstore.yaml").
+                       Execute()).To(Succeed())
 
-               g.Eventually(IntegrationPodPhase(t, ctx, ns, "petstore"), 
TestTimeoutLong).
-                       Should(Equal(corev1.PodRunning))
-               g.Eventually(DeploymentWithIntegrationLabel(t, ctx, ns, 
"petstore"), TestTimeoutLong).
-                       Should(Not(BeNil()))
-
-               g.Eventually(IntegrationLogs(t, ctx, ns, "petstore"), 
TestTimeoutMedium).
-                       Should(ContainSubstring("Started listPets 
(rest://get:/v1:/pets)"))
-               g.Eventually(IntegrationLogs(t, ctx, ns, "petstore"), 
TestTimeoutMedium).
-                       Should(ContainSubstring("Started createPets 
(rest://post:/v1:/pets)"))
-               g.Eventually(IntegrationLogs(t, ctx, ns, "petstore"), 
TestTimeoutMedium).
-                       Should(ContainSubstring("Started showPetById 
(rest://get:/v1:/pets/%7BpetId%7D)"))
+               g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, 
v1.IntegrationConditionReady), TestTimeoutMedium).
+                       Should(Equal(corev1.ConditionTrue))
+               g.Eventually(IntegrationPodPhase(t, ctx, ns, 
name)).Should(Equal(corev1.PodRunning))
+               // Let's make sure the Integration is ready to receive traffic
+               g.Eventually(IntegrationLogs(t, ctx, ns, 
name)).Should(ContainSubstring("Listening on: http://0.0.0.0:8080";))
+               pod := IntegrationPod(t, ctx, ns, name)()
+               g.Expect(pod).NotTo(BeNil())
+               response, err := TestClient(t).CoreV1().RESTClient().Get().
+                       Timeout(30 * time.Second).
+                       
AbsPath(fmt.Sprintf("/api/v1/namespaces/%s/pods/%s/proxy/v1/pets", 
pod.Namespace, pod.Name)).
+                       DoRaw(ctx)
+               require.NoError(t, err)
+               assert.Equal(t, "listPets", string(response))
        })
 }
diff --git a/e2e/support/test_support.go b/e2e/support/test_support.go
index 54d58fc63..7b055195a 100644
--- a/e2e/support/test_support.go
+++ b/e2e/support/test_support.go
@@ -1774,26 +1774,6 @@ func KnativeService(t *testing.T, ctx context.Context, 
ns string, name string) f
                return &answer
        }
 }
-func DeploymentWithIntegrationLabel(t *testing.T, ctx context.Context, ns 
string, label string) func() *appsv1.Deployment {
-       return func() *appsv1.Deployment {
-               lst := appsv1.DeploymentList{
-                       TypeMeta: metav1.TypeMeta{
-                               Kind:       "Deployment",
-                               APIVersion: appsv1.SchemeGroupVersion.String(),
-                       },
-               }
-               if err := TestClient(t).List(ctx, &lst, ctrl.InNamespace(ns), 
ctrl.MatchingLabels{v1.IntegrationLabel: label}); err != nil && 
k8serrors.IsNotFound(err) {
-                       return nil
-               } else if err != nil {
-                       log.Errorf(err, "Error while retrieving deployment %s", 
label)
-                       return nil
-               }
-               if len(lst.Items) == 0 {
-                       return nil
-               }
-               return &lst.Items[0]
-       }
-}
 
 func Deployment(t *testing.T, ctx context.Context, ns string, name string) 
func() *appsv1.Deployment {
        return func() *appsv1.Deployment {
diff --git a/pkg/apis/camel/v1/trait/openapi.go 
b/pkg/apis/camel/v1/trait/openapi.go
index a8c7f6a41..de0acedb1 100644
--- a/pkg/apis/camel/v1/trait/openapi.go
+++ b/pkg/apis/camel/v1/trait/openapi.go
@@ -19,7 +19,11 @@ package trait
 
 // The OpenAPI DSL trait is internally used to allow creating integrations 
from a OpenAPI specs.
 //
+// WARNING: The Openapi trait is **deprecated** and will removed in future 
release versions:
+// use Camel REST contract first instead, 
https://camel.apache.org/manual/rest-dsl-openapi.html
+//
 // +camel-k:trait=openapi.
+// +camel-k:deprecated=2.5.0.
 type OpenAPITrait struct {
        PlatformBaseTrait `property:",squash" json:",inline"`
        // The configmaps holding the spec of the OpenAPI (compatible with > 
3.0 spec only).
diff --git a/pkg/apis/camel/v1/trait/service_binding.go 
b/pkg/apis/camel/v1/trait/service_binding.go
index 82aff8e01..4b5a8bb63 100644
--- a/pkg/apis/camel/v1/trait/service_binding.go
+++ b/pkg/apis/camel/v1/trait/service_binding.go
@@ -17,7 +17,7 @@ limitations under the License.
 
 package trait
 
-// WARNING: The Registry trait is **deprecated** and will removed in future 
release versions.
+// WARNING: The Service Binding trait is **deprecated** and will removed in 
future release versions.
 //
 
 // The Service Binding trait allows users to connect to Services in Kubernetes:
diff --git a/pkg/trait/openapi.go b/pkg/trait/openapi.go
index fbc1bf49d..4b1a1100b 100644
--- a/pkg/trait/openapi.go
+++ b/pkg/trait/openapi.go
@@ -62,12 +62,19 @@ func newOpenAPITrait() Trait {
 }
 
 func (t *openAPITrait) Configure(e *Environment) (bool, *TraitCondition, 
error) {
-       if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
-               return false, nil, nil
-       }
-
        if t.Configmaps != nil {
-               return e.IntegrationInPhase(v1.IntegrationPhaseInitialization), 
nil, nil
+               if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
+                       condition := NewIntegrationCondition(
+                               "OpenApi",
+                               v1.IntegrationConditionTraitInfo,
+                               corev1.ConditionTrue,
+                               traitConfigurationReason,
+                               "OpenApi trait is deprecated and may be removed 
in future version: "+
+                                       "use Camel REST contract first instead, 
https://camel.apache.org/manual/rest-dsl-openapi.html";,
+                       )
+
+                       return true, condition, nil
+               }
        }
 
        return false, nil, nil
diff --git a/pkg/trait/openapi_test.go b/pkg/trait/openapi_test.go
index 8ef68f2a2..85a55a68c 100644
--- a/pkg/trait/openapi_test.go
+++ b/pkg/trait/openapi_test.go
@@ -73,7 +73,11 @@ func TestRestDslTraitApplicability(t *testing.T) {
        enabled, condition, err = trait.Configure(e)
        require.NoError(t, err)
        assert.True(t, enabled)
-       assert.Nil(t, condition)
+       assert.NotNil(t, condition)
+       assert.Equal(t, "OpenApi trait is deprecated and may be removed in 
future version: "+
+               "use Camel REST contract first instead, 
https://camel.apache.org/manual/rest-dsl-openapi.html";,
+               condition.message,
+       )
 }
 
 func TestRestDslTraitApplyError(t *testing.T) {
diff --git a/pkg/util/source/inspector.go b/pkg/util/source/inspector.go
index 04c646b95..1c697b9a4 100644
--- a/pkg/util/source/inspector.go
+++ b/pkg/util/source/inspector.go
@@ -54,6 +54,7 @@ var (
        restConfigurationRegexp = 
regexp.MustCompile(`.*restConfiguration\(\).*`)
        restRegexp              = regexp.MustCompile(`.*rest\s*\([^)]*\).*`)
        restClosureRegexp       = regexp.MustCompile(`.*rest\s*{\s*`)
+       openAPIRegexp           = 
regexp.MustCompile(`.*\.openApi\s*\([^)]*\).*`)
        groovyLanguageRegexp    = regexp.MustCompile(`.*\.groovy\s*\(.*\).*`)
        jsonPathLanguageRegexp  = 
regexp.MustCompile(`.*\.?(jsonpath|jsonpathWriteAsString)\s*\(.*\).*`)
        ognlRegexp              = regexp.MustCompile(`.*\.ognl\s*\(.*\).*`)
@@ -110,6 +111,12 @@ var (
                        }
                        return deps
                },
+               openAPIRegexp: func(catalog *camel.RuntimeCatalog) []string {
+                       if dfDep := 
catalog.GetArtifactByScheme("rest-openapi"); dfDep != nil {
+                               return []string{dfDep.GetDependencyID()}
+                       }
+                       return []string{}
+               },
                groovyLanguageRegexp: func(catalog *camel.RuntimeCatalog) 
[]string {
                        if dependency, ok := 
catalog.GetLanguageDependency("groovy"); ok {
                                return []string{dependency}
diff --git a/pkg/util/source/inspector_java_source_test.go 
b/pkg/util/source/inspector_java_source_test.go
index 71e60e2db..33e4722ba 100644
--- a/pkg/util/source/inspector_java_source_test.go
+++ b/pkg/util/source/inspector_java_source_test.go
@@ -171,3 +171,22 @@ func TestJavaReplaceURI(t *testing.T) {
        assert.True(t, replaced)
        assert.Equal(t, "from(\"direct:newURI?hello=world\").to(\"log:info\")", 
sourceSpec.Content)
 }
+
+func TestJavaRestOpenapiFirst(t *testing.T) {
+       inspector := newTestJavaSourceInspector(t)
+
+       sourceSpec := v1.SourceSpec{
+               DataSpec: v1.DataSpec{
+                       Name: "test.java",
+                       Content: `
+public void configure() throws Exception {
+    rest().openApi("petstore-v3.json");
+}
+                       `,
+               },
+       }
+       meta := NewMetadata()
+       err := inspector.Extract(sourceSpec, &meta)
+       require.NoError(t, err)
+       assert.Contains(t, meta.Dependencies.List(), "camel:rest-openapi")
+}
diff --git a/pkg/util/source/inspector_xml.go b/pkg/util/source/inspector_xml.go
index 1a1954879..2604a5944 100644
--- a/pkg/util/source/inspector_xml.go
+++ b/pkg/util/source/inspector_xml.go
@@ -49,9 +49,14 @@ func (i XMLInspector) Extract(source v1.SourceSpec, meta 
*Metadata) error {
 
                if se, ok := t.(xml.StartElement); ok {
                        switch se.Name.Local {
+                       //nolint: goconst
                        case "rest", "restConfiguration":
                                meta.ExposesHTTPServices = true
                                meta.RequiredCapabilities.Add(v1.CapabilityRest)
+                       case "openApi":
+                               if dfDep := 
i.catalog.GetArtifactByScheme("rest-openapi"); dfDep != nil {
+                                       
meta.AddDependency(dfDep.GetDependencyID())
+                               }
                        case "circuitBreaker":
                                
meta.RequiredCapabilities.Add(v1.CapabilityCircuitBreaker)
                        case "json":
diff --git a/pkg/util/source/inspector_xml_test.go 
b/pkg/util/source/inspector_xml_test.go
index 8e68c3bcf..98f326ced 100644
--- a/pkg/util/source/inspector_xml_test.go
+++ b/pkg/util/source/inspector_xml_test.go
@@ -205,3 +205,26 @@ func TestXMLReplaceURI(t *testing.T) {
        assert.True(t, replaced)
        assert.Contains(t, sourceSpec.Content, "<from 
uri=\"direct:newURI?hello=world\"/>")
 }
+
+func TestXMLRestOpenapiFirst(t *testing.T) {
+       inspector := newTestXMLInspector(t)
+
+       sourceSpec := v1.SourceSpec{
+               DataSpec: v1.DataSpec{
+                       Name: "test.xml",
+                       Content: `
+                 <rest>
+                       <openApi specification="petstore-v3.json"/>
+                 </rest>
+                 <route>
+                       <from uri="direct:getUserByName"/>
+                       // do something here
+                 </route>
+                       `,
+               },
+       }
+       meta := NewMetadata()
+       err := inspector.Extract(sourceSpec, &meta)
+       require.NoError(t, err)
+       assert.Contains(t, meta.Dependencies.List(), "camel:rest-openapi")
+}
diff --git a/pkg/util/source/inspector_yaml.go 
b/pkg/util/source/inspector_yaml.go
index 199007635..dac9165c0 100644
--- a/pkg/util/source/inspector_yaml.go
+++ b/pkg/util/source/inspector_yaml.go
@@ -41,6 +41,9 @@ func (i YAMLInspector) Extract(source v1.SourceSpec, meta 
*Metadata) error {
        }
 
        for _, definition := range definitions {
+               if err := i.parseDefinition(definition, meta); err != nil {
+                       return err
+               }
                for k, v := range definition {
                        if err := i.parseStep(k, v, meta); err != nil {
                                return err
@@ -62,6 +65,26 @@ func (i YAMLInspector) Extract(source v1.SourceSpec, meta 
*Metadata) error {
        return nil
 }
 
+//nolint:nestif
+func (i YAMLInspector) parseDefinition(def map[string]interface{}, meta 
*Metadata) error {
+       for k, v := range def {
+               if k == "rest" {
+                       meta.ExposesHTTPServices = true
+                       meta.RequiredCapabilities.Add(v1.CapabilityRest)
+                       // support contract first openapi
+                       if oa, ok := v.(map[interface{}]interface{}); ok {
+                               if _, oaOk := oa["openApi"]; oaOk {
+                                       if dfDep := 
i.catalog.GetArtifactByScheme("rest-openapi"); dfDep != nil {
+                                               
meta.AddDependency(dfDep.GetDependencyID())
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return nil
+}
+
 //nolint:nestif
 func (i YAMLInspector) parseStep(key string, content interface{}, meta 
*Metadata) error {
        switch key {
diff --git a/pkg/util/source/inspector_yaml_test.go 
b/pkg/util/source/inspector_yaml_test.go
index d1eee1462..03cd99178 100644
--- a/pkg/util/source/inspector_yaml_test.go
+++ b/pkg/util/source/inspector_yaml_test.go
@@ -729,3 +729,31 @@ func TestYAMLRouteReplaceURI(t *testing.T) {
        // Assert changed uri and removed parameters
        assert.Contains(t, sourceSpec.Content, expectedYamlRouteCronReplacement)
 }
+
+func TestYAMLRESTContractFirst(t *testing.T) {
+       yamlContractFirst := `
+- rest:
+    openApi:
+      specification: petstore-v3.json
+
+- route:
+    id: route1
+    from:
+      uri: "timer:tick"
+      parameters:
+        period: "5000"
+    steps:
+      - setBody:
+          constant: "Hello Yaml !!!"
+      - transform:
+          simple: "${body.toUpperCase()}"
+      - to: "{{url}}"
+`
+
+       inspector := newTestYAMLInspector(t)
+       t.Run("TestYAMLRESTContractFirst", func(t *testing.T) {
+               assertExtractYAML(t, inspector, yamlContractFirst, func(meta 
*Metadata) {
+                       assert.Contains(t, meta.Dependencies.List(), 
"camel:rest-openapi")
+               })
+       })
+}

Reply via email to