Skip to content

Commit dfe6ab0

Browse files
committed
Merge branch 'task/tag-metadata' into 'master'
node: Add support for node tags and metadata management See merge request app-frameworks/esp-rainmaker-cli!83
2 parents ef273a2 + 4c596c8 commit dfe6ab0

13 files changed

Lines changed: 754 additions & 17 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
All major changes to ESP RainMaker CLI will be documented in this file.
44

5+
## [1.11.0] - 09-Feb-2-26
6+
- Add support for Tags and Metadata during provisioning and also after mapping a user. Check `provision`
7+
and `node` commands
8+
59
## [1.10.0] - 22-Jan-2026
610
### Added
711
- BLE local control support for `getparams`, `setparams`, and `getnodeconfig` commands during provisioning phase:

docs/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ The CLI supports the following main commands:
5959
* `getnodestatus` - Get online/offline status of the node
6060
* `getnodedetails` - Get detailed information for all nodes or a specific node
6161
* `removenode` - Remove user node mapping
62+
* `node add-tags` - Add tags to a node
63+
* `node remove-tags` - Remove tags from a node
64+
* `node set-metadata` - Set or update metadata for a node
65+
* `node delete-metadata` - Delete metadata from a node
6266

6367
### Parameter Management
6468

@@ -105,6 +109,7 @@ For detailed documentation on specific commands, refer to the following files:
105109
* [Node Sharing](./commands/node_sharing.md)
106110
* [Parameter Management](./commands/parameters.md)
107111
* [Node Management](./commands/node_management.md)
112+
* [Node Tags and Metadata](./commands/node_tags_metadata.md)
108113
* [Claiming](./commands/claiming.md)
109114
* [Provisioning](./commands/provisioning.md)
110115
* [Command Response](./commands/command_response.md)

docs/commands/node_management.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,26 @@ esp-rainmaker-cli removenode abcd1234
202202

203203
This removes the association between your user account and the node. The node will need to be claimed again before it can be used.
204204

205+
### Managing Tags and Metadata
206+
207+
Use the `node` command to add/remove tags and set/delete metadata on existing nodes. See the [Node Tags and Metadata](./node_tags_metadata.md) documentation for full details.
208+
209+
```bash
210+
# Add tags
211+
esp-rainmaker-cli node add-tags <nodeid> --tags "location:pune,name:espressif"
212+
213+
# Remove tags
214+
esp-rainmaker-cli node remove-tags <nodeid> --tags "location:pune"
215+
216+
# Set metadata
217+
esp-rainmaker-cli node set-metadata <nodeid> --data '{"serial_no": "abc123"}'
218+
219+
# Delete metadata
220+
esp-rainmaker-cli node delete-metadata <nodeid> --key "serial_no"
221+
```
222+
223+
Tags and metadata can also be attached during provisioning via the `--tags` and `--metadata` options on the `provision` command.
224+
205225
## Understanding Node Information
206226

