From 6a860261410706b8ac82e0d843bc8a1dca9c7dc8 Mon Sep 17 00:00:00 2001
From: Bob Callaway <bobcallaway@users.noreply.github.com>
Date: Mon, 7 Dec 2020 16:19:43 -0500
Subject: [PATCH] add XML & YAML support to API (#66)

* add xml & yaml format support

* add attributes to denote files that are generated so GH skips them on diffs
---
 .gitattributes                                |  2 +
 cmd/server/app/serve.go                       |  6 +++
 openapi.yaml                                  |  4 ++
 .../client/entries/entries_client.go          | 20 +++++-----
 pkg/generated/client/tlog/tlog_client.go      |  8 ++--
 .../restapi/configure_rekor_server.go         |  3 ++
 pkg/generated/restapi/doc.go                  |  4 ++
 pkg/generated/restapi/embedded_spec.go        | 16 ++++++--
 .../restapi/operations/rekor_server_api.go    | 37 +++++++++++++++++++
 9 files changed, 82 insertions(+), 18 deletions(-)
 create mode 100644 .gitattributes

diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..a86b714
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+/pkg/generated/** linguist-generated
+/pkg/generated/restapi/configure_rekor_server.go -linguist-generated
diff --git a/cmd/server/app/serve.go b/cmd/server/app/serve.go
index 7888786..55e0ea8 100644
--- a/cmd/server/app/serve.go
+++ b/cmd/server/app/serve.go
@@ -35,6 +35,12 @@ var serveCmd = &cobra.Command{
 
 		doc, _ := loads.Embedded(restapi.SwaggerJSON, restapi.FlatSwaggerJSON)
 		server := restapi.NewServer(operations.NewRekorServerAPI(doc))
+		defer func() {
+			if err := server.Shutdown(); err != nil {
+				log.Logger.Error(err)
+			}
+		}()
+
 		server.Host = viper.GetString("rekor_server.address")
 		server.Port = int(viper.GetUint("rekor_server.port"))
 		server.ConfigureAPI()
diff --git a/openapi.yaml b/openapi.yaml
index daf0530..786ba00 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -6,8 +6,12 @@ info:
 
 consumes:
   - application/json
+  - application/xml
+  - application/yaml
 produces:
   - application/json
+  - application/xml
+  - application/yaml
 
 paths:
   /api/v1/log:
diff --git a/pkg/generated/client/entries/entries_client.go b/pkg/generated/client/entries/entries_client.go
index e34df29..78c81aa 100644
--- a/pkg/generated/client/entries/entries_client.go
+++ b/pkg/generated/client/entries/entries_client.go
@@ -54,8 +54,8 @@ func (a *Client) CreateLogEntry(params *CreateLogEntryParams) (*CreateLogEntryCr
 		ID:                 "createLogEntry",
 		Method:             "POST",
 		PathPattern:        "/api/v1/log/entries",
-		ProducesMediaTypes: []string{"application/json"},
-		ConsumesMediaTypes: []string{"application/json"},
+		ProducesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
+		ConsumesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
 		Schemes:            []string{"http"},
 		Params:             params,
 		Reader:             &CreateLogEntryReader{formats: a.formats},
@@ -87,8 +87,8 @@ func (a *Client) GetLogEntryByIndex(params *GetLogEntryByIndexParams) (*GetLogEn
 		ID:                 "getLogEntryByIndex",
 		Method:             "GET",
 		PathPattern:        "/api/v1/log/entries",
-		ProducesMediaTypes: []string{"application/json"},
-		ConsumesMediaTypes: []string{"application/json"},
+		ProducesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
+		ConsumesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
 		Schemes:            []string{"http"},
 		Params:             params,
 		Reader:             &GetLogEntryByIndexReader{formats: a.formats},
@@ -120,8 +120,8 @@ func (a *Client) GetLogEntryByUUID(params *GetLogEntryByUUIDParams) (*GetLogEntr
 		ID:                 "getLogEntryByUUID",
 		Method:             "GET",
 		PathPattern:        "/api/v1/log/entries/{entryUUID}",
-		ProducesMediaTypes: []string{"application/json"},
-		ConsumesMediaTypes: []string{"application/json"},
+		ProducesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
+		ConsumesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
 		Schemes:            []string{"http"},
 		Params:             params,
 		Reader:             &GetLogEntryByUUIDReader{formats: a.formats},
@@ -155,8 +155,8 @@ func (a *Client) GetLogEntryProof(params *GetLogEntryProofParams) (*GetLogEntryP
 		ID:                 "getLogEntryProof",
 		Method:             "GET",
 		PathPattern:        "/api/v1/log/entries/{entryUUID}/proof",
-		ProducesMediaTypes: []string{"application/json"},
-		ConsumesMediaTypes: []string{"application/json"},
+		ProducesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
+		ConsumesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
 		Schemes:            []string{"http"},
 		Params:             params,
 		Reader:             &GetLogEntryProofReader{formats: a.formats},
@@ -188,8 +188,8 @@ func (a *Client) SearchLogQuery(params *SearchLogQueryParams) (*SearchLogQueryOK
 		ID:                 "searchLogQuery",
 		Method:             "POST",
 		PathPattern:        "/api/v1/log/entries/retrieve",
-		ProducesMediaTypes: []string{"application/json"},
-		ConsumesMediaTypes: []string{"application/json"},
+		ProducesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
+		ConsumesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
 		Schemes:            []string{"http"},
 		Params:             params,
 		Reader:             &SearchLogQueryReader{formats: a.formats},
diff --git a/pkg/generated/client/tlog/tlog_client.go b/pkg/generated/client/tlog/tlog_client.go
index d542788..76e39a9 100644
--- a/pkg/generated/client/tlog/tlog_client.go
+++ b/pkg/generated/client/tlog/tlog_client.go
@@ -47,8 +47,8 @@ func (a *Client) GetLogInfo(params *GetLogInfoParams) (*GetLogInfoOK, error) {
 		ID:                 "getLogInfo",
 		Method:             "GET",
 		PathPattern:        "/api/v1/log",
-		ProducesMediaTypes: []string{"application/json"},
-		ConsumesMediaTypes: []string{"application/json"},
+		ProducesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
+		ConsumesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
 		Schemes:            []string{"http"},
 		Params:             params,
 		Reader:             &GetLogInfoReader{formats: a.formats},
@@ -82,8 +82,8 @@ func (a *Client) GetLogProof(params *GetLogProofParams) (*GetLogProofOK, error)
 		ID:                 "getLogProof",
 		Method:             "GET",
 		PathPattern:        "/api/v1/log/proof",
-		ProducesMediaTypes: []string{"application/json"},
-		ConsumesMediaTypes: []string{"application/json"},
+		ProducesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
+		ConsumesMediaTypes: []string{"application/json", "application/xml", "application/yaml"},
 		Schemes:            []string{"http"},
 		Params:             params,
 		Reader:             &GetLogProofReader{formats: a.formats},
diff --git a/pkg/generated/restapi/configure_rekor_server.go b/pkg/generated/restapi/configure_rekor_server.go
index 2bf3de1..b528cf0 100644
--- a/pkg/generated/restapi/configure_rekor_server.go
+++ b/pkg/generated/restapi/configure_rekor_server.go
@@ -38,6 +38,9 @@ func configureAPI(api *operations.RekorServerAPI) http.Handler {
 	// To continue using redoc as your UI, uncomment the following line
 	// api.UseRedoc()
 
+	// this is needed to adhere to the order of producers specified in openapi.yaml
+	api.SetDefaultProduces("")
+
 	api.JSONConsumer = runtime.JSONConsumer()
 
 	api.JSONProducer = runtime.JSONProducer()
diff --git a/pkg/generated/restapi/doc.go b/pkg/generated/restapi/doc.go
index 00e8330..4a19e7e 100644
--- a/pkg/generated/restapi/doc.go
+++ b/pkg/generated/restapi/doc.go
@@ -11,9 +11,13 @@
 //
 //  Consumes:
 //    - application/json
+//    - application/xml
+//    - application/yaml
 //
 //  Produces:
 //    - application/json
+//    - application/xml
+//    - application/yaml
 //
 // swagger:meta
 package restapi
diff --git a/pkg/generated/restapi/embedded_spec.go b/pkg/generated/restapi/embedded_spec.go
index c82cca5..c376b08 100644
--- a/pkg/generated/restapi/embedded_spec.go
+++ b/pkg/generated/restapi/embedded_spec.go
@@ -19,10 +19,14 @@ var (
 func init() {
 	SwaggerJSON = json.RawMessage([]byte(`{
   "consumes": [
-    "application/json"
+    "application/json",
+    "application/xml",
+    "application/yaml"
   ],
   "produces": [
-    "application/json"
+    "application/json",
+    "application/xml",
+    "application/yaml"
   ],
   "swagger": "2.0",
   "info": {
@@ -529,10 +533,14 @@ func init() {
 }`))
 	FlatSwaggerJSON = json.RawMessage([]byte(`{
   "consumes": [
-    "application/json"
+    "application/json",
+    "application/xml",
+    "application/yaml"
   ],
   "produces": [
-    "application/json"
+    "application/json",
+    "application/xml",
+    "application/yaml"
   ],
   "swagger": "2.0",
   "info": {
diff --git a/pkg/generated/restapi/operations/rekor_server_api.go b/pkg/generated/restapi/operations/rekor_server_api.go
index 53d504d..223a16a 100644
--- a/pkg/generated/restapi/operations/rekor_server_api.go
+++ b/pkg/generated/restapi/operations/rekor_server_api.go
@@ -15,6 +15,7 @@ import (
 	"github.com/go-openapi/runtime"
 	"github.com/go-openapi/runtime/middleware"
 	"github.com/go-openapi/runtime/security"
+	"github.com/go-openapi/runtime/yamlpc"
 	"github.com/go-openapi/spec"
 	"github.com/go-openapi/strfmt"
 	"github.com/go-openapi/swag"
@@ -42,8 +43,12 @@ func NewRekorServerAPI(spec *loads.Document) *RekorServerAPI {
 		BearerAuthenticator: security.BearerAuth,
 
 		JSONConsumer: runtime.JSONConsumer(),
+		XMLConsumer:  runtime.XMLConsumer(),
+		YamlConsumer: yamlpc.YAMLConsumer(),
 
 		JSONProducer: runtime.JSONProducer(),
+		XMLProducer:  runtime.XMLProducer(),
+		YamlProducer: yamlpc.YAMLProducer(),
 
 		EntriesCreateLogEntryHandler: entries.CreateLogEntryHandlerFunc(func(params entries.CreateLogEntryParams) middleware.Responder {
 			return middleware.NotImplemented("operation entries.CreateLogEntry has not yet been implemented")
@@ -95,10 +100,22 @@ type RekorServerAPI struct {
 	// JSONConsumer registers a consumer for the following mime types:
 	//   - application/json
 	JSONConsumer runtime.Consumer
+	// XMLConsumer registers a consumer for the following mime types:
+	//   - application/xml
+	XMLConsumer runtime.Consumer
+	// YamlConsumer registers a consumer for the following mime types:
+	//   - application/yaml
+	YamlConsumer runtime.Consumer
 
 	// JSONProducer registers a producer for the following mime types:
 	//   - application/json
 	JSONProducer runtime.Producer
+	// XMLProducer registers a producer for the following mime types:
+	//   - application/xml
+	XMLProducer runtime.Producer
+	// YamlProducer registers a producer for the following mime types:
+	//   - application/yaml
+	YamlProducer runtime.Producer
 
 	// EntriesCreateLogEntryHandler sets the operation handler for the create log entry operation
 	EntriesCreateLogEntryHandler entries.CreateLogEntryHandler
@@ -185,10 +202,22 @@ func (o *RekorServerAPI) Validate() error {
 	if o.JSONConsumer == nil {
 		unregistered = append(unregistered, "JSONConsumer")
 	}
+	if o.XMLConsumer == nil {
+		unregistered = append(unregistered, "XMLConsumer")
+	}
+	if o.YamlConsumer == nil {
+		unregistered = append(unregistered, "YamlConsumer")
+	}
 
 	if o.JSONProducer == nil {
 		unregistered = append(unregistered, "JSONProducer")
 	}
+	if o.XMLProducer == nil {
+		unregistered = append(unregistered, "XMLProducer")
+	}
+	if o.YamlProducer == nil {
+		unregistered = append(unregistered, "YamlProducer")
+	}
 
 	if o.EntriesCreateLogEntryHandler == nil {
 		unregistered = append(unregistered, "entries.CreateLogEntryHandler")
@@ -242,6 +271,10 @@ func (o *RekorServerAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Co
 		switch mt {
 		case "application/json":
 			result["application/json"] = o.JSONConsumer
+		case "application/xml":
+			result["application/xml"] = o.XMLConsumer
+		case "application/yaml":
+			result["application/yaml"] = o.YamlConsumer
 		}
 
 		if c, ok := o.customConsumers[mt]; ok {
@@ -259,6 +292,10 @@ func (o *RekorServerAPI) ProducersFor(mediaTypes []string) map[string]runtime.Pr
 		switch mt {
 		case "application/json":
 			result["application/json"] = o.JSONProducer
+		case "application/xml":
+			result["application/xml"] = o.XMLProducer
+		case "application/yaml":
+			result["application/yaml"] = o.YamlProducer
 		}
 
 		if p, ok := o.customProducers[mt]; ok {
-- 
GitLab