@alwaysai/device-agent 1.5.0 → 2.0.0

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.
Files changed (273) hide show
  1. package/lib/application-control/config.d.ts.map +1 -1
  2. package/lib/application-control/config.js +8 -3
  3. package/lib/application-control/config.js.map +1 -1
  4. package/lib/application-control/environment-variables.d.ts +1 -5
  5. package/lib/application-control/environment-variables.d.ts.map +1 -1
  6. package/lib/application-control/environment-variables.js +9 -26
  7. package/lib/application-control/environment-variables.js.map +1 -1
  8. package/lib/application-control/environment-variables.test.js +27 -7
  9. package/lib/application-control/environment-variables.test.js.map +1 -1
  10. package/lib/application-control/index.d.ts +4 -4
  11. package/lib/application-control/index.d.ts.map +1 -1
  12. package/lib/application-control/index.js +1 -4
  13. package/lib/application-control/index.js.map +1 -1
  14. package/lib/application-control/install.d.ts.map +1 -1
  15. package/lib/application-control/install.js +8 -7
  16. package/lib/application-control/install.js.map +1 -1
  17. package/lib/application-control/models.d.ts +0 -11
  18. package/lib/application-control/models.d.ts.map +1 -1
  19. package/lib/application-control/models.js +5 -54
  20. package/lib/application-control/models.js.map +1 -1
  21. package/lib/application-control/utils.d.ts +0 -4
  22. package/lib/application-control/utils.d.ts.map +1 -1
  23. package/lib/application-control/utils.js +1 -24
  24. package/lib/application-control/utils.js.map +1 -1
  25. package/lib/cloud-connection/bootstrap-provision.js +3 -2
  26. package/lib/cloud-connection/bootstrap-provision.js.map +1 -1
  27. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +10 -15
  28. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  29. package/lib/cloud-connection/device-agent-cloud-connection.js +279 -250
  30. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  31. package/lib/cloud-connection/device-agent.d.ts.map +1 -1
  32. package/lib/cloud-connection/device-agent.js +11 -9
  33. package/lib/cloud-connection/device-agent.js.map +1 -1
  34. package/lib/cloud-connection/live-updates-handler.d.ts +18 -28
  35. package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
  36. package/lib/cloud-connection/live-updates-handler.js +54 -169
  37. package/lib/cloud-connection/live-updates-handler.js.map +1 -1
  38. package/lib/cloud-connection/live-updates-handler.test.js +71 -165
  39. package/lib/cloud-connection/live-updates-handler.test.js.map +1 -1
  40. package/lib/cloud-connection/passthrough-handler.d.ts +4 -1
  41. package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -1
  42. package/lib/cloud-connection/passthrough-handler.js +30 -11
  43. package/lib/cloud-connection/passthrough-handler.js.map +1 -1
  44. package/lib/cloud-connection/shadow-handler.d.ts +5 -3
  45. package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
  46. package/lib/cloud-connection/shadow-handler.js +59 -27
  47. package/lib/cloud-connection/shadow-handler.js.map +1 -1
  48. package/lib/cloud-connection/shadow-handler.test.js +45 -57
  49. package/lib/cloud-connection/shadow-handler.test.js.map +1 -1
  50. package/lib/cloud-connection/shadow.d.ts.map +1 -1
  51. package/lib/cloud-connection/shadow.js +2 -1
  52. package/lib/cloud-connection/shadow.js.map +1 -1
  53. package/lib/cloud-connection/transaction-manager.d.ts +4 -2
  54. package/lib/cloud-connection/transaction-manager.d.ts.map +1 -1
  55. package/lib/cloud-connection/transaction-manager.js +18 -29
  56. package/lib/cloud-connection/transaction-manager.js.map +1 -1
  57. package/lib/cloud-connection/transaction-manager.test.js +3 -3
  58. package/lib/cloud-connection/transaction-manager.test.js.map +1 -1
  59. package/lib/device-control/device-control.d.ts +8 -8
  60. package/lib/device-control/device-control.d.ts.map +1 -1
  61. package/lib/device-control/device-control.js +95 -71
  62. package/lib/device-control/device-control.js.map +1 -1
  63. package/lib/docker/docker-compose.d.ts.map +1 -1
  64. package/lib/docker/docker-compose.js +2 -1
  65. package/lib/docker/docker-compose.js.map +1 -1
  66. package/lib/infrastructure/agent-config.d.ts +2 -1
  67. package/lib/infrastructure/agent-config.d.ts.map +1 -1
  68. package/lib/infrastructure/agent-config.js +7 -7
  69. package/lib/infrastructure/agent-config.js.map +1 -1
  70. package/lib/infrastructure/agent-config.test.js +3 -1
  71. package/lib/infrastructure/agent-config.test.js.map +1 -1
  72. package/lib/infrastructure/config-check-utility.d.ts +6 -0
  73. package/lib/infrastructure/config-check-utility.d.ts.map +1 -0
  74. package/lib/infrastructure/config-check-utility.js +67 -0
  75. package/lib/infrastructure/config-check-utility.js.map +1 -0
  76. package/lib/infrastructure/config-check-utility.test.d.ts +2 -0
  77. package/lib/infrastructure/config-check-utility.test.d.ts.map +1 -0
  78. package/lib/infrastructure/config-check-utility.test.js +109 -0
  79. package/lib/infrastructure/config-check-utility.test.js.map +1 -0
  80. package/lib/infrastructure/device-certificate.d.ts +10 -0
  81. package/lib/infrastructure/device-certificate.d.ts.map +1 -0
  82. package/lib/infrastructure/device-certificate.js +47 -0
  83. package/lib/infrastructure/device-certificate.js.map +1 -0
  84. package/lib/infrastructure/device-certificate.test.d.ts +2 -0
  85. package/lib/infrastructure/device-certificate.test.d.ts.map +1 -0
  86. package/lib/infrastructure/device-certificate.test.js +24 -0
  87. package/lib/infrastructure/device-certificate.test.js.map +1 -0
  88. package/lib/infrastructure/legacy-migration/legacy-file.test.d.ts +2 -0
  89. package/lib/infrastructure/legacy-migration/legacy-file.test.d.ts.map +1 -0
  90. package/lib/infrastructure/legacy-migration/legacy-file.test.js +61 -0
  91. package/lib/infrastructure/legacy-migration/legacy-file.test.js.map +1 -0
  92. package/lib/infrastructure/legacy-migration/legacy-files.d.ts +75 -0
  93. package/lib/infrastructure/legacy-migration/legacy-files.d.ts.map +1 -0
  94. package/lib/infrastructure/legacy-migration/legacy-files.js +75 -0
  95. package/lib/infrastructure/legacy-migration/legacy-files.js.map +1 -0
  96. package/lib/infrastructure/legacy-migration/legacy-migration.d.ts +6 -0
  97. package/lib/infrastructure/legacy-migration/legacy-migration.d.ts.map +1 -0
  98. package/lib/infrastructure/legacy-migration/legacy-migration.js +149 -0
  99. package/lib/infrastructure/legacy-migration/legacy-migration.js.map +1 -0
  100. package/lib/infrastructure/legacy-migration/legacy-migration.test.d.ts +2 -0
  101. package/lib/infrastructure/legacy-migration/legacy-migration.test.d.ts.map +1 -0
  102. package/lib/infrastructure/legacy-migration/legacy-migration.test.js +226 -0
  103. package/lib/infrastructure/legacy-migration/legacy-migration.test.js.map +1 -0
  104. package/lib/infrastructure/require-files-present-ready.test.d.ts +2 -0
  105. package/lib/infrastructure/require-files-present-ready.test.d.ts.map +1 -0
  106. package/lib/infrastructure/require-files-present-ready.test.js +44 -0
  107. package/lib/infrastructure/require-files-present-ready.test.js.map +1 -0
  108. package/lib/infrastructure/required-config-checks.d.ts +2 -0
  109. package/lib/infrastructure/required-config-checks.d.ts.map +1 -0
  110. package/lib/infrastructure/required-config-checks.js +30 -0
  111. package/lib/infrastructure/required-config-checks.js.map +1 -0
  112. package/lib/infrastructure/tokens-and-device-cfg.d.ts.map +1 -1
  113. package/lib/infrastructure/tokens-and-device-cfg.js +11 -8
  114. package/lib/infrastructure/tokens-and-device-cfg.js.map +1 -1
  115. package/lib/local-connection/rabbitmq-connection.d.ts.map +1 -1
  116. package/lib/local-connection/rabbitmq-connection.js +14 -14
  117. package/lib/local-connection/rabbitmq-connection.js.map +1 -1
  118. package/lib/secure-tunneling/secure-tunneling.d.ts +9 -9
  119. package/lib/secure-tunneling/secure-tunneling.d.ts.map +1 -1
  120. package/lib/secure-tunneling/secure-tunneling.js +21 -16
  121. package/lib/secure-tunneling/secure-tunneling.js.map +1 -1
  122. package/lib/secure-tunneling/secure-tunneling.test.js +11 -13
  123. package/lib/secure-tunneling/secure-tunneling.test.js.map +1 -1
  124. package/lib/subcommands/app/analytics.d.ts.map +1 -1
  125. package/lib/subcommands/app/analytics.js +1 -2
  126. package/lib/subcommands/app/analytics.js.map +1 -1
  127. package/lib/subcommands/app/env-vars.d.ts +4 -0
  128. package/lib/subcommands/app/env-vars.d.ts.map +1 -1
  129. package/lib/subcommands/app/env-vars.js +52 -6
  130. package/lib/subcommands/app/env-vars.js.map +1 -1
  131. package/lib/subcommands/app/index.d.ts.map +1 -1
  132. package/lib/subcommands/app/index.js +1 -3
  133. package/lib/subcommands/app/index.js.map +1 -1
  134. package/lib/subcommands/app/models.d.ts +0 -11
  135. package/lib/subcommands/app/models.d.ts.map +1 -1
  136. package/lib/subcommands/app/models.js +2 -58
  137. package/lib/subcommands/app/models.js.map +1 -1
  138. package/lib/subcommands/app/shadow.d.ts.map +1 -1
  139. package/lib/subcommands/app/shadow.js +6 -5
  140. package/lib/subcommands/app/shadow.js.map +1 -1
  141. package/lib/subcommands/app/version.d.ts.map +1 -1
  142. package/lib/subcommands/app/version.js +2 -4
  143. package/lib/subcommands/app/version.js.map +1 -1
  144. package/lib/subcommands/config.d.ts +2 -0
  145. package/lib/subcommands/config.d.ts.map +1 -0
  146. package/lib/subcommands/config.js +39 -0
  147. package/lib/subcommands/config.js.map +1 -0
  148. package/lib/subcommands/device/clean.d.ts +1 -1
  149. package/lib/subcommands/device/clean.d.ts.map +1 -1
  150. package/lib/subcommands/device/clean.js +23 -13
  151. package/lib/subcommands/device/clean.js.map +1 -1
  152. package/lib/subcommands/device/index.d.ts.map +1 -1
  153. package/lib/subcommands/device/index.js +3 -1
  154. package/lib/subcommands/device/index.js.map +1 -1
  155. package/lib/subcommands/device/init.js +8 -8
  156. package/lib/subcommands/device/init.js.map +1 -1
  157. package/lib/subcommands/device/migrate.d.ts +2 -0
  158. package/lib/subcommands/device/migrate.d.ts.map +1 -0
  159. package/lib/subcommands/device/migrate.js +24 -0
  160. package/lib/subcommands/device/migrate.js.map +1 -0
  161. package/lib/subcommands/device/refresh.d.ts.map +1 -1
  162. package/lib/subcommands/device/refresh.js +1 -0
  163. package/lib/subcommands/device/refresh.js.map +1 -1
  164. package/lib/subcommands/index.d.ts +1 -1
  165. package/lib/subcommands/index.d.ts.map +1 -1
  166. package/lib/subcommands/index.js +3 -1
  167. package/lib/subcommands/index.js.map +1 -1
  168. package/lib/subcommands/rabbitmq-connection.d.ts +1 -1
  169. package/lib/subcommands/rabbitmq-connection.d.ts.map +1 -1
  170. package/lib/util/aai-error.d.ts +12 -0
  171. package/lib/util/aai-error.d.ts.map +1 -0
  172. package/lib/util/aai-error.js +11 -0
  173. package/lib/util/aai-error.js.map +1 -0
  174. package/lib/util/aws-regions.d.ts +2 -0
  175. package/lib/util/aws-regions.d.ts.map +1 -0
  176. package/lib/util/{cloud-mode-ready.js → aws-regions.js} +2 -20
  177. package/lib/util/aws-regions.js.map +1 -0
  178. package/lib/util/check-for-updates.d.ts.map +1 -1
  179. package/lib/util/check-for-updates.js +5 -28
  180. package/lib/util/check-for-updates.js.map +1 -1
  181. package/lib/util/clean-certs.d.ts.map +1 -1
  182. package/lib/util/clean-certs.js +5 -4
  183. package/lib/util/clean-certs.js.map +1 -1
  184. package/lib/util/directories.d.ts +4 -18
  185. package/lib/util/directories.d.ts.map +1 -1
  186. package/lib/util/directories.js +18 -32
  187. package/lib/util/directories.js.map +1 -1
  188. package/lib/util/file.d.ts +4 -0
  189. package/lib/util/file.d.ts.map +1 -1
  190. package/lib/util/file.js +65 -4
  191. package/lib/util/file.js.map +1 -1
  192. package/lib/util/get-device-id.d.ts.map +1 -1
  193. package/lib/util/get-device-id.js +7 -1
  194. package/lib/util/get-device-id.js.map +1 -1
  195. package/lib/util/http-client.js +3 -3
  196. package/lib/util/http-client.js.map +1 -1
  197. package/package.json +19 -17
  198. package/readme.md +12 -32
  199. package/src/application-control/config.ts +9 -12
  200. package/src/application-control/environment-variables.test.ts +28 -7
  201. package/src/application-control/environment-variables.ts +13 -40
  202. package/src/application-control/index.ts +3 -16
  203. package/src/application-control/install.ts +15 -10
  204. package/src/application-control/models.ts +6 -87
  205. package/src/application-control/utils.ts +0 -28
  206. package/src/cloud-connection/bootstrap-provision.ts +7 -7
  207. package/src/cloud-connection/device-agent-cloud-connection.ts +639 -525
  208. package/src/cloud-connection/device-agent.ts +16 -7
  209. package/src/cloud-connection/live-updates-handler.test.ts +121 -189
  210. package/src/cloud-connection/live-updates-handler.ts +99 -234
  211. package/src/cloud-connection/passthrough-handler.ts +55 -18
  212. package/src/cloud-connection/shadow-handler.test.ts +45 -57
  213. package/src/cloud-connection/shadow-handler.ts +103 -57
  214. package/src/cloud-connection/shadow.ts +4 -1
  215. package/src/cloud-connection/transaction-manager.test.ts +3 -3
  216. package/src/cloud-connection/transaction-manager.ts +53 -39
  217. package/src/device-control/device-control.ts +102 -70
  218. package/src/docker/docker-compose.ts +3 -2
  219. package/src/infrastructure/agent-config.test.ts +6 -2
  220. package/src/infrastructure/agent-config.ts +8 -7
  221. package/src/infrastructure/config-check-utility.test.ts +154 -0
  222. package/src/infrastructure/config-check-utility.ts +77 -0
  223. package/src/infrastructure/device-certificate.test.ts +40 -0
  224. package/src/infrastructure/device-certificate.ts +58 -0
  225. package/src/infrastructure/legacy-migration/legacy-file.test.ts +88 -0
  226. package/src/infrastructure/legacy-migration/legacy-files.ts +101 -0
  227. package/src/infrastructure/legacy-migration/legacy-migration.test.ts +396 -0
  228. package/src/infrastructure/legacy-migration/legacy-migration.ts +229 -0
  229. package/src/infrastructure/require-files-present-ready.test.ts +53 -0
  230. package/src/infrastructure/required-config-checks.ts +33 -0
  231. package/src/infrastructure/tokens-and-device-cfg.ts +12 -10
  232. package/src/local-connection/rabbitmq-connection.ts +22 -17
  233. package/src/secure-tunneling/secure-tunneling.test.ts +20 -22
  234. package/src/secure-tunneling/secure-tunneling.ts +41 -29
  235. package/src/subcommands/app/analytics.ts +2 -4
  236. package/src/subcommands/app/env-vars.ts +72 -9
  237. package/src/subcommands/app/index.ts +3 -11
  238. package/src/subcommands/app/models.ts +5 -81
  239. package/src/subcommands/app/shadow.ts +6 -5
  240. package/src/subcommands/app/version.ts +3 -4
  241. package/src/subcommands/config.ts +42 -0
  242. package/src/subcommands/device/clean.ts +31 -17
  243. package/src/subcommands/device/index.ts +3 -1
  244. package/src/subcommands/device/init.ts +11 -11
  245. package/src/subcommands/device/migrate.ts +20 -0
  246. package/src/subcommands/device/refresh.ts +1 -0
  247. package/src/subcommands/index.ts +3 -1
  248. package/src/util/aai-error.ts +20 -0
  249. package/src/util/{cloud-mode-ready.ts → aws-regions.ts} +0 -24
  250. package/src/util/check-for-updates.ts +14 -30
  251. package/src/util/clean-certs.ts +8 -4
  252. package/src/util/directories.ts +23 -67
  253. package/src/util/file.ts +83 -3
  254. package/src/util/get-device-id.ts +7 -7
  255. package/src/util/http-client.ts +2 -2
  256. package/lib/util/cloud-mode-ready.d.ts +0 -3
  257. package/lib/util/cloud-mode-ready.d.ts.map +0 -1
  258. package/lib/util/cloud-mode-ready.js.map +0 -1
  259. package/lib/util/download-file.d.ts +0 -6
  260. package/lib/util/download-file.d.ts.map +0 -1
  261. package/lib/util/download-file.js +0 -25
  262. package/lib/util/download-file.js.map +0 -1
  263. package/lib/util/fetch-with-timeout.d.ts +0 -4
  264. package/lib/util/fetch-with-timeout.d.ts.map +0 -1
  265. package/lib/util/fetch-with-timeout.js +0 -30
  266. package/lib/util/fetch-with-timeout.js.map +0 -1
  267. package/lib/util/parsing.d.ts +0 -2
  268. package/lib/util/parsing.d.ts.map +0 -1
  269. package/lib/util/parsing.js +0 -17
  270. package/lib/util/parsing.js.map +0 -1
  271. package/src/util/download-file.ts +0 -25
  272. package/src/util/fetch-with-timeout.ts +0 -35
  273. package/src/util/parsing.ts +0 -11
