@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.
Files changed (151) hide show
  1. package/lib/application-control/backup.js +3 -3
  2. package/lib/application-control/backup.js.map +1 -1
  3. package/lib/application-control/index.d.ts +4 -4
  4. package/lib/application-control/index.d.ts.map +1 -1
  5. package/lib/application-control/index.js +1 -4
  6. package/lib/application-control/index.js.map +1 -1
  7. package/lib/application-control/install.d.ts +1 -1
  8. package/lib/application-control/install.d.ts.map +1 -1
  9. package/lib/application-control/install.js +41 -54
  10. package/lib/application-control/install.js.map +1 -1
  11. package/lib/application-control/models.d.ts +0 -4
  12. package/lib/application-control/models.d.ts.map +1 -1
  13. package/lib/application-control/models.js +13 -22
  14. package/lib/application-control/models.js.map +1 -1
  15. package/lib/application-control/status.d.ts +0 -6
  16. package/lib/application-control/status.d.ts.map +1 -1
  17. package/lib/application-control/status.js +3 -19
  18. package/lib/application-control/status.js.map +1 -1
  19. package/lib/application-control/utils.d.ts +3 -0
  20. package/lib/application-control/utils.d.ts.map +1 -1
  21. package/lib/application-control/utils.js +50 -21
  22. package/lib/application-control/utils.js.map +1 -1
  23. package/lib/cloud-connection/bootstrap-provision.d.ts +1 -1
  24. package/lib/cloud-connection/bootstrap-provision.d.ts.map +1 -1
  25. package/lib/cloud-connection/bootstrap-provision.js +9 -9
  26. package/lib/cloud-connection/bootstrap-provision.js.map +1 -1
  27. package/lib/cloud-connection/cmd-status.d.ts +8 -0
  28. package/lib/cloud-connection/cmd-status.d.ts.map +1 -0
  29. package/lib/cloud-connection/cmd-status.js +62 -0
  30. package/lib/cloud-connection/cmd-status.js.map +1 -0
  31. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +10 -2
  32. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  33. package/lib/cloud-connection/device-agent-cloud-connection.js +156 -66
  34. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  35. package/lib/cloud-connection/device-agent.d.ts.map +1 -1
  36. package/lib/cloud-connection/device-agent.js +4 -3
  37. package/lib/cloud-connection/device-agent.js.map +1 -1
  38. package/lib/cloud-connection/live-updates-handler.d.ts +10 -18
  39. package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
  40. package/lib/cloud-connection/live-updates-handler.js +50 -50
  41. package/lib/cloud-connection/live-updates-handler.js.map +1 -1
  42. package/lib/cloud-connection/messages.d.ts +3 -1
  43. package/lib/cloud-connection/messages.d.ts.map +1 -1
  44. package/lib/cloud-connection/messages.js +13 -1
  45. package/lib/cloud-connection/messages.js.map +1 -1
  46. package/lib/cloud-connection/passthrough-handler.d.ts +11 -0
  47. package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -0
  48. package/lib/cloud-connection/passthrough-handler.js +59 -0
  49. package/lib/cloud-connection/passthrough-handler.js.map +1 -0
  50. package/lib/cloud-connection/publisher.d.ts +1 -0
  51. package/lib/cloud-connection/publisher.d.ts.map +1 -1
  52. package/lib/cloud-connection/publisher.js +14 -0
  53. package/lib/cloud-connection/publisher.js.map +1 -1
  54. package/lib/cloud-connection/shadow-handler.d.ts +2 -3
  55. package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
  56. package/lib/cloud-connection/shadow-handler.js +18 -4
  57. package/lib/cloud-connection/shadow-handler.js.map +1 -1
  58. package/lib/cloud-connection/shadow-handler.test.d.ts +2 -0
  59. package/lib/cloud-connection/shadow-handler.test.d.ts.map +1 -0
  60. package/lib/cloud-connection/shadow-handler.test.js +321 -0
  61. package/lib/cloud-connection/shadow-handler.test.js.map +1 -0
  62. package/lib/environment.d.ts +1 -0
  63. package/lib/environment.d.ts.map +1 -1
  64. package/lib/environment.js +3 -2
  65. package/lib/environment.js.map +1 -1
  66. package/lib/index.js +2 -2
  67. package/lib/index.js.map +1 -1
  68. package/lib/infrastructure/agent-config.d.ts +15 -48
  69. package/lib/infrastructure/agent-config.d.ts.map +1 -1
  70. package/lib/infrastructure/agent-config.js.map +1 -1
  71. package/lib/infrastructure/agent-config.test.js +0 -6
  72. package/lib/infrastructure/agent-config.test.js.map +1 -1
  73. package/lib/infrastructure/system-id.js +2 -2
  74. package/lib/infrastructure/system-id.js.map +1 -1
  75. package/lib/infrastructure/tokens-and-device-cfg.d.ts.map +1 -1
  76. package/lib/infrastructure/tokens-and-device-cfg.js +5 -9
  77. package/lib/infrastructure/tokens-and-device-cfg.js.map +1 -1
  78. package/lib/local-connection/rabbitmq-connection.d.ts +4 -0
  79. package/lib/local-connection/rabbitmq-connection.d.ts.map +1 -0
  80. package/lib/local-connection/rabbitmq-connection.js +58 -0
  81. package/lib/local-connection/rabbitmq-connection.js.map +1 -0
  82. package/lib/subcommands/app/app.d.ts +4 -3
  83. package/lib/subcommands/app/app.d.ts.map +1 -1
  84. package/lib/subcommands/app/app.js +78 -27
  85. package/lib/subcommands/app/app.js.map +1 -1
  86. package/lib/subcommands/app/index.js +2 -2
  87. package/lib/subcommands/device/clean.js +4 -4
  88. package/lib/subcommands/device/clean.js.map +1 -1
  89. package/lib/subcommands/device/device.d.ts +1 -1
  90. package/lib/subcommands/device/device.d.ts.map +1 -1
  91. package/lib/subcommands/device/device.js +9 -10
  92. package/lib/subcommands/device/device.js.map +1 -1
  93. package/lib/subcommands/index.d.ts +0 -1
  94. package/lib/subcommands/index.d.ts.map +1 -1
  95. package/lib/subcommands/login.d.ts +0 -1
  96. package/lib/subcommands/login.d.ts.map +1 -1
  97. package/lib/subcommands/login.js +1 -9
  98. package/lib/subcommands/login.js.map +1 -1
  99. package/lib/util/directories.d.ts +11 -12
  100. package/lib/util/directories.d.ts.map +1 -1
  101. package/lib/util/directories.js +24 -29
  102. package/lib/util/directories.js.map +1 -1
  103. package/lib/util/fetch-with-timeout.d.ts +4 -0
  104. package/lib/util/fetch-with-timeout.d.ts.map +1 -0
  105. package/lib/util/fetch-with-timeout.js +15 -0
  106. package/lib/util/fetch-with-timeout.js.map +1 -0
  107. package/lib/util/logger.js +1 -0
  108. package/lib/util/logger.js.map +1 -1
  109. package/lib/util/require-logged-in-and-paid-plan.d.ts +2 -0
  110. package/lib/util/require-logged-in-and-paid-plan.d.ts.map +1 -0
  111. package/lib/util/require-logged-in-and-paid-plan.js +18 -0
  112. package/lib/util/require-logged-in-and-paid-plan.js.map +1 -0
  113. package/package.json +20 -32
  114. package/readme.md +100 -89
  115. package/src/application-control/backup.ts +3 -3
  116. package/src/application-control/index.ts +0 -6
  117. package/src/application-control/install.ts +53 -73
  118. package/src/application-control/models.ts +7 -19
  119. package/src/application-control/status.ts +3 -19
  120. package/src/application-control/utils.ts +61 -22
  121. package/src/cloud-connection/bootstrap-provision.ts +13 -10
  122. package/src/cloud-connection/cmd-status.ts +71 -0
  123. package/src/cloud-connection/device-agent-cloud-connection.ts +211 -102
  124. package/src/cloud-connection/device-agent.ts +7 -4
  125. package/src/cloud-connection/live-updates-handler.ts +79 -86
  126. package/src/cloud-connection/messages.ts +22 -1
  127. package/src/cloud-connection/passthrough-handler.ts +67 -0
  128. package/src/cloud-connection/publisher.ts +21 -0
  129. package/src/cloud-connection/shadow-handler.test.ts +361 -0
  130. package/src/cloud-connection/shadow-handler.ts +28 -7
  131. package/src/environment.ts +4 -1
  132. package/src/index.ts +2 -2
  133. package/src/infrastructure/agent-config.test.ts +0 -7
  134. package/src/infrastructure/agent-config.ts +24 -2
  135. package/src/infrastructure/system-id.ts +1 -1
  136. package/src/infrastructure/tokens-and-device-cfg.ts +8 -13
  137. package/src/local-connection/rabbitmq-connection.ts +53 -0
  138. package/src/subcommands/app/app.ts +82 -31
  139. package/src/subcommands/app/index.ts +4 -4
  140. package/src/subcommands/device/clean.ts +4 -4
  141. package/src/subcommands/device/device.ts +13 -13
  142. package/src/subcommands/login.ts +1 -9
  143. package/src/util/directories.ts +31 -29
  144. package/src/util/fetch-with-timeout.ts +18 -0
  145. package/src/util/logger.ts +2 -0
  146. package/src/util/require-logged-in-and-paid-plan.ts +16 -0
  147. package/lib/cloud-connection/app-install-status.d.ts +0 -16
  148. package/lib/cloud-connection/app-install-status.d.ts.map +0 -1
  149. package/lib/cloud-connection/app-install-status.js +0 -53
  150. package/lib/cloud-connection/app-install-status.js.map +0 -1
  151. 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 is a tool that runs on an alwaysAI device provisioned
