@alwaysai/device-agent 0.0.13 → 0.0.15
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.js +3 -3
- package/lib/application-control/backup.js.map +1 -1
- package/lib/application-control/index.d.ts +4 -4
- package/lib/application-control/index.d.ts.map +1 -1
- package/lib/application-control/index.js +1 -4
- 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 +41 -54
- package/lib/application-control/install.js.map +1 -1
- package/lib/application-control/models.d.ts +0 -4
- package/lib/application-control/models.d.ts.map +1 -1
- package/lib/application-control/models.js +13 -22
- 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 +3 -19
- package/lib/application-control/status.js.map +1 -1
- package/lib/application-control/utils.d.ts +3 -0
- package/lib/application-control/utils.d.ts.map +1 -1
- package/lib/application-control/utils.js +50 -21
- package/lib/application-control/utils.js.map +1 -1
- package/lib/cloud-connection/bootstrap-provision.d.ts +1 -1
- package/lib/cloud-connection/bootstrap-provision.d.ts.map +1 -1
- package/lib/cloud-connection/bootstrap-provision.js +9 -9
- package/lib/cloud-connection/bootstrap-provision.js.map +1 -1
- package/lib/cloud-connection/cmd-status.d.ts +8 -0
- package/lib/cloud-connection/cmd-status.d.ts.map +1 -0
- package/lib/cloud-connection/cmd-status.js +62 -0
- package/lib/cloud-connection/cmd-status.js.map +1 -0
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts +10 -2
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.js +156 -66
- 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 +4 -3
- package/lib/cloud-connection/device-agent.js.map +1 -1
- package/lib/cloud-connection/live-updates-handler.d.ts +10 -18
- package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
- package/lib/cloud-connection/live-updates-handler.js +50 -50
- package/lib/cloud-connection/live-updates-handler.js.map +1 -1
- package/lib/cloud-connection/messages.d.ts +3 -1
- package/lib/cloud-connection/messages.d.ts.map +1 -1
- package/lib/cloud-connection/messages.js +13 -1
- package/lib/cloud-connection/messages.js.map +1 -1
- 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 +1 -0
- package/lib/cloud-connection/publisher.d.ts.map +1 -1
- package/lib/cloud-connection/publisher.js +14 -0
- package/lib/cloud-connection/publisher.js.map +1 -1
- package/lib/cloud-connection/shadow-handler.d.ts +2 -3
- package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
- package/lib/cloud-connection/shadow-handler.js +18 -4
- package/lib/cloud-connection/shadow-handler.js.map +1 -1
- 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/environment.d.ts +1 -0
- package/lib/environment.d.ts.map +1 -1
- package/lib/environment.js +3 -2
- package/lib/environment.js.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/infrastructure/agent-config.d.ts +15 -48
- package/lib/infrastructure/agent-config.d.ts.map +1 -1
- package/lib/infrastructure/agent-config.js.map +1 -1
- package/lib/infrastructure/agent-config.test.js +0 -6
- package/lib/infrastructure/agent-config.test.js.map +1 -1
- package/lib/infrastructure/system-id.js +2 -2
- package/lib/infrastructure/system-id.js.map +1 -1
- package/lib/infrastructure/tokens-and-device-cfg.d.ts.map +1 -1
- package/lib/infrastructure/tokens-and-device-cfg.js +5 -9
- package/lib/infrastructure/tokens-and-device-cfg.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/subcommands/app/app.d.ts +4 -3
- package/lib/subcommands/app/app.d.ts.map +1 -1
- package/lib/subcommands/app/app.js +78 -27
- package/lib/subcommands/app/app.js.map +1 -1
- package/lib/subcommands/app/index.js +2 -2
- package/lib/subcommands/device/clean.js +4 -4
- package/lib/subcommands/device/clean.js.map +1 -1
- 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 +9 -10
- package/lib/subcommands/device/device.js.map +1 -1
- package/lib/subcommands/index.d.ts +0 -1
- package/lib/subcommands/index.d.ts.map +1 -1
- package/lib/subcommands/login.d.ts +0 -1
- package/lib/subcommands/login.d.ts.map +1 -1
- package/lib/subcommands/login.js +1 -9
- package/lib/subcommands/login.js.map +1 -1
- package/lib/util/directories.d.ts +11 -12
- package/lib/util/directories.d.ts.map +1 -1
- package/lib/util/directories.js +24 -29
- 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/logger.js +1 -0
- 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/package.json +20 -32
- package/readme.md +100 -89
- package/src/application-control/backup.ts +3 -3
- package/src/application-control/index.ts +0 -6
- package/src/application-control/install.ts +53 -73
- package/src/application-control/models.ts +7 -19
- package/src/application-control/status.ts +3 -19
- package/src/application-control/utils.ts +61 -22
- package/src/cloud-connection/bootstrap-provision.ts +13 -10
- package/src/cloud-connection/cmd-status.ts +71 -0
- package/src/cloud-connection/device-agent-cloud-connection.ts +211 -102
- package/src/cloud-connection/device-agent.ts +7 -4
- package/src/cloud-connection/live-updates-handler.ts +79 -86
- package/src/cloud-connection/messages.ts +22 -1
- package/src/cloud-connection/passthrough-handler.ts +67 -0
- package/src/cloud-connection/publisher.ts +21 -0
- package/src/cloud-connection/shadow-handler.test.ts +361 -0
- package/src/cloud-connection/shadow-handler.ts +28 -7
- package/src/environment.ts +4 -1
- package/src/index.ts +2 -2
- package/src/infrastructure/agent-config.test.ts +0 -7
- package/src/infrastructure/agent-config.ts +24 -2
- package/src/infrastructure/system-id.ts +1 -1
- package/src/infrastructure/tokens-and-device-cfg.ts +8 -13
- package/src/local-connection/rabbitmq-connection.ts +53 -0
- package/src/subcommands/app/app.ts +82 -31
- package/src/subcommands/app/index.ts +4 -4
- package/src/subcommands/device/clean.ts +4 -4
- package/src/subcommands/device/device.ts +13 -13
- package/src/subcommands/login.ts +1 -9
- package/src/util/directories.ts +31 -29
- package/src/util/fetch-with-timeout.ts +18 -0
- package/src/util/logger.ts +2 -0
- package/src/util/require-logged-in-and-paid-plan.ts +16 -0
- package/lib/cloud-connection/app-install-status.d.ts +0 -16
- package/lib/cloud-connection/app-install-status.d.ts.map +0 -1
- package/lib/cloud-connection/app-install-status.js +0 -53
- package/lib/cloud-connection/app-install-status.js.map +0 -1
- package/src/cloud-connection/app-install-status.ts +0 -62
package/readme.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# alwaysAI Device Agent
|
|
2
2
|
|
|
3
|
-
The alwaysAI Device Agent
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
The alwaysAI Device Agent enables provisioning devices and managing devices and
|
|
4
|
+
applications in production deployments of alwaysAI Computer Vision applications.
|
|
5
|
+
Once installed and running, it connects to the alwaysAI Cloud to enable remotely
|
|
6
|
+
controlling the device and applications from the alwaysAI Dashboard.
|
|
6
7
|
|
|
7
8
|
Note that the Device Agent is still in an experimental phase and these commands
|
|
8
9
|
are likely to change. This guide will be updated with the latest usage as things
|
|
@@ -10,80 +11,125 @@ change.
|
|
|
10
11
|
|
|
11
12
|
## System Requirements
|
|
12
13
|
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
|
|
18
|
-
*
|
|
19
|
-
*
|
|
14
|
+
* Supported OS:
|
|
15
|
+
* Debian Bullseye, Buster
|
|
16
|
+
* Ubuntu 20.04, 18.04
|
|
17
|
+
* NVIDIA Jetpack 4.6.x
|
|
18
|
+
* Supported target architecture
|
|
19
|
+
* amd64
|
|
20
|
+
* aarch64
|
|
21
|
+
* armv7hf
|
|
22
|
+
* `docker` version >= 19.03
|
|
23
|
+
* `curl` installed (required to download provisioning scripts)
|
|
20
24
|
|
|
21
25
|
## Provision Device
|
|
22
26
|
|
|
23
|
-
###
|
|
24
|
-
|
|
25
|
-
If you're system already meets all the system requirements, you can simply install the device agent via `npm`:
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
sudo npm install -g @alwaysai/device-agent@latest
|
|
29
|
-
```
|
|
27
|
+
### Install the alwaysAI Device Agent and dependencies
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
On the target device, run:
|
|
32
30
|
|
|
33
31
|
```
|
|
34
|
-
curl -fsSL https://
|
|
32
|
+
$ curl -fsSL https://artifacts.alwaysai.co/device-agent/install-device-agent.sh | sudo -E bash -
|
|
35
33
|
```
|
|
36
34
|
|
|
37
35
|
The Device Agent will be available in the terminal as `aai-agent`.
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
aai-agent login --email <username> --password <password> [--device <device_id>]
|
|
43
|
-
```
|
|
37
|
+
### Provision the device
|
|
44
38
|
|
|
45
|
-
|
|
46
|
-
can optionally provide that device ID in the login command. If you don't yet
|
|
47
|
-
have a device configured, follow the next step to initialize the device.
|
|
39
|
+
Provisioning the device performs the following:
|
|
48
40
|
|
|
49
|
-
|
|
41
|
+
1. Create the device in the alwaysAI Cloud
|
|
42
|
+
2. Obtain device credentials to connect to alwaysAI Cloud
|
|
43
|
+
3. Run the alwaysAI Device Agent in the background
|
|
50
44
|
|
|
51
|
-
|
|
52
|
-
an alwaysAI device:
|
|
45
|
+
Run the following command on the target device to provision it:
|
|
53
46
|
|
|
54
47
|
```
|
|
55
|
-
$
|
|
48
|
+
$ curl -fsSL https://artifacts.alwaysai.co/device-agent/provision.sh | bash -s -- --email <email> --password <password> [--device-name <device_name>]
|
|
56
49
|
```
|
|
57
50
|
|
|
58
|
-
|
|
51
|
+
Where:
|
|
52
|
+
* `email` is the email associated with your alwaysAI account.
|
|
53
|
+
* `password` is the password for your alwaysAI account.
|
|
54
|
+
* `device_name` is an optional device name, which will be displayed on the
|
|
55
|
+
devices page of the alwaysAI Dashboard. If a device name is not provided, one
|
|
56
|
+
will be generated for you and logged to the console for reference.
|
|
57
|
+
|
|
58
|
+
If you'd like to only provision the device, but not start the Device Agent in
|
|
59
|
+
the background (skip step 3), run with the `--provision-only` flag:
|
|
59
60
|
|
|
60
61
|
```
|
|
61
|
-
$
|
|
62
|
+
$ curl -fsSL https://artifacts.alwaysai.co/device-agent/provision-agent.sh | bash -s -- --email <email> --password <password> [--device-name <device_name>] --provision-only
|
|
62
63
|
```
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
When the script completes, the device will be provisioned but the Device Agent will not be running in the background.
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
## Run an alwaysAI application on your device
|
|
67
68
|
|
|
68
69
|
First, you must publish your application to the alwaysAI cloud. From the root
|
|
69
70
|
of your application directory (where the `alwaysai.app.json` file is) on your
|
|
70
71
|
development host:
|
|
71
72
|
|
|
72
73
|
```
|
|
73
|
-
aai app configure
|
|
74
|
-
aai app publish
|
|
74
|
+
$ aai app configure
|
|
75
|
+
$ aai app publish
|
|
75
76
|
```
|
|
76
77
|
|
|
77
78
|
The output of the final command will give you the release hash that was
|
|
78
79
|
published. You can run `aai release list --project <project_id>` to list all
|
|
79
80
|
release versions for the project, where project ID can be found in the
|
|
80
|
-
`alwaysai.project.json` file.
|
|
81
|
+
`alwaysai.project.json` file. The application release will now show up on the
|
|
82
|
+
project page of the alwaysAI Dashboard as well!
|
|
83
|
+
|
|
84
|
+
Now you can deploy to your device from the alwaysAI Dashboard.
|
|
85
|
+
|
|
86
|
+
## The alwaysAI Device Agent Command Line interface
|
|
87
|
+
|
|
88
|
+
The Device Agent can also be used directly on the device with it's command line interface.
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
$ aai-agent --help
|
|
92
|
+
Usage: aai-agent <subcommand> ...
|
|
93
|
+
|
|
94
|
+
Manage your alwaysAI production device
|
|
95
|
+
|
|
96
|
+
Subcommands:
|
|
97
|
+
|
|
98
|
+
login : Login to alwaysAI (this is meant for scripted environments)
|
|
99
|
+
app list : List all installed apps
|
|
100
|
+
app install : Install an alwaysAI app from a project
|
|
101
|
+
app status : Get the status of an installed alwaysAI app
|
|
102
|
+
app start : Start an installed alwaysAI app
|
|
103
|
+
app stop : Stop a running alwaysAI app
|
|
104
|
+
app restart : Restart running alwaysAI app
|
|
105
|
+
app logs : Get logs for an application
|
|
106
|
+
app uninstall : Remove an alwaysAI app
|
|
107
|
+
app show-models : Show the application models
|
|
108
|
+
app add-model : Add a model to an alwaysAI app
|
|
109
|
+
app remove-model : Remove a model from an alwaysAI app
|
|
110
|
+
app replace-models : Replace all models of an alwaysAI app with new models
|
|
111
|
+
app update-models : Update all models for an alwaysAI app
|
|
112
|
+
app get-all-envs : Get environment variables for an application
|
|
113
|
+
app set-env : Set environment variables for a service
|
|
114
|
+
device init : Initialize device
|
|
115
|
+
device get-info : Get device info
|
|
116
|
+
device clean : Remove all provisioning files
|
|
117
|
+
get-model-package : Download and unpack a model package
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
To see the output logs, run the following command:
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
export ALWAYSAI_LOG_TO_CONSOLE=1
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Install the application on the device
|
|
81
127
|
|
|
82
128
|
Now you can install the application on the device using the device agent. Run
|
|
83
129
|
the following on the device where the Device Agent is installed:
|
|
84
130
|
|
|
85
131
|
```
|
|
86
|
-
aai-agent app install --project <project_id>
|
|
132
|
+
$ aai-agent app install --project <project_id> --release <release_hash>
|
|
87
133
|
```
|
|
88
134
|
|
|
89
135
|
### Control the application
|
|
@@ -92,27 +138,27 @@ Run the following commands on the device where the Device Agent is installed:
|
|
|
92
138
|
|
|
93
139
|
Get application status:
|
|
94
140
|
```
|
|
95
|
-
aai-agent app status --project <project_id>
|
|
141
|
+
$ aai-agent app status --project <project_id>
|
|
96
142
|
```
|
|
97
143
|
|
|
98
144
|
Start the application:
|
|
99
145
|
```
|
|
100
|
-
aai-agent app start --project <project_id>
|
|
146
|
+
$ aai-agent app start --project <project_id>
|
|
101
147
|
```
|
|
102
148
|
|
|
103
149
|
Show the application logs:
|
|
104
150
|
```
|
|
105
|
-
aai-agent app logs --project <project_id>
|
|
151
|
+
$ aai-agent app logs --project <project_id>
|
|
106
152
|
```
|
|
107
153
|
|
|
108
154
|
Stop the application:
|
|
109
155
|
```
|
|
110
|
-
aai-agent app stop --project <project_id>
|
|
156
|
+
$ aai-agent app stop --project <project_id>
|
|
111
157
|
```
|
|
112
158
|
|
|
113
159
|
Uninstall the application:
|
|
114
160
|
```
|
|
115
|
-
aai-agent app uninstall --project <project_id>
|
|
161
|
+
$ aai-agent app uninstall --project <project_id>
|
|
116
162
|
```
|
|
117
163
|
|
|
118
164
|
### Manage application models
|
|
@@ -126,9 +172,9 @@ application is already configured to be using that model ID, updating to the
|
|
|
126
172
|
new model can simply be done with:
|
|
127
173
|
|
|
128
174
|
```
|
|
129
|
-
aai-agent app stop --project <project_id>
|
|
130
|
-
aai-agent app update-models --project <project_id>
|
|
131
|
-
aai-agent app start --project <project_id>
|
|
175
|
+
$ aai-agent app stop --project <project_id>
|
|
176
|
+
$ aai-agent app update-models --project <project_id>
|
|
177
|
+
$ aai-agent app start --project <project_id>
|
|
132
178
|
```
|
|
133
179
|
|
|
134
180
|
#### Replace models for an application for new ID
|
|
@@ -137,9 +183,9 @@ If you'd like to install an entirely new model to an application, replacing the
|
|
|
137
183
|
model the app was originally configured with, run the following command:
|
|
138
184
|
|
|
139
185
|
```
|
|
140
|
-
aai-agent app stop --project <project_id>
|
|
141
|
-
aai-agent app replace-models --project <project_id> --models <model_id_1> [<model_id_2> ...]
|
|
142
|
-
aai-agent app start --project <project_id>
|
|
186
|
+
$ aai-agent app stop --project <project_id>
|
|
187
|
+
$ aai-agent app replace-models --project <project_id> --models <model_id_1> [<model_id_2> ...]
|
|
188
|
+
$ aai-agent app start --project <project_id>
|
|
143
189
|
```
|
|
144
190
|
|
|
145
191
|
If you plan on using this method, you can make your application source model ID
|
|
@@ -155,13 +201,13 @@ obj_detect = edgeiq.ObjectDetection(edgeiq._globals.MODEL_ID_LIST[0])
|
|
|
155
201
|
To download a model package from the alwaysAI cloud and unpack to a specific directory, run:
|
|
156
202
|
|
|
157
203
|
```
|
|
158
|
-
aai-agent get-model-package <model ID> [--path <destination path>]
|
|
204
|
+
$ aai-agent get-model-package <model ID> [--path <destination path>]
|
|
159
205
|
```
|
|
160
206
|
|
|
161
207
|
For example, to download `alwaysai/yolo_v3` to `~/alwaysai` run:
|
|
162
208
|
|
|
163
209
|
```
|
|
164
|
-
aai-agent get-model-package alwaysai/yolo_v3 --path ~/alwaysai
|
|
210
|
+
$ aai-agent get-model-package alwaysai/yolo_v3 --path ~/alwaysai
|
|
165
211
|
```
|
|
166
212
|
|
|
167
213
|
Once the command completes, you'll see the model package in the
|
|
@@ -173,47 +219,12 @@ The Device Agent enables you to set and update environment variables for all
|
|
|
173
219
|
services or a single service of you application.
|
|
174
220
|
|
|
175
221
|
```
|
|
176
|
-
aai-agent app set-env <key=val> --project <project_id> [--service <service>]
|
|
222
|
+
$ aai-agent app set-env <key=val> --project <project_id> [--service <service>]
|
|
177
223
|
```
|
|
178
224
|
|
|
179
225
|
For example, to set the following environment variable for the `alwaysai`
|
|
180
226
|
service run the following command on the device:
|
|
181
227
|
|
|
182
228
|
```
|
|
183
|
-
aai-agent app set-env TEST_ENV=1 --project <project_id> --service alwaysai
|
|
229
|
+
$ aai-agent app set-env TEST_ENV=1 --project <project_id> --service alwaysai
|
|
184
230
|
```
|
|
185
|
-
|
|
186
|
-
## Device Agent Commands
|
|
187
|
-
|
|
188
|
-
```
|
|
189
|
-
$ aai-agent --help
|
|
190
|
-
Starting alwaysAI Device Agent
|
|
191
|
-
Usage: aai-agent <subcommand> ...
|
|
192
|
-
|
|
193
|
-
Manage your alwaysAI production device
|
|
194
|
-
|
|
195
|
-
Subcommands:
|
|
196
|
-
|
|
197
|
-
login : Login to alwaysAI (this is meant for scripted environments)
|
|
198
|
-
app list : List all installed apps
|
|
199
|
-
app list-releases : List all releases for a given app
|
|
200
|
-
app list-latest-release : List the latest release hash for a given app
|
|
201
|
-
app install : Install an alwaysAI app from a project
|
|
202
|
-
app status : Get the status of an installed alwaysAI app
|
|
203
|
-
app start : Start an installed alwaysAI app
|
|
204
|
-
app stop : Stop a running alwaysAI app
|
|
205
|
-
app restart : Restart running alwaysAI app
|
|
206
|
-
app logs : Get logs for an application
|
|
207
|
-
app uninstall : Remove an alwaysAI app
|
|
208
|
-
app rollback : Rollback an alwaysAI app to the previous version
|
|
209
|
-
app show-models : Show the application models
|
|
210
|
-
app add-model : Add a model to an alwaysAI app
|
|
211
|
-
app remove-model : Remove a model from an alwaysAI app
|
|
212
|
-
app replace-models : Replace all models of an alwaysAI app with new models
|
|
213
|
-
app update-models : Update all models for an alwaysAI app
|
|
214
|
-
app get-all-envs : Get environment variables for an application
|
|
215
|
-
app set-env : Set environment variables for a service
|
|
216
|
-
device init : Initialize device
|
|
217
|
-
device get-info : Get device info
|
|
218
|
-
get-model-package : Download and unpack a model package
|
|
219
|
-
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { rimraf } from 'rimraf';
|
|
2
2
|
|
|
3
3
|
import { copyDir } from '../util/copy-dir';
|
|
4
4
|
import { buildApp, getAppDir } from './utils';
|
|
@@ -11,7 +11,7 @@ export async function createAppBackup(props: { projectId: string }) {
|
|
|
11
11
|
const { projectId } = props;
|
|
12
12
|
const appDir = getAppDir(projectId);
|
|
13
13
|
const backupAppDir = `${appDir}${BACKUP_EXT}`;
|
|
14
|
-
rimraf
|
|
14
|
+
await rimraf(backupAppDir);
|
|
15
15
|
await copyDir({ srcPath: appDir, destPath: backupAppDir });
|
|
16
16
|
await AgentConfigFile().setAppBackup({ projectId });
|
|
17
17
|
logger.info(`Backed up app ${projectId} to ${backupAppDir}`);
|
|
@@ -30,7 +30,7 @@ export async function rollbackApp(props: { projectId: string }) {
|
|
|
30
30
|
});
|
|
31
31
|
const appDir = getAppDir(projectId);
|
|
32
32
|
const backupAppDir = `${appDir}${BACKUP_EXT}`;
|
|
33
|
-
rimraf
|
|
33
|
+
await rimraf(appDir);
|
|
34
34
|
await copyDir({ srcPath: backupAppDir, destPath: appDir });
|
|
35
35
|
await buildApp({ appDir });
|
|
36
36
|
await AgentConfigFile().setAppInstalled({
|
|
@@ -7,8 +7,6 @@ import {
|
|
|
7
7
|
import { installApp, uninstallApp } from './install';
|
|
8
8
|
import { rollbackApp } from './backup';
|
|
9
9
|
import {
|
|
10
|
-
listAppReleases,
|
|
11
|
-
listAppLatestRelease,
|
|
12
10
|
getAppStatus,
|
|
13
11
|
startApp,
|
|
14
12
|
getAppLogs,
|
|
@@ -26,8 +24,6 @@ export {
|
|
|
26
24
|
installApp,
|
|
27
25
|
uninstallApp,
|
|
28
26
|
rollbackApp,
|
|
29
|
-
listAppReleases,
|
|
30
|
-
listAppLatestRelease,
|
|
31
27
|
getAppStatus,
|
|
32
28
|
startApp,
|
|
33
29
|
getAppLogs,
|
|
@@ -40,7 +36,6 @@ export {
|
|
|
40
36
|
|
|
41
37
|
// CLI-mode only
|
|
42
38
|
import {
|
|
43
|
-
addModel,
|
|
44
39
|
getAppModels,
|
|
45
40
|
removeModel,
|
|
46
41
|
replaceModels,
|
|
@@ -49,7 +44,6 @@ import {
|
|
|
49
44
|
} from './models';
|
|
50
45
|
|
|
51
46
|
export {
|
|
52
|
-
addModel,
|
|
53
47
|
getAppModels,
|
|
54
48
|
removeModel,
|
|
55
49
|
replaceModels,
|
|
@@ -1,6 +1,7 @@
|
|
|
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
7
|
import { AppDetailsPacket } from '@alwaysai/device-agent-schemas';
|
|
@@ -11,21 +12,17 @@ import { ProjectJsonFile } from 'alwaysai/lib/core/project';
|
|
|
11
12
|
import {
|
|
12
13
|
getTargetHardwareType,
|
|
13
14
|
AppJsonFile,
|
|
14
|
-
TargetJsonFile
|
|
15
|
+
TargetJsonFile,
|
|
16
|
+
appCleanDocker,
|
|
17
|
+
getPythonVenvPaths,
|
|
18
|
+
installPythonVenv,
|
|
19
|
+
installPythonReqs
|
|
15
20
|
} from 'alwaysai/lib/core/app';
|
|
16
|
-
import {
|
|
17
|
-
appCleanDockerComponent,
|
|
18
|
-
buildDocker
|
|
19
|
-
} from 'alwaysai/lib/components/app';
|
|
20
|
-
import {
|
|
21
|
-
appInstallComponent,
|
|
22
|
-
installVenv
|
|
23
|
-
} from 'alwaysai/lib/components/app/app-install-component';
|
|
24
21
|
import {
|
|
25
22
|
DOCKERFILE,
|
|
26
|
-
DOCKER_IMAGE_ID_INITIAL_VALUE
|
|
23
|
+
DOCKER_IMAGE_ID_INITIAL_VALUE,
|
|
24
|
+
PYTHON_REQUIREMENTS_FILE_NAME
|
|
27
25
|
} from 'alwaysai/lib/constants';
|
|
28
|
-
import { appReleasePullComponent } from 'alwaysai/lib/components/release';
|
|
29
26
|
import { runInDir } from '../util/run-in-dir';
|
|
30
27
|
import { installModelsWithPresignedURLs } from './models';
|
|
31
28
|
import { logger } from '../util/logger';
|
|
@@ -54,7 +51,7 @@ export async function getInstalledApps(): Promise<AppDetailsPacket[]> {
|
|
|
54
51
|
export async function installApp(props: {
|
|
55
52
|
projectId: string;
|
|
56
53
|
appReleaseHash: string;
|
|
57
|
-
signedUrlsPayload
|
|
54
|
+
signedUrlsPayload: SignedUrlPayloadType;
|
|
58
55
|
}): Promise<void> {
|
|
59
56
|
const { projectId, appReleaseHash, signedUrlsPayload } = props;
|
|
60
57
|
logger.info(`Installing ${projectId}:${appReleaseHash}`);
|
|
@@ -82,25 +79,11 @@ export async function installApp(props: {
|
|
|
82
79
|
|
|
83
80
|
// download app package
|
|
84
81
|
const localDest = path.join(appDir, `${path.basename(appReleaseHash)}.tgz`);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
yes: true,
|
|
91
|
-
project: projectId,
|
|
92
|
-
releaseHash: appReleaseHash
|
|
93
|
-
}
|
|
94
|
-
],
|
|
95
|
-
appDir
|
|
96
|
-
);
|
|
97
|
-
} else {
|
|
98
|
-
const { appSignedUrl } = signedUrlsPayload.appInstallPayload;
|
|
99
|
-
await downloadPackageUsingPresignedUrl({
|
|
100
|
-
localDest,
|
|
101
|
-
presignedUrl: appSignedUrl
|
|
102
|
-
});
|
|
103
|
-
}
|
|
82
|
+
const { appSignedUrl } = signedUrlsPayload.appInstallPayload;
|
|
83
|
+
await downloadPackageUsingPresignedUrl({
|
|
84
|
+
localDest,
|
|
85
|
+
presignedUrl: appSignedUrl
|
|
86
|
+
});
|
|
104
87
|
|
|
105
88
|
// Unpack app package and remove tar file
|
|
106
89
|
await unPackApp({ spawner, localDest, appDir });
|
|
@@ -111,28 +94,11 @@ export async function installApp(props: {
|
|
|
111
94
|
// NOTE: this process no longer checks project collaboration
|
|
112
95
|
await checkValidProjectFiles({ appDir });
|
|
113
96
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
{
|
|
120
|
-
yes: true,
|
|
121
|
-
pull: true,
|
|
122
|
-
clean: true,
|
|
123
|
-
skipModels: false,
|
|
124
|
-
source: false
|
|
125
|
-
}
|
|
126
|
-
],
|
|
127
|
-
appDir
|
|
128
|
-
);
|
|
129
|
-
} else {
|
|
130
|
-
await installAppBuildReqs({ appDir });
|
|
131
|
-
await installModelsWithPresignedURLs(
|
|
132
|
-
signedUrlsPayload.modelsInstallPayload,
|
|
133
|
-
path.join(appDir, 'models')
|
|
134
|
-
);
|
|
135
|
-
}
|
|
97
|
+
await installAppBuildReqs({ appDir });
|
|
98
|
+
await installModelsWithPresignedURLs(
|
|
99
|
+
signedUrlsPayload.modelsInstallPayload,
|
|
100
|
+
path.join(appDir, 'models')
|
|
101
|
+
);
|
|
136
102
|
|
|
137
103
|
await buildApp({ appDir });
|
|
138
104
|
|
|
@@ -147,29 +113,43 @@ export async function installApp(props: {
|
|
|
147
113
|
async function installAppBuildReqs(props: { appDir: string }) {
|
|
148
114
|
const { appDir } = props;
|
|
149
115
|
const targetJsonFile = TargetJsonFile(appDir);
|
|
150
|
-
const
|
|
151
|
-
if (!
|
|
152
|
-
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!');
|
|
153
119
|
}
|
|
154
120
|
|
|
155
121
|
await runInDir(
|
|
156
122
|
async () => {
|
|
157
|
-
const
|
|
123
|
+
const hostSpawner = targetJsonFile.readHostSpawner();
|
|
158
124
|
|
|
159
|
-
await
|
|
125
|
+
await appCleanDocker({ targetHostSpawner: hostSpawner });
|
|
160
126
|
|
|
161
|
-
await
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
127
|
+
const dockerImageId = await buildDockerImage({
|
|
128
|
+
targetHostSpawner: hostSpawner,
|
|
129
|
+
targetHardware: targetCfg.targetHardware,
|
|
130
|
+
dockerImageTag: targetCfg.dockerImageId,
|
|
131
|
+
pullBaseImage: true,
|
|
132
|
+
logger
|
|
166
133
|
});
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
+
}
|
|
172
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
|
+
}
|
|
173
153
|
},
|
|
174
154
|
[],
|
|
175
155
|
appDir
|
|
@@ -218,13 +198,13 @@ export async function uninstallApp(props: {
|
|
|
218
198
|
}
|
|
219
199
|
try {
|
|
220
200
|
await stopApp({ projectId });
|
|
221
|
-
} catch {
|
|
222
|
-
logger.warn(`Failed to stop ${projectId}, may be left running
|
|
201
|
+
} catch (e) {
|
|
202
|
+
logger.warn(`Failed to stop ${projectId}, may be left running...\n${e}`);
|
|
223
203
|
}
|
|
224
204
|
await AgentConfigFile().setAppUninstalled({ projectId });
|
|
225
205
|
// Delete application directory and backup
|
|
226
206
|
const appDir = getAppDir(projectId);
|
|
227
|
-
rimraf
|
|
228
|
-
rimraf
|
|
207
|
+
await rimraf(appDir);
|
|
208
|
+
await rimraf(`${appDir}${BACKUP_EXT}`);
|
|
229
209
|
logger.info(`Completed uninstalling ${projectId}`);
|
|
230
210
|
}
|
|
@@ -20,11 +20,11 @@ import {
|
|
|
20
20
|
buildApp,
|
|
21
21
|
downloadPackageUsingPresignedUrl,
|
|
22
22
|
getAppDir,
|
|
23
|
-
|
|
23
|
+
requireAppReady
|
|
24
24
|
} from './utils';
|
|
25
25
|
import { MODEL_JSON_FILE_NAME } from 'alwaysai/lib/core/model';
|
|
26
26
|
import { APP_MODELS_DIRECTORY_NAME } from 'alwaysai/lib/constants';
|
|
27
|
-
import { readAppCfgFile,
|
|
27
|
+
import { readAppCfgFile, writeAppCfgFile } from './config';
|
|
28
28
|
import { AppConfig } from '@alwaysai/app-configuration-schemas';
|
|
29
29
|
|
|
30
30
|
export async function getAppModels(props: { projectId: string }) {
|
|
@@ -49,26 +49,12 @@ export async function getAppModels(props: { projectId: string }) {
|
|
|
49
49
|
return modelDetails;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
export async function addModel(props: { projectId: string; modelId: string }) {
|
|
53
|
-
const { projectId, modelId } = props;
|
|
54
|
-
await requireAppInstalled({ projectId });
|
|
55
|
-
|
|
56
|
-
const appDir = getAppDir(projectId);
|
|
57
|
-
await appModelsAddComponent({
|
|
58
|
-
yes: false,
|
|
59
|
-
dir: appDir,
|
|
60
|
-
id: modelId,
|
|
61
|
-
addToProject: false
|
|
62
|
-
});
|
|
63
|
-
await buildApp({ appDir });
|
|
64
|
-
}
|
|
65
|
-
|
|
66
52
|
export async function removeModel(props: {
|
|
67
53
|
projectId: string;
|
|
68
54
|
modelId: string;
|
|
69
55
|
}) {
|
|
70
56
|
const { projectId, modelId } = props;
|
|
71
|
-
await
|
|
57
|
+
await requireAppReady({ projectId });
|
|
72
58
|
|
|
73
59
|
const appDir = getAppDir(projectId);
|
|
74
60
|
|
|
@@ -90,7 +76,7 @@ export async function replaceModels(props: {
|
|
|
90
76
|
modelIds: string[];
|
|
91
77
|
}) {
|
|
92
78
|
const { projectId, modelIds } = props;
|
|
93
|
-
await
|
|
79
|
+
await requireAppReady({ projectId });
|
|
94
80
|
|
|
95
81
|
const appDir = getAppDir(projectId);
|
|
96
82
|
|
|
@@ -117,7 +103,7 @@ export async function replaceModels(props: {
|
|
|
117
103
|
|
|
118
104
|
export async function updateModels(props: { projectId: string }) {
|
|
119
105
|
const { projectId } = props;
|
|
120
|
-
await
|
|
106
|
+
await requireAppReady({ projectId });
|
|
121
107
|
|
|
122
108
|
const appDir = getAppDir(projectId);
|
|
123
109
|
await appModelsUpdateComponent({
|
|
@@ -223,6 +209,7 @@ export async function updateModelsWithPresignedUrls(props: {
|
|
|
223
209
|
await restartApp({ projectId });
|
|
224
210
|
|
|
225
211
|
logger.info(`Models installed for project ${projectId}`);
|
|
212
|
+
/* Leave error handling to higher level so errors are sent to cloud
|
|
226
213
|
} catch (e) {
|
|
227
214
|
logger.error(
|
|
228
215
|
'Error updating app models from presigned URL, restoring models.',
|
|
@@ -231,6 +218,7 @@ export async function updateModelsWithPresignedUrls(props: {
|
|
|
231
218
|
await spawner.rimraf(ogDir);
|
|
232
219
|
await copyDir({ srcPath: restoreDir, destPath: ogDir });
|
|
233
220
|
await writeAppCfgFile({ projectId, appCfg: ogAppCfg });
|
|
221
|
+
*/
|
|
234
222
|
} finally {
|
|
235
223
|
await spawner.rimraf(tmpDir);
|
|
236
224
|
await spawner.rimraf(restoreDir);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import compose from 'docker-compose';
|
|
2
|
-
import { fetchAppReleaseHistory } from 'alwaysai/lib/infrastructure';
|
|
3
2
|
import { JsSpawner } from 'alwaysai/lib/util';
|
|
4
3
|
|
|
5
4
|
import { runDockerLogin } from '../docker/docker-cmd';
|
|
6
|
-
import { getAppDir, requireAppInstalled } from './utils';
|
|
5
|
+
import { getAppDir, requireAppInstalled, requireAppReady } from './utils';
|
|
7
6
|
import {
|
|
8
7
|
ServiceStatusPacket,
|
|
9
8
|
AppStatePacket,
|
|
@@ -13,21 +12,6 @@ import {
|
|
|
13
12
|
import { AgentConfigFile } from '../infrastructure/agent-config';
|
|
14
13
|
import { logger } from '../util/logger';
|
|
15
14
|
|
|
16
|
-
export async function listAppReleases(props: { projectId: string }) {
|
|
17
|
-
const { projectId } = props;
|
|
18
|
-
const releaseHistory = await fetchAppReleaseHistory(projectId);
|
|
19
|
-
return releaseHistory;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export async function listAppLatestRelease(props: { projectId: string }) {
|
|
23
|
-
const { projectId } = props;
|
|
24
|
-
const releaseHistory = await fetchAppReleaseHistory(projectId);
|
|
25
|
-
if (releaseHistory.length >= 1) {
|
|
26
|
-
return releaseHistory[0]['releaseHash'];
|
|
27
|
-
}
|
|
28
|
-
return undefined;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
15
|
export async function getAppStatus(props: {
|
|
32
16
|
projectId: string;
|
|
33
17
|
}): Promise<AppStatePacket> {
|
|
@@ -117,7 +101,7 @@ export async function getAppLogs(props: {
|
|
|
117
101
|
args?: string[];
|
|
118
102
|
}): Promise<NodeJS.ReadableStream> {
|
|
119
103
|
const { projectId, services, args } = props;
|
|
120
|
-
await
|
|
104
|
+
await requireAppReady({ projectId });
|
|
121
105
|
|
|
122
106
|
const appDir = getAppDir(projectId);
|
|
123
107
|
|
|
@@ -143,7 +127,7 @@ export async function startApp(props: {
|
|
|
143
127
|
dockerLoginToken?: string;
|
|
144
128
|
}): Promise<void> {
|
|
145
129
|
const { projectId, dockerLoginToken } = props;
|
|
146
|
-
await
|
|
130
|
+
await requireAppReady({ projectId });
|
|
147
131
|
|
|
148
132
|
const appDir = getAppDir(projectId);
|
|
149
133
|
if (dockerLoginToken !== undefined) {
|