Skip to content

Commit b66ac5d

Browse files
committed
Add an append action for entry array properties
plus fix a few typos Signed-off-by: Jacob Floyd <cognifloyd@gmail.com>
1 parent 7f496c5 commit b66ac5d

File tree

5 files changed

+91
-3
lines changed

5 files changed

+91
-3
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ You can also use dynamic values from the datastore. See the
5050
of a JSON serialized object. Then, serialize and store the updated object.
5151
The property's value may be any json-serializable type.
5252
Fails if the datastore key does not exist. A coordination backend is recommended.
53+
* ``kv.append_entry_property`` - Add the value to the end of an array property
54+
in the named entry of a JSON serialized object. Then, serialize and store the
55+
updated object. The property must be an array. The value to append can be anything.
56+
Fails if the datastore key does not exist. A coordination backend is recommended.
5357
* ``kv.delete_entry_property`` - Delete a property from a named entry of a JSON
5458
serialized object in the datastore. If the entry is empty, delete it as well.
5559
Fails if the datastore key does not exist. A coordination backend is recommended.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import json
2+
3+
from st2common.services import coordination as coordination_service
4+
5+
from lib.action import St2BaseAction
6+
7+
__all__ = [
8+
'St2KVPAppendEntryPropertyAction'
9+
]
10+
11+
12+
class St2KVPAppendEntryPropertyAction(St2BaseAction):
13+
# noinspection PyShadowingBuiltins
14+
def run(self, key, entry, property, value):
15+
with coordination_service.get_coordinator().get_lock('st2.kv_entry.' + key):
16+
# get and deserialize object or fail.
17+
_key = self.client.keys.get_by_name(key, decrypt=False)
18+
19+
if not _key:
20+
raise Exception("Key does not exist in datastore")
21+
22+
# optimistically try to decode a json value
23+
try:
24+
value = json.loads(value)
25+
except (TypeError, ValueError):
26+
# assume it is either already decoded (TypeError)
27+
# or it is a plain string (ValueError)
28+
# (malformed JSON objects/arrays will be strings)
29+
pass
30+
31+
deserialized = json.loads(_key.value)
32+
33+
# update or insert object.entry.property
34+
_entry = deserialized.get(entry, {})
35+
_property = _entry.get(property, [])
36+
try:
37+
_property.append(value)
38+
except AttributeError:
39+
raise Exception("Cannot append. Property {}.{}.{} is not an array!".format(key, entry, property))
40+
41+
_entry[property] = _property
42+
deserialized[entry] = _entry
43+
44+
# re-serialize and save
45+
serialized = json.dumps(deserialized)
46+
kvp = self._kvp(name=key, value=serialized)
47+
kvp.id = key
48+
49+
self.client.keys.update(kvp)
50+
response = {
51+
'key': key,
52+
'entry_name': entry,
53+
'entry': _entry,
54+
}
55+
return response
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
name: 'kv.append_entry_property'
3+
enabled: true
4+
description: |
5+
Add a value to the end of an array property under a named entry (sub-object)
6+
of a serialized object in kv datastore.
7+
Fails if the key does not exist in the datastore, as a property inside it can't be appended to yet.
8+
The kv object uses this structure: { entry: { property: [value, value], ...}, ...}
9+
This action does not support encrypted datastore objects.
10+
11+
runner_type: python-script
12+
entry_point: kv_append_entry_property.py
13+
parameters:
14+
key:
15+
required: true
16+
type: string
17+
entry:
18+
description: name of the key's entry
19+
required: false
20+
type: string
21+
default: default
22+
property:
23+
description: name of the entry's property to append to (property should have an array value)
24+
required: true
25+
type: string
26+
value:
27+
description: the value may be any json-serializable type (string, number, array, object)
28+
required: true
29+
# type: any

actions/kv_delete_entry_property.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name: 'kv.delete_entry_property'
33
enabled: true
44
description: |
5-
Delete a property (if it exists) under an named entry (sub-object) of a
5+
Delete a property (if it exists) under a named entry (sub-object) of a
66
serialized object in kv datastore. If the entry is empty after deleting
77
the property, this deletes the entry as well.
88
Fails if the key does not exist in the datastore.

actions/kv_upsert_entry_property.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name: 'kv.upsert_entry_property'
33
enabled: true
44
description: |
5-
Insert or update a property under an named entry (sub-object) of a serialized object in kv datastore.
5+
Insert or update a property under a named entry (sub-object) of a serialized object in kv datastore.
66
Fails if the key does not exist in the datastore, as a property inside it can't be upserted yet.
77
The kv object uses this structure: { entry: { property: value, ... }, entry: {}, ...}
88
This action does not support encrypted datastore objects.
@@ -23,6 +23,6 @@ parameters:
2323
required: true
2424
type: string
2525
value:
26-
description: the property value may be any json-serialible type (string, number, array, object)
26+
description: the property value may be any json-serializable type (string, number, array, object)
2727
required: true
2828
# type: any

0 commit comments

Comments
 (0)