acex-cli 4.6.0__tar.gz → 5.0.0__tar.gz
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.
- {acex_cli-4.6.0 → acex_cli-5.0.0}/PKG-INFO +4 -4
- {acex_cli-4.6.0 → acex_cli-5.0.0}/pyproject.toml +11 -4
- acex_cli-5.0.0/src/acex_cli/changelog.json +498 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/commands/node.py +4 -4
- {acex_cli-4.6.0 → acex_cli-5.0.0}/README.md +0 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/__init__.py +0 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/commands/__init__.py +0 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/commands/asset.py +0 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/commands/context.py +0 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/commands/logical_node.py +0 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/commands/ned.py +0 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/context.py +0 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/diff_formatters.py +0 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/main.py +0 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/output.py +0 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/print_utils.py +0 -0
- {acex_cli-4.6.0 → acex_cli-5.0.0}/src/acex_cli/sdk.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: acex-cli
|
|
3
|
-
Version:
|
|
3
|
+
Version: 5.0.0
|
|
4
4
|
Summary: ACE-X CLI - Command-line interface for ACE-X
|
|
5
5
|
License: AGPL-3.0
|
|
6
6
|
Keywords: automation,cli,control
|
|
@@ -12,9 +12,9 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.13
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.14
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.15
|
|
15
|
-
Requires-Dist: acex-client (>=4.
|
|
16
|
-
Requires-Dist: acex-devkit (>=
|
|
17
|
-
Requires-Dist: acex-driver-cisco-ioscli (>=
|
|
15
|
+
Requires-Dist: acex-client (>=4.12.0,<5.0.0)
|
|
16
|
+
Requires-Dist: acex-devkit (>=3.0.0,<4.0.0)
|
|
17
|
+
Requires-Dist: acex-driver-cisco-ioscli (>=5.1.0,<6.0.0)
|
|
18
18
|
Requires-Dist: click (>=8.1.7)
|
|
19
19
|
Requires-Dist: ntc-templates (>=8.1.0)
|
|
20
20
|
Requires-Dist: rich (>=13.0.0)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "acex-cli"
|
|
3
|
-
version = "
|
|
3
|
+
version = "5.0.0"
|
|
4
4
|
description = "ACE-X CLI - Command-line interface for ACE-X"
|
|
5
5
|
authors = ["Johan Lahti <johan.lahti@acebit.se>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -17,9 +17,9 @@ python = "^3.13"
|
|
|
17
17
|
typer = ">=0.12.0"
|
|
18
18
|
rich = ">=13.0.0"
|
|
19
19
|
click = ">=8.1.7"
|
|
20
|
-
acex-client = "^4.
|
|
21
|
-
acex-devkit = "^
|
|
22
|
-
acex-driver-cisco-ioscli = "^
|
|
20
|
+
acex-client = "^4.12.0" # Changes to real dep. by switch_acex_client_dep for publishing
|
|
21
|
+
acex-devkit = "^3.0.0"
|
|
22
|
+
acex-driver-cisco-ioscli = "^5.1.0"
|
|
23
23
|
ntc-templates = ">=8.1.0"
|
|
24
24
|
|
|
25
25
|
[tool.poetry.scripts]
|
|
@@ -29,6 +29,13 @@ acex = "acex_cli.main:app"
|
|
|
29
29
|
pytest = "^8.0.0"
|
|
30
30
|
pytest-asyncio = "^0.23.0"
|
|
31
31
|
|
|
32
|
+
[tool.poetry.plugins."acex.changelog"]
|
|
33
|
+
acex-cli = "acex_cli"
|
|
34
|
+
|
|
35
|
+
# Shown as the component's name in Settings > What's new.
|
|
36
|
+
[tool.acex.changelog]
|
|
37
|
+
name = "ACEX CLI"
|
|
38
|
+
|
|
32
39
|
[build-system]
|
|
33
40
|
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
34
41
|
build-backend = "poetry.core.masonry.api"
|
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema_version": 1,
|
|
3
|
+
"component": "acex-cli",
|
|
4
|
+
"name": "ACEX CLI",
|
|
5
|
+
"releases": [
|
|
6
|
+
{
|
|
7
|
+
"version": "5.0.0",
|
|
8
|
+
"date": "2026-11-06",
|
|
9
|
+
"entries": [
|
|
10
|
+
{
|
|
11
|
+
"id": "20261013-node-status-is-split-into-admin-status-a",
|
|
12
|
+
"kind": "changed",
|
|
13
|
+
"title": "Node `status` is split into `admin_status` and `provision_status`",
|
|
14
|
+
"description": "`acex node list` no longer has `--status`; use `--admin-status` (planned, active, decommissioned) and `--provision-status` instead. The node table, `acex node show`, and JSON/CSV output now carry `admin_status` and `provision_status` instead of `status`, so scripts that read `status` or pass `--columns status` must be updated. Needs a server that has the same change.",
|
|
15
|
+
"breaking": true,
|
|
16
|
+
"audience": "user",
|
|
17
|
+
"refs": [
|
|
18
|
+
{
|
|
19
|
+
"label": "#292",
|
|
20
|
+
"url": null
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"version": "4.5.1",
|
|
28
|
+
"date": "2026-09-02",
|
|
29
|
+
"summary": "The compact and flat diff views work with changes, and `acex version` prints a version again.",
|
|
30
|
+
"entries": [
|
|
31
|
+
{
|
|
32
|
+
"id": "01-acex-node-config-diff-plan-f-compact-and",
|
|
33
|
+
"kind": "fixed",
|
|
34
|
+
"title": "`acex node config diff plan -f compact` and `-f flat` work with changes",
|
|
35
|
+
"description": "Both views used a field name that does not exist on the diff objects, so they should have stopped with a Python error whenever the diff was not empty. They now read the right field and list added, removed and changed components.",
|
|
36
|
+
"breaking": false,
|
|
37
|
+
"audience": "user",
|
|
38
|
+
"refs": [
|
|
39
|
+
{
|
|
40
|
+
"label": "#207",
|
|
41
|
+
"url": null
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": "02-acex-version-prints-a-version-again-but-",
|
|
47
|
+
"kind": "fixed",
|
|
48
|
+
"title": "`acex version` prints a version again, but it still says 0.2.0",
|
|
49
|
+
"description": "The command no longer fails on a missing output helper. The number it prints comes from a constant that was never updated, so it reports 0.2.0 whatever release is installed.",
|
|
50
|
+
"breaking": false,
|
|
51
|
+
"audience": "user",
|
|
52
|
+
"refs": [
|
|
53
|
+
{
|
|
54
|
+
"label": "#207",
|
|
55
|
+
"url": null
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"id": "03-management-connection-lookups-use-the-ap",
|
|
61
|
+
"kind": "fixed",
|
|
62
|
+
"title": "Management connection lookups use the API path without a trailing slash",
|
|
63
|
+
"description": "`acex node show` (management address, port and protocol), `acex node connect` and `acex node config diff apply` now request the node's management connection from the path without a trailing slash, matching the server change in this release. Against a server that expects the old path, these commands would fail to find the connection.",
|
|
64
|
+
"breaking": false,
|
|
65
|
+
"audience": "user",
|
|
66
|
+
"refs": [
|
|
67
|
+
{
|
|
68
|
+
"label": "#251",
|
|
69
|
+
"url": null
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"version": "4.5.0",
|
|
77
|
+
"date": "2026-04-22",
|
|
78
|
+
"entries": [
|
|
79
|
+
{
|
|
80
|
+
"id": "01-acex-node-connect-node-opens-an-ssh-sess",
|
|
81
|
+
"kind": "added",
|
|
82
|
+
"title": "`acex node connect NODE` opens an SSH session to the node",
|
|
83
|
+
"description": "Looks up the node's management connection and starts `ssh` to its address, replacing the `acex` process. It uses your local `ssh` and login name, and exits with status 1 if there is no connection, it is not SSH, or it has no address.",
|
|
84
|
+
"breaking": false,
|
|
85
|
+
"audience": "user",
|
|
86
|
+
"refs": [
|
|
87
|
+
{
|
|
88
|
+
"label": "#126",
|
|
89
|
+
"url": null
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"version": "4.4.1",
|
|
97
|
+
"date": "2026-04-22",
|
|
98
|
+
"entries": [
|
|
99
|
+
{
|
|
100
|
+
"id": "01-acex-node-show-also-shows-the-management",
|
|
101
|
+
"kind": "added",
|
|
102
|
+
"title": "`acex node show` also shows the management address, port and protocol",
|
|
103
|
+
"description": "The node details now include `mgmt_target_ip`, `mgmt_target_port` and `mgmt_protocol` from the node's first management connection. If the connection cannot be fetched, the command still prints the rest. The `id` field is filled in even when the API response leaves it out.",
|
|
104
|
+
"breaking": false,
|
|
105
|
+
"audience": "user",
|
|
106
|
+
"refs": [
|
|
107
|
+
{
|
|
108
|
+
"label": "#122",
|
|
109
|
+
"url": null
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"version": "4.3.1",
|
|
117
|
+
"date": "2026-04-21",
|
|
118
|
+
"entries": [
|
|
119
|
+
{
|
|
120
|
+
"id": "01-acex-node-config-show-desired-no-longer-",
|
|
121
|
+
"kind": "fixed",
|
|
122
|
+
"title": "`acex node config show desired` no longer prints a debug timing line",
|
|
123
|
+
"description": "The \"[debug] sdk init: ...\" line that 4.3.0 printed after the output is gone, and `--render` no longer ends with a Python error.",
|
|
124
|
+
"breaking": false,
|
|
125
|
+
"audience": "user",
|
|
126
|
+
"refs": [
|
|
127
|
+
{
|
|
128
|
+
"label": "#119",
|
|
129
|
+
"url": null
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"version": "4.3.0",
|
|
137
|
+
"date": "2026-04-21",
|
|
138
|
+
"entries": [
|
|
139
|
+
{
|
|
140
|
+
"id": "01-acex-logical-node-and-acex-ned-list-and-",
|
|
141
|
+
"kind": "added",
|
|
142
|
+
"title": "`acex logical-node` and `acex ned` list and show commands",
|
|
143
|
+
"description": "`acex logical-node list|show LOGICAL_NODE_ID` and `acex ned list|show NED_ID` print logical nodes and network element drivers. Command groups with underscores in their code name are typed with hyphens.",
|
|
144
|
+
"breaking": false,
|
|
145
|
+
"audience": "user",
|
|
146
|
+
"refs": [
|
|
147
|
+
{
|
|
148
|
+
"label": "#115",
|
|
149
|
+
"url": null
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"id": "06-acex-node-config-show-local-node-dir-dir",
|
|
155
|
+
"kind": "added",
|
|
156
|
+
"title": "`acex node config show local NODE --dir DIR` compiles config from local files",
|
|
157
|
+
"description": "Builds the configuration for a node from the config map files in a local directory, without publishing them, and shows it like `show desired` (`--render`, `--path`, `--format` work the same). It needs the `acex` backend package installed and reports which config maps were found and matched.",
|
|
158
|
+
"breaking": false,
|
|
159
|
+
"audience": "user",
|
|
160
|
+
"refs": [
|
|
161
|
+
{
|
|
162
|
+
"label": "#115",
|
|
163
|
+
"url": null
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"id": "03-filter-and-page-asset-list-node-list-and",
|
|
169
|
+
"kind": "added",
|
|
170
|
+
"title": "Filter and page `asset list`, `node list` and `logical-node list`",
|
|
171
|
+
"description": "`asset list` filters on `--vendor`, `--os`, `--hardware-model`, `--ned-id`, `--serial-number` and `--assigned`; `node list` on `--site`, `--hostname`, `--logical-node-id`, `--asset-ref-id` and `--status`; `logical-node list` on `--role`, `--site`, `--hostname`, `--sequence` and `--assigned`. All three return at most 100 rows unless `--limit` (`-l`) and `--offset` say otherwise, and the table shows \"Showing 1-100 of N\" when more exist.",
|
|
172
|
+
"breaking": false,
|
|
173
|
+
"audience": "user",
|
|
174
|
+
"refs": [
|
|
175
|
+
{
|
|
176
|
+
"label": "#115",
|
|
177
|
+
"url": null
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"id": "02-output-as-table-json-or-csv-with-format-",
|
|
183
|
+
"kind": "added",
|
|
184
|
+
"title": "Output as table, JSON or CSV with `--format`, `--columns` and `--no-header`",
|
|
185
|
+
"description": "All `list` and `show` commands for assets, nodes, logical nodes and NEDs take `--format` (`-f`) `table`, `json` or `csv`, plus `--columns` (`-c`) with a comma-separated list of columns. `list` commands also take `--no-header`, which makes the output easier to use in scripts.",
|
|
186
|
+
"breaking": false,
|
|
187
|
+
"audience": "user",
|
|
188
|
+
"refs": [
|
|
189
|
+
{
|
|
190
|
+
"label": "#115",
|
|
191
|
+
"url": null
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"id": "05-acex-node-config-show-desired-observed-g",
|
|
197
|
+
"kind": "changed",
|
|
198
|
+
"title": "`acex node config show desired|observed` give a section overview and `--path`",
|
|
199
|
+
"description": "Without `--render` they now print a table of configuration sections with component counts; `--path system.ntp` (or another section) drills in, and `--format json` dumps everything. `--render` prints the device configuration with line numbers and syntax highlighting.",
|
|
200
|
+
"breaking": false,
|
|
201
|
+
"audience": "user",
|
|
202
|
+
"refs": [
|
|
203
|
+
{
|
|
204
|
+
"label": "#115",
|
|
205
|
+
"url": null
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"id": "07-node-and-configuration-lookups-that-find",
|
|
211
|
+
"kind": "changed",
|
|
212
|
+
"title": "Node and configuration lookups that find nothing now exit with status 1",
|
|
213
|
+
"description": "`acex node show`, `config show observed`, `config diff plan` and `config diff apply` exit with status 1 for an unknown node or a missing configuration, with \"Node 'X' not found.\", \"No observed config found.\" or \"No desired configuration found.\". Earlier versions printed the message and exited with 0.",
|
|
214
|
+
"breaking": false,
|
|
215
|
+
"audience": "user",
|
|
216
|
+
"refs": [
|
|
217
|
+
{
|
|
218
|
+
"label": "#115",
|
|
219
|
+
"url": null
|
|
220
|
+
}
|
|
221
|
+
]
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"id": "04-node-commands-accept-a-hostname-as-well-",
|
|
225
|
+
"kind": "changed",
|
|
226
|
+
"title": "Node commands accept a hostname as well as an ID",
|
|
227
|
+
"description": "`acex node show`, `acex node config show ...` and `acex node config diff ...` take `NODE` as a numeric ID or a hostname. If several nodes share the hostname, they are listed and the command asks for the ID.",
|
|
228
|
+
"breaking": false,
|
|
229
|
+
"audience": "user",
|
|
230
|
+
"refs": [
|
|
231
|
+
{
|
|
232
|
+
"label": "#115",
|
|
233
|
+
"url": null
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"id": "09-the-could-not-connect-to-api-message-is-",
|
|
239
|
+
"kind": "changed",
|
|
240
|
+
"title": "The \"Could not connect to API\" message is no longer shown",
|
|
241
|
+
"description": "Commands no longer test the API address first, so an unreachable or untrusted server is no longer reported with that message. What appears instead comes from the client library, and its wording is not confirmed.",
|
|
242
|
+
"breaking": false,
|
|
243
|
+
"audience": "user",
|
|
244
|
+
"refs": [
|
|
245
|
+
{
|
|
246
|
+
"label": "#115",
|
|
247
|
+
"url": null
|
|
248
|
+
}
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
]
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
"version": "4.1.3",
|
|
255
|
+
"date": "2026-03-18",
|
|
256
|
+
"entries": [
|
|
257
|
+
{
|
|
258
|
+
"id": "01-acex-node-config-diff-apply-node-id-push",
|
|
259
|
+
"kind": "added",
|
|
260
|
+
"title": "`acex node config diff apply NODE_ID` pushes the planned changes to a device",
|
|
261
|
+
"description": "It works out the difference between observed and desired configuration, prints the device commands in a box and asks \"Are you sure you want to apply the config above?\". On yes it sends them over the node's first management connection; on no it exits without changes (exit status 0).",
|
|
262
|
+
"breaking": false,
|
|
263
|
+
"audience": "user",
|
|
264
|
+
"refs": [
|
|
265
|
+
{
|
|
266
|
+
"label": "#72",
|
|
267
|
+
"url": null
|
|
268
|
+
}
|
|
269
|
+
]
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"id": "03-acex-node-config-diff-plan-f-commands-pr",
|
|
273
|
+
"kind": "changed",
|
|
274
|
+
"title": "`acex node config diff plan -f commands` prints driver-rendered patch commands",
|
|
275
|
+
"description": "The `commands` format now asks the device driver to render the patch for the node, the same text that `diff apply` shows before asking for confirmation.",
|
|
276
|
+
"breaking": false,
|
|
277
|
+
"audience": "user",
|
|
278
|
+
"refs": [
|
|
279
|
+
{
|
|
280
|
+
"label": "#72",
|
|
281
|
+
"url": null
|
|
282
|
+
}
|
|
283
|
+
]
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
"id": "02-acex-node-config-diff-plan-shows-changes",
|
|
287
|
+
"kind": "changed",
|
|
288
|
+
"title": "`acex node config diff plan` shows changes per component and attribute",
|
|
289
|
+
"description": "The `tree`, `compact`, `flat` and `summary` views now list added, removed and changed components, with before and after values per changed attribute; `flat` is a table of Type, Component, Attribute, Before and After. Output from earlier versions looked different, so scripts that parse it need to be checked.",
|
|
290
|
+
"breaking": false,
|
|
291
|
+
"audience": "user",
|
|
292
|
+
"refs": [
|
|
293
|
+
{
|
|
294
|
+
"label": "#70",
|
|
295
|
+
"url": null
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"label": "#81",
|
|
299
|
+
"url": null
|
|
300
|
+
}
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
]
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
"version": "4.1.0",
|
|
307
|
+
"date": "2026-02-13",
|
|
308
|
+
"entries": [
|
|
309
|
+
{
|
|
310
|
+
"id": "03-acex-node-config-diff-plan-node-id-shows",
|
|
311
|
+
"kind": "added",
|
|
312
|
+
"title": "`acex node config diff plan NODE_ID` shows what would change on a node",
|
|
313
|
+
"description": "Compares the latest observed configuration with the desired one. `--format` (`-f`) selects `tree` (default), `compact`, `flat`, `summary` or `json`; `--max-depth` (`-d`) and `--no-values` shorten the tree view. A `commands` format is also accepted, but is not listed in the help; it appears to print device commands.",
|
|
314
|
+
"breaking": false,
|
|
315
|
+
"audience": "user",
|
|
316
|
+
"refs": [
|
|
317
|
+
{
|
|
318
|
+
"label": "#49",
|
|
319
|
+
"url": null
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
"label": "#52",
|
|
323
|
+
"url": null
|
|
324
|
+
}
|
|
325
|
+
]
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"id": "01-acex-node-config-show-desired-node-id-pr",
|
|
329
|
+
"kind": "added",
|
|
330
|
+
"title": "`acex node config show desired NODE_ID` prints the desired configuration",
|
|
331
|
+
"description": "Prints the configuration defined for the node as JSON, or as device configuration text with `--render`. A `--path` option is accepted but has no effect yet.",
|
|
332
|
+
"breaking": false,
|
|
333
|
+
"audience": "user",
|
|
334
|
+
"refs": [
|
|
335
|
+
{
|
|
336
|
+
"label": "#48",
|
|
337
|
+
"url": null
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"label": "#49",
|
|
341
|
+
"url": null
|
|
342
|
+
}
|
|
343
|
+
]
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
"id": "02-acex-node-config-show-observed-node-id-p",
|
|
347
|
+
"kind": "added",
|
|
348
|
+
"title": "`acex node config show observed NODE_ID` prints the latest backed-up config",
|
|
349
|
+
"description": "Prints the last configuration read from the device as parsed JSON, or as device configuration text with `--render`. Prints \"No observed config found.\" when there is none.",
|
|
350
|
+
"breaking": false,
|
|
351
|
+
"audience": "user",
|
|
352
|
+
"refs": [
|
|
353
|
+
{
|
|
354
|
+
"label": "#48",
|
|
355
|
+
"url": null
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
"label": "#49",
|
|
359
|
+
"url": null
|
|
360
|
+
}
|
|
361
|
+
]
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"id": "04-acex-starts-again-after-the-start-up-fai",
|
|
365
|
+
"kind": "fixed",
|
|
366
|
+
"title": "`acex` starts again after the start-up failure in 0.2.5",
|
|
367
|
+
"description": "The undefined option type in the node commands is gone, so the `acex` command loads normally.",
|
|
368
|
+
"breaking": false,
|
|
369
|
+
"audience": "user",
|
|
370
|
+
"refs": [
|
|
371
|
+
{
|
|
372
|
+
"label": "#47",
|
|
373
|
+
"url": null
|
|
374
|
+
}
|
|
375
|
+
]
|
|
376
|
+
}
|
|
377
|
+
]
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"version": "0.2.5",
|
|
381
|
+
"date": "2026-02-10",
|
|
382
|
+
"entries": [
|
|
383
|
+
{
|
|
384
|
+
"id": "02-acex-node-config-observed-node-id-prints",
|
|
385
|
+
"kind": "added",
|
|
386
|
+
"title": "`acex node config observed NODE_ID` prints the latest backed-up configuration",
|
|
387
|
+
"description": "Prints the last configuration stored for a node, as device text by default or as JSON with `--format json` (`-f`), or a specific backup with `--hash`. In this release it cannot be used, because `acex` itself fails to start (see the next entry).",
|
|
388
|
+
"breaking": false,
|
|
389
|
+
"audience": "user",
|
|
390
|
+
"refs": [
|
|
391
|
+
{
|
|
392
|
+
"label": "#44",
|
|
393
|
+
"url": null
|
|
394
|
+
}
|
|
395
|
+
]
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"id": "01-clear-message-when-the-acex-api-cannot-b",
|
|
399
|
+
"kind": "added",
|
|
400
|
+
"title": "Clear message when the ACEX API cannot be reached",
|
|
401
|
+
"description": "Before running a command, `acex` now contacts the API address of the active context. If the connection fails it prints \"Could not connect to API!\" plus the reason, and for a certificate problem \"Could not connect to API due to untrusted certificate!\"; it then stops with exit status 0, so scripts cannot detect the failure from the status.",
|
|
402
|
+
"breaking": false,
|
|
403
|
+
"audience": "user",
|
|
404
|
+
"refs": [
|
|
405
|
+
{
|
|
406
|
+
"label": "#44",
|
|
407
|
+
"url": null
|
|
408
|
+
}
|
|
409
|
+
]
|
|
410
|
+
}
|
|
411
|
+
]
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
"version": "0.2.1",
|
|
415
|
+
"date": "2026-01-29",
|
|
416
|
+
"entries": [
|
|
417
|
+
{
|
|
418
|
+
"id": "03-placeholder-commands-acex-run-acex-list-",
|
|
419
|
+
"kind": "removed",
|
|
420
|
+
"title": "Placeholder commands `acex run`, `acex list` and `acex status` are gone",
|
|
421
|
+
"description": "These three commands did nothing but print a message and have been removed. Use `acex node list`, `acex asset list` and the `acex context` commands instead.",
|
|
422
|
+
"breaking": false,
|
|
423
|
+
"audience": "user",
|
|
424
|
+
"refs": [
|
|
425
|
+
{
|
|
426
|
+
"label": "#35",
|
|
427
|
+
"url": null
|
|
428
|
+
}
|
|
429
|
+
]
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
"id": "02-choose-which-acex-api-to-talk-to-with-ac",
|
|
433
|
+
"kind": "added",
|
|
434
|
+
"title": "Choose which ACEX API to talk to with `acex context`",
|
|
435
|
+
"description": "`acex context add --name NAME --url URL` saves and activates an API address (`--no-verify-ssl` skips certificate checking). `acex context list`, `use NAME`, `show` and `verify-ssl true|false` manage saved contexts, which are kept in `~/.acex/.acex_cli_context.json`. Without an active context, node and asset commands report that none is selected.",
|
|
436
|
+
"breaking": false,
|
|
437
|
+
"audience": "user",
|
|
438
|
+
"refs": [
|
|
439
|
+
{
|
|
440
|
+
"label": "#35",
|
|
441
|
+
"url": null
|
|
442
|
+
}
|
|
443
|
+
]
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"id": "01-list-and-show-nodes-and-assets-with-acex",
|
|
447
|
+
"kind": "added",
|
|
448
|
+
"title": "List and show nodes and assets with `acex node` and `acex asset`",
|
|
449
|
+
"description": "`acex node list`, `acex node show NODE_ID`, `acex asset list` and `acex asset show ASSET_ID` fetch data from the ACEX API and print it as a table (one row per item, or a Field/Value table for `show`). An empty list prints \"No nodes found.\" or \"No assets found.\".",
|
|
450
|
+
"breaking": false,
|
|
451
|
+
"audience": "user",
|
|
452
|
+
"refs": [
|
|
453
|
+
{
|
|
454
|
+
"label": "#35",
|
|
455
|
+
"url": null
|
|
456
|
+
}
|
|
457
|
+
]
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
"id": "04-shell-completion-is-enabled-for-acex",
|
|
461
|
+
"kind": "changed",
|
|
462
|
+
"title": "Shell completion is enabled for `acex`",
|
|
463
|
+
"description": "The command now offers the standard `--install-completion` and `--show-completion` options. Running `acex` with no sub-command prints the help text.",
|
|
464
|
+
"breaking": false,
|
|
465
|
+
"audience": "user",
|
|
466
|
+
"refs": [
|
|
467
|
+
{
|
|
468
|
+
"label": "#35",
|
|
469
|
+
"url": null
|
|
470
|
+
}
|
|
471
|
+
]
|
|
472
|
+
}
|
|
473
|
+
]
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"version": "0.2.0",
|
|
477
|
+
"date": "2025-11-04",
|
|
478
|
+
"entries": [
|
|
479
|
+
{
|
|
480
|
+
"id": "01-first-acex-command-with-version-run-list",
|
|
481
|
+
"kind": "added",
|
|
482
|
+
"title": "First `acex` command with `version`, `run`, `list` and `status`",
|
|
483
|
+
"description": "The `acex` command exists, with `acex version`, `acex run FILE`, `acex list` and `acex status`.",
|
|
484
|
+
"breaking": false,
|
|
485
|
+
"audience": "user",
|
|
486
|
+
"refs": [
|
|
487
|
+
{
|
|
488
|
+
"label": "83efd0b",
|
|
489
|
+
"url": null
|
|
490
|
+
}
|
|
491
|
+
]
|
|
492
|
+
}
|
|
493
|
+
]
|
|
494
|
+
}
|
|
495
|
+
],
|
|
496
|
+
"coming": [],
|
|
497
|
+
"highlights": []
|
|
498
|
+
}
|
|
@@ -45,7 +45,7 @@ def _decode_config_content(content: str) -> str:
|
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
def _fetch_node_instance(sdk, identifier: str):
|
|
48
|
-
"""Resolve identifier to full
|
|
48
|
+
"""Resolve identifier to full NodeInstance. Used by show/apply that need asset info."""
|
|
49
49
|
if identifier.isdigit():
|
|
50
50
|
node = sdk.node_instances.get(identifier)
|
|
51
51
|
else:
|
|
@@ -177,7 +177,7 @@ def _fetch_desired_config(sdk, identifier: str):
|
|
|
177
177
|
typer.echo("No desired configuration found.")
|
|
178
178
|
raise typer.Exit(1)
|
|
179
179
|
|
|
180
|
-
# Return quick node + config. Config commands that need full
|
|
180
|
+
# Return quick node + config. Config commands that need full NodeInstance
|
|
181
181
|
# (e.g. render, apply) will call _fetch_node_instance separately.
|
|
182
182
|
return quick, config
|
|
183
183
|
|
|
@@ -638,7 +638,7 @@ def _print_config_section(console, data: dict, path: str):
|
|
|
638
638
|
|
|
639
639
|
|
|
640
640
|
def _flatten_node(node, node_id: str = None) -> dict:
|
|
641
|
-
"""Flatten
|
|
641
|
+
"""Flatten NodeInstance into a single-level dict for display."""
|
|
642
642
|
data = node.model_dump() if hasattr(node, "model_dump") else dict(node)
|
|
643
643
|
asset = data.pop("asset", {}) or {}
|
|
644
644
|
logical_node = data.pop("logical_node", {}) or {}
|
|
@@ -666,7 +666,7 @@ def _flatten_node(node, node_id: str = None) -> dict:
|
|
|
666
666
|
|
|
667
667
|
|
|
668
668
|
def _resolve_node(sdk, identifier: str):
|
|
669
|
-
"""Resolve a node by ID or hostname. Returns
|
|
669
|
+
"""Resolve a node by ID or hostname. Returns NodeInstance or exits."""
|
|
670
670
|
# Try as numeric ID first
|
|
671
671
|
if identifier.isdigit():
|
|
672
672
|
node = sdk.node_instances.get(identifier)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|