@alwaysai/device-agent 0.0.8 → 0.0.10
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 +2 -0
- package/lib/application-control/backup.js.map +1 -1
- 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.map +1 -1
- package/lib/application-control/environment-variables.js +4 -12
- package/lib/application-control/environment-variables.js.map +1 -1
- package/lib/application-control/index.d.ts +2 -1
- package/lib/application-control/index.d.ts.map +1 -1
- package/lib/application-control/index.js +6 -1
- package/lib/application-control/index.js.map +1 -1
- package/lib/application-control/install.d.ts +12 -10
- package/lib/application-control/install.d.ts.map +1 -1
- package/lib/application-control/install.js +79 -41
- package/lib/application-control/install.js.map +1 -1
- package/lib/application-control/models.d.ts +3 -0
- package/lib/application-control/models.d.ts.map +1 -1
- package/lib/application-control/models.js +92 -19
- package/lib/application-control/models.js.map +1 -1
- package/lib/application-control/utils.d.ts +4 -3
- package/lib/application-control/utils.d.ts.map +1 -1
- package/lib/application-control/utils.js +30 -10
- package/lib/application-control/utils.js.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts +16 -9
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.js +165 -89
- package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
- package/lib/infrastructure/agent-config.d.ts.map +1 -1
- package/lib/infrastructure/agent-config.js +7 -18
- package/lib/infrastructure/agent-config.js.map +1 -1
- package/lib/infrastructure/agent-config.test.js +47 -0
- package/lib/infrastructure/agent-config.test.js.map +1 -1
- package/lib/subcommands/login.d.ts.map +1 -1
- package/lib/subcommands/login.js +4 -3
- package/lib/subcommands/login.js.map +1 -1
- package/lib/util/copy-dir.d.ts.map +1 -1
- package/lib/util/copy-dir.js +3 -1
- package/lib/util/copy-dir.js.map +1 -1
- 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/package.json +4 -3
- package/src/application-control/backup.ts +3 -0
- package/src/application-control/config.ts +61 -0
- package/src/application-control/environment-variables.ts +4 -10
- package/src/application-control/index.ts +5 -0
- package/src/application-control/install.ts +121 -52
- package/src/application-control/models.ts +132 -22
- package/src/application-control/utils.ts +37 -12
- package/src/cloud-connection/device-agent-cloud-connection.ts +197 -105
- package/src/infrastructure/agent-config.test.ts +56 -0
- package/src/infrastructure/agent-config.ts +10 -19
- package/src/subcommands/login.ts +6 -4
- package/src/util/copy-dir.ts +3 -1
- package/src/util/run-in-dir.ts +15 -0
- package/lib/util/run-cli-cmd.d.ts +0 -5
- package/lib/util/run-cli-cmd.d.ts.map +0 -1
- package/lib/util/run-cli-cmd.js +0 -24
- package/lib/util/run-cli-cmd.js.map +0 -1
- package/src/util/run-cli-cmd.ts +0 -18
|
@@ -1,13 +1,38 @@
|
|
|
1
1
|
import * as rimraf from 'rimraf';
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
|
-
import { JsSpawner } from 'alwaysai/lib/util';
|
|
4
|
+
import { JsSpawner, Spawner } from 'alwaysai/lib/util';
|
|
5
5
|
import { getAppDir, downloadPackageUsingPresignedUrl, buildApp } from './utils';
|
|
6
6
|
import { AppDetailsPacket, ModelInstallPayload } from '@alwaysai/device-agent-schemas';
|
|
7
7
|
import { BACKUP_EXT, createAppBackup } from './backup';
|
|
8
8
|
import { stopApp } from './status';
|
|
9
9
|
import { AgentConfigFile } from '../infrastructure/agent-config';
|
|
10
|
-
import {
|
|
10
|
+
import { ProjectJsonFile } from 'alwaysai/lib/core/project';
|
|
11
|
+
import {
|
|
12
|
+
getTargetHardwareType,
|
|
13
|
+
AppJsonFile,
|
|
14
|
+
TargetJsonFile,
|
|
15
|
+
} from 'alwaysai/lib/core/app';
|
|
16
|
+
import { appCleanDockerComponent, buildDocker } from 'alwaysai/lib/components/app';
|
|
17
|
+
import {
|
|
18
|
+
appInstallComponent,
|
|
19
|
+
installVenv,
|
|
20
|
+
} from 'alwaysai/lib/components/app/app-install-component';
|
|
21
|
+
import { DOCKERFILE, DOCKER_IMAGE_ID_INITIAL_VALUE } from 'alwaysai/lib/constants';
|
|
22
|
+
import { appReleasePullComponent } from 'alwaysai/lib/components/release';
|
|
23
|
+
import { runInDir } from '../util/run-in-dir';
|
|
24
|
+
import { installModelsWithPresignedURLs } from './models';
|
|
25
|
+
|
|
26
|
+
type SignedUrlPayloadType = {
|
|
27
|
+
appInstallPayload: {
|
|
28
|
+
appSignedUrl: string;
|
|
29
|
+
};
|
|
30
|
+
modelsInstallPayload: {
|
|
31
|
+
id: string;
|
|
32
|
+
version: number;
|
|
33
|
+
modelSignedUrl: string;
|
|
34
|
+
}[];
|
|
35
|
+
};
|
|
11
36
|
|
|
12
37
|
export async function getInstalledApps(): Promise<AppDetailsPacket[]> {
|
|
13
38
|
const apps = await AgentConfigFile().getApps();
|
|
@@ -22,16 +47,7 @@ export async function getInstalledApps(): Promise<AppDetailsPacket[]> {
|
|
|
22
47
|
export async function installApp(props: {
|
|
23
48
|
projectId: string;
|
|
24
49
|
appReleaseHash: string;
|
|
25
|
-
signedUrlsPayload?:
|
|
26
|
-
appInstallPayload: {
|
|
27
|
-
appSignedUrl: string;
|
|
28
|
-
};
|
|
29
|
-
modelsInstallPayload: {
|
|
30
|
-
id: string;
|
|
31
|
-
version: number;
|
|
32
|
-
modelSignedUrl: string;
|
|
33
|
-
}[];
|
|
34
|
-
};
|
|
50
|
+
signedUrlsPayload?: SignedUrlPayloadType;
|
|
35
51
|
}): Promise<void> {
|
|
36
52
|
const { projectId, appReleaseHash, signedUrlsPayload } = props;
|
|
37
53
|
|
|
@@ -41,9 +57,8 @@ export async function installApp(props: {
|
|
|
41
57
|
if (!(await AgentConfigFile().isAppReady({ projectId }))) {
|
|
42
58
|
throw new Error('Application already has installation in progress!');
|
|
43
59
|
}
|
|
44
|
-
await AgentConfigFile().setAppInstalling({ projectId, version: appReleaseHash });
|
|
45
60
|
console.log('Application is already installed, updating');
|
|
46
|
-
await
|
|
61
|
+
await AgentConfigFile().setAppInstalling({ projectId, version: appReleaseHash });
|
|
47
62
|
await spawner.rimraf(appDir);
|
|
48
63
|
} else {
|
|
49
64
|
await AgentConfigFile().setAppInstalling({ projectId, version: appReleaseHash });
|
|
@@ -54,56 +69,51 @@ export async function installApp(props: {
|
|
|
54
69
|
// download app package
|
|
55
70
|
const localDest = path.join(appDir, `${path.basename(appReleaseHash)}.tgz`);
|
|
56
71
|
if (!signedUrlsPayload) {
|
|
57
|
-
await
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
appReleaseHash,
|
|
72
|
+
await runInDir(
|
|
73
|
+
appReleasePullComponent,
|
|
74
|
+
[
|
|
75
|
+
{
|
|
76
|
+
yes: true,
|
|
77
|
+
project: projectId,
|
|
78
|
+
releaseHash: appReleaseHash,
|
|
79
|
+
},
|
|
66
80
|
],
|
|
67
|
-
|
|
68
|
-
|
|
81
|
+
appDir,
|
|
82
|
+
);
|
|
69
83
|
} else {
|
|
70
84
|
const { appSignedUrl } = signedUrlsPayload.appInstallPayload;
|
|
71
85
|
await downloadPackageUsingPresignedUrl({ localDest, presignedUrl: appSignedUrl });
|
|
72
86
|
}
|
|
73
87
|
|
|
74
88
|
// Unpack app package and remove tar file
|
|
75
|
-
await spawner
|
|
76
|
-
await spawner.rimraf(localDest);
|
|
89
|
+
await unPackApp({ spawner, localDest, appDir });
|
|
77
90
|
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
});
|
|
91
|
+
// The following changes replace the runCliCmd for 'app configure'
|
|
92
|
+
// This part replaces findOrWriteProjectJsonFile() due to the
|
|
93
|
+
// calls that check the user is logged in and also for project collaboration
|
|
94
|
+
// NOTE: this process no longer checks project collaboration
|
|
95
|
+
await checkValidProjectFiles({ appDir });
|
|
83
96
|
|
|
84
97
|
// install models, python venv, and docker image
|
|
85
98
|
if (!signedUrlsPayload) {
|
|
86
|
-
await
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
99
|
+
await runInDir(
|
|
100
|
+
appInstallComponent,
|
|
101
|
+
[
|
|
102
|
+
{
|
|
103
|
+
yes: true,
|
|
104
|
+
pull: true,
|
|
105
|
+
clean: true,
|
|
106
|
+
skipModels: false,
|
|
107
|
+
source: false,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
appDir,
|
|
111
|
+
);
|
|
90
112
|
} else {
|
|
91
|
-
await
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
await Promise.all(
|
|
96
|
-
signedUrlsPayload.modelsInstallPayload.map(async (payload: ModelInstallPayload) => {
|
|
97
|
-
const modelDest = `${appDir}/models/${payload.id}`;
|
|
98
|
-
await spawner.mkdirp(modelDest);
|
|
99
|
-
const localDest = `${modelDest}/${payload.version}.tar.gz`;
|
|
100
|
-
await downloadPackageUsingPresignedUrl({
|
|
101
|
-
localDest,
|
|
102
|
-
presignedUrl: payload.modelSignedUrl,
|
|
103
|
-
});
|
|
104
|
-
await spawner.untar(fs.createReadStream(localDest), path.dirname(modelDest));
|
|
105
|
-
await spawner.rimraf(localDest);
|
|
106
|
-
}),
|
|
113
|
+
await installAppBuildReqs({ appDir });
|
|
114
|
+
await installModelsWithPresignedURLs(
|
|
115
|
+
signedUrlsPayload.modelsInstallPayload,
|
|
116
|
+
path.join(appDir, 'models'),
|
|
107
117
|
);
|
|
108
118
|
}
|
|
109
119
|
|
|
@@ -116,6 +126,65 @@ export async function installApp(props: {
|
|
|
116
126
|
);
|
|
117
127
|
}
|
|
118
128
|
|
|
129
|
+
async function installAppBuildReqs(props: { appDir: string }) {
|
|
130
|
+
const { appDir } = props;
|
|
131
|
+
const targetJsonFile = TargetJsonFile(appDir);
|
|
132
|
+
const targetJson = targetJsonFile.readIfExists();
|
|
133
|
+
if (!targetJson) {
|
|
134
|
+
throw new Error('Target json file does not exist!');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
await runInDir(
|
|
138
|
+
async () => {
|
|
139
|
+
const targetHostSpawner = targetJsonFile.readHostSpawner();
|
|
140
|
+
|
|
141
|
+
await appCleanDockerComponent({ targetHostSpawner });
|
|
142
|
+
|
|
143
|
+
await buildDocker({
|
|
144
|
+
targetJson,
|
|
145
|
+
targetJsonFile,
|
|
146
|
+
targetHostSpawner,
|
|
147
|
+
pull: true,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
await installVenv({
|
|
151
|
+
targetJson,
|
|
152
|
+
sourceSpawner: targetHostSpawner,
|
|
153
|
+
targetJsonFile,
|
|
154
|
+
});
|
|
155
|
+
},
|
|
156
|
+
[],
|
|
157
|
+
appDir,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function unPackApp(props: { spawner: Spawner; localDest: string; appDir: string }) {
|
|
162
|
+
const { spawner, localDest, appDir } = props;
|
|
163
|
+
await spawner.untar(fs.createReadStream(localDest), appDir);
|
|
164
|
+
await spawner.rimraf(localDest);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function checkValidProjectFiles({ appDir }) {
|
|
168
|
+
if (!ProjectJsonFile(appDir).readIfExists()) {
|
|
169
|
+
throw new Error('Project JSON file does not exist!');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// check for app json file and app.py files
|
|
173
|
+
if (!AppJsonFile(appDir).readIfExists()) {
|
|
174
|
+
throw new Error('App JSON file does not exist!');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// write target json
|
|
178
|
+
if (!fs.existsSync(path.join(appDir, DOCKERFILE))) {
|
|
179
|
+
throw new Error('No Dockerfile found for application!');
|
|
180
|
+
}
|
|
181
|
+
TargetJsonFile(appDir).write({
|
|
182
|
+
targetProtocol: 'docker:',
|
|
183
|
+
dockerImageId: DOCKER_IMAGE_ID_INITIAL_VALUE,
|
|
184
|
+
targetHardware: await getTargetHardwareType({}),
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
119
188
|
export async function uninstallApp(props: { projectId: string }): Promise<void> {
|
|
120
189
|
const { projectId } = props;
|
|
121
190
|
if (!(await AgentConfigFile().isAppPresent({ projectId }))) {
|
|
@@ -1,11 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { keyMirrors, ModelInstallPayload } from '@alwaysai/device-agent-schemas';
|
|
2
|
+
import { app } from 'alwaysai/lib/components';
|
|
3
|
+
import {
|
|
4
|
+
appModelsAddComponent,
|
|
5
|
+
appModelsRemoveAllComponent,
|
|
6
|
+
appModelsRemoveComponent,
|
|
7
|
+
appModelsUpdateComponent,
|
|
8
|
+
} from 'alwaysai/lib/components/app';
|
|
9
|
+
import { JsSpawner, logger } from 'alwaysai/lib/util';
|
|
10
|
+
import { existsSync, createReadStream } from 'fs';
|
|
11
|
+
import { join, dirname } from 'path';
|
|
4
12
|
import { AgentConfigFile } from '../infrastructure/agent-config';
|
|
13
|
+
import { copyDir } from '../util/copy-dir';
|
|
14
|
+
import { runInDir } from '../util/run-in-dir';
|
|
15
|
+
import { getAppStatus, restartApp } from './status';
|
|
5
16
|
|
|
6
|
-
import { runCliCmd } from '../util/run-cli-cmd';
|
|
7
17
|
import { ModelDetails } from './types';
|
|
8
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
buildApp,
|
|
20
|
+
downloadPackageUsingPresignedUrl,
|
|
21
|
+
getAppDir,
|
|
22
|
+
requireAppInstalled,
|
|
23
|
+
} from './utils';
|
|
9
24
|
|
|
10
25
|
export async function getAppModels(props: { projectId: string }) {
|
|
11
26
|
const { projectId } = props;
|
|
@@ -34,9 +49,11 @@ export async function addModel(props: { projectId: string; modelId: string }) {
|
|
|
34
49
|
await requireAppInstalled({ projectId });
|
|
35
50
|
|
|
36
51
|
const appDir = getAppDir(projectId);
|
|
37
|
-
await
|
|
38
|
-
|
|
39
|
-
|
|
52
|
+
await appModelsAddComponent({
|
|
53
|
+
yes: false,
|
|
54
|
+
dir: appDir,
|
|
55
|
+
id: modelId,
|
|
56
|
+
addToProject: false,
|
|
40
57
|
});
|
|
41
58
|
await buildApp({ appDir });
|
|
42
59
|
}
|
|
@@ -46,10 +63,18 @@ export async function removeModel(props: { projectId: string; modelId: string })
|
|
|
46
63
|
await requireAppInstalled({ projectId });
|
|
47
64
|
|
|
48
65
|
const appDir = getAppDir(projectId);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
66
|
+
|
|
67
|
+
await runInDir(
|
|
68
|
+
appModelsRemoveComponent,
|
|
69
|
+
[
|
|
70
|
+
{
|
|
71
|
+
id: modelId,
|
|
72
|
+
purge: true,
|
|
73
|
+
removeFromProject: false,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
appDir,
|
|
77
|
+
);
|
|
53
78
|
}
|
|
54
79
|
|
|
55
80
|
export async function replaceModels(props: { projectId: string; modelIds: string[] }) {
|
|
@@ -57,14 +82,23 @@ export async function replaceModels(props: { projectId: string; modelIds: string
|
|
|
57
82
|
await requireAppInstalled({ projectId });
|
|
58
83
|
|
|
59
84
|
const appDir = getAppDir(projectId);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
85
|
+
|
|
86
|
+
await runInDir(
|
|
87
|
+
appModelsRemoveAllComponent,
|
|
88
|
+
[
|
|
89
|
+
{
|
|
90
|
+
purge: true,
|
|
91
|
+
removeFromProject: false,
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
appDir,
|
|
95
|
+
);
|
|
64
96
|
for (const modelId of modelIds) {
|
|
65
|
-
await
|
|
66
|
-
|
|
67
|
-
|
|
97
|
+
await appModelsAddComponent({
|
|
98
|
+
yes: false,
|
|
99
|
+
dir: appDir,
|
|
100
|
+
id: modelId,
|
|
101
|
+
addToProject: false,
|
|
68
102
|
});
|
|
69
103
|
}
|
|
70
104
|
await buildApp({ appDir });
|
|
@@ -75,9 +109,85 @@ export async function updateModels(props: { projectId: string }) {
|
|
|
75
109
|
await requireAppInstalled({ projectId });
|
|
76
110
|
|
|
77
111
|
const appDir = getAppDir(projectId);
|
|
78
|
-
await
|
|
79
|
-
|
|
80
|
-
|
|
112
|
+
await appModelsUpdateComponent({
|
|
113
|
+
yes: false,
|
|
114
|
+
dir: appDir,
|
|
81
115
|
});
|
|
82
116
|
await buildApp({ appDir });
|
|
83
117
|
}
|
|
118
|
+
|
|
119
|
+
export async function installModelsWithPresignedURLs(
|
|
120
|
+
modelPayloads: ModelInstallPayload[],
|
|
121
|
+
targetDir: string,
|
|
122
|
+
) {
|
|
123
|
+
const spawner = JsSpawner();
|
|
124
|
+
await Promise.all(
|
|
125
|
+
modelPayloads.map(async (payload: ModelInstallPayload) => {
|
|
126
|
+
const modelDest = `${targetDir}/${payload.id}`;
|
|
127
|
+
await spawner.mkdirp(modelDest);
|
|
128
|
+
const localDest = `${modelDest}/${payload.version}.tar.gz`;
|
|
129
|
+
await downloadPackageUsingPresignedUrl({
|
|
130
|
+
localDest,
|
|
131
|
+
presignedUrl: payload.modelSignedUrl,
|
|
132
|
+
});
|
|
133
|
+
await spawner.untar(createReadStream(localDest), dirname(modelDest));
|
|
134
|
+
await spawner.rimraf(localDest);
|
|
135
|
+
}),
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export async function updateModelsWithPresignedUrls(
|
|
140
|
+
project: string,
|
|
141
|
+
modelInstallPayloads: ModelInstallPayload[],
|
|
142
|
+
) {
|
|
143
|
+
// create temp dir with all untouched models
|
|
144
|
+
const spawner = JsSpawner();
|
|
145
|
+
const appDir = getAppDir(project);
|
|
146
|
+
const ogDir = `${appDir}/models`;
|
|
147
|
+
const tmpDir = `${ogDir}.tmp`;
|
|
148
|
+
const restoreDir = `${ogDir}.restore`;
|
|
149
|
+
await copyDir({ srcPath: ogDir, destPath: restoreDir });
|
|
150
|
+
await spawner.rimraf(tmpDir);
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
// Move unchanged models
|
|
154
|
+
const existingModels = await getAppModels({ projectId: project });
|
|
155
|
+
for (const model of existingModels) {
|
|
156
|
+
if (
|
|
157
|
+
!modelInstallPayloads
|
|
158
|
+
.map((newModel: ModelInstallPayload) => newModel.id)
|
|
159
|
+
.includes(model.modelId)
|
|
160
|
+
) {
|
|
161
|
+
// model does not need to be updated
|
|
162
|
+
await copyDir({
|
|
163
|
+
srcPath: `${ogDir}/${model.modelId}`,
|
|
164
|
+
destPath: `${tmpDir}/${model.modelId}`,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// install model packages
|
|
170
|
+
await installModelsWithPresignedURLs(modelInstallPayloads, tmpDir);
|
|
171
|
+
await spawner.rimraf(ogDir);
|
|
172
|
+
await copyDir({ srcPath: tmpDir, destPath: ogDir });
|
|
173
|
+
await spawner.rimraf(tmpDir);
|
|
174
|
+
|
|
175
|
+
await buildApp({ appDir: getAppDir(project) });
|
|
176
|
+
|
|
177
|
+
const appStatus = await getAppStatus({ projectId: project });
|
|
178
|
+
const appIsRunning =
|
|
179
|
+
appStatus.services.length &&
|
|
180
|
+
appStatus.services[0].state !== keyMirrors.appState.stopped;
|
|
181
|
+
|
|
182
|
+
if (appIsRunning) {
|
|
183
|
+
restartApp({ projectId: project });
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
console.log(`Models installed for project ${project}`);
|
|
187
|
+
} catch (e) {
|
|
188
|
+
console.error(e, 'Error updating app models from presigned URL, restoring models.');
|
|
189
|
+
await spawner.rimraf(tmpDir);
|
|
190
|
+
await spawner.rimraf(ogDir);
|
|
191
|
+
await copyDir({ srcPath: restoreDir, destPath: ogDir });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import compose from 'docker-compose';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import * as fs from 'fs';
|
|
4
|
-
import { AAI_DIR } from 'alwaysai/lib/constants';
|
|
4
|
+
import { AAI_DIR, TARGET_JSON_FILE_NAME } from 'alwaysai/lib/constants';
|
|
5
5
|
|
|
6
|
-
import { runCliCmd } from '../util/run-cli-cmd';
|
|
7
6
|
import { AgentConfigFile } from '../infrastructure/agent-config';
|
|
8
7
|
import nodeFetch from 'node-fetch';
|
|
8
|
+
import { TargetJsonFile } from 'alwaysai/lib/core/app';
|
|
9
|
+
import { appDeployLinuxAndRemoteDevice } from 'alwaysai/lib/components/app';
|
|
10
|
+
import { runInDir } from '../util/run-in-dir';
|
|
11
|
+
import { JsSpawner } from 'alwaysai/lib/util';
|
|
9
12
|
|
|
10
13
|
export const APP_ROOT = path.join(AAI_DIR, 'applications');
|
|
11
|
-
const DOCKER_COMPOSE_FILENAME = 'docker-compose.yaml';
|
|
12
14
|
|
|
13
15
|
export function getAppDir(projectId: string): string {
|
|
14
16
|
return path.join(APP_ROOT, projectId);
|
|
@@ -27,15 +29,27 @@ export async function requireAppInstalled(props: { projectId: string }) {
|
|
|
27
29
|
|
|
28
30
|
export async function buildApp(props: { appDir: string }) {
|
|
29
31
|
const { appDir } = props;
|
|
30
|
-
console.log(appDir);
|
|
31
32
|
|
|
32
33
|
// Build standalone image and docker-compose
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
});
|
|
34
|
+
const targetJson = TargetJsonFile(appDir);
|
|
35
|
+
const targetConfig = targetJson.read();
|
|
36
|
+
if (targetConfig.targetProtocol !== 'docker:') {
|
|
37
|
+
throw new Error(`${TARGET_JSON_FILE_NAME} is not properly configured!`);
|
|
38
38
|
}
|
|
39
|
+
await runInDir(
|
|
40
|
+
appDeployLinuxAndRemoteDevice,
|
|
41
|
+
[
|
|
42
|
+
{
|
|
43
|
+
yes: true,
|
|
44
|
+
generateDockerCompose: true,
|
|
45
|
+
logs: false,
|
|
46
|
+
stop: false,
|
|
47
|
+
targetJson,
|
|
48
|
+
targetConfig,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
appDir,
|
|
52
|
+
);
|
|
39
53
|
|
|
40
54
|
const buildOut = await compose.buildAll({ cwd: appDir });
|
|
41
55
|
console.log(buildOut);
|
|
@@ -46,10 +60,12 @@ export async function buildApp(props: { appDir: string }) {
|
|
|
46
60
|
}
|
|
47
61
|
}
|
|
48
62
|
|
|
49
|
-
export async function downloadPackageUsingPresignedUrl({
|
|
50
|
-
localDest
|
|
51
|
-
presignedUrl
|
|
63
|
+
export async function downloadPackageUsingPresignedUrl(props: {
|
|
64
|
+
localDest: string;
|
|
65
|
+
presignedUrl: string;
|
|
52
66
|
}): Promise<void> {
|
|
67
|
+
console.log('downloading URL');
|
|
68
|
+
const { localDest, presignedUrl } = props;
|
|
53
69
|
const response = await nodeFetch(presignedUrl);
|
|
54
70
|
if (response.status !== 200) {
|
|
55
71
|
// If the URL is invalid; I think we shouldn't get here with the new changes
|
|
@@ -67,3 +83,12 @@ export async function downloadPackageUsingPresignedUrl({
|
|
|
67
83
|
stream.on('error', reject);
|
|
68
84
|
});
|
|
69
85
|
}
|
|
86
|
+
|
|
87
|
+
export async function getAppConfig(project: string) {
|
|
88
|
+
const appCfgPath = path.join(getAppDir(project), 'alwaysai.app.json');
|
|
89
|
+
if (!fs.existsSync(appCfgPath)) {
|
|
90
|
+
throw new Error(`Application config not found for project ${project}`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return JSON.parse(await JsSpawner().readFile(appCfgPath));
|
|
94
|
+
}
|