From 78bcc21709a666cd5be8e693fb9e9c0952a97453 Mon Sep 17 00:00:00 2001 From: lburgazzoli Date: Tue, 19 Feb 2019 17:52:18 +0100 Subject: [PATCH] add a tool to generate json schema from custom resources #461 --- Gopkg.lock | 9 + assets/json-schema/CamelCatalog.json | 352 ++++++++++++++ assets/json-schema/Integration.json | 449 +++++++++++++++++ assets/json-schema/IntegrationContext.json | 403 +++++++++++++++ assets/json-schema/IntegrationPlatform.json | 321 ++++++++++++ cmd/util/json-schema-gen/jsonschemagen.go | 73 +++ script/Makefile | 2 + .../github.com/alecthomas/jsonschema/COPYING | 19 + .../alecthomas/jsonschema/reflect.go | 460 ++++++++++++++++++ 9 files changed, 2088 insertions(+) create mode 100644 assets/json-schema/CamelCatalog.json create mode 100644 assets/json-schema/Integration.json create mode 100644 assets/json-schema/IntegrationContext.json create mode 100644 assets/json-schema/IntegrationPlatform.json create mode 100644 cmd/util/json-schema-gen/jsonschemagen.go create mode 100644 vendor/github.com/alecthomas/jsonschema/COPYING create mode 100644 vendor/github.com/alecthomas/jsonschema/reflect.go diff --git a/Gopkg.lock b/Gopkg.lock index f47e069f60..5ec4e466da 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -33,6 +33,14 @@ pruneopts = "NT" revision = "de5bf2ad457846296e2031421a34e2568e304e35" +[[projects]] + branch = "master" + digest = "1:2caa05ca997989079689d13beb3c2f0540809f0696add8e5a1cbd1d9d9b8875b" + name = "github.com/alecthomas/jsonschema" + packages = ["."] + pruneopts = "NT" + revision = "a6952de1bbe6e1c7ef118614925fe4b02847383a" + [[projects]] digest = "1:680b63a131506e668818d630d3ca36123ff290afa0afc9f4be21940adca3f27d" name = "github.com/appscode/jsonpatch" @@ -1077,6 +1085,7 @@ analyzer-version = 1 input-imports = [ "github.com/Masterminds/semver", + "github.com/alecthomas/jsonschema", "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1", "github.com/fatih/structs", "github.com/go-logr/logr", diff --git a/assets/json-schema/CamelCatalog.json b/assets/json-schema/CamelCatalog.json new file mode 100644 index 0000000000..1266aa1354 --- /dev/null +++ b/assets/json-schema/CamelCatalog.json @@ -0,0 +1,352 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/CamelCatalog", + "definitions": { + "CamelArtifact": { + "required": [ + "groupId", + "artifactId" + ], + "properties": { + "artifactId": { + "type": "string" + }, + "dataformats": { + "items": { + "type": "string" + }, + "type": "array" + }, + "dependencies": { + "items": { + "$ref": "#/definitions/CamelArtifact" + }, + "type": "array" + }, + "exclusions": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/CamelArtifactExclusion" + }, + "type": "array" + }, + "groupId": { + "type": "string" + }, + "languages": { + "items": { + "type": "string" + }, + "type": "array" + }, + "schemes": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/CamelScheme" + }, + "type": "array" + }, + "version": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "CamelArtifactExclusion": { + "required": [ + "groupId", + "artifactId" + ], + "properties": { + "artifactId": { + "type": "string" + }, + "groupId": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "CamelCatalog": { + "properties": { + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "apiVersion": { + "type": "string" + }, + "clusterName": { + "type": "string" + }, + "creationTimestamp": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Time" + }, + "deletionGracePeriodSeconds": { + "type": "integer" + }, + "deletionTimestamp": { + "$ref": "#/definitions/Time" + }, + "finalizers": { + "items": { + "type": "string" + }, + "type": "array" + }, + "generateName": { + "type": "string" + }, + "generation": { + "type": "integer" + }, + "initializers": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Initializers" + }, + "kind": { + "type": "string" + }, + "labels": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "ownerReferences": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/OwnerReference" + }, + "type": "array" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "spec": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/CamelCatalogSpec" + }, + "status": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/CamelCatalogStatus" + }, + "uid": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "CamelCatalogSpec": { + "required": [ + "version", + "artifacts" + ], + "properties": { + "artifacts": { + "patternProperties": { + ".*": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/CamelArtifact" + } + }, + "type": "object" + }, + "version": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "CamelCatalogStatus": { + "additionalProperties": false, + "type": "object" + }, + "CamelScheme": { + "required": [ + "id", + "passive", + "http" + ], + "properties": { + "http": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "passive": { + "type": "boolean" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Initializer": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Initializers": { + "required": [ + "pending" + ], + "properties": { + "pending": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Initializer" + }, + "type": "array" + }, + "result": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Status" + } + }, + "additionalProperties": false, + "type": "object" + }, + "OwnerReference": { + "required": [ + "apiVersion", + "kind", + "name", + "uid" + ], + "properties": { + "apiVersion": { + "type": "string" + }, + "blockOwnerDeletion": { + "type": "boolean" + }, + "controller": { + "type": "boolean" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "uid": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Status": { + "properties": { + "apiVersion": { + "type": "string" + }, + "code": { + "type": "integer" + }, + "continue": { + "type": "string" + }, + "details": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/StatusDetails" + }, + "kind": { + "type": "string" + }, + "message": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "StatusCause": { + "properties": { + "field": { + "type": "string" + }, + "message": { + "type": "string" + }, + "reason": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "StatusDetails": { + "properties": { + "causes": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/StatusCause" + }, + "type": "array" + }, + "group": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "retryAfterSeconds": { + "type": "integer" + }, + "uid": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Time": { + "additionalProperties": false, + "type": "object" + } + } +} \ No newline at end of file diff --git a/assets/json-schema/Integration.json b/assets/json-schema/Integration.json new file mode 100644 index 0000000000..e60c5f4e87 --- /dev/null +++ b/assets/json-schema/Integration.json @@ -0,0 +1,449 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Integration", + "definitions": { + "ConfigurationSpec": { + "required": [ + "type", + "value" + ], + "properties": { + "type": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Failure": { + "required": [ + "reason", + "time", + "recovery" + ], + "properties": { + "reason": { + "type": "string" + }, + "recovery": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/FailureRecovery" + }, + "time": { + "$ref": "#/definitions/Time" + } + }, + "additionalProperties": false, + "type": "object" + }, + "FailureRecovery": { + "required": [ + "attempt", + "attemptMax", + "attemptTime" + ], + "properties": { + "attempt": { + "type": "integer" + }, + "attemptMax": { + "type": "integer" + }, + "attemptTime": { + "$ref": "#/definitions/Time" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Initializer": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Initializers": { + "required": [ + "pending" + ], + "properties": { + "pending": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Initializer" + }, + "type": "array" + }, + "result": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Status" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Integration": { + "properties": { + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "apiVersion": { + "type": "string" + }, + "clusterName": { + "type": "string" + }, + "creationTimestamp": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Time" + }, + "deletionGracePeriodSeconds": { + "type": "integer" + }, + "deletionTimestamp": { + "$ref": "#/definitions/Time" + }, + "finalizers": { + "items": { + "type": "string" + }, + "type": "array" + }, + "generateName": { + "type": "string" + }, + "generation": { + "type": "integer" + }, + "initializers": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Initializers" + }, + "kind": { + "type": "string" + }, + "labels": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "ownerReferences": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/OwnerReference" + }, + "type": "array" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "spec": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/IntegrationSpec" + }, + "status": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/IntegrationStatus" + }, + "uid": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IntegrationSpec": { + "properties": { + "configuration": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/ConfigurationSpec" + }, + "type": "array" + }, + "context": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "profile": { + "type": "string" + }, + "replicas": { + "type": "integer" + }, + "repositories": { + "items": { + "type": "string" + }, + "type": "array" + }, + "resources": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/ResourceSpec" + }, + "type": "array" + }, + "serviceAccountName": { + "type": "string" + }, + "sources": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/SourceSpec" + }, + "type": "array" + }, + "traits": { + "patternProperties": { + ".*": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/IntegrationTraitSpec" + } + }, + "type": "object" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IntegrationStatus": { + "properties": { + "camelVersion": { + "type": "string" + }, + "context": { + "type": "string" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "digest": { + "type": "string" + }, + "failure": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Failure" + }, + "generatedSources": { + "items": { + "$ref": "#/definitions/SourceSpec" + }, + "type": "array" + }, + "image": { + "type": "string" + }, + "phase": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IntegrationTraitSpec": { + "properties": { + "configuration": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "additionalProperties": false, + "type": "object" + }, + "OwnerReference": { + "required": [ + "apiVersion", + "kind", + "name", + "uid" + ], + "properties": { + "apiVersion": { + "type": "string" + }, + "blockOwnerDeletion": { + "type": "boolean" + }, + "controller": { + "type": "boolean" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "uid": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ResourceSpec": { + "properties": { + "compression": { + "type": "boolean" + }, + "content": { + "type": "string" + }, + "contentRef": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "SourceSpec": { + "properties": { + "compression": { + "type": "boolean" + }, + "content": { + "type": "string" + }, + "contentRef": { + "type": "string" + }, + "language": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Status": { + "properties": { + "apiVersion": { + "type": "string" + }, + "code": { + "type": "integer" + }, + "continue": { + "type": "string" + }, + "details": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/StatusDetails" + }, + "kind": { + "type": "string" + }, + "message": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "StatusCause": { + "properties": { + "field": { + "type": "string" + }, + "message": { + "type": "string" + }, + "reason": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "StatusDetails": { + "properties": { + "causes": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/StatusCause" + }, + "type": "array" + }, + "group": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "retryAfterSeconds": { + "type": "integer" + }, + "uid": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Time": { + "additionalProperties": false, + "type": "object" + } + } +} \ No newline at end of file diff --git a/assets/json-schema/IntegrationContext.json b/assets/json-schema/IntegrationContext.json new file mode 100644 index 0000000000..f5453fdc99 --- /dev/null +++ b/assets/json-schema/IntegrationContext.json @@ -0,0 +1,403 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/IntegrationContext", + "definitions": { + "Artifact": { + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "location": { + "type": "string" + }, + "target": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "ConfigurationSpec": { + "required": [ + "type", + "value" + ], + "properties": { + "type": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Failure": { + "required": [ + "reason", + "time", + "recovery" + ], + "properties": { + "reason": { + "type": "string" + }, + "recovery": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/FailureRecovery" + }, + "time": { + "$ref": "#/definitions/Time" + } + }, + "additionalProperties": false, + "type": "object" + }, + "FailureRecovery": { + "required": [ + "attempt", + "attemptMax", + "attemptTime" + ], + "properties": { + "attempt": { + "type": "integer" + }, + "attemptMax": { + "type": "integer" + }, + "attemptTime": { + "$ref": "#/definitions/Time" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Initializer": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Initializers": { + "required": [ + "pending" + ], + "properties": { + "pending": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Initializer" + }, + "type": "array" + }, + "result": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Status" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IntegrationContext": { + "properties": { + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "apiVersion": { + "type": "string" + }, + "clusterName": { + "type": "string" + }, + "creationTimestamp": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Time" + }, + "deletionGracePeriodSeconds": { + "type": "integer" + }, + "deletionTimestamp": { + "$ref": "#/definitions/Time" + }, + "finalizers": { + "items": { + "type": "string" + }, + "type": "array" + }, + "generateName": { + "type": "string" + }, + "generation": { + "type": "integer" + }, + "initializers": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Initializers" + }, + "kind": { + "type": "string" + }, + "labels": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "ownerReferences": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/OwnerReference" + }, + "type": "array" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "spec": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/IntegrationContextSpec" + }, + "status": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/IntegrationContextStatus" + }, + "uid": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IntegrationContextSpec": { + "properties": { + "configuration": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/ConfigurationSpec" + }, + "type": "array" + }, + "dependencies": { + "items": { + "type": "string" + }, + "type": "array" + }, + "image": { + "type": "string" + }, + "profile": { + "type": "string" + }, + "repositories": { + "items": { + "type": "string" + }, + "type": "array" + }, + "traits": { + "patternProperties": { + ".*": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/IntegrationTraitSpec" + } + }, + "type": "object" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IntegrationContextStatus": { + "properties": { + "artifacts": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Artifact" + }, + "type": "array" + }, + "baseImage": { + "type": "string" + }, + "camelVersion": { + "type": "string" + }, + "digest": { + "type": "string" + }, + "failure": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Failure" + }, + "image": { + "type": "string" + }, + "phase": { + "type": "string" + }, + "publicImage": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IntegrationTraitSpec": { + "properties": { + "configuration": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + } + }, + "additionalProperties": false, + "type": "object" + }, + "OwnerReference": { + "required": [ + "apiVersion", + "kind", + "name", + "uid" + ], + "properties": { + "apiVersion": { + "type": "string" + }, + "blockOwnerDeletion": { + "type": "boolean" + }, + "controller": { + "type": "boolean" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "uid": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Status": { + "properties": { + "apiVersion": { + "type": "string" + }, + "code": { + "type": "integer" + }, + "continue": { + "type": "string" + }, + "details": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/StatusDetails" + }, + "kind": { + "type": "string" + }, + "message": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "StatusCause": { + "properties": { + "field": { + "type": "string" + }, + "message": { + "type": "string" + }, + "reason": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "StatusDetails": { + "properties": { + "causes": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/StatusCause" + }, + "type": "array" + }, + "group": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "retryAfterSeconds": { + "type": "integer" + }, + "uid": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Time": { + "additionalProperties": false, + "type": "object" + } + } +} \ No newline at end of file diff --git a/assets/json-schema/IntegrationPlatform.json b/assets/json-schema/IntegrationPlatform.json new file mode 100644 index 0000000000..25694d77f2 --- /dev/null +++ b/assets/json-schema/IntegrationPlatform.json @@ -0,0 +1,321 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/IntegrationPlatform", + "definitions": { + "Initializer": { + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Initializers": { + "required": [ + "pending" + ], + "properties": { + "pending": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Initializer" + }, + "type": "array" + }, + "result": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Status" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IntegrationPlatform": { + "properties": { + "annotations": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "apiVersion": { + "type": "string" + }, + "clusterName": { + "type": "string" + }, + "creationTimestamp": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Time" + }, + "deletionGracePeriodSeconds": { + "type": "integer" + }, + "deletionTimestamp": { + "$ref": "#/definitions/Time" + }, + "finalizers": { + "items": { + "type": "string" + }, + "type": "array" + }, + "generateName": { + "type": "string" + }, + "generation": { + "type": "integer" + }, + "initializers": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Initializers" + }, + "kind": { + "type": "string" + }, + "labels": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "ownerReferences": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/OwnerReference" + }, + "type": "array" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "spec": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/IntegrationPlatformSpec" + }, + "status": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/IntegrationPlatformStatus" + }, + "uid": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IntegrationPlatformBuildSpec": { + "properties": { + "baseImage": { + "type": "string" + }, + "camelVersion": { + "type": "string" + }, + "localRepository": { + "type": "string" + }, + "organization": { + "type": "string" + }, + "properties": { + "patternProperties": { + ".*": { + "type": "string" + } + }, + "type": "object" + }, + "publishStrategy": { + "type": "string" + }, + "pushSecret": { + "type": "string" + }, + "registry": { + "type": "string" + }, + "repositories": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IntegrationPlatformResourcesSpec": { + "properties": { + "contexts": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IntegrationPlatformSpec": { + "properties": { + "build": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/IntegrationPlatformBuildSpec" + }, + "cluster": { + "type": "string" + }, + "profile": { + "type": "string" + }, + "resources": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/IntegrationPlatformResourcesSpec" + } + }, + "additionalProperties": false, + "type": "object" + }, + "IntegrationPlatformStatus": { + "properties": { + "phase": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "OwnerReference": { + "required": [ + "apiVersion", + "kind", + "name", + "uid" + ], + "properties": { + "apiVersion": { + "type": "string" + }, + "blockOwnerDeletion": { + "type": "boolean" + }, + "controller": { + "type": "boolean" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "uid": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Status": { + "properties": { + "apiVersion": { + "type": "string" + }, + "code": { + "type": "integer" + }, + "continue": { + "type": "string" + }, + "details": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/StatusDetails" + }, + "kind": { + "type": "string" + }, + "message": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "resourceVersion": { + "type": "string" + }, + "selfLink": { + "type": "string" + }, + "status": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "StatusCause": { + "properties": { + "field": { + "type": "string" + }, + "message": { + "type": "string" + }, + "reason": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "StatusDetails": { + "properties": { + "causes": { + "items": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/StatusCause" + }, + "type": "array" + }, + "group": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "name": { + "type": "string" + }, + "retryAfterSeconds": { + "type": "integer" + }, + "uid": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, + "Time": { + "additionalProperties": false, + "type": "object" + } + } +} \ No newline at end of file diff --git a/cmd/util/json-schema-gen/jsonschemagen.go b/cmd/util/json-schema-gen/jsonschemagen.go new file mode 100644 index 0000000000..adb77a90eb --- /dev/null +++ b/cmd/util/json-schema-gen/jsonschemagen.go @@ -0,0 +1,73 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one or more +contributor license agreements. See the NOTICE file distributed with +this work for additional information regarding copyright ownership. +The ASF licenses this file to You under the Apache License, Version 2.0 +(the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "os" + "path" + "reflect" + + "github.com/alecthomas/jsonschema" + "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" + "github.com/spf13/cobra" +) + +// Publishes predefined images for all Camel components +func main() { + sources := []interface{}{ + v1alpha1.Integration{}, + v1alpha1.IntegrationContext{}, + v1alpha1.IntegrationPlatform{}, + v1alpha1.CamelCatalog{}, + } + + var out string + + var cmd = cobra.Command{ + Use: "jsonschemagen --out=${path}", + Run: func(_ *cobra.Command, _ []string) { + for _, source := range sources { + //pin + source := source + + schema := jsonschema.Reflect(source) + b, err := json.MarshalIndent(schema, "", " ") + if err != nil { + fmt.Println("error:", err) + } + + v := reflect.ValueOf(source) + t := reflect.Indirect(v).Type().Name() + o := path.Join(out, t+".json") + + fmt.Println("Write", t, "json-schema to:", o) + ioutil.WriteFile(o, b, 0644) + } + }, + } + + cmd.Flags().StringVar(&out, "out", ".", "the path where to generate the json schema for cr") + + if err := cmd.Execute(); err != nil { + fmt.Println("error:", err) + os.Exit(-1) + } +} diff --git a/script/Makefile b/script/Makefile index f86bed3008..c5aaef8717 100644 --- a/script/Makefile +++ b/script/Makefile @@ -15,6 +15,8 @@ build-embed-resources: ./script/build_catalog.sh ./script/build_catalog.sh 2.23.0 ./script/embed_resources.sh deploy + mkdir -p ./assets/json-schema + go run cmd/util/json-schema-gen/jsonschemagen.go --out=./assets/json-schema build-compile-integration-tests: go test -c -tags=integration ./test/*.go diff --git a/vendor/github.com/alecthomas/jsonschema/COPYING b/vendor/github.com/alecthomas/jsonschema/COPYING new file mode 100644 index 0000000000..2993ec085d --- /dev/null +++ b/vendor/github.com/alecthomas/jsonschema/COPYING @@ -0,0 +1,19 @@ +Copyright (C) 2014 Alec Thomas + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/alecthomas/jsonschema/reflect.go b/vendor/github.com/alecthomas/jsonschema/reflect.go new file mode 100644 index 0000000000..bbeedc3c6d --- /dev/null +++ b/vendor/github.com/alecthomas/jsonschema/reflect.go @@ -0,0 +1,460 @@ +// Package jsonschema uses reflection to generate JSON Schemas from Go types [1]. +// +// If json tags are present on struct fields, they will be used to infer +// property names and if a property is required (omitempty is present). +// +// [1] http://json-schema.org/latest/json-schema-validation.html +package jsonschema + +import ( + "encoding/json" + "net" + "net/url" + "reflect" + "strconv" + "strings" + "time" +) + +// Version is the JSON Schema version. +// If extending JSON Schema with custom values use a custom URI. +// RFC draft-wright-json-schema-00, section 6 +var Version = "http://json-schema.org/draft-04/schema#" + +// Schema is the root schema. +// RFC draft-wright-json-schema-00, section 4.5 +type Schema struct { + *Type + Definitions Definitions `json:"definitions,omitempty"` +} + +// Type represents a JSON Schema object type. +type Type struct { + // RFC draft-wright-json-schema-00 + Version string `json:"$schema,omitempty"` // section 6.1 + Ref string `json:"$ref,omitempty"` // section 7 + // RFC draft-wright-json-schema-validation-00, section 5 + MultipleOf int `json:"multipleOf,omitempty"` // section 5.1 + Maximum int `json:"maximum,omitempty"` // section 5.2 + ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"` // section 5.3 + Minimum int `json:"minimum,omitempty"` // section 5.4 + ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty"` // section 5.5 + MaxLength int `json:"maxLength,omitempty"` // section 5.6 + MinLength int `json:"minLength,omitempty"` // section 5.7 + Pattern string `json:"pattern,omitempty"` // section 5.8 + AdditionalItems *Type `json:"additionalItems,omitempty"` // section 5.9 + Items *Type `json:"items,omitempty"` // section 5.9 + MaxItems int `json:"maxItems,omitempty"` // section 5.10 + MinItems int `json:"minItems,omitempty"` // section 5.11 + UniqueItems bool `json:"uniqueItems,omitempty"` // section 5.12 + MaxProperties int `json:"maxProperties,omitempty"` // section 5.13 + MinProperties int `json:"minProperties,omitempty"` // section 5.14 + Required []string `json:"required,omitempty"` // section 5.15 + Properties map[string]*Type `json:"properties,omitempty"` // section 5.16 + PatternProperties map[string]*Type `json:"patternProperties,omitempty"` // section 5.17 + AdditionalProperties json.RawMessage `json:"additionalProperties,omitempty"` // section 5.18 + Dependencies map[string]*Type `json:"dependencies,omitempty"` // section 5.19 + Enum []interface{} `json:"enum,omitempty"` // section 5.20 + Type string `json:"type,omitempty"` // section 5.21 + AllOf []*Type `json:"allOf,omitempty"` // section 5.22 + AnyOf []*Type `json:"anyOf,omitempty"` // section 5.23 + OneOf []*Type `json:"oneOf,omitempty"` // section 5.24 + Not *Type `json:"not,omitempty"` // section 5.25 + Definitions Definitions `json:"definitions,omitempty"` // section 5.26 + // RFC draft-wright-json-schema-validation-00, section 6, 7 + Title string `json:"title,omitempty"` // section 6.1 + Description string `json:"description,omitempty"` // section 6.1 + Default interface{} `json:"default,omitempty"` // section 6.2 + Format string `json:"format,omitempty"` // section 7 + // RFC draft-wright-json-schema-hyperschema-00, section 4 + Media *Type `json:"media,omitempty"` // section 4.3 + BinaryEncoding string `json:"binaryEncoding,omitempty"` // section 4.3 +} + +// Reflect reflects to Schema from a value using the default Reflector +func Reflect(v interface{}) *Schema { + return ReflectFromType(reflect.TypeOf(v)) +} + +// ReflectFromType generates root schema using the default Reflector +func ReflectFromType(t reflect.Type) *Schema { + r := &Reflector{} + return r.ReflectFromType(t) +} + +// A Reflector reflects values into a Schema. +type Reflector struct { + // AllowAdditionalProperties will cause the Reflector to generate a schema + // with additionalProperties to 'true' for all struct types. This means + // the presence of additional keys in JSON objects will not cause validation + // to fail. Note said additional keys will simply be dropped when the + // validated JSON is unmarshaled. + AllowAdditionalProperties bool + + // RequiredFromJSONSchemaTags will cause the Reflector to generate a schema + // that requires any key tagged with `jsonschema:required`, overriding the + // default of requiring any key *not* tagged with `json:,omitempty`. + RequiredFromJSONSchemaTags bool + + // ExpandedStruct will cause the toplevel definitions of the schema not + // be referenced itself to a definition. + ExpandedStruct bool +} + +// Reflect reflects to Schema from a value. +func (r *Reflector) Reflect(v interface{}) *Schema { + return r.ReflectFromType(reflect.TypeOf(v)) +} + +// ReflectFromType generates root schema +func (r *Reflector) ReflectFromType(t reflect.Type) *Schema { + definitions := Definitions{} + if r.ExpandedStruct { + st := &Type{ + Version: Version, + Type: "object", + Properties: map[string]*Type{}, + AdditionalProperties: []byte("false"), + } + if r.AllowAdditionalProperties { + st.AdditionalProperties = []byte("true") + } + r.reflectStructFields(st, definitions, t) + r.reflectStruct(definitions, t) + delete(definitions, t.Name()) + return &Schema{Type: st, Definitions: definitions} + } + + s := &Schema{ + Type: r.reflectTypeToSchema(definitions, t), + Definitions: definitions, + } + return s +} + +// Definitions hold schema definitions. +// http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.26 +// RFC draft-wright-json-schema-validation-00, section 5.26 +type Definitions map[string]*Type + +// Available Go defined types for JSON Schema Validation. +// RFC draft-wright-json-schema-validation-00, section 7.3 +var ( + timeType = reflect.TypeOf(time.Time{}) // date-time RFC section 7.3.1 + ipType = reflect.TypeOf(net.IP{}) // ipv4 and ipv6 RFC section 7.3.4, 7.3.5 + uriType = reflect.TypeOf(url.URL{}) // uri RFC section 7.3.6 +) + +// Byte slices will be encoded as base64 +var byteSliceType = reflect.TypeOf([]byte(nil)) + +// Go code generated from protobuf enum types should fulfil this interface. +type protoEnum interface { + EnumDescriptor() ([]byte, []int) +} + +var protoEnumType = reflect.TypeOf((*protoEnum)(nil)).Elem() + +func (r *Reflector) reflectTypeToSchema(definitions Definitions, t reflect.Type) *Type { + // Already added to definitions? + if _, ok := definitions[t.Name()]; ok { + return &Type{Ref: "#/definitions/" + t.Name()} + } + + // jsonpb will marshal protobuf enum options as either strings or integers. + // It will unmarshal either. + if t.Implements(protoEnumType) { + return &Type{OneOf: []*Type{ + {Type: "string"}, + {Type: "integer"}, + }} + } + + // Defined format types for JSON Schema Validation + // RFC draft-wright-json-schema-validation-00, section 7.3 + // TODO email RFC section 7.3.2, hostname RFC section 7.3.3, uriref RFC section 7.3.7 + switch t { + case ipType: + // TODO differentiate ipv4 and ipv6 RFC section 7.3.4, 7.3.5 + return &Type{Type: "string", Format: "ipv4"} // ipv4 RFC section 7.3.4 + } + + switch t.Kind() { + case reflect.Struct: + + switch t { + case timeType: // date-time RFC section 7.3.1 + return &Type{Type: "string", Format: "date-time"} + case uriType: // uri RFC section 7.3.6 + return &Type{Type: "string", Format: "uri"} + default: + return r.reflectStruct(definitions, t) + } + + case reflect.Map: + rt := &Type{ + Type: "object", + PatternProperties: map[string]*Type{ + ".*": r.reflectTypeToSchema(definitions, t.Elem()), + }, + } + delete(rt.PatternProperties, "additionalProperties") + return rt + + case reflect.Slice, reflect.Array: + returnType := &Type{} + if t.Kind() == reflect.Array { + returnType.MinItems = t.Len() + returnType.MaxItems = returnType.MinItems + } + switch t { + case byteSliceType: + returnType.Type = "string" + returnType.Media = &Type{BinaryEncoding: "base64"} + return returnType + default: + returnType.Type = "array" + returnType.Items = r.reflectTypeToSchema(definitions, t.Elem()) + return returnType + } + + case reflect.Interface: + return &Type{ + Type: "object", + AdditionalProperties: []byte("true"), + } + + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return &Type{Type: "integer"} + + case reflect.Float32, reflect.Float64: + return &Type{Type: "number"} + + case reflect.Bool: + return &Type{Type: "boolean"} + + case reflect.String: + return &Type{Type: "string"} + + case reflect.Ptr: + return r.reflectTypeToSchema(definitions, t.Elem()) + } + panic("unsupported type " + t.String()) +} + +// Refects a struct to a JSON Schema type. +func (r *Reflector) reflectStruct(definitions Definitions, t reflect.Type) *Type { + st := &Type{ + Type: "object", + Properties: map[string]*Type{}, + AdditionalProperties: []byte("false"), + } + if r.AllowAdditionalProperties { + st.AdditionalProperties = []byte("true") + } + definitions[t.Name()] = st + r.reflectStructFields(st, definitions, t) + + return &Type{ + Version: Version, + Ref: "#/definitions/" + t.Name(), + } +} + +func (r *Reflector) reflectStructFields(st *Type, definitions Definitions, t reflect.Type) { + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + // anonymous and exported type should be processed recursively + // current type should inherit properties of anonymous one + if f.Anonymous && f.PkgPath == "" { + r.reflectStructFields(st, definitions, f.Type) + continue + } + + name, required := r.reflectFieldName(f) + if name == "" { + continue + } + property := r.reflectTypeToSchema(definitions, f.Type) + property.structKeywordsFromTags(f) + st.Properties[name] = property + if required { + st.Required = append(st.Required, name) + } + } +} + +func (t *Type) structKeywordsFromTags(f reflect.StructField) { + tags := strings.Split(f.Tag.Get("jsonschema"), ",") + switch t.Type { + case "string": + t.stringKeywords(tags) + case "number": + t.numbericKeywords(tags) + case "integer": + t.numbericKeywords(tags) + case "array": + t.arrayKeywords(tags) + } +} + +// read struct tags for string type keyworks +func (t *Type) stringKeywords(tags []string) { + for _, tag := range tags { + nameValue := strings.Split(tag, "=") + if len(nameValue) == 2 { + name, val := nameValue[0], nameValue[1] + switch name { + case "minLength": + i, _ := strconv.Atoi(val) + t.MinLength = i + case "maxLength": + i, _ := strconv.Atoi(val) + t.MaxLength = i + case "pattern": + t.Pattern = val + case "format": + switch val { + case "date-time", "email", "hostname", "ipv4", "ipv6", "uri": + t.Format = val + break + } + } + } + } +} + +// read struct tags for numberic type keyworks +func (t *Type) numbericKeywords(tags []string) { + for _, tag := range tags { + nameValue := strings.Split(tag, "=") + if len(nameValue) == 2 { + name, val := nameValue[0], nameValue[1] + switch name { + case "multipleOf": + i, _ := strconv.Atoi(val) + t.MultipleOf = i + case "minimum": + i, _ := strconv.Atoi(val) + t.Minimum = i + case "maximum": + i, _ := strconv.Atoi(val) + t.Maximum = i + case "exclusiveMaximum": + b, _ := strconv.ParseBool(val) + t.ExclusiveMaximum = b + case "exclusiveMinimum": + b, _ := strconv.ParseBool(val) + t.ExclusiveMinimum = b + } + } + } +} + +// read struct tags for object type keyworks +// func (t *Type) objectKeywords(tags []string) { +// for _, tag := range tags{ +// nameValue := strings.Split(tag, "=") +// name, val := nameValue[0], nameValue[1] +// switch name{ +// case "dependencies": +// t.Dependencies = val +// break; +// case "patternProperties": +// t.PatternProperties = val +// break; +// } +// } +// } + +// read struct tags for array type keyworks +func (t *Type) arrayKeywords(tags []string) { + for _, tag := range tags { + nameValue := strings.Split(tag, "=") + if len(nameValue) == 2 { + name, val := nameValue[0], nameValue[1] + switch name { + case "minItems": + i, _ := strconv.Atoi(val) + t.MinItems = i + case "maxItems": + i, _ := strconv.Atoi(val) + t.MaxItems = i + case "uniqueItems": + t.UniqueItems = true + } + } + } +} + +func requiredFromJSONTags(tags []string) bool { + if ignoredByJSONTags(tags) { + return false + } + + for _, tag := range tags[1:] { + if tag == "omitempty" { + return false + } + } + return true +} + +func requiredFromJSONSchemaTags(tags []string) bool { + if ignoredByJSONSchemaTags(tags) { + return false + } + for _, tag := range tags { + if tag == "required" { + return true + } + } + return false +} + +func ignoredByJSONTags(tags []string) bool { + return tags[0] == "-" +} + +func ignoredByJSONSchemaTags(tags []string) bool { + return tags[0] == "-" +} + +func (r *Reflector) reflectFieldName(f reflect.StructField) (string, bool) { + if f.PkgPath != "" { // unexported field, ignore it + return "", false + } + + jsonTags, exist := f.Tag.Lookup("json") + if !exist { + jsonTags = f.Tag.Get("yaml") + } + + jsonTagsList := strings.Split(jsonTags, ",") + + if ignoredByJSONTags(jsonTagsList) { + return "", false + } + + jsonSchemaTags := strings.Split(f.Tag.Get("jsonschema"), ",") + if ignoredByJSONSchemaTags(jsonSchemaTags) { + return "", false + } + + name := f.Name + required := requiredFromJSONTags(jsonTagsList) + + if r.RequiredFromJSONSchemaTags { + required = requiredFromJSONSchemaTags(jsonSchemaTags) + } + + if jsonTagsList[0] != "" { + name = jsonTagsList[0] + } + + return name, required +}