207227
### Node Structure
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# Node Tags and Metadata
2+
3+
## Overview
4+
5+
ESP RainMaker allows you to attach **tags** and **metadata** to nodes. Tags are simple key-value labels useful for categorization and filtering, while metadata is freeform JSON data for storing custom information about a node.
6+
7+
Tags and metadata can be:
8+
- **Set during provisioning** (at mapping time, via the `provision` command)
9+
- **Managed on existing nodes** (via the `node` command)
10+
11+
## The `node` Command
12+
13+
The `node` command provides subcommands for managing tags and metadata on existing nodes.
14+
15+
```bash
16+
esp-rainmaker-cli node --help
17+
```
18+
19+
### Add Tags
20+
21+
Add tags to a node. Tags must be in `key:value` format.
22+
23+
```bash
24+
esp-rainmaker-cli node add-tags <nodeid> --tags <tags>
25+
```
26+
27+
**Parameters:**
28+
- `<nodeid>`: Node ID (required)
29+
- `--tags`: Comma-separated list of tags in `key:value` format (required)
30+
31+
**Examples:**
32+
```bash
33+
# Add a single tag
34+
esp-rainmaker-cli node add-tags mynode123 --tags "location:pune"
35+
36+
# Add multiple tags
37+
esp-rainmaker-cli node add-tags mynode123 --tags "location:pune,name:espressif,env:production"
38+
```
39+
40+
### Remove Tags
41+
42+
Remove specific tags from a node.
43+
44+
```bash
45+
esp-rainmaker-cli node remove-tags <nodeid> --tags <tags>
46+
```
47+
48+
**Parameters:**
49+
- `<nodeid>`: Node ID (required)
50+
- `--tags`: Comma-separated list of tags to remove (required)
51+
52+
**Examples:**
53+
```bash
54+
# Remove a single tag
55+
esp-rainmaker-cli node remove-tags mynode123 --tags "location:pune"
56+
57+
# Remove multiple tags
58+
esp-rainmaker-cli node remove-tags mynode123 --tags "location:pune,env:production"
59+
```
60+
61+
### Set Metadata
62+
63+
Set or update metadata for a node. Metadata follows shadow-style merge rules:
64+
- New keys are added, existing keys are updated
65+
- Setting a key to `null` deletes that specific key
66+
- Arrays are overwritten (not merged)
67+
68+
```bash
69+
esp-rainmaker-cli node set-metadata <nodeid> --data <json>
70+
esp-rainmaker-cli node set-metadata <nodeid> --filepath <path>
71+
```
72+
73+
**Parameters:**
74+
- `<nodeid>`: Node ID (required)
75+
- `--data`: Metadata as a JSON string (mutually exclusive with `--filepath`)
76+
- `--filepath`: Path to a JSON file containing metadata (mutually exclusive with `--data`)
77+
78+
**Examples:**
79+
```bash
80+
# Set metadata using inline JSON
81+
esp-rainmaker-cli node set-metadata mynode123 --data '{"serial_no": "abc123", "region": "us"}'
82+
83+
# Set metadata from a file
84+
esp-rainmaker-cli node set-metadata mynode123 --filepath metadata.json
85+
86+
# Update a specific key (other keys are preserved)
87+
esp-rainmaker-cli node set-metadata mynode123 --data '{"region": "eu"}'
88+
89+
# Delete a specific key by setting it to null
90+
esp-rainmaker-cli node set-metadata mynode123 --data '{"region": null}'
91+
```
92+
93+
### Delete Metadata
94+
95+
Delete metadata from a node. Without `--key`, deletes all metadata. With `--key`, deletes only the specified key(s).
96+
97+
```bash
98+
esp-rainmaker-cli node delete-metadata <nodeid> [--key <keys>]
99+
```
100+
101+
**Parameters:**
102+
- `<nodeid>`: Node ID (required)
103+
- `--key`: Comma-separated list of metadata keys to delete (optional; if omitted, all metadata is deleted)
104+
105+
**Examples:**
106+
```bash
107+
# Delete specific metadata keys
108+
esp-rainmaker-cli node delete-metadata mynode123 --key "region,serial_no"
109+
110+
# Delete all metadata
111+
esp-rainmaker-cli node delete-metadata mynode123
112+
```
113+
114+
## Tags and Metadata During Provisioning
115+
116+
Tags and metadata can also be attached at the time of node mapping during provisioning. This works with all transport modes (BLE, SoftAP, on-network) and both mapping flows (traditional and challenge-response).
117+
118+
```bash
119+
esp-rainmaker-cli provision [provisioning options] --tags <tags> --metadata <json>
120+
```
121+
122+
**Parameters:**
123+
- `--tags`: Comma-separated list of tags in `key:value` format
124+
- `--metadata`: Metadata as a JSON string
125+
126+
**Examples:**
127+
```bash
128+
# BLE provisioning with tags and metadata
129+
esp-rainmaker-cli provision --pop abcd1234 \
130+
--transport ble --device_name PROV_d76c30 \
131+
--tags "location:mumbai,env:production" \
132+
--metadata '{"serial_no": "abc123", "batch": "2026-Q1"}'
133+
134+
# On-network mapping with tags
135+
esp-rainmaker-cli provision --transport on-network \
136+
--device-ip 192.168.1.50 --pop abcd1234 \
137+
--tags "esp.location:office"
138+
139+
# SoftAP provisioning with metadata only
140+
esp-rainmaker-cli provision --pop abcd1234 \
141+
--transport softap \
142+
--metadata '{"firmware": "v2.0", "hw_rev": "B"}'
143+
```
144+
145+
## Tag Format
146+
147+
Tags must follow the `key:value` format:
148+
- Both key and value are strings
149+
- Example valid tags: `location:pune`, `name:espressif`, `esp.location:mumbai`
150+
- Invalid tags (missing colon) will be rejected by the API with error code `105046`
151+
152+
## Metadata Merge Rules
153+
154+
Metadata updates follow shadow-style merge semantics:
155+
156+
| Operation | Payload | Effect |
157+
|-----------|---------|--------|
158+
| Add/update keys | `{"key": "value"}` | Upserts the specified keys |
159+
| Delete a key | `{"key": null}` | Removes that specific key |
160+
| Delete all metadata | `null` (via `delete-metadata` without `--key`) | Removes all metadata |
161+
| Overwrite array | `{"regions": ["a", "b"]}` | Replaces the entire array |
162+
| Empty object | `{}` | No change |
163+
164+
## Viewing Tags and Metadata
165+
166+
Tags and metadata for a node are displayed by the `getnodedetails` command:
167+
168+
```bash
169+
esp-rainmaker-cli getnodedetails <nodeid>
170+
```
171+
172+
The output includes `Tags` and `Metadata` sections when they are set on a node.