@@ -1,13 +1,14 @@
1
- import { logger } from '../util/logger';
2
- import { microServiceHttpClient } from '../util/http-client';
3
- import { requireLoggedInAndPaidPlan } from '../util/require-logged-in-and-paid-plan';
4
1
  import {
5
2
  DeviceTokens,
6
- writeOrValidateDeviceCfgFile,
7
- writeTokens
3
+ writeOrValidateDeviceCfgFile
8
4
  } from 'alwaysai/lib/core/device';
9
- import { JsSpawner } from 'alwaysai/lib/util';
5
+ import { getDeviceConfigPath } from 'alwaysai/lib/infrastructure';
10
6
  import { LOCAL_AAI_CFG_DIR } from 'alwaysai/lib/paths';
7
+ import { JsSpawner } from 'alwaysai/lib/util';
8
+ import { join } from 'path';
9
+ import { microServiceHttpClient } from '../util/http-client';
10
+ import { logger } from '../util/logger';
11
+ import { requireLoggedInAndPaidPlan } from '../util/require-logged-in-and-paid-plan';
11
12
 
12
13
  // NOTE: This closely follows the flow of deviceCheckAndUpdateComponent in the CLI
13
14
  export async function writeTokenAndDeviceCfg(props: { deviceUuid: string }) {
@@ -21,14 +22,15 @@ export async function writeTokenAndDeviceCfg(props: { deviceUuid: string }) {
21
22
  );
22
23
 
23
24
  const tokens: DeviceTokens = {
24
- deviceId: deviceUuid,
25
+ deviceUuid,
25
26
  accessToken,
26
27
  refreshToken,
27
28
  idToken
28
29
  };
29
- const tokenSpawner = JsSpawner({ path: LOCAL_AAI_CFG_DIR });
30
- await writeTokens({ spawner: tokenSpawner, tokens });
31
- await writeOrValidateDeviceCfgFile({ spawner: tokenSpawner, deviceUuid });
30
+ const tokenSpawner = JsSpawner({
31
+ path: join(LOCAL_AAI_CFG_DIR, getDeviceConfigPath())
32
+ });
33
+ await writeOrValidateDeviceCfgFile({ spawner: tokenSpawner, ...tokens });
32
34
 
33
35
  logger.info('Updated tokens and certificate');
34
36
  }
