github.com/mmatczuk/gohan@v0.0.0-20170206152520-30e45d9bdb69/docs/schema.md (about) 1 # Schema 2 3 Developers defines resource model itself, and Gohan derives APIs, CLIs, and Docs from it. It is a so-called model-based development and conceptual difference from OpenAPI where developers define API. 4 5 We will have a list of schemas to define a resource model. 6 Each schema will have following properties. 7 8 - id -- resource id (must be unique) 9 - singular -- a singular form of the schema name 10 - plural -- plural form of the schema name 11 - title -- use the visible label of resource title 12 - description -- a description of the schema 13 - schema -- JSON schema (see Spec on http://json-schema.org/) 14 15 Schemas might also have any of the following optional properties. 16 17 - parent -- the id of the parent schema 18 - on_parent_delete_cascade -- cascading delete when parent resource deleted 19 - namespace -- resource namespace for grouping 20 - prefix -- resource path prefix 21 - metadata -- application specific schema metadata (object) 22 - type -- can be an abstract or empty string (see more in schema inheritance) 23 - extends -- list of base schemas 24 25 ## Schema Inheritance 26 27 Gohan supports mix-in of multiple schemas. 28 Developers can make a schema as abstract schema specifying type=abstract. The developer can mix-in abstract schema. 29 30 ``` 31 schemas: 32 - description: base 33 type: abstract 34 id: base 35 metadata: 36 state_versioning: true 37 plural: bases 38 prefix: /v2.0 39 schema: 40 properties: 41 description: 42 description: Description 43 default: "" 44 permission: 45 - create 46 - update 47 title: Description 48 type: string 49 unique: false 50 id: 51 description: ID 52 permission: 53 - create 54 title: ID 55 type: string 56 unique: false 57 name: 58 description: Name 59 permission: 60 - create 61 - update 62 title: Name 63 type: string 64 unique: false 65 tenant_id: 66 description: Tenant ID 67 permission: 68 - create 69 title: Tenant 70 type: string 71 unique: false 72 propertiesOrder: 73 - id 74 - name 75 - description 76 - tenant_id 77 type: object 78 singular: base 79 title: base 80 - description: Network 81 id: network 82 extends: 83 - base 84 plural: networks 85 schema: 86 properties: 87 providor_networks: 88 description: Providor networks 89 default: {} 90 permission: 91 - create 92 - update 93 properties: 94 segmentaion_type: 95 enum: 96 - vlan 97 - vxlan 98 - gre 99 type: string 100 segmentation_id: 101 minimum: 0 102 type: integer 103 title: Provider Networks 104 type: object 105 unique: false 106 route_targets: 107 description: Route targets 108 default: [] 109 items: 110 type: string 111 permission: 112 - create 113 - update 114 title: RouteTargets 115 type: array 116 unique: false 117 shared: 118 description: Shared 119 permission: 120 - create 121 - update 122 title: Shared 123 type: boolean 124 unique: false 125 default: false 126 propertiesOrder: 127 - providor_networks 128 - route_targets 129 - shared 130 type: object 131 singular: network 132 title: Network 133 ``` 134 135 ## Metadata 136 137 - nosync (boolean) 138 139 We don't sync this resource for sync backend when this option is true. 140 141 - state_versioning (boolean) 142 143 whether to support state versioning <subsection-state-update>, defaults to false. 144 145 - sync_key_template (string) 146 147 configurable sync key path for schemas based on properties, for example: /v1.0/devices/{{device_id}}/virtual_machine/{{id}}, 148 149 - sync_plain (boolean) 150 151 Write plain data, which is not JSON marshaled in the Gohan format, to the sync backend if true. 152 By default, which is false, Gohan writes sync data in JSON with its own format. The format has `body` and `version` properties, then the value of the resource, which is also JSON object, is stored in the `body` property with escaping (e.g. `{"body": "{\"id\":1,\"property\":\"value\"}", "version": 1}`). 153 However, this format is not always supported by your worker. Therefore you sometimes want Gohan to write sync data in a simpler way. This option allow you to get the body JSON data without encapsulation by Gohan (e.g. `{"id":1,"property":"value"}`). 154 Note that when you use this option with `sync_property`, you can get the value of a specified property. For instance, when you provide `property` to `sync_property`, you will get `value` for the result. In this case, when the type of the value is `string`, Gohan doesn't marshal the value into a JSON string, which means you don't get `"value"` here. When the value is an array or an object, you will get a JSON marshalled string. 155 156 - sync_property (string) 157 158 Write only the value of the specified property to the sync backend. 159 160 ## Properties 161 162 We need to define properties of a resource using following parameters. 163 164 - title 165 166 User visible label of the property 167 168 - format 169 170 Additional validation hints for this property 171 you can use defined attribute on http://json-schema.org/latest/json-schema-validation.html#anchor107 172 173 - type 174 175 Gohan supports standard JSON schema types including string, number, integer, boolean, array, object and combinations such as ["string", "null"] 176 The Schema itself should be the object type. 177 178 - default 179 180 the default value of the property 181 182 - enum 183 184 You can specify list of allowed values 185 186 - required 187 188 List of required attributes to specified during creation 189 190 191 Following properties are extended from JSON schema v4. 192 193 - permission 194 195 permission is a list of allowing actions for this property. 196 valid values contains "create", "update". 197 Gohan generates JSON schema for creating API and update API based on this value. 198 Note that we can use this property for only first level properties. 199 200 - unique boolean (unique key constraint) 201 202 - indexed boolean 203 204 Specify if index should be created in DB for given column 205 206 ## type string 207 208 type string is for defining a string. 209 You can use following parameters for a string. 210 211 - minLength max length of string 212 - maxLength min length of string 213 - pattern regexp pattern for this string 214 - relation (extended spec by Gohan) define resource relation 215 - relationColumn (extended spec by Gohan) define which column relation references (default: "id") 216 - relation_property (extended spec by Gohan) relation resource will be joined in list API request for this property name 217 - on_delete_cascade (extended spec by Gohan) cascading delete when related resource deleted 218 219 eg. 220 ``` 221 name: 222 permission: 223 - create 224 - update 225 title: Name 226 type: string 227 unique: false 228 ``` 229 230 ## type boolean 231 232 type boolean for boolean value 233 234 eg. 235 236 ``` 237 admin_state: 238 permission: 239 - create 240 - update 241 title: admin_state 242 type: boolean 243 unique: false 244 ``` 245 246 ## type integer or type number 247 248 type integer or type number for numeric properties. 249 You can use following parameters to define valid range 250 251 - maximum (number) and exclusiveMaximum (boolean) 252 - minimum (number) and exclusiveMinimum (boolean) 253 254 eg. 255 256 ``` 257 age: 258 permission: 259 - create 260 - update 261 title: age 262 type: number 263 unique: false 264 ``` 265 266 ## type array 267 268 type array is for a defining list of elements 269 270 ### items 271 272 Only allowed for array type 273 You can define element type on this property. 274 275 eg. 276 277 ``` 278 route_targets: 279 default: [] 280 items: 281 type: string 282 permission: 283 - create 284 - update 285 title: RouteTargets 286 type: array 287 unique: false 288 ``` 289 290 ## type object 291 292 Object type is for a defining object in the resources. 293 Note that resource itself should be an object. 294 Following parameters supported in the object type. 295 296 - properties 297 298 Only allowed for object type 299 You can define properties of this object 300 301 - propertiesOrder (extended parameter in gohan) 302 303 Only allowed for object type 304 You can define an ordering of properties using propertiesOrder for UI / CLI 305 306 eg. 307 308 ``` 309 providor_networks: 310 default: {} 311 permission: 312 - create 313 - update 314 properties: 315 segmentaion_type: 316 enum: 317 - vlan 318 - vxlan 319 - gre 320 type: string 321 segmentation_id: 322 minimum: 0 323 type: integer 324 required: 325 - segmentation_type 326 - segmentation_id 327 title: Provider Networks 328 type: object 329 unique: false 330 ``` 331 332 Parent - child relationship 333 ------------------------------- 334 335 Resources can be in a parent-child relationship. It means that the child resource has a foreign key to its parent, and utilized for UI and CLI. 336 337 Gohan adds <parent>_id property automatically when Gohan loads schemas. 338 339 eg. 340 341 ``` 342 schemas: 343 - description: Test Device 344 id: test_device 345 parent: "" 346 singular: test_device 347 plural: test_devices 348 prefix: /v1.0 349 schema: 350 properties: 351 name: 352 default: "" 353 permission: 354 - create 355 - update 356 title: Name 357 type: string 358 unique: false 359 id: 360 permission: 361 - create 362 title: ID 363 type: string 364 format: uuid 365 required: 366 - segmentation_type 367 - segmentation_id 368 type: object 369 title: Test Device 370 - description: Test Physical Port 371 id: test_port 372 parent: "test_device" 373 singular: test_port 374 plural: test_ports 375 prefix: /v1.0 376 schema: 377 properties: 378 name: 379 default: "" 380 permission: 381 - create 382 - update 383 title: Name 384 type: string 385 unique: false 386 id: 387 permission: 388 - create 389 title: ID 390 type: string 391 format: uuid 392 type: object 393 title: Test Physical Port 394 ``` 395 396 ## Custom actions schema 397 398 Resources can have custom actions, besides CRUD. To define them, add "actions" section and define JSON schema of allowed input format 399 400 eg. 401 402 ``` 403 schemas: 404 - description: Server 405 id: server 406 parent: "" 407 singular: server 408 plural: server 409 prefix: /v1.0 410 schema: 411 properties: 412 name: 413 default: "" 414 permission: 415 - create 416 - update 417 title: Name 418 type: string 419 unique: false 420 management_ip: 421 default: "" 422 format: ipv4 423 permission: 424 - create 425 - update 426 title: Management IP 427 type: string 428 unique: false 429 id: 430 permission: 431 - create 432 title: ID 433 type: string 434 format: uuid 435 actions: 436 reboot: 437 path: /:id/reboot 438 method: POST 439 input: 440 type: object 441 properties: 442 message: 443 type: string 444 delay: 445 type: string 446 output: null 447 ``` 448 449 Then, register extension to handle it, e.g. 450 451 ``` 452 gohan_register_handler("action_reboot", function(context){ 453 // handle reboot in southbound 454 }); 455 ``` 456 457 In order to query above action, POST to /v1.0/servers/:id/action with 458 459 ``` 460 { 461 "reboot": { 462 "message": "Maintenance", 463 "delay": "1h" 464 } 465 } 466 ``` 467 468 ## Custom Isolation Level 469 470 Developers can specify the transaction isolation level for API requests when Gohan is configured to connect MySQL database. 471 The default setting is "read repeatable" for read operations and "serializable" for operations that modify the database (create, update, delete) and sync operation. (state_update, monitoring_update). The default for unspecified action is repeatable read. 472 473 ``` 474 isolation_level: 475 read: REPEATABLE READ 476 create: SERIALIZABLE 477 update: SERIALIZABLE 478 delete: SERIALIZABLE 479 ``` 480 481 ## OpenAPI / Swagger 482 483 Gohan schema is supposed to define "Data Model," whereas OpenAPI/Swagger is supposed to define API. 484 485 You can generate OpenAPI / Swagger file from Gohan schema so that you can afford swagger utility tools. 486 487 ``` 488 489 gohan openapi --config-file etc/gohan.yaml 490 491 # or you can customize template file using 492 493 gohan openapi --config-file etc/gohan.yaml --template etc/templates/swagger.tmpl 494 ``` 495 496 then you will get swagger.json. 497 You can use this file for using swagger utility tools. 498 499 For example, you can use go-swagger to generate go related code. (see http://goswagger.io/) 500 501 ``` 502 $ swagger validate swagger.json 503 The swagger spec at "swagger.json" is valid against swagger specification 2.0 504 ``` 505 506 # API 507 508 In this section, we show how we generate REST API based on a schema. 509 510 "$plural", "$singular", "$prefix" and "$id" are read directly from schema, 511 "$namespace_prefix" is computed using namespace information and might be empty if schema has no namespace specified. 512 513 Note: An extension computes actual access URL for each resource and substitutes prefix property with it during schema listing calls. User can list resources using this URL and access a single instance of resource by prepending "/$id" 514 suffix. 515 516 ## List REST API 517 518 List supports pagination by optional GET query parameters ``sort_key`` and ``sort_order``. 519 520 Query Parameter Style Type Default Description 521 sort_key query xsd:string id Sort key for results 522 sort_order query xsd:string asc Sort order - allowed values are ``asc`` or ``desc`` 523 limit query xsd:int 0 Specifies maximum number of results. 524 Unlimited for non-positive values 525 offset query xsd:int 0 Specifies number of results to be skipped 526 <parent>_id query xsd:string N/A When resources which have a parent are listed, 527 <parent>_id can be specified to show only parent's children. 528 <property_id> query xsd:string N/A filter result by property (exact match). You can use multiple filters. 529 530 When specified query parameters are invalid, server will return HTTP Status Code ``400`` (Bad Request) 531 with an error message explaining the problem. 532 533 To make navigation easier, each ``List`` response contains additional header ``X-Total-Count`` 534 indicating number of all elements without applying ``limit`` or ``offset``. 535 536 Example: 537 GET http://$GOHAN/[$namespace_prefix/]$prefix/$plural?sort_key=name&limit=2 538 539 Response will be 540 541 HTTP Status Code: 200 542 543 ``` 544 545 { 546 "$plural": [ 547 { 548 "attr1": XX, 549 "attr2": XX 550 } 551 ] 552 } 553 554 ``` 555 556 ### Child resources access 557 558 Gohan provides two paths for child resources. 559 560 Full path 561 To access a child resource in that way, we need to know all it parents. 562 563 e.g. POST http://$GOHAN/[$namespace_prefix/]$prefix/[$ancestor_plural/$ancestor_id/]$plural 564 565 Short path 566 567 e.g. POST http://$GOHAN/[$namespace_prefix/]$prefix/$plural?$parent_id=<parent_id> 568 569 ## GET 570 571 Show REST API 572 573 GET http://$GOHAN/[$namespace_prefix/]$prefix/$plural/$id 574 575 Response will be 576 577 HTTP Status Code: 200 578 579 ``` 580 { 581 "$singular": { 582 "attr1": XX, 583 "attr2": XX 584 } 585 } 586 ``` 587 588 ## CREATE 589 590 CREATE Resource REST API 591 592 POST http://$GOHAN/[$namespace_prefix/]$prefix/$plural/ 593 594 Input 595 596 Note that input JSON can only contain if you set "create" permission for this 597 598 HTTP Status Code: 202 599 600 ``` 601 { 602 "$singular": { 603 "attr1": XX, 604 "attr2": XX 605 } 606 } 607 ``` 608 609 Response will be 610 611 ``` 612 { 613 "$singular": { 614 "attr1": XX, 615 "attr2": XX 616 } 617 } 618 ``` 619 620 ## Update 621 622 Update Resource REST API 623 624 PUT http://$GOHAN/[$namespace_prefix/]$prefix/$plural/$id 625 626 Input 627 628 Note that input JSON can only contain if you set "update" permission for this 629 630 ``` 631 { 632 "$singular": { 633 "attr1": XX, 634 "attr2": XX 635 } 636 } 637 ``` 638 639 Response will be 640 641 HTTP Status Code: 200 642 643 ``` 644 { 645 "$singular": { 646 "attr1": XX, 647 "attr2": XX 648 } 649 } 650 ``` 651 652 ## DELETE 653 654 Delete Resource REST API 655 656 HTTP Status Code: 204 657 658 DELETE http://$GOHAN/[$namespace_prefix/]$prefix/$plural/$id 659 660 661 ## Custom Actions 662 663 Run custom action on a resource 664 665 POST http://$GOHAN/[$namespace_prefix/]$prefix/$plural/$id/$action_path 666 667 Input 668 669 Input JSON can only contain parameters defined in the input schema definition. It requires "$action" allow policy 670 671 ``` 672 { 673 "parameter1": XX, 674 "parameter2": XX 675 } 676 ``` 677 678 Response will be 679 680 HTTP Status Code: 200 681 682 ``` 683 { 684 "output1": XX, 685 "output2": XX 686 } 687 ```