moat-kv 0.70.24__py3-none-any.whl → 0.71.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- build/lib/moat/kv/_cfg.yaml +2 -6
- build/lib/moat/kv/backend/mqtt.py +0 -3
- ci/rtd-requirements.txt +4 -0
- ci/test-requirements.txt +7 -0
- ci/travis.sh +96 -0
- debian/.gitignore +7 -0
- debian/changelog +1435 -0
- debian/control +43 -0
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/_cfg.yaml +2 -6
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/backend/mqtt.py +0 -3
- debian/moat-kv.postinst +3 -0
- debian/rules +20 -0
- debian/source/format +1 -0
- debian/watch +4 -0
- docs/Makefile +20 -0
- docs/make.bat +36 -0
- docs/source/TODO.rst +61 -0
- docs/source/_static/.gitkeep +0 -0
- docs/source/acls.rst +80 -0
- docs/source/auth.rst +84 -0
- docs/source/client_protocol.rst +456 -0
- docs/source/code.rst +341 -0
- docs/source/command_line.rst +1187 -0
- docs/source/common_protocol.rst +47 -0
- docs/source/debugging.rst +70 -0
- docs/source/extend.rst +37 -0
- docs/source/history.rst +36 -0
- docs/source/index.rst +75 -0
- docs/source/model.rst +54 -0
- docs/source/overview.rst +83 -0
- docs/source/related.rst +89 -0
- docs/source/server_protocol.rst +450 -0
- docs/source/startup.rst +31 -0
- docs/source/translator.rst +244 -0
- docs/source/tutorial.rst +711 -0
- docs/source/v3.rst +168 -0
- examples/code/transform.scale.yml +21 -0
- examples/code/transform.switch.yml +82 -0
- examples/code/transform.timeslot.yml +63 -0
- moat/kv/_cfg.yaml +2 -6
- moat/kv/backend/mqtt.py +0 -3
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.0.dist-info}/METADATA +2 -5
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.0.dist-info}/RECORD +68 -17
- scripts/current +15 -0
- scripts/env +8 -0
- scripts/init +39 -0
- scripts/recover +17 -0
- scripts/rotate +33 -0
- scripts/run +29 -0
- scripts/run-all +10 -0
- scripts/run-any +10 -0
- scripts/run-single +15 -0
- scripts/success +4 -0
- systemd/moat-kv-recover.service +21 -0
- systemd/moat-kv-rotate.service +20 -0
- systemd/moat-kv-rotate.timer +10 -0
- systemd/moat-kv-run-all.service +26 -0
- systemd/moat-kv-run-all@.service +25 -0
- systemd/moat-kv-run-any.service +26 -0
- systemd/moat-kv-run-any@.service +25 -0
- systemd/moat-kv-run-single.service +26 -0
- systemd/moat-kv-run-single@.service +25 -0
- systemd/moat-kv.service +27 -0
- systemd/postinst +7 -0
- systemd/sysusers +3 -0
- build/lib/moat/kv/backend/serf.py +0 -45
- build/lib/moat/kv/mock/serf.py +0 -250
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/backend/serf.py +0 -45
- debian/moat-kv/usr/lib/python3/dist-packages/moat/kv/mock/serf.py +0 -250
- moat/kv/backend/serf.py +0 -45
- moat/kv/mock/serf.py +0 -250
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.0.dist-info}/WHEEL +0 -0
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.0.dist-info}/licenses/LICENSE.txt +0 -0
- {moat_kv-0.70.24.dist-info → moat_kv-0.71.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,244 @@
|
|
1
|
+
=================================
|
2
|
+
Verifying and Translating Entries
|
3
|
+
=================================
|
4
|
+
|
5
|
+
++++++++++++
|
6
|
+
Verification
|
7
|
+
++++++++++++
|
8
|
+
|
9
|
+
Your application may require consistency guarantees. Instead of committing
|
10
|
+
fraud when a transaction in your bookkeeping system doesn't add up to zero,
|
11
|
+
you might want to add a verification step to make sure that that doesn't
|
12
|
+
happen in the first place. More prosaically, the statement "The door is
|
13
|
+
locked" is either True or False. (However, you always should be prepared
|
14
|
+
for an answer of "No idea", aka ``None``. That's not avoidable.)
|
15
|
+
|
16
|
+
|
17
|
+
Types
|
18
|
+
=====
|
19
|
+
|
20
|
+
Type entries may contain a ``schema`` attribute with a JSON Schema that
|
21
|
+
verifies the data. They also may contain a ``code`` attribute which forms
|
22
|
+
the body of a validation procedure. The variable ``value`` contains the
|
23
|
+
value in question.
|
24
|
+
|
25
|
+
Type entries are hierarchic: An ("int","percent") type is first validated
|
26
|
+
against (None,"type","int"), then against (None,"type","int","percent").
|
27
|
+
|
28
|
+
Type checkers cannot modify data.
|
29
|
+
|
30
|
+
Type check entries *must* be accompanied by "good" and "bad" values, which
|
31
|
+
must be non-empty arrays of values which pass or fail this type check. For
|
32
|
+
subordinate types, both kinds must pass the supertype check: if you
|
33
|
+
add a type "float percentage", the ``bad`` list may contain values like ``-1.2`` or
|
34
|
+
``123.45``, but not ``"hello"``.
|
35
|
+
|
36
|
+
Beware that restricting an existing type is dangerous. The MoaT-KV server
|
37
|
+
does not verify that all existing entries verify correctly.
|
38
|
+
In pedantic mode, your network may no longer load its data or converge.
|
39
|
+
|
40
|
+
|
41
|
+
Matches
|
42
|
+
=======
|
43
|
+
|
44
|
+
The (None,"match") hierarchy mirrors the actual object tree, except that
|
45
|
+
wildcards are allowed:
|
46
|
+
|
47
|
+
* "#"
|
48
|
+
|
49
|
+
matches any number of levels
|
50
|
+
|
51
|
+
* "+"
|
52
|
+
|
53
|
+
matches exactly one level
|
54
|
+
|
55
|
+
This matches MQTT's behavior.
|
56
|
+
|
57
|
+
Unlike MQTT, there may be more than one "#" wildcard.
|
58
|
+
|
59
|
+
Be aware that adding or modifying matches to existing entries is dangerous.
|
60
|
+
The MoaT-KV server does not verify that all existing entries verify correctly.
|
61
|
+
In pedantic mode, your network may no longer load its data or converge.
|
62
|
+
|
63
|
+
|
64
|
+
Putting it all together
|
65
|
+
=======================
|
66
|
+
|
67
|
+
Given the following structure, values stored at ("foo", anything, "bar")
|
68
|
+
must be integers::
|
69
|
+
|
70
|
+
match:
|
71
|
+
foo:
|
72
|
+
+:
|
73
|
+
bar:
|
74
|
+
_:
|
75
|
+
type:
|
76
|
+
- int
|
77
|
+
- percent
|
78
|
+
type:
|
79
|
+
int:
|
80
|
+
_:
|
81
|
+
bad: [none, "foo"]
|
82
|
+
code: 'if not isinstance(value,int): raise ValueError(''not an int'')'
|
83
|
+
good: [0,2]
|
84
|
+
percent:
|
85
|
+
_:
|
86
|
+
bad: [-1,555]
|
87
|
+
code: 'if not 0<=value<=100: raise ValueError(''not a percentage'')'
|
88
|
+
good: [0,100,50]
|
89
|
+
---
|
90
|
+
_: 123
|
91
|
+
foo:
|
92
|
+
dud:
|
93
|
+
bar:
|
94
|
+
_: 55
|
95
|
+
|
96
|
+
The above is the server content at the end of the testcase
|
97
|
+
``tests/test_feature_typecheck.py::test_72_cmd``, when
|
98
|
+
dumped with the commands ``moat kv internal dump`` and
|
99
|
+
``moat kv «path» get -rd_``.
|
100
|
+
|
101
|
+
On the command line, you can do the same thing thus::
|
102
|
+
|
103
|
+
$ echo "if not isinstance(value,int): raise ValueError('not an int')" | \
|
104
|
+
moat kv type set -b None -b '"foo"' -g 0 -g 2 -s - int
|
105
|
+
$ echo "if not 0<=value<=100: raise ValueError('not a percentage')" | \
|
106
|
+
moat kv type set -b -1 -b 555 -g 0 -g 100 -g 50 -s - int percent
|
107
|
+
$ moat kv type match -t int -t percent foo + bar
|
108
|
+
|
109
|
+
+++++++++++
|
110
|
+
Translation
|
111
|
+
+++++++++++
|
112
|
+
|
113
|
+
Sometimes, clients need special treatment. For instance, an IoT-MQTT message
|
114
|
+
that reports turning on a light might send "ON" to topic
|
115
|
+
``/home/state/bath/light``, while what you'd really like to do is to change
|
116
|
+
the Boolean ``state`` attribute of ``home.bath.light``. Or maybe the value
|
117
|
+
is a percentage and you'd like to ensure that the stored value is 0.5
|
118
|
+
instead of "50%", and that no rogue client can set it to -20 or "gotcha".
|
119
|
+
|
120
|
+
To ensure this, MoaT-KV uses two typing mechanisms. One has been described,
|
121
|
+
above, and ensures that the values are correct:
|
122
|
+
|
123
|
+
* "type" entries describe the type of entry ("this is an integer between 0
|
124
|
+
and 42").
|
125
|
+
|
126
|
+
* "match" entries describe the path position to which that type applies
|
127
|
+
|
128
|
+
Another, similar mechanism may then be used to convert clients' values to
|
129
|
+
MoaT-KV entries and back:
|
130
|
+
|
131
|
+
* "codec" entries describe distinct converters ("50%" => 0.5; "ON" => 'set
|
132
|
+
the entry's "state" property to ``True``')
|
133
|
+
|
134
|
+
* "map" entries are activated per client (via command, or controlled by its
|
135
|
+
login) and describe the path position to which a codec applies
|
136
|
+
|
137
|
+
|
138
|
+
Codecs
|
139
|
+
======
|
140
|
+
|
141
|
+
Codec entries contain ``decode`` and ``encode`` attributes which form the
|
142
|
+
bodies of procedures that rewrite external data to MoaT-KV values and vice
|
143
|
+
versa, respectively, using the ``value`` parameter as input. The ``decode``
|
144
|
+
procedure gets an additional ``prev`` variable which contains the old
|
145
|
+
value. That value **must not** be modified; create a copy or (preferably)
|
146
|
+
use :func:`moat.util.combine_dict` to assemble the result.
|
147
|
+
|
148
|
+
Codecs may be named hierarchically for convenience; if you want to
|
149
|
+
call the "parent" codec, put the common code in a module and import that.
|
150
|
+
|
151
|
+
Codecs also require "in" and "out" attributes, each of which must contain a list
|
152
|
+
of 2-tuples with that conversion's source value and its result. "in"
|
153
|
+
corresponds to decoding, "out" to encoding – much like Python's binary
|
154
|
+
codecs.
|
155
|
+
|
156
|
+
|
157
|
+
Converters
|
158
|
+
==========
|
159
|
+
|
160
|
+
While the ``(None,"map")`` subtree contains a single mapping, ``(None,"conv")``
|
161
|
+
uses an additional single level of codec group names. A mapping must be
|
162
|
+
applied to a user (by adding a "conv=GROUPNAME" to the user's aux data
|
163
|
+
field) before it is used. This change is instantaneous, i.e. an existing
|
164
|
+
user does not need to reconnect.
|
165
|
+
|
166
|
+
Below that, converter naming works like that for mappings. Of course, the
|
167
|
+
pointing attribute is named ``codec`` instead of ``type``.
|
168
|
+
|
169
|
+
|
170
|
+
Putting it all together
|
171
|
+
=======================
|
172
|
+
|
173
|
+
Given the following data structure, the user "conv" will only be able to
|
174
|
+
write stringified integers under keys below the "inty" key, which will be
|
175
|
+
stored as integers::
|
176
|
+
|
177
|
+
|
178
|
+
auth:
|
179
|
+
_:
|
180
|
+
current: _test
|
181
|
+
_test:
|
182
|
+
user:
|
183
|
+
con:
|
184
|
+
_:
|
185
|
+
_aux:
|
186
|
+
conv: foo
|
187
|
+
std:
|
188
|
+
_:
|
189
|
+
_aux: {}
|
190
|
+
codec:
|
191
|
+
int:
|
192
|
+
_:
|
193
|
+
decode: assert isinstance(value,str); return int(value)
|
194
|
+
encode: return str(value)
|
195
|
+
in:
|
196
|
+
- [ '1', 1 ]
|
197
|
+
- [ '2', 2 ]
|
198
|
+
- [ '3', 3 ]
|
199
|
+
out:
|
200
|
+
- [ 1, '1' ]
|
201
|
+
- [ 2, '2' ]
|
202
|
+
- [ -3, '-3' ]
|
203
|
+
conv:
|
204
|
+
foo:
|
205
|
+
inty:
|
206
|
+
'#':
|
207
|
+
_:
|
208
|
+
codec:
|
209
|
+
- int
|
210
|
+
---
|
211
|
+
inty:
|
212
|
+
_: hello
|
213
|
+
ten:
|
214
|
+
_: 10
|
215
|
+
yep:
|
216
|
+
yepyepyep:
|
217
|
+
_: 13
|
218
|
+
yep:
|
219
|
+
_: 99
|
220
|
+
|
221
|
+
|
222
|
+
The above is the server content at the end of the testcase
|
223
|
+
``tests/test_feature_convert.py::test_71_basic``, when
|
224
|
+
dumped with the commands ``moat kv internal dump`` and
|
225
|
+
``moat kv «path» get -rd_``.
|
226
|
+
|
227
|
+
Paths
|
228
|
+
=====
|
229
|
+
|
230
|
+
Currently, MoaT-KV does not offer automatic path translation. If you need
|
231
|
+
that, the best way is to code two active object hierarchies, and
|
232
|
+
let their ``set_value`` methods shuffle data to the "other" side.
|
233
|
+
|
234
|
+
There are some caveats:
|
235
|
+
|
236
|
+
* All such data are stored twice.
|
237
|
+
|
238
|
+
* Don't change a value that didn't in fact change; if you do, you'll
|
239
|
+
generate an endless loop.
|
240
|
+
|
241
|
+
* You need to verify that the two trees match when you start up, and decide
|
242
|
+
which is more correct. (The ``tock`` stamp will help you here.) Don't
|
243
|
+
accidentally overwrite changes that arrive while you do that.
|
244
|
+
|