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

commit 46706b8f379291ddd8875a32dfd585203742757b
Author: Pasquale Congiusti <[email protected]>
AuthorDate: Tue Dec 7 11:32:02 2021 +0100

    feat(trait/openapi): support configmap configuration
    
    Closes #2772
---
 examples/openapi/README.md        | 23 +++++++++++-
 examples/openapi/greetings.groovy |  2 +-
 examples/openapi/petstore.groovy  |  2 +-
 pkg/trait/openapi.go              | 73 ++++++++++++++++++++++++++++++---------
 pkg/util/digest/digest.go         |  8 +----
 5 files changed, 81 insertions(+), 27 deletions(-)

diff --git a/examples/openapi/README.md b/examples/openapi/README.md
index 41193d7..c8ca3c0 100644
--- a/examples/openapi/README.md
+++ b/examples/openapi/README.md
@@ -1,3 +1,24 @@
 # Open API Camel K examples
 
-Find useful examples about how to expose an Open API specification in a Camel 
K integration.
\ No newline at end of file
+Find useful examples about how to expose an Open API specification in a Camel 
K integration.
+
+## Greetings example
+
+Deploy the examples running
+
+```
+kamel run --dev --name greetings --open-api greetings-api.json greetings.groovy
+```
+
+Then you can test by calling the hello endpoint, ie:
+
+```
+$ curl -i http://192.168.49.2:31373/camel/greetings/hello
+HTTP/1.1 200 OK
+Accept: */*
+name: hello
+User-Agent: curl/7.68.0
+transfer-encoding: chunked
+
+Hello from hello
+```
\ No newline at end of file
diff --git a/examples/openapi/greetings.groovy 
b/examples/openapi/greetings.groovy
index a96fa64..90a09ce 100644
--- a/examples/openapi/greetings.groovy
+++ b/examples/openapi/greetings.groovy
@@ -17,7 +17,7 @@
  */
 
 //
-//  kamel run --dev --name greetings --open-api examples/greetings-api.json 
examples/greetings.groovy
+//  kamel run --dev --name greetings --open-api greetings-api.json 
greetings.groovy
 // 
 
 from('direct:greeting-api')
diff --git a/examples/openapi/petstore.groovy b/examples/openapi/petstore.groovy
index d382b21..880e22b 100644
--- a/examples/openapi/petstore.groovy
+++ b/examples/openapi/petstore.groovy
@@ -17,7 +17,7 @@
  */
 
 //
-//  kamel run --dev --name petstore --open-api examples/petstore-api.yaml 
examples/petstore.groovy
+//  kamel run --dev --name petstore --open-api petstore-api.yaml 
petstore.groovy
 // 
 
 from('direct:listPets')
