github.com/jbking/gohan@v0.0.0-20151217002006-b41ccf1c2a96/docs/source/extension.rst (about) 1 ============== 2 Extension 3 ============== 4 5 You can add additional logic using Gohan Extension. 6 Extensions has properties: 7 8 - id identity of the code 9 - code contents of code 10 - code_type javascript, go and donburi (DSL) are supported 11 - url placement of code. currenty, file://, http:// and https:// schemes are supported 12 - path resource path to execute code 13 14 Example Code 15 16 .. code-block:: yaml 17 18 extensions: 19 - code: console.log(Object.keys(context)); 20 id: test 21 path: /v2.0/.* 22 23 Javascirpt Code block 24 --------------------- 25 26 In the gohan extension code, you need to register context using 27 gohan_register_handler function. 28 gohan_register_handler talkes event_type (string)_ and handler (function(context)). 29 30 .. code-block:: javascript 31 32 gohan_register_handler("pre_show", function(context){ 33 context.resp = "pre_show event" 34 }); 35 36 gohan_register_handler("pre_update", function(context){ 37 context.resp = "pre_update event " 38 }); 39 40 context has following items 41 42 context.schema : schema information 43 context.path : url path 44 context.role : user role 45 context.auth : auth_context information 46 context.http_request : Go HTTP request object 47 context.http_response : Go HTTP response writer object 48 49 50 Build in exception types 51 ------------------------ 52 53 In an effort to simplify writing extensions for validation Gohan supports 54 throwing some exceptions and handles them internally. 55 Gohan provides the following exception types. 56 57 - BaseException(msg) 58 59 The base type of exception, should never be raised as itself, only extended. 60 61 - CustomException(msg, code) 62 63 A BaseException with an additional code property. When thrown will result in 64 an http response with the provided code and message being written. 65 66 One can extend the CustomException. An example follows. 67 68 .. code-block:: javascript 69 70 function ValidationException(msg) { 71 CustomException.call(this, msg, 400); 72 this.name = "ValidationException"; 73 } 74 ValidationException.prototype = Object.create(CustomException.prototype); 75 76 77 .. _`gohan built in functions`: 78 79 Build in javascript functions 80 ----------------------------- 81 82 Gohan extension supports some build-in functions. 83 84 - console.log(string) 85 86 Logging output 87 88 - gohan_http(method, url, headers, data, options) 89 90 fetch data from url 91 method : GET | POST | PUT | DELETE 92 url : destination url 93 headers : additional headers (eg. AUTH_TOKEN) 94 data : post or put data 95 options : dictionary of options for http client 96 opaque : boolean - whether to parse URL or to treat it as raw 97 98 - gohan_db_list(transaction, schema_id, filter_object) 99 100 retrive all data from database 101 102 - gohan_db_fetch(transaction, schema_id, id, tenant_id) 103 104 get one data from db 105 106 - gohan_db_query(transaction, schema_id, query_string, arguments) 107 108 Retrieve data with a raw query 109 110 - transaction: The transaction to use. When null will use a new one. 111 - schema_id: The ID of the schema of which the query result populates instances 112 - query_string: Raw query string such as a SQL SELECT query 113 114 - You can put a "?" as the placeholder of variables in your query string 115 116 - arguments: An array of actual values that replace place holders in query_string 117 118 - gohan_db_create(transaction, schema_id, object) 119 120 create data in db 121 122 - gohan_db_update(transaction, schema_id, object) 123 124 update data in db 125 126 - gohan_db_state_update(transaction, schema_id, object) 127 128 update data in db without informing etcd 129 130 - gohan_db_delete(transaction, schema_id, object) 131 132 delete data in db 133 134 - gohan_model_list(context, schema_id, filter) 135 136 Retrieve data through Gohan. 137 138 - context: You need to have transaction in this dictionary which you can get from given context 139 - schema_id: The id of the schema of the objects we want to retrieve. 140 - filter: How to filter retrieved objects. Should be a dictionary with each key being either: 141 142 - A property of the schema we are retrieving. Then the value has to either be a string or an array of strings. 143 The response is then filtered by removing all entries that do not have the value for the given key in the provided array. 144 - Any of the strings 'sort_key', 'sort_order', 'limit', 'offset'. These are interpreted with their values as query parameters. 145 146 - gohan_model_fetch(context, schema_id, resource_ids) 147 148 Retrieve a specific resource through Gohan. 149 150 - context: You need to have transaction in this dictionary which you can get from given context 151 - schema_id: The id of the schema of the object we want to retrieve. 152 - resource_id: The id of the object we want to retrieve. 153 - tenant_ids: allowed tenant id 154 155 - gohan_model_create(context, schema_id, data) 156 157 Create an object through Gohan. 158 159 - context: You need to have transaction in this dictionary which you can get from given context 160 - schema_id: The id of the schema of the object we want to create. 161 - data: The data needed to create the object, in the form of a dictionary. 162 163 - gohan_model_update(context, schema_id, resource_id, data, tenant_ids) 164 165 Update an object through Gohan. 166 167 - context: You need to have transaction in this dictionary which you can get from given context 168 - schema_id: The id of the schema of the object we want to update. 169 - resource_id: The id of the object we want to update. 170 - data: The data needed to update the object, in the form of a dictionary. 171 - tenant_ids: allowed tenant id 172 173 - gohan_model_delete(context, schema_id, resource_id) 174 175 Delete an object through Gohan. 176 177 - context: You need to have transaction in this dictionary which you can get from given context 178 - schema_id: The id of the schema of the object we want to delete. 179 - resource_id: The id of the object we want to delete. 180 181 - gohan_schemas() 182 183 returns all registered schemas 184 185 - gohan_schema_url(schema) 186 187 returns the url for the schema 188 189 - gohan_policies() 190 191 returns all policies 192 193 - gohan_uuid() 194 195 generate uuid v4 196 197 - gohan_sleep(time) 198 199 sleep time (ms) 200 201 - gohan_execute(comand_name, args) 202 203 execute shell command 204 205 - gohan_template(template_string, variables) 206 207 apply go style template 208 209 - gohan_netconf_open(hostname, username) 210 211 open netconf session. 212 (Note: you need set up ssh key configuraion 213 on both of gohan and target node.) 214 In gohan, you need to setup ssh/key_file 215 configuraion. 216 217 - gohan_netconf_exec(session, command) 218 219 execute netconf command 220 221 - gohan_netconf_close(session) 222 223 close netconf session 224 225 - gohan_ssh_open(hostname, username) 226 227 open ssh session. 228 (Note: you need set up ssh key configuraion 229 on both of gohan and target node.) 230 In gohan, you need to setup ssh/key_file 231 configuraion. 232 233 - gohan_ssh_exec(session, command) 234 235 execute command on ssh session 236 237 - gohan_ssh_close(session) 238 239 close ssh session 240 241 - require(module) 242 243 Dynamically load modules 244 245 .. _event: 246 247 Event 248 ---------------- 249 250 - pre_list 251 252 list event before db operation 253 254 context.response contains response data. 255 You can also update response here 256 257 Note you can skip db operation if you set context response in here 258 259 - pre_list_in_transaction 260 261 same as pre_list but executed in the db transaction 262 context.transaction contains transaction object for db operation 263 264 id : request id 265 context.response contains response data. 266 You can also update response here 267 268 - post_list_in_transaction 269 270 same as post_list but executed in the db transaction 271 context.transaction contains transaction object for db operation 272 273 id : request id 274 context.response contains response data. 275 You can also update response here 276 277 - post_list 278 279 list event after db operation. 280 281 context.response contains response data. 282 You can also update response here 283 284 - pre_show 285 286 show event before db access 287 288 id : request id 289 context.response contains response data. 290 You can also update response here 291 292 Note you can skip db operation if you set context response in here 293 294 - pre_show_in_transaction 295 296 same as pre_show but executed in the db transaction 297 context.transaction contains transaction object for db operation 298 299 id : request id 300 context.response contains response data. 301 You can also update response here 302 303 - post_show_in_transaction 304 305 same as post_show but executed in the db transaction 306 context.transaction contains transaction object for db operation 307 308 id : request id 309 context.response contains response data. 310 You can also update response here 311 312 - post_show 313 314 show event after db operation 315 316 id : request id 317 context.response contains response data. 318 You can also update response here 319 320 - pre_create 321 322 executed before creation 323 Mainly used for validation purpose 324 325 context.resource contains user input data 326 327 Note you can skip db operation if you set context response in here 328 329 - pre_create_in_transaction 330 331 same as pre_create but executed in the db transaction 332 context.transaction contains transaction object for db operation 333 334 - post_create_in_transaction 335 336 after creation in transaction 337 338 - post_create 339 340 after create 341 context.response contains response data. 342 context.transaction contains transaction object for db operation 343 344 - pre_update 345 346 executed before update 347 Mainly used for validation purpose 348 349 context.resource contains user input data 350 351 Note you can skip db operation if you set context response in here 352 353 - pre_update_in_transaction 354 355 same as pre_update but executed in the db transaction 356 context.transaction contains transaction object for db operation 357 358 - post_update_in_transaction 359 360 after creation in transaction 361 362 - post_update 363 364 after update 365 context.response contains response data. 366 context.transaction contains transaction object for db operation 367 368 - pre_delete 369 370 executed before delete 371 Mainly used for validation purpose 372 373 context.id contains resource id we are trying to delete 374 context.transaction contains transaction object for db operation 375 376 - pre_delete_in_transaction 377 378 same as pre_delete but executed in the db transaction 379 context.transaction contains transaction object for db operation 380 381 - post_delete_in_transaction 382 383 after creation in transaction 384 385 - post_delete 386 387 after delete 388 389 - pre_state_update_in_transaction 390 391 executed before a state update triggerred by a backend event 392 393 context.resource contains the resource associated with the update, 394 context.state contains the state changes, 395 context.config_version contains the current config version 396 397 - post_state_update_in_transaction 398 399 as above, but after the state update 400 401 - pre_monitoring_update_in_transaction 402 403 executed before a monitoring update triggerred by a backend event 404 405 context.resource contains the resource associated with the update, 406 context.monitoring contains the new monitoring information 407 408 - post_monitoring_update_in_transaction 409 410 as above, but after the monitoring update 411 412 - notification 413 414 executed when you receive amqp/snmp/cron notification 415 416 Testing javascript extensions 417 ----------------------------- 418 419 You can test extensions using a testing tool bundled with Gohan through new 420 command ``testextensions`` (or simply ``te``). Build and install Gohan, then 421 run ``gohan testextensions <paths to files/directories to test>``. The 422 framework will walk through files and recursively through directories, matching 423 files named ``test_.*.js`` and running tests. 424 425 Test file contents 426 ^^^^^^^^^^^^^^^^^^ 427 Each test file must specify schema and path for preloading extensions: 428 429 * var SCHEMA - path to the schema that stores extensions to be tested 430 * var PATH - path for preloading extensions 431 432 Additionally each file can specify: 433 434 * one setUp() function that will be called before each test 435 * one tearDown() function that will be called after each test 436 * multiple test_<name>() functions that will be called by the framework 437 * multiple helper functions and variables, with names not starting with prefix 438 ``test_`` 439 440 Framework API 441 ^^^^^^^^^^^^^ 442 Test framework provides all built in function mentioned in subsection 443 describing `gohan built in functions`_. 444 445 To avoid making HTTP requests during tests, ``gohan_http`` function is a mock. 446 You can pass values that will be returned for given arguments during subsequent 447 calls by calling ``gohan_http.Expect(argument, ...).Return(value)``. One call to 448 ``gohan_http.Expect(arguments, ...).Return(value)`` provides one response of 449 ``gohan_http`` (FIFO queue). If no return value, or wrong arguments are provided 450 for a call then an unexpected call is assumed, which will result in test failures. 451 452 In addition to the abovementioned functions, the framework provides the 453 following API: 454 455 * ``Fail(format_string, ...)`` - stop execution of a single test case and 456 return an error 457 458 * ``GohanTrigger(event_type, context) : <new context>`` - triggers a specified 459 type of Gohan event 460 461 * ``event_type`` - one of the event types recognized by Gohan (see 462 event_ subsection) 463 464 * ``context`` - context passed to the event handler 465 466 * ``MockTransaction() : <mock transaction>`` - return a mock transaction that 467 can be used with built-in Gohan methods. Each test is run using a separate 468 database that is deleted after ``tearDown()``, so there is no need to 469 clean up the database between tests. Multiple calls to ``MockTransaction()`` 470 within a single ``setUp()``, test, ``tearDown()`` routine when no call to 471 ``CommitMockTransaction()`` has been made will yield the same transaction. 472 473 * ``CommitMockTransaction()`` - commit and close the last nonclosed 474 transaction. After this call any calls to ``MockTransaction()`` return 475 a new transaction. 476 477 * ``MockPolicy() : <mock policy>`` - return a mock policy that 478 can be used with built-in Gohan methods. 479 480 * ``MockAuthorization() : <mock authorization>`` - return a mock authorization that 481 can be used with built-in Gohan methods. 482 483 Example 484 ^^^^^^^ 485 A sample test may look like this: 486 487 .. code-block:: javascript 488 489 // Schema file containing extensions to be tested 490 var SCHEMA = "../test_schema.yaml"; 491 492 /** 493 * Sample contents of test_schema.yaml: 494 * 495 * extensions: 496 * - id: network 497 * path: /v2.0/network.* 498 * url: file://./etc/examples/neutron/network.js 499 * - id: exceptions 500 * path: "" 501 * url: file://./etc/examples/neutron/exceptions.js 502 * - id: urls 503 * path: /gohan/v0.1/schema.* 504 * url: file://./etc/examples/url.js 505 * schemas: 506 * - description: Network 507 * id: network 508 * parent: "" 509 * plural: networks 510 * schema: 511 * properties: 512 * id: 513 * format: uuid 514 * permission: 515 * - create 516 * title: ID 517 * type: string 518 * unique: true 519 * tenant_id: 520 * format: uuid 521 * permission: 522 * - create 523 * title: Tenant id 524 * type: string 525 * unique: false 526 * propertiesOrder: 527 * - name 528 * - id 529 * - tenant_id 530 * singular: network 531 * title: Network 532 */ 533 534 // With the following PATH, "network" and "exceptions" extensions will be loaded 535 var PATH = "/v2.0/networks"; 536 537 /** 538 * Sample contents of network.js: 539 * 540 * // filter removes the network with the unwanted id 541 * gohan_register_handler("post_list", function filter(context) { 542 * // This call will be mocked, see testNetworkListFilter below 543 * response = gohan_http("GET", "http://whatisunwanted.com", {}, null); 544 * 545 * for (var i = 0; i < context.response.networks.length; i++) { 546 * if (context.response.networks[i].id == response.unwanted) { 547 * context.response.networks.splice(i, 1); 548 * break; 549 * } 550 * } 551 * }); 552 */ 553 554 var context; 555 var network; 556 557 function setUp() { 558 var network_to_create = { 559 'id': 'new', 560 'tenant_id': 'azerty' 561 }; 562 network = gohan_db_create(MockTransaction(), "network", network_to_create); 563 context = { 564 'schema': { /* ... */ }, 565 'http_request': { /* ... */ }, 566 'http_response': { /* ... */ }, 567 'path': '/gohan/v0.1/schema', 568 'response': { 569 'networks': [ 570 network, 571 { 572 'id': 'foo', 573 'tenant_id': 'xyz' 574 } 575 ] 576 } 577 } 578 } 579 580 function tearDown() { 581 gohan_db_delete(MockTransaction(), "network", "new"); 582 } 583 584 function testNetworkListFilter() { 585 // First call to gohan_http will return {'unwanted': 'foo'} 586 gohan_http.Expect("GET", "http://whatisunwanted.com", {}, null).Return({'unwanted': 'foo'}); 587 // Second call to gohan_http will return empty response 588 gohan_http.Expect("GET", "http://whatisunwanted.com", {}, null).Return({}); 589 // Subsequent calls to gohan_http will fail since they are not expected 590 var new_context = GohanTrigger('post_list', context); 591 592 if (new_context.response.networks.length != 1) { 593 Fail('Expected 1 network but %d found.', new_context.response.networks.length); 594 } 595 596 if (new_context.response.networks[0].id != network.id) { 597 Fail('Expected network with id "%s" but "%s" found.', network.id, new_context.response.networks[0].id); 598 } 599 } 600 601 function testSomethingElse() { 602 /* ... */ 603 } 604 605 Javascript Backend 606 ------------------------- 607 608 Currenly, gohan is using Otto. Otto is a pure golang implementation 609 for javascript. 610 Gohan also have experimental support for v8. v8 runs js code 100-1000 times faster than Otto. 611 612 TODOs 613 - no build-in are implemented yet 614 615 In order to make v8 version of Gohan, you need v8worker https://github.com/ry/v8worker installed in your env. (see more instruction on the repository). 616 617 In order to enable v8 support on extension. then set ENABLE_V8=true 618 619 .. code-block:: shell 620 621 ENABLE_V8=true make 622 623 624 Go based extension 625 ------------------------- 626 627 You can extend gohan extension by native go. 628 You can use "go" for code_type and specify your callback id in code. 629 Also, you can register go struct & call it from javascript. 630 631 .. code-block:: yaml 632 633 extensions: 634 - code: exampleapp_callback 635 code_type: go 636 id: example 637 path: .* 638 - code: exampleapp_callback 639 code_type: go 640 id: example 641 path: .* 642 - code: | 643 gohan_register_handler("pre_list", function (context){ 644 var exampleModule = require("exampleapp"); 645 exampleModule.HelloWorld("example app!", 646 {"hobby": "sleeping"}); 647 }); 648 id: example_js 649 path: .* 650 651 652 .. code-block:: go 653 654 //Register go callback 655 extension.RegisterGoCallback("exampleapp_callback", 656 func(event string, context map[string]interface{}) error { 657 fmt.Printf("callback on %s : %v", event, context) 658 return nil 659 }) 660 661 exampleModule := &ExampleModule{} 662 //Register go based module for javascript 663 extension.RegisterModule("exampleapp", exampleModule) 664 665 666 We have exampleapp with comments in exampleapp directory. 667 You can also, import github.com/cloudwan/server module and 668 have your own RunServer method to have whole custom route written in go. 669 670 671 Donburi 672 ------------------------- 673 674 Note: This function is experimental. Any APIs are subject to change. 675 676 Gohan support Donburi which is a yaml based DSL to support extension. 677 Donburi is heavyly inspired by Ansible yaml script. 678 The goal of Donburi is pain-less extension using YAML. 679 This is donburi example. 680 681 .. code-block:: yaml 682 683 db_tasks: 684 - list: 685 schema_id: "test" 686 tenant_id: "xxx" 687 register: gohan_db 688 - fetch: 689 schema_id: "test" 690 id: "xxx" 691 - resource: 692 id: "xxx" 693 schema: "test" 694 properties: 695 name: "test" 696 register: "xxx" 697 tasks: 698 - vars: 699 message: world 700 - debug: "hello {{ .message }} " 701 - eval: "console.log(id);" 702 - contrail: 703 schema: "virtual_networks" 704 properties: 705 name: "test" 706 register: vm1_out 707 708 709 This is the other sample. 710 711 .. code-block:: yaml 712 713 tasks: 714 - eval: "1 + 1" 715 register: result 716 - eval: "true" 717 register: when_is_working 718 when: "result == 2" 719 - block: 720 - vars: 721 list2 : [4, 5, 6] 722 - eval: "result += item" 723 with_items: 724 - 1 725 - 2 726 - 3 727 when: when_is_working 728 - eval: "result += item" 729 with_items: "list2" 730 731 732 you can find an example application at etc/appts/donburi.yaml, and 733 example server configuraion in etc/donburi.yaml. 734 735 Example Application 736 ^^^^^^^^^^^^^^^^^^^ 737 738 - Setup contrail + openstack using vagrant 739 740 See https://github.com/mwiget/opencontrail 741 742 - Setup CORS (Cross-Origin Resource Sharing) on keystone 743 744 See https://ianunruh.com/2014/11/openstack-cors.html 745 746 - Setup notification configuration on heat 747 748 /etc/heat/heat.conf 749 750 notification_driver=heat.openstack.common.notifier.rpc_notifier 751 752 restart heat-api and heat-engine 753 754 - Allow rabbitmq connection from your gohan host 755 756 Example 757 758 .. code-block:: shell 759 760 root@ubuntu-14:/etc/rabbitmq# cat rabbitmq.config 761 [ 762 {rabbit, [ {tcp_listeners, [{"0.0.0.0", 5672}]}, 763 {loopback_users, []}, 764 {log_levels,[{connection, info},{mirroring, info}]} ] 765 766 767 root@ubuntu-14:/etc/rabbitmq# cat rabbitmq-env.conf 768 769 NODE_IP_ADDRESS=0.0.0.0 770 NODENAME=rabbit@ubuntu-14-ctrl 771 772 restart rabbitmq 773 774 - Update keystone configuraion on etc/donburi.yaml 775 776 keystone: 777 use_keystone: true 778 fake: false 779 auth_url: "http://172.16.25.130:5000/v3" 780 user_name: "admin" 781 tenant_name: "admin" 782 password: "secret123" 783 version: v3 784 785 - Start gohan 786 787 gohan server --config-file etc/donburi.yaml 788 789 790 Variables 791 ^^^^^^^^^^^^^^^^^^^ 792 793 You can register variables using vars task 794 795 .. code-block:: yaml 796 797 - vars: 798 list2 : [4, 5, 6] 799 800 you can use values in context in each value using golang 801 template format. 802 (see more details on http://golang.org/pkg/text/template/ ) 803 804 For example, you can use context.tenant value using 805 "{{ .tenant }}"" 806 807 Note that template isn't allowed in eval and when. 808 809 Block 810 ^^^^^^^^^^^^^^^^^^^ 811 812 You can have a logical grouping of tasks. 813 We have "block" and "resources". 814 815 816 .. code-block:: yaml 817 818 - block: 819 - vars: 820 list2 : [4, 5, 6] 821 - eval: "result += item" 822 with_items: 823 - 1 824 - 2 825 - 3 826 when: when_is_working 827 828 If you use reousrces block, each sub task will be executed 829 on reverse order on resource deletion. 830 831 .. code-block:: yaml 832 833 - resources: 834 - resource A 835 - resource B # depends on resource A 836 837 Define 838 ^^^^^^^^^^^^^^^^^^^ 839 840 You can define a function using "define" block. 841 last task execution result will be returned. 842 843 .. code-block:: yaml 844 845 - define: 846 name: add 847 tasks: 848 - eval: "a + b" 849 - add: 850 a: 1 851 b: 2 852 register: c 853 854 855 Event handling 856 ^^^^^^^^^^^^^^^^^^^ 857 858 db_tasks will be executed in main transaction 859 tasks will be executed outside of transaction 860 861 Conditionals 862 ^^^^^^^^^^^^^^^^^^^ 863 864 when: the statement specifed in "when" will be evaluated, and when it is true 865 the task will be executed 866 else: if evaluation result of "when" get false, else will be executed 867 868 .. code-block:: yaml 869 870 tasks: 871 - debug: "result is 2" 872 when: "result == 2" 873 else: 874 - debug: "result is not 2" 875 876 Error handling 877 ^^^^^^^^^^^^^^^^^^^ 878 879 You can use rescue and always block task for error handling. 880 rescue will be executed only if we got execption. 881 always will be executed always. 882 retry (int) block, rescue, always will be executed "retry" count 883 times. 884 885 .. code-block:: yaml 886 887 tasks: 888 - block: 889 - eval: throw 'error' 890 rescue: 891 - eval: "rescue_executed = true" 892 always: 893 - eval: "always_executed = true" 894 retry: 3 895 896 897 Note that last error will be stored in context.error 898 899 Loops 900 ^^^^^^^^^^^^^^^^^^^ 901 902 with_items: task will be executed for each specifed items. 903 if you specify string, it will be evaluated and result will be used as item. 904 905 .. code-block:: yaml 906 907 - eval: "[4, 5, 6]" 908 register: "list2" 909 - eval: "result += item" 910 with_items: 911 - 1 912 - 2 913 - 3 914 - eval: "result += item" 915 with_items: "list2" 916 917 with_dict: loop over object. item will have key and value. 918 919 .. code-block:: yaml 920 921 - eval: "context[item.key] = item.value" 922 with_dict: 923 alice: 18 924 bob: 21 925 926 927 Supported tasks 928 ^^^^^^^^^^^^^^^^^^^ 929 930 - debug -- show debug message 931 - eval -- eval javasciprt 932 - sleep: miliseconds sleep certin time 933 - command: execute shell command 934 935 .. code-block:: yaml 936 937 - command: 938 name: echo 939 args: 940 - test 941 942 943 - fetch -- get data from db 944 945 schema: schema id 946 tenant_id: target tenant id 947 id: id of the resource 948 949 950 .. code-block:: yaml 951 952 - fetch: 953 schema: "network" 954 id: "{{ response.network_id }}" 955 tenant_id: "" 956 register: network 957 958 - list -- get data from db 959 960 schema: schema id 961 tenant_id: target tenant id 962 id: id of the resource 963 964 .. code-block:: yaml 965 966 - list: 967 schema: "network" 968 tenant_id: "" 969 register: network 970 971 - contrail 972 973 Create contrail resources 974 In order to use this, you need to set correct api URL on etc/contrail/extensions/contrail_extension_config.js, and proper keystone configuraion 975 976 id: remote resource uuid will be saved on this specificed property in 977 main resource 978 schema: contrail resource id 979 allow_update: list of properties allowed to be updated 980 properties: remote resource properties 981 982 .. code-block:: yaml 983 984 - contrail: 985 id: "contrail_virtual_network" 986 schema: "virtual-network" 987 allow_update: [] 988 properties: 989 parent_type: "project" 990 fq_name: 991 - default-domain 992 - "{{ tenant_name }}" 993 - "{{ response.id }}" 994 995 996 - heat 997 998 You can crud heat stack from donburi. 999 This is a example 1000 1001 .. code-block:: yaml 1002 1003 - heat: 1004 id: "heat_stack_id" 1005 stack_name: "{{ response.name }}" 1006 template: 1007 heat_template_version: 2013-05-23 1008 parameters: {} 1009 resources: 1010 server: 1011 type: OS::Nova::Server 1012 properties: 1013 image: "tinycore-in-network-nat" 1014 flavor: "m1.tiny" 1015 outputs: 1016 server_networks: 1017 description: The networks of the deployed server 1018 value: { get_attr: [server, networks] } 1019 1020 - netconf 1021 1022 You can use netconf to configure remote network devices. 1023 Note that it is possible you get code injection attack if you 1024 directly use user's input. 1025 1026 .. code-block:: yaml 1027 1028 tasks: 1029 - block: 1030 - netconf_open: 1031 host: "{{.response.management_ip}}" 1032 username: "admin" 1033 register: session 1034 - netconf_exec: 1035 connection: session 1036 command: "<get-config><source><running/></get-config>" 1037 register: output 1038 - debug: "{{.output.output.Data}}" 1039 always: 1040 - netconf_close: session 1041 1042 - ssh 1043 1044 You can use ssh to configure remote hosts. 1045 Note that it is possible you get code injection attack if you 1046 directly use user's input. 1047 1048 .. code-block:: yaml 1049 1050 - block: 1051 - ssh_open: 1052 host: "{{.response.management_ip}}:22" 1053 username: "admin" 1054 register: session 1055 rescue: 1056 - debug: "{{.error}}" 1057 - ssh_exec: 1058 connection: session 1059 command: "show interfaces" 1060 register: output 1061 rescue: 1062 - debug: "{{.error}}" 1063 - debug: "{{.output.output}}" 1064 always: 1065 - ssh_close: session