docs/commands/provisioning.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,23 @@ esp-rainmaker-cli provision --sec_ver 2 \
235235
--sec2_password mypass
236236
```
237237

238+
### Provisioning with Tags and Metadata
239+
240+
You can attach tags and metadata to a node at mapping time. This works with all transport modes and both mapping flows (traditional and challenge-response). See [Node Tags and Metadata](./node_tags_metadata.md) for details.
241+
242+
```bash
243+
# BLE provisioning with tags and metadata
244+
esp-rainmaker-cli provision --pop abcd1234 \
245+
--transport ble --device_name PROV_d76c30 \
246+
--tags "location:mumbai,env:production" \
247+
--metadata '{"serial_no": "abc123"}'
248+
249+
# On-network mapping with tags
250+
esp-rainmaker-cli provision --transport on-network \
251+
--device-ip 192.168.1.50 --pop abcd1234 \
252+
--tags "esp.location:office"
253+
```
254+
238255
### User-Node Mapping Without Wi-Fi Provisioning
239256
```bash
240257
# Perform challenge-response mapping and skip sending Wi-Fi credentials
@@ -272,6 +289,8 @@ This workflow will be useful for BLE-only cases in future, wherein the nodes wil
272289
| `--discovery-timeout` | mDNS discovery timeout in seconds for on-network transport (default: 5.0) | `--discovery-timeout 10.0` |
273290
| `--disable-chal-resp` | Disable challenge-response on device after successful mapping (default: True for on-network, False for BLE/SoftAP) | `--disable-chal-resp` |
274291
| `--no-disable-chal-resp` | Do NOT disable challenge-response after successful mapping (overrides `--disable-chal-resp`) | `--no-disable-chal-resp` |
292+
| `--tags` | Comma-separated tags in `key:value` format to attach during node mapping | `--tags "location:pune,name:espressif"` |
293+
| `--metadata` | Metadata as JSON string to attach during node mapping | `--metadata '{"serial_no": "abc123"}'` |
275294

276295
## Provisioning Process
277296

rainmaker/rainmaker.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import sys
88
import argparse
99
from rmaker_cmd.node import *
10+
from rmaker_cmd.node import node_add_tags, node_remove_tags, node_set_metadata, node_delete_metadata
1011
from rmaker_cmd.user import signup, login, forgot_password,\
1112
get_user_details, logout, set_region_configuration, \
1213
profile_list, profile_current, profile_switch, profile_add, profile_remove, delete_user
@@ -483,6 +484,16 @@ def main():
483484
help='Do NOT disable challenge-response on device after successful mapping.\n'
484485
'Overrides the transport-specific default behavior.')
485486

487+
provision_parser.add_argument('--tags',
488+
type=str,
489+
help='Comma-separated list of tags to attach during node mapping\n'
490+
'(e.g., "location:pune,name:espressif"). Tags must be in key:value format.')
491+
492+
provision_parser.add_argument('--metadata',
493+
type=str,
494+
help='Metadata as JSON string to attach during node mapping\n'
495+
'(e.g., \'{"serial_no": "abc123", "region": "us"}\')')
496+
486497
add_profile_argument(provision_parser)
487498
provision_parser.set_defaults(func=provision)
488499

@@ -839,6 +850,89 @@ def main():
839850
add_profile_argument(group_list_nodes_parser)
840851
group_list_nodes_parser.set_defaults(func=group_list_nodes)
841852