@@ -1,13 +1,12 @@
1
- import { logger } from '../util/logger';
2
- import sleep from '../util/sleep';
3
- import { compose } from '../docker/docker-compose';
1
+ import { JsSpawner, stringifyError } from 'alwaysai/lib/util';
4
2
  import * as YAML from 'yaml';
5
-
3
+ import { compose } from '../docker/docker-compose';
6
4
  import {
7
- DEVICE_AGENT_CFG_PATH,
8
- DEVICE_AGENT_DOCKER_COMPOSE_PATH
5
+ getDeviceAgentConfigPath,
6
+ getDeviceAgentDockerComposePath
9
7
  } from '../util/directories';
10
- import { JsSpawner } from 'alwaysai/lib/util';
8
+ import { logger } from '../util/logger';
9
+ import sleep from '../util/sleep';
11
10
  import { LOCAL_CONNECTION_PORT } from './constants';
12
11
 
13
12
  export const rabbitMQServiceName = 'alwaysAIRabbitMQ';
@@ -16,13 +15,13 @@ export const rabbitMQContainerName = 'alwaysAIRabbitMQContainer';
16
15
  export async function checkRabbitMQContainerRunning() {
17
16
  logger.debug('Checking alwaysAI Local Connection Container status');
18
17
  const spawner = JsSpawner();
19
- if (!(await spawner.exists(DEVICE_AGENT_DOCKER_COMPOSE_PATH))) {
18
+ if (!(await spawner.exists(getDeviceAgentDockerComposePath()))) {
20
19
  logger.warn(
21
20
  'alwaysAI Location Connection configuration file is not present'
22
21
  );
23
22
  return false;
24
23
  }
25
- const containerData = await compose.ps({ cwd: DEVICE_AGENT_CFG_PATH });
24
+ const containerData = await compose.ps({ cwd: getDeviceAgentConfigPath() });
26
25
  if (containerData !== undefined) {
27
26
  const rabbitmqService = containerData.data.services[0];
28
27
  if (
@@ -41,8 +40,8 @@ export async function checkRabbitMQContainerRunning() {
41
40
 
42
41
  export async function writeRabbitMQDockerComposeFile() {
43
42
  const spawner = JsSpawner();
44
- if (!(await spawner.exists(DEVICE_AGENT_CFG_PATH))) {
45
- await JsSpawner().mkdirp(DEVICE_AGENT_CFG_PATH);
43
+ if (!(await spawner.exists(getDeviceAgentConfigPath()))) {
44
+ await JsSpawner().mkdirp(getDeviceAgentConfigPath());
46
45
  }
47
46
 
48
47
  logger.debug(
@@ -68,7 +67,7 @@ export async function writeRabbitMQDockerComposeFile() {
68
67
 
69
68
  const RabbitMQDockerComposeYaml = YAML.stringify(rabbitmqDockerComposeCmd);
70
69
  await spawner.writeFile(
71
- DEVICE_AGENT_DOCKER_COMPOSE_PATH,
70
+ getDeviceAgentDockerComposePath(),
72
71
  RabbitMQDockerComposeYaml
73
72
  );
74
73
  }
@@ -79,12 +78,14 @@ export async function setupRabbitMQContainer() {
79
78
  await writeRabbitMQDockerComposeFile();
80
79
  } catch (e) {
81
80
  logger.error(
82
- `An error occurred setting up docker-compose.yaml for Device Agent pass through:\n{e.message}`
81
+ `An error occurred setting up docker-compose.yaml for Device Agent pass through!\n${stringifyError(
82
+ e
83
+ )}`
83
84
  );
84
85
  }
85
86
  try {
86
87
  const upOut = await compose.upAll({
87
- cwd: DEVICE_AGENT_CFG_PATH
88
+ cwd: getDeviceAgentConfigPath()
88
89
  });
89
90
  logger.debug(
90
91
  `Docker compose up for alwaysAI Local Connection:\n${JSON.stringify(
@@ -97,14 +98,16 @@ export async function setupRabbitMQContainer() {
97
98
  }
98
99
  } catch (e) {
99
100
  logger.error(
100
- `Unable to start alwaysAI Device Agent Local Connection Container:\n${e}`
101
+ `Unable to start alwaysAI Device Agent Local Connection Container!\n${stringifyError(
102
+ e
103
+ )}`
101
104
  );
102
105
  }
103
106
  }
104
107
 
105
108
  export async function stopRabbitMQContainer() {
106
109
  try {
107
- const downOut = await compose.down({ cwd: DEVICE_AGENT_CFG_PATH });
110
+ const downOut = await compose.down({ cwd: getDeviceAgentConfigPath() });
108
111
  logger.debug(`Stopping alwaysAI Local Connection container`);
109
112
  logger.debug(
110
113
  `Docker compose down for alwaysAI Local Connection:\n${JSON.stringify(
@@ -113,7 +116,9 @@ export async function stopRabbitMQContainer() {
113
116
  );
114
117
  } catch (e) {
115
118
  logger.error(
116
- `Unable to stop alwaysAI Device Agent Local Connection Container:\n${e.message}`
119
+ `Unable to stop alwaysAI Device Agent Local Connection Container!\n${stringifyError(
120
+ e
121
+ )}`
117
122
  );
118
123
  }
119
124
  }
@@ -1,4 +1,10 @@
1
+ import {
2
+ SecureTunnelPortInfo,
3
+ SecureTunnelShadowUpdate
4
+ } from '@alwaysai/device-agent-schemas';
1
5
  import { AAI_DIR } from 'alwaysai/lib/paths';
6
+ import { downloadToFile } from '../util/file';
7
+ import { ChildProcess } from 'child_process';
2
8
  import { join } from 'path';
3
9
  import { aaiArtifactsBucketUrl } from '../urls';
4
10
  import {
@@ -7,19 +13,12 @@ import {
7
13
  SECURE_TUNNEL_BIN_NAME,
8
14
  SECURE_TUNNEL_BIN_PATH
9
15
  } from '../util/directories';
10
- import { downloadFile } from '../util/download-file';
11
16
  import { getArch, getDistribution, getOsVersion } from '../util/system-info';
12
17
  import {
13
18
  SecureTunnelHandlerSingleton,
14
19
  SecureTunnelShadowUpdateDelta
15
20
  } from './secure-tunneling';
16
- // import { JsSpawner } from 'alwaysai/lib/util/spawner';
17
- import { ChildProcess } from 'child_process';
18
21
  import { killDetachedProcess, runDetachedProcess } from './spawner-detached';
19
- import {
20
- SecureTunnelPortInfo,
21
- SecureTunnelShadowDescriptionReported
22
- } from '@alwaysai/device-agent-schemas';
23
22
  //-----------------------------------------------------------------------------
24
23
  // mocks
25
24
  //-----------------------------------------------------------------------------
@@ -50,9 +49,8 @@ jest.mock('../util/system-info', () => ({
50
49
  getDistribution: jest.fn()
51
50
  }));
52
51
 
53
- jest.mock('../util/download-file', () => ({
54
- downloadFile: jest.fn()
55
- }));
52
+ jest.mock('../util/file');
53
+ const mockDownloadToFile = jest.mocked(downloadToFile);
56
54
 
57
55
  jest.mock('./spawner-detached', () => ({
58
56
  runDetachedProcess: jest.fn(),
@@ -174,10 +172,11 @@ describe('SecureTunnelHandlerSingleton', () => {
174
172
 
175
173
  function transformDeltaToUpdateReported(
176
174
  deltaMsg: SecureTunnelShadowUpdateDelta
177
- ): SecureTunnelShadowDescriptionReported {
175
+ ): SecureTunnelShadowUpdate {
178
176
  const { version, state } = deltaMsg;
179
- const reportedStateReported: SecureTunnelShadowDescriptionReported =
180
- JSON.parse(JSON.stringify(state));
177
+ const reportedStateReported: SecureTunnelShadowUpdate = JSON.parse(
178
+ JSON.stringify(state)
179
+ );
181
180
  return reportedStateReported;
182
181
  }
183
182
 
@@ -705,7 +704,7 @@ describe('SecureTunnelHandlerSingleton', () => {
705
704
  expect(getDistribution).not.toHaveBeenCalled();
706
705
  expect(mockJsSpawner.mkdirp).not.toHaveBeenCalled();
707
706
  expect(mockJsSpawner.run).not.toHaveBeenCalled();
708
- expect(downloadFile).not.toHaveBeenCalled();
707
+ expect(mockDownloadToFile).not.toHaveBeenCalled();
709
708
  expect(runDetachedProcess).toHaveBeenCalledTimes(1);
710
709
  expect(runDetachedProcess).toHaveBeenCalledWith(
711
710
  SECURE_TUNNEL_BIN_PATH,
@@ -782,11 +781,10 @@ describe('SecureTunnelHandlerSingleton', () => {
782
781
  exe: 'chmod',
783
782
  args: ['+x', SECURE_TUNNEL_BIN_PATH]
784
783
  });
785
- expect(downloadFile).toHaveBeenCalledTimes(1);
786
- expect(downloadFile).toHaveBeenCalledWith({
784
+ expect(mockDownloadToFile).toHaveBeenCalledTimes(1);
785
+ expect(mockDownloadToFile).toHaveBeenCalledWith({
787
786
  url: expectedUrl,
788
- path: SECURE_TUNNEL_BIN_PATH,
789
- errorMessage: `Secure Tunnel bin for ${linuxDistro} ${osVersion} ${arch} not found}`
787
+ path: SECURE_TUNNEL_BIN_PATH
790
788
  });
791
789
  expect(runDetachedProcess).toHaveBeenCalledTimes(1);
792
790
  expect(runDetachedProcess).toHaveBeenCalledWith(
@@ -916,7 +914,7 @@ describe('SecureTunnelHandlerSingleton', () => {
916
914
  expect(getOsVersion).not.toHaveBeenCalled();
917
915
  expect(getDistribution).not.toHaveBeenCalled();
918
916
  expect(mockJsSpawner.mkdirp).not.toHaveBeenCalled();
919
- expect(downloadFile).not.toHaveBeenCalled();
917
+ expect(mockDownloadToFile).not.toHaveBeenCalled();
920
918
  expect(mockJsSpawner.run).not.toHaveBeenCalled();
921
919
  expect(runDetachedProcess).not.toHaveBeenCalled();
922
920
  expect(killDetachedProcess).not.toHaveBeenCalled();
@@ -1028,7 +1026,7 @@ describe('SecureTunnelHandlerSingleton', () => {
1028
1026
  expect(getOsVersion).not.toHaveBeenCalled();
1029
1027
  expect(getDistribution).not.toHaveBeenCalled();
1030
1028
  expect(mockJsSpawner.mkdirp).not.toHaveBeenCalled();
1031
- expect(downloadFile).not.toHaveBeenCalled();
1029
+ expect(mockDownloadToFile).not.toHaveBeenCalled();
1032
1030
  expect(runDetachedProcess).not.toHaveBeenCalled();
1033
1031
  expect(killDetachedProcess).not.toHaveBeenCalled();
1034
1032
  }
@@ -1153,7 +1151,7 @@ describe('SecureTunnelHandlerSingleton', () => {
1153
1151
  expect(getOsVersion).not.toHaveBeenCalled();
1154
1152
  expect(getDistribution).not.toHaveBeenCalled();
1155
1153
  expect(mockJsSpawner.mkdirp).not.toHaveBeenCalled();
1156
- expect(downloadFile).not.toHaveBeenCalled();
1154
+ expect(mockDownloadToFile).not.toHaveBeenCalled();
1157
1155
  expect(mockJsSpawner.run).not.toHaveBeenCalled();
1158
1156
  expect(runDetachedProcess).toHaveBeenCalledTimes(1);
1159
1157
  expect(runDetachedProcess).toHaveBeenCalledWith(
@@ -1228,7 +1226,7 @@ describe('SecureTunnelHandlerSingleton', () => {
1228
1226
  expect(getOsVersion).not.toHaveBeenCalled();
1229
1227
  expect(getDistribution).not.toHaveBeenCalled();
1230
1228
  expect(mockJsSpawner.mkdirp).not.toHaveBeenCalled();
1231
- expect(downloadFile).not.toHaveBeenCalled();
1229
+ expect(mockDownloadToFile).not.toHaveBeenCalled();
1232
1230
  expect(mockJsSpawner.run).not.toHaveBeenCalled();
1233
1231
  expect(runDetachedProcess).toHaveBeenCalledTimes(0);
1234
1232
  expect(killDetachedProcess).toHaveBeenCalledTimes(2);
@@ -1,23 +1,23 @@
1
+ import {
2
+ SecureTunnelPortInfo,
3
+ SecureTunnelShadowUpdate
4
+ } from '@alwaysai/device-agent-schemas';
1
5
  import { AAI_DIR } from 'alwaysai/lib/paths';
2
- import { JsSpawner } from 'alwaysai/lib/util';
6
+ import { JsSpawner, stringifyError } from 'alwaysai/lib/util';
3
7
  import { ChildProcess } from 'child_process';
4
8
  import { join } from 'path';
5
9
  import { aaiArtifactsBucketUrl } from '../urls';
6
- import { isValidAwsRegion } from '../util/cloud-mode-ready';
10
+ import { isValidAwsRegion } from '../util/aws-regions';
7
11
  import {
8
12
  AWS_ROOT_CERTIFICATE_FILE_PATH,
9
13
  SECURE_TUNNEL_BIN_DIR,
10
14
  SECURE_TUNNEL_BIN_NAME,
11
15
  SECURE_TUNNEL_BIN_PATH
12
16
  } from '../util/directories';
13
- import { downloadFile } from '../util/download-file';
14
17
  import { logger } from '../util/logger';
15
18
  import { getArch, getDistribution, getOsVersion } from '../util/system-info';
16
19
  import { killDetachedProcess, runDetachedProcess } from './spawner-detached';
17
- import {
18
- SecureTunnelPortInfo,
19
- SecureTunnelShadowDescriptionReported
20
- } from '@alwaysai/device-agent-schemas';
20
+ import { downloadToFile } from '../util/file';
21
21
 
22
22
  enum SecureTunnelServiceType {
23
23
  SSH = 'SSH',
@@ -25,18 +25,18 @@ enum SecureTunnelServiceType {
25
25
  }
26
26
 
27
27
  export type SecureTunnelShadowState = {
28
- reported?: SecureTunnelShadowDescriptionReported;
29
- desired?: SecureTunnelShadowDescriptionReported;
28
+ reported?: SecureTunnelShadowUpdate;
29
+ desired?: SecureTunnelShadowUpdate;
30
30
  };
31
31
 
32
32
  export type SecureTunnelShadowUpdateDelta = {
33
33
  version: number;
34
34
  timestamp: number;
35
- state: SecureTunnelShadowDescriptionReported;
35
+ state: SecureTunnelShadowUpdate;
36
36
  metadata?: any;
37
37
  };
38
38
 
39
- export type SecureTunnelShadowUpdate = {
39
+ export type SecureTunnelShadow = {
40
40
  version: number;
41
41
  state: SecureTunnelShadowState;
42
42
  };
@@ -76,7 +76,7 @@ const ST_START_PORT_NUMBER = 5010;
76
76
  */
77
77
  export class SecureTunnelHandlerSingleton {
78
78
  private static instance: SecureTunnelHandlerSingleton;
79
- private reported: SecureTunnelShadowDescriptionReported;
79
+ private reported: SecureTunnelShadowUpdate;
80
80
  private httpProxyMap: SecureTunnelProxyMap[];
81
81
  private localProxyInfo: SecureTunnelLocalProxyInfo;
82
82
 
@@ -146,9 +146,9 @@ export class SecureTunnelHandlerSingleton {
146
146
 
147
147
  /**
148
148
  * Returns current state of SecureTunnel shadow
149
- * @returns {SecureTunnelShadowDescriptionReported} - reported state of the SecureTunnel shadow
149
+ * @returns {SecureTunnelShadowUpdate} - reported state of the SecureTunnel shadow
150
150
  */
151
- public getSecureTunnelShadow(): SecureTunnelShadowDescriptionReported {
151
+ public getSecureTunnelShadow(): SecureTunnelShadowUpdate {
152
152
  logger.debug('-> SecureTunnelHandlerSingleton.getSecureTunnelShadow');
153
153
  logger.debug(`reported: ${JSON.stringify(this.reported)}`);
154
154
  logger.debug('<- SecureTunnelHandlerSingleton.getSecureTunnelShadow');
@@ -158,11 +158,11 @@ export class SecureTunnelHandlerSingleton {
158
158
  /**
159
159
  * Updates current state of SecureTunnel shadow
160
160
  * @param {SecureTunnelShadowUpdateDelta} deltaMsg - delta message, which includes desired state of the SecureTunnel shadow
161
- * @return {SecureTunnelShadowDescriptionReported} update reported message to send back to AWS IoT device shadow
161
+ * @return {SecureTunnelShadowUpdate} update reported message to send back to AWS IoT device shadow
162
162
  */
163
163
  public async syncShadowToDeviceState(
164
164
  deltaMsg: SecureTunnelShadowUpdateDelta
165
- ): Promise<SecureTunnelShadowDescriptionReported> {
165
+ ): Promise<SecureTunnelShadowUpdate> {
166
166
  logger.debug('-> SecureTunnelHandlerSingleton.syncShadowToDeviceState');
167
167
  const { version, state } = deltaMsg;
168
168
  if (!state || typeof state.st_ports === 'undefined') {
@@ -234,8 +234,8 @@ export class SecureTunnelHandlerSingleton {
234
234
  this.processNotifyMessage(message);
235
235
  await this.downloadSecureTunnel();
236
236
  await this.startLocalProxy();
237
- } catch (error) {
238
- logger.error(error);
237
+ } catch (e) {
238
+ logger.error(stringifyError(e));
239
239
  }
240
240
 
241
241
  logger.info(`Local Proxy Started: ${JSON.stringify(this.localProxyInfo)}`);
@@ -324,9 +324,11 @@ export class SecureTunnelHandlerSingleton {
324
324
  this.httpProxyMap[this.httpProxyMap.length - 1]
325
325
  )}`
326
326
  );
327
- } catch (error) {
327
+ } catch (e) {
328
328
  logger.error(
329
- `ERROR: starting socat for: ${portInfo.ip}:${portInfo.port} on localhost port: ${localPort}, error: ${error}`
329
+ `ERROR: starting socat for: ${portInfo.ip}:${
330
+ portInfo.port
331
+ } on localhost port: ${localPort}\nerror:\n${stringifyError(e)}`
330
332
  );
331
333
  const lastHttpProxyMap = this.httpProxyMap.pop();
332
334
  logger.info(`removed last proxyMap: ${JSON.stringify(lastHttpProxyMap)}`);
@@ -371,7 +373,7 @@ export class SecureTunnelHandlerSingleton {
371
373
  );
372
374
  logger.debug(`Remaining map: ${JSON.stringify(this.httpProxyMap)}`);
373
375
  } catch (e) {
374
- logger.error('ERROR: killing socat process:', e);
376
+ logger.error(`ERROR: killing socat process:\n${stringifyError(e)}`);
375
377
  }
376
378
  logger.debug(
377
379
  `Removing map: ${JSON.stringify(this.httpProxyMap[itemIndex])}`
@@ -427,7 +429,7 @@ export class SecureTunnelHandlerSingleton {
427
429
  ]);
428
430
  logger.debug('SUCCESS: killing local proxy process');
429
431
  } catch (e) {
430
- logger.error('ERROR: killing local proxy process:', e);
432
+ logger.error(`ERROR: killing local proxy process:\n${stringifyError(e)}`);
431
433
  }
432
434
  this.localProxyInfo = {
433
435
  lpDstAccessKey: '',
@@ -545,11 +547,21 @@ export class SecureTunnelHandlerSingleton {
545
547
  logger.info('Downloading SecureTunnel local proxy ...');
546
548
  const url = `${aaiArtifactsBucketUrl}/securetunnel/${linuxDistro}/${osVersion}/${arch}/${SECURE_TUNNEL_BIN_NAME}`;
547
549
  await JsSpawner().mkdirp(join(AAI_DIR, SECURE_TUNNEL_BIN_DIR));
548
- await downloadFile({
549
- url,
550
- path: SECURE_TUNNEL_BIN_PATH,
551
- errorMessage: `Secure Tunnel bin for ${linuxDistro} ${osVersion} ${arch} not found}`
552
- });
550
+ try {
551
+ await downloadToFile({
552
+ url,
553
+ path: SECURE_TUNNEL_BIN_PATH
554
+ });
555
+ } catch (error) {
556
+ logger.error(
557
+ `Secure Tunnel bin for ${linuxDistro} ${osVersion} ${arch} not found}: ${stringifyError(
558
+ error
559
+ )}`
560
+ );
561
+ throw new Error(
562
+ `Secure Tunnel bin for ${linuxDistro} ${osVersion} ${arch} not found}`
563
+ );
564
+ }
553
565
 
554
566
  await JsSpawner().run({
555
567
  exe: 'chmod',
@@ -578,8 +590,8 @@ export class SecureTunnelHandlerSingleton {
578
590
  }
579
591
 
580
592
  private sortPorts(
581
- desired: SecureTunnelShadowDescriptionReported
582
- ): SecureTunnelShadowDescriptionReported {
593
+ desired: SecureTunnelShadowUpdate
594
+ ): SecureTunnelShadowUpdate {
583
595
  logger.debug('-> SecureTunnelHandlerSingleton.sortPorts');
584
596
  const sortedPorts = JSON.parse(JSON.stringify(this.reported));
585
597
  sortedPorts.st_ports.sort((a, b) => {
@@ -7,10 +7,9 @@ import {
7
7
  import { readAppCfgFile } from '../../application-control';
8
8
  import { DeviceAgentCloudConnection } from '../../cloud-connection/device-agent-cloud-connection';
9
9
  import sleep from '../../util/sleep';
10
- import { logger } from '../../util/logger';
11
10
  import { assign, merge } from 'lodash';
12
11
  import {
13
- buildUpdateProjectShadowMessage,
12
+ buildUpdateShadowMessage,
14
13
  getShadowTopic
15
14
  } from '@alwaysai/device-agent-schemas';
16
15
 
@@ -64,7 +63,6 @@ export const setAnalyticsCfgCliLeaf = CliLeaf({
64
63
  }
65
64
  ) {
66
65
  const deviceAgent = new DeviceAgentCloudConnection();
67
- await deviceAgent.setupHandlers();
68
66
 
69
67
  const newAppCfg = {
70
68
  analytics: {
@@ -85,7 +83,7 @@ export const setAnalyticsCfgCliLeaf = CliLeaf({
85
83
  deviceAgent.publisher.publish(
86
84
  getShadowTopic(deviceAgent.getClientId(), 'projects', 'update'),
87
85
  JSON.stringify(
88
- buildUpdateProjectShadowMessage({
86
+ buildUpdateShadowMessage({
89
87
  clientId: 'client',
90
88
  desired: toDesire
91
89
  })
@@ -4,13 +4,13 @@ import {
4
4
  CliStringInput,
5
5
  CliTerseError
6
6
  } from '@alwaysai/alwayscli';
7
- import { EnvVars, getAllEnvs } from '../../application-control';
7
+ import { getAllEnvs } from '../../application-control';
8
8
  import { DeviceAgentCloudConnection } from '../../cloud-connection/device-agent-cloud-connection';
9
9
  import sleep from '../../util/sleep';
10
- import { logger } from '../../util/logger';
11
10
  import {
12
- buildUpdateProjectShadowMessage,
13
- getShadowTopic
11
+ buildUpdateShadowMessage,
12
+ getShadowTopic,
13
+ EnvVars
14
14
  } from '@alwaysai/device-agent-schemas';
15
15
 
16
16
  export const getAllEnvsCliLeaf = CliLeaf({
@@ -48,27 +48,90 @@ export const setEnvCliLeaf = CliLeaf({
48
48
  },
49
49
  async action(args, opts) {
50
50
  const { project: projectId, service } = opts;
51
- const envVars: EnvVars = { [service]: {} };
51
+ const currentEnvs = await getAllEnvs({ projectId });
52
+ const envVars: EnvVars = { [service]: { ...currentEnvs[service] } };
53
+
52
54
  args.forEach((arg: string) => {
53
55
  const nameVal = arg.split('=');
54
56
  if (nameVal.length !== 2) {
55
57
  throw new CliTerseError(`Invalid argument: ${arg}`);
56
58
  }
57
- const value = nameVal[1] === '' ? null : nameVal[1];
59
+ const value = nameVal[1];
58
60
  envVars[service][nameVal[0]] = value;
59
61
  });
60
62
  const deviceAgent = new DeviceAgentCloudConnection();
61
- await deviceAgent.setupHandlers();
62
63
 
63
64
  const toDesire = {
64
65
  [projectId]: {
65
- envVars
66
+ envVars: JSON.stringify(envVars)
67
+ }
68
+ };
69
+ deviceAgent.publisher.publish(
70
+ getShadowTopic(deviceAgent.getClientId(), 'projects', 'update'),
71
+ JSON.stringify(
72
+ buildUpdateShadowMessage({
73
+ clientId: 'client',
74
+ desired: toDesire
75
+ })
76
+ )
77
+ );
78
+ // Sleep for extra time to ensure time for shadow response
79
+ await sleep(10000);
80
+
81
+ while (deviceAgent.isCmdInProgress(projectId)) {
82
+ await sleep(1000);
83
+ }
84
+ await deviceAgent.stop();
85
+ }
86
+ });
87
+
88
+ export const rmEnvCliLeaf = CliLeaf({
89
+ name: 'rm-env',
90
+ description: 'Remove an environment variable from an application',
91
+ positionalInput: CliStringInput({
92
+ description: 'The key of the environment variable to be removed',
93
+ required: true
94
+ }),
95
+ namedInputs: {
96
+ project: CliStringInput({
97
+ description: 'Project Id',
98
+ required: true
99
+ }),
100
+ service: CliStringInput({
101
+ description:
102
+ 'Docker compose service to remove an environment variable from',
103
+ required: true
104
+ })
105
+ },
106
+ async action(arg, opts) {
107
+ const { project: projectId, service } = opts;
108
+ const envVar = arg;
109
+ const currentEnvs = await getAllEnvs({ projectId: projectId });
110
+
111
+ const newEnvs = { ...currentEnvs };
112
+ if (Object.keys(newEnvs[service]).includes(envVar)) {
113
+ delete newEnvs[service][envVar];
114
+ } else {
115
+ throw new CliTerseError(
116
+ `Could not find key "${envVar}" in service ${service}. Current keys are:\n ${JSON.stringify(
117
+ Object.keys(currentEnvs[service]),
118
+ null,
119
+ 2
120
+ )}.\nPlease check the key and try again.`
121
+ );
122
+ }
123
+
124
+ const deviceAgent = new DeviceAgentCloudConnection();
125
+
126
+ const toDesire = {
127
+ [projectId]: {
128
+ envVars: JSON.stringify(newEnvs)
66
129
  }
67
130
  };
68
131
  deviceAgent.publisher.publish(
69
132
  getShadowTopic(deviceAgent.getClientId(), 'projects', 'update'),
70
133
  JSON.stringify(
71
- buildUpdateProjectShadowMessage({
134
+ buildUpdateShadowMessage({
72
135
  clientId: 'client',
73
136
  desired: toDesire
74
137
  })
@@ -1,12 +1,6 @@
1
1
  import { CliBranch } from '@alwaysai/alwayscli';
2
- import { getAllEnvsCliLeaf, setEnvCliLeaf } from './env-vars';
3
- import {
4
- showAppModelsCliLeaf,
5
- addModelCliLeaf,
6
- removeModelCliLeaf,
7
- replaceModelsCliLeaf,
8
- updateModelsCliLeaf
9
- } from './models';
2
+ import { getAllEnvsCliLeaf, setEnvCliLeaf, rmEnvCliLeaf } from './env-vars';
3
+ import { showAppModelsCliLeaf, addModelCliLeaf } from './models';
10
4
  import {
11
5
  getAppStatusCliLeaf,
12
6
  startAppCliLeaf,
@@ -38,11 +32,9 @@ export const appCliBranch = CliBranch({
38
32
  rollbackAppCliLeaf,
39
33
  showAppModelsCliLeaf,
40
34
  addModelCliLeaf,
41
- removeModelCliLeaf,
42
- replaceModelsCliLeaf,
43
- updateModelsCliLeaf,
44
35
  getAllEnvsCliLeaf,
45
36
  setEnvCliLeaf,
37
+ rmEnvCliLeaf,
46
38
  getAnalyticsCfgCliLeaf,
47
39
  setAnalyticsCfgCliLeaf,
48
40
  getShadowCliLeaf,