Hi all
Hopefully this is the right place to post this. If not please let me
know. If a GitHub issue is preferred just let me know and I'll open.
I've recently been playing with extracting the type definitions from
the Kubernetes OpenAPI description, and published individual schemas
for the types. You can see these published here:
https://github.com/garethr/kubernetes-json-schema
The intention is for these schemas to be used in other tools, I'm
particularly interested in developer tooling. Kubeval
(
https://github.com/garethr/kubeval) is a simple example, but we've
talked about Helm validation, support in editors, ksonnet validation
and more in a few forums. For more background see
https://www.morethanseven.net/2017/06/26/schemas-for-kubernetes-types/.
In doing this I hit an issue with how Kubernetes uses OpenAPI/JSON
Schema which I'd love to get some thoughts on, in particular the
"int-or-string" format.
Here's a quick example from the Service API:
https://github.com/garethr/kubernetes-json-schema/blob/master/master-standalone/service.json#L108-L111
If you use the above JSON Schema (which is the same as the data from
the full description at
https://github.com/kubernetes/kubernetes/blob/master/api/openapi-spec/swagger.json)
to validate a service description which uses a target port specified
as an integer it will fail using standard jsonschema libraries:
https://github.com/garethr/kubeval/blob/int-or-string/fixtures/int_or_string.yaml
This is because it fails the type check (ie. it's not a string, it's a
JSON number).
The OpenAPI spec says:
"Primitive data types in the Swagger Specification are based on the
types supported by the JSON-Schema Draft 4."
(those are listed here for reference:
https://tools.ietf.org/html/draft-zyp-json-schema-04#section-3.5)
and also says:
"Primitives have an optional modifier property format. Swagger uses
several known formats to more finely define the data type being used."
and
"However, the format property is an open string-valued property, and
can have any value to support documentation needs"
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types
So, my reading of this is that format is intended to "more finely
define the data type". In the case of int-or-string it's actually
being used to broaden the data types accepted, ie. from it being a
string to it being an integer or a string.
This doesn't invalidate the OpenAPI document because format "can have
any value". But the intention in that case is to "support
documentation". In the case of int-or-string this isn't documentation,
it's parsing rules.
The current usage of int-or-string is unfortunately incompatible with
using standard JSON Schema tooling with the same data.
It could also be argued that the usage of OpenAPI here is incorrect,
even if the Kubernetes OpenAPI description is technically valid.
Note that OpenAPI does have a documented mechanism for vendor
extensions, so it might be possible to see this as a new type, ie.
x-int-or-string, rather than a string with a formatting instruction.
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#vendorExtensions
JSON Schema also supports extensions so these could be passed down to
relevant tooling I think.
http://json-schema.org/latest/json-schema-core.html#rfc.section.6.4
(Sidenote: "Implementations SHOULD ignore keywords they do not
support", which I think would mean x-* types should *just work* with
most clients. In practice I know at least the Go client doesn't do
this, but I'd argue that's a bug in the client.)
I'd be interested in someone sense checking the above. It's a twisty
maze of nested specs and producer and consumer behaviour.
If the above is right, I'd be interested in how it might be possible
to fix it. I think usage of the type definitions in higher-level tools
opens up a bunch of possibilities (see the post above or the brief
conversation at SIG Apps a few weeks back).
Thanks
Gareth
--
Gareth Rushgrove
@garethr
devopsweekly.com
morethanseven.net
garethrushgrove.com