@layr-labs/ecloud-cli 0.1.0-rc.1 → 0.1.0
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/README.md +6 -4
- package/VERSION +2 -2
- package/dist/commands/auth/generate.js +184 -46
- package/dist/commands/auth/generate.js.map +1 -1
- package/dist/commands/auth/login.js +234 -93
- package/dist/commands/auth/login.js.map +1 -1
- package/dist/commands/auth/logout.js +170 -30
- package/dist/commands/auth/logout.js.map +1 -1
- package/dist/commands/auth/migrate.js +216 -76
- package/dist/commands/auth/migrate.js.map +1 -1
- package/dist/commands/auth/whoami.js +145 -17
- package/dist/commands/auth/whoami.js.map +1 -1
- package/dist/commands/billing/cancel.js +164 -30
- package/dist/commands/billing/cancel.js.map +1 -1
- package/dist/commands/billing/status.js +213 -80
- package/dist/commands/billing/status.js.map +1 -1
- package/dist/commands/billing/subscribe.js +179 -45
- package/dist/commands/billing/subscribe.js.map +1 -1
- package/dist/commands/compute/app/create.js +148 -20
- package/dist/commands/compute/app/create.js.map +1 -1
- package/dist/commands/compute/app/deploy.js +244 -146
- package/dist/commands/compute/app/deploy.js.map +1 -1
- package/dist/commands/compute/app/info.js +2 -1
- package/dist/commands/compute/app/info.js.map +1 -1
- package/dist/commands/compute/app/list.js +194 -111
- package/dist/commands/compute/app/list.js.map +1 -1
- package/dist/commands/compute/app/logs.js +105 -20
- package/dist/commands/compute/app/logs.js.map +1 -1
- package/dist/commands/compute/app/profile/set.js +153 -64
- package/dist/commands/compute/app/profile/set.js.map +1 -1
- package/dist/commands/compute/app/start.js +132 -43
- package/dist/commands/compute/app/start.js.map +1 -1
- package/dist/commands/compute/app/stop.js +132 -43
- package/dist/commands/compute/app/stop.js.map +1 -1
- package/dist/commands/compute/app/terminate.js +131 -44
- package/dist/commands/compute/app/terminate.js.map +1 -1
- package/dist/commands/compute/app/upgrade.js +210 -109
- package/dist/commands/compute/app/upgrade.js.map +1 -1
- package/dist/commands/compute/environment/list.js +104 -12
- package/dist/commands/compute/environment/list.js.map +1 -1
- package/dist/commands/compute/environment/set.js +103 -18
- package/dist/commands/compute/environment/set.js.map +1 -1
- package/dist/commands/compute/environment/show.js +122 -30
- package/dist/commands/compute/environment/show.js.map +1 -1
- package/dist/commands/compute/undelegate.js +113 -13
- package/dist/commands/compute/undelegate.js.map +1 -1
- package/dist/commands/telemetry.js +213 -0
- package/dist/commands/telemetry.js.map +1 -0
- package/dist/commands/upgrade.js +159 -19
- package/dist/commands/upgrade.js.map +1 -1
- package/dist/commands/version.js +163 -23
- package/dist/commands/version.js.map +1 -1
- package/package.json +2 -2
|
@@ -11,38 +11,15 @@ import {
|
|
|
11
11
|
watchUpgrade
|
|
12
12
|
} from "@layr-labs/ecloud-sdk";
|
|
13
13
|
|
|
14
|
-
// src/
|
|
15
|
-
import { Flags } from "@oclif/core";
|
|
16
|
-
|
|
17
|
-
// src/utils/prompts.ts
|
|
18
|
-
import { input, select, password, confirm as inquirerConfirm } from "@inquirer/prompts";
|
|
19
|
-
import fs3 from "fs";
|
|
20
|
-
import path3 from "path";
|
|
21
|
-
import os3 from "os";
|
|
22
|
-
import { isAddress as isAddress2 } from "viem";
|
|
23
|
-
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
14
|
+
// src/telemetry.ts
|
|
24
15
|
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
validateAppName,
|
|
33
|
-
validateImageReference,
|
|
34
|
-
validateFilePath,
|
|
35
|
-
validatePrivateKeyFormat,
|
|
36
|
-
extractAppNameFromImage,
|
|
37
|
-
UserApiClient as UserApiClient2
|
|
38
|
-
} from "@layr-labs/ecloud-sdk";
|
|
39
|
-
|
|
40
|
-
// src/utils/appResolver.ts
|
|
41
|
-
import { isAddress } from "viem";
|
|
42
|
-
import { privateKeyToAccount } from "viem/accounts";
|
|
43
|
-
import {
|
|
44
|
-
UserApiClient,
|
|
45
|
-
getAllAppsByDeveloper
|
|
16
|
+
createTelemetryClient,
|
|
17
|
+
createAppEnvironment,
|
|
18
|
+
createMetricsContext,
|
|
19
|
+
addMetric,
|
|
20
|
+
addMetricWithDimensions,
|
|
21
|
+
emitMetrics,
|
|
22
|
+
getBuildType as getBuildType2
|
|
46
23
|
} from "@layr-labs/ecloud-sdk";
|
|
47
24
|
|
|
48
25
|
// src/utils/globalConfig.ts
|
|
@@ -51,6 +28,7 @@ import * as path from "path";
|
|
|
51
28
|
import * as os from "os";
|
|
52
29
|
import { load as loadYaml, dump as dumpYaml } from "js-yaml";
|
|
53
30
|
import { getBuildType } from "@layr-labs/ecloud-sdk";
|
|
31
|
+
import * as crypto from "crypto";
|
|
54
32
|
var GLOBAL_CONFIG_FILE = "config.yaml";
|
|
55
33
|
var PROFILE_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
56
34
|
function getGlobalConfigDir() {
|
|
@@ -93,6 +71,14 @@ function saveGlobalConfig(config) {
|
|
|
93
71
|
const content = dumpYaml(config, { lineWidth: -1 });
|
|
94
72
|
fs.writeFileSync(configPath, content, { mode: 420 });
|
|
95
73
|
}
|
|
74
|
+
function getDefaultEnvironment() {
|
|
75
|
+
const config = loadGlobalConfig();
|
|
76
|
+
return config.default_environment;
|
|
77
|
+
}
|
|
78
|
+
function getGlobalTelemetryPreference() {
|
|
79
|
+
const config = loadGlobalConfig();
|
|
80
|
+
return config.telemetry_enabled;
|
|
81
|
+
}
|
|
96
82
|
function getProfileCache(environment) {
|
|
97
83
|
const config = loadGlobalConfig();
|
|
98
84
|
const cacheEntry = config.profile_cache?.[environment];
|
|
@@ -116,6 +102,107 @@ function setProfileCache(environment, profiles) {
|
|
|
116
102
|
};
|
|
117
103
|
saveGlobalConfig(config);
|
|
118
104
|
}
|
|
105
|
+
function getOrCreateUserUUID() {
|
|
106
|
+
const config = loadGlobalConfig();
|
|
107
|
+
if (config.user_uuid) {
|
|
108
|
+
return config.user_uuid;
|
|
109
|
+
}
|
|
110
|
+
const uuid = generateUUID();
|
|
111
|
+
config.user_uuid = uuid;
|
|
112
|
+
config.first_run = false;
|
|
113
|
+
saveGlobalConfig(config);
|
|
114
|
+
return uuid;
|
|
115
|
+
}
|
|
116
|
+
function generateUUID() {
|
|
117
|
+
const bytes = crypto.randomBytes(16);
|
|
118
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
119
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
120
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0"));
|
|
121
|
+
return hex.slice(0, 4).join("") + hex.slice(4, 6).join("") + "-" + hex.slice(6, 8).join("") + "-" + hex.slice(8, 10).join("") + "-" + hex.slice(10, 12).join("") + "-" + hex.slice(12, 16).join("");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/telemetry.ts
|
|
125
|
+
function createCLITelemetryClient() {
|
|
126
|
+
const userUUID = getOrCreateUserUUID();
|
|
127
|
+
const environment = createAppEnvironment(userUUID);
|
|
128
|
+
const telemetryEnabled = getGlobalTelemetryPreference();
|
|
129
|
+
return createTelemetryClient(environment, "ecloud-cli", {
|
|
130
|
+
telemetryEnabled: telemetryEnabled === true
|
|
131
|
+
// Only enabled if explicitly set to true
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
async function withTelemetry(command, action) {
|
|
135
|
+
const client = createCLITelemetryClient();
|
|
136
|
+
const metrics = createMetricsContext();
|
|
137
|
+
metrics.properties["source"] = "ecloud-cli";
|
|
138
|
+
metrics.properties["command"] = command.id || command.constructor.name;
|
|
139
|
+
const environment = getDefaultEnvironment() || "sepolia";
|
|
140
|
+
metrics.properties["environment"] = environment;
|
|
141
|
+
const buildType = getBuildType2() || "prod";
|
|
142
|
+
metrics.properties["build_type"] = buildType;
|
|
143
|
+
const cliVersion = command.config.version;
|
|
144
|
+
if (cliVersion) {
|
|
145
|
+
metrics.properties["cli_version"] = cliVersion;
|
|
146
|
+
}
|
|
147
|
+
addMetric(metrics, "Count", 1);
|
|
148
|
+
let actionError;
|
|
149
|
+
let result;
|
|
150
|
+
try {
|
|
151
|
+
result = await action();
|
|
152
|
+
return result;
|
|
153
|
+
} catch (err) {
|
|
154
|
+
actionError = err instanceof Error ? err : new Error(String(err));
|
|
155
|
+
throw err;
|
|
156
|
+
} finally {
|
|
157
|
+
const resultValue = actionError ? "Failure" : "Success";
|
|
158
|
+
const dimensions = {};
|
|
159
|
+
if (actionError) {
|
|
160
|
+
dimensions["error"] = actionError.message;
|
|
161
|
+
}
|
|
162
|
+
addMetricWithDimensions(metrics, resultValue, 1, dimensions);
|
|
163
|
+
const duration = Date.now() - metrics.startTime.getTime();
|
|
164
|
+
addMetric(metrics, "DurationMilliseconds", duration);
|
|
165
|
+
try {
|
|
166
|
+
await emitMetrics(client, metrics);
|
|
167
|
+
await client.close();
|
|
168
|
+
} catch {
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/flags.ts
|
|
174
|
+
import { Flags } from "@oclif/core";
|
|
175
|
+
|
|
176
|
+
// src/utils/prompts.ts
|
|
177
|
+
import { input, select, password, confirm as inquirerConfirm } from "@inquirer/prompts";
|
|
178
|
+
import fs3 from "fs";
|
|
179
|
+
import path3 from "path";
|
|
180
|
+
import os3 from "os";
|
|
181
|
+
import { isAddress as isAddress2 } from "viem";
|
|
182
|
+
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
183
|
+
import {
|
|
184
|
+
getEnvironmentConfig,
|
|
185
|
+
getAvailableEnvironments,
|
|
186
|
+
isEnvironmentAvailable,
|
|
187
|
+
getAllAppsByDeveloper as getAllAppsByDeveloper2,
|
|
188
|
+
getCategoryDescriptions,
|
|
189
|
+
fetchTemplateCatalog,
|
|
190
|
+
PRIMARY_LANGUAGES,
|
|
191
|
+
validateAppName,
|
|
192
|
+
validateImageReference,
|
|
193
|
+
validateFilePath,
|
|
194
|
+
validatePrivateKeyFormat,
|
|
195
|
+
extractAppNameFromImage,
|
|
196
|
+
UserApiClient as UserApiClient2
|
|
197
|
+
} from "@layr-labs/ecloud-sdk";
|
|
198
|
+
|
|
199
|
+
// src/utils/appResolver.ts
|
|
200
|
+
import { isAddress } from "viem";
|
|
201
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
202
|
+
import {
|
|
203
|
+
UserApiClient,
|
|
204
|
+
getAllAppsByDeveloper
|
|
205
|
+
} from "@layr-labs/ecloud-sdk";
|
|
119
206
|
|
|
120
207
|
// src/utils/appNames.ts
|
|
121
208
|
import * as fs2 from "fs";
|
|
@@ -163,7 +250,7 @@ function listApps(environment) {
|
|
|
163
250
|
|
|
164
251
|
// src/utils/version.ts
|
|
165
252
|
function getCliVersion() {
|
|
166
|
-
return true ? "0.1.0
|
|
253
|
+
return true ? "0.1.0" : "0.0.0";
|
|
167
254
|
}
|
|
168
255
|
function getClientId() {
|
|
169
256
|
return `ecloud-cli/v${getCliVersion()}`;
|
|
@@ -444,7 +531,7 @@ async function getImageReferenceInteractive(imageRef, buildFromDockerfile = fals
|
|
|
444
531
|
if (buildFromDockerfile) {
|
|
445
532
|
console.log("\n\u{1F4E6} Build & Push Configuration");
|
|
446
533
|
console.log("Your Docker image will be built and pushed to a registry");
|
|
447
|
-
console.log("so that
|
|
534
|
+
console.log("so that Ecloud CLI can pull and run it in the TEE.");
|
|
448
535
|
console.log();
|
|
449
536
|
if (registries.length > 0) {
|
|
450
537
|
displayDetectedRegistries(registries, appName);
|
|
@@ -969,88 +1056,102 @@ var AppUpgrade = class _AppUpgrade extends Command {
|
|
|
969
1056
|
})
|
|
970
1057
|
};
|
|
971
1058
|
async run() {
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
appID
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
rpcUrl,
|
|
988
|
-
action: "upgrade"
|
|
989
|
-
});
|
|
990
|
-
const dockerfilePath = await getDockerfileInteractive(flags.dockerfile);
|
|
991
|
-
const buildFromDockerfile = dockerfilePath !== "";
|
|
992
|
-
const imageRef = await getImageReferenceInteractive(flags["image-ref"], buildFromDockerfile);
|
|
993
|
-
const envFilePath = await getEnvFileInteractive(flags["env-file"]);
|
|
994
|
-
let currentInstanceType = "";
|
|
995
|
-
try {
|
|
996
|
-
const userApiClient = new UserApiClient3(environmentConfig, privateKey, rpcUrl, getClientId());
|
|
997
|
-
const infos = await userApiClient.getInfos([appID], 1);
|
|
998
|
-
if (infos.length > 0) {
|
|
999
|
-
currentInstanceType = infos[0].machineType || "";
|
|
1000
|
-
}
|
|
1001
|
-
} catch {
|
|
1002
|
-
}
|
|
1003
|
-
const availableTypes = await fetchAvailableInstanceTypes(environmentConfig, privateKey, rpcUrl);
|
|
1004
|
-
const instanceType = await getInstanceTypeInteractive(
|
|
1005
|
-
flags["instance-type"],
|
|
1006
|
-
currentInstanceType,
|
|
1007
|
-
availableTypes
|
|
1008
|
-
);
|
|
1009
|
-
const logSettings = await getLogSettingsInteractive(
|
|
1010
|
-
flags["log-visibility"]
|
|
1011
|
-
);
|
|
1012
|
-
const resourceUsageMonitoring = await getResourceUsageMonitoringInteractive(
|
|
1013
|
-
flags["resource-usage-monitoring"]
|
|
1014
|
-
);
|
|
1015
|
-
const logVisibility = logSettings.publicLogs ? "public" : logSettings.logRedirect ? "private" : "off";
|
|
1016
|
-
const { prepared, gasEstimate } = await prepareUpgrade(
|
|
1017
|
-
{
|
|
1018
|
-
appId: appID,
|
|
1059
|
+
return withTelemetry(this, async () => {
|
|
1060
|
+
const { args, flags } = await this.parse(_AppUpgrade);
|
|
1061
|
+
const logger = {
|
|
1062
|
+
info: (msg) => this.log(msg),
|
|
1063
|
+
warn: (msg) => this.warn(msg),
|
|
1064
|
+
error: (msg) => this.error(msg),
|
|
1065
|
+
debug: (msg) => flags.verbose && this.log(msg)
|
|
1066
|
+
};
|
|
1067
|
+
const environment = flags.environment || "sepolia";
|
|
1068
|
+
const environmentConfig = getEnvironmentConfig2(environment);
|
|
1069
|
+
const rpcUrl = flags["rpc-url"] || environmentConfig.defaultRPCURL;
|
|
1070
|
+
const privateKey = await getPrivateKeyInteractive(flags["private-key"]);
|
|
1071
|
+
const appID = await getOrPromptAppID({
|
|
1072
|
+
appID: args["app-id"],
|
|
1073
|
+
environment,
|
|
1019
1074
|
privateKey,
|
|
1020
1075
|
rpcUrl,
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1076
|
+
action: "upgrade"
|
|
1077
|
+
});
|
|
1078
|
+
const dockerfilePath = await getDockerfileInteractive(flags.dockerfile);
|
|
1079
|
+
const buildFromDockerfile = dockerfilePath !== "";
|
|
1080
|
+
const imageRef = await getImageReferenceInteractive(flags["image-ref"], buildFromDockerfile);
|
|
1081
|
+
const envFilePath = await getEnvFileInteractive(flags["env-file"]);
|
|
1082
|
+
let currentInstanceType = "";
|
|
1083
|
+
try {
|
|
1084
|
+
const userApiClient = new UserApiClient3(
|
|
1085
|
+
environmentConfig,
|
|
1086
|
+
privateKey,
|
|
1087
|
+
rpcUrl,
|
|
1088
|
+
getClientId()
|
|
1089
|
+
);
|
|
1090
|
+
const infos = await userApiClient.getInfos([appID], 1);
|
|
1091
|
+
if (infos.length > 0) {
|
|
1092
|
+
currentInstanceType = infos[0].machineType || "";
|
|
1093
|
+
}
|
|
1094
|
+
} catch {
|
|
1095
|
+
}
|
|
1096
|
+
const availableTypes = await fetchAvailableInstanceTypes(
|
|
1097
|
+
environmentConfig,
|
|
1098
|
+
privateKey,
|
|
1099
|
+
rpcUrl
|
|
1100
|
+
);
|
|
1101
|
+
const instanceType = await getInstanceTypeInteractive(
|
|
1102
|
+
flags["instance-type"],
|
|
1103
|
+
currentInstanceType,
|
|
1104
|
+
availableTypes
|
|
1105
|
+
);
|
|
1106
|
+
const logSettings = await getLogSettingsInteractive(
|
|
1107
|
+
flags["log-visibility"]
|
|
1108
|
+
);
|
|
1109
|
+
const resourceUsageMonitoring = await getResourceUsageMonitoringInteractive(
|
|
1110
|
+
flags["resource-usage-monitoring"]
|
|
1111
|
+
);
|
|
1112
|
+
const logVisibility = logSettings.publicLogs ? "public" : logSettings.logRedirect ? "private" : "off";
|
|
1113
|
+
const { prepared, gasEstimate } = await prepareUpgrade(
|
|
1114
|
+
{
|
|
1115
|
+
appId: appID,
|
|
1116
|
+
privateKey,
|
|
1117
|
+
rpcUrl,
|
|
1118
|
+
environment,
|
|
1119
|
+
dockerfilePath,
|
|
1120
|
+
imageRef,
|
|
1121
|
+
envFilePath,
|
|
1122
|
+
instanceType,
|
|
1123
|
+
logVisibility,
|
|
1124
|
+
resourceUsageMonitoring,
|
|
1125
|
+
skipTelemetry: true
|
|
1126
|
+
},
|
|
1127
|
+
logger
|
|
1128
|
+
);
|
|
1129
|
+
this.log(`
|
|
1032
1130
|
Estimated transaction cost: ${chalk.cyan(gasEstimate.maxCostEth)} ETH`);
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1131
|
+
if (isMainnet(environmentConfig)) {
|
|
1132
|
+
const confirmed = await confirm(`Continue with upgrade?`);
|
|
1133
|
+
if (!confirmed) {
|
|
1134
|
+
this.log(`
|
|
1037
1135
|
${chalk.gray(`Upgrade cancelled`)}`);
|
|
1038
|
-
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1039
1138
|
}
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1139
|
+
const res = await executeUpgrade(
|
|
1140
|
+
prepared,
|
|
1141
|
+
{
|
|
1142
|
+
maxFeePerGas: gasEstimate.maxFeePerGas,
|
|
1143
|
+
maxPriorityFeePerGas: gasEstimate.maxPriorityFeePerGas
|
|
1144
|
+
},
|
|
1145
|
+
logger,
|
|
1146
|
+
true
|
|
1147
|
+
// skipTelemetry
|
|
1148
|
+
);
|
|
1149
|
+
await watchUpgrade(res.appId, privateKey, rpcUrl, environment, logger, getClientId(), true);
|
|
1150
|
+
this.log(
|
|
1151
|
+
`
|
|
1052
1152
|
\u2705 ${chalk.green(`App upgraded successfully ${chalk.bold(`(id: ${res.appId}, image: ${res.imageRef})`)}`)}`
|
|
1053
|
-
|
|
1153
|
+
);
|
|
1154
|
+
});
|
|
1054
1155
|
}
|
|
1055
1156
|
};
|
|
1056
1157
|
async function fetchAvailableInstanceTypes(environmentConfig, privateKey, rpcUrl) {
|