@alwaysai/device-agent 1.4.0 → 1.5.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 (139) hide show
  1. package/lib/application-control/config.js +2 -2
  2. package/lib/application-control/config.js.map +1 -1
  3. package/lib/application-control/install.d.ts.map +1 -1
  4. package/lib/application-control/install.js +1 -0
  5. package/lib/application-control/install.js.map +1 -1
  6. package/lib/application-control/models.d.ts +5 -0
  7. package/lib/application-control/models.d.ts.map +1 -1
  8. package/lib/application-control/models.js +24 -12
  9. package/lib/application-control/models.js.map +1 -1
  10. package/lib/application-control/status.d.ts.map +1 -1
  11. package/lib/application-control/status.js +10 -12
  12. package/lib/application-control/status.js.map +1 -1
  13. package/lib/application-control/utils.js +2 -2
  14. package/lib/application-control/utils.js.map +1 -1
  15. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +2 -2
  16. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  17. package/lib/cloud-connection/device-agent-cloud-connection.js +35 -15
  18. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  19. package/lib/cloud-connection/live-updates-handler.d.ts +3 -2
  20. package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
  21. package/lib/cloud-connection/live-updates-handler.js +24 -21
  22. package/lib/cloud-connection/live-updates-handler.js.map +1 -1
  23. package/lib/cloud-connection/live-updates-handler.test.js +132 -16
  24. package/lib/cloud-connection/live-updates-handler.test.js.map +1 -1
  25. package/lib/cloud-connection/passthrough-handler.d.ts +5 -3
  26. package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -1
  27. package/lib/cloud-connection/passthrough-handler.js +76 -62
  28. package/lib/cloud-connection/passthrough-handler.js.map +1 -1
  29. package/lib/cloud-connection/shadow-handler.d.ts +2 -0
  30. package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
  31. package/lib/cloud-connection/shadow-handler.js +5 -5
  32. package/lib/cloud-connection/shadow-handler.js.map +1 -1
  33. package/lib/cloud-connection/transaction-manager.d.ts +3 -0
  34. package/lib/cloud-connection/transaction-manager.d.ts.map +1 -1
  35. package/lib/cloud-connection/transaction-manager.js +11 -0
  36. package/lib/cloud-connection/transaction-manager.js.map +1 -1
  37. package/lib/cloud-connection/transaction-manager.test.js +102 -0
  38. package/lib/cloud-connection/transaction-manager.test.js.map +1 -1
  39. package/lib/device-control/device-control.d.ts +10 -2
  40. package/lib/device-control/device-control.d.ts.map +1 -1
  41. package/lib/device-control/device-control.js +86 -10
  42. package/lib/device-control/device-control.js.map +1 -1
  43. package/lib/docker/docker-compose.d.ts +14 -0
  44. package/lib/docker/docker-compose.d.ts.map +1 -0
  45. package/lib/docker/docker-compose.js +56 -0
  46. package/lib/docker/docker-compose.js.map +1 -0
  47. package/lib/index.js +2 -5
  48. package/lib/index.js.map +1 -1
  49. package/lib/infrastructure/agent-config.d.ts +45 -14
  50. package/lib/infrastructure/agent-config.d.ts.map +1 -1
  51. package/lib/infrastructure/agent-config.js +30 -15
  52. package/lib/infrastructure/agent-config.js.map +1 -1
  53. package/lib/infrastructure/agent-config.test.js +3 -0
  54. package/lib/infrastructure/agent-config.test.js.map +1 -1
  55. package/lib/local-connection/rabbitmq-connection.js +11 -11
  56. package/lib/local-connection/rabbitmq-connection.js.map +1 -1
  57. package/lib/secure-tunneling/secure-tunneling.d.ts +14 -22
  58. package/lib/secure-tunneling/secure-tunneling.d.ts.map +1 -1
  59. package/lib/secure-tunneling/secure-tunneling.js +34 -34
  60. package/lib/secure-tunneling/secure-tunneling.js.map +1 -1
  61. package/lib/secure-tunneling/secure-tunneling.test.js +18 -18
  62. package/lib/secure-tunneling/secure-tunneling.test.js.map +1 -1
  63. package/lib/subcommands/device/clean.js +5 -5
  64. package/lib/subcommands/device/clean.js.map +1 -1
  65. package/lib/subcommands/device/get-info.d.ts +2 -0
  66. package/lib/subcommands/device/get-info.d.ts.map +1 -0
  67. package/lib/subcommands/device/get-info.js +36 -0
  68. package/lib/subcommands/device/get-info.js.map +1 -0
  69. package/lib/subcommands/device/index.d.ts.map +1 -1
  70. package/lib/subcommands/device/index.js +11 -2
  71. package/lib/subcommands/device/index.js.map +1 -1
  72. package/lib/subcommands/device/init.d.ts +5 -0
  73. package/lib/subcommands/device/init.d.ts.map +1 -0
  74. package/lib/subcommands/device/{device.js → init.js} +2 -41
  75. package/lib/subcommands/device/init.js.map +1 -0
  76. package/lib/subcommands/device/refresh.d.ts +2 -0
  77. package/lib/subcommands/device/refresh.d.ts.map +1 -0
  78. package/lib/subcommands/device/refresh.js +24 -0
  79. package/lib/subcommands/device/refresh.js.map +1 -0
  80. package/lib/subcommands/device/restart.d.ts +2 -0
  81. package/lib/subcommands/device/restart.d.ts.map +1 -0
  82. package/lib/subcommands/device/restart.js +14 -0
  83. package/lib/subcommands/device/restart.js.map +1 -0
  84. package/lib/util/check-for-updates.d.ts +3 -0
  85. package/lib/util/check-for-updates.d.ts.map +1 -0
  86. package/lib/util/check-for-updates.js +69 -0
  87. package/lib/util/check-for-updates.js.map +1 -0
  88. package/lib/util/file.d.ts +7 -0
  89. package/lib/util/file.d.ts.map +1 -0
  90. package/lib/util/file.js +66 -0
  91. package/lib/util/file.js.map +1 -0
  92. package/lib/util/file.test.d.ts +2 -0
  93. package/lib/util/file.test.d.ts.map +1 -0
  94. package/lib/util/file.test.js +87 -0
  95. package/lib/util/file.test.js.map +1 -0
  96. package/package.json +8 -7
  97. package/readme.md +3 -3
  98. package/src/application-control/config.ts +1 -1
  99. package/src/application-control/install.ts +1 -0
  100. package/src/application-control/models.ts +36 -13
  101. package/src/application-control/status.ts +9 -7
  102. package/src/application-control/utils.ts +1 -1
  103. package/src/cloud-connection/device-agent-cloud-connection.ts +54 -30
  104. package/src/cloud-connection/live-updates-handler.test.ts +161 -20
  105. package/src/cloud-connection/live-updates-handler.ts +30 -26
  106. package/src/cloud-connection/passthrough-handler.ts +98 -76
  107. package/src/cloud-connection/shadow-handler.ts +19 -7
  108. package/src/cloud-connection/transaction-manager.test.ts +124 -0
  109. package/src/cloud-connection/transaction-manager.ts +15 -0
  110. package/src/device-control/device-control.ts +86 -11
  111. package/src/docker/docker-compose.ts +60 -0
  112. package/src/index.ts +2 -6
  113. package/src/infrastructure/agent-config.test.ts +3 -0
  114. package/src/infrastructure/agent-config.ts +38 -40
  115. package/src/local-connection/rabbitmq-connection.ts +8 -8
  116. package/src/secure-tunneling/secure-tunneling.test.ts +26 -26
  117. package/src/secure-tunneling/secure-tunneling.ts +48 -55
  118. package/src/subcommands/device/clean.ts +1 -1
  119. package/src/subcommands/device/get-info.ts +49 -0
  120. package/src/subcommands/device/index.ts +11 -2
  121. package/src/subcommands/device/{device.ts → init.ts} +0 -58
  122. package/src/subcommands/device/refresh.ts +22 -0
  123. package/src/subcommands/device/restart.ts +11 -0
  124. package/src/util/check-for-updates.ts +69 -0
  125. package/src/util/file.test.ts +90 -0
  126. package/src/util/file.ts +76 -0
  127. package/lib/docker/docker-compose-cmd.d.ts +0 -5
  128. package/lib/docker/docker-compose-cmd.d.ts.map +0 -1
  129. package/lib/docker/docker-compose-cmd.js +0 -16
  130. package/lib/docker/docker-compose-cmd.js.map +0 -1
  131. package/lib/subcommands/device/device.d.ts +0 -7
  132. package/lib/subcommands/device/device.d.ts.map +0 -1
  133. package/lib/subcommands/device/device.js.map +0 -1
  134. package/lib/util/safe-rimraf.d.ts +0 -2
  135. package/lib/util/safe-rimraf.d.ts.map +0 -1
  136. package/lib/util/safe-rimraf.js +0 -16
  137. package/lib/util/safe-rimraf.js.map +0 -1
  138. package/src/docker/docker-compose-cmd.ts +0 -15
  139. package/src/util/safe-rimraf.ts +0 -14