diff --git a/pkg/trait/openapi.go b/pkg/trait/openapi.go
index 09d7ab5..b1ff98d 100644
--- a/pkg/trait/openapi.go
+++ b/pkg/trait/openapi.go
@@ -27,8 +27,6 @@ import (
        "strconv"
        "strings"
 
-       "go.uber.org/multierr"
-
        "github.com/pkg/errors"
 
        corev1 "k8s.io/api/core/v1"
@@ -52,6 +50,8 @@ import (
 // +camel-k:trait=openapi.
 type openAPITrait struct {
        BaseTrait `property:",squash"`
+       // The configmaps holding the spec of the OpenAPI
+       Configmaps []string `property:"configmaps" json:"configmaps,omitempty"`
 }
 
 func newOpenAPITrait() Trait {
@@ -85,6 +85,10 @@ func (t *openAPITrait) Configure(e *Environment) (bool, 
error) {
                }
        }
 
+       if t.Configmaps != nil {
+               return e.IntegrationInPhase(v1.IntegrationPhaseInitialization), 
nil
+       }
+
        return false, nil
 }
 
@@ -97,26 +101,63 @@ func (t *openAPITrait) Apply(e *Environment) error {
                return err
        }
 
-       for i, resource := range e.Integration.Spec.Resources {
+       generatedFromResources, err := t.generateFromResources(e, tmpDir)
+       if err != nil {
+               return os.RemoveAll(tmpDir)
+       }
+       generatedFromConfigmaps, err := t.generateFromConfigmaps(e, tmpDir)
+       if err != nil {
+               return os.RemoveAll(tmpDir)
+       }
+       if generatedFromConfigmaps != nil && len(generatedFromConfigmaps) > 0 {
+               generatedFromResources = append(generatedFromResources, 
generatedFromConfigmaps...)
+       }
+       e.Integration.Status.GeneratedSources = generatedFromResources
+
+       return os.RemoveAll(tmpDir)
+}
+
+func (t *openAPITrait) generateFromResources(e *Environment, tmpDir string) 
([]v1.SourceSpec, error) {
+       dataSpecs := make([]v1.DataSpec, 0, len(e.Integration.Spec.Resources))
+       for _, resource := range e.Integration.Spec.Resources {
                if resource.Type != v1.ResourceTypeOpenAPI {
                        continue
                }
                if resource.Name == "" {
-                       return multierr.Append(
-                               fmt.Errorf("no name defined for the openapi 
resource: %v", resource),
-                               os.RemoveAll(tmpDir))
+                       return nil, fmt.Errorf("no name defined for the openapi 
resource: %v", resource)
+               }
+               dataSpecs = append(dataSpecs, resource.DataSpec)
+       }
+
+       return t.generateFromDataSpecs(e, tmpDir, dataSpecs)
+}
+
+func (t *openAPITrait) generateFromConfigmaps(e *Environment, tmpDir string) 
([]v1.SourceSpec, error) {
+       dataSpecs := make([]v1.DataSpec, 0, len(t.Configmaps))
+       for _, configmap := range t.Configmaps {
+               cm := kubernetes.LookupConfigmap(e.Ctx, e.Client, 
e.Integration.Namespace, configmap)
+               // Iterate over each configmap key which may hold a different 
OpenAPI spec
+               for k, v := range cm.Data {
+                       dataSpecs = append(dataSpecs, v1.DataSpec{
+                               Name:        k,
+                               Content:     v,
+                               Compression: false,
+                       })
                }
+       }
 
-               generatedContentName := fmt.Sprintf("%s-openapi-%03d", 
e.Integration.Name, i)
+       return t.generateFromDataSpecs(e, tmpDir, dataSpecs)
+}
 
+func (t *openAPITrait) generateFromDataSpecs(e *Environment, tmpDir string, 
specs []v1.DataSpec) ([]v1.SourceSpec, error) {
+       generatedSources := make([]v1.SourceSpec, 0, 
len(e.Integration.Status.GeneratedSources))
+       for i, resource := range specs {
+               generatedContentName := fmt.Sprintf("%s-openapi-%03d", 
e.Integration.Name, i)
+               generatedSourceName := strings.TrimSuffix(resource.Name, 
filepath.Ext(resource.Name)) + ".xml"
                // Generate configmap or reuse existing one
                if err := t.generateOpenAPIConfigMap(e, resource, tmpDir, 
generatedContentName); err != nil {
-                       return errors.Wrapf(err, "cannot generate configmap for 
openapi resource %s", resource.Name)
+                       return nil, errors.Wrapf(err, "cannot generate 
configmap for openapi resource %s", resource.Name)
                }
-
-               generatedSourceName := strings.TrimSuffix(resource.Name, 
filepath.Ext(resource.Name)) + ".xml"
-               generatedSources := make([]v1.SourceSpec, 0, 
len(e.Integration.Status.GeneratedSources))
-
                if e.Integration.Status.GeneratedSources != nil {
                        // Filter out the previously generated source
                        for _, x := range e.Integration.Status.GeneratedSources 
{
@@ -135,14 +176,12 @@ func (t *openAPITrait) Apply(e *Environment) error {
                        },
                        Language: v1.LanguageXML,
                })
-
-               e.Integration.Status.GeneratedSources = generatedSources
        }
 
-       return os.RemoveAll(tmpDir)
+       return generatedSources, nil
 }
 
-func (t *openAPITrait) generateOpenAPIConfigMap(e *Environment, resource 
v1.ResourceSpec, tmpDir, generatedContentName string) error {
+func (t *openAPITrait) generateOpenAPIConfigMap(e *Environment, resource 
v1.DataSpec, tmpDir, generatedContentName string) error {
        cm := corev1.ConfigMap{}
        key := client.ObjectKey{
                Namespace: e.Integration.Namespace,
@@ -176,7 +215,7 @@ func (t *openAPITrait) generateOpenAPIConfigMap(e 
*Environment, resource v1.Reso
        return t.createNewOpenAPIConfigMap(e, resource, tmpDir, 
generatedContentName)
 }
 
-func (t *openAPITrait) createNewOpenAPIConfigMap(e *Environment, resource 
v1.ResourceSpec, tmpDir, generatedContentName string) error {
+func (t *openAPITrait) createNewOpenAPIConfigMap(e *Environment, resource 
v1.DataSpec, tmpDir, generatedContentName string) error {
        tmpDir = path.Join(tmpDir, generatedContentName)
        err := os.MkdirAll(tmpDir, os.ModePerm)
        if err != nil {
diff --git a/pkg/util/digest/digest.go b/pkg/util/digest/digest.go
index 4d999a1..566a873 100644
--- a/pkg/util/digest/digest.go
+++ b/pkg/util/digest/digest.go
@@ -160,7 +160,7 @@ func ComputeForIntegrationKit(kit *v1.IntegrationKit) 
(string, error) {
 }
 
 // ComputeForResource returns a digest for the specific resource.
-func ComputeForResource(res v1.ResourceSpec) (string, error) {
+func ComputeForResource(res v1.DataSpec) (string, error) {
        hash := sha256.New()
        // Operator version is relevant
        if _, err := hash.Write([]byte(defaults.Version)); err != nil {
@@ -173,18 +173,12 @@ func ComputeForResource(res v1.ResourceSpec) (string, 
error) {
        if _, err := hash.Write([]byte(res.Name)); err != nil {
                return "", err
        }
-       if _, err := hash.Write([]byte(res.Type)); err != nil {
-               return "", err
-       }
        if _, err := hash.Write([]byte(res.ContentKey)); err != nil {
                return "", err
        }
        if _, err := hash.Write([]byte(res.ContentRef)); err != nil {
                return "", err
        }
-       if _, err := hash.Write([]byte(res.MountPath)); err != nil {
-               return "", err
-       }
        if _, err := hash.Write([]byte(strconv.FormatBool(res.Compression))); 
err != nil {
                return "", err
        }

Reply via email to