853+
# Node Management (tags, metadata)
854+
node_parser = subparsers.add_parser('node',
855+
help='Manage node properties (tags, metadata)')
856+
node_parser.set_defaults(func=lambda vars=None: node_parser.print_help())
857+
node_subparsers = node_parser.add_subparsers(dest='node_command', help='Node operations')
858+
859+
# node add-tags
860+
node_add_tags_parser = node_subparsers.add_parser('add-tags',
861+
help='Add tags to a node',
862+
description='Add tags to a node. Tags must be in key:value format.')
863+
node_add_tags_parser.add_argument('nodeid',
864+
type=str,
865+
metavar='<nodeid>',
866+
help='Node ID for the node')
867+
node_add_tags_parser.add_argument('--tags',
868+
type=str,
869+
required=True,
870+
metavar='<tags>',
871+
help='Comma-separated list of tags in key:value format\n'
872+
'(e.g., "location:pune,name:espressif")')
873+
add_profile_argument(node_add_tags_parser)
874+
node_add_tags_parser.set_defaults(func=node_add_tags)
875+
876+
# node remove-tags
877+
node_remove_tags_parser = node_subparsers.add_parser('remove-tags',
878+
help='Remove tags from a node',
879+
description='Remove specific tags from a node.')
880+
node_remove_tags_parser.add_argument('nodeid',
881+
type=str,
882+
metavar='<nodeid>',
883+
help='Node ID for the node')
884+
node_remove_tags_parser.add_argument('--tags',
885+
type=str,
886+
required=True,
887+
metavar='<tags>',
888+
help='Comma-separated list of tags to remove\n'
889+
'(e.g., "location:pune,name:espressif")')
890+
add_profile_argument(node_remove_tags_parser)
891+
node_remove_tags_parser.set_defaults(func=node_remove_tags)
892+
893+
# node set-metadata
894+
node_set_metadata_parser = node_subparsers.add_parser('set-metadata',
895+
help='Set or update metadata for a node',
896+
description='Set or update metadata for a node.\n'
897+
'Follows shadow-style merge rules:\n'
898+
' - New keys are added, existing keys are updated\n'
899+
' - Set a key to null to delete it\n'
900+
' - Arrays are overwritten (not merged)')
901+
node_set_metadata_parser.add_argument('nodeid',
902+
type=str,
903+
metavar='<nodeid>',
904+
help='Node ID for the node')
905+
node_set_metadata_data_group = node_set_metadata_parser.add_mutually_exclusive_group(required=True)
906+
node_set_metadata_data_group.add_argument('--data',
907+
type=str,
908+
metavar='<json>',
909+
help='Metadata as JSON string\n'
910+
'(e.g., \'{"key": "value", "region": "us"}\')')
911+
node_set_metadata_data_group.add_argument('--filepath',
912+
type=str,
913+
metavar='<path>',
914+
help='Path to JSON file containing metadata')
915+
add_profile_argument(node_set_metadata_parser)
916+
node_set_metadata_parser.set_defaults(func=node_set_metadata)
917+
918+
# node delete-metadata
919+
node_delete_metadata_parser = node_subparsers.add_parser('delete-metadata',
920+
help='Delete metadata from a node',
921+
description='Delete metadata from a node.\n'
922+
'Without --key, deletes all metadata.\n'
923+
'With --key, deletes only the specified key(s).')
924+
node_delete_metadata_parser.add_argument('nodeid',
925+
type=str,
926+
metavar='<nodeid>',
927+
help='Node ID for the node')
928+
node_delete_metadata_parser.add_argument('--key',
929+
type=str,
930+
metavar='<keys>',
931+
help='Comma-separated list of metadata keys to delete\n'
932+
'(e.g., "region,name"). If omitted, all metadata is deleted.')
933+
add_profile_argument(node_delete_metadata_parser)
934+
node_delete_metadata_parser.set_defaults(func=node_delete_metadata)
935+
842936
# Raw API command
843937
raw_api_parser = subparsers.add_parser('raw-api',
844938
help='Make raw API calls to RainMaker backend',

rainmaker/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
# SPDX-License-Identifier: Apache-2.0
66

77
# This file contains the version information for the ESP RainMaker CLI
8-
VERSION = "1.10.0"
8+
VERSION = "1.11.0"

0 commit comments

Comments
 (0)