From 38f486cbb6339fbdf7a90cd7e33a1471828374eb Mon Sep 17 00:00:00 2001 From: Alejandro Saucedo Date: Mon, 6 Apr 2020 21:06:24 +0100 Subject: [PATCH 1/5] Fixed file version path typo --- wrappers/s2i/python/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrappers/s2i/python/Makefile b/wrappers/s2i/python/Makefile index 54d1ac98c0..db70f0256c 100644 --- a/wrappers/s2i/python/Makefile +++ b/wrappers/s2i/python/Makefile @@ -1,4 +1,4 @@ -VERSION := $(shell cat ../version.txt) +IMAGE_VERSION := $(shell cat ../../../version.txt) SHELL:=/bin/bash PYTHON_VERSION=3.7 From 407781a356b4291b045b2cb31cf7c77bc19ce6cc Mon Sep 17 00:00:00 2001 From: Alejandro Saucedo Date: Wed, 22 Apr 2020 22:30:47 +0100 Subject: [PATCH 2/5] Added swagger file and ui --- executor/Dockerfile | 2 + .../api/rest/openapi/v1.0/dist/seldon.json | 611 ++++++++++++++++++ .../openapi/v1.0/dist/swagger_ui_bundled.html | 84 +++ .../openapi/v1.0/dist/swagger_ui_cdn.html | 58 ++ executor/api/rest/server.go | 2 + 5 files changed, 757 insertions(+) create mode 100644 executor/api/rest/openapi/v1.0/dist/seldon.json create mode 100644 executor/api/rest/openapi/v1.0/dist/swagger_ui_bundled.html create mode 100644 executor/api/rest/openapi/v1.0/dist/swagger_ui_cdn.html diff --git a/executor/Dockerfile b/executor/Dockerfile index fed80f1982..79f536d949 100644 --- a/executor/Dockerfile +++ b/executor/Dockerfile @@ -25,5 +25,7 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o executor FROM gcr.io/distroless/static:latest WORKDIR / COPY --from=builder /workspace/executor . +# Copy openapi and swagger files +COPY --from=builder /workspace/api/rest/openapi/ openapi/ COPY licenses/license.txt . ENTRYPOINT ["/executor"] diff --git a/executor/api/rest/openapi/v1.0/dist/seldon.json b/executor/api/rest/openapi/v1.0/dist/seldon.json new file mode 100644 index 0000000000..fd69600f67 --- /dev/null +++ b/executor/api/rest/openapi/v1.0/dist/seldon.json @@ -0,0 +1,611 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Seldon External API", + "version": "0.1", + "contact": { + "name": "Seldon Core", + "url": "https://github.com/SeldonIO/seldon-core" + } + }, + "externalDocs": { + "description": "Seldon Core Documentation", + "url": "https://github.com/SeldonIO/seldon-core" + }, + "servers": [ + { + "url": "http://{host}:{port}", + "variables": { + "host": { + "default": "localhost", + "description": "host running seldon core" + }, + "port": { + "default": "80" + } + } + }, + { + "url": "http://localhost:8002", + "description": "fixed host as swagger UI has bug with variables for auth" + } + ], + "paths": { + "/seldon/{namespace}/{deployment}/api/v1.0/predictions": { + "post": { + "operationId": "Predict", + "responses": { + "200": { + "description": "A successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SeldonMessage" + } + } + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "deployment", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "tags": [ + "External Ambassador API" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SeldonMessage" + }, + "example": { + "data": { + "names": [ + "feature1" + ], + "tensor": { + "shape": [ + 1, + 1 + ], + "values": [ + 1 + ] + } + } + } + }, + "text/*": { + "schema": { + "type": "string" + } + }, + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "required": true + } + } + }, + "/seldon/{namespace}/{deployment}/api/v1.0/feedback": { + "post": { + "operationId": "SendFeedback", + "responses": { + "200": { + "description": "A successful response.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SeldonMessage" + } + } + } + } + }, + "parameters": [ + { + "name": "namespace", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "deployment", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "tags": [ + "External Ambassador API" + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Feedback" + } + } + }, + "required": true + } + } + } + }, + "components": { + "schemas": { + "StatusStatusFlag": { + "type": "string", + "enum": [ + "SUCCESS", + "FAILURE" + ], + "default": "SUCCESS" + }, + "AnyValue": { + "description": "Can be anything: string, number, array, object, etc." + }, + "MetricType": { + "type": "string", + "enum": [ + "COUNTER", + "GAUGE", + "TIMER" + ], + "default": "COUNTER" + }, + "Metric": { + "type": "object", + "properties": { + "type": { + "$ref": "#/components/schemas/MetricType" + }, + "key": { + "type": "string" + }, + "value": { + "type": "number", + "format": "float" + } + } + }, + "DefaultData": { + "type": "object", + "properties": { + "names": { + "type": "array", + "items": { + "type": "string" + } + }, + "tensor": { + "$ref": "#/components/schemas/Tensor" + }, + "ndarry": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AnyValue" + } + }, + "tftensor": { + "$ref": "#/components/schemas/TensorflowTensorProto" + } + } + }, + "Feedback": { + "type": "object", + "properties": { + "request": { + "$ref": "#/components/schemas/SeldonMessage" + }, + "response": { + "$ref": "#/components/schemas/SeldonMessage" + }, + "reward": { + "type": "number", + "format": "float" + }, + "truth": { + "$ref": "#/components/schemas/SeldonMessage" + } + } + }, + "Meta": { + "type": "object", + "properties": { + "puid": { + "type": "string" + }, + "tags": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/AnyValue" + }, + "example": { + "mytag": "myvalue" + } + }, + "routing": { + "type": "object", + "additionalProperties": { + "type": "integer", + "format": "int32" + }, + "example": { + "router1": 1 + } + }, + "requestPath": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "example": { + "classifier": "seldonio/mock_classifier:1.0" + } + }, + "metrics": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Metric" + } + } + } + }, + "SeldonMessage": { + "type": "object", + "properties": { + "status": { + "$ref": "#/components/schemas/Status" + }, + "meta": { + "$ref": "#/components/schemas/Meta" + }, + "data": { + "$ref": "#/components/schemas/DefaultData" + }, + "binData": { + "type": "string", + "format": "byte" + }, + "strData": { + "type": "string" + } + } + }, + "SeldonMessageList": { + "type": "object", + "properties": { + "seldonMessages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SeldonMessage" + } + } + } + }, + "Status": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "info": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "status": { + "$ref": "#/components/schemas/StatusStatusFlag" + } + } + }, + "Tensor": { + "type": "object", + "properties": { + "shape": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + }, + "values": { + "type": "array", + "items": { + "type": "number", + "format": "double" + } + } + } + }, + "TensorShapeProtoDim": { + "type": "object", + "properties": { + "size": { + "type": "string", + "format": "int64", + "description": "Size of the tensor in that dimension.\nThis value must be >= -1, but values of -1 are reserved for \"unknown\"\nshapes (values of -1 mean \"unknown\" dimension). Certain wrappers\nthat work with TensorShapeProto may fail at runtime when deserializing\na TensorShapeProto containing a dim value of -1." + }, + "name": { + "type": "string", + "description": "Optional name of the tensor dimension." + } + }, + "description": "One dimension of the tensor." + }, + "TensorflowDataType": { + "type": "string", + "enum": [ + "DT_INVALID", + "DT_FLOAT", + "DT_DOUBLE", + "DT_INT32", + "DT_UINT8", + "DT_INT16", + "DT_INT8", + "DT_STRING", + "DT_COMPLEX64", + "DT_INT64", + "DT_BOOL", + "DT_QINT8", + "DT_QUINT8", + "DT_QINT32", + "DT_BFLOAT16", + "DT_QINT16", + "DT_QUINT16", + "DT_UINT16", + "DT_COMPLEX128", + "DT_HALF", + "DT_RESOURCE", + "DT_VARIANT", + "DT_UINT32", + "DT_UINT64", + "DT_FLOAT_REF", + "DT_DOUBLE_REF", + "DT_INT32_REF", + "DT_UINT8_REF", + "DT_INT16_REF", + "DT_INT8_REF", + "DT_STRING_REF", + "DT_COMPLEX64_REF", + "DT_INT64_REF", + "DT_BOOL_REF", + "DT_QINT8_REF", + "DT_QUINT8_REF", + "DT_QINT32_REF", + "DT_BFLOAT16_REF", + "DT_QINT16_REF", + "DT_QUINT16_REF", + "DT_UINT16_REF", + "DT_COMPLEX128_REF", + "DT_HALF_REF", + "DT_RESOURCE_REF", + "DT_VARIANT_REF", + "DT_UINT32_REF", + "DT_UINT64_REF" + ], + "default": "DT_INVALID", + "description": "- DT_INVALID: Not a legal value for DataType. Used to indicate a DataType field\nhas not been set.\n - DT_FLOAT: Data types that all computation devices are expected to be\ncapable to support.\n - DT_FLOAT_REF: Do not use! These are only for parameters. Every enum above\nshould have a corresponding value below (verified by types_test).", + "title": "LINT.IfChange" + }, + "TensorflowResourceHandleProto": { + "type": "object", + "properties": { + "device": { + "type": "string", + "description": "Unique name for the device containing the resource." + }, + "container": { + "type": "string", + "description": "Container in which this resource is placed." + }, + "name": { + "type": "string", + "description": "Unique name of this resource." + }, + "hash_code": { + "type": "string", + "format": "uint64", + "description": "Hash code for the type of the resource. Is only valid in the same device\nand in the same execution." + }, + "maybe_type_name": { + "type": "string", + "description": "For debug-only, the name of the type pointed to by this handle, if\navailable." + } + }, + "description": "Protocol buffer representing a handle to a tensorflow resource. Handles are\nnot valid across executions, but can be serialized back and forth from within\na single run." + }, + "TensorflowTensorProto": { + "type": "object", + "properties": { + "dtype": { + "$ref": "#/components/schemas/TensorflowDataType" + }, + "tensor_shape": { + "$ref": "#/components/schemas/TensorflowTensorShapeProto", + "description": "Shape of the tensor. TODO(touts): sort out the 0-rank issues." + }, + "version_number": { + "type": "integer", + "format": "int32", + "description": "Version number.\n\nIn version 0, if the \"repeated xxx\" representations contain only one\nelement, that element is repeated to fill the shape. This makes it easy\nto represent a constant Tensor with a single value." + }, + "tensor_content": { + "type": "string", + "format": "byte", + "description": "Serialized raw tensor content from either Tensor::AsProtoTensorContent or\nmemcpy in tensorflow::grpc::EncodeTensorToByteBuffer. This representation\ncan be used for all tensor types. The purpose of this representation is to\nreduce serialization overhead during RPC call by avoiding serialization of\nmany repeated small items." + }, + "half_val": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + }, + "description": "DT_HALF, DT_BFLOAT16. Note that since protobuf has no int16 type, we'll\nhave some pointless zero padding for each value here." + }, + "float_val": { + "type": "array", + "items": { + "type": "number", + "format": "float" + }, + "description": "DT_FLOAT." + }, + "double_val": { + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "description": "DT_DOUBLE." + }, + "int_val": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + }, + "description": "DT_INT32, DT_INT16, DT_INT8, DT_UINT8." + }, + "string_val": { + "type": "array", + "items": { + "type": "string", + "format": "byte" + }, + "title": "DT_STRING" + }, + "scomplex_val": { + "type": "array", + "items": { + "type": "number", + "format": "float" + }, + "description": "DT_COMPLEX64. scomplex_val(2*i) and scomplex_val(2*i+1) are real\nand imaginary parts of i-th single precision complex." + }, + "int64_val": { + "type": "array", + "items": { + "type": "string", + "format": "int64" + }, + "title": "DT_INT64" + }, + "bool_val": { + "type": "array", + "items": { + "type": "boolean", + "format": "boolean" + }, + "title": "DT_BOOL" + }, + "dcomplex_val": { + "type": "array", + "items": { + "type": "number", + "format": "double" + }, + "description": "DT_COMPLEX128. dcomplex_val(2*i) and dcomplex_val(2*i+1) are real\nand imaginary parts of i-th double precision complex." + }, + "resource_handle_val": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TensorflowResourceHandleProto" + }, + "title": "DT_RESOURCE" + }, + "variant_val": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TensorflowVariantTensorDataProto" + }, + "title": "DT_VARIANT" + }, + "uint32_val": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "title": "DT_UINT32" + }, + "uint64_val": { + "type": "array", + "items": { + "type": "string", + "format": "uint64" + }, + "title": "DT_UINT64" + } + }, + "description": "Protocol buffer representing a tensor." + }, + "TensorflowTensorShapeProto": { + "type": "object", + "properties": { + "dim": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TensorShapeProtoDim" + }, + "description": "Dimensions of the tensor, such as {\"input\", 30}, {\"output\", 40}\nfor a 30 x 40 2D tensor. If an entry has size -1, this\ncorresponds to a dimension of unknown size. The names are\noptional.\n\nThe order of entries in \"dim\" matters: It indicates the layout of the\nvalues in the tensor in-memory representation.\n\nThe first entry in \"dim\" is the outermost dimension used to layout the\nvalues, the last entry is the innermost dimension. This matches the\nin-memory layout of RowMajor Eigen tensors.\n\nIf \"dim.size()\" > 0, \"unknown_rank\" must be false." + }, + "unknown_rank": { + "type": "boolean", + "format": "boolean", + "description": "If true, the number of dimensions in the shape is unknown.\n\nIf true, \"dim.size()\" must be 0." + } + }, + "description": "Dimensions of a tensor." + }, + "TensorflowVariantTensorDataProto": { + "type": "object", + "properties": { + "type_name": { + "type": "string", + "description": "Name of the type of objects being serialized." + }, + "metadata": { + "type": "string", + "format": "byte", + "description": "Portions of the object that are not Tensors." + }, + "tensors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TensorflowTensorProto" + }, + "description": "Tensors contained within objects being serialized." + } + }, + "description": "Protocol buffer representing the serialization format of DT_VARIANT tensors." + } + } + } +} diff --git a/executor/api/rest/openapi/v1.0/dist/swagger_ui_bundled.html b/executor/api/rest/openapi/v1.0/dist/swagger_ui_bundled.html new file mode 100644 index 0000000000..22eda9b1d4 --- /dev/null +++ b/executor/api/rest/openapi/v1.0/dist/swagger_ui_bundled.html @@ -0,0 +1,84 @@ + + + + + + Swagger UI + + + + + +
+ + + + + + + + + + diff --git a/executor/api/rest/openapi/v1.0/dist/swagger_ui_cdn.html b/executor/api/rest/openapi/v1.0/dist/swagger_ui_cdn.html new file mode 100644 index 0000000000..829aa68236 --- /dev/null +++ b/executor/api/rest/openapi/v1.0/dist/swagger_ui_cdn.html @@ -0,0 +1,58 @@ + + + + + + Swagger UI + + + + + +
+ + + + + + diff --git a/executor/api/rest/server.go b/executor/api/rest/server.go index cef87b3dfc..0c8aee3d0d 100644 --- a/executor/api/rest/server.go +++ b/executor/api/rest/server.go @@ -141,11 +141,13 @@ func (r *SeldonRestApi) Initialise() { api01.Handle("/predictions", r.wrapMetrics(metric.PredictionHttpServiceName, r.predictions)) r.Router.NewRoute().Path("/api/v0.1/status/{" + ModelHttpPathVariable + "}").Methods("GET").HandlerFunc(r.wrapMetrics(metric.StatusHttpServiceName, r.status)) r.Router.NewRoute().Path("/api/v0.1/metadata/{" + ModelHttpPathVariable + "}").Methods("GET").HandlerFunc(r.wrapMetrics(metric.StatusHttpServiceName, r.metadata)) + r.Router.NewRoute().PathPrefix("/api/v0.1/doc/").Handler(http.StripPrefix("/api/v0.1/doc/", http.FileServer(http.Dir("./openapi/v1.0/dist/")))) //v1.0 API api1 := r.Router.PathPrefix("/api/v1.0").Methods("POST").Subrouter() api1.Handle("/predictions", r.wrapMetrics(metric.PredictionServiceMetricName, r.predictions)) r.Router.NewRoute().Path("/api/v1.0/status/{" + ModelHttpPathVariable + "}").Methods("GET").HandlerFunc(r.wrapMetrics(metric.StatusHttpServiceName, r.status)) r.Router.NewRoute().Path("/api/v1.0/metadata/{" + ModelHttpPathVariable + "}").Methods("GET").HandlerFunc(r.wrapMetrics(metric.StatusHttpServiceName, r.metadata)) + r.Router.NewRoute().PathPrefix("/api/v1.0/doc/").Handler(http.StripPrefix("/api/v1.0/doc/", http.FileServer(http.Dir("./openapi/v1.0/dist/")))) case api.ProtocolTensorflow: r.Router.NewRoute().Path("/v1/models/{" + ModelHttpPathVariable + "}/:predict").Methods("POST").HandlerFunc(r.wrapMetrics(metric.PredictionHttpServiceName, r.predictions)) From f041a4476215d2ae4a5203402b1fc6821ba87391 Mon Sep 17 00:00:00 2001 From: Alejandro Saucedo Date: Fri, 24 Apr 2020 09:35:01 +0100 Subject: [PATCH 3/5] Moved executor files to openapi folder --- executor/Dockerfile | 5 +- .../api/rest/openapi/v1.0/dist/seldon.json | 611 ------------------ .../swagger-ui}/swagger_ui_bundled.html | 0 .../swagger-ui}/swagger_ui_cdn.html | 0 4 files changed, 3 insertions(+), 613 deletions(-) delete mode 100644 executor/api/rest/openapi/v1.0/dist/seldon.json rename {executor/api/rest/openapi/v1.0/dist => openapi/swagger-ui}/swagger_ui_bundled.html (100%) rename {executor/api/rest/openapi/v1.0/dist => openapi/swagger-ui}/swagger_ui_cdn.html (100%) diff --git a/executor/Dockerfile b/executor/Dockerfile index 79f536d949..540a5d295c 100644 --- a/executor/Dockerfile +++ b/executor/Dockerfile @@ -25,7 +25,8 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o executor FROM gcr.io/distroless/static:latest WORKDIR / COPY --from=builder /workspace/executor . -# Copy openapi and swagger files -COPY --from=builder /workspace/api/rest/openapi/ openapi/ +# Copy openapi spec and swagger UI files +COPY ../openapi/swagger-ui/ /workspace/api/rest/openapi/ +COPY ../openapi/seldon.json /workspace/api/rest/openapi/seldon.json COPY licenses/license.txt . ENTRYPOINT ["/executor"] diff --git a/executor/api/rest/openapi/v1.0/dist/seldon.json b/executor/api/rest/openapi/v1.0/dist/seldon.json deleted file mode 100644 index fd69600f67..0000000000 --- a/executor/api/rest/openapi/v1.0/dist/seldon.json +++ /dev/null @@ -1,611 +0,0 @@ -{ - "openapi": "3.0.0", - "info": { - "title": "Seldon External API", - "version": "0.1", - "contact": { - "name": "Seldon Core", - "url": "https://github.com/SeldonIO/seldon-core" - } - }, - "externalDocs": { - "description": "Seldon Core Documentation", - "url": "https://github.com/SeldonIO/seldon-core" - }, - "servers": [ - { - "url": "http://{host}:{port}", - "variables": { - "host": { - "default": "localhost", - "description": "host running seldon core" - }, - "port": { - "default": "80" - } - } - }, - { - "url": "http://localhost:8002", - "description": "fixed host as swagger UI has bug with variables for auth" - } - ], - "paths": { - "/seldon/{namespace}/{deployment}/api/v1.0/predictions": { - "post": { - "operationId": "Predict", - "responses": { - "200": { - "description": "A successful response.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SeldonMessage" - } - } - } - } - }, - "parameters": [ - { - "name": "namespace", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "deployment", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "tags": [ - "External Ambassador API" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SeldonMessage" - }, - "example": { - "data": { - "names": [ - "feature1" - ], - "tensor": { - "shape": [ - 1, - 1 - ], - "values": [ - 1 - ] - } - } - } - }, - "text/*": { - "schema": { - "type": "string" - } - }, - "application/octet-stream": { - "schema": { - "type": "string", - "format": "binary" - } - } - }, - "required": true - } - } - }, - "/seldon/{namespace}/{deployment}/api/v1.0/feedback": { - "post": { - "operationId": "SendFeedback", - "responses": { - "200": { - "description": "A successful response.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SeldonMessage" - } - } - } - } - }, - "parameters": [ - { - "name": "namespace", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "deployment", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "tags": [ - "External Ambassador API" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Feedback" - } - } - }, - "required": true - } - } - } - }, - "components": { - "schemas": { - "StatusStatusFlag": { - "type": "string", - "enum": [ - "SUCCESS", - "FAILURE" - ], - "default": "SUCCESS" - }, - "AnyValue": { - "description": "Can be anything: string, number, array, object, etc." - }, - "MetricType": { - "type": "string", - "enum": [ - "COUNTER", - "GAUGE", - "TIMER" - ], - "default": "COUNTER" - }, - "Metric": { - "type": "object", - "properties": { - "type": { - "$ref": "#/components/schemas/MetricType" - }, - "key": { - "type": "string" - }, - "value": { - "type": "number", - "format": "float" - } - } - }, - "DefaultData": { - "type": "object", - "properties": { - "names": { - "type": "array", - "items": { - "type": "string" - } - }, - "tensor": { - "$ref": "#/components/schemas/Tensor" - }, - "ndarry": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AnyValue" - } - }, - "tftensor": { - "$ref": "#/components/schemas/TensorflowTensorProto" - } - } - }, - "Feedback": { - "type": "object", - "properties": { - "request": { - "$ref": "#/components/schemas/SeldonMessage" - }, - "response": { - "$ref": "#/components/schemas/SeldonMessage" - }, - "reward": { - "type": "number", - "format": "float" - }, - "truth": { - "$ref": "#/components/schemas/SeldonMessage" - } - } - }, - "Meta": { - "type": "object", - "properties": { - "puid": { - "type": "string" - }, - "tags": { - "type": "object", - "additionalProperties": { - "$ref": "#/components/schemas/AnyValue" - }, - "example": { - "mytag": "myvalue" - } - }, - "routing": { - "type": "object", - "additionalProperties": { - "type": "integer", - "format": "int32" - }, - "example": { - "router1": 1 - } - }, - "requestPath": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "example": { - "classifier": "seldonio/mock_classifier:1.0" - } - }, - "metrics": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Metric" - } - } - } - }, - "SeldonMessage": { - "type": "object", - "properties": { - "status": { - "$ref": "#/components/schemas/Status" - }, - "meta": { - "$ref": "#/components/schemas/Meta" - }, - "data": { - "$ref": "#/components/schemas/DefaultData" - }, - "binData": { - "type": "string", - "format": "byte" - }, - "strData": { - "type": "string" - } - } - }, - "SeldonMessageList": { - "type": "object", - "properties": { - "seldonMessages": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SeldonMessage" - } - } - } - }, - "Status": { - "type": "object", - "properties": { - "code": { - "type": "integer", - "format": "int32" - }, - "info": { - "type": "string" - }, - "reason": { - "type": "string" - }, - "status": { - "$ref": "#/components/schemas/StatusStatusFlag" - } - } - }, - "Tensor": { - "type": "object", - "properties": { - "shape": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - } - }, - "values": { - "type": "array", - "items": { - "type": "number", - "format": "double" - } - } - } - }, - "TensorShapeProtoDim": { - "type": "object", - "properties": { - "size": { - "type": "string", - "format": "int64", - "description": "Size of the tensor in that dimension.\nThis value must be >= -1, but values of -1 are reserved for \"unknown\"\nshapes (values of -1 mean \"unknown\" dimension). Certain wrappers\nthat work with TensorShapeProto may fail at runtime when deserializing\na TensorShapeProto containing a dim value of -1." - }, - "name": { - "type": "string", - "description": "Optional name of the tensor dimension." - } - }, - "description": "One dimension of the tensor." - }, - "TensorflowDataType": { - "type": "string", - "enum": [ - "DT_INVALID", - "DT_FLOAT", - "DT_DOUBLE", - "DT_INT32", - "DT_UINT8", - "DT_INT16", - "DT_INT8", - "DT_STRING", - "DT_COMPLEX64", - "DT_INT64", - "DT_BOOL", - "DT_QINT8", - "DT_QUINT8", - "DT_QINT32", - "DT_BFLOAT16", - "DT_QINT16", - "DT_QUINT16", - "DT_UINT16", - "DT_COMPLEX128", - "DT_HALF", - "DT_RESOURCE", - "DT_VARIANT", - "DT_UINT32", - "DT_UINT64", - "DT_FLOAT_REF", - "DT_DOUBLE_REF", - "DT_INT32_REF", - "DT_UINT8_REF", - "DT_INT16_REF", - "DT_INT8_REF", - "DT_STRING_REF", - "DT_COMPLEX64_REF", - "DT_INT64_REF", - "DT_BOOL_REF", - "DT_QINT8_REF", - "DT_QUINT8_REF", - "DT_QINT32_REF", - "DT_BFLOAT16_REF", - "DT_QINT16_REF", - "DT_QUINT16_REF", - "DT_UINT16_REF", - "DT_COMPLEX128_REF", - "DT_HALF_REF", - "DT_RESOURCE_REF", - "DT_VARIANT_REF", - "DT_UINT32_REF", - "DT_UINT64_REF" - ], - "default": "DT_INVALID", - "description": "- DT_INVALID: Not a legal value for DataType. Used to indicate a DataType field\nhas not been set.\n - DT_FLOAT: Data types that all computation devices are expected to be\ncapable to support.\n - DT_FLOAT_REF: Do not use! These are only for parameters. Every enum above\nshould have a corresponding value below (verified by types_test).", - "title": "LINT.IfChange" - }, - "TensorflowResourceHandleProto": { - "type": "object", - "properties": { - "device": { - "type": "string", - "description": "Unique name for the device containing the resource." - }, - "container": { - "type": "string", - "description": "Container in which this resource is placed." - }, - "name": { - "type": "string", - "description": "Unique name of this resource." - }, - "hash_code": { - "type": "string", - "format": "uint64", - "description": "Hash code for the type of the resource. Is only valid in the same device\nand in the same execution." - }, - "maybe_type_name": { - "type": "string", - "description": "For debug-only, the name of the type pointed to by this handle, if\navailable." - } - }, - "description": "Protocol buffer representing a handle to a tensorflow resource. Handles are\nnot valid across executions, but can be serialized back and forth from within\na single run." - }, - "TensorflowTensorProto": { - "type": "object", - "properties": { - "dtype": { - "$ref": "#/components/schemas/TensorflowDataType" - }, - "tensor_shape": { - "$ref": "#/components/schemas/TensorflowTensorShapeProto", - "description": "Shape of the tensor. TODO(touts): sort out the 0-rank issues." - }, - "version_number": { - "type": "integer", - "format": "int32", - "description": "Version number.\n\nIn version 0, if the \"repeated xxx\" representations contain only one\nelement, that element is repeated to fill the shape. This makes it easy\nto represent a constant Tensor with a single value." - }, - "tensor_content": { - "type": "string", - "format": "byte", - "description": "Serialized raw tensor content from either Tensor::AsProtoTensorContent or\nmemcpy in tensorflow::grpc::EncodeTensorToByteBuffer. This representation\ncan be used for all tensor types. The purpose of this representation is to\nreduce serialization overhead during RPC call by avoiding serialization of\nmany repeated small items." - }, - "half_val": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - }, - "description": "DT_HALF, DT_BFLOAT16. Note that since protobuf has no int16 type, we'll\nhave some pointless zero padding for each value here." - }, - "float_val": { - "type": "array", - "items": { - "type": "number", - "format": "float" - }, - "description": "DT_FLOAT." - }, - "double_val": { - "type": "array", - "items": { - "type": "number", - "format": "double" - }, - "description": "DT_DOUBLE." - }, - "int_val": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - }, - "description": "DT_INT32, DT_INT16, DT_INT8, DT_UINT8." - }, - "string_val": { - "type": "array", - "items": { - "type": "string", - "format": "byte" - }, - "title": "DT_STRING" - }, - "scomplex_val": { - "type": "array", - "items": { - "type": "number", - "format": "float" - }, - "description": "DT_COMPLEX64. scomplex_val(2*i) and scomplex_val(2*i+1) are real\nand imaginary parts of i-th single precision complex." - }, - "int64_val": { - "type": "array", - "items": { - "type": "string", - "format": "int64" - }, - "title": "DT_INT64" - }, - "bool_val": { - "type": "array", - "items": { - "type": "boolean", - "format": "boolean" - }, - "title": "DT_BOOL" - }, - "dcomplex_val": { - "type": "array", - "items": { - "type": "number", - "format": "double" - }, - "description": "DT_COMPLEX128. dcomplex_val(2*i) and dcomplex_val(2*i+1) are real\nand imaginary parts of i-th double precision complex." - }, - "resource_handle_val": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TensorflowResourceHandleProto" - }, - "title": "DT_RESOURCE" - }, - "variant_val": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TensorflowVariantTensorDataProto" - }, - "title": "DT_VARIANT" - }, - "uint32_val": { - "type": "array", - "items": { - "type": "integer", - "format": "int64" - }, - "title": "DT_UINT32" - }, - "uint64_val": { - "type": "array", - "items": { - "type": "string", - "format": "uint64" - }, - "title": "DT_UINT64" - } - }, - "description": "Protocol buffer representing a tensor." - }, - "TensorflowTensorShapeProto": { - "type": "object", - "properties": { - "dim": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TensorShapeProtoDim" - }, - "description": "Dimensions of the tensor, such as {\"input\", 30}, {\"output\", 40}\nfor a 30 x 40 2D tensor. If an entry has size -1, this\ncorresponds to a dimension of unknown size. The names are\noptional.\n\nThe order of entries in \"dim\" matters: It indicates the layout of the\nvalues in the tensor in-memory representation.\n\nThe first entry in \"dim\" is the outermost dimension used to layout the\nvalues, the last entry is the innermost dimension. This matches the\nin-memory layout of RowMajor Eigen tensors.\n\nIf \"dim.size()\" > 0, \"unknown_rank\" must be false." - }, - "unknown_rank": { - "type": "boolean", - "format": "boolean", - "description": "If true, the number of dimensions in the shape is unknown.\n\nIf true, \"dim.size()\" must be 0." - } - }, - "description": "Dimensions of a tensor." - }, - "TensorflowVariantTensorDataProto": { - "type": "object", - "properties": { - "type_name": { - "type": "string", - "description": "Name of the type of objects being serialized." - }, - "metadata": { - "type": "string", - "format": "byte", - "description": "Portions of the object that are not Tensors." - }, - "tensors": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TensorflowTensorProto" - }, - "description": "Tensors contained within objects being serialized." - } - }, - "description": "Protocol buffer representing the serialization format of DT_VARIANT tensors." - } - } - } -} diff --git a/executor/api/rest/openapi/v1.0/dist/swagger_ui_bundled.html b/openapi/swagger-ui/swagger_ui_bundled.html similarity index 100% rename from executor/api/rest/openapi/v1.0/dist/swagger_ui_bundled.html rename to openapi/swagger-ui/swagger_ui_bundled.html diff --git a/executor/api/rest/openapi/v1.0/dist/swagger_ui_cdn.html b/openapi/swagger-ui/swagger_ui_cdn.html similarity index 100% rename from executor/api/rest/openapi/v1.0/dist/swagger_ui_cdn.html rename to openapi/swagger-ui/swagger_ui_cdn.html From cf3d641156de55eb42bbc7247ef5c608ada9b96a Mon Sep 17 00:00:00 2001 From: Alejandro Saucedo Date: Fri, 24 Apr 2020 13:58:44 +0100 Subject: [PATCH 4/5] Moved swagger files in the correct location and added code to copy --- executor/.gitignore | 3 ++- executor/Dockerfile | 3 +-- executor/Makefile | 9 +++++++-- executor/api/rest/server.go | 4 ++-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/executor/.gitignore b/executor/.gitignore index b394b3ec4b..ee569b0d5e 100644 --- a/executor/.gitignore +++ b/executor/.gitignore @@ -5,4 +5,5 @@ executor ./bin/ cover.out executor.tar - \ No newline at end of file +openapi/ + diff --git a/executor/Dockerfile b/executor/Dockerfile index 540a5d295c..1a95d3a67d 100644 --- a/executor/Dockerfile +++ b/executor/Dockerfile @@ -26,7 +26,6 @@ FROM gcr.io/distroless/static:latest WORKDIR / COPY --from=builder /workspace/executor . # Copy openapi spec and swagger UI files -COPY ../openapi/swagger-ui/ /workspace/api/rest/openapi/ -COPY ../openapi/seldon.json /workspace/api/rest/openapi/seldon.json +COPY openapi/ /openapi/ COPY licenses/license.txt . ENTRYPOINT ["/executor"] diff --git a/executor/Makefile b/executor/Makefile index a45388829d..23618fd5d9 100644 --- a/executor/Makefile +++ b/executor/Makefile @@ -57,12 +57,17 @@ add_protos: test: fmt vet go test ./api/... ./predictor/... ./k8s/... -coverprofile cover.out +copy-openapi-resources: + mkdir -p openapi/ + cp ../openapi/swagger-ui/* openapi/ + cp ../openapi/engine.oas3.json openapi/seldon.json + # Build the docker image -docker-build: test +docker-build: test copy-openapi-resources docker build -f Dockerfile -t ${IMG} . # Build the docker image for Redhat -docker-build-redhat: test +docker-build-redhat: test copy-openapi-resources docker build . -f Dockerfile.redhat -t ${IMG_REDHAT} # Push the docker image diff --git a/executor/api/rest/server.go b/executor/api/rest/server.go index 0c8aee3d0d..5eef51aaf7 100644 --- a/executor/api/rest/server.go +++ b/executor/api/rest/server.go @@ -141,13 +141,13 @@ func (r *SeldonRestApi) Initialise() { api01.Handle("/predictions", r.wrapMetrics(metric.PredictionHttpServiceName, r.predictions)) r.Router.NewRoute().Path("/api/v0.1/status/{" + ModelHttpPathVariable + "}").Methods("GET").HandlerFunc(r.wrapMetrics(metric.StatusHttpServiceName, r.status)) r.Router.NewRoute().Path("/api/v0.1/metadata/{" + ModelHttpPathVariable + "}").Methods("GET").HandlerFunc(r.wrapMetrics(metric.StatusHttpServiceName, r.metadata)) - r.Router.NewRoute().PathPrefix("/api/v0.1/doc/").Handler(http.StripPrefix("/api/v0.1/doc/", http.FileServer(http.Dir("./openapi/v1.0/dist/")))) + r.Router.NewRoute().PathPrefix("/api/v0.1/doc/").Handler(http.StripPrefix("/api/v0.1/doc/", http.FileServer(http.Dir("./openapi/")))) //v1.0 API api1 := r.Router.PathPrefix("/api/v1.0").Methods("POST").Subrouter() api1.Handle("/predictions", r.wrapMetrics(metric.PredictionServiceMetricName, r.predictions)) r.Router.NewRoute().Path("/api/v1.0/status/{" + ModelHttpPathVariable + "}").Methods("GET").HandlerFunc(r.wrapMetrics(metric.StatusHttpServiceName, r.status)) r.Router.NewRoute().Path("/api/v1.0/metadata/{" + ModelHttpPathVariable + "}").Methods("GET").HandlerFunc(r.wrapMetrics(metric.StatusHttpServiceName, r.metadata)) - r.Router.NewRoute().PathPrefix("/api/v1.0/doc/").Handler(http.StripPrefix("/api/v1.0/doc/", http.FileServer(http.Dir("./openapi/v1.0/dist/")))) + r.Router.NewRoute().PathPrefix("/api/v1.0/doc/").Handler(http.StripPrefix("/api/v1.0/doc/", http.FileServer(http.Dir("./openapi/")))) case api.ProtocolTensorflow: r.Router.NewRoute().Path("/v1/models/{" + ModelHttpPathVariable + "}/:predict").Methods("POST").HandlerFunc(r.wrapMetrics(metric.PredictionHttpServiceName, r.predictions)) From 1a0fd1e823222066dd520981d61ee3de77f656a2 Mon Sep 17 00:00:00 2001 From: Alejandro Saucedo Date: Fri, 24 Apr 2020 14:33:05 +0100 Subject: [PATCH 5/5] renamed swaggerui --- openapi/swagger-ui/{swagger_ui_cdn.html => index.html} | 0 .../swagger-ui/{swagger_ui_bundled.html => index_bundled.html} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename openapi/swagger-ui/{swagger_ui_cdn.html => index.html} (100%) rename openapi/swagger-ui/{swagger_ui_bundled.html => index_bundled.html} (100%) diff --git a/openapi/swagger-ui/swagger_ui_cdn.html b/openapi/swagger-ui/index.html similarity index 100% rename from openapi/swagger-ui/swagger_ui_cdn.html rename to openapi/swagger-ui/index.html diff --git a/openapi/swagger-ui/swagger_ui_bundled.html b/openapi/swagger-ui/index_bundled.html similarity index 100% rename from openapi/swagger-ui/swagger_ui_bundled.html rename to openapi/swagger-ui/index_bundled.html