You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2022/01/07 13:48:20 UTC
[camel-k] 14/24: feat(trait/openapi): support configmap configuration
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 <pa...@gmail.com>
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
}