luci-app-banip: sync with forthcoming banIP 1.0
[project/luci.git] / applications / luci-app-example / YAML.md
1 # Processing YAML in Lua
2
3 You may need to deal with YAML data in your Lua code.
4
5 ## root/usr/libexec/rpcd/luci.example
6 These are the changes you would need in the `usr/libexec/rpcd/luci.example` file.
7
8 First, declare that you want YAML libraries:
9
10 ```lua
11 -- If you need to process YAML, opkg install lyaml
12 local lyaml = require "lyaml"
13 ```
14
15 Then, declare a function to handle the YAML data, and a helper to read the file
16
17 ```lua
18 local function readfile(path)
19 local s = fs.readfile(path)
20 return s and (s:gsub("^%s+", ""):gsub("%s+$", ""))
21 end
22
23 local function reading_from_yaml()
24 -- Use the locally declared readfile() function to read in the
25 -- sample YAML file that ships with this package.
26 local example_config = readfile("/etc/luci.example.yaml")
27
28 -- Map that string to a Lua table via lyaml's load() method
29 local example_table = lyaml.load(example_config)
30
31 -- Convert the table to JSON
32 local example_json = jsonc.stringify(example_table)
33
34 -- Pass the JSON back
35 return example_json
36 end
37 ```
38
39 Declare the method in the `methods` table
40
41 ```lua
42 -- Converts the AGH YAML configuration into JSON for consumption by
43 -- the LuCI app.
44 get_yaml_file_sample = {
45 -- A special key of 'call' points to a function definition for execution.
46 call = function()
47
48 local r = {}
49 r.result = reading_from_yaml()
50 -- The 'call' handler will refer to '.code', but also defaults if not found.
51 r.code = 0
52 -- Return the table object; the call handler will access the attributes
53 -- of the table.
54 return r
55 end
56 },
57 ```
58
59 ## htdocs/luci-static/resources/view/example/rpc.js
60
61 These are the changes you need in the `rpc.js` file.
62
63 Declare the RPC call
64
65 ```js
66 var load_sample_yaml = rpc.declare({
67 object: 'luci.example',
68 method: 'get_yaml_file_sample'
69 });
70 ```
71
72 Add this declaration to the `view.extend()` call
73
74 ```js
75 render_sample_yaml: function(sample) {
76 console.log('render_sample_yaml()');
77 console.log(sample);
78
79 if (sample.error) {
80 return this.generic_failure(sample.error)
81 }
82 // Basically, a fully static table declaration.
83 var table = E('table', { 'class': 'table', 'id': 'sample-yaml' }, [
84 E('tr', {}, [
85 E('td', { 'class': 'td left', 'width': '33%' }, _("Top Level Int")),
86 E('td', { 'class': 'td left' }, sample.top_level_int),
87 ]),
88 E('tr', {}, [
89 E('td', { 'class': 'td left', 'width': '33%' }, _("Top Level String")),
90 E('td', { 'class': 'td left' }, sample.top_level_string),
91 ])
92 ]);
93 return table;
94 },
95 ```
96
97 Add a call to the `load` function in `view.extend()`
98
99 ```js
100 load: function () {
101 return Promise.all([
102 load_sample_yaml(),
103 load_sample1()
104 ]);
105 },
106 ```
107
108 Add this code to the `render` function in `view.extend()`
109
110 ```js
111 E('div', { 'class': 'cbi-section', 'id': 'cbi-sample-yaml' }, [
112 E('div', { 'class': 'left' }, [
113 E('h3', _('Sample YAML via RPC')),
114 E('div', {}), _("YAML transformed to JSON, table built explicitly"),
115 this.render_sample_yaml(sample_yaml),
116 ]),
117 ]),
118 ```
119
120 ## root/usr/share/rpcd/acl.d/luci-app-example.json
121
122 Allow access to the new RPC API
123
124 ```json
125 "read": {
126 "ubus": {
127 "luci.example": [
128 "get_yaml_file_sample",
129 "get_sample1",
130 "get_sample2"
131 ]
132 },
133 ```
134
135 ## root/etc/luci.example.yaml
136
137 Set up the sample YAML file, by placing it either in `root/etc` of the development tree, or directly
138 in `/etc` on the target machine and call it `luci.example.yaml` to match up to the `reading_from_yaml`
139 function's expectations.
140
141 ```yaml
142 top_level_string: example
143 top_level_int: 8080
144 top_level:
145 list_elements:
146 - foo
147 - bar
148 ```
149
150 That's it. Don't forget to also update the `LUCI_DEPENDS` segment of the `Makefile` to include
151 `+lyaml` so that the packaging system knows your code needs the YAML parsing package.