From cb490453d2487f3a5aa95cb84110aab10df409d6 Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Fri, 10 Feb 2023 16:13:50 +1100 Subject: [PATCH] functionbuilder --- build/app/cmd/export-xlsx-server/main.go | 57 -- build/app/models/error.go | 88 --- build/app/models/post_o_k_body.go | 50 -- build/app/models/post_params_body.go | 91 ---- build/app/restapi/configure_export_xlsx.go | 170 ------ build/app/restapi/doc.go | 19 - build/app/restapi/embedded_spec.go | 398 -------------- build/app/restapi/operations/delete.go | 56 -- .../restapi/operations/delete_parameters.go | 74 --- .../restapi/operations/delete_responses.go | 36 -- .../app/restapi/operations/direktiv_delete.go | 58 -- .../app/restapi/operations/direktiv_helper.go | 279 ---------- build/app/restapi/operations/direktiv_post.go | 251 --------- .../app/restapi/operations/export_xlsx_api.go | 313 ----------- build/app/restapi/operations/post.go | 56 -- .../app/restapi/operations/post_parameters.go | 149 ----- .../app/restapi/operations/post_responses.go | 160 ------ build/app/restapi/server.go | 513 ------------------ tests/v1.0/karate-event.yaml | 46 -- tests/v1.0/karate.yaml | 22 - tests/v1.0/karate.yaml.test.feature | 41 -- tests/v1.0/tests-event.yaml | 44 -- tests/v1.0/tests.yaml | 16 - 23 files changed, 2987 deletions(-) delete mode 100644 build/app/cmd/export-xlsx-server/main.go delete mode 100644 build/app/models/error.go delete mode 100644 build/app/models/post_o_k_body.go delete mode 100644 build/app/models/post_params_body.go delete mode 100644 build/app/restapi/configure_export_xlsx.go delete mode 100644 build/app/restapi/doc.go delete mode 100644 build/app/restapi/embedded_spec.go delete mode 100644 build/app/restapi/operations/delete.go delete mode 100644 build/app/restapi/operations/delete_parameters.go delete mode 100644 build/app/restapi/operations/delete_responses.go delete mode 100644 build/app/restapi/operations/direktiv_delete.go delete mode 100644 build/app/restapi/operations/direktiv_helper.go delete mode 100644 build/app/restapi/operations/direktiv_post.go delete mode 100644 build/app/restapi/operations/export_xlsx_api.go delete mode 100644 build/app/restapi/operations/post.go delete mode 100644 build/app/restapi/operations/post_parameters.go delete mode 100644 build/app/restapi/operations/post_responses.go delete mode 100644 build/app/restapi/server.go delete mode 100644 tests/v1.0/karate-event.yaml delete mode 100644 tests/v1.0/karate.yaml delete mode 100644 tests/v1.0/karate.yaml.test.feature delete mode 100644 tests/v1.0/tests-event.yaml delete mode 100644 tests/v1.0/tests.yaml diff --git a/build/app/cmd/export-xlsx-server/main.go b/build/app/cmd/export-xlsx-server/main.go deleted file mode 100644 index 086bc63..0000000 --- a/build/app/cmd/export-xlsx-server/main.go +++ /dev/null @@ -1,57 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package main - -import ( - "log" - "os" - - "github.com/go-openapi/loads" - flags "github.com/jessevdk/go-flags" - - "app/restapi" - "app/restapi/operations" -) - -// This file was generated by the swagger tool. -// Make sure not to overwrite this file after you generated it because all your edits would be lost! - -func main() { - - swaggerSpec, err := loads.Embedded(restapi.SwaggerJSON, restapi.FlatSwaggerJSON) - if err != nil { - log.Fatalln(err) - } - - api := operations.NewExportXlsxAPI(swaggerSpec) - server := restapi.NewServer(api) - defer server.Shutdown() - - parser := flags.NewParser(server, flags.Default) - parser.ShortDescription = "export-xlsx" - parser.LongDescription = "Transform json input to xlsx spreadsheet" - server.ConfigureFlags() - for _, optsGroup := range api.CommandLineOptionsGroups { - _, err := parser.AddGroup(optsGroup.ShortDescription, optsGroup.LongDescription, optsGroup.Options) - if err != nil { - log.Fatalln(err) - } - } - - if _, err := parser.Parse(); err != nil { - code := 1 - if fe, ok := err.(*flags.Error); ok { - if fe.Type == flags.ErrHelp { - code = 0 - } - } - os.Exit(code) - } - - server.ConfigureAPI() - - if err := server.Serve(); err != nil { - log.Fatalln(err) - } - -} diff --git a/build/app/models/error.go b/build/app/models/error.go deleted file mode 100644 index 6a4074e..0000000 --- a/build/app/models/error.go +++ /dev/null @@ -1,88 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - - "github.com/go-openapi/errors" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// Error error -// -// swagger:model error -type Error struct { - - // error code - // Required: true - ErrorCode *string `json:"errorCode"` - - // error message - // Required: true - ErrorMessage *string `json:"errorMessage"` -} - -// Validate validates this error -func (m *Error) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateErrorCode(formats); err != nil { - res = append(res, err) - } - - if err := m.validateErrorMessage(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *Error) validateErrorCode(formats strfmt.Registry) error { - - if err := validate.Required("errorCode", "body", m.ErrorCode); err != nil { - return err - } - - return nil -} - -func (m *Error) validateErrorMessage(formats strfmt.Registry) error { - - if err := validate.Required("errorMessage", "body", m.ErrorMessage); err != nil { - return err - } - - return nil -} - -// ContextValidate validates this error based on context it is used -func (m *Error) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - return nil -} - -// MarshalBinary interface implementation -func (m *Error) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *Error) UnmarshalBinary(b []byte) error { - var res Error - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/build/app/models/post_o_k_body.go b/build/app/models/post_o_k_body.go deleted file mode 100644 index 6b614d5..0000000 --- a/build/app/models/post_o_k_body.go +++ /dev/null @@ -1,50 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" -) - -// PostOKBody post o k body -// -// swagger:model postOKBody -type PostOKBody struct { - - // export excel - ExportExcel string `json:"export-excel,omitempty"` -} - -// Validate validates this post o k body -func (m *PostOKBody) Validate(formats strfmt.Registry) error { - return nil -} - -// ContextValidate validates this post o k body based on context it is used -func (m *PostOKBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - return nil -} - -// MarshalBinary interface implementation -func (m *PostOKBody) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *PostOKBody) UnmarshalBinary(b []byte) error { - var res PostOKBody - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/build/app/models/post_params_body.go b/build/app/models/post_params_body.go deleted file mode 100644 index d0a989b..0000000 --- a/build/app/models/post_params_body.go +++ /dev/null @@ -1,91 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package models - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - - "github.com/go-openapi/errors" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" - "github.com/go-openapi/validate" -) - -// PostParamsBody post params body -// -// swagger:model postParamsBody -type PostParamsBody struct { - - // Name of the json input file to utilise - Infile string `json:"infile,omitempty"` - - // the filename of the output spreadsheet - // Required: true - OutFilename *string `json:"out-filename"` - - // Label for the worksheet created in the spreadsheet - // Required: true - WorksheetName *string `json:"worksheet-name"` -} - -// Validate validates this post params body -func (m *PostParamsBody) Validate(formats strfmt.Registry) error { - var res []error - - if err := m.validateOutFilename(formats); err != nil { - res = append(res, err) - } - - if err := m.validateWorksheetName(formats); err != nil { - res = append(res, err) - } - - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -func (m *PostParamsBody) validateOutFilename(formats strfmt.Registry) error { - - if err := validate.Required("out-filename", "body", m.OutFilename); err != nil { - return err - } - - return nil -} - -func (m *PostParamsBody) validateWorksheetName(formats strfmt.Registry) error { - - if err := validate.Required("worksheet-name", "body", m.WorksheetName); err != nil { - return err - } - - return nil -} - -// ContextValidate validates this post params body based on context it is used -func (m *PostParamsBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { - return nil -} - -// MarshalBinary interface implementation -func (m *PostParamsBody) MarshalBinary() ([]byte, error) { - if m == nil { - return nil, nil - } - return swag.WriteJSON(m) -} - -// UnmarshalBinary interface implementation -func (m *PostParamsBody) UnmarshalBinary(b []byte) error { - var res PostParamsBody - if err := swag.ReadJSON(b, &res); err != nil { - return err - } - *m = res - return nil -} diff --git a/build/app/restapi/configure_export_xlsx.go b/build/app/restapi/configure_export_xlsx.go deleted file mode 100644 index 0cdff8f..0000000 --- a/build/app/restapi/configure_export_xlsx.go +++ /dev/null @@ -1,170 +0,0 @@ -// This file is safe to edit. Once it exists it will not be overwritten - -package restapi - -import ( - "crypto/tls" - "encoding/json" - "fmt" - "net/http" - "reflect" - "strings" - - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/runtime/middleware" - - "app/restapi/operations" -) - -//go:generate swagger generate server --target ../../app --name ExportXlsx --spec ../../../swagger.yaml --template-dir /home/nathan/direktiv/export-xlsx/build/templates --principal interface{} - -func configureFlags(api *operations.ExportXlsxAPI) { - // api.CommandLineOptionsGroups = []swag.CommandLineOptionsGroup{ ... } -} - -func errorAsJSON(err errors.Error) []byte { - b, _ := json.Marshal(struct { - Code int32 `json:"errorCode"` - Message string `json:"errorMessage"` - }{err.Code(), err.Error()}) - return b -} - -func asHTTPCode(input int) int { - if input >= 600 { - return errors.DefaultHTTPCode - } - return input -} - -func flattenComposite(errs *errors.CompositeError) *errors.CompositeError { - var res []error - for _, er := range errs.Errors { - switch e := er.(type) { - case *errors.CompositeError: - if len(e.Errors) > 0 { - flat := flattenComposite(e) - if len(flat.Errors) > 0 { - res = append(res, flat.Errors...) - } - } - default: - if e != nil { - res = append(res, e) - } - } - } - return errors.CompositeValidationError(res...) -} - -func addErrorHeaders(rw http.ResponseWriter, code, message string) { - - rw.Header().Add("Direktiv-ErrorCode", code) - rw.Header().Add("Direktiv-ErrorMessage", message) - -} - -// modified version of the openapi error function -// https://github.com/go-openapi/errors/blob/8b5b7790aa74a2148bf29be0d24e1f455fdbc706/api.go -func serveError(rw http.ResponseWriter, r *http.Request, err error) { - - rw.Header().Set("Content-Type", "application/json") - switch e := err.(type) { - case *errors.CompositeError: - er := flattenComposite(e) - // strips composite errors to first element only - if len(er.Errors) > 0 { - serveError(rw, r, er.Errors[0]) - } else { - // guard against empty CompositeError (invalid construct) - serveError(rw, r, nil) - } - case *errors.MethodNotAllowedError: - rw.Header().Add("Allow", strings.Join(err.(*errors.MethodNotAllowedError).Allowed, ",")) - rw.WriteHeader(asHTTPCode(int(e.Code()))) - addErrorHeaders(rw, "io.direktiv.method", err.Error()) - if r == nil || r.Method != http.MethodHead { - _, _ = rw.Write(errorAsJSON(e)) - } - case errors.Error: - value := reflect.ValueOf(e) - if value.Kind() == reflect.Ptr && value.IsNil() { - rw.WriteHeader(http.StatusInternalServerError) - _, _ = rw.Write(errorAsJSON(errors.New(http.StatusInternalServerError, "Unknown error"))) - return - } - addErrorHeaders(rw, "io.direktiv.unfit", fmt.Sprintf("%s (%v)", e.Error(), e.Code())) - rw.WriteHeader(asHTTPCode(int(e.Code()))) - if r == nil || r.Method != http.MethodHead { - _, _ = rw.Write(errorAsJSON(e)) - } - case nil: - addErrorHeaders(rw, "io.direktiv.unknown", "Unknown error") - rw.WriteHeader(http.StatusInternalServerError) - _, _ = rw.Write(errorAsJSON(errors.New(http.StatusInternalServerError, "Unknown error"))) - default: - addErrorHeaders(rw, "io.direktiv.error", err.Error()) - rw.WriteHeader(http.StatusInternalServerError) - if r == nil || r.Method != http.MethodHead { - _, _ = rw.Write(errorAsJSON(errors.New(http.StatusInternalServerError, err.Error()))) - } - } - -} - -func configureAPI(api *operations.ExportXlsxAPI) http.Handler { - // configure the api here - api.ServeError = serveError - - // Set your custom logger if needed. Default one is log.Printf - // Expected interface func(string, ...interface{}) - // - // Example: - // api.Logger = log.Printf - - api.UseSwaggerUI() - // To continue using redoc as your UI, uncomment the following line - // api.UseRedoc() - - api.JSONConsumer = runtime.JSONConsumer() - - api.JSONProducer = runtime.JSONProducer() - - api.DeleteHandler = operations.DeleteHandlerFunc(func(params operations.DeleteParams) middleware.Responder { - return operations.DeleteDirektivHandle(params) - }) - api.PostHandler = operations.PostHandlerFunc(func(params operations.PostParams) middleware.Responder { - return operations.PostDirektivHandle(params) - }) - - api.PreServerShutdown = func() {} - - api.ServerShutdown = func() {} - - return setupGlobalMiddleware(api.Serve(setupMiddlewares)) -} - -// The TLS configuration before HTTPS server starts. -func configureTLS(tlsConfig *tls.Config) { - // Make all necessary changes to the TLS configuration here. -} - -// As soon as server is initialized but not run yet, this function will be called. -// If you need to modify a config, store server instance to stop it individually later, this is the place. -// This function can be called multiple times, depending on the number of serving schemes. -// scheme value will be set accordingly: "http", "https" or "unix". -func configureServer(s *http.Server, scheme, addr string) { -} - -// The middleware configuration is for the handler executors. These do not apply to the swagger.json document. -// The middleware executes after routing but before authentication, binding and validation. -func setupMiddlewares(handler http.Handler) http.Handler { - return handler -} - -// The middleware configuration happens before anything, this middleware also applies to serving the swagger.json document. -// So this is a good place to plug in a panic handling middleware, logging and metrics. -func setupGlobalMiddleware(handler http.Handler) http.Handler { - return handler -} diff --git a/build/app/restapi/doc.go b/build/app/restapi/doc.go deleted file mode 100644 index 0f47818..0000000 --- a/build/app/restapi/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -// Package restapi export-xlsx -// -// Transform json input to xlsx spreadsheet -// Schemes: -// http -// Host: localhost -// BasePath: / -// Version: 1.0 -// -// Consumes: -// - application/json -// -// Produces: -// - application/json -// -// swagger:meta -package restapi diff --git a/build/app/restapi/embedded_spec.go b/build/app/restapi/embedded_spec.go deleted file mode 100644 index bdf56ac..0000000 --- a/build/app/restapi/embedded_spec.go +++ /dev/null @@ -1,398 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package restapi - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "encoding/json" -) - -var ( - // SwaggerJSON embedded version of the swagger document used at generation time - SwaggerJSON json.RawMessage - // FlatSwaggerJSON embedded flattened version of the swagger document used at generation time - FlatSwaggerJSON json.RawMessage -) - -func init() { - SwaggerJSON = json.RawMessage([]byte(`{ - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "schemes": [ - "http" - ], - "swagger": "2.0", - "info": { - "description": "Transform json input to xlsx spreadsheet", - "title": "export-xlsx", - "version": "1.0", - "x-direktiv-meta": { - "categories": [ - "unknown" - ], - "container": "registry.coadcorp.com/export-xlsx:1.0", - "issues": "https://git.coadcorp.com/nathan/export-xlsx/issues", - "license": "[Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0)", - "long-description": "Transform json input to excel spreadsheet via json2excel command", - "maintainer": "[nathan.coad@dell.com](nathan.coad@dell.com)", - "url": "https://git.coadcorp.com/nathan/export-xls" - } - }, - "paths": { - "/": { - "post": { - "parameters": [ - { - "type": "string", - "default": "development", - "description": "direktiv action id is an UUID. \nFor development it can be set to 'development'\n", - "name": "Direktiv-ActionID", - "in": "header" - }, - { - "type": "string", - "default": "/tmp", - "description": "direktiv temp dir is the working directory for that request\nFor development it can be set to e.g. '/tmp'\n", - "name": "Direktiv-TempDir", - "in": "header" - }, - { - "name": "body", - "in": "body", - "schema": { - "type": "object", - "required": [ - "worksheet-name", - "out-filename" - ], - "properties": { - "infile": { - "description": "Name of the json input file to utilise", - "type": "string" - }, - "out-filename": { - "description": "the filename of the output spreadsheet", - "type": "string", - "default": "output.xlsx" - }, - "worksheet-name": { - "description": "Label for the worksheet created in the spreadsheet", - "type": "string", - "default": "Sheet1" - } - } - } - } - ], - "responses": { - "200": { - "description": "List of executed commands.", - "schema": { - "type": "object", - "properties": { - "export-excel": { - "type": "string" - } - }, - "additionalProperties": false - }, - "examples": { - "export-excel": "{\"export-excel\": \"JVBERi0xLjUKJdDUxdgKNSAwIG9iago8PAov==\"}" - } - }, - "default": { - "description": "generic error response", - "schema": { - "$ref": "#/definitions/error" - }, - "headers": { - "Direktiv-ErrorCode": { - "type": "string" - }, - "Direktiv-ErrorMessage": { - "type": "string" - } - } - } - }, - "x-direktiv": { - "cmds": [ - { - "action": "exec", - "exec": "/bin/json2excel -inputJson {{- if eq (deref .Infile) \"\" }} \"/tmp/input.json\" {{- else }} {{ .Infile }} {{- end }} input.json -worksheetName \"{{ .WorksheetName }}\" -outputFilename '{{ .OutFilename }}'", - "print": true, - "silent": false - }, - { - "action": "exec", - "exec": "base64 -w 0 /tmp/{{ .OutFilename }}" - } - ], - "output": "{\n \"export-excel\": {{ (index . 1).result | toJson }}\n}\n" - }, - "x-direktiv-errors": { - "io.direktiv.command.error": "Command execution failed", - "io.direktiv.output.error": "Template error for output generation of the service", - "io.direktiv.ri.error": "Can not create information object from request" - }, - "x-direktiv-examples": [ - { - "content": "- id: export-xlsx\n type: action\n action:\n function: export-xlsx\n input: \n files:\n - name: /tmp/input.json\n data: |\n jq(.input) \n worksheet-name: \"TestSpreadsheet\"\n out-filename: example.xlsx", - "title": "Basic" - } - ], - "x-direktiv-function": "functions:\n- id: export-xlsx\n image: registry.coadcorp.com/export-xlsx:1.0\n type: knative-workflow", - "x-direktiv-secrets": [ - { - "description": "This is a secret value", - "name": "export-xlsxSecret" - } - ] - }, - "delete": { - "parameters": [ - { - "type": "string", - "description": "On cancel Direktiv sends a DELETE request to\nthe action with id in the header\n", - "name": "Direktiv-ActionID", - "in": "header" - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-direktiv": { - "cancel": "echo 'cancel {{ .DirektivActionID }}'" - } - } - } - }, - "definitions": { - "direktivFile": { - "type": "object", - "x-go-type": { - "import": { - "package": "github.com/direktiv/apps/go/pkg/apps" - }, - "type": "DirektivFile" - } - }, - "error": { - "type": "object", - "required": [ - "errorCode", - "errorMessage" - ], - "properties": { - "errorCode": { - "type": "string" - }, - "errorMessage": { - "type": "string" - } - } - } - } -}`)) - FlatSwaggerJSON = json.RawMessage([]byte(`{ - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "schemes": [ - "http" - ], - "swagger": "2.0", - "info": { - "description": "Transform json input to xlsx spreadsheet", - "title": "export-xlsx", - "version": "1.0", - "x-direktiv-meta": { - "categories": [ - "unknown" - ], - "container": "registry.coadcorp.com/export-xlsx:1.0", - "issues": "https://git.coadcorp.com/nathan/export-xlsx/issues", - "license": "[Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0)", - "long-description": "Transform json input to excel spreadsheet via json2excel command", - "maintainer": "[nathan.coad@dell.com](nathan.coad@dell.com)", - "url": "https://git.coadcorp.com/nathan/export-xls" - } - }, - "paths": { - "/": { - "post": { - "parameters": [ - { - "type": "string", - "default": "development", - "description": "direktiv action id is an UUID. \nFor development it can be set to 'development'\n", - "name": "Direktiv-ActionID", - "in": "header" - }, - { - "type": "string", - "default": "/tmp", - "description": "direktiv temp dir is the working directory for that request\nFor development it can be set to e.g. '/tmp'\n", - "name": "Direktiv-TempDir", - "in": "header" - }, - { - "name": "body", - "in": "body", - "schema": { - "$ref": "#/definitions/postParamsBody" - } - } - ], - "responses": { - "200": { - "description": "List of executed commands.", - "schema": { - "$ref": "#/definitions/postOKBody" - }, - "examples": { - "export-excel": "{\"export-excel\": \"JVBERi0xLjUKJdDUxdgKNSAwIG9iago8PAov==\"}" - } - }, - "default": { - "description": "generic error response", - "schema": { - "$ref": "#/definitions/error" - }, - "headers": { - "Direktiv-ErrorCode": { - "type": "string" - }, - "Direktiv-ErrorMessage": { - "type": "string" - } - } - } - }, - "x-direktiv": { - "cmds": [ - { - "action": "exec", - "exec": "/bin/json2excel -inputJson {{- if eq (deref .Infile) \"\" }} \"/tmp/input.json\" {{- else }} {{ .Infile }} {{- end }} input.json -worksheetName \"{{ .WorksheetName }}\" -outputFilename '{{ .OutFilename }}'", - "print": true, - "silent": false - }, - { - "action": "exec", - "exec": "base64 -w 0 /tmp/{{ .OutFilename }}" - } - ], - "output": "{\n \"export-excel\": {{ (index . 1).result | toJson }}\n}\n" - }, - "x-direktiv-errors": { - "io.direktiv.command.error": "Command execution failed", - "io.direktiv.output.error": "Template error for output generation of the service", - "io.direktiv.ri.error": "Can not create information object from request" - }, - "x-direktiv-examples": [ - { - "content": "- id: export-xlsx\n type: action\n action:\n function: export-xlsx\n input: \n files:\n - name: /tmp/input.json\n data: |\n jq(.input) \n worksheet-name: \"TestSpreadsheet\"\n out-filename: example.xlsx", - "title": "Basic" - } - ], - "x-direktiv-function": "functions:\n- id: export-xlsx\n image: registry.coadcorp.com/export-xlsx:1.0\n type: knative-workflow", - "x-direktiv-secrets": [ - { - "description": "This is a secret value", - "name": "export-xlsxSecret" - } - ] - }, - "delete": { - "parameters": [ - { - "type": "string", - "description": "On cancel Direktiv sends a DELETE request to\nthe action with id in the header\n", - "name": "Direktiv-ActionID", - "in": "header" - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-direktiv": { - "cancel": "echo 'cancel {{ .DirektivActionID }}'" - } - } - } - }, - "definitions": { - "direktivFile": { - "type": "object", - "x-go-type": { - "import": { - "package": "github.com/direktiv/apps/go/pkg/apps" - }, - "type": "DirektivFile" - } - }, - "error": { - "type": "object", - "required": [ - "errorCode", - "errorMessage" - ], - "properties": { - "errorCode": { - "type": "string" - }, - "errorMessage": { - "type": "string" - } - } - }, - "postOKBody": { - "type": "object", - "properties": { - "export-excel": { - "type": "string" - } - }, - "additionalProperties": false, - "x-go-gen-location": "operations" - }, - "postParamsBody": { - "type": "object", - "required": [ - "worksheet-name", - "out-filename" - ], - "properties": { - "infile": { - "description": "Name of the json input file to utilise", - "type": "string" - }, - "out-filename": { - "description": "the filename of the output spreadsheet", - "type": "string", - "default": "output.xlsx" - }, - "worksheet-name": { - "description": "Label for the worksheet created in the spreadsheet", - "type": "string", - "default": "Sheet1" - } - }, - "x-go-gen-location": "operations" - } - } -}`)) -} diff --git a/build/app/restapi/operations/delete.go b/build/app/restapi/operations/delete.go deleted file mode 100644 index 0b0f29a..0000000 --- a/build/app/restapi/operations/delete.go +++ /dev/null @@ -1,56 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package operations - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the generate command - -import ( - "net/http" - - "github.com/go-openapi/runtime/middleware" -) - -// DeleteHandlerFunc turns a function with the right signature into a delete handler -type DeleteHandlerFunc func(DeleteParams) middleware.Responder - -// Handle executing the request and returning a response -func (fn DeleteHandlerFunc) Handle(params DeleteParams) middleware.Responder { - return fn(params) -} - -// DeleteHandler interface for that can handle valid delete params -type DeleteHandler interface { - Handle(DeleteParams) middleware.Responder -} - -// NewDelete creates a new http.Handler for the delete operation -func NewDelete(ctx *middleware.Context, handler DeleteHandler) *Delete { - return &Delete{Context: ctx, Handler: handler} -} - -/* Delete swagger:route DELETE / delete - -Delete delete API - -*/ -type Delete struct { - Context *middleware.Context - Handler DeleteHandler -} - -func (o *Delete) ServeHTTP(rw http.ResponseWriter, r *http.Request) { - route, rCtx, _ := o.Context.RouteInfo(r) - if rCtx != nil { - *r = *rCtx - } - var Params = NewDeleteParams() - if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params - o.Context.Respond(rw, r, route.Produces, route, err) - return - } - - res := o.Handler.Handle(Params) // actually handle the request - o.Context.Respond(rw, r, route.Produces, route, res) - -} diff --git a/build/app/restapi/operations/delete_parameters.go b/build/app/restapi/operations/delete_parameters.go deleted file mode 100644 index c85be82..0000000 --- a/build/app/restapi/operations/delete_parameters.go +++ /dev/null @@ -1,74 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package operations - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "net/http" - - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/strfmt" -) - -// NewDeleteParams creates a new DeleteParams object -// -// There are no default values defined in the spec. -func NewDeleteParams() DeleteParams { - - return DeleteParams{} -} - -// DeleteParams contains all the bound params for the delete operation -// typically these are obtained from a http.Request -// -// swagger:parameters Delete -type DeleteParams struct { - - // HTTP Request Object - HTTPRequest *http.Request `json:"-"` - - /*On cancel Direktiv sends a DELETE request to - the action with id in the header - - In: header - */ - DirektivActionID *string -} - -// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls. -// -// To ensure default values, the struct must have been initialized with NewDeleteParams() beforehand. -func (o *DeleteParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { - var res []error - - o.HTTPRequest = r - - if err := o.bindDirektivActionID(r.Header[http.CanonicalHeaderKey("Direktiv-ActionID")], true, route.Formats); err != nil { - res = append(res, err) - } - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -// bindDirektivActionID binds and validates parameter DirektivActionID from header. -func (o *DeleteParams) bindDirektivActionID(rawData []string, hasKey bool, formats strfmt.Registry) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - // Required: false - - if raw == "" { // empty values pass all other validations - return nil - } - o.DirektivActionID = &raw - - return nil -} diff --git a/build/app/restapi/operations/delete_responses.go b/build/app/restapi/operations/delete_responses.go deleted file mode 100644 index 578571d..0000000 --- a/build/app/restapi/operations/delete_responses.go +++ /dev/null @@ -1,36 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package operations - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "net/http" - - "github.com/go-openapi/runtime" -) - -// DeleteOKCode is the HTTP code returned for type DeleteOK -const DeleteOKCode int = 200 - -/*DeleteOK delete o k - -swagger:response deleteOK -*/ -type DeleteOK struct { -} - -// NewDeleteOK creates DeleteOK with default headers values -func NewDeleteOK() *DeleteOK { - - return &DeleteOK{} -} - -// WriteResponse to the client -func (o *DeleteOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { - - rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses - - rw.WriteHeader(200) -} diff --git a/build/app/restapi/operations/direktiv_delete.go b/build/app/restapi/operations/direktiv_delete.go deleted file mode 100644 index da50729..0000000 --- a/build/app/restapi/operations/direktiv_delete.go +++ /dev/null @@ -1,58 +0,0 @@ -package operations - -import ( - "context" - "fmt" - - "github.com/direktiv/apps/go/pkg/apps" - "github.com/go-openapi/runtime/middleware" -) - -func DeleteDirektivHandle(params DeleteParams) middleware.Responder { - - actionId := *params.DirektivActionID - // defer sm.Delete(actionId) - - if actionId == "" { - return NewDeleteOK() - } - - ri, err := apps.RequestinfoFromRequest(params.HTTPRequest) - if err != nil { - fmt.Println("can not create ri from request") - return NewDeleteOK() - } - - // cancel, ok := sm.Load(actionId) - ci, ok := sm.Load(actionId) - if !ok { - ri.Logger().Infof("can not load context for action id1", err) - return NewDeleteOK() - } - - cinfo, ok := ci.(*ctxInfo) - if !ok { - ri.Logger().Infof("can not load context for action id2") - return NewDeleteOK() - } - - // set to cancelled - cinfo.cancelled = true - - ri.Logger().Infof("cancelling action id %v", actionId) - cinfo.cf() - - cmd, err := templateString("echo 'cancel {{ .DirektivActionID }}'", params) - if err != nil { - ri.Logger().Infof("can not template cancel command: %v", err) - return NewDeleteOK() - } - - _, err = runCmd(context.Background(), cmd, []string{}, "", false, true, ri) - if err != nil { - ri.Logger().Infof("error running cancel function: %v", err) - } - - return NewDeleteOK() - -} diff --git a/build/app/restapi/operations/direktiv_helper.go b/build/app/restapi/operations/direktiv_helper.go deleted file mode 100644 index 92800ff..0000000 --- a/build/app/restapi/operations/direktiv_helper.go +++ /dev/null @@ -1,279 +0,0 @@ -package operations - -import ( - "bytes" - "context" - "crypto/tls" - "encoding/base64" - "encoding/json" - "fmt" - "html" - "html/template" - "io" - "net/http" - "net/http/cookiejar" - "net/url" - "os" - "os/exec" - "strconv" - "strings" - - "github.com/Masterminds/sprig" - "github.com/direktiv/apps/go/pkg/apps" - "github.com/mattn/go-shellwords" - "golang.org/x/net/publicsuffix" -) - -func fileExists(file string) bool { - _, err := os.Open(file) - if err != nil { - return false - } - return true -} - -func file64(path string) string { - - b, err := os.ReadFile(path) - if err != nil { - return err.Error() - } - - return base64.StdEncoding.EncodeToString(b) - -} - -func deref(dd interface{}) interface{} { - switch p := dd.(type) { - case *string: - return *p - case *int: - return *p - default: - return p - } -} - -func templateString(tmplIn string, data interface{}) (string, error) { - - tmpl, err := template.New("base").Funcs(sprig.FuncMap()).Funcs(template.FuncMap{ - "fileExists": fileExists, - "deref": deref, - "file64": file64, - }).Parse(tmplIn) - - if err != nil { - return "", err - } - - var b bytes.Buffer - err = tmpl.Execute(&b, data) - if err != nil { - return "", err - } - - v := b.String() - if v == "" { - v = "" - } - - return html.UnescapeString(v), nil - -} - -func convertTemplateToBool(template string, data interface{}, defaultValue bool) bool { - - out, err := templateString(template, data) - if err != nil { - return defaultValue - } - - ins, err := strconv.ParseBool(out) - if err != nil { - return defaultValue - } - - return ins - -} - -func runCmd(ctx context.Context, cmdString string, envs []string, - output string, silent, print bool, ri *apps.RequestInfo) (map[string]interface{}, error) { - - ir := make(map[string]interface{}) - ir[successKey] = false - - a, err := shellwords.Parse(cmdString) - if err != nil { - ir[resultKey] = err.Error() - return ir, err - } - - if len(a) == 0 { - return ir, fmt.Errorf("command '%v' parsed to empty array", cmdString) - } - - // get the binary and args - bin := a[0] - argsIn := []string{} - if len(a) > 1 { - argsIn = a[1:] - } - - logger := io.Discard - stdo := io.Discard - if !silent { - logger = ri.LogWriter() - stdo = os.Stdout - } - - var o bytes.Buffer - var oerr bytes.Buffer - - mwStdout := io.MultiWriter(stdo, &o, logger) - mwStdErr := io.MultiWriter(os.Stdout, &oerr, logger) - - cmd := exec.CommandContext(ctx, bin, argsIn...) - cmd.Stdout = mwStdout - cmd.Stderr = mwStdErr - cmd.Dir = ri.Dir() - - // change HOME - curEnvs := append(os.Environ(), fmt.Sprintf("HOME=%s", ri.Dir())) - cmd.Env = append(curEnvs, envs...) - - if print { - ri.Logger().Infof("running command %v", cmd) - } - - err = cmd.Run() - if err != nil { - ir[resultKey] = string(oerr.String()) - if oerr.String() == "" { - ir[resultKey] = err.Error() - } else { - ri.Logger().Errorf(oerr.String()) - err = fmt.Errorf(oerr.String()) - } - return ir, err - } - - // successful here - ir[successKey] = true - - // output check - b := o.Bytes() - if output != "" { - b, err = os.ReadFile(output) - if err != nil { - ir[resultKey] = err.Error() - return ir, err - } - } - - var rj interface{} - err = json.Unmarshal(b, &rj) - if err != nil { - rj = apps.ToJSON(string(b)) - } - ir[resultKey] = rj - - return ir, nil - -} - -func doHttpRequest(debug bool, method, u, user, pwd string, - headers map[string]string, insecure, errNo200 bool, - data []byte) (map[string]interface{}, error) { - - ir := make(map[string]interface{}) - ir[successKey] = false - - urlParsed, err := url.Parse(u) - if err != nil { - ir[resultKey] = err.Error() - return ir, err - } - - v, err := url.ParseQuery(urlParsed.RawQuery) - if err != nil { - ir[resultKey] = err.Error() - return ir, err - } - - urlParsed.RawQuery = v.Encode() - - req, err := http.NewRequest(strings.ToUpper(method), urlParsed.String(), bytes.NewReader(data)) - if err != nil { - ir[resultKey] = err.Error() - return ir, err - } - req.Close = true - - for k, v := range headers { - req.Header.Add(k, v) - } - - if user != "" { - req.SetBasicAuth(user, pwd) - } - - jar, err := cookiejar.New(&cookiejar.Options{ - PublicSuffixList: publicsuffix.List, - }) - cr := http.DefaultTransport.(*http.Transport).Clone() - cr.TLSClientConfig = &tls.Config{ - InsecureSkipVerify: insecure, - } - - client := &http.Client{ - Jar: jar, - Transport: cr, - } - - if debug { - fmt.Printf("method: %s, insecure: %v\n", method, insecure) - fmt.Printf("url: %s\n", req.URL.String()) - fmt.Println("Headers:") - for k, v := range headers { - fmt.Printf("%v = %v\n", k, v) - } - } - - resp, err := client.Do(req) - if err != nil { - ir[resultKey] = err.Error() - return ir, err - } - defer resp.Body.Close() - - b, err := io.ReadAll(resp.Body) - if err != nil { - ir[resultKey] = err.Error() - return ir, err - } - - if errNo200 && (resp.StatusCode < 200 || resp.StatusCode > 299) { - err = fmt.Errorf("response status is not between 200-299: %v (%v)", resp.StatusCode, resp.Status) - ir[resultKey] = err.Error() - return ir, err - } - - // from here on it is successful - ir[successKey] = true - ir[statusKey] = resp.Status - ir[codeKey] = resp.StatusCode - ir[headersKey] = resp.Header - - var rj interface{} - err = json.Unmarshal(b, &rj) - ir[resultKey] = rj - - // if the response is not json, base64 the result - if err != nil { - ir[resultKey] = base64.StdEncoding.EncodeToString(b) - } - - return ir, nil - -} diff --git a/build/app/restapi/operations/direktiv_post.go b/build/app/restapi/operations/direktiv_post.go deleted file mode 100644 index 57545f7..0000000 --- a/build/app/restapi/operations/direktiv_post.go +++ /dev/null @@ -1,251 +0,0 @@ -package operations - -import ( - "context" - "fmt" - "strings" - "sync" - - "github.com/direktiv/apps/go/pkg/apps" - "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/strfmt" - - "app/models" -) - -const ( - successKey = "success" - resultKey = "result" - - // http related - statusKey = "status" - codeKey = "code" - headersKey = "headers" -) - -var sm sync.Map - -const ( - cmdErr = "io.direktiv.command.error" - outErr = "io.direktiv.output.error" - riErr = "io.direktiv.ri.error" -) - -type accParams struct { - PostParams - Commands []interface{} - DirektivDir string -} - -type accParamsTemplate struct { - models.PostParamsBody - Commands []interface{} - DirektivDir string -} - -type ctxInfo struct { - cf context.CancelFunc - cancelled bool -} - -func PostDirektivHandle(params PostParams) middleware.Responder { - resp := &models.PostOKBody{} - - var ( - err error - ret interface{} - cont bool - ) - - ri, err := apps.RequestinfoFromRequest(params.HTTPRequest) - if err != nil { - return generateError(riErr, err) - } - - ctx, cancel := context.WithCancel(params.HTTPRequest.Context()) - - sm.Store(*params.DirektivActionID, &ctxInfo{ - cancel, - false, - }) - - defer sm.Delete(*params.DirektivActionID) - - var responses []interface{} - - var paramsCollector []interface{} - accParams := accParams{ - params, - nil, - ri.Dir(), - } - - ret, err = runCommand0(ctx, accParams, ri) - - responses = append(responses, ret) - - // if foreach returns an error there is no continue - // - // default we do not continue - cont = convertTemplateToBool("", accParams, false) - // cont = convertTemplateToBool("", accParams, true) - // - - if err != nil && !cont { - - errName := cmdErr - - // if the delete function added the cancel tag - ci, ok := sm.Load(*params.DirektivActionID) - if ok { - cinfo, ok := ci.(*ctxInfo) - if ok && cinfo.cancelled { - errName = "direktiv.actionCancelled" - err = fmt.Errorf("action got cancel request") - } - } - - return generateError(errName, err) - } - - paramsCollector = append(paramsCollector, ret) - accParams.Commands = paramsCollector - - ret, err = runCommand1(ctx, accParams, ri) - - responses = append(responses, ret) - - // if foreach returns an error there is no continue - // - // default we do not continue - cont = convertTemplateToBool("", accParams, false) - // cont = convertTemplateToBool("", accParams, true) - // - - if err != nil && !cont { - - errName := cmdErr - - // if the delete function added the cancel tag - ci, ok := sm.Load(*params.DirektivActionID) - if ok { - cinfo, ok := ci.(*ctxInfo) - if ok && cinfo.cancelled { - errName = "direktiv.actionCancelled" - err = fmt.Errorf("action got cancel request") - } - } - - return generateError(errName, err) - } - - paramsCollector = append(paramsCollector, ret) - accParams.Commands = paramsCollector - - s, err := templateString(`{ - "export-excel": {{ (index . 1).result | toJson }} -} -`, responses) - if err != nil { - return generateError(outErr, err) - } - - responseBytes := []byte(s) - - // validate - resp.UnmarshalBinary(responseBytes) - err = resp.Validate(strfmt.Default) - - if err != nil { - return generateError(outErr, err) - } - - return NewPostOK().WithPayload(resp) -} - -// exec -func runCommand0(ctx context.Context, - params accParams, ri *apps.RequestInfo) (map[string]interface{}, error) { - - ir := make(map[string]interface{}) - ir[successKey] = false - - at := accParamsTemplate{ - *params.Body, - params.Commands, - params.DirektivDir, - } - - cmd, err := templateString(`/bin/json2excel -inputJson {{- if eq (deref .Infile) "" }} "/tmp/input.json" {{- else }} {{ .Infile }} {{- end }} input.json -worksheetName "{{ .WorksheetName }}" -outputFilename '{{ .OutFilename }}'`, at) - if err != nil { - ri.Logger().Infof("error executing command: %v", err) - ir[resultKey] = err.Error() - return ir, err - } - cmd = strings.Replace(cmd, "\n", "", -1) - - silent := convertTemplateToBool("false", at, false) - print := convertTemplateToBool("true", at, true) - output := "" - - envs := []string{} - - return runCmd(ctx, cmd, envs, output, silent, print, ri) - -} - -// end commands - -// exec -func runCommand1(ctx context.Context, - params accParams, ri *apps.RequestInfo) (map[string]interface{}, error) { - - ir := make(map[string]interface{}) - ir[successKey] = false - - at := accParamsTemplate{ - *params.Body, - params.Commands, - params.DirektivDir, - } - - cmd, err := templateString(`base64 -w 0 /tmp/{{ .OutFilename }}`, at) - if err != nil { - ri.Logger().Infof("error executing command: %v", err) - ir[resultKey] = err.Error() - return ir, err - } - cmd = strings.Replace(cmd, "\n", "", -1) - - silent := convertTemplateToBool("", at, false) - print := convertTemplateToBool("", at, true) - output := "" - - envs := []string{} - - return runCmd(ctx, cmd, envs, output, silent, print, ri) - -} - -// end commands - -func generateError(code string, err error) *PostDefault { - - d := NewPostDefault(0).WithDirektivErrorCode(code). - WithDirektivErrorMessage(err.Error()) - - errString := err.Error() - - errResp := models.Error{ - ErrorCode: &code, - ErrorMessage: &errString, - } - - d.SetPayload(&errResp) - - return d -} - -func HandleShutdown() { - // nothing for generated functions -} diff --git a/build/app/restapi/operations/export_xlsx_api.go b/build/app/restapi/operations/export_xlsx_api.go deleted file mode 100644 index 1d7398a..0000000 --- a/build/app/restapi/operations/export_xlsx_api.go +++ /dev/null @@ -1,313 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package operations - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "fmt" - "net/http" - "strings" - - "github.com/go-openapi/errors" - "github.com/go-openapi/loads" - "github.com/go-openapi/runtime" - "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/runtime/security" - "github.com/go-openapi/spec" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/swag" -) - -// NewExportXlsxAPI creates a new ExportXlsx instance -func NewExportXlsxAPI(spec *loads.Document) *ExportXlsxAPI { - return &ExportXlsxAPI{ - handlers: make(map[string]map[string]http.Handler), - formats: strfmt.Default, - defaultConsumes: "application/json", - defaultProduces: "application/json", - customConsumers: make(map[string]runtime.Consumer), - customProducers: make(map[string]runtime.Producer), - PreServerShutdown: func() {}, - ServerShutdown: func() {}, - spec: spec, - useSwaggerUI: false, - ServeError: errors.ServeError, - BasicAuthenticator: security.BasicAuth, - APIKeyAuthenticator: security.APIKeyAuth, - BearerAuthenticator: security.BearerAuth, - - JSONConsumer: runtime.JSONConsumer(), - - JSONProducer: runtime.JSONProducer(), - - DeleteHandler: DeleteHandlerFunc(func(params DeleteParams) middleware.Responder { - return middleware.NotImplemented("operation Delete has not yet been implemented") - }), - PostHandler: PostHandlerFunc(func(params PostParams) middleware.Responder { - return middleware.NotImplemented("operation Post has not yet been implemented") - }), - } -} - -/*ExportXlsxAPI Transform json input to xlsx spreadsheet */ -type ExportXlsxAPI struct { - spec *loads.Document - context *middleware.Context - handlers map[string]map[string]http.Handler - formats strfmt.Registry - customConsumers map[string]runtime.Consumer - customProducers map[string]runtime.Producer - defaultConsumes string - defaultProduces string - Middleware func(middleware.Builder) http.Handler - useSwaggerUI bool - - // BasicAuthenticator generates a runtime.Authenticator from the supplied basic auth function. - // It has a default implementation in the security package, however you can replace it for your particular usage. - BasicAuthenticator func(security.UserPassAuthentication) runtime.Authenticator - - // APIKeyAuthenticator generates a runtime.Authenticator from the supplied token auth function. - // It has a default implementation in the security package, however you can replace it for your particular usage. - APIKeyAuthenticator func(string, string, security.TokenAuthentication) runtime.Authenticator - - // BearerAuthenticator generates a runtime.Authenticator from the supplied bearer token auth function. - // It has a default implementation in the security package, however you can replace it for your particular usage. - BearerAuthenticator func(string, security.ScopedTokenAuthentication) runtime.Authenticator - - // JSONConsumer registers a consumer for the following mime types: - // - application/json - JSONConsumer runtime.Consumer - - // JSONProducer registers a producer for the following mime types: - // - application/json - JSONProducer runtime.Producer - - // DeleteHandler sets the operation handler for the delete operation - DeleteHandler DeleteHandler - // PostHandler sets the operation handler for the post operation - PostHandler PostHandler - - // ServeError is called when an error is received, there is a default handler - // but you can set your own with this - ServeError func(http.ResponseWriter, *http.Request, error) - - // PreServerShutdown is called before the HTTP(S) server is shutdown - // This allows for custom functions to get executed before the HTTP(S) server stops accepting traffic - PreServerShutdown func() - - // ServerShutdown is called when the HTTP(S) server is shut down and done - // handling all active connections and does not accept connections any more - ServerShutdown func() - - // Custom command line argument groups with their descriptions - CommandLineOptionsGroups []swag.CommandLineOptionsGroup - - // User defined logger function. - Logger func(string, ...interface{}) -} - -// UseRedoc for documentation at /docs -func (o *ExportXlsxAPI) UseRedoc() { - o.useSwaggerUI = false -} - -// UseSwaggerUI for documentation at /docs -func (o *ExportXlsxAPI) UseSwaggerUI() { - o.useSwaggerUI = true -} - -// SetDefaultProduces sets the default produces media type -func (o *ExportXlsxAPI) SetDefaultProduces(mediaType string) { - o.defaultProduces = mediaType -} - -// SetDefaultConsumes returns the default consumes media type -func (o *ExportXlsxAPI) SetDefaultConsumes(mediaType string) { - o.defaultConsumes = mediaType -} - -// SetSpec sets a spec that will be served for the clients. -func (o *ExportXlsxAPI) SetSpec(spec *loads.Document) { - o.spec = spec -} - -// DefaultProduces returns the default produces media type -func (o *ExportXlsxAPI) DefaultProduces() string { - return o.defaultProduces -} - -// DefaultConsumes returns the default consumes media type -func (o *ExportXlsxAPI) DefaultConsumes() string { - return o.defaultConsumes -} - -// Formats returns the registered string formats -func (o *ExportXlsxAPI) Formats() strfmt.Registry { - return o.formats -} - -// RegisterFormat registers a custom format validator -func (o *ExportXlsxAPI) RegisterFormat(name string, format strfmt.Format, validator strfmt.Validator) { - o.formats.Add(name, format, validator) -} - -// Validate validates the registrations in the ExportXlsxAPI -func (o *ExportXlsxAPI) Validate() error { - var unregistered []string - - if o.JSONConsumer == nil { - unregistered = append(unregistered, "JSONConsumer") - } - - if o.JSONProducer == nil { - unregistered = append(unregistered, "JSONProducer") - } - - if o.DeleteHandler == nil { - unregistered = append(unregistered, "DeleteHandler") - } - if o.PostHandler == nil { - unregistered = append(unregistered, "PostHandler") - } - - if len(unregistered) > 0 { - return fmt.Errorf("missing registration: %s", strings.Join(unregistered, ", ")) - } - - return nil -} - -// ServeErrorFor gets a error handler for a given operation id -func (o *ExportXlsxAPI) ServeErrorFor(operationID string) func(http.ResponseWriter, *http.Request, error) { - return o.ServeError -} - -// AuthenticatorsFor gets the authenticators for the specified security schemes -func (o *ExportXlsxAPI) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator { - return nil -} - -// Authorizer returns the registered authorizer -func (o *ExportXlsxAPI) Authorizer() runtime.Authorizer { - return nil -} - -// ConsumersFor gets the consumers for the specified media types. -// MIME type parameters are ignored here. -func (o *ExportXlsxAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer { - result := make(map[string]runtime.Consumer, len(mediaTypes)) - for _, mt := range mediaTypes { - switch mt { - case "application/json": - result["application/json"] = o.JSONConsumer - } - - if c, ok := o.customConsumers[mt]; ok { - result[mt] = c - } - } - return result -} - -// ProducersFor gets the producers for the specified media types. -// MIME type parameters are ignored here. -func (o *ExportXlsxAPI) ProducersFor(mediaTypes []string) map[string]runtime.Producer { - result := make(map[string]runtime.Producer, len(mediaTypes)) - for _, mt := range mediaTypes { - switch mt { - case "application/json": - result["application/json"] = o.JSONProducer - } - - if p, ok := o.customProducers[mt]; ok { - result[mt] = p - } - } - return result -} - -// HandlerFor gets a http.Handler for the provided operation method and path -func (o *ExportXlsxAPI) HandlerFor(method, path string) (http.Handler, bool) { - if o.handlers == nil { - return nil, false - } - um := strings.ToUpper(method) - if _, ok := o.handlers[um]; !ok { - return nil, false - } - if path == "/" { - path = "" - } - h, ok := o.handlers[um][path] - return h, ok -} - -// Context returns the middleware context for the export xlsx API -func (o *ExportXlsxAPI) Context() *middleware.Context { - if o.context == nil { - o.context = middleware.NewRoutableContext(o.spec, o, nil) - } - - return o.context -} - -func (o *ExportXlsxAPI) initHandlerCache() { - o.Context() // don't care about the result, just that the initialization happened - if o.handlers == nil { - o.handlers = make(map[string]map[string]http.Handler) - } - - if o.handlers["DELETE"] == nil { - o.handlers["DELETE"] = make(map[string]http.Handler) - } - o.handlers["DELETE"][""] = NewDelete(o.context, o.DeleteHandler) - if o.handlers["POST"] == nil { - o.handlers["POST"] = make(map[string]http.Handler) - } - o.handlers["POST"][""] = NewPost(o.context, o.PostHandler) -} - -// Serve creates a http handler to serve the API over HTTP -// can be used directly in http.ListenAndServe(":8000", api.Serve(nil)) -func (o *ExportXlsxAPI) Serve(builder middleware.Builder) http.Handler { - o.Init() - - if o.Middleware != nil { - return o.Middleware(builder) - } - if o.useSwaggerUI { - return o.context.APIHandlerSwaggerUI(builder) - } - return o.context.APIHandler(builder) -} - -// Init allows you to just initialize the handler cache, you can then recompose the middleware as you see fit -func (o *ExportXlsxAPI) Init() { - if len(o.handlers) == 0 { - o.initHandlerCache() - } -} - -// RegisterConsumer allows you to add (or override) a consumer for a media type. -func (o *ExportXlsxAPI) RegisterConsumer(mediaType string, consumer runtime.Consumer) { - o.customConsumers[mediaType] = consumer -} - -// RegisterProducer allows you to add (or override) a producer for a media type. -func (o *ExportXlsxAPI) RegisterProducer(mediaType string, producer runtime.Producer) { - o.customProducers[mediaType] = producer -} - -// AddMiddlewareFor adds a http middleware to existing handler -func (o *ExportXlsxAPI) AddMiddlewareFor(method, path string, builder middleware.Builder) { - um := strings.ToUpper(method) - if path == "/" { - path = "" - } - o.Init() - if h, ok := o.handlers[um][path]; ok { - o.handlers[method][path] = builder(h) - } -} diff --git a/build/app/restapi/operations/post.go b/build/app/restapi/operations/post.go deleted file mode 100644 index fbddb96..0000000 --- a/build/app/restapi/operations/post.go +++ /dev/null @@ -1,56 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package operations - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the generate command - -import ( - "net/http" - - "github.com/go-openapi/runtime/middleware" -) - -// PostHandlerFunc turns a function with the right signature into a post handler -type PostHandlerFunc func(PostParams) middleware.Responder - -// Handle executing the request and returning a response -func (fn PostHandlerFunc) Handle(params PostParams) middleware.Responder { - return fn(params) -} - -// PostHandler interface for that can handle valid post params -type PostHandler interface { - Handle(PostParams) middleware.Responder -} - -// NewPost creates a new http.Handler for the post operation -func NewPost(ctx *middleware.Context, handler PostHandler) *Post { - return &Post{Context: ctx, Handler: handler} -} - -/* Post swagger:route POST / post - -Post post API - -*/ -type Post struct { - Context *middleware.Context - Handler PostHandler -} - -func (o *Post) ServeHTTP(rw http.ResponseWriter, r *http.Request) { - route, rCtx, _ := o.Context.RouteInfo(r) - if rCtx != nil { - *r = *rCtx - } - var Params = NewPostParams() - if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params - o.Context.Respond(rw, r, route.Produces, route, err) - return - } - - res := o.Handler.Handle(Params) // actually handle the request - o.Context.Respond(rw, r, route.Produces, route, res) - -} diff --git a/build/app/restapi/operations/post_parameters.go b/build/app/restapi/operations/post_parameters.go deleted file mode 100644 index 9e7110c..0000000 --- a/build/app/restapi/operations/post_parameters.go +++ /dev/null @@ -1,149 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package operations - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "context" - "net/http" - - "github.com/go-openapi/errors" - "github.com/go-openapi/runtime" - "github.com/go-openapi/runtime/middleware" - "github.com/go-openapi/strfmt" - "github.com/go-openapi/validate" - - "app/models" -) - -// NewPostParams creates a new PostParams object -// with the default values initialized. -func NewPostParams() PostParams { - - var ( - // initialize parameters with default values - - direktivActionIDDefault = string("development") - direktivTempDirDefault = string("/tmp") - ) - - return PostParams{ - DirektivActionID: &direktivActionIDDefault, - - DirektivTempDir: &direktivTempDirDefault, - } -} - -// PostParams contains all the bound params for the post operation -// typically these are obtained from a http.Request -// -// swagger:parameters Post -type PostParams struct { - - // HTTP Request Object - HTTPRequest *http.Request `json:"-"` - - /*direktiv action id is an UUID. - For development it can be set to 'development' - - In: header - Default: "development" - */ - DirektivActionID *string - /*direktiv temp dir is the working directory for that request - For development it can be set to e.g. '/tmp' - - In: header - Default: "/tmp" - */ - DirektivTempDir *string - /* - In: body - */ - Body *models.PostParamsBody -} - -// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface -// for simple values it will use straight method calls. -// -// To ensure default values, the struct must have been initialized with NewPostParams() beforehand. -func (o *PostParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { - var res []error - - o.HTTPRequest = r - - if err := o.bindDirektivActionID(r.Header[http.CanonicalHeaderKey("Direktiv-ActionID")], true, route.Formats); err != nil { - res = append(res, err) - } - - if err := o.bindDirektivTempDir(r.Header[http.CanonicalHeaderKey("Direktiv-TempDir")], true, route.Formats); err != nil { - res = append(res, err) - } - - if runtime.HasBody(r) { - defer r.Body.Close() - var body models.PostParamsBody - if err := route.Consumer.Consume(r.Body, &body); err != nil { - res = append(res, errors.NewParseError("body", "body", "", err)) - } else { - // validate body object - if err := body.Validate(route.Formats); err != nil { - res = append(res, err) - } - - // direktiv: add request to context so we can use in validate - baseCtx := context.WithValue(r.Context(), "req", r) - - ctx := validate.WithOperationRequest(baseCtx) - if err := body.ContextValidate(ctx, route.Formats); err != nil { - res = append(res, err) - } - - if len(res) == 0 { - o.Body = &body - } - } - } - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -// bindDirektivActionID binds and validates parameter DirektivActionID from header. -func (o *PostParams) bindDirektivActionID(rawData []string, hasKey bool, formats strfmt.Registry) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - // Required: false - - if raw == "" { // empty values pass all other validations - // Default values have been previously initialized by NewPostParams() - return nil - } - o.DirektivActionID = &raw - - return nil -} - -// bindDirektivTempDir binds and validates parameter DirektivTempDir from header. -func (o *PostParams) bindDirektivTempDir(rawData []string, hasKey bool, formats strfmt.Registry) error { - var raw string - if len(rawData) > 0 { - raw = rawData[len(rawData)-1] - } - - // Required: false - - if raw == "" { // empty values pass all other validations - // Default values have been previously initialized by NewPostParams() - return nil - } - o.DirektivTempDir = &raw - - return nil -} diff --git a/build/app/restapi/operations/post_responses.go b/build/app/restapi/operations/post_responses.go deleted file mode 100644 index e56af05..0000000 --- a/build/app/restapi/operations/post_responses.go +++ /dev/null @@ -1,160 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package operations - -// This file was generated by the swagger tool. -// Editing this file might prove futile when you re-run the swagger generate command - -import ( - "net/http" - - "github.com/go-openapi/runtime" - - "app/models" -) - -// PostOKCode is the HTTP code returned for type PostOK -const PostOKCode int = 200 - -/*PostOK List of executed commands. - -swagger:response postOK -*/ -type PostOK struct { - - /* - In: Body - */ - Payload *models.PostOKBody `json:"body,omitempty"` -} - -// NewPostOK creates PostOK with default headers values -func NewPostOK() *PostOK { - - return &PostOK{} -} - -// WithPayload adds the payload to the post o k response -func (o *PostOK) WithPayload(payload *models.PostOKBody) *PostOK { - o.Payload = payload - return o -} - -// SetPayload sets the payload to the post o k response -func (o *PostOK) SetPayload(payload *models.PostOKBody) { - o.Payload = payload -} - -// WriteResponse to the client -func (o *PostOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { - - rw.WriteHeader(200) - if o.Payload != nil { - payload := o.Payload - if err := producer.Produce(rw, payload); err != nil { - panic(err) // let the recovery middleware deal with this - } - } -} - -/*PostDefault generic error response - -swagger:response postDefault -*/ -type PostDefault struct { - _statusCode int - /* - - */ - DirektivErrorCode string `json:"Direktiv-ErrorCode"` - /* - - */ - DirektivErrorMessage string `json:"Direktiv-ErrorMessage"` - - /* - In: Body - */ - Payload *models.Error `json:"body,omitempty"` -} - -// NewPostDefault creates PostDefault with default headers values -func NewPostDefault(code int) *PostDefault { - if code <= 0 { - code = 500 - } - - return &PostDefault{ - _statusCode: code, - } -} - -// WithStatusCode adds the status to the post default response -func (o *PostDefault) WithStatusCode(code int) *PostDefault { - o._statusCode = code - return o -} - -// SetStatusCode sets the status to the post default response -func (o *PostDefault) SetStatusCode(code int) { - o._statusCode = code -} - -// WithDirektivErrorCode adds the direktivErrorCode to the post default response -func (o *PostDefault) WithDirektivErrorCode(direktivErrorCode string) *PostDefault { - o.DirektivErrorCode = direktivErrorCode - return o -} - -// SetDirektivErrorCode sets the direktivErrorCode to the post default response -func (o *PostDefault) SetDirektivErrorCode(direktivErrorCode string) { - o.DirektivErrorCode = direktivErrorCode -} - -// WithDirektivErrorMessage adds the direktivErrorMessage to the post default response -func (o *PostDefault) WithDirektivErrorMessage(direktivErrorMessage string) *PostDefault { - o.DirektivErrorMessage = direktivErrorMessage - return o -} - -// SetDirektivErrorMessage sets the direktivErrorMessage to the post default response -func (o *PostDefault) SetDirektivErrorMessage(direktivErrorMessage string) { - o.DirektivErrorMessage = direktivErrorMessage -} - -// WithPayload adds the payload to the post default response -func (o *PostDefault) WithPayload(payload *models.Error) *PostDefault { - o.Payload = payload - return o -} - -// SetPayload sets the payload to the post default response -func (o *PostDefault) SetPayload(payload *models.Error) { - o.Payload = payload -} - -// WriteResponse to the client -func (o *PostDefault) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { - - // response header Direktiv-ErrorCode - - direktivErrorCode := o.DirektivErrorCode - if direktivErrorCode != "" { - rw.Header().Set("Direktiv-ErrorCode", direktivErrorCode) - } - - // response header Direktiv-ErrorMessage - - direktivErrorMessage := o.DirektivErrorMessage - if direktivErrorMessage != "" { - rw.Header().Set("Direktiv-ErrorMessage", direktivErrorMessage) - } - - rw.WriteHeader(o._statusCode) - if o.Payload != nil { - payload := o.Payload - if err := producer.Produce(rw, payload); err != nil { - panic(err) // let the recovery middleware deal with this - } - } -} diff --git a/build/app/restapi/server.go b/build/app/restapi/server.go deleted file mode 100644 index 6ea3590..0000000 --- a/build/app/restapi/server.go +++ /dev/null @@ -1,513 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package restapi - -import ( - "context" - "crypto/tls" - "crypto/x509" - "errors" - "fmt" - "io/ioutil" - "log" - "net" - "net/http" - "os" - "os/signal" - "strconv" - "sync" - "sync/atomic" - "syscall" - "time" - - "github.com/go-openapi/runtime/flagext" - "github.com/go-openapi/swag" - flags "github.com/jessevdk/go-flags" - "golang.org/x/net/netutil" - - "app/restapi/operations" -) - -const ( - schemeHTTP = "http" - schemeHTTPS = "https" - schemeUnix = "unix" -) - -var defaultSchemes []string - -func init() { - defaultSchemes = []string{ - schemeHTTP, - } -} - -// NewServer creates a new api export xlsx server but does not configure it -func NewServer(api *operations.ExportXlsxAPI) *Server { - s := new(Server) - - s.shutdown = make(chan struct{}) - s.api = api - s.interrupt = make(chan os.Signal, 1) - return s -} - -// ConfigureAPI configures the API and handlers. -func (s *Server) ConfigureAPI() { - if s.api != nil { - s.handler = configureAPI(s.api) - } - - s.ReadTimeout = 86400 * time.Second - s.WriteTimeout = 86400 * time.Second -} - -// ConfigureFlags configures the additional flags defined by the handlers. Needs to be called before the parser.Parse -func (s *Server) ConfigureFlags() { - if s.api != nil { - configureFlags(s.api) - } -} - -// Server for the export xlsx API -type Server struct { - EnabledListeners []string `long:"scheme" description:"the listeners to enable, this can be repeated and defaults to the schemes in the swagger spec"` - CleanupTimeout time.Duration `long:"cleanup-timeout" description:"grace period for which to wait before killing idle connections" default:"10s"` - GracefulTimeout time.Duration `long:"graceful-timeout" description:"grace period for which to wait before shutting down the server" default:"15s"` - MaxHeaderSize flagext.ByteSize `long:"max-header-size" description:"controls the maximum number of bytes the server will read parsing the request header's keys and values, including the request line. It does not limit the size of the request body." default:"1MiB"` - - SocketPath flags.Filename `long:"socket-path" description:"the unix socket to listen on" default:"/var/run/export-xlsx.sock"` - domainSocketL net.Listener - - Host string `long:"host" description:"the IP to listen on" default:"localhost" env:"HOST"` - Port int `long:"port" description:"the port to listen on for insecure connections, defaults to a random value" env:"PORT"` - ListenLimit int `long:"listen-limit" description:"limit the number of outstanding requests"` - KeepAlive time.Duration `long:"keep-alive" description:"sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)" default:"3m"` - ReadTimeout time.Duration `long:"read-timeout" description:"maximum duration before timing out read of the request" default:"30s"` - WriteTimeout time.Duration `long:"write-timeout" description:"maximum duration before timing out write of the response" default:"60s"` - httpServerL net.Listener - - TLSHost string `long:"tls-host" description:"the IP to listen on for tls, when not specified it's the same as --host" env:"TLS_HOST"` - TLSPort int `long:"tls-port" description:"the port to listen on for secure connections, defaults to a random value" env:"TLS_PORT"` - TLSCertificate flags.Filename `long:"tls-certificate" description:"the certificate to use for secure connections" env:"TLS_CERTIFICATE"` - TLSCertificateKey flags.Filename `long:"tls-key" description:"the private key to use for secure connections" env:"TLS_PRIVATE_KEY"` - TLSCACertificate flags.Filename `long:"tls-ca" description:"the certificate authority file to be used with mutual tls auth" env:"TLS_CA_CERTIFICATE"` - TLSListenLimit int `long:"tls-listen-limit" description:"limit the number of outstanding requests"` - TLSKeepAlive time.Duration `long:"tls-keep-alive" description:"sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)"` - TLSReadTimeout time.Duration `long:"tls-read-timeout" description:"maximum duration before timing out read of the request"` - TLSWriteTimeout time.Duration `long:"tls-write-timeout" description:"maximum duration before timing out write of the response"` - httpsServerL net.Listener - - api *operations.ExportXlsxAPI - handler http.Handler - hasListeners bool - shutdown chan struct{} - shuttingDown int32 - interrupted bool - interrupt chan os.Signal -} - -// Logf logs message either via defined user logger or via system one if no user logger is defined. -func (s *Server) Logf(f string, args ...interface{}) { - if s.api != nil && s.api.Logger != nil { - s.api.Logger(f, args...) - } else { - log.Printf(f, args...) - } -} - -// Fatalf logs message either via defined user logger or via system one if no user logger is defined. -// Exits with non-zero status after printing -func (s *Server) Fatalf(f string, args ...interface{}) { - if s.api != nil && s.api.Logger != nil { - s.api.Logger(f, args...) - os.Exit(1) - } else { - log.Fatalf(f, args...) - } -} - -// SetAPI configures the server with the specified API. Needs to be called before Serve -func (s *Server) SetAPI(api *operations.ExportXlsxAPI) { - if api == nil { - s.api = nil - s.handler = nil - return - } - - s.api = api - s.handler = configureAPI(api) -} - -func (s *Server) hasScheme(scheme string) bool { - schemes := s.EnabledListeners - if len(schemes) == 0 { - schemes = defaultSchemes - } - - for _, v := range schemes { - if v == scheme { - return true - } - } - return false -} - -// Serve the api -func (s *Server) Serve() (err error) { - - if !s.hasListeners { - if err = s.Listen(); err != nil { - return err - } - } - - // set default handler, if none is set - if s.handler == nil { - if s.api == nil { - return errors.New("can't create the default handler, as no api is set") - } - - s.SetHandler(s.api.Serve(nil)) - } - - wg := new(sync.WaitGroup) - once := new(sync.Once) - signalNotify(s.interrupt) - go handleInterrupt(once, s) - - servers := []*http.Server{} - - if s.hasScheme(schemeUnix) { - domainSocket := new(http.Server) - domainSocket.MaxHeaderBytes = int(s.MaxHeaderSize) - domainSocket.Handler = s.handler - if int64(s.CleanupTimeout) > 0 { - domainSocket.IdleTimeout = s.CleanupTimeout - } - - configureServer(domainSocket, "unix", string(s.SocketPath)) - - servers = append(servers, domainSocket) - wg.Add(1) - s.Logf("Serving export xlsx at unix://%s", s.SocketPath) - go func(l net.Listener) { - defer wg.Done() - if err := domainSocket.Serve(l); err != nil && err != http.ErrServerClosed { - s.Fatalf("%v", err) - } - s.Logf("Stopped serving export xlsx at unix://%s", s.SocketPath) - }(s.domainSocketL) - } - - if s.hasScheme(schemeHTTP) { - httpServer := new(http.Server) - httpServer.MaxHeaderBytes = int(s.MaxHeaderSize) - httpServer.ReadTimeout = s.ReadTimeout - httpServer.WriteTimeout = s.WriteTimeout - httpServer.SetKeepAlivesEnabled(int64(s.KeepAlive) > 0) - if s.ListenLimit > 0 { - s.httpServerL = netutil.LimitListener(s.httpServerL, s.ListenLimit) - } - - if int64(s.CleanupTimeout) > 0 { - httpServer.IdleTimeout = s.CleanupTimeout - } - - httpServer.Handler = s.handler - - configureServer(httpServer, "http", s.httpServerL.Addr().String()) - - servers = append(servers, httpServer) - wg.Add(1) - s.Logf("Serving export xlsx at http://%s", s.httpServerL.Addr()) - go func(l net.Listener) { - defer wg.Done() - if err := httpServer.Serve(l); err != nil && err != http.ErrServerClosed { - s.Fatalf("%v", err) - } - s.Logf("Stopped serving export xlsx at http://%s", l.Addr()) - }(s.httpServerL) - } - - if s.hasScheme(schemeHTTPS) { - httpsServer := new(http.Server) - httpsServer.MaxHeaderBytes = int(s.MaxHeaderSize) - httpsServer.ReadTimeout = s.TLSReadTimeout - httpsServer.WriteTimeout = s.TLSWriteTimeout - httpsServer.SetKeepAlivesEnabled(int64(s.TLSKeepAlive) > 0) - if s.TLSListenLimit > 0 { - s.httpsServerL = netutil.LimitListener(s.httpsServerL, s.TLSListenLimit) - } - if int64(s.CleanupTimeout) > 0 { - httpsServer.IdleTimeout = s.CleanupTimeout - } - httpsServer.Handler = s.handler - - // Inspired by https://blog.bracebin.com/achieving-perfect-ssl-labs-score-with-go - httpsServer.TLSConfig = &tls.Config{ - // Causes servers to use Go's default ciphersuite preferences, - // which are tuned to avoid attacks. Does nothing on clients. - PreferServerCipherSuites: true, - // Only use curves which have assembly implementations - // https://github.com/golang/go/tree/master/src/crypto/elliptic - CurvePreferences: []tls.CurveID{tls.CurveP256}, - // Use modern tls mode https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility - NextProtos: []string{"h2", "http/1.1"}, - // https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet#Rule_-_Only_Support_Strong_Protocols - MinVersion: tls.VersionTLS12, - // These ciphersuites support Forward Secrecy: https://en.wikipedia.org/wiki/Forward_secrecy - CipherSuites: []uint16{ - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, - tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, - }, - } - - // build standard config from server options - if s.TLSCertificate != "" && s.TLSCertificateKey != "" { - httpsServer.TLSConfig.Certificates = make([]tls.Certificate, 1) - httpsServer.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(string(s.TLSCertificate), string(s.TLSCertificateKey)) - if err != nil { - return err - } - } - - if s.TLSCACertificate != "" { - // include specified CA certificate - caCert, caCertErr := ioutil.ReadFile(string(s.TLSCACertificate)) - if caCertErr != nil { - return caCertErr - } - caCertPool := x509.NewCertPool() - ok := caCertPool.AppendCertsFromPEM(caCert) - if !ok { - return fmt.Errorf("cannot parse CA certificate") - } - httpsServer.TLSConfig.ClientCAs = caCertPool - httpsServer.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert - } - - // call custom TLS configurator - configureTLS(httpsServer.TLSConfig) - - if len(httpsServer.TLSConfig.Certificates) == 0 && httpsServer.TLSConfig.GetCertificate == nil { - // after standard and custom config are passed, this ends up with no certificate - if s.TLSCertificate == "" { - if s.TLSCertificateKey == "" { - s.Fatalf("the required flags `--tls-certificate` and `--tls-key` were not specified") - } - s.Fatalf("the required flag `--tls-certificate` was not specified") - } - if s.TLSCertificateKey == "" { - s.Fatalf("the required flag `--tls-key` was not specified") - } - // this happens with a wrong custom TLS configurator - s.Fatalf("no certificate was configured for TLS") - } - - configureServer(httpsServer, "https", s.httpsServerL.Addr().String()) - - servers = append(servers, httpsServer) - wg.Add(1) - s.Logf("Serving export xlsx at https://%s", s.httpsServerL.Addr()) - go func(l net.Listener) { - defer wg.Done() - if err := httpsServer.Serve(l); err != nil && err != http.ErrServerClosed { - s.Fatalf("%v", err) - } - s.Logf("Stopped serving export xlsx at https://%s", l.Addr()) - }(tls.NewListener(s.httpsServerL, httpsServer.TLSConfig)) - } - - wg.Add(1) - go s.handleShutdown(wg, &servers) - - wg.Wait() - return nil -} - -// Listen creates the listeners for the server -func (s *Server) Listen() error { - if s.hasListeners { // already done this - return nil - } - - if s.hasScheme(schemeHTTPS) { - // Use http host if https host wasn't defined - if s.TLSHost == "" { - s.TLSHost = s.Host - } - // Use http listen limit if https listen limit wasn't defined - if s.TLSListenLimit == 0 { - s.TLSListenLimit = s.ListenLimit - } - // Use http tcp keep alive if https tcp keep alive wasn't defined - if int64(s.TLSKeepAlive) == 0 { - s.TLSKeepAlive = s.KeepAlive - } - // Use http read timeout if https read timeout wasn't defined - if int64(s.TLSReadTimeout) == 0 { - s.TLSReadTimeout = s.ReadTimeout - } - // Use http write timeout if https write timeout wasn't defined - if int64(s.TLSWriteTimeout) == 0 { - s.TLSWriteTimeout = s.WriteTimeout - } - } - - if s.hasScheme(schemeUnix) { - domSockListener, err := net.Listen("unix", string(s.SocketPath)) - if err != nil { - return err - } - s.domainSocketL = domSockListener - } - - if s.hasScheme(schemeHTTP) { - listener, err := net.Listen("tcp", net.JoinHostPort(s.Host, strconv.Itoa(s.Port))) - if err != nil { - return err - } - - h, p, err := swag.SplitHostPort(listener.Addr().String()) - if err != nil { - return err - } - s.Host = h - s.Port = p - s.httpServerL = listener - } - - if s.hasScheme(schemeHTTPS) { - tlsListener, err := net.Listen("tcp", net.JoinHostPort(s.TLSHost, strconv.Itoa(s.TLSPort))) - if err != nil { - return err - } - - sh, sp, err := swag.SplitHostPort(tlsListener.Addr().String()) - if err != nil { - return err - } - s.TLSHost = sh - s.TLSPort = sp - s.httpsServerL = tlsListener - } - - s.hasListeners = true - return nil -} - -// Shutdown server and clean up resources -func (s *Server) Shutdown() error { - if atomic.CompareAndSwapInt32(&s.shuttingDown, 0, 1) { - close(s.shutdown) - } - return nil -} - -func (s *Server) handleShutdown(wg *sync.WaitGroup, serversPtr *[]*http.Server) { - // wg.Done must occur last, after s.api.ServerShutdown() - // (to preserve old behaviour) - defer wg.Done() - - <-s.shutdown - - servers := *serversPtr - - ctx, cancel := context.WithTimeout(context.TODO(), s.GracefulTimeout) - defer cancel() - - // first execute the pre-shutdown hook - s.api.PreServerShutdown() - - shutdownChan := make(chan bool) - for i := range servers { - server := servers[i] - go func() { - var success bool - defer func() { - shutdownChan <- success - }() - if err := server.Shutdown(ctx); err != nil { - // Error from closing listeners, or context timeout: - s.Logf("HTTP server Shutdown: %v", err) - } else { - success = true - } - }() - } - - // Wait until all listeners have successfully shut down before calling ServerShutdown - success := true - for range servers { - success = success && <-shutdownChan - } - if success { - s.api.ServerShutdown() - } -} - -// GetHandler returns a handler useful for testing -func (s *Server) GetHandler() http.Handler { - return s.handler -} - -// SetHandler allows for setting a http handler on this server -func (s *Server) SetHandler(handler http.Handler) { - s.handler = handler -} - -// UnixListener returns the domain socket listener -func (s *Server) UnixListener() (net.Listener, error) { - if !s.hasListeners { - if err := s.Listen(); err != nil { - return nil, err - } - } - return s.domainSocketL, nil -} - -// HTTPListener returns the http listener -func (s *Server) HTTPListener() (net.Listener, error) { - if !s.hasListeners { - if err := s.Listen(); err != nil { - return nil, err - } - } - return s.httpServerL, nil -} - -// TLSListener returns the https listener -func (s *Server) TLSListener() (net.Listener, error) { - if !s.hasListeners { - if err := s.Listen(); err != nil { - return nil, err - } - } - return s.httpsServerL, nil -} - -func handleInterrupt(once *sync.Once, s *Server) { - once.Do(func() { - for range s.interrupt { - if s.interrupted { - s.Logf("Server already shutting down") - continue - } - s.interrupted = true - s.Logf("Shutting down... ") - operations.HandleShutdown() - if err := s.Shutdown(); err != nil { - s.Logf("HTTP server Shutdown: %v", err) - } - } - }) -} - -func signalNotify(interrupt chan<- os.Signal) { - signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM) -} diff --git a/tests/v1.0/karate-event.yaml b/tests/v1.0/karate-event.yaml deleted file mode 100644 index fd89d0b..0000000 --- a/tests/v1.0/karate-event.yaml +++ /dev/null @@ -1,46 +0,0 @@ -url: "" -functions: -- type: subflow - id: call-karate - workflow: karate -start: - type: event - state: call-subflow - event: - type: io.direktiv.function.test - context: - function: 'export-xlsx' - version: '1.0' -states: -- id: call-subflow - type: action - action: - function: call-karate - input: - host: jq(."io.direktiv.function.test".host) - catch: - - error: "*" - transition: report-failure - transition: report-success -- id: report-success - type: generateEvent - event: - type: io.direktiv.function.test.result.karate - source: karate - data: '' - context: - result: success - function: jq(."io.direktiv.function.test".function) - version: jq(."io.direktiv.function.test".version) -- id: report-failure - type: generateEvent - event: - type: io.direktiv.function.test.result.karate - source: karate - data: jq(.error) - context: - result: failure - function: jq(."io.direktiv.function.test".function) - version: jq(."io.direktiv.function.test".version) - - diff --git a/tests/v1.0/karate.yaml b/tests/v1.0/karate.yaml deleted file mode 100644 index 28fed23..0000000 --- a/tests/v1.0/karate.yaml +++ /dev/null @@ -1,22 +0,0 @@ -url: "" -functions: -- type: knative-workflow - id: karate - image: gcr.io/direktiv/functions/karate:1.0 -states: -- id: run-test - type: action - action: - function: karate - input: - commands: - - command: java -DtestURL=jq(.host) -Dexport-xlsxSecret=jq(.secrets.export-xlsxSecret) - -jar /karate.jar test.feature - print: false - - command: cat target/karate-reports/karate-summary-json.txt - logging: info - secrets: - - export-xlsxSecret - files: - - key: test.feature - scope: workflow diff --git a/tests/v1.0/karate.yaml.test.feature b/tests/v1.0/karate.yaml.test.feature deleted file mode 100644 index 22b2b6b..0000000 --- a/tests/v1.0/karate.yaml.test.feature +++ /dev/null @@ -1,41 +0,0 @@ - -Feature: Basic - -# The secrects can be used in the payload with the following syntax #(mysecretname) -Background: -* def export-xlsxSecret = karate.properties['export-xlsxSecret'] - - -Scenario: get request - - Given url karate.properties['testURL'] - - And path '/' - And header Direktiv-ActionID = 'development' - And header Direktiv-TempDir = '/tmp' - And request - """ - { - "commands": [ - { - "command": "ls -la", - "silent": true, - "print": false, - } - ] - } - """ - When method POST - Then status 200 - And match $ == - """ - { - "export-xlsx": [ - { - "result": "#notnull", - "success": true - } - ] - } - """ - \ No newline at end of file diff --git a/tests/v1.0/tests-event.yaml b/tests/v1.0/tests-event.yaml deleted file mode 100644 index 838c8aa..0000000 --- a/tests/v1.0/tests-event.yaml +++ /dev/null @@ -1,44 +0,0 @@ -url: "" -functions: -- type: subflow - id: call-tests - workflow: tests -start: - type: event - state: call-subflow - event: - type: io.direktiv.function.test - context: - function: 'export-xlsx' - version: '1.0' -states: -- id: call-subflow - type: action - action: - function: call-tests - catch: - - error: "*" - transition: report-failure - transition: report-success -- id: report-success - type: generateEvent - event: - type: io.direktiv.function.test.result - source: tests - data: '' - context: - result: success - function: jq(."io.direktiv.function.test".function) - version: jq(."io.direktiv.function.test".version) -- id: report-failure - type: generateEvent - event: - type: io.direktiv.function.test.result - source: tests - data: jq(.error) - context: - result: failure - function: jq(."io.direktiv.function.test".function) - version: jq(."io.direktiv.function.test".version) - - diff --git a/tests/v1.0/tests.yaml b/tests/v1.0/tests.yaml deleted file mode 100644 index 9afe227..0000000 --- a/tests/v1.0/tests.yaml +++ /dev/null @@ -1,16 +0,0 @@ -url: "" -functions: -- type: knative-workflow - id: export-xlsx - image: registry.coadcorp.com/export-xlsx:test -states: -- id: state0 - type: action - action: - function: export-xlsx - input: - files: - - data: "jq(.input) \n" - name: /tmp/input.json - out-filename: example.xlsx - worksheet-name: TestSpreadsheet