@alwaysai/device-agent 0.0.1-2.1-beta-provision
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.
- package/lib/application-control/backup.d.ts +8 -0
- package/lib/application-control/backup.d.ts.map +1 -0
- package/lib/application-control/backup.js +37 -0
- package/lib/application-control/backup.js.map +1 -0
- package/lib/application-control/config.d.ts +17 -0
- package/lib/application-control/config.d.ts.map +1 -0
- package/lib/application-control/config.js +62 -0
- package/lib/application-control/config.js.map +1 -0
- package/lib/application-control/environment-variables.d.ts +9 -0
- package/lib/application-control/environment-variables.d.ts.map +1 -0
- package/lib/application-control/environment-variables.js +73 -0
- package/lib/application-control/environment-variables.js.map +1 -0
- package/lib/application-control/index.d.ts +10 -0
- package/lib/application-control/index.d.ts.map +1 -0
- package/lib/application-control/index.js +32 -0
- package/lib/application-control/index.js.map +1 -0
- package/lib/application-control/install.d.ts +22 -0
- package/lib/application-control/install.d.ts.map +1 -0
- package/lib/application-control/install.js +156 -0
- package/lib/application-control/install.js.map +1 -0
- package/lib/application-control/models.d.ts +23 -0
- package/lib/application-control/models.d.ts.map +1 -0
- package/lib/application-control/models.js +154 -0
- package/lib/application-control/models.js.map +1 -0
- package/lib/application-control/status.d.ts +27 -0
- package/lib/application-control/status.d.ts.map +1 -0
- package/lib/application-control/status.js +153 -0
- package/lib/application-control/status.js.map +1 -0
- package/lib/application-control/types.d.ts +5 -0
- package/lib/application-control/types.d.ts.map +1 -0
- package/lib/application-control/types.js +3 -0
- package/lib/application-control/types.js.map +1 -0
- package/lib/application-control/utils.d.ts +14 -0
- package/lib/application-control/utils.d.ts.map +1 -0
- package/lib/application-control/utils.js +82 -0
- package/lib/application-control/utils.js.map +1 -0
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts +51 -0
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -0
- package/lib/cloud-connection/device-agent-cloud-connection.js +490 -0
- package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -0
- package/lib/cloud-connection/device-agent.d.ts +21 -0
- package/lib/cloud-connection/device-agent.d.ts.map +1 -0
- package/lib/cloud-connection/device-agent.js +65 -0
- package/lib/cloud-connection/device-agent.js.map +1 -0
- package/lib/device-control/device-control.d.ts +4 -0
- package/lib/device-control/device-control.d.ts.map +1 -0
- package/lib/device-control/device-control.js +20 -0
- package/lib/device-control/device-control.js.map +1 -0
- package/lib/docker/docker-cmd.d.ts +4 -0
- package/lib/docker/docker-cmd.d.ts.map +1 -0
- package/lib/docker/docker-cmd.js +16 -0
- package/lib/docker/docker-cmd.js.map +1 -0
- package/lib/docker/docker-compose-cmd.d.ts +5 -0
- package/lib/docker/docker-compose-cmd.d.ts.map +1 -0
- package/lib/docker/docker-compose-cmd.js +16 -0
- package/lib/docker/docker-compose-cmd.js.map +1 -0
- package/lib/endpoints.d.ts +3 -0
- package/lib/endpoints.d.ts.map +1 -0
- package/lib/endpoints.js +28 -0
- package/lib/endpoints.js.map +1 -0
- package/lib/environment.d.ts +7 -0
- package/lib/environment.d.ts.map +1 -0
- package/lib/environment.js +24 -0
- package/lib/environment.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +26 -0
- package/lib/index.js.map +1 -0
- package/lib/infrastructure/agent-config.d.ts +73 -0
- package/lib/infrastructure/agent-config.d.ts.map +1 -0
- package/lib/infrastructure/agent-config.js +175 -0
- package/lib/infrastructure/agent-config.js.map +1 -0
- package/lib/infrastructure/agent-config.test.d.ts +2 -0
- package/lib/infrastructure/agent-config.test.d.ts.map +1 -0
- package/lib/infrastructure/agent-config.test.js +182 -0
- package/lib/infrastructure/agent-config.test.js.map +1 -0
- package/lib/infrastructure/certificates-and-tokens.d.ts +6 -0
- package/lib/infrastructure/certificates-and-tokens.d.ts.map +1 -0
- package/lib/infrastructure/certificates-and-tokens.js +37 -0
- package/lib/infrastructure/certificates-and-tokens.js.map +1 -0
- package/lib/infrastructure/urls.d.ts +2 -0
- package/lib/infrastructure/urls.d.ts.map +1 -0
- package/lib/infrastructure/urls.js +25 -0
- package/lib/infrastructure/urls.js.map +1 -0
- package/lib/root.d.ts +2 -0
- package/lib/root.d.ts.map +1 -0
- package/lib/root.js +12 -0
- package/lib/root.js.map +1 -0
- package/lib/subcommands/app/app.d.ts +59 -0
- package/lib/subcommands/app/app.d.ts.map +1 -0
- package/lib/subcommands/app/app.js +317 -0
- package/lib/subcommands/app/app.js.map +1 -0
- package/lib/subcommands/app/index.d.ts +2 -0
- package/lib/subcommands/app/index.d.ts.map +1 -0
- package/lib/subcommands/app/index.js +30 -0
- package/lib/subcommands/app/index.js.map +1 -0
- package/lib/subcommands/device/clean.d.ts +2 -0
- package/lib/subcommands/device/clean.d.ts.map +1 -0
- package/lib/subcommands/device/clean.js +20 -0
- package/lib/subcommands/device/clean.js.map +1 -0
- package/lib/subcommands/device/device.d.ts +6 -0
- package/lib/subcommands/device/device.d.ts.map +1 -0
- package/lib/subcommands/device/device.js +92 -0
- package/lib/subcommands/device/device.js.map +1 -0
- package/lib/subcommands/device/index.d.ts +2 -0
- package/lib/subcommands/device/index.d.ts.map +1 -0
- package/lib/subcommands/device/index.js +12 -0
- package/lib/subcommands/device/index.js.map +1 -0
- package/lib/subcommands/get-model-package.d.ts +5 -0
- package/lib/subcommands/get-model-package.d.ts.map +1 -0
- package/lib/subcommands/get-model-package.js +35 -0
- package/lib/subcommands/get-model-package.js.map +1 -0
- package/lib/subcommands/index.d.ts +9 -0
- package/lib/subcommands/index.d.ts.map +1 -0
- package/lib/subcommands/index.js +14 -0
- package/lib/subcommands/index.js.map +1 -0
- package/lib/subcommands/login.d.ts +6 -0
- package/lib/subcommands/login.d.ts.map +1 -0
- package/lib/subcommands/login.js +35 -0
- package/lib/subcommands/login.js.map +1 -0
- package/lib/util/clean-certs.d.ts +2 -0
- package/lib/util/clean-certs.d.ts.map +1 -0
- package/lib/util/clean-certs.js +16 -0
- package/lib/util/clean-certs.js.map +1 -0
- package/lib/util/copy-dir.d.ts +5 -0
- package/lib/util/copy-dir.d.ts.map +1 -0
- package/lib/util/copy-dir.js +16 -0
- package/lib/util/copy-dir.js.map +1 -0
- package/lib/util/directories.d.ts +23 -0
- package/lib/util/directories.d.ts.map +1 -0
- package/lib/util/directories.js +50 -0
- package/lib/util/directories.js.map +1 -0
- package/lib/util/get-device-id.d.ts +2 -0
- package/lib/util/get-device-id.d.ts.map +1 -0
- package/lib/util/get-device-id.js +24 -0
- package/lib/util/get-device-id.js.map +1 -0
- package/lib/util/http-client.d.ts +3 -0
- package/lib/util/http-client.d.ts.map +1 -0
- package/lib/util/http-client.js +30 -0
- package/lib/util/http-client.js.map +1 -0
- package/lib/util/logger.d.ts +4 -0
- package/lib/util/logger.d.ts.map +1 -0
- package/lib/util/logger.js +24 -0
- package/lib/util/logger.js.map +1 -0
- package/lib/util/run-in-dir.d.ts +2 -0
- package/lib/util/run-in-dir.d.ts.map +1 -0
- package/lib/util/run-in-dir.js +17 -0
- package/lib/util/run-in-dir.js.map +1 -0
- package/lib/util/sleep.d.ts +2 -0
- package/lib/util/sleep.d.ts.map +1 -0
- package/lib/util/sleep.js +9 -0
- package/lib/util/sleep.js.map +1 -0
- package/package.json +98 -0
- package/readme.md +219 -0
- package/src/application-control/backup.ts +36 -0
- package/src/application-control/config.ts +61 -0
- package/src/application-control/environment-variables.ts +74 -0
- package/src/application-control/index.ts +45 -0
- package/src/application-control/install.ts +206 -0
- package/src/application-control/models.ts +194 -0
- package/src/application-control/status.ts +187 -0
- package/src/application-control/types.ts +1 -0
- package/src/application-control/utils.ts +95 -0
- package/src/cloud-connection/device-agent-cloud-connection.ts +673 -0
- package/src/cloud-connection/device-agent.ts +120 -0
- package/src/device-control/device-control.ts +16 -0
- package/src/docker/docker-cmd.ts +12 -0
- package/src/docker/docker-compose-cmd.ts +12 -0
- package/src/endpoints.ts +24 -0
- package/src/environment.ts +28 -0
- package/src/index.ts +26 -0
- package/src/infrastructure/agent-config.test.ts +199 -0
- package/src/infrastructure/agent-config.ts +208 -0
- package/src/infrastructure/certificates-and-tokens.ts +47 -0
- package/src/infrastructure/urls.ts +21 -0
- package/src/root.ts +11 -0
- package/src/subcommands/app/app.ts +337 -0
- package/src/subcommands/app/index.ts +46 -0
- package/src/subcommands/device/clean.ts +16 -0
- package/src/subcommands/device/device.ts +126 -0
- package/src/subcommands/device/index.ts +9 -0
- package/src/subcommands/get-model-package.ts +33 -0
- package/src/subcommands/index.ts +11 -0
- package/src/subcommands/login.ts +33 -0
- package/src/util/clean-certs.ts +12 -0
- package/src/util/copy-dir.ts +12 -0
- package/src/util/directories.ts +82 -0
- package/src/util/get-device-id.ts +22 -0
- package/src/util/http-client.ts +35 -0
- package/src/util/logger.ts +28 -0
- package/src/util/run-in-dir.ts +15 -0
- package/src/util/sleep.ts +5 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CliTerseError } from '@alwaysai/alwayscli';
|
|
2
|
+
import { getSystemId } from 'alwaysai/lib/infrastructure';
|
|
3
|
+
|
|
4
|
+
export function getIoTCoreEndpointUrl() {
|
|
5
|
+
let iotCoreEndpointUrl = '';
|
|
6
|
+
switch (getSystemId()) {
|
|
7
|
+
case 'local':
|
|
8
|
+
case 'development':
|
|
9
|
+
iotCoreEndpointUrl = 'a170opbva29ts8-ats.iot.us-west-2.amazonaws.com';
|
|
10
|
+
break;
|
|
11
|
+
case 'qa':
|
|
12
|
+
iotCoreEndpointUrl = 'a3bff3qyyopgws-ats.iot.us-west-2.amazonaws.com';
|
|
13
|
+
break;
|
|
14
|
+
case 'production':
|
|
15
|
+
iotCoreEndpointUrl = 'a3tzi5g7sq5zsj-ats.iot.us-west-2.amazonaws.com';
|
|
16
|
+
break;
|
|
17
|
+
default:
|
|
18
|
+
throw new CliTerseError(`Remote deployment not supported on ${getSystemId()}!`);
|
|
19
|
+
}
|
|
20
|
+
return iotCoreEndpointUrl;
|
|
21
|
+
}
|
package/src/root.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const winston = require("winston");
|
|
2
|
+
|
|
3
|
+
import { CliBranch } from "@alwaysai/alwayscli";
|
|
4
|
+
|
|
5
|
+
import { subcommands } from "./subcommands";
|
|
6
|
+
|
|
7
|
+
export const root = CliBranch({
|
|
8
|
+
name: "aai-agent",
|
|
9
|
+
description: "Manage your alwaysAI production device",
|
|
10
|
+
subcommands,
|
|
11
|
+
});
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CliLeaf,
|
|
3
|
+
CliStringArrayInput,
|
|
4
|
+
CliStringInput,
|
|
5
|
+
CliTerseError,
|
|
6
|
+
} from '@alwaysai/alwayscli';
|
|
7
|
+
import {
|
|
8
|
+
addModel,
|
|
9
|
+
getAllEnvs,
|
|
10
|
+
getAppLogs,
|
|
11
|
+
getAppModels,
|
|
12
|
+
getAppStatus,
|
|
13
|
+
installApp,
|
|
14
|
+
listAppLatestRelease,
|
|
15
|
+
listAppReleases,
|
|
16
|
+
removeModel,
|
|
17
|
+
replaceModels,
|
|
18
|
+
restartApp,
|
|
19
|
+
rollbackApp,
|
|
20
|
+
setEnv,
|
|
21
|
+
startApp,
|
|
22
|
+
stopApp,
|
|
23
|
+
uninstallApp,
|
|
24
|
+
updateModels,
|
|
25
|
+
} from '../../application-control';
|
|
26
|
+
import { AgentConfigFile } from '../../infrastructure/agent-config';
|
|
27
|
+
import { logger } from '../../util/logger';
|
|
28
|
+
|
|
29
|
+
export const listAppsCliLeaf = CliLeaf({
|
|
30
|
+
name: 'list',
|
|
31
|
+
description: 'List all installed apps',
|
|
32
|
+
namedInputs: {},
|
|
33
|
+
async action(_, opts) {
|
|
34
|
+
const apps = await AgentConfigFile().getApps();
|
|
35
|
+
console.table(apps);
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
export const listAppReleasesCliLeaf = CliLeaf({
|
|
40
|
+
name: 'list-releases',
|
|
41
|
+
description: 'List all releases for a given app',
|
|
42
|
+
namedInputs: {
|
|
43
|
+
project: CliStringInput({
|
|
44
|
+
description: 'Project ID',
|
|
45
|
+
required: true,
|
|
46
|
+
}),
|
|
47
|
+
},
|
|
48
|
+
async action(_, opts) {
|
|
49
|
+
const { project } = opts;
|
|
50
|
+
const releaseHistory = await listAppReleases({ projectId: project });
|
|
51
|
+
logger.info(releaseHistory);
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export const listAppLatestReleaseCliLeaf = CliLeaf({
|
|
56
|
+
name: 'list-latest-release',
|
|
57
|
+
description: 'List the latest release hash for a given app',
|
|
58
|
+
namedInputs: {
|
|
59
|
+
project: CliStringInput({
|
|
60
|
+
description: 'Project ID',
|
|
61
|
+
required: true,
|
|
62
|
+
}),
|
|
63
|
+
},
|
|
64
|
+
async action(_, opts) {
|
|
65
|
+
const { project } = opts;
|
|
66
|
+
const latestReleaseHash = await listAppLatestRelease({ projectId: project });
|
|
67
|
+
if (latestReleaseHash === undefined) {
|
|
68
|
+
throw new CliTerseError('This application has not been published yet');
|
|
69
|
+
}
|
|
70
|
+
logger.info(latestReleaseHash);
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
export const installAppCliLeaf = CliLeaf({
|
|
75
|
+
name: 'install',
|
|
76
|
+
description: 'Install an alwaysAI app from a project',
|
|
77
|
+
namedInputs: {
|
|
78
|
+
project: CliStringInput({
|
|
79
|
+
description: 'Project ID',
|
|
80
|
+
required: true,
|
|
81
|
+
}),
|
|
82
|
+
releaseHash: CliStringInput({
|
|
83
|
+
description: 'Release Hash',
|
|
84
|
+
}),
|
|
85
|
+
},
|
|
86
|
+
async action(_, opts) {
|
|
87
|
+
const project = opts.project;
|
|
88
|
+
let releaseHash = opts.releaseHash;
|
|
89
|
+
if (releaseHash === undefined) {
|
|
90
|
+
releaseHash = await listAppLatestRelease({ projectId: project });
|
|
91
|
+
}
|
|
92
|
+
if (releaseHash === undefined) {
|
|
93
|
+
throw new CliTerseError('This application has not been published yet');
|
|
94
|
+
}
|
|
95
|
+
await installApp({ projectId: project, appReleaseHash: releaseHash });
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
export const getAppStatusCliLeaf = CliLeaf({
|
|
100
|
+
name: 'status',
|
|
101
|
+
description: 'Get the status of an installed alwaysAI app',
|
|
102
|
+
namedInputs: {
|
|
103
|
+
project: CliStringInput({
|
|
104
|
+
description: 'Project ID',
|
|
105
|
+
required: true,
|
|
106
|
+
}),
|
|
107
|
+
},
|
|
108
|
+
async action(_, opts) {
|
|
109
|
+
const { project } = opts;
|
|
110
|
+
const appStatus = await getAppStatus({ projectId: project });
|
|
111
|
+
logger.info(appStatus);
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
export const startAppCliLeaf = CliLeaf({
|
|
116
|
+
name: 'start',
|
|
117
|
+
description: 'Start an installed alwaysAI app',
|
|
118
|
+
namedInputs: {
|
|
119
|
+
project: CliStringInput({
|
|
120
|
+
description: 'Project ID',
|
|
121
|
+
required: true,
|
|
122
|
+
}),
|
|
123
|
+
dockerLoginToken: CliStringInput({
|
|
124
|
+
description: 'Docker login token',
|
|
125
|
+
}),
|
|
126
|
+
},
|
|
127
|
+
async action(_, opts) {
|
|
128
|
+
const { project, dockerLoginToken } = opts;
|
|
129
|
+
await startApp({ projectId: project, dockerLoginToken });
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
export const getAppLogsCliLeaf = CliLeaf({
|
|
134
|
+
name: 'logs',
|
|
135
|
+
description: 'Get logs for an application',
|
|
136
|
+
namedInputs: {
|
|
137
|
+
project: CliStringInput({
|
|
138
|
+
description: 'Project ID',
|
|
139
|
+
required: true,
|
|
140
|
+
}),
|
|
141
|
+
},
|
|
142
|
+
async action(_, opts) {
|
|
143
|
+
const { project } = opts;
|
|
144
|
+
const readable = await getAppLogs({ projectId: project });
|
|
145
|
+
readable.setEncoding('utf8');
|
|
146
|
+
for await (const chunk of readable) {
|
|
147
|
+
logger.info(chunk);
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
export const stopAppCliLeaf = CliLeaf({
|
|
153
|
+
name: 'stop',
|
|
154
|
+
description: 'Stop a running alwaysAI app',
|
|
155
|
+
namedInputs: {
|
|
156
|
+
project: CliStringInput({
|
|
157
|
+
description: 'Project ID',
|
|
158
|
+
required: true,
|
|
159
|
+
}),
|
|
160
|
+
},
|
|
161
|
+
async action(_, opts) {
|
|
162
|
+
const { project } = opts;
|
|
163
|
+
await stopApp({ projectId: project });
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
export const restartAppCliLeaf = CliLeaf({
|
|
168
|
+
name: 'restart',
|
|
169
|
+
description: 'Restart running alwaysAI app',
|
|
170
|
+
namedInputs: {
|
|
171
|
+
project: CliStringInput({
|
|
172
|
+
description: 'Project ID',
|
|
173
|
+
required: true,
|
|
174
|
+
}),
|
|
175
|
+
},
|
|
176
|
+
async action(_, opts) {
|
|
177
|
+
const { project } = opts;
|
|
178
|
+
await restartApp({ projectId: project });
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
export const uninstallAppCliLeaf = CliLeaf({
|
|
183
|
+
name: 'uninstall',
|
|
184
|
+
description: 'Remove an alwaysAI app',
|
|
185
|
+
namedInputs: {
|
|
186
|
+
project: CliStringInput({
|
|
187
|
+
description: 'Project ID',
|
|
188
|
+
required: true,
|
|
189
|
+
}),
|
|
190
|
+
},
|
|
191
|
+
async action(_, opts) {
|
|
192
|
+
const { project } = opts;
|
|
193
|
+
await uninstallApp({ projectId: project });
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
export const rollbackAppCliLeaf = CliLeaf({
|
|
198
|
+
name: 'rollback',
|
|
199
|
+
description: 'Rollback an alwaysAI app to the previous version',
|
|
200
|
+
namedInputs: {
|
|
201
|
+
project: CliStringInput({
|
|
202
|
+
description: 'Project ID',
|
|
203
|
+
required: true,
|
|
204
|
+
}),
|
|
205
|
+
},
|
|
206
|
+
async action(_, opts) {
|
|
207
|
+
const { project } = opts;
|
|
208
|
+
await rollbackApp({ projectId: project });
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
export const showAppModelsCliLeaf = CliLeaf({
|
|
213
|
+
name: 'show-models',
|
|
214
|
+
description: 'Show the application models',
|
|
215
|
+
namedInputs: {
|
|
216
|
+
project: CliStringInput({
|
|
217
|
+
description: 'Project ID',
|
|
218
|
+
required: true,
|
|
219
|
+
}),
|
|
220
|
+
},
|
|
221
|
+
async action(_, opts) {
|
|
222
|
+
const { project } = opts;
|
|
223
|
+
const appModels = await getAppModels({ projectId: project });
|
|
224
|
+
console.table(appModels);
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
export const addModelCliLeaf = CliLeaf({
|
|
229
|
+
name: 'add-model',
|
|
230
|
+
description: 'Add a model to an alwaysAI app',
|
|
231
|
+
namedInputs: {
|
|
232
|
+
project: CliStringInput({
|
|
233
|
+
description: 'Project ID',
|
|
234
|
+
required: true,
|
|
235
|
+
}),
|
|
236
|
+
model: CliStringInput({
|
|
237
|
+
description: 'Model ID',
|
|
238
|
+
required: true,
|
|
239
|
+
}),
|
|
240
|
+
},
|
|
241
|
+
async action(_, opts) {
|
|
242
|
+
const { project, model } = opts;
|
|
243
|
+
await addModel({ projectId: project, modelId: model });
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
export const removeModelCliLeaf = CliLeaf({
|
|
248
|
+
name: 'remove-model',
|
|
249
|
+
description: 'Remove a model from an alwaysAI app',
|
|
250
|
+
namedInputs: {
|
|
251
|
+
project: CliStringInput({
|
|
252
|
+
description: 'Project ID',
|
|
253
|
+
required: true,
|
|
254
|
+
}),
|
|
255
|
+
model: CliStringInput({
|
|
256
|
+
description: 'Model ID',
|
|
257
|
+
required: true,
|
|
258
|
+
}),
|
|
259
|
+
},
|
|
260
|
+
async action(_, opts) {
|
|
261
|
+
const { project, model } = opts;
|
|
262
|
+
await removeModel({ projectId: project, modelId: model });
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
export const replaceModelsCliLeaf = CliLeaf({
|
|
267
|
+
name: 'replace-models',
|
|
268
|
+
description: 'Replace all models of an alwaysAI app with new models',
|
|
269
|
+
namedInputs: {
|
|
270
|
+
project: CliStringInput({
|
|
271
|
+
description: 'Project Id',
|
|
272
|
+
required: true,
|
|
273
|
+
}),
|
|
274
|
+
models: CliStringArrayInput({
|
|
275
|
+
description: 'One or more model IDs',
|
|
276
|
+
required: true,
|
|
277
|
+
}),
|
|
278
|
+
},
|
|
279
|
+
async action(_, opts) {
|
|
280
|
+
const { project, models } = opts;
|
|
281
|
+
await replaceModels({ projectId: project, modelIds: models });
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
export const updateModelsCliLeaf = CliLeaf({
|
|
286
|
+
name: 'update-models',
|
|
287
|
+
description: 'Update all models for an alwaysAI app',
|
|
288
|
+
namedInputs: {
|
|
289
|
+
project: CliStringInput({
|
|
290
|
+
description: 'Project Id',
|
|
291
|
+
required: true,
|
|
292
|
+
}),
|
|
293
|
+
},
|
|
294
|
+
async action(_, opts) {
|
|
295
|
+
const { project } = opts;
|
|
296
|
+
await updateModels({ projectId: project });
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
export const getAllEnvsCLiLeaf = CliLeaf({
|
|
301
|
+
name: 'get-all-envs',
|
|
302
|
+
description: 'Get environment variables for an application',
|
|
303
|
+
namedInputs: {
|
|
304
|
+
project: CliStringInput({
|
|
305
|
+
description: 'Project Id',
|
|
306
|
+
required: true,
|
|
307
|
+
}),
|
|
308
|
+
},
|
|
309
|
+
async action(_, opts) {
|
|
310
|
+
const { project } = opts;
|
|
311
|
+
logger.info(await getAllEnvs({ projectId: project }));
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
export const setEnvCLiLeaf = CliLeaf({
|
|
316
|
+
name: 'set-env',
|
|
317
|
+
description: 'Set environment variables for a service',
|
|
318
|
+
positionalInput: CliStringArrayInput({
|
|
319
|
+
placeholder: '<NAME=VALUE> [<NAME=VALUE> ...]',
|
|
320
|
+
required: true,
|
|
321
|
+
}),
|
|
322
|
+
namedInputs: {
|
|
323
|
+
project: CliStringInput({
|
|
324
|
+
description: 'Project Id',
|
|
325
|
+
required: true,
|
|
326
|
+
}),
|
|
327
|
+
service: CliStringInput({
|
|
328
|
+
description:
|
|
329
|
+
'The name of the docker-compose service to apply environment variable to',
|
|
330
|
+
required: false,
|
|
331
|
+
}),
|
|
332
|
+
},
|
|
333
|
+
async action(args, opts) {
|
|
334
|
+
const { project, service } = opts;
|
|
335
|
+
await setEnv({ projectId: project, vars: args, service });
|
|
336
|
+
},
|
|
337
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { CliBranch } from '@alwaysai/alwayscli';
|
|
2
|
+
import {
|
|
3
|
+
getAppStatusCliLeaf,
|
|
4
|
+
listAppsCliLeaf,
|
|
5
|
+
installAppCliLeaf,
|
|
6
|
+
rollbackAppCliLeaf,
|
|
7
|
+
startAppCliLeaf,
|
|
8
|
+
stopAppCliLeaf,
|
|
9
|
+
uninstallAppCliLeaf,
|
|
10
|
+
addModelCliLeaf,
|
|
11
|
+
removeModelCliLeaf,
|
|
12
|
+
updateModelsCliLeaf,
|
|
13
|
+
getAppLogsCliLeaf,
|
|
14
|
+
listAppReleasesCliLeaf,
|
|
15
|
+
listAppLatestReleaseCliLeaf,
|
|
16
|
+
restartAppCliLeaf,
|
|
17
|
+
replaceModelsCliLeaf,
|
|
18
|
+
showAppModelsCliLeaf,
|
|
19
|
+
getAllEnvsCLiLeaf,
|
|
20
|
+
setEnvCLiLeaf,
|
|
21
|
+
} from './app';
|
|
22
|
+
|
|
23
|
+
export const appCliBranch = CliBranch({
|
|
24
|
+
name: 'app',
|
|
25
|
+
description: 'Manage alwaysAI applications',
|
|
26
|
+
subcommands: [
|
|
27
|
+
listAppsCliLeaf,
|
|
28
|
+
listAppReleasesCliLeaf,
|
|
29
|
+
listAppLatestReleaseCliLeaf,
|
|
30
|
+
installAppCliLeaf,
|
|
31
|
+
getAppStatusCliLeaf,
|
|
32
|
+
startAppCliLeaf,
|
|
33
|
+
stopAppCliLeaf,
|
|
34
|
+
restartAppCliLeaf,
|
|
35
|
+
getAppLogsCliLeaf,
|
|
36
|
+
uninstallAppCliLeaf,
|
|
37
|
+
rollbackAppCliLeaf,
|
|
38
|
+
showAppModelsCliLeaf,
|
|
39
|
+
addModelCliLeaf,
|
|
40
|
+
removeModelCliLeaf,
|
|
41
|
+
replaceModelsCliLeaf,
|
|
42
|
+
updateModelsCliLeaf,
|
|
43
|
+
getAllEnvsCLiLeaf,
|
|
44
|
+
setEnvCLiLeaf,
|
|
45
|
+
],
|
|
46
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CliLeaf, CliStringInput } from "@alwaysai/alwayscli";
|
|
2
|
+
import * as rimraf from "rimraf";
|
|
3
|
+
import { AAI_DIR, LOCAL_CERT_AND_KEY_DIR } from "alwaysai/lib/constants";
|
|
4
|
+
import { AGENT_CONFIG_FILE_PATH } from "../../util/directories";
|
|
5
|
+
import { logger } from "../../util/logger";
|
|
6
|
+
export const cleanCliLeaf = CliLeaf({
|
|
7
|
+
name: "clean",
|
|
8
|
+
description: "Removes current provisioned device-agent",
|
|
9
|
+
async action(_, opts) {
|
|
10
|
+
logger.info("Removing files...");
|
|
11
|
+
rimraf.sync(AAI_DIR);
|
|
12
|
+
rimraf.sync(LOCAL_CERT_AND_KEY_DIR);
|
|
13
|
+
rimraf.sync(AGENT_CONFIG_FILE_PATH);
|
|
14
|
+
logger.info("Files removed");
|
|
15
|
+
},
|
|
16
|
+
});
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { CliLeaf, CliStringInput } from "@alwaysai/alwayscli";
|
|
2
|
+
import { checkUserIsLoggedInComponent } from "alwaysai/lib/components/user";
|
|
3
|
+
import { checkPaidPlan } from "alwaysai/lib/core/project";
|
|
4
|
+
import { v4 as uuidv4 } from "uuid";
|
|
5
|
+
import { CliAuthenticationClient } from "alwaysai/lib/infrastructure";
|
|
6
|
+
import { existsSync } from "fs";
|
|
7
|
+
import { httpClient, microServiceHttpClient } from "../../util/http-client";
|
|
8
|
+
import {
|
|
9
|
+
AWS_ROOT_CERTIFICATE_FILE_NAME,
|
|
10
|
+
BOOTSTRAP_CERTIFICATES_DIR_PATH,
|
|
11
|
+
getPrivateKeyFilePath,
|
|
12
|
+
} from "../../util/directories";
|
|
13
|
+
|
|
14
|
+
import { LOCAL_CERT_AND_KEY_DIR } from "alwaysai/lib/constants";
|
|
15
|
+
import { JsSpawner } from "alwaysai/lib/util";
|
|
16
|
+
import {
|
|
17
|
+
getCpuUtil,
|
|
18
|
+
getDiskUtil,
|
|
19
|
+
getMemUtil,
|
|
20
|
+
} from "../../device-control/device-control";
|
|
21
|
+
import { writeCertificateAndToken } from "../../infrastructure/certificates-and-tokens";
|
|
22
|
+
import { logger } from "../../util/logger";
|
|
23
|
+
|
|
24
|
+
export const initCliLeaf = CliLeaf({
|
|
25
|
+
name: "init",
|
|
26
|
+
description: "Initialize device",
|
|
27
|
+
namedInputs: {
|
|
28
|
+
name: CliStringInput({
|
|
29
|
+
description: "Device name",
|
|
30
|
+
required: true,
|
|
31
|
+
}),
|
|
32
|
+
description: CliStringInput({
|
|
33
|
+
description: "Device description",
|
|
34
|
+
required: false,
|
|
35
|
+
}),
|
|
36
|
+
},
|
|
37
|
+
async action(_, opts) {
|
|
38
|
+
const { name, description } = opts;
|
|
39
|
+
switch (true) {
|
|
40
|
+
case !existsSync(getPrivateKeyFilePath()):
|
|
41
|
+
{
|
|
42
|
+
logger.info("Initializing device");
|
|
43
|
+
await checkUserIsLoggedInComponent({ yes: true });
|
|
44
|
+
if (!(await checkPaidPlan())) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`This action only supported for Enterprise alwaysAI accounts!`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
const { username } = await CliAuthenticationClient().getInfo();
|
|
50
|
+
const spawner = JsSpawner();
|
|
51
|
+
const device = {
|
|
52
|
+
deviceMode: "production",
|
|
53
|
+
hardwareId: uuidv4(),
|
|
54
|
+
txId: uuidv4(),
|
|
55
|
+
userName: username,
|
|
56
|
+
friendlyName: name,
|
|
57
|
+
};
|
|
58
|
+
//**NOTE: hardwareId currently is mocked. The real hardwareId will be used in future work
|
|
59
|
+
|
|
60
|
+
const response: { deviceUuid: string; claimCertificate: string[] } =
|
|
61
|
+
await microServiceHttpClient(
|
|
62
|
+
"fleet-provision",
|
|
63
|
+
"addDevice",
|
|
64
|
+
"POST",
|
|
65
|
+
JSON.stringify(device)
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
if (Object.hasOwn(response, "claimCertificate")) {
|
|
69
|
+
const ROOT_CERT_AWS = await httpClient(
|
|
70
|
+
"https://www.amazontrust.com/repository/AmazonRootCA1.pem",
|
|
71
|
+
"GET"
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
await writeCertificateAndToken({ deviceUuid: response.deviceUuid });
|
|
75
|
+
|
|
76
|
+
const hardwareIdSpawner = JsSpawner({
|
|
77
|
+
path: LOCAL_CERT_AND_KEY_DIR,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await JsSpawner().mkdirp(BOOTSTRAP_CERTIFICATES_DIR_PATH);
|
|
81
|
+
await hardwareIdSpawner.writeFile(
|
|
82
|
+
"hardware-id.txt",
|
|
83
|
+
device.hardwareId
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
JsSpawner({ path: LOCAL_CERT_AND_KEY_DIR }).writeFile(
|
|
87
|
+
AWS_ROOT_CERTIFICATE_FILE_NAME,
|
|
88
|
+
ROOT_CERT_AWS
|
|
89
|
+
);
|
|
90
|
+
const certSpawner = JsSpawner({
|
|
91
|
+
path: BOOTSTRAP_CERTIFICATES_DIR_PATH,
|
|
92
|
+
});
|
|
93
|
+
for (const key in response.claimCertificate) {
|
|
94
|
+
await certSpawner.writeFile(key, response.claimCertificate[key]);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
logger.info(`Initialized device as ${response.deviceUuid}`);
|
|
98
|
+
} else {
|
|
99
|
+
logger.info(
|
|
100
|
+
"Device cannot be provisioned. Run 'device-agent device clean' and retry."
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
break;
|
|
105
|
+
default: {
|
|
106
|
+
logger.info(
|
|
107
|
+
"Device has been previously provisioned. Run 'device-agent device clean' to re-provision"
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
export const getInfoCliLeaf = CliLeaf({
|
|
115
|
+
name: "get-info",
|
|
116
|
+
description: "Get device info",
|
|
117
|
+
namedInputs: {},
|
|
118
|
+
async action(_, opts) {
|
|
119
|
+
const deviceInfo = [
|
|
120
|
+
["CPU Utilization", `${String(await getCpuUtil())} %`],
|
|
121
|
+
["Disk Utilization", `${String(await getDiskUtil())} %`],
|
|
122
|
+
["Memory Utilization", `${String(await getMemUtil())} %`],
|
|
123
|
+
];
|
|
124
|
+
console.table(deviceInfo);
|
|
125
|
+
},
|
|
126
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CliBranch } from "@alwaysai/alwayscli";
|
|
2
|
+
import { getInfoCliLeaf, initCliLeaf } from "./device";
|
|
3
|
+
import { cleanCliLeaf } from "./clean";
|
|
4
|
+
|
|
5
|
+
export const deviceCliBranch = CliBranch({
|
|
6
|
+
name: "device",
|
|
7
|
+
description: "Manage current device",
|
|
8
|
+
subcommands: [initCliLeaf, getInfoCliLeaf, cleanCliLeaf],
|
|
9
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { CliLeaf, CliNumberInput, CliStringInput } from '@alwaysai/alwayscli';
|
|
2
|
+
import { appInstallModel } from 'alwaysai/lib/core/app';
|
|
3
|
+
import { CliRpcClient } from 'alwaysai/lib/infrastructure';
|
|
4
|
+
import { JsSpawner } from 'alwaysai/lib/util';
|
|
5
|
+
import { logger } from '../util/logger';
|
|
6
|
+
|
|
7
|
+
export const getModelPackageCliLeaf = CliLeaf({
|
|
8
|
+
name: 'get-model-package',
|
|
9
|
+
description: 'Download and unpack a model package',
|
|
10
|
+
positionalInput: CliStringInput({
|
|
11
|
+
description: 'For example, "alwaysai/mobilenet_ssd"',
|
|
12
|
+
required: true,
|
|
13
|
+
placeholder: '<id>',
|
|
14
|
+
}),
|
|
15
|
+
namedInputs: {
|
|
16
|
+
version: CliNumberInput({
|
|
17
|
+
description: 'The version number of the model',
|
|
18
|
+
required: false,
|
|
19
|
+
}),
|
|
20
|
+
path: CliStringInput({
|
|
21
|
+
description: 'The output path to write model package to',
|
|
22
|
+
required: false,
|
|
23
|
+
}),
|
|
24
|
+
},
|
|
25
|
+
async action(id, opts) {
|
|
26
|
+
const path = opts.path || process.cwd();
|
|
27
|
+
const spawner = JsSpawner({ path });
|
|
28
|
+
const version =
|
|
29
|
+
opts.version || (await CliRpcClient().getModelVersion({ id })).version;
|
|
30
|
+
await appInstallModel(spawner, id, version);
|
|
31
|
+
logger.info(`Completed downloading ${id} to ${path}`);
|
|
32
|
+
},
|
|
33
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { appCliBranch } from './app';
|
|
2
|
+
import { deviceCliBranch } from './device';
|
|
3
|
+
import { loginCliLeaf } from './login';
|
|
4
|
+
import { getModelPackageCliLeaf } from './get-model-package';
|
|
5
|
+
|
|
6
|
+
export const subcommands = [
|
|
7
|
+
loginCliLeaf,
|
|
8
|
+
appCliBranch,
|
|
9
|
+
deviceCliBranch,
|
|
10
|
+
getModelPackageCliLeaf,
|
|
11
|
+
];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { CliLeaf, CliStringInput } from '@alwaysai/alwayscli';
|
|
2
|
+
import { alwaysaiUserLoginYesComponent } from 'alwaysai/lib/components/user';
|
|
3
|
+
import { writeCertificateAndToken } from '../infrastructure/certificates-and-tokens';
|
|
4
|
+
|
|
5
|
+
export const loginCliLeaf = CliLeaf({
|
|
6
|
+
name: 'login',
|
|
7
|
+
description: 'Login to alwaysAI (this is meant for scripted environments)',
|
|
8
|
+
namedInputs: {
|
|
9
|
+
email: CliStringInput({
|
|
10
|
+
description: 'alwaysAI email',
|
|
11
|
+
required: true,
|
|
12
|
+
}),
|
|
13
|
+
password: CliStringInput({
|
|
14
|
+
description: 'Account password',
|
|
15
|
+
required: true,
|
|
16
|
+
}),
|
|
17
|
+
device: CliStringInput({
|
|
18
|
+
description: 'The device UUID',
|
|
19
|
+
required: false,
|
|
20
|
+
}),
|
|
21
|
+
},
|
|
22
|
+
async action(_, opts) {
|
|
23
|
+
const { email, password, device } = opts;
|
|
24
|
+
|
|
25
|
+
await alwaysaiUserLoginYesComponent({
|
|
26
|
+
alwaysaiUserEmail: email,
|
|
27
|
+
alwaysaiUserPassword: password,
|
|
28
|
+
});
|
|
29
|
+
if (device) {
|
|
30
|
+
await writeCertificateAndToken({ deviceUuid: device });
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { JsSpawner } from "alwaysai/lib/util";
|
|
2
|
+
import { logger } from "../util/logger";
|
|
3
|
+
import { LOCAL_CERT_AND_KEY_DIR } from "alwaysai/lib/constants";
|
|
4
|
+
import { BOOTSTRAP_CERTIFICATES_DIR_PATH } from "../util/directories";
|
|
5
|
+
|
|
6
|
+
export const rmBootstrapCertsAndClose = async () => {
|
|
7
|
+
const spawner = JsSpawner();
|
|
8
|
+
await spawner.rimraf(BOOTSTRAP_CERTIFICATES_DIR_PATH);
|
|
9
|
+
await spawner.rimraf(LOCAL_CERT_AND_KEY_DIR);
|
|
10
|
+
logger.info("Could not provision device. Try again.");
|
|
11
|
+
process.exit();
|
|
12
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { JsSpawner } from "alwaysai/lib/util";
|
|
2
|
+
|
|
3
|
+
export async function copyDir(props: { srcPath: string; destPath: string }) {
|
|
4
|
+
const { srcPath, destPath } = props;
|
|
5
|
+
const src = JsSpawner({ path: srcPath });
|
|
6
|
+
const allFileNames = await src.readdir();
|
|
7
|
+
const dest = JsSpawner({ path: destPath });
|
|
8
|
+
await dest.mkdirp();
|
|
9
|
+
if (allFileNames.length) {
|
|
10
|
+
await dest.untar(await src.tar(...allFileNames));
|
|
11
|
+
}
|
|
12
|
+
}
|