4
- for production remote deployment. It enables management of one or more alwaysAI
5
- apps on a particular device via a command line interface.
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
- * Recent version of Debian or Ubuntu
14
- * `npm` >= 7.0.0
15
- * `node` >= 16.0.0
16
- * Recent version of `docker` with user access
17
- * On Linux: `$ sudo usermod -aG docker $USER`
18
- * Recent version of `docker-compose`
19
- * `curl` installed.
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
- ### Provision the device
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
- Otherwise, you can run the provision script to install the agent and its dependencies:
29
+ On the target device, run:
32
30
 
33
31
  ```
34
- curl -fsSL https://alwaysai-artifacts-prod.s3.us-west-1.amazonaws.com/device-agent/install-device-agent.sh | sudo -E bash -
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
- Next, log in to the Device Agent with the following command:
40
-
41
- ```
42
- aai-agent login --email <username> --password <password> [--device <device_id>]
43
- ```
37
+ ### Provision the device
44
38
 
45
- Note that if you already have a device registered with the alwaysAI cloud, you
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
- ### Initialize the alwaysAI device
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
- After logging in, run the following command to initialize the current device as
52
- an alwaysAI device:
45
+ Run the following command on the target device to provision it:
53
46
 
54
47
  ```
55
- $ aai-agent device init --name <name> [--description <description>]
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
- For example:
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
- $ aai-agent device init --name test-dev-1 --description "Device for testing alwaysAI Device Agent"
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
- ## Run an alwaysAI application on your device
65
+ When the script completes, the device will be provisioned but the Device Agent will not be running in the background.
65
66
 
