Skip to content

Commit

Permalink
feat(trait/openapi): support configmap configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
squakez committed Dec 15, 2021
1 parent 0c7ba0c commit fc85372
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 27 deletions.
23 changes: 22 additions & 1 deletion examples/openapi/README.md
Original file line number Diff line number Diff line change
@@ -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.
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
```
2 changes: 1 addition & 1 deletion examples/openapi/greetings.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down
2 changes: 1 addition & 1 deletion examples/openapi/petstore.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down
73 changes: 56 additions & 17 deletions pkg/trait/openapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ import (
"strconv"
"strings"

"go.uber.org/multierr"

"github.com/pkg/errors"

corev1 "k8s.io/api/core/v1"
Expand All @@ -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 {
Expand Down Expand Up @@ -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
}

Expand All @@ -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 {
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down
8 changes: 1 addition & 7 deletions pkg/util/digest/digest.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
Expand Down

0 comments on commit fc85372

Please sign in to comment.