@@ -58,26 +58,7 @@ const ALWAYSAI_CONFIG_DIR = join(homedir(), '.config', 'alwaysai');
58
58
 
59
59
  const AGENT_CONFIG_FILE_NAME = 'alwaysai.agent.json';
60
60
 
61
- export interface AgentJsonFileReturnType
62
- extends ConfigFileSchemaReturnType<AgentConfig> {
63
- name: string;
64
- getApps: () => Promise<InstalledAppConfig[]>;
65
- getReadyApps;
66
- getApp;
67
- isAppPresent;
68
- isAppReady;
69
- removeApp;
70
- setAppInstalling;
71
- setAppInstalled;
72
- setAppUninstalled;
73
- getAppVersion: (props: { projectId: string }) => Promise<string>;
74
- setAppBackup;
75
- getAppBackup;
76
- }
77
-
78
- export function AgentConfigFile(
79
- dir = ALWAYSAI_CONFIG_DIR
80
- ): AgentJsonFileReturnType {
61
+ export function AgentConfigFile(dir = ALWAYSAI_CONFIG_DIR) {
81
62
  const path = join(dir, AGENT_CONFIG_FILE_NAME);
82
63
  const initialValue: AgentConfig = {
83
64
  applications: []
@@ -88,31 +69,14 @@ export function AgentConfigFile(
88
69
  initialValue
89
70
  });
90
71
 
91
- return {
92
- ...configFile,
93
- name: AGENT_CONFIG_FILE_NAME,
94
- getApps,
95
- getReadyApps,
96
- getApp,
97
- isAppPresent,
98
- isAppReady,
99
- removeApp,
100
- setAppInstalling,
101
- setAppInstalled,
102
- setAppUninstalled,
103
- getAppVersion,
104
- setAppBackup,
105
- getAppBackup
106
- };
107
-
108
72
  async function getApps() {
109
73
  const config = configFile.read();
110
- return config && config.applications ? config.applications : [];
74
+ return config?.applications ? config.applications : [];
111
75
  }
112
76
 
113
77
  async function getReadyApps() {
114
78
  const config = configFile.read();
115
- return config && config.applications
79
+ return config?.applications
116
80
  ? config.applications.filter((app) => {
117
81
  return app.ready;
118
82
  })
@@ -205,6 +169,23 @@ export function AgentConfigFile(
205
169
  }
206
170
  }
207
171
 
172
+ async function setAppUninstalling(props: { projectId: string }) {
173
+ const { projectId } = props;
174
+ const app = await getApp({ projectId });
175
+ if (app) {
176
+ await removeApp({ projectId });
177
+ const config = configFile.read();
178
+ config.applications.push({ ...app, ...{ ready: false } });
179
+ configFile.write(config);
180
+ } else {
181
+ // NOTE: we should never be setting an app as installed
182
+ // if it doesn't exist (setAppInstalling was never called)
183
+ throw new Error(
184
+ `App ${projectId} was not previously configured and could not be set to installed!`
185
+ );
186
+ }
187
+ }
188
+
208
189
  async function setAppUninstalled(props: { projectId: string }) {
209
190
  const { projectId } = props;
210
191
  await removeApp({ projectId });
@@ -235,9 +216,26 @@ export function AgentConfigFile(
235
216
  async function getAppBackup(props: { projectId: string }) {
236
217
  const { projectId } = props;
237
218
  const app = await getApp({ projectId });
238
- if (app && app.backup) {
219
+ if (app?.backup) {
239
220
  return app.backup;
240
221
  }
241
222
  return null;
242
223
  }
224
+
225
+ return {
226
+ ...configFile,
227
+ name: AGENT_CONFIG_FILE_NAME,
228
+ getApps,
229
+ getReadyApps,
230
+ getApp,
231
+ isAppPresent,
232
+ isAppReady,
233
+ setAppInstalling,
234
+ setAppInstalled,
235
+ setAppUninstalling,
236
+ setAppUninstalled,
237
+ getAppVersion,
238
+ setAppBackup,
239
+ getAppBackup
240
+ };
243
241
  }
@@ -1,6 +1,6 @@
1
1
  import { logger } from '../util/logger';
2
2
  import sleep from '../util/sleep';
3
- import compose from 'docker-compose';
3
+ import { compose } from '../docker/docker-compose';
4
4
  import * as YAML from 'yaml';
5
5
 
6
6
  import {
@@ -23,19 +23,19 @@ export async function checkRabbitMQContainerRunning() {
23
23
  return false;
24
24
  }
25
25
  const containerData = await compose.ps({ cwd: DEVICE_AGENT_CFG_PATH });
26
- if (!(containerData === undefined)) {
26
+ if (containerData !== undefined) {
27
27
  const rabbitmqService = containerData.data.services[0];
28
28
  if (
29
- rabbitmqService.name === rabbitMQContainerName &&
30
- rabbitmqService.state === 'Up'
29
+ rabbitmqService?.name === rabbitMQContainerName &&
30
+ rabbitmqService.state.includes('Up')
31
31
  ) {
32
- logger.debug('alwaysAI Local Connection is running');
32
+ logger.debug('alwaysAI Local Connection Container is up');
33
33
  return true;
34
34
  }
35
- logger.debug('alwaysAI Local Connection is not running');
35
+ logger.debug('alwaysAI Local Connection Container is not up');
36
36
  return false;
37
37
  }
38
- logger.warn('alwaysAI Local Connection container was undefined');
38
+ logger.warn('alwaysAI Local Connection Container is undefined');
39
39
  return false;
40
40
  }
41
41
 
@@ -97,7 +97,7 @@ export async function setupRabbitMQContainer() {
97
97
  }
98
98
  } catch (e) {
99
99
  logger.error(
100
- `Unable to start alwaysAI Device Agent Local Connection Container:\n${e.messaage}`
100
+ `Unable to start alwaysAI Device Agent Local Connection Container:\n${e}`
101
101
  );
102
102
  }
103
103
  }
@@ -11,14 +11,15 @@ import { downloadFile } from '../util/download-file';
11
11
  import { getArch, getDistribution, getOsVersion } from '../util/system-info';
12
12
  import {
13
13
  SecureTunnelHandlerSingleton,
14
- SecureTunnelPortInfo,
15
- SecureTunnelShadowDesRep,
16
14
  SecureTunnelShadowUpdateDelta
17
15
  } from './secure-tunneling';
18
16
  // import { JsSpawner } from 'alwaysai/lib/util/spawner';
19
17
  import { ChildProcess } from 'child_process';
20
18
  import { killDetachedProcess, runDetachedProcess } from './spawner-detached';
21
-
19
+ import {
20
+ SecureTunnelPortInfo,
21
+ SecureTunnelShadowDescriptionReported
22
+ } from '@alwaysai/device-agent-schemas';
22
23
  //-----------------------------------------------------------------------------
23
24
  // mocks
24
25
  //-----------------------------------------------------------------------------
@@ -173,11 +174,10 @@ describe('SecureTunnelHandlerSingleton', () => {
173
174
 
174
175
  function transformDeltaToUpdateReported(
175
176
  deltaMsg: SecureTunnelShadowUpdateDelta
176
- ): SecureTunnelShadowDesRep {
177
+ ): SecureTunnelShadowDescriptionReported {
177
178
  const { version, state } = deltaMsg;
178
- const reportedStateReported: SecureTunnelShadowDesRep = JSON.parse(
179
- JSON.stringify(state)
180
- );
179
+ const reportedStateReported: SecureTunnelShadowDescriptionReported =
180
+ JSON.parse(JSON.stringify(state));
181
181
  return reportedStateReported;
182
182
  }
183
183
 
@@ -671,16 +671,16 @@ describe('SecureTunnelHandlerSingleton', () => {
671
671
  //---------------------------------------------------------------------------
672
672
  // test secureTunnelNotifyHandler function
673
673
  //---------------------------------------------------------------------------
674
- it('should start Secure Tunnel, given localproxy already downloaded and default shadow is not enabled, that is default SSH connection', async () => {
674
+ it('should start Secure Tunnel, given local proxy already downloaded and default shadow is not enabled, that is default SSH connection', async () => {
675
675
  // Arrange
676
676
  // --------------------------------------------------------------------
677
- mockJsSpawner.exists.mockResolvedValueOnce(true); // mock that localproxy already exists on file system
677
+ mockJsSpawner.exists.mockResolvedValueOnce(true); // mock that local proxy already exists on file system
678
678
  const message: SecureTunnelNotifyMsg = {
679
679
  clientAccessToken: 'DefaultSSHConnection_001',
680
680
  region: 'us-west-2',
681
681
  services: ['SSH']
682
682
  };
683
- const expectedLocalproxyArgs = [
683
+ const expectedLocalProxyArgs = [
684
684
  '--destination-app',
685
685
  '22',
686
686
  '--region',
@@ -709,12 +709,12 @@ describe('SecureTunnelHandlerSingleton', () => {
709
709
  expect(runDetachedProcess).toHaveBeenCalledTimes(1);
710
710
  expect(runDetachedProcess).toHaveBeenCalledWith(
711
711
  SECURE_TUNNEL_BIN_PATH,
712
- expectedLocalproxyArgs
712
+ expectedLocalProxyArgs
713
713
  );
714
714
  expect(killDetachedProcess).not.toHaveBeenCalled();
715
715
  });
716
716
 
717
- const testCasesForDIfferentLocalproxyEnv: [string, string, string][] = [
717
+ const testCasesForDIfferentLocalProxyEnv: [string, string, string][] = [
718
718
  // linuxDistro, osVersion, arch
719
719
  ['debian', '12', 'aarch64'],
720
720
  ['debian', '12', 'arm64'],
@@ -734,12 +734,12 @@ describe('SecureTunnelHandlerSingleton', () => {
734
734
  ['ubuntu', '23.10', 'amd64'],
735
735
  ['ubuntu', '23.10', 'arm64']
736
736
  ];
737
- test.each(testCasesForDIfferentLocalproxyEnv)(
738
- 'should start Secure Tunnel, given localproxy downloaded needed and default shadow is not enabled, that is default SSH connection',
737
+ test.each(testCasesForDIfferentLocalProxyEnv)(
738
+ 'should start Secure Tunnel, given local proxy downloaded needed and default shadow is not enabled, that is default SSH connection',
739
739
  async (linuxDistro: string, osVersion: string, arch: string) => {
740
740
  // Arrange
741
741
  // --------------------------------------------------------------------
742
- mockJsSpawner.exists.mockResolvedValueOnce(false); // mock that localproxy does not exist on file system
742
+ mockJsSpawner.exists.mockResolvedValueOnce(false); // mock that local proxy does not exist on file system
743
743
  jest.mocked(getArch).mockResolvedValueOnce(arch);
744
744
  jest.mocked(getOsVersion).mockResolvedValueOnce(osVersion);
745
745
  jest.mocked(getDistribution).mockResolvedValueOnce(linuxDistro);
@@ -749,7 +749,7 @@ describe('SecureTunnelHandlerSingleton', () => {
749
749
  region: 'us-west-2',
750
750
  services: ['SSH']
751
751
  };
752
- const expectedLocalproxyArgs = [
752
+ const expectedLocalProxyArgs = [
753
753
  '--destination-app',
754
754
  '22',
755
755
  '--region',
@@ -791,7 +791,7 @@ describe('SecureTunnelHandlerSingleton', () => {
791
791
  expect(runDetachedProcess).toHaveBeenCalledTimes(1);
792
792
  expect(runDetachedProcess).toHaveBeenCalledWith(
793
793
  SECURE_TUNNEL_BIN_PATH,
794
- expectedLocalproxyArgs
794
+ expectedLocalProxyArgs
795
795
  );
796
796
  expect(killDetachedProcess).not.toHaveBeenCalled();
797
797
  }
@@ -891,8 +891,8 @@ describe('SecureTunnelHandlerSingleton', () => {
891
891
  async (message) => {
892
892
  // Arrange
893
893
  // --------------------------------------------------------------------
894
- mockJsSpawner.exists.mockResolvedValueOnce(true); // mock that localproxy already exists on file system
895
- const expectedLocalproxyArgs = [
894
+ mockJsSpawner.exists.mockResolvedValueOnce(true); // mock that local proxy already exists on file system
895
+ const expectedLocalProxyArgs = [
896
896
  '--destination-app',
897
897
  '22',
898
898
  '--region',
@@ -1003,8 +1003,8 @@ describe('SecureTunnelHandlerSingleton', () => {
1003
1003
  expect(actualReportedShadow).toEqual(updateReported);
1004
1004
  jest.clearAllMocks(); // after setting up the shadow, we need to reset mocks again
1005
1005
  jest.resetModules();
1006
- mockJsSpawner.exists.mockResolvedValueOnce(true); // mock that localproxy already exists on file system
1007
- const expectedLocalproxyArgs = [
1006
+ mockJsSpawner.exists.mockResolvedValueOnce(true); // mock that local proxy already exists on file system
1007
+ const expectedLocalProxyArgs = [
1008
1008
  '--destination-app',
1009
1009
  '22',
1010
1010
  '--region',
@@ -1128,8 +1128,8 @@ describe('SecureTunnelHandlerSingleton', () => {
1128
1128
  expect(actualReportedShadow).toEqual(updateReported);
1129
1129
  jest.clearAllMocks(); // after setting up the shadow, we need to reset mocks again
1130
1130
  jest.resetModules();
1131
- mockJsSpawner.exists.mockResolvedValueOnce(true); // mock that localproxy already exists on file system
1132
- const expectedLocalproxyArgs = [
1131
+ mockJsSpawner.exists.mockResolvedValueOnce(true); // mock that local proxy already exists on file system
1132
+ const expectedLocalProxyArgs = [
1133
1133
  '--destination-app',
1134
1134
  expectedPortMapping,
1135
1135
  '--region',
@@ -1158,7 +1158,7 @@ describe('SecureTunnelHandlerSingleton', () => {
1158
1158
  expect(runDetachedProcess).toHaveBeenCalledTimes(1);
1159
1159
  expect(runDetachedProcess).toHaveBeenCalledWith(
1160
1160
  SECURE_TUNNEL_BIN_PATH,
1161
- expectedLocalproxyArgs
1161
+ expectedLocalProxyArgs
1162
1162
  );
1163
1163
  expect(killDetachedProcess).toHaveBeenCalledTimes(0);
1164
1164
  }
@@ -1192,8 +1192,8 @@ describe('SecureTunnelHandlerSingleton', () => {
1192
1192
  expect(beforeReportedShadow).toEqual(updateReported);
1193
1193
  jest.clearAllMocks(); // after setting up the shadow, we need to reset mocks again
1194
1194
  jest.resetModules();
1195
- mockJsSpawner.exists.mockResolvedValueOnce(true); // mock that localproxy already exists on file system
1196
- const expectedLocalproxyArgs = [
1195
+ mockJsSpawner.exists.mockResolvedValueOnce(true); // mock that local proxy already exists on file system
1196
+ const expectedLocalProxyArgs = [
1197
1197
  '--destination-app',
1198
1198
  expectedPortMapping,
1199
1199
  '--region',
@@ -14,32 +14,25 @@ import { downloadFile } from '../util/download-file';
14
14
  import { logger } from '../util/logger';
15
15
  import { getArch, getDistribution, getOsVersion } from '../util/system-info';
16
16
  import { killDetachedProcess, runDetachedProcess } from './spawner-detached';
17
+ import {
18
+ SecureTunnelPortInfo,
19
+ SecureTunnelShadowDescriptionReported
20
+ } from '@alwaysai/device-agent-schemas';
17
21
 
18
22
  enum SecureTunnelServiceType {
19
23
  SSH = 'SSH',
20
24
  HTTP = 'HTTP'
21
25
  }
22
26
 
23
- export type SecureTunnelPortInfo = {
24
- enabled: boolean;
25
- type: string;
26
- ip: string;
27
- port: number;
28
- };
29
-
30
- export type SecureTunnelShadowDesRep = {
31
- st_ports: SecureTunnelPortInfo[];
32
- };
33
-
34
27
  export type SecureTunnelShadowState = {
35
- reported?: SecureTunnelShadowDesRep;
36
- desired?: SecureTunnelShadowDesRep;
28
+ reported?: SecureTunnelShadowDescriptionReported;
29
+ desired?: SecureTunnelShadowDescriptionReported;
37
30
  };
38
31
 
39
32
  export type SecureTunnelShadowUpdateDelta = {
40
33
  version: number;
41
34
  timestamp: number;
42
- state: SecureTunnelShadowDesRep;
35
+ state: SecureTunnelShadowDescriptionReported;
43
36
  metadata?: any;
44
37
  };
45
38
 
@@ -54,7 +47,7 @@ type SecureTunnelProxyMap = {
54
47
  mapProcess: ChildProcess;
55
48
  };
56
49
 
57
- type SecureTunnelLocalproxyInfo = {
50
+ type SecureTunnelLocalProxyInfo = {
58
51
  lpDstAccessKey: string;
59
52
  lpRegion: string;
60
53
  lpServices: string;
@@ -83,9 +76,9 @@ const ST_START_PORT_NUMBER = 5010;
83
76
  */
84
77
  export class SecureTunnelHandlerSingleton {
85
78
  private static instance: SecureTunnelHandlerSingleton;
86
- private reported: SecureTunnelShadowDesRep;
79
+ private reported: SecureTunnelShadowDescriptionReported;
87
80
  private httpProxyMap: SecureTunnelProxyMap[];
88
- private localproxyInfo: SecureTunnelLocalproxyInfo;
81
+ private localProxyInfo: SecureTunnelLocalProxyInfo;
89
82
 
90
83
  /**
91
84
  * Initializes private variables of SecureTunnel handler.
@@ -97,7 +90,7 @@ export class SecureTunnelHandlerSingleton {
97
90
  st_ports: [JSON.parse(JSON.stringify(defaultSecureTunnelPortInfo))]
98
91
  };
99
92
  this.httpProxyMap = [];
100
- this.localproxyInfo = {
93
+ this.localProxyInfo = {
101
94
  lpDstAccessKey: '',
102
95
  lpRegion: '',
103
96
  lpServices: '',
@@ -147,15 +140,15 @@ export class SecureTunnelHandlerSingleton {
147
140
  };
148
141
  logger.debug(`httpProxyMap after : ${JSON.stringify(this.httpProxyMap)}`);
149
142
  logger.debug(`reported after : ${JSON.stringify(this.reported)}`);
150
- await this.stopLocalproxy();
143
+ await this.stopLocalProxy();
151
144
  logger.debug('<- SecureTunnelHandlerSingleton.destroy');
152
145
  }
153
146
 
154
147
  /**
155
148
  * Returns current state of SecureTunnel shadow
156
- * @returns {SecureTunnelShadowDesRep} - reported state of the SecureTunnel shadow
149
+ * @returns {SecureTunnelShadowDescriptionReported} - reported state of the SecureTunnel shadow
157
150
  */
158
- public getSecureTunnelShadow(): SecureTunnelShadowDesRep {
151
+ public getSecureTunnelShadow(): SecureTunnelShadowDescriptionReported {
159
152
  logger.debug('-> SecureTunnelHandlerSingleton.getSecureTunnelShadow');
160
153
  logger.debug(`reported: ${JSON.stringify(this.reported)}`);
161
154
  logger.debug('<- SecureTunnelHandlerSingleton.getSecureTunnelShadow');
@@ -165,11 +158,11 @@ export class SecureTunnelHandlerSingleton {
165
158
  /**
166
159
  * Updates current state of SecureTunnel shadow
167
160
  * @param {SecureTunnelShadowUpdateDelta} deltaMsg - delta message, which includes desired state of the SecureTunnel shadow
168
- * @return {SecureTunnelShadowDesRep} update reported message to send back to AWS IoT device shadow
161
+ * @return {SecureTunnelShadowDescriptionReported} update reported message to send back to AWS IoT device shadow
169
162
  */
170
163
  public async syncShadowToDeviceState(
171
164
  deltaMsg: SecureTunnelShadowUpdateDelta
172
- ): Promise<SecureTunnelShadowDesRep> {
165
+ ): Promise<SecureTunnelShadowDescriptionReported> {
173
166
  logger.debug('-> SecureTunnelHandlerSingleton.syncShadowToDeviceState');
174
167
  const { version, state } = deltaMsg;
175
168
  if (!state || typeof state.st_ports === 'undefined') {
@@ -216,7 +209,7 @@ export class SecureTunnelHandlerSingleton {
216
209
 
217
210
  // if all entries are disabled, we need also to kill local proxy
218
211
  if (this.reported.st_ports.every((portInfo) => !portInfo.enabled)) {
219
- await this.stopLocalproxy();
212
+ await this.stopLocalProxy();
220
213
  }
221
214
 
222
215
  // need to order list in the same order as desired before sending back
@@ -237,15 +230,15 @@ export class SecureTunnelHandlerSingleton {
237
230
  logger.debug('-> SecureTunnelHandlerSingleton.secureTunnelNotifyHandler');
238
231
 
239
232
  try {
240
- await this.stopLocalproxy();
233
+ await this.stopLocalProxy();
241
234
  this.processNotifyMessage(message);
242
235
  await this.downloadSecureTunnel();
243
- await this.startLocalproxy();
236
+ await this.startLocalProxy();
244
237
  } catch (error) {
245
238
  logger.error(error);
246
239
  }
247
240
 
248
- logger.info(`Local Proxy Started: ${JSON.stringify(this.localproxyInfo)}`);
241
+ logger.info(`Local Proxy Started: ${JSON.stringify(this.localProxyInfo)}`);
249
242
  logger.debug('<- SecureTunnelHandlerSingleton.secureTunnelNotifyHandler');
250
243
  }
251
244
 
@@ -389,60 +382,60 @@ export class SecureTunnelHandlerSingleton {
389
382
  }
390
383
 
391
384
  /**
392
- * Starts SecureTunnel localproxy process
385
+ * Starts SecureTunnel localProxy process
393
386
  */
394
- private async startLocalproxy(): Promise<void> {
395
- logger.debug('-> SecureTunnelHandlerSingleton.startLocalproxy');
387
+ private async startLocalProxy(): Promise<void> {
388
+ logger.debug('-> SecureTunnelHandlerSingleton.startLocalProxy');
396
389
 
397
390
  const args = [
398
391
  '--destination-app',
399
- this.localproxyInfo.lpServices,
392
+ this.localProxyInfo.lpServices,
400
393
  '--region',
401
- this.localproxyInfo.lpRegion,
394
+ this.localProxyInfo.lpRegion,
402
395
  '--capath',
403
396
  AWS_ROOT_CERTIFICATE_FILE_PATH,
404
397
  '--local-bind-address',
405
398
  '0.0.0.0',
406
399
  '-t',
407
- this.localproxyInfo.lpDstAccessKey
400
+ this.localProxyInfo.lpDstAccessKey
408
401
  ];
409
402
 
410
- this.localproxyInfo.lpProcess = await runDetachedProcess(
403
+ this.localProxyInfo.lpProcess = await runDetachedProcess(
411
404
  SECURE_TUNNEL_BIN_PATH,
412
405
  args
413
406
  );
414
- logger.debug('<- SecureTunnelHandlerSingleton.startLocalproxy');
407
+ logger.debug('<- SecureTunnelHandlerSingleton.startLocalProxy');
415
408
  }
416
409
 
417
410
  /**
418
- * Stops SecureTunnel localproxy process
411
+ * Stops SecureTunnel local proxy process
419
412
  */
420
- private async stopLocalproxy(): Promise<void> {
421
- logger.debug('-> SecureTunnelHandlerSingleton.stopLocalproxy');
422
- if (!this.localproxyInfo.lpProcess) {
423
- logger.debug('No localproxy process running');
424
- logger.debug('<- SecureTunnelHandlerSingleton.stopLocalproxy');
413
+ private async stopLocalProxy(): Promise<void> {
414
+ logger.debug('-> SecureTunnelHandlerSingleton.stopLocalProxy');
415
+ if (!this.localProxyInfo.lpProcess) {
416
+ logger.debug('No local proxy process running');
417
+ logger.debug('<- SecureTunnelHandlerSingleton.stopLocalProxy');
425
418
  return;
426
419
  }
427
420
 
428
421
  try {
429
422
  logger.debug(
430
- `About to kill localproxy: ${this.localproxyInfo.lpDstAccessKey}`
423
+ `About to kill local proxy: ${this.localProxyInfo.lpDstAccessKey}`
431
424
  );
432
- await killDetachedProcess(this.localproxyInfo.lpProcess, [
425
+ await killDetachedProcess(this.localProxyInfo.lpProcess, [
433
426
  SECURE_TUNNEL_BIN_PATH
434
427
  ]);
435
- logger.debug('SUCCESS: killing localproxy process');
428
+ logger.debug('SUCCESS: killing local proxy process');
436
429
  } catch (e) {
437
- logger.error('ERROR: killing localproxy process:', e);
430
+ logger.error('ERROR: killing local proxy process:', e);
438
431
  }
439
- this.localproxyInfo = {
432
+ this.localProxyInfo = {
440
433
  lpDstAccessKey: '',
441
434
  lpRegion: '',
442
435
  lpServices: '',
443
436
  lpProcess: null
444
437
  };
445
- logger.debug('<- SecureTunnelHandlerSingleton.stopLocalproxy');
438
+ logger.debug('<- SecureTunnelHandlerSingleton.stopLocalProxy');
446
439
  }
447
440
 
448
441
  /**
@@ -524,16 +517,16 @@ export class SecureTunnelHandlerSingleton {
524
517
  });
525
518
  }
526
519
 
527
- this.localproxyInfo.lpDstAccessKey = clientAccessToken;
528
- this.localproxyInfo.lpRegion = region;
529
- this.localproxyInfo.lpServices = portMappingList.join(',');
520
+ this.localProxyInfo.lpDstAccessKey = clientAccessToken;
521
+ this.localProxyInfo.lpRegion = region;
522
+ this.localProxyInfo.lpServices = portMappingList.join(',');
530
523
  logger.debug(`reported = ${JSON.stringify(this.reported.st_ports)}`);
531
- logger.debug(`localproxyInfo = ${JSON.stringify(this.localproxyInfo)}`);
524
+ logger.debug(`localProxyInfo = ${JSON.stringify(this.localProxyInfo)}`);
532
525
  logger.debug('<- SecureTunnelHandlerSingleton.processNotifyMessage');
533
526
  }
534
527
 
535
528
  /**
536
- * Downloads SecureTunnel localproxy, if it was not downloaded before
529
+ * Downloads SecureTunnel local proxy, if it was not downloaded before
537
530
  */
538
531
  private async downloadSecureTunnel(): Promise<void> {
539
532
  logger.debug('-> SecureTunnelHandlerSingleton.downloadSecureTunnel');
@@ -549,7 +542,7 @@ export class SecureTunnelHandlerSingleton {
549
542
  getOsVersion()
550
543
  ]);
551
544
 
552
- logger.info('Downloading SecureTunnel localproxy ...');
545
+ logger.info('Downloading SecureTunnel local proxy ...');
553
546
  const url = `${aaiArtifactsBucketUrl}/securetunnel/${linuxDistro}/${osVersion}/${arch}/${SECURE_TUNNEL_BIN_NAME}`;
554
547
  await JsSpawner().mkdirp(join(AAI_DIR, SECURE_TUNNEL_BIN_DIR));
555
548
  await downloadFile({
@@ -585,8 +578,8 @@ export class SecureTunnelHandlerSingleton {
585
578
  }
586
579
 
587
580
  private sortPorts(
588
- desired: SecureTunnelShadowDesRep
589
- ): SecureTunnelShadowDesRep {
581
+ desired: SecureTunnelShadowDescriptionReported
582
+ ): SecureTunnelShadowDescriptionReported {
590
583
  logger.debug('-> SecureTunnelHandlerSingleton.sortPorts');
591
584
  const sortedPorts = JSON.parse(JSON.stringify(this.reported));
592
585
  sortedPorts.st_ports.sort((a, b) => {
@@ -14,7 +14,7 @@ import {
14
14
  } from '../../local-connection/rabbitmq-connection';
15
15
  import { stopApp } from '../../application-control';
16
16
  import { LOCAL_CERT_AND_KEY_DIR } from 'alwaysai/lib/paths';
17
- import safeRimraf from '../../util/safe-rimraf';
17
+ import { safeRimraf } from '../../util/file';
18
18
 
19
19
  export const cleanCliLeaf = CliLeaf({
20
20
  name: 'clean',
@@ -0,0 +1,49 @@
1
+ import { CliLeaf } from '@alwaysai/alwayscli';
2
+ import {
3
+ getCpuDetails,
4
+ getDiskDetails,
5
+ getMemDetails,
6
+ getSystemInformation
7
+ } from '../../device-control/device-control';
8
+
9
+ export const getInfoCliLeaf = CliLeaf({
10
+ name: 'get-info',
11
+ description: 'Get device info',
12
+ namedInputs: {},
13
+ async action(_, opts) {
14
+ const cpuDetails = await getCpuDetails();
15
+ const diskDetails = await getDiskDetails();
16
+ const memDetails = await getMemDetails();
17
+ const out = {
18
+ 'CPU Utilization': `${
19
+ cpuDetails?.usedPerc && cpuDetails.temperature
20
+ ? `Used ${cpuDetails?.usedPerc?.toFixed(2)}%, Temperature ${
21
+ cpuDetails?.temperature
22
+ } °C`
23
+ : 'Unavailable'
24
+ }`,
25
+ 'Disk Utilization': `${
26
+ diskDetails?.usedGb && diskDetails.freeGb
27
+ ? `${diskDetails?.usedGb} GB / ${
28
+ diskDetails?.usedGb + diskDetails?.freeGb
29
+ } GB`
30
+ : 'Unavailable'
31
+ }`,
32
+ 'Memory Utilization': `${
33
+ memDetails?.usedMb && memDetails.freeMb
34
+ ? `${memDetails.usedMb} MB / ${
35
+ memDetails.usedMb + memDetails.freeMb
36
+ } MB`
37
+ : 'Unavailable'
38
+ }`
39
+ };
40
+ console.table(out);
41
+ const systemInfo = await getSystemInformation();
42
+ console.table(systemInfo.os);
43
+ console.table(systemInfo.cpu);
44
+ console.table(systemInfo.disk?.drives);
45
+ console.table(systemInfo.device);
46
+ console.table(systemInfo.network);
47
+ console.table(systemInfo.versions);
48
+ }
49
+ });
@@ -1,9 +1,18 @@
1
1
  import { CliBranch } from '@alwaysai/alwayscli';
2
- import { getInfoCliLeaf, initCliLeaf, restartCliLeaf } from './device';
2
+ import { getInfoCliLeaf } from './get-info';
3
3
  import { cleanCliLeaf } from './clean';
4
+ import { initCliLeaf } from './init';
5
+ import { restartCliLeaf } from './restart';
6
+ import { refreshCliLeaf } from './refresh';
4
7
 
5
8
  export const deviceCliBranch = CliBranch({
6
9
  name: 'device',
7
10
  description: 'Manage current device',
8
- subcommands: [initCliLeaf, getInfoCliLeaf, cleanCliLeaf, restartCliLeaf]
11
+ subcommands: [
12
+ initCliLeaf,
13
+ getInfoCliLeaf,
14
+ refreshCliLeaf,
15
+ cleanCliLeaf,
16
+ restartCliLeaf
17
+ ]
9
18
  });