66
- ### Publish an application release and install on device
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> [--release <release_hash>]
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 * as rimraf from 'rimraf';
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.sync(backupAppDir);
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.sync(appDir);
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 * as rimraf from 'rimraf';
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?: SignedUrlPayloadType;
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
- if (!signedUrlsPayload) {
86
- await runInDir(
87
- appReleasePullComponent,
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
- // install models, python venv, and docker image
115
- if (!signedUrlsPayload) {
116
- await runInDir(
117
- appInstallComponent,
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 targetJson = targetJsonFile.readIfExists();
151
- if (!targetJson) {
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 targetHostSpawner = targetJsonFile.readHostSpawner();
123
+ const hostSpawner = targetJsonFile.readHostSpawner();
158
124
 
159
- await appCleanDockerComponent({ targetHostSpawner });
125
+ await appCleanDocker({ targetHostSpawner: hostSpawner });
160
126
 
161
- await buildDocker({
162
- targetJson,
163
- targetJsonFile,
164
- targetHostSpawner,
165
- pull: true
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
- await installVenv({
169
- targetJson,
170
- sourceSpawner: targetHostSpawner,
171
- targetJsonFile
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.sync(appDir);
228
- rimraf.sync(`${appDir}${BACKUP_EXT}`);
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
- requireAppInstalled
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, updateAppCfgFile, writeAppCfgFile } from './config';
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 requireAppInstalled({ projectId });
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 requireAppInstalled({ projectId });
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 requireAppInstalled({ projectId });
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 requireAppInstalled({ projectId });
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 requireAppInstalled({ projectId });
130
+ await requireAppReady({ projectId });
147
131
 
148
132
  const appDir = getAppDir(projectId);
149
133
  if (dockerLoginToken !== undefined) {