@alwaysai/device-agent 0.0.12 → 0.0.14
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.map +1 -1
- package/lib/application-control/backup.js +11 -5
- package/lib/application-control/backup.js.map +1 -1
- package/lib/application-control/config.d.ts +12 -4
- package/lib/application-control/config.d.ts.map +1 -1
- package/lib/application-control/config.js +59 -16
- package/lib/application-control/config.js.map +1 -1
- package/lib/application-control/environment-variables.d.ts.map +1 -1
- package/lib/application-control/environment-variables.js.map +1 -1
- package/lib/application-control/index.d.ts +5 -5
- package/lib/application-control/index.d.ts.map +1 -1
- package/lib/application-control/index.js +4 -6
- package/lib/application-control/index.js.map +1 -1
- package/lib/application-control/install.d.ts +1 -1
- package/lib/application-control/install.d.ts.map +1 -1
- package/lib/application-control/install.js +58 -57
- package/lib/application-control/install.js.map +1 -1
- package/lib/application-control/models.d.ts +7 -5
- package/lib/application-control/models.d.ts.map +1 -1
- package/lib/application-control/models.js +78 -57
- package/lib/application-control/models.js.map +1 -1
- package/lib/application-control/status.d.ts +0 -6
- package/lib/application-control/status.d.ts.map +1 -1
- package/lib/application-control/status.js +21 -33
- package/lib/application-control/status.js.map +1 -1
- package/lib/application-control/utils.d.ts +3 -2
- package/lib/application-control/utils.d.ts.map +1 -1
- package/lib/application-control/utils.js +54 -34
- package/lib/application-control/utils.js.map +1 -1
- package/lib/cloud-connection/app-install-status.d.ts +16 -0
- package/lib/cloud-connection/app-install-status.d.ts.map +1 -0
- package/lib/cloud-connection/app-install-status.js +53 -0
- package/lib/cloud-connection/app-install-status.js.map +1 -0
- package/lib/cloud-connection/bootstrap-provision.d.ts +2 -0
- package/lib/cloud-connection/bootstrap-provision.d.ts.map +1 -0
- package/lib/cloud-connection/bootstrap-provision.js +34 -0
- package/lib/cloud-connection/bootstrap-provision.js.map +1 -0
- package/lib/cloud-connection/cmd-status.d.ts +16 -0
- package/lib/cloud-connection/cmd-status.d.ts.map +1 -0
- package/lib/cloud-connection/cmd-status.js +49 -0
- package/lib/cloud-connection/cmd-status.js.map +1 -0
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts +21 -34
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.js +211 -387
- package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
- package/lib/cloud-connection/device-agent.d.ts.map +1 -1
- package/lib/cloud-connection/device-agent.js +22 -26
- package/lib/cloud-connection/device-agent.js.map +1 -1
- package/lib/cloud-connection/live-updates-handler.d.ts +34 -0
- package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -0
- package/lib/cloud-connection/live-updates-handler.js +167 -0
- package/lib/cloud-connection/live-updates-handler.js.map +1 -0
- package/lib/cloud-connection/messages.d.ts +14 -0
- package/lib/cloud-connection/messages.d.ts.map +1 -0
- package/lib/cloud-connection/messages.js +38 -0
- package/lib/cloud-connection/messages.js.map +1 -0
- package/lib/cloud-connection/passthrough-handler.d.ts +11 -0
- package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -0
- package/lib/cloud-connection/passthrough-handler.js +59 -0
- package/lib/cloud-connection/passthrough-handler.js.map +1 -0
- package/lib/cloud-connection/publisher.d.ts +15 -0
- package/lib/cloud-connection/publisher.d.ts.map +1 -0
- package/lib/cloud-connection/publisher.js +58 -0
- package/lib/cloud-connection/publisher.js.map +1 -0
- package/lib/cloud-connection/shadow-handler.d.ts +33 -0
- package/lib/cloud-connection/shadow-handler.d.ts.map +1 -0
- package/lib/cloud-connection/shadow-handler.js +108 -0
- package/lib/cloud-connection/shadow-handler.js.map +1 -0
- package/lib/cloud-connection/shadow-handler.test.d.ts +2 -0
- package/lib/cloud-connection/shadow-handler.test.d.ts.map +1 -0
- package/lib/cloud-connection/shadow-handler.test.js +321 -0
- package/lib/cloud-connection/shadow-handler.test.js.map +1 -0
- package/lib/cloud-connection/shadow.d.ts +16 -0
- package/lib/cloud-connection/shadow.d.ts.map +1 -0
- package/lib/cloud-connection/shadow.js +36 -0
- package/lib/cloud-connection/shadow.js.map +1 -0
- package/lib/device-control/device-control.d.ts.map +1 -1
- package/lib/device-control/device-control.js +1 -0
- package/lib/device-control/device-control.js.map +1 -1
- package/lib/docker/docker-cmd.js +1 -1
- package/lib/docker/docker-compose-cmd.d.ts.map +1 -1
- package/lib/docker/docker-compose-cmd.js +1 -1
- package/lib/docker/docker-compose-cmd.js.map +1 -1
- package/lib/endpoints.js +10 -10
- package/lib/endpoints.js.map +1 -1
- package/lib/environment.d.ts +1 -0
- package/lib/environment.d.ts.map +1 -1
- package/lib/environment.js +2 -1
- package/lib/environment.js.map +1 -1
- package/lib/infrastructure/agent-config.d.ts +15 -58
- package/lib/infrastructure/agent-config.d.ts.map +1 -1
- package/lib/infrastructure/agent-config.js +22 -15
- package/lib/infrastructure/agent-config.js.map +1 -1
- package/lib/infrastructure/agent-config.test.js +25 -23
- package/lib/infrastructure/agent-config.test.js.map +1 -1
- package/lib/infrastructure/system-id.d.ts +2 -0
- package/lib/infrastructure/system-id.d.ts.map +1 -0
- package/lib/infrastructure/system-id.js +21 -0
- package/lib/infrastructure/system-id.js.map +1 -0
- package/lib/infrastructure/tokens-and-device-cfg.d.ts +4 -0
- package/lib/infrastructure/tokens-and-device-cfg.d.ts.map +1 -0
- package/lib/infrastructure/tokens-and-device-cfg.js +27 -0
- package/lib/infrastructure/tokens-and-device-cfg.js.map +1 -0
- package/lib/infrastructure/urls.d.ts.map +1 -1
- package/lib/infrastructure/urls.js +3 -3
- package/lib/infrastructure/urls.js.map +1 -1
- package/lib/local-connection/rabbitmq-connection.d.ts +4 -0
- package/lib/local-connection/rabbitmq-connection.d.ts.map +1 -0
- package/lib/local-connection/rabbitmq-connection.js +58 -0
- package/lib/local-connection/rabbitmq-connection.js.map +1 -0
- package/lib/root.d.ts.map +1 -1
- package/lib/root.js +2 -7
- package/lib/root.js.map +1 -1
- package/lib/subcommands/app/app.d.ts +2 -1
- package/lib/subcommands/app/app.d.ts.map +1 -1
- package/lib/subcommands/app/app.js +112 -77
- package/lib/subcommands/app/app.js.map +1 -1
- package/lib/subcommands/app/index.js +2 -2
- 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 +29 -0
- package/lib/subcommands/device/clean.js.map +1 -0
- package/lib/subcommands/device/device.d.ts +1 -1
- package/lib/subcommands/device/device.d.ts.map +1 -1
- package/lib/subcommands/device/device.js +44 -33
- package/lib/subcommands/device/device.js.map +1 -1
- package/lib/subcommands/device/index.d.ts.map +1 -1
- package/lib/subcommands/device/index.js +2 -1
- package/lib/subcommands/device/index.js.map +1 -1
- package/lib/subcommands/get-model-package.js +5 -5
- package/lib/subcommands/index.d.ts +0 -1
- package/lib/subcommands/index.d.ts.map +1 -1
- package/lib/subcommands/index.js +1 -1
- package/lib/subcommands/login.d.ts +0 -1
- package/lib/subcommands/login.d.ts.map +1 -1
- package/lib/subcommands/login.js +6 -14
- package/lib/subcommands/login.js.map +1 -1
- 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/directories.d.ts +16 -15
- package/lib/util/directories.d.ts.map +1 -1
- package/lib/util/directories.js +45 -26
- package/lib/util/directories.js.map +1 -1
- package/lib/util/fetch-with-timeout.d.ts +4 -0
- package/lib/util/fetch-with-timeout.d.ts.map +1 -0
- package/lib/util/fetch-with-timeout.js +15 -0
- package/lib/util/fetch-with-timeout.js.map +1 -0
- package/lib/util/get-device-id.d.ts +1 -1
- package/lib/util/get-device-id.d.ts.map +1 -1
- package/lib/util/get-device-id.js +14 -19
- package/lib/util/get-device-id.js.map +1 -1
- package/lib/util/http-client.d.ts +1 -1
- package/lib/util/http-client.d.ts.map +1 -1
- package/lib/util/http-client.js +10 -8
- package/lib/util/http-client.js.map +1 -1
- package/lib/util/logger.d.ts.map +1 -1
- package/lib/util/logger.js +4 -5
- package/lib/util/logger.js.map +1 -1
- package/lib/util/require-logged-in-and-paid-plan.d.ts +2 -0
- package/lib/util/require-logged-in-and-paid-plan.d.ts.map +1 -0
- package/lib/util/require-logged-in-and-paid-plan.js +18 -0
- package/lib/util/require-logged-in-and-paid-plan.js.map +1 -0
- package/lib/util/run-in-dir.d.ts.map +1 -1
- package/lib/util/run-in-dir.js +1 -0
- package/lib/util/run-in-dir.js.map +1 -1
- package/lib/util/timer.d.ts +2 -0
- package/lib/util/timer.d.ts.map +1 -0
- package/lib/util/timer.js +6 -0
- package/lib/util/timer.js.map +1 -0
- package/package.json +32 -35
- package/readme.md +100 -89
- package/src/application-control/backup.ts +11 -6
- package/src/application-control/config.ts +75 -13
- package/src/application-control/environment-variables.ts +3 -3
- package/src/application-control/index.ts +18 -11
- package/src/application-control/install.ts +82 -78
- package/src/application-control/models.ts +104 -72
- package/src/application-control/status.ts +29 -40
- package/src/application-control/utils.ts +66 -38
- package/src/cloud-connection/app-install-status.ts +62 -0
- package/src/cloud-connection/bootstrap-provision.ts +40 -0
- package/src/cloud-connection/cmd-status.ts +52 -0
- package/src/cloud-connection/device-agent-cloud-connection.ts +302 -526
- package/src/cloud-connection/device-agent.ts +31 -38
- package/src/cloud-connection/live-updates-handler.ts +226 -0
- package/src/cloud-connection/messages.ts +39 -0
- package/src/cloud-connection/passthrough-handler.ts +67 -0
- package/src/cloud-connection/publisher.ts +86 -0
- package/src/cloud-connection/shadow-handler.test.ts +361 -0
- package/src/cloud-connection/shadow-handler.ts +175 -0
- package/src/cloud-connection/shadow.ts +50 -0
- package/src/device-control/device-control.ts +1 -0
- package/src/docker/docker-cmd.ts +1 -1
- package/src/docker/docker-compose-cmd.ts +5 -2
- package/src/endpoints.ts +9 -9
- package/src/environment.ts +11 -3
- package/src/infrastructure/agent-config.test.ts +33 -29
- package/src/infrastructure/agent-config.ts +57 -22
- package/src/infrastructure/system-id.ts +18 -0
- package/src/infrastructure/tokens-and-device-cfg.ts +34 -0
- package/src/infrastructure/urls.ts +4 -2
- package/src/local-connection/rabbitmq-connection.ts +53 -0
- package/src/root.ts +2 -8
- package/src/subcommands/app/app.ts +119 -83
- package/src/subcommands/app/index.ts +3 -3
- package/src/subcommands/device/clean.ts +26 -0
- package/src/subcommands/device/device.ts +67 -54
- package/src/subcommands/device/index.ts +2 -1
- package/src/subcommands/get-model-package.ts +5 -5
- package/src/subcommands/index.ts +1 -1
- package/src/subcommands/login.ts +6 -14
- package/src/util/clean-certs.ts +12 -0
- package/src/util/directories.ts +68 -52
- package/src/util/fetch-with-timeout.ts +18 -0
- package/src/util/get-device-id.ts +16 -18
- package/src/util/http-client.ts +18 -13
- package/src/util/logger.ts +6 -6
- package/src/util/require-logged-in-and-paid-plan.ts +16 -0
- package/src/util/run-in-dir.ts +2 -1
- package/src/util/timer.ts +1 -0
- package/lib/infrastructure/certificates-and-tokens.d.ts +0 -6
- package/lib/infrastructure/certificates-and-tokens.d.ts.map +0 -1
- package/lib/infrastructure/certificates-and-tokens.js +0 -43
- package/lib/infrastructure/certificates-and-tokens.js.map +0 -1
- package/src/infrastructure/certificates-and-tokens.ts +0 -53
|
@@ -1,35 +1,97 @@
|
|
|
1
|
-
import { AppConfig, AppJsonFile } from 'alwaysai/lib/core/app';
|
|
2
1
|
import { AgentConfigFile } from '../infrastructure/agent-config';
|
|
3
2
|
import { parse, stringify } from 'yaml';
|
|
4
|
-
import { getAppDir } from './utils';
|
|
3
|
+
import { buildApp, getAppDir } from './utils';
|
|
5
4
|
import { JsSpawner } from 'alwaysai/lib/util';
|
|
6
5
|
import compose from 'docker-compose';
|
|
7
6
|
import { assign, merge } from 'lodash';
|
|
7
|
+
import { AppJsonFile } from 'alwaysai/lib/core/app';
|
|
8
|
+
import { AppConfig } from '@alwaysai/app-configuration-schemas';
|
|
9
|
+
import { restartApp } from './status';
|
|
10
|
+
import { logger } from '../util/logger';
|
|
8
11
|
|
|
9
|
-
export async function
|
|
12
|
+
export async function readAppCfgFile(props: {
|
|
13
|
+
projectId: string;
|
|
14
|
+
}): Promise<AppConfig> {
|
|
10
15
|
const { projectId } = props;
|
|
11
|
-
if (!(await AgentConfigFile().
|
|
12
|
-
throw new Error(`App ${projectId} is not
|
|
16
|
+
if (!(await AgentConfigFile().isAppPresent({ projectId }))) {
|
|
17
|
+
throw new Error(`App ${projectId} is not present!`);
|
|
13
18
|
}
|
|
14
19
|
const appDir = getAppDir(projectId);
|
|
15
20
|
const appJson = AppJsonFile(appDir);
|
|
16
|
-
|
|
21
|
+
if (!appJson.exists()) {
|
|
22
|
+
throw new Error(`App config for ${projectId} doesn't exist!`);
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
return appJson.read();
|
|
26
|
+
} catch (err) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Error reading app config for ${projectId}:\n${err}\n${appJson.getErrors()}`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
17
31
|
}
|
|
18
32
|
|
|
19
|
-
export async function
|
|
33
|
+
export async function writeAppCfgFile(props: {
|
|
34
|
+
projectId: string;
|
|
35
|
+
appCfg: AppConfig;
|
|
36
|
+
}) {
|
|
20
37
|
const { projectId, appCfg } = props;
|
|
21
|
-
if (!(await AgentConfigFile().
|
|
22
|
-
throw new Error(`App ${projectId} is not
|
|
38
|
+
if (!(await AgentConfigFile().isAppPresent({ projectId }))) {
|
|
39
|
+
throw new Error(`App ${projectId} is not present!`);
|
|
23
40
|
}
|
|
24
41
|
const appDir = getAppDir(projectId);
|
|
25
42
|
const appJson = AppJsonFile(appDir);
|
|
26
|
-
|
|
43
|
+
try {
|
|
44
|
+
appJson.write(appCfg);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Error writing app config for ${projectId}:\n${err}\n${appJson.getErrors()}`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
27
50
|
}
|
|
28
51
|
|
|
29
|
-
export async function
|
|
30
|
-
|
|
52
|
+
export async function updateAppCfgFile(props: {
|
|
53
|
+
projectId: string;
|
|
54
|
+
newAppCfg: any;
|
|
55
|
+
}) {
|
|
56
|
+
const { projectId, newAppCfg } = props;
|
|
57
|
+
const existingAppCfg = await readAppCfgFile({ projectId });
|
|
31
58
|
const appCfg = assign(existingAppCfg, merge(existingAppCfg, newAppCfg));
|
|
32
|
-
await
|
|
59
|
+
await writeAppCfgFile({ projectId, appCfg });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function updateAppCfg(props: {
|
|
63
|
+
projectId: string;
|
|
64
|
+
appReleaseHash: string;
|
|
65
|
+
newAppCfg: AppConfig;
|
|
66
|
+
}) {
|
|
67
|
+
const { projectId, appReleaseHash, newAppCfg } = props;
|
|
68
|
+
logger.info(`Updating app config for ${projectId}:${appReleaseHash}.`);
|
|
69
|
+
const appDir = getAppDir(projectId);
|
|
70
|
+
|
|
71
|
+
if (await AgentConfigFile().isAppPresent({ projectId })) {
|
|
72
|
+
if (!(await AgentConfigFile().isAppReady({ projectId }))) {
|
|
73
|
+
throw new Error('Application already has installation in progress!');
|
|
74
|
+
}
|
|
75
|
+
logger.info('Application is already installed, updating');
|
|
76
|
+
await AgentConfigFile().setAppInstalling({
|
|
77
|
+
projectId,
|
|
78
|
+
version: appReleaseHash
|
|
79
|
+
});
|
|
80
|
+
} else {
|
|
81
|
+
throw new Error('Application is not installed!');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
await writeAppCfgFile({ projectId, appCfg: newAppCfg });
|
|
85
|
+
await buildApp({ appDir });
|
|
86
|
+
|
|
87
|
+
await AgentConfigFile().setAppInstalled({
|
|
88
|
+
projectId,
|
|
89
|
+
version: appReleaseHash
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
await restartApp({ projectId });
|
|
93
|
+
|
|
94
|
+
logger.info(`Updated app config and rebuilt ${projectId}:${appReleaseHash}.`);
|
|
33
95
|
}
|
|
34
96
|
|
|
35
97
|
export async function readDockerCompose(props: { projectId: string }) {
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { JsSpawner } from 'alwaysai/lib/util';
|
|
2
|
-
import compose from 'docker-compose';
|
|
3
|
-
import { parse, stringify } from 'yaml';
|
|
4
2
|
import { AgentConfigFile } from '../infrastructure/agent-config';
|
|
5
3
|
import { readDockerCompose, writeDockerCompose } from './config';
|
|
6
4
|
import { getAppDir } from './utils';
|
|
@@ -56,7 +54,9 @@ export async function getAllEnvs(props: { projectId: string }) {
|
|
|
56
54
|
if ('env_file' in service) {
|
|
57
55
|
const envFiles: string[] = service['env_file'];
|
|
58
56
|
for (const ef of envFiles) {
|
|
59
|
-
envVars[s] = envVars[s].concat(
|
|
57
|
+
envVars[s] = envVars[s].concat(
|
|
58
|
+
(await spawner.readFile(ef)).split('\n')
|
|
59
|
+
);
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
if ('environment' in service) {
|
|
@@ -1,28 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
readAppCfgFile,
|
|
3
|
+
updateAppCfg,
|
|
4
|
+
readDockerCompose,
|
|
5
|
+
writeDockerCompose
|
|
6
|
+
} from './config';
|
|
2
7
|
import { installApp, uninstallApp } from './install';
|
|
3
8
|
import { rollbackApp } from './backup';
|
|
4
9
|
import {
|
|
5
|
-
listAppReleases,
|
|
6
|
-
listAppLatestRelease,
|
|
7
10
|
getAppStatus,
|
|
8
11
|
startApp,
|
|
9
12
|
getAppLogs,
|
|
10
13
|
stopApp,
|
|
11
|
-
restartApp
|
|
14
|
+
restartApp
|
|
12
15
|
} from './status';
|
|
13
16
|
import { ModelDetails } from './types';
|
|
14
17
|
import { getAllEnvs, setEnv } from './environment-variables';
|
|
15
18
|
|
|
16
19
|
export {
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
readAppCfgFile,
|
|
21
|
+
updateAppCfg,
|
|
19
22
|
readDockerCompose,
|
|
20
23
|
writeDockerCompose,
|
|
21
24
|
installApp,
|
|
22
25
|
uninstallApp,
|
|
23
26
|
rollbackApp,
|
|
24
|
-
listAppReleases,
|
|
25
|
-
listAppLatestRelease,
|
|
26
27
|
getAppStatus,
|
|
27
28
|
startApp,
|
|
28
29
|
getAppLogs,
|
|
@@ -30,16 +31,22 @@ export {
|
|
|
30
31
|
restartApp,
|
|
31
32
|
ModelDetails,
|
|
32
33
|
getAllEnvs,
|
|
33
|
-
setEnv
|
|
34
|
+
setEnv
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
// CLI-mode only
|
|
37
38
|
import {
|
|
38
|
-
addModel,
|
|
39
39
|
getAppModels,
|
|
40
40
|
removeModel,
|
|
41
41
|
replaceModels,
|
|
42
42
|
updateModels,
|
|
43
|
+
updateModelsWithPresignedUrls
|
|
43
44
|
} from './models';
|
|
44
45
|
|
|
45
|
-
export {
|
|
46
|
+
export {
|
|
47
|
+
getAppModels,
|
|
48
|
+
removeModel,
|
|
49
|
+
replaceModels,
|
|
50
|
+
updateModels,
|
|
51
|
+
updateModelsWithPresignedUrls
|
|
52
|
+
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { rimraf } from 'rimraf';
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
|
+
import { buildDockerImage } from 'alwaysai/lib/util/docker';
|
|
4
5
|
import { JsSpawner, Spawner } from 'alwaysai/lib/util';
|
|
5
6
|
import { getAppDir, downloadPackageUsingPresignedUrl, buildApp } from './utils';
|
|
6
|
-
import { AppDetailsPacket
|
|
7
|
-
import { BACKUP_EXT
|
|
7
|
+
import { AppDetailsPacket } from '@alwaysai/device-agent-schemas';
|
|
8
|
+
import { BACKUP_EXT } from './backup';
|
|
8
9
|
import { stopApp } from './status';
|
|
9
10
|
import { AgentConfigFile } from '../infrastructure/agent-config';
|
|
10
11
|
import { ProjectJsonFile } from 'alwaysai/lib/core/project';
|
|
@@ -12,14 +13,16 @@ import {
|
|
|
12
13
|
getTargetHardwareType,
|
|
13
14
|
AppJsonFile,
|
|
14
15
|
TargetJsonFile,
|
|
16
|
+
appCleanDocker,
|
|
17
|
+
getPythonVenvPaths,
|
|
18
|
+
installPythonVenv,
|
|
19
|
+
installPythonReqs
|
|
15
20
|
} from 'alwaysai/lib/core/app';
|
|
16
|
-
import { appCleanDockerComponent, buildDocker } from 'alwaysai/lib/components/app';
|
|
17
21
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
import { appReleasePullComponent } from 'alwaysai/lib/components/release';
|
|
22
|
+
DOCKERFILE,
|
|
23
|
+
DOCKER_IMAGE_ID_INITIAL_VALUE,
|
|
24
|
+
PYTHON_REQUIREMENTS_FILE_NAME
|
|
25
|
+
} from 'alwaysai/lib/constants';
|
|
23
26
|
import { runInDir } from '../util/run-in-dir';
|
|
24
27
|
import { installModelsWithPresignedURLs } from './models';
|
|
25
28
|
import { logger } from '../util/logger';
|
|
@@ -48,9 +51,10 @@ export async function getInstalledApps(): Promise<AppDetailsPacket[]> {
|
|
|
48
51
|
export async function installApp(props: {
|
|
49
52
|
projectId: string;
|
|
50
53
|
appReleaseHash: string;
|
|
51
|
-
signedUrlsPayload
|
|
54
|
+
signedUrlsPayload: SignedUrlPayloadType;
|
|
52
55
|
}): Promise<void> {
|
|
53
56
|
const { projectId, appReleaseHash, signedUrlsPayload } = props;
|
|
57
|
+
logger.info(`Installing ${projectId}:${appReleaseHash}`);
|
|
54
58
|
|
|
55
59
|
const appDir = getAppDir(projectId);
|
|
56
60
|
const spawner = JsSpawner();
|
|
@@ -59,32 +63,27 @@ export async function installApp(props: {
|
|
|
59
63
|
throw new Error('Application already has installation in progress!');
|
|
60
64
|
}
|
|
61
65
|
logger.info('Application is already installed, updating');
|
|
62
|
-
await AgentConfigFile().setAppInstalling({
|
|
66
|
+
await AgentConfigFile().setAppInstalling({
|
|
67
|
+
projectId,
|
|
68
|
+
version: appReleaseHash
|
|
69
|
+
});
|
|
63
70
|
await spawner.rimraf(appDir);
|
|
64
71
|
} else {
|
|
65
|
-
await AgentConfigFile().setAppInstalling({
|
|
72
|
+
await AgentConfigFile().setAppInstalling({
|
|
73
|
+
projectId,
|
|
74
|
+
version: appReleaseHash
|
|
75
|
+
});
|
|
66
76
|
}
|
|
67
77
|
|
|
68
78
|
await spawner.mkdirp(appDir);
|
|
69
79
|
|
|
70
80
|
// download app package
|
|
71
81
|
const localDest = path.join(appDir, `${path.basename(appReleaseHash)}.tgz`);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
yes: true,
|
|
78
|
-
project: projectId,
|
|
79
|
-
releaseHash: appReleaseHash,
|
|
80
|
-
},
|
|
81
|
-
],
|
|
82
|
-
appDir,
|
|
83
|
-
);
|
|
84
|
-
} else {
|
|
85
|
-
const { appSignedUrl } = signedUrlsPayload.appInstallPayload;
|
|
86
|
-
await downloadPackageUsingPresignedUrl({ localDest, presignedUrl: appSignedUrl });
|
|
87
|
-
}
|
|
82
|
+
const { appSignedUrl } = signedUrlsPayload.appInstallPayload;
|
|
83
|
+
await downloadPackageUsingPresignedUrl({
|
|
84
|
+
localDest,
|
|
85
|
+
presignedUrl: appSignedUrl
|
|
86
|
+
});
|
|
88
87
|
|
|
89
88
|
// Unpack app package and remove tar file
|
|
90
89
|
await unPackApp({ spawner, localDest, appDir });
|
|
@@ -95,71 +94,73 @@ export async function installApp(props: {
|
|
|
95
94
|
// NOTE: this process no longer checks project collaboration
|
|
96
95
|
await checkValidProjectFiles({ appDir });
|
|
97
96
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
{
|
|
104
|
-
yes: true,
|
|
105
|
-
pull: true,
|
|
106
|
-
clean: true,
|
|
107
|
-
skipModels: false,
|
|
108
|
-
source: false,
|
|
109
|
-
},
|
|
110
|
-
],
|
|
111
|
-
appDir,
|
|
112
|
-
);
|
|
113
|
-
} else {
|
|
114
|
-
await installAppBuildReqs({ appDir });
|
|
115
|
-
await installModelsWithPresignedURLs(
|
|
116
|
-
signedUrlsPayload.modelsInstallPayload,
|
|
117
|
-
path.join(appDir, 'models'),
|
|
118
|
-
);
|
|
119
|
-
}
|
|
97
|
+
await installAppBuildReqs({ appDir });
|
|
98
|
+
await installModelsWithPresignedURLs(
|
|
99
|
+
signedUrlsPayload.modelsInstallPayload,
|
|
100
|
+
path.join(appDir, 'models')
|
|
101
|
+
);
|
|
120
102
|
|
|
121
103
|
await buildApp({ appDir });
|
|
122
104
|
|
|
123
|
-
await AgentConfigFile().setAppInstalled({
|
|
105
|
+
await AgentConfigFile().setAppInstalled({
|
|
106
|
+
projectId,
|
|
107
|
+
version: appReleaseHash
|
|
108
|
+
});
|
|
124
109
|
|
|
125
|
-
logger.info(
|
|
126
|
-
`Installed app version ${appReleaseHash} from project ${projectId} to ${appDir}.`,
|
|
127
|
-
);
|
|
110
|
+
logger.info(`Completed installing ${projectId}:${appReleaseHash}`);
|
|
128
111
|
}
|
|
129
112
|
|
|
130
113
|
async function installAppBuildReqs(props: { appDir: string }) {
|
|
131
114
|
const { appDir } = props;
|
|
132
115
|
const targetJsonFile = TargetJsonFile(appDir);
|
|
133
|
-
const
|
|
134
|
-
if (!
|
|
135
|
-
throw new Error('Target json file does not exist!');
|
|
116
|
+
const targetCfg = targetJsonFile.readIfExists();
|
|
117
|
+
if (!targetCfg || targetCfg.targetProtocol !== 'docker:') {
|
|
118
|
+
throw new Error('Target json file does not exist or is invalid!');
|
|
136
119
|
}
|
|
137
120
|
|
|
138
121
|
await runInDir(
|
|
139
122
|
async () => {
|
|
140
|
-
const
|
|
123
|
+
const hostSpawner = targetJsonFile.readHostSpawner();
|
|
141
124
|
|
|
142
|
-
await
|
|
125
|
+
await appCleanDocker({ targetHostSpawner: hostSpawner });
|
|
143
126
|
|
|
144
|
-
await
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
127
|
+
const dockerImageId = await buildDockerImage({
|
|
128
|
+
targetHostSpawner: hostSpawner,
|
|
129
|
+
targetHardware: targetCfg.targetHardware,
|
|
130
|
+
dockerImageTag: targetCfg.dockerImageId,
|
|
131
|
+
pullBaseImage: true,
|
|
132
|
+
logger
|
|
149
133
|
});
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
134
|
+
targetCfg.dockerImageId = dockerImageId;
|
|
135
|
+
// FIXME: This should use async internally
|
|
136
|
+
targetJsonFile.update((cfg) => {
|
|
137
|
+
if (cfg.targetProtocol === 'docker:') {
|
|
138
|
+
cfg.dockerImageId = dockerImageId;
|
|
139
|
+
}
|
|
155
140
|
});
|
|
141
|
+
|
|
142
|
+
const targetSpawner = targetJsonFile.readContainerSpawner();
|
|
143
|
+
const pythonVenvPaths = await getPythonVenvPaths({ targetCfg });
|
|
144
|
+
await installPythonVenv({ targetSpawner, pythonVenvPaths, logger });
|
|
145
|
+
if (await hostSpawner.exists(PYTHON_REQUIREMENTS_FILE_NAME)) {
|
|
146
|
+
await installPythonReqs({
|
|
147
|
+
reqFilePath: PYTHON_REQUIREMENTS_FILE_NAME,
|
|
148
|
+
targetSpawner,
|
|
149
|
+
pythonVenvPaths,
|
|
150
|
+
logger
|
|
151
|
+
});
|
|
152
|
+
}
|
|
156
153
|
},
|
|
157
154
|
[],
|
|
158
|
-
appDir
|
|
155
|
+
appDir
|
|
159
156
|
);
|
|
160
157
|
}
|
|
161
158
|
|
|
162
|
-
async function unPackApp(props: {
|
|
159
|
+
async function unPackApp(props: {
|
|
160
|
+
spawner: Spawner;
|
|
161
|
+
localDest: string;
|
|
162
|
+
appDir: string;
|
|
163
|
+
}) {
|
|
163
164
|
const { spawner, localDest, appDir } = props;
|
|
164
165
|
await spawner.untar(fs.createReadStream(localDest), appDir);
|
|
165
166
|
await spawner.rimraf(localDest);
|
|
@@ -182,25 +183,28 @@ async function checkValidProjectFiles({ appDir }) {
|
|
|
182
183
|
TargetJsonFile(appDir).write({
|
|
183
184
|
targetProtocol: 'docker:',
|
|
184
185
|
dockerImageId: DOCKER_IMAGE_ID_INITIAL_VALUE,
|
|
185
|
-
targetHardware: await getTargetHardwareType({})
|
|
186
|
+
targetHardware: await getTargetHardwareType({})
|
|
186
187
|
});
|
|
187
188
|
}
|
|
188
189
|
|
|
189
|
-
export async function uninstallApp(props: {
|
|
190
|
+
export async function uninstallApp(props: {
|
|
191
|
+
projectId: string;
|
|
192
|
+
}): Promise<void> {
|
|
190
193
|
const { projectId } = props;
|
|
194
|
+
logger.info(`Uninstalling ${projectId}`);
|
|
191
195
|
if (!(await AgentConfigFile().isAppPresent({ projectId }))) {
|
|
192
196
|
logger.info(`Application ${projectId} not installed`);
|
|
193
197
|
return;
|
|
194
198
|
}
|
|
195
199
|
try {
|
|
196
200
|
await stopApp({ projectId });
|
|
197
|
-
} catch {
|
|
198
|
-
logger.
|
|
201
|
+
} catch (e) {
|
|
202
|
+
logger.warn(`Failed to stop ${projectId}, may be left running...\n${e}`);
|
|
199
203
|
}
|
|
200
204
|
await AgentConfigFile().setAppUninstalled({ projectId });
|
|
201
205
|
// Delete application directory and backup
|
|
202
206
|
const appDir = getAppDir(projectId);
|
|
203
|
-
rimraf
|
|
204
|
-
rimraf
|
|
205
|
-
logger.info(
|
|
207
|
+
await rimraf(appDir);
|
|
208
|
+
await rimraf(`${appDir}${BACKUP_EXT}`);
|
|
209
|
+
logger.info(`Completed uninstalling ${projectId}`);
|
|
206
210
|
}
|