@layr-labs/ecloud-sdk 1.0.0-devep7 → 1.0.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/VERSION +2 -2
- package/dist/billing.cjs +164 -37
- package/dist/billing.cjs.map +1 -1
- package/dist/billing.d.cts +12 -3
- package/dist/billing.d.ts +12 -3
- package/dist/billing.js +164 -37
- package/dist/billing.js.map +1 -1
- package/dist/browser.cjs +1699 -139
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +5 -4
- package/dist/browser.d.ts +5 -4
- package/dist/browser.js +1699 -140
- package/dist/browser.js.map +1 -1
- package/dist/compute-B-V7Dbj9.d.cts +465 -0
- package/dist/compute-BJ_sqrKn.d.ts +465 -0
- package/dist/compute.cjs +1884 -735
- package/dist/compute.cjs.map +1 -1
- package/dist/compute.d.cts +3 -2
- package/dist/compute.d.ts +3 -2
- package/dist/compute.js +1873 -724
- package/dist/compute.js.map +1 -1
- package/dist/{helpers-B8KBOdM4.d.ts → helpers-CkcuSkNM.d.ts} +18 -191
- package/dist/{helpers-BVSe7yTf.d.cts → helpers-fmu7es2L.d.cts} +18 -191
- package/dist/{index-XhjPvHIY.d.cts → index-BVnxNfqb.d.cts} +67 -3
- package/dist/{index-XhjPvHIY.d.ts → index-BVnxNfqb.d.ts} +67 -3
- package/dist/index.cjs +2075 -744
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +73 -241
- package/dist/index.d.ts +73 -241
- package/dist/index.js +2054 -730
- package/dist/index.js.map +1 -1
- package/dist/validation-D3yIUF-Z.d.cts +167 -0
- package/dist/validation-D3yIUF-Z.d.ts +167 -0
- package/package.json +4 -5
- package/dist/compute-2WkiO-d8.d.ts +0 -194
- package/dist/compute-CoBGVJXh.d.cts +0 -194
- package/tools/ecloud-drain-watcher-linux-amd64 +0 -0
package/dist/compute.js
CHANGED
|
@@ -139,8 +139,8 @@ import * as child_process from "child_process";
|
|
|
139
139
|
import { promisify } from "util";
|
|
140
140
|
|
|
141
141
|
// src/client/common/constants.ts
|
|
142
|
-
import { sepolia, mainnet } from "viem/chains";
|
|
143
|
-
var SUPPORTED_CHAINS = [mainnet, sepolia];
|
|
142
|
+
import { sepolia, mainnet, baseSepolia } from "viem/chains";
|
|
143
|
+
var SUPPORTED_CHAINS = [mainnet, sepolia, baseSepolia];
|
|
144
144
|
var DOCKER_PLATFORM = "linux/amd64";
|
|
145
145
|
var REGISTRY_PROPAGATION_WAIT_SECONDS = 3;
|
|
146
146
|
var LAYERED_DOCKERFILE_NAME = "Dockerfile.eigencompute";
|
|
@@ -148,7 +148,6 @@ var ENV_SOURCE_SCRIPT_NAME = "compute-source-env.sh";
|
|
|
148
148
|
var KMS_CLIENT_BINARY_NAME = "kms-client";
|
|
149
149
|
var KMS_SIGNING_KEY_NAME = "kms-signing-public-key.pem";
|
|
150
150
|
var TLS_KEYGEN_BINARY_NAME = "tls-keygen";
|
|
151
|
-
var DRAIN_WATCHER_BINARY_NAME = "ecloud-drain-watcher";
|
|
152
151
|
var CADDYFILE_NAME = "Caddyfile";
|
|
153
152
|
var LAYERED_BUILD_DIR_PREFIX = "ecloud-layered-build";
|
|
154
153
|
|
|
@@ -435,12 +434,14 @@ USER root
|
|
|
435
434
|
{{/if}}
|
|
436
435
|
|
|
437
436
|
# Copy core TEE components
|
|
437
|
+
# CA bundle for kms-client / tls-keygen to validate HTTPS calls to
|
|
438
|
+
# eigencloud.xyz endpoints. Bundled at a non-standard path and consumed
|
|
439
|
+
# only via SSL_CERT_FILE in compute-source-env.sh, so the user's
|
|
440
|
+
# /etc/ssl/ is never touched.
|
|
441
|
+
COPY --from=alpine:3.20.10 /etc/ssl/certs/ca-certificates.crt /usr/local/share/eigenx-ca-certs.crt
|
|
438
442
|
COPY compute-source-env.sh /usr/local/bin/
|
|
439
443
|
COPY kms-client /usr/local/bin/
|
|
440
444
|
COPY kms-signing-public-key.pem /usr/local/bin/
|
|
441
|
-
{{#if includeDrainWatcher}}
|
|
442
|
-
COPY ecloud-drain-watcher /usr/local/bin/
|
|
443
|
-
{{/if}}
|
|
444
445
|
|
|
445
446
|
{{#if includeTLS}}
|
|
446
447
|
# Copy Caddy from official image
|
|
@@ -454,8 +455,7 @@ COPY Caddyfile /etc/caddy/
|
|
|
454
455
|
{{#if originalUser}}
|
|
455
456
|
# Make binaries executable (755 for executables, 644 for keys)
|
|
456
457
|
RUN chmod 755 /usr/local/bin/compute-source-env.sh \\
|
|
457
|
-
&& chmod 755 /usr/local/bin/kms-client{{#if
|
|
458
|
-
&& chmod 755 /usr/local/bin/ecloud-drain-watcher{{/if}}{{#if includeTLS}} \\
|
|
458
|
+
&& chmod 755 /usr/local/bin/kms-client{{#if includeTLS}} \\
|
|
459
459
|
&& chmod 755 /usr/local/bin/tls-keygen \\
|
|
460
460
|
&& chmod 755 /usr/local/bin/caddy{{/if}} \\
|
|
461
461
|
&& chmod 644 /usr/local/bin/kms-signing-public-key.pem
|
|
@@ -465,8 +465,7 @@ ENV __ECLOUD_ORIGINAL_USER={{originalUser}}
|
|
|
465
465
|
{{else}}
|
|
466
466
|
# Make binaries executable (preserve existing permissions, just add execute)
|
|
467
467
|
RUN chmod +x /usr/local/bin/compute-source-env.sh \\
|
|
468
|
-
&& chmod +x /usr/local/bin/kms-client{{#if
|
|
469
|
-
&& chmod +x /usr/local/bin/ecloud-drain-watcher{{/if}}{{#if includeTLS}} \\
|
|
468
|
+
&& chmod +x /usr/local/bin/kms-client{{#if includeTLS}} \\
|
|
470
469
|
&& chmod +x /usr/local/bin/tls-keygen{{/if}}
|
|
471
470
|
{{/if}}
|
|
472
471
|
|
|
@@ -479,36 +478,8 @@ LABEL tee.launch_policy.log_redirect={{logRedirect}}
|
|
|
479
478
|
LABEL tee.launch_policy.monitoring_memory_allow={{resourceUsageAllow}}
|
|
480
479
|
{{/if}}
|
|
481
480
|
|
|
482
|
-
# Allow-list the envvars the ecloud-platform sets via GCE \`tee-env-*\`
|
|
483
|
-
# metadata. Without this label, Confidential Space's launcher rejects
|
|
484
|
-
# any \`tee-env-*\` override at container-start with
|
|
485
|
-
# "env var {...} is not allowed to be overridden on this image" and
|
|
486
|
-
# exits with code 1 \u2014 which terminates the VM before the entrypoint
|
|
487
|
-
# ever runs. User-supplied env vars flow through KMS (not tee-env-*)
|
|
488
|
-
# and don't need to be listed here.
|
|
489
|
-
#
|
|
490
|
-
# Entries:
|
|
491
|
-
# - ECLOUD_PD_EXPECTED set on PD-backed apps so the entrypoint
|
|
492
|
-
# (compute-source-env.sh) knows to wait for
|
|
493
|
-
# the persistent disk before exec'ing the
|
|
494
|
-
# user workload.
|
|
495
|
-
# - ECLOUD_PLATFORM_HOST the platform-routed hostname
|
|
496
|
-
# (<addr>.<env>.eigencloud.xyz) so the
|
|
497
|
-
# entrypoint's setup_tls can issue an ACME
|
|
498
|
-
# cert for it. Injected by the CLI into
|
|
499
|
-
# publicEnv at deploy/upgrade time and
|
|
500
|
-
# propagated by ecloud-platform's
|
|
501
|
-
# compute.go as a tee-env-* metadata key.
|
|
502
|
-
#
|
|
503
|
-
# The CS launcher parses this label as a comma-separated list
|
|
504
|
-
# (go-tpm-tools/launcher/spec/launch_policy.go:185 \u2014 strings.Split
|
|
505
|
-
# on ","). Quotes are not required; keep the value bare for
|
|
506
|
-
# consistency with compute-tee's and eigenx-kms's existing labels.
|
|
507
|
-
LABEL tee.launch_policy.allow_env_override=ECLOUD_PD_EXPECTED,ECLOUD_PLATFORM_HOST
|
|
508
|
-
|
|
509
481
|
LABEL eigenx_cli_version={{ecloudCLIVersion}}
|
|
510
482
|
LABEL eigenx_vm_image=eigen
|
|
511
|
-
LABEL eigenx_container_contract=v1
|
|
512
483
|
|
|
513
484
|
{{#if includeTLS}}
|
|
514
485
|
# Expose both HTTP and HTTPS ports for Caddy
|
|
@@ -530,54 +501,11 @@ import Handlebars2 from "handlebars";
|
|
|
530
501
|
|
|
531
502
|
// src/client/common/templates/compute-source-env.sh.tmpl
|
|
532
503
|
var compute_source_env_sh_default = `#!/bin/sh
|
|
533
|
-
# EigenCompute container entrypoint script
|
|
534
|
-
# This script handles KMS secret fetching, TLS setup, and privilege dropping
|
|
535
|
-
# before executing the user's application.
|
|
536
|
-
#
|
|
537
|
-
# Handlebars template variables (replaced at build time by the CLI):
|
|
538
|
-
# kmsServerURL - URL of the KMS server
|
|
539
|
-
# userAPIURL - URL of the user API (ecloud-platform)
|
|
540
|
-
# The KMS signing public key is copied into the image as
|
|
541
|
-
# /usr/local/bin/kms-signing-public-key.pem at layer-build time by the CLI.
|
|
542
|
-
#
|
|
543
|
-
# ecloud-platform divergence from compute-tee:
|
|
544
|
-
# This script emits ECLOUD_READY / ECLOUD_FAIL / ECLOUD_AWAITING_USERDATA /
|
|
545
|
-
# ECLOUD_DETACHED markers to stdout at key lifecycle points. The GCP
|
|
546
|
-
# provisioner's serial-console watcher in ecloud-platform
|
|
547
|
-
# (pkg/services/infraService/providers/gcp/compute.go) parses those
|
|
548
|
-
# markers to gate "VM ready" and to coordinate the prewarm-detach
|
|
549
|
-
# upgrade flow. Without the markers, the platform's waitForStartupReady
|
|
550
|
-
# times out at ~10 minutes per deploy, rollback fires, and the VM is
|
|
551
|
-
# deleted \u2014 seen in dev on 2026-05-04 with an older copy of this
|
|
552
|
-
# template that lacked the markers.
|
|
553
|
-
#
|
|
554
|
-
# Prewarm-detach contract:
|
|
555
|
-
# - If ECLOUD_PD_EXPECTED=1 and /mnt/disks/userdata is not present at boot,
|
|
556
|
-
# emit ECLOUD_AWAITING_USERDATA and wait until the disk is attached.
|
|
557
|
-
# - On SIGTERM (drain-requested), forward to child, wait for exit, sync
|
|
558
|
-
# + unmount /mnt/disks/userdata, emit ECLOUD_DETACHED, exit.
|
|
559
|
-
# - ECLOUD_READY is emitted once runtime is bootstrapped (same as before).
|
|
560
|
-
# - ECLOUD_FAIL is emitted on any unrecoverable setup error.
|
|
561
|
-
# Keep the markers on any line that resolves a lifecycle outcome.
|
|
562
|
-
#
|
|
563
|
-
# This file is kept in lockstep with
|
|
564
|
-
# ecloud-platform/pkg/services/buildService/assets/compute-source-env.sh.tmpl
|
|
565
|
-
# \u2014 if you change one, change the other. Differences vs the platform copy
|
|
566
|
-
# are intentionally minimal:
|
|
567
|
-
# - Handlebars placeholders use the CLI's naming (kmsServerURL,
|
|
568
|
-
# userAPIURL) rather than the platform's (KMS_SERVER_URL,
|
|
569
|
-
# USER_API_URL). (See top of file for real placeholder syntax \u2014
|
|
570
|
-
# not repeated here so Handlebars doesn't expand it in this comment.)
|
|
571
|
-
# - KMS signing key is read from a file the CLI copies into the image,
|
|
572
|
-
# not heredoc-embedded in the script, because the CLI's image
|
|
573
|
-
# layering writes it as a separate file (kms-signing-public-key.pem).
|
|
574
|
-
# - TLS binary is \`tls-keygen\` (CLI-bundled) not \`tls-client\`.
|
|
575
|
-
|
|
576
504
|
echo "compute-source-env.sh: Running setup script..."
|
|
577
505
|
|
|
578
506
|
# Fetch and source environment variables from KMS
|
|
579
507
|
echo "Fetching secrets from KMS..."
|
|
580
|
-
if /usr/local/bin/kms-client \\
|
|
508
|
+
if SSL_CERT_FILE=/usr/local/share/eigenx-ca-certs.crt /usr/local/bin/kms-client \\
|
|
581
509
|
--kms-server-url "{{kmsServerURL}}" \\
|
|
582
510
|
--kms-signing-key-file /usr/local/bin/kms-signing-public-key.pem \\
|
|
583
511
|
--userapi-url "{{userAPIURL}}" \\
|
|
@@ -588,187 +516,93 @@ if /usr/local/bin/kms-client \\
|
|
|
588
516
|
else
|
|
589
517
|
echo "compute-source-env.sh: ERROR - Failed to fetch environment variables from KMS"
|
|
590
518
|
echo "compute-source-env.sh: Exiting - cannot start user workload without KMS secrets"
|
|
591
|
-
echo "ECLOUD_FAIL kms_bootstrap"
|
|
592
519
|
exit 1
|
|
593
520
|
fi
|
|
594
521
|
|
|
595
|
-
#
|
|
596
|
-
# produced fullchain/privkey into $1's output directory ($2). Returns
|
|
597
|
-
# 0 on success, non-zero on any failure (caller decides whether that's
|
|
598
|
-
# fatal). tls-keygen writes to /run/tls/{fullchain,privkey}.pem by
|
|
599
|
-
# default; we move those to a per-host subdirectory so the two-site
|
|
600
|
-
# Caddyfile can select the right cert by path.
|
|
601
|
-
issue_cert_for() {
|
|
602
|
-
local host="$1"
|
|
603
|
-
local cert_dir="$2"
|
|
604
|
-
local mnemonic="$3"
|
|
605
|
-
local challenge="$4"
|
|
606
|
-
local staging_flag="$5"
|
|
607
|
-
|
|
608
|
-
echo "compute-source-env.sh: Obtaining TLS certificate for $host (challenge=$challenge)..."
|
|
609
|
-
# Remove any stale default outputs from a prior tls-keygen run
|
|
610
|
-
rm -f /run/tls/fullchain.pem /run/tls/privkey.pem
|
|
611
|
-
if ! MNEMONIC="$mnemonic" DOMAIN="$host" API_URL="{{userAPIURL}}" /usr/local/bin/tls-keygen \\
|
|
612
|
-
-challenge "$challenge" \\
|
|
613
|
-
$staging_flag; then
|
|
614
|
-
return 1
|
|
615
|
-
fi
|
|
616
|
-
mkdir -p "$cert_dir"
|
|
617
|
-
mv /run/tls/fullchain.pem "$cert_dir/fullchain.pem"
|
|
618
|
-
mv /run/tls/privkey.pem "$cert_dir/privkey.pem"
|
|
619
|
-
echo "compute-source-env.sh: Cert for $host written to $cert_dir"
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
# Setup TLS: issues certs for
|
|
623
|
-
# - ECLOUD_PLATFORM_HOST (platform-routed <addr>.<env>.eigencloud.xyz),
|
|
624
|
-
# when the CLI/platform has set it
|
|
625
|
-
# - DOMAIN (user-supplied custom domain), when set and non-localhost
|
|
626
|
-
#
|
|
627
|
-
# No client-side DNS precheck. Earlier versions tried to gate ACME on
|
|
628
|
-
# "does this hostname resolve to my external IP" but that's wrong for
|
|
629
|
-
# the platform-routing model (DNS points at the shared nginx NLB, not
|
|
630
|
-
# the VM) and was preventing cert issuance on the production path.
|
|
631
|
-
# tls-client (eigencompute-containers/tls-client) does its own DNS
|
|
632
|
-
# poll before calling ACME and surfaces a clear error when challenges
|
|
633
|
-
# can't reach the VM, which is the right place for that check \u2014
|
|
634
|
-
# attempting it here from inside the VM cannot tell platform-routed
|
|
635
|
-
# from compute-tee-routed apps.
|
|
522
|
+
# Setup TLS if tls-keygen is present (which means TLS was configured at build time)
|
|
636
523
|
setup_tls() {
|
|
637
524
|
# If tls-keygen isn't present, TLS wasn't configured during build
|
|
638
525
|
if [ ! -x /usr/local/bin/tls-keygen ]; then
|
|
639
526
|
echo "compute-source-env.sh: TLS not configured (no tls-keygen binary)"
|
|
640
527
|
return 0
|
|
641
528
|
fi
|
|
642
|
-
|
|
643
|
-
local
|
|
644
|
-
local user_domain="\${DOMAIN:-}"
|
|
529
|
+
|
|
530
|
+
local domain="\${DOMAIN:-}"
|
|
645
531
|
local mnemonic="\${MNEMONIC:-}"
|
|
646
|
-
|
|
647
|
-
#
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
# If the user set DOMAIN to the same value as the platform
|
|
654
|
-
# hostname, collapse them. Without this we'd burn a second ACME
|
|
655
|
-
# issuance for the exact same name (each VM boot counts against
|
|
656
|
-
# Let's Encrypt's 5-certs-per-domain-per-week limit), and Caddy
|
|
657
|
-
# would then refuse to start because two site blocks bound to
|
|
658
|
-
# the same address is a config error. Also unset DOMAIN so the
|
|
659
|
-
# DOMAIN site block in the Caddyfile falls back to its
|
|
660
|
-
# "localhost.user.invalid" placeholder and stays dormant.
|
|
661
|
-
if [ -n "$platform_host" ] && [ "$user_domain" = "$platform_host" ]; then
|
|
662
|
-
echo "compute-source-env.sh: DOMAIN matches ECLOUD_PLATFORM_HOST; skipping duplicate cert"
|
|
663
|
-
user_domain=""
|
|
664
|
-
unset DOMAIN
|
|
665
|
-
fi
|
|
666
|
-
|
|
667
|
-
if [ -z "$platform_host" ] && [ -z "$user_domain" ]; then
|
|
668
|
-
echo "compute-source-env.sh: TLS skipped (neither ECLOUD_PLATFORM_HOST nor DOMAIN set)"
|
|
669
|
-
return 0
|
|
532
|
+
|
|
533
|
+
# Since tls-keygen is present, TLS is expected - validate requirements
|
|
534
|
+
if [ -z "$domain" ] || [ "$domain" = "localhost" ]; then
|
|
535
|
+
echo "compute-source-env.sh: ERROR - TLS binary present but DOMAIN not configured or is localhost"
|
|
536
|
+
echo "compute-source-env.sh: Set DOMAIN environment variable to a valid domain"
|
|
537
|
+
exit 1
|
|
670
538
|
fi
|
|
671
|
-
|
|
539
|
+
|
|
672
540
|
if [ -z "$mnemonic" ]; then
|
|
673
|
-
echo "compute-source-env.sh: ERROR - TLS
|
|
674
|
-
echo "
|
|
541
|
+
echo "compute-source-env.sh: ERROR - TLS binary present but MNEMONIC not available"
|
|
542
|
+
echo "compute-source-env.sh: Cannot obtain TLS certificate without mnemonic"
|
|
675
543
|
exit 1
|
|
676
544
|
fi
|
|
677
|
-
|
|
545
|
+
|
|
678
546
|
if [ ! -x /usr/local/bin/caddy ]; then
|
|
679
|
-
echo "compute-source-env.sh: ERROR - TLS
|
|
680
|
-
echo "ECLOUD_FAIL tls_caddy_missing"
|
|
547
|
+
echo "compute-source-env.sh: ERROR - TLS binary present but Caddy not found"
|
|
681
548
|
exit 1
|
|
682
549
|
fi
|
|
683
|
-
|
|
550
|
+
|
|
551
|
+
echo "compute-source-env.sh: Setting up TLS for domain: $domain"
|
|
552
|
+
|
|
553
|
+
# Obtain TLS certificate using ACME
|
|
554
|
+
# Default to http-01, but allow override via ACME_CHALLENGE env var
|
|
684
555
|
local challenge="\${ACME_CHALLENGE:-http-01}"
|
|
556
|
+
|
|
557
|
+
# Check if we should use staging (for testing)
|
|
685
558
|
local staging_flag=""
|
|
686
559
|
if [ "\${ACME_STAGING:-false}" = "true" ]; then
|
|
687
560
|
staging_flag="-staging"
|
|
688
|
-
echo "compute-source-env.sh: Using Let's Encrypt STAGING environment"
|
|
689
|
-
fi
|
|
690
|
-
|
|
691
|
-
local certs_issued=0
|
|
692
|
-
|
|
693
|
-
if [ -n "$platform_host" ]; then
|
|
694
|
-
if issue_cert_for "$platform_host" "/run/tls/platform" "$mnemonic" "$challenge" "$staging_flag"; then
|
|
695
|
-
certs_issued=$((certs_issued + 1))
|
|
696
|
-
else
|
|
697
|
-
echo "compute-source-env.sh: ERROR - failed to issue cert for platform host $platform_host"
|
|
698
|
-
echo "ECLOUD_FAIL tls_setup"
|
|
699
|
-
exit 1
|
|
700
|
-
fi
|
|
701
|
-
fi
|
|
702
|
-
|
|
703
|
-
if [ -n "$user_domain" ]; then
|
|
704
|
-
if issue_cert_for "$user_domain" "/run/tls/domain" "$mnemonic" "$challenge" "$staging_flag"; then
|
|
705
|
-
certs_issued=$((certs_issued + 1))
|
|
706
|
-
else
|
|
707
|
-
echo "compute-source-env.sh: ERROR - failed to issue cert for user domain $user_domain"
|
|
708
|
-
echo "ECLOUD_FAIL tls_setup"
|
|
709
|
-
exit 1
|
|
710
|
-
fi
|
|
561
|
+
echo "compute-source-env.sh: Using Let's Encrypt STAGING environment (certificates won't be trusted)"
|
|
711
562
|
fi
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
563
|
+
|
|
564
|
+
echo "compute-source-env.sh: Obtaining TLS certificate using $challenge challenge..."
|
|
565
|
+
# Pass the API URL for certificate persistence
|
|
566
|
+
if ! SSL_CERT_FILE=/usr/local/share/eigenx-ca-certs.crt \\
|
|
567
|
+
MNEMONIC="$mnemonic" DOMAIN="$domain" API_URL="{{userAPIURL}}" /usr/local/bin/tls-keygen \\
|
|
568
|
+
-challenge "$challenge" \\
|
|
569
|
+
$staging_flag; then
|
|
570
|
+
echo "compute-source-env.sh: ERROR - Failed to obtain TLS certificate"
|
|
571
|
+
echo "compute-source-env.sh: Certificate issuance failed for $domain"
|
|
572
|
+
exit 1
|
|
716
573
|
fi
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
#
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
# receive real traffic (its hostname falls back to
|
|
726
|
-
# localhost.{platform,user}.invalid, which Caddy routes by SNI and
|
|
727
|
-
# never matches public traffic), so the symlink is never actually
|
|
728
|
-
# presented. Skipped when a user-supplied Caddyfile is in use,
|
|
729
|
-
# since we don't know what cert paths it references.
|
|
730
|
-
if [ -d /run/tls/platform ] && [ ! -e /run/tls/domain/fullchain.pem ]; then
|
|
731
|
-
mkdir -p /run/tls/domain
|
|
732
|
-
ln -sf /run/tls/platform/fullchain.pem /run/tls/domain/fullchain.pem
|
|
733
|
-
ln -sf /run/tls/platform/privkey.pem /run/tls/domain/privkey.pem
|
|
734
|
-
elif [ -d /run/tls/domain ] && [ ! -e /run/tls/platform/fullchain.pem ]; then
|
|
735
|
-
mkdir -p /run/tls/platform
|
|
736
|
-
ln -sf /run/tls/domain/fullchain.pem /run/tls/platform/fullchain.pem
|
|
737
|
-
ln -sf /run/tls/domain/privkey.pem /run/tls/platform/privkey.pem
|
|
574
|
+
|
|
575
|
+
echo "compute-source-env.sh: TLS certificate obtained successfully"
|
|
576
|
+
|
|
577
|
+
# Validate Caddyfile before starting
|
|
578
|
+
if ! /usr/local/bin/caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile 2>/dev/null; then
|
|
579
|
+
echo "compute-source-env.sh: ERROR - Invalid Caddyfile"
|
|
580
|
+
echo "compute-source-env.sh: TLS was requested (DOMAIN=$domain) but setup failed"
|
|
581
|
+
exit 1
|
|
738
582
|
fi
|
|
739
|
-
|
|
740
|
-
#
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
#
|
|
744
|
-
if [
|
|
745
|
-
if ! /usr/local/bin/caddy
|
|
746
|
-
echo "compute-source-env.sh: ERROR -
|
|
747
|
-
echo "
|
|
583
|
+
|
|
584
|
+
# Start Caddy in background
|
|
585
|
+
echo "compute-source-env.sh: Starting Caddy reverse proxy..."
|
|
586
|
+
|
|
587
|
+
# Check if Caddy logs should be enabled
|
|
588
|
+
if [ "\${ENABLE_CADDY_LOGS:-false}" = "true" ]; then
|
|
589
|
+
if ! /usr/local/bin/caddy start --config /etc/caddy/Caddyfile --adapter caddyfile 2>&1; then
|
|
590
|
+
echo "compute-source-env.sh: ERROR - Failed to start Caddy"
|
|
591
|
+
echo "compute-source-env.sh: TLS was requested (DOMAIN=$domain) but setup failed"
|
|
748
592
|
exit 1
|
|
749
593
|
fi
|
|
750
|
-
|
|
751
|
-
echo "compute-source-env.sh: Starting Caddy reverse proxy..."
|
|
752
|
-
if [ "\${ENABLE_CADDY_LOGS:-false}" = "true" ]; then
|
|
753
|
-
if ! /usr/local/bin/caddy start --config /etc/caddy/Caddyfile --adapter caddyfile 2>&1; then
|
|
754
|
-
echo "compute-source-env.sh: ERROR - Failed to start Caddy"
|
|
755
|
-
echo "ECLOUD_FAIL tls_caddy_start"
|
|
756
|
-
exit 1
|
|
757
|
-
fi
|
|
758
|
-
else
|
|
759
|
-
if ! /usr/local/bin/caddy start --config /etc/caddy/Caddyfile --adapter caddyfile >/dev/null 2>&1; then
|
|
760
|
-
echo "compute-source-env.sh: ERROR - Failed to start Caddy"
|
|
761
|
-
echo "ECLOUD_FAIL tls_caddy_start"
|
|
762
|
-
exit 1
|
|
763
|
-
fi
|
|
764
|
-
fi
|
|
765
|
-
|
|
766
|
-
sleep 2
|
|
767
|
-
echo "compute-source-env.sh: Caddy started successfully"
|
|
768
594
|
else
|
|
769
|
-
|
|
595
|
+
# Redirect Caddy output to /dev/null to silence logs
|
|
596
|
+
if ! /usr/local/bin/caddy start --config /etc/caddy/Caddyfile --adapter caddyfile >/dev/null 2>&1; then
|
|
597
|
+
echo "compute-source-env.sh: ERROR - Failed to start Caddy"
|
|
598
|
+
echo "compute-source-env.sh: TLS was requested (DOMAIN=$domain) but setup failed"
|
|
599
|
+
exit 1
|
|
600
|
+
fi
|
|
770
601
|
fi
|
|
771
|
-
|
|
602
|
+
|
|
603
|
+
# Give Caddy a moment to fully initialize
|
|
604
|
+
sleep 2
|
|
605
|
+
echo "compute-source-env.sh: Caddy started successfully"
|
|
772
606
|
return 0
|
|
773
607
|
}
|
|
774
608
|
|
|
@@ -779,233 +613,15 @@ setup_tls
|
|
|
779
613
|
export KMS_SERVER_URL="{{kmsServerURL}}"
|
|
780
614
|
export KMS_PUBLIC_KEY="$(cat /usr/local/bin/kms-signing-public-key.pem)"
|
|
781
615
|
|
|
782
|
-
# \u2500\u2500 Prewarm-detach: wait for PD if expected \u2500\u2500
|
|
783
|
-
# Orchestrator sets ECLOUD_PD_EXPECTED=1 on apps using StorageBackend=pd.
|
|
784
|
-
# When the prewarm path is used, the new VM boots WITHOUT the disk; we
|
|
785
|
-
# signal awaiting-userdata and poll until the disk is attached.
|
|
786
|
-
USERDATA_MOUNT="/mnt/disks/userdata"
|
|
787
|
-
USERDATA_DEV="/dev/disk/by-id/google-persistent_storage_1"
|
|
788
|
-
|
|
789
|
-
wait_for_userdata() {
|
|
790
|
-
if [ "\${ECLOUD_PD_EXPECTED:-0}" != "1" ]; then
|
|
791
|
-
return 0
|
|
792
|
-
fi
|
|
793
|
-
if mountpoint -q "$USERDATA_MOUNT" 2>/dev/null; then
|
|
794
|
-
echo "compute-source-env.sh: userdata already mounted at $USERDATA_MOUNT"
|
|
795
|
-
return 0
|
|
796
|
-
fi
|
|
797
|
-
# Refuse to proceed if the tools we need for safe first-attach
|
|
798
|
-
# detection are missing. Without blkid we cannot tell an empty new
|
|
799
|
-
# disk from an already-formatted one \u2014 running mkfs.ext4 on the
|
|
800
|
-
# latter would destroy data.
|
|
801
|
-
if ! command -v blkid >/dev/null 2>&1; then
|
|
802
|
-
echo "ECLOUD_FAIL pd_tools_missing"
|
|
803
|
-
exit 1
|
|
804
|
-
fi
|
|
805
|
-
echo "ECLOUD_AWAITING_USERDATA"
|
|
806
|
-
echo "compute-source-env.sh: waiting for PD at $USERDATA_DEV..."
|
|
807
|
-
# Poll for up to 10 minutes (120 * 5s). The orchestrator's overall
|
|
808
|
-
# attach timeout is shorter; the ceiling here just bounds the wait
|
|
809
|
-
# for manual / diagnostic scenarios.
|
|
810
|
-
local i=0
|
|
811
|
-
local mount_failures=0
|
|
812
|
-
while [ "$i" -lt 120 ]; do
|
|
813
|
-
if [ -e "$USERDATA_DEV" ]; then
|
|
814
|
-
mkdir -p "$USERDATA_MOUNT"
|
|
815
|
-
if mount -o noatime "$USERDATA_DEV" "$USERDATA_MOUNT" 2>/dev/null; then
|
|
816
|
-
echo "compute-source-env.sh: PD mounted at $USERDATA_MOUNT"
|
|
817
|
-
return 0
|
|
818
|
-
fi
|
|
819
|
-
# Disk present but mount failed. Check whether it has a
|
|
820
|
-
# recognized filesystem. \`blkid -s TYPE -o value\` prints the
|
|
821
|
-
# FS type (empty if none). We only mkfs when there is
|
|
822
|
-
# demonstrably NO filesystem \u2014 never on the basis of blkid
|
|
823
|
-
# returning non-zero alone, which could mean "blkid missing"
|
|
824
|
-
# or "device busy".
|
|
825
|
-
local fstype
|
|
826
|
-
fstype=$(blkid -s TYPE -o value "$USERDATA_DEV" 2>/dev/null)
|
|
827
|
-
if [ -z "$fstype" ]; then
|
|
828
|
-
echo "compute-source-env.sh: formatting $USERDATA_DEV (first attach)"
|
|
829
|
-
mkfs.ext4 -F -L eclouddata "$USERDATA_DEV" >/dev/null 2>&1 || {
|
|
830
|
-
echo "ECLOUD_FAIL pd_mkfs_failed"
|
|
831
|
-
exit 1
|
|
832
|
-
}
|
|
833
|
-
mount -o noatime "$USERDATA_DEV" "$USERDATA_MOUNT" || {
|
|
834
|
-
echo "ECLOUD_FAIL pd_mount_after_format_failed"
|
|
835
|
-
exit 1
|
|
836
|
-
}
|
|
837
|
-
return 0
|
|
838
|
-
fi
|
|
839
|
-
# Disk has a filesystem but mount still failed. Give it a
|
|
840
|
-
# few retries to cover transient cases (device busy, udev
|
|
841
|
-
# still settling), but don't pretend this is an attach
|
|
842
|
-
# timeout if it persists.
|
|
843
|
-
mount_failures=$((mount_failures + 1))
|
|
844
|
-
if [ "$mount_failures" -ge 6 ]; then
|
|
845
|
-
echo "ECLOUD_FAIL pd_mount_failed"
|
|
846
|
-
exit 1
|
|
847
|
-
fi
|
|
848
|
-
else
|
|
849
|
-
# Device disappeared (e.g. udev re-enumeration between
|
|
850
|
-
# attach and mount). Reset the consecutive-failure counter
|
|
851
|
-
# so only true back-to-back mount failures trip
|
|
852
|
-
# pd_mount_failed; a device blip should not steal retries.
|
|
853
|
-
mount_failures=0
|
|
854
|
-
fi
|
|
855
|
-
i=$((i + 1))
|
|
856
|
-
sleep 5
|
|
857
|
-
done
|
|
858
|
-
echo "ECLOUD_FAIL pd_attach_timeout"
|
|
859
|
-
exit 1
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
wait_for_userdata
|
|
863
|
-
|
|
864
|
-
# \u2500\u2500 Prewarm-detach: install SIGTERM handler for graceful drain \u2500\u2500
|
|
865
|
-
# Orchestrator signals drain by setting the instance metadata key
|
|
866
|
-
# ECLOUD_DRAIN_REQUESTED=1, which a host-level agent translates into
|
|
867
|
-
# SIGTERM on PID 1. On SIGTERM we:
|
|
868
|
-
# 1. Forward to the child (wakes the user's app for graceful exit)
|
|
869
|
-
# 2. Wait for child exit
|
|
870
|
-
# 3. Sync + unmount the PD
|
|
871
|
-
# 4. Emit ECLOUD_DETACHED so the orchestrator can proceed to detach
|
|
872
|
-
CHILD_PID=""
|
|
873
|
-
_DRAIN_IN_PROGRESS=0
|
|
874
|
-
|
|
875
|
-
drain_handler() {
|
|
876
|
-
# Guard against re-entry if SIGTERM arrives twice (e.g. both the
|
|
877
|
-
# drain_watcher and an external signal fire in quick succession).
|
|
878
|
-
if [ "$_DRAIN_IN_PROGRESS" = "1" ]; then
|
|
879
|
-
return 0
|
|
880
|
-
fi
|
|
881
|
-
_DRAIN_IN_PROGRESS=1
|
|
882
|
-
echo "compute-source-env.sh: received drain signal, forwarding to child pgid=$CHILD_PID"
|
|
883
|
-
if [ -n "$CHILD_PID" ]; then
|
|
884
|
-
# Send to the process group so intermediate wrappers (su, sh -c,
|
|
885
|
-
# etc.) don't swallow the signal. The leading \`-\` targets the
|
|
886
|
-
# pgid, which equals the direct child's pid for a shell-backgrounded
|
|
887
|
-
# process. Fall back to the pid alone if pgid signaling fails
|
|
888
|
-
# (e.g. kernel older than 3.9 or PID namespace edge cases).
|
|
889
|
-
kill -TERM -"$CHILD_PID" 2>/dev/null || kill -TERM "$CHILD_PID" 2>/dev/null || true
|
|
890
|
-
# Give the app up to 30s to exit cleanly.
|
|
891
|
-
local i=0
|
|
892
|
-
while [ "$i" -lt 30 ] && kill -0 "$CHILD_PID" 2>/dev/null; do
|
|
893
|
-
i=$((i + 1))
|
|
894
|
-
sleep 1
|
|
895
|
-
done
|
|
896
|
-
if kill -0 "$CHILD_PID" 2>/dev/null; then
|
|
897
|
-
echo "compute-source-env.sh: child did not exit in 30s, sending SIGKILL"
|
|
898
|
-
kill -KILL -"$CHILD_PID" 2>/dev/null || kill -KILL "$CHILD_PID" 2>/dev/null || true
|
|
899
|
-
# Reap the process so its in-flight I/O is flushed to the
|
|
900
|
-
# filesystem before we sync + unmount. SIGKILL schedules
|
|
901
|
-
# death; wait guarantees it's complete.
|
|
902
|
-
wait "$CHILD_PID" 2>/dev/null || true
|
|
903
|
-
fi
|
|
904
|
-
fi
|
|
905
|
-
if [ "\${ECLOUD_PD_EXPECTED:-0}" = "1" ] && mountpoint -q "$USERDATA_MOUNT" 2>/dev/null; then
|
|
906
|
-
sync
|
|
907
|
-
if umount "$USERDATA_MOUNT" 2>/dev/null; then
|
|
908
|
-
echo "compute-source-env.sh: unmounted $USERDATA_MOUNT cleanly"
|
|
909
|
-
else
|
|
910
|
-
# Force lazy unmount as last resort \u2014 orchestrator still needs
|
|
911
|
-
# the DETACHED signal to proceed.
|
|
912
|
-
umount -l "$USERDATA_MOUNT" 2>/dev/null || true
|
|
913
|
-
echo "compute-source-env.sh: WARNING - used lazy unmount on $USERDATA_MOUNT"
|
|
914
|
-
fi
|
|
915
|
-
# ECLOUD_DETACHED is strictly a PD-lifecycle signal. Only emit
|
|
916
|
-
# it when we actually had a PD mount in play, so serial-log
|
|
917
|
-
# parsers and alerting for non-PD apps don't see spurious
|
|
918
|
-
# lifecycle markers on routine container SIGTERM.
|
|
919
|
-
echo "ECLOUD_DETACHED"
|
|
920
|
-
fi
|
|
921
|
-
# Always exit 0: drain is a managed shutdown and the orchestrator
|
|
922
|
-
# waits on ECLOUD_DETACHED, not the container exit code. Forwarding
|
|
923
|
-
# the child's exit status here would make a crash-during-drain look
|
|
924
|
-
# like a drain failure to whatever reads the container exit code.
|
|
925
|
-
exit 0
|
|
926
|
-
}
|
|
927
|
-
trap drain_handler TERM
|
|
928
|
-
|
|
929
|
-
# \u2500\u2500 Prewarm-detach: background drain watcher \u2500\u2500
|
|
930
|
-
# Container metadata delivery in Confidential Space is limited, so we
|
|
931
|
-
# poll the instance metadata server for ECLOUD_DRAIN_REQUESTED and
|
|
932
|
-
# raise SIGTERM on ourselves when it flips to "1".
|
|
933
|
-
#
|
|
934
|
-
# Try wget first (present in most Alpine bases), fall back to curl.
|
|
935
|
-
# If neither is present, drain watcher is disabled \u2014 the orchestrator
|
|
936
|
-
# will hit its drain timeout and fail the upgrade explicitly, which is
|
|
937
|
-
# the correct behavior (we cannot silently ignore a drain request).
|
|
938
|
-
_fetch_drain_flag() {
|
|
939
|
-
local url="http://metadata.google.internal/computeMetadata/v1/instance/attributes/ECLOUD_DRAIN_REQUESTED"
|
|
940
|
-
if command -v wget >/dev/null 2>&1; then
|
|
941
|
-
wget -q --tries=1 --timeout=2 --header='Metadata-Flavor: Google' -O - "$url" 2>/dev/null
|
|
942
|
-
elif command -v curl >/dev/null 2>&1; then
|
|
943
|
-
curl -sf --max-time 2 -H 'Metadata-Flavor: Google' "$url" 2>/dev/null
|
|
944
|
-
else
|
|
945
|
-
return 2
|
|
946
|
-
fi
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
drain_watcher() {
|
|
950
|
-
# Preflight: confirm we have an HTTP client
|
|
951
|
-
if ! _fetch_drain_flag >/dev/null 2>&1; then
|
|
952
|
-
# Either no http client available OR metadata server not
|
|
953
|
-
# responding yet. If no client, give up and log; otherwise the
|
|
954
|
-
# loop below will retry.
|
|
955
|
-
if ! command -v wget >/dev/null 2>&1 && ! command -v curl >/dev/null 2>&1; then
|
|
956
|
-
echo "compute-source-env.sh: WARNING - no wget/curl; drain_watcher disabled"
|
|
957
|
-
return 0
|
|
958
|
-
fi
|
|
959
|
-
fi
|
|
960
|
-
while true; do
|
|
961
|
-
local v
|
|
962
|
-
v=$(_fetch_drain_flag || true)
|
|
963
|
-
if [ "$v" = "1" ]; then
|
|
964
|
-
echo "compute-source-env.sh: drain_watcher saw ECLOUD_DRAIN_REQUESTED=1, signaling PID 1"
|
|
965
|
-
# The CS launcher runs this script directly as PID 1, so
|
|
966
|
-
# kill -TERM 1 delivers SIGTERM to the shell that installed
|
|
967
|
-
# the drain_handler trap. If the launch mechanism ever
|
|
968
|
-
# wraps this script in another process, this assumption
|
|
969
|
-
# breaks and drain will silently no-op \u2014 audit here.
|
|
970
|
-
kill -TERM 1 2>/dev/null || true
|
|
971
|
-
return 0
|
|
972
|
-
fi
|
|
973
|
-
sleep 2
|
|
974
|
-
done
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
if [ "\${ECLOUD_PD_EXPECTED:-0}" = "1" ]; then
|
|
978
|
-
# Assumption: the orchestrator only flips ECLOUD_DRAIN_REQUESTED=1
|
|
979
|
-
# after observing ECLOUD_AWAITING_USERDATA (old VM) or
|
|
980
|
-
# ECLOUD_READY (new VM), so CHILD_PID is always set by the time
|
|
981
|
-
# drain_handler fires. If drain somehow arrived in the tiny window
|
|
982
|
-
# between this watcher spawn and CHILD_PID assignment below,
|
|
983
|
-
# drain_handler would skip the child-kill branch and still emit
|
|
984
|
-
# ECLOUD_DETACHED \u2014 harmless because there's nothing to drain yet.
|
|
985
|
-
if [ -x /usr/local/bin/ecloud-drain-watcher ]; then
|
|
986
|
-
/usr/local/bin/ecloud-drain-watcher &
|
|
987
|
-
else
|
|
988
|
-
drain_watcher &
|
|
989
|
-
fi
|
|
990
|
-
fi
|
|
991
|
-
|
|
992
616
|
echo "compute-source-env.sh: Environment sourced."
|
|
993
|
-
echo "ECLOUD_READY runtime_bootstrapped"
|
|
994
617
|
|
|
995
618
|
# Drop privileges to original user for the application command
|
|
996
619
|
if [ -n "$__ECLOUD_ORIGINAL_USER" ] && [ "$(id -u)" = "0" ]; then
|
|
997
620
|
echo "compute-source-env.sh: Dropping privileges to user: $__ECLOUD_ORIGINAL_USER"
|
|
998
|
-
|
|
999
|
-
su -s /bin/sh "$__ECLOUD_ORIGINAL_USER" -c 'exec "$@"' -- sh "$@" &
|
|
1000
|
-
CHILD_PID=$!
|
|
1001
|
-
wait "$CHILD_PID"
|
|
1002
|
-
exit $?
|
|
621
|
+
exec su -s /bin/sh "$__ECLOUD_ORIGINAL_USER" -c 'exec "$@"' -- sh "$@"
|
|
1003
622
|
fi
|
|
1004
623
|
|
|
1005
|
-
"$@"
|
|
1006
|
-
CHILD_PID=$!
|
|
1007
|
-
wait "$CHILD_PID"
|
|
1008
|
-
exit $?
|
|
624
|
+
exec "$@"
|
|
1009
625
|
`;
|
|
1010
626
|
|
|
1011
627
|
// src/client/common/templates/scriptTemplate.ts
|
|
@@ -1014,14 +630,6 @@ function processScriptTemplate(data) {
|
|
|
1014
630
|
return template(data);
|
|
1015
631
|
}
|
|
1016
632
|
|
|
1017
|
-
// src/client/common/templates/Caddyfile.default.tmpl
|
|
1018
|
-
var Caddyfile_default_default = '# Caddy configuration for automatic HTTPS\n#\n# Two sites can be configured at runtime via env vars that\n# ecloud-platform / the CLI inject into tee-env metadata:\n#\n# ECLOUD_PLATFORM_HOST \u2014 the platform-derived hostname\n# (<addr>.<env>.eigencloud.xyz). Always set\n# for platform-routed apps. Cert at\n# /run/tls/platform/fullchain.pem.\n# DOMAIN \u2014 optional user-supplied custom domain.\n# Cert at /run/tls/domain/fullchain.pem.\n#\n# When a variable is unset, Caddy substitutes the default listed\n# after the colon. We use distinct defaults per site so each block\n# binds to a unique name at bootstrap \u2014 both blocks overlapping\n# on "localhost" would cause Caddy to reject the config.\n{$ECLOUD_PLATFORM_HOST:localhost.platform.invalid} {\n tls /run/tls/platform/fullchain.pem /run/tls/platform/privkey.pem\n\n reverse_proxy localhost:{$APP_PORT:3000} {\n health_uri /health\n health_interval 30s\n health_timeout 5s\n health_status 200\n }\n\n header {\n X-Content-Type-Options "nosniff"\n X-Frame-Options "DENY"\n X-XSS-Protection "1; mode=block"\n Referrer-Policy "strict-origin-when-cross-origin"\n -Server\n }\n\n log {\n output stdout\n format console\n level INFO\n }\n\n request_body {\n max_size 10MB\n }\n}\n\n{$DOMAIN:localhost.user.invalid} {\n tls /run/tls/domain/fullchain.pem /run/tls/domain/privkey.pem\n\n reverse_proxy localhost:{$APP_PORT:3000} {\n health_uri /health\n health_interval 30s\n health_timeout 5s\n health_status 200\n }\n\n header {\n X-Content-Type-Options "nosniff"\n X-Frame-Options "DENY"\n X-XSS-Protection "1; mode=block"\n Referrer-Policy "strict-origin-when-cross-origin"\n -Server\n }\n\n log {\n output stdout\n format console\n level INFO\n }\n\n request_body {\n max_size 10MB\n }\n}\n\n# HTTP endpoint (optional, for health checks or redirects)\n:80 {\n # Redirect to HTTPS for any real (non-placeholder) host\n @for_domain expression {host} != "localhost.platform.invalid" && {host} != "localhost.user.invalid" && {host} != "localhost"\n redir @for_domain https://{host}{uri} permanent\n\n # Health check endpoint (always available via HTTP)\n handle /health {\n respond "OK" 200\n }\n}\n';
|
|
1019
|
-
|
|
1020
|
-
// src/client/common/templates/caddyfileTemplate.ts
|
|
1021
|
-
function getDefaultCaddyfile() {
|
|
1022
|
-
return Caddyfile_default_default;
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
633
|
// keys/mainnet-alpha/prod/kms-encryption-public-key.pem
|
|
1026
634
|
var kms_encryption_public_key_default = "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0kHU86k17ofCIGcJKDcf\nAFurFhSLeWmOL0bwWLCeVnTPG0MMHtJOq+woE0XXSWw6lzm+jzavBBTwKde1dgal\nAp91vULAZFMUpiUdd2dNUVtvU89qW0Pgf1Eu5FDj7BkY/SnyECbWJM4ga0BmpiGy\nnQwLNN9mMGhjVoVLn2zwEGZ7JzS9Nz11EZKO/k/9DcO6LaoIFmKuvVf3jl6lvZg8\naeA0LoZXjkycHlRUt/kfKwZnhakUaYHP1ksV7ZNmolS5GYDTSKGB2KPPNR1s4/Xu\nu8zeEFC8HuGRU8XuuBeaAunitnGhbNVREUNJGff6HZOGB6CIFNXjbQETeZ3p5uro\n0v+hd1QqQYBv7+DEaMCmGnJNGAyIMr2mn4vr7wGsIj0HonlSHmQ8rmdUhL2ocNTc\nLhKgZiZmBuDpSbFW/r53R2G7CHcqaqGeUBnT54QCH4zsYKw0/4dOtwFxQpTyBf9/\n+k+KaWEJYKkx9d9OzKGyAvzrTDVOFoajddiJ6LPvRlMdOUQr3hl4IAC0/nh9lhHq\nD0R+i5WAU96TkdAe7B7iTGH2D22k0KUPR6Q9W3aF353SLxQAMPNrgG4QQufAdRJn\nAF+8ntun5TkTqjTWRSwAsUJZ1z4wb96DympWJbDi0OciJRZ3Fz3j9+amC43yCHGg\naaEMjdt35ewbztUSc04F10MCAwEAAQ==\n-----END PUBLIC KEY-----";
|
|
1027
635
|
|
|
@@ -1196,9 +804,15 @@ async function layerLocalImage(options, logger) {
|
|
|
1196
804
|
const imageConfig = await extractImageConfig(docker, sourceImageRef);
|
|
1197
805
|
const originalCmd = imageConfig.cmd.length > 0 ? imageConfig.cmd : imageConfig.entrypoint;
|
|
1198
806
|
const originalUser = imageConfig.user;
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
807
|
+
let includeTLS = false;
|
|
808
|
+
if (envFilePath && fs.existsSync(envFilePath)) {
|
|
809
|
+
const envContent = fs.readFileSync(envFilePath, "utf-8");
|
|
810
|
+
const domainMatch = envContent.match(/^DOMAIN=(.+)$/m);
|
|
811
|
+
if (domainMatch && domainMatch[1] && domainMatch[1] !== "localhost") {
|
|
812
|
+
includeTLS = true;
|
|
813
|
+
logger.debug(`Found DOMAIN=${domainMatch[1]} in ${envFilePath}, including TLS components`);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
1202
816
|
const layeredDockerfileContent = processDockerfileTemplate({
|
|
1203
817
|
baseImage: sourceImageRef,
|
|
1204
818
|
originalCmd: JSON.stringify(originalCmd),
|
|
@@ -1206,9 +820,8 @@ async function layerLocalImage(options, logger) {
|
|
|
1206
820
|
logRedirect,
|
|
1207
821
|
resourceUsageAllow,
|
|
1208
822
|
includeTLS,
|
|
1209
|
-
ecloudCLIVersion: "0.1.0"
|
|
823
|
+
ecloudCLIVersion: "0.1.0"
|
|
1210
824
|
// TODO: Get from package.json
|
|
1211
|
-
includeDrainWatcher
|
|
1212
825
|
});
|
|
1213
826
|
const scriptContent = processScriptTemplate({
|
|
1214
827
|
kmsServerURL: environmentConfig.kmsServerURL,
|
|
@@ -1218,8 +831,7 @@ async function layerLocalImage(options, logger) {
|
|
|
1218
831
|
environmentConfig,
|
|
1219
832
|
layeredDockerfileContent,
|
|
1220
833
|
scriptContent,
|
|
1221
|
-
includeTLS
|
|
1222
|
-
includeDrainWatcher ? drainWatcherSource : void 0
|
|
834
|
+
includeTLS
|
|
1223
835
|
// logger
|
|
1224
836
|
);
|
|
1225
837
|
try {
|
|
@@ -1234,7 +846,7 @@ async function layerLocalImage(options, logger) {
|
|
|
1234
846
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
1235
847
|
}
|
|
1236
848
|
}
|
|
1237
|
-
async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileContent, scriptContent, includeTLS
|
|
849
|
+
async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileContent, scriptContent, includeTLS) {
|
|
1238
850
|
const tempDir = fs.mkdtempSync(path2.join(os.tmpdir(), LAYERED_BUILD_DIR_PREFIX));
|
|
1239
851
|
try {
|
|
1240
852
|
const layeredDockerfilePath = path2.join(tempDir, LAYERED_DOCKERFILE_NAME);
|
|
@@ -1258,11 +870,6 @@ async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileCo
|
|
|
1258
870
|
}
|
|
1259
871
|
fs.copyFileSync(kmsClientSource, kmsClientPath);
|
|
1260
872
|
fs.chmodSync(kmsClientPath, 493);
|
|
1261
|
-
if (drainWatcherSource && fs.existsSync(drainWatcherSource)) {
|
|
1262
|
-
const drainWatcherPath = path2.join(tempDir, DRAIN_WATCHER_BINARY_NAME);
|
|
1263
|
-
fs.copyFileSync(drainWatcherSource, drainWatcherPath);
|
|
1264
|
-
fs.chmodSync(drainWatcherPath, 493);
|
|
1265
|
-
}
|
|
1266
873
|
if (includeTLS) {
|
|
1267
874
|
const tlsKeygenPath = path2.join(tempDir, TLS_KEYGEN_BINARY_NAME);
|
|
1268
875
|
const tlsKeygenSource = findBinary("tls-keygen-linux-amd64");
|
|
@@ -1273,13 +880,15 @@ async function setupLayeredBuildDirectory(environmentConfig, layeredDockerfileCo
|
|
|
1273
880
|
}
|
|
1274
881
|
fs.copyFileSync(tlsKeygenSource, tlsKeygenPath);
|
|
1275
882
|
fs.chmodSync(tlsKeygenPath, 493);
|
|
1276
|
-
const
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
fs.
|
|
883
|
+
const caddyfilePath = path2.join(process.cwd(), CADDYFILE_NAME);
|
|
884
|
+
if (fs.existsSync(caddyfilePath)) {
|
|
885
|
+
const caddyfileContent = fs.readFileSync(caddyfilePath);
|
|
886
|
+
const destCaddyfilePath = path2.join(tempDir, CADDYFILE_NAME);
|
|
887
|
+
fs.writeFileSync(destCaddyfilePath, caddyfileContent, { mode: 420 });
|
|
1281
888
|
} else {
|
|
1282
|
-
|
|
889
|
+
throw new Error(
|
|
890
|
+
"TLS is enabled (DOMAIN is set) but Caddyfile not found. Run configure TLS to set up TLS configuration"
|
|
891
|
+
);
|
|
1283
892
|
}
|
|
1284
893
|
}
|
|
1285
894
|
return tempDir;
|
|
@@ -1347,16 +956,7 @@ async function extractDigestFromSinglePlatform(manifest, imageRef) {
|
|
|
1347
956
|
architecture: inspectData[0].Architecture
|
|
1348
957
|
} : null;
|
|
1349
958
|
if (!config) {
|
|
1350
|
-
|
|
1351
|
-
const digest = hexStringToBytes32(manifest.config.digest);
|
|
1352
|
-
const registry = extractRegistryName(imageRef);
|
|
1353
|
-
return {
|
|
1354
|
-
digest,
|
|
1355
|
-
registry,
|
|
1356
|
-
platform: DOCKER_PLATFORM
|
|
1357
|
-
};
|
|
1358
|
-
}
|
|
1359
|
-
throw new Error(`Could not determine platform for ${imageRef}`);
|
|
959
|
+
throw createPlatformErrorMessage(imageRef, ["unknown (could not determine architecture)"]);
|
|
1360
960
|
}
|
|
1361
961
|
const platform2 = `${config.os}/${config.architecture}`;
|
|
1362
962
|
if (platform2 === DOCKER_PLATFORM) {
|
|
@@ -1428,14 +1028,11 @@ Image: ${imageRef}
|
|
|
1428
1028
|
Found platform(s): ${platforms.join(", ")}
|
|
1429
1029
|
Required platform: ${DOCKER_PLATFORM}
|
|
1430
1030
|
|
|
1431
|
-
To fix
|
|
1432
|
-
1.
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
docker push ${imageRef}
|
|
1437
|
-
|
|
1438
|
-
2. Or use the SDK to build with the correct platform automatically.`;
|
|
1031
|
+
To fix, either:
|
|
1032
|
+
1. Rebuild the image for ${DOCKER_PLATFORM} and push it:
|
|
1033
|
+
docker buildx build --platform ${DOCKER_PLATFORM} -t ${imageRef} --push .
|
|
1034
|
+
2. Or use a verifiable build (--verifiable --repo <repo> --commit <sha>), which
|
|
1035
|
+
builds server-side and needs no local Docker.`;
|
|
1439
1036
|
return new Error(errorMsg);
|
|
1440
1037
|
}
|
|
1441
1038
|
|
|
@@ -1540,6 +1137,8 @@ async function prepareRelease(options, logger) {
|
|
|
1540
1137
|
logger.info(`Waiting ${REGISTRY_PROPAGATION_WAIT_SECONDS} seconds for registry propagation...`);
|
|
1541
1138
|
await new Promise((resolve2) => setTimeout(resolve2, REGISTRY_PROPAGATION_WAIT_SECONDS * 1e3));
|
|
1542
1139
|
} else {
|
|
1140
|
+
logger.info("Verifying image platform (linux/amd64)...");
|
|
1141
|
+
await getImageDigestAndName(imageRef);
|
|
1543
1142
|
logger.info("Checking if image needs layering...");
|
|
1544
1143
|
finalImageRef = await layerRemoteImageIfNeeded(
|
|
1545
1144
|
{
|
|
@@ -1698,6 +1297,13 @@ function extractRegistryNameNoDocker(imageRef) {
|
|
|
1698
1297
|
import { encodeFunctionData, encodeAbiParameters, decodeErrorResult } from "viem";
|
|
1699
1298
|
|
|
1700
1299
|
// src/client/common/types/index.ts
|
|
1300
|
+
var EMPTY_CONTAINER_POLICY = {
|
|
1301
|
+
args: [],
|
|
1302
|
+
cmdOverride: [],
|
|
1303
|
+
env: [],
|
|
1304
|
+
envOverride: [],
|
|
1305
|
+
restartPolicy: ""
|
|
1306
|
+
};
|
|
1701
1307
|
var noopLogger = {
|
|
1702
1308
|
debug: () => {
|
|
1703
1309
|
},
|
|
@@ -2938,32 +2544,1577 @@ async function executeBatch(options, logger = noopLogger) {
|
|
|
2938
2544
|
} else {
|
|
2939
2545
|
revertReason = callError.message || "Unknown reason";
|
|
2940
2546
|
}
|
|
2941
|
-
}
|
|
2942
|
-
throw new Error(`Transaction reverted: ${hash}. Reason: ${revertReason}`);
|
|
2547
|
+
}
|
|
2548
|
+
throw new Error(`Transaction reverted: ${hash}. Reason: ${revertReason}`);
|
|
2549
|
+
}
|
|
2550
|
+
return hash;
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2553
|
+
// src/client/common/contract/caller.ts
|
|
2554
|
+
import { encodeFunctionData as encodeFunctionData2, decodeErrorResult as decodeErrorResult2, bytesToHex } from "viem";
|
|
2555
|
+
|
|
2556
|
+
// src/client/common/utils/helpers.ts
|
|
2557
|
+
import { extractChain, createPublicClient, createWalletClient, http, fallback } from "viem";
|
|
2558
|
+
import { sepolia as sepolia2 } from "viem/chains";
|
|
2559
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
2560
|
+
function getChainFromID(chainID, fallback2 = sepolia2) {
|
|
2561
|
+
const id = Number(chainID);
|
|
2562
|
+
return extractChain({ chains: SUPPORTED_CHAINS, id }) || fallback2;
|
|
2563
|
+
}
|
|
2564
|
+
function addHexPrefix(value) {
|
|
2565
|
+
return value.startsWith("0x") ? value : `0x${value}`;
|
|
2566
|
+
}
|
|
2567
|
+
function stripHexPrefix(value) {
|
|
2568
|
+
return value.startsWith("0x") ? value.slice(2) : value;
|
|
2569
|
+
}
|
|
2570
|
+
|
|
2571
|
+
// src/client/common/abis/AppController.json
|
|
2572
|
+
var AppController_default = [
|
|
2573
|
+
{
|
|
2574
|
+
type: "constructor",
|
|
2575
|
+
inputs: [
|
|
2576
|
+
{
|
|
2577
|
+
name: "_version",
|
|
2578
|
+
type: "string",
|
|
2579
|
+
internalType: "string"
|
|
2580
|
+
},
|
|
2581
|
+
{
|
|
2582
|
+
name: "_permissionController",
|
|
2583
|
+
type: "address",
|
|
2584
|
+
internalType: "contractIPermissionController"
|
|
2585
|
+
},
|
|
2586
|
+
{
|
|
2587
|
+
name: "_releaseManager",
|
|
2588
|
+
type: "address",
|
|
2589
|
+
internalType: "contractIReleaseManager"
|
|
2590
|
+
},
|
|
2591
|
+
{
|
|
2592
|
+
name: "_computeAVSRegistrar",
|
|
2593
|
+
type: "address",
|
|
2594
|
+
internalType: "contractIComputeAVSRegistrar"
|
|
2595
|
+
},
|
|
2596
|
+
{
|
|
2597
|
+
name: "_computeOperator",
|
|
2598
|
+
type: "address",
|
|
2599
|
+
internalType: "contractIComputeOperator"
|
|
2600
|
+
},
|
|
2601
|
+
{
|
|
2602
|
+
name: "_appBeacon",
|
|
2603
|
+
type: "address",
|
|
2604
|
+
internalType: "contractIBeacon"
|
|
2605
|
+
}
|
|
2606
|
+
],
|
|
2607
|
+
stateMutability: "nonpayable"
|
|
2608
|
+
},
|
|
2609
|
+
{
|
|
2610
|
+
type: "function",
|
|
2611
|
+
name: "API_PERMISSION_TYPEHASH",
|
|
2612
|
+
inputs: [],
|
|
2613
|
+
outputs: [
|
|
2614
|
+
{
|
|
2615
|
+
name: "",
|
|
2616
|
+
type: "bytes32",
|
|
2617
|
+
internalType: "bytes32"
|
|
2618
|
+
}
|
|
2619
|
+
],
|
|
2620
|
+
stateMutability: "view"
|
|
2621
|
+
},
|
|
2622
|
+
{
|
|
2623
|
+
type: "function",
|
|
2624
|
+
name: "appBeacon",
|
|
2625
|
+
inputs: [],
|
|
2626
|
+
outputs: [
|
|
2627
|
+
{
|
|
2628
|
+
name: "",
|
|
2629
|
+
type: "address",
|
|
2630
|
+
internalType: "contractIBeacon"
|
|
2631
|
+
}
|
|
2632
|
+
],
|
|
2633
|
+
stateMutability: "view"
|
|
2634
|
+
},
|
|
2635
|
+
{
|
|
2636
|
+
type: "function",
|
|
2637
|
+
name: "calculateApiPermissionDigestHash",
|
|
2638
|
+
inputs: [
|
|
2639
|
+
{
|
|
2640
|
+
name: "permission",
|
|
2641
|
+
type: "bytes4",
|
|
2642
|
+
internalType: "bytes4"
|
|
2643
|
+
},
|
|
2644
|
+
{
|
|
2645
|
+
name: "expiry",
|
|
2646
|
+
type: "uint256",
|
|
2647
|
+
internalType: "uint256"
|
|
2648
|
+
}
|
|
2649
|
+
],
|
|
2650
|
+
outputs: [
|
|
2651
|
+
{
|
|
2652
|
+
name: "",
|
|
2653
|
+
type: "bytes32",
|
|
2654
|
+
internalType: "bytes32"
|
|
2655
|
+
}
|
|
2656
|
+
],
|
|
2657
|
+
stateMutability: "view"
|
|
2658
|
+
},
|
|
2659
|
+
{
|
|
2660
|
+
type: "function",
|
|
2661
|
+
name: "calculateAppId",
|
|
2662
|
+
inputs: [
|
|
2663
|
+
{
|
|
2664
|
+
name: "deployer",
|
|
2665
|
+
type: "address",
|
|
2666
|
+
internalType: "address"
|
|
2667
|
+
},
|
|
2668
|
+
{
|
|
2669
|
+
name: "salt",
|
|
2670
|
+
type: "bytes32",
|
|
2671
|
+
internalType: "bytes32"
|
|
2672
|
+
}
|
|
2673
|
+
],
|
|
2674
|
+
outputs: [
|
|
2675
|
+
{
|
|
2676
|
+
name: "",
|
|
2677
|
+
type: "address",
|
|
2678
|
+
internalType: "contractIApp"
|
|
2679
|
+
}
|
|
2680
|
+
],
|
|
2681
|
+
stateMutability: "view"
|
|
2682
|
+
},
|
|
2683
|
+
{
|
|
2684
|
+
type: "function",
|
|
2685
|
+
name: "computeAVSRegistrar",
|
|
2686
|
+
inputs: [],
|
|
2687
|
+
outputs: [
|
|
2688
|
+
{
|
|
2689
|
+
name: "",
|
|
2690
|
+
type: "address",
|
|
2691
|
+
internalType: "contractIComputeAVSRegistrar"
|
|
2692
|
+
}
|
|
2693
|
+
],
|
|
2694
|
+
stateMutability: "view"
|
|
2695
|
+
},
|
|
2696
|
+
{
|
|
2697
|
+
type: "function",
|
|
2698
|
+
name: "computeOperator",
|
|
2699
|
+
inputs: [],
|
|
2700
|
+
outputs: [
|
|
2701
|
+
{
|
|
2702
|
+
name: "",
|
|
2703
|
+
type: "address",
|
|
2704
|
+
internalType: "contractIComputeOperator"
|
|
2705
|
+
}
|
|
2706
|
+
],
|
|
2707
|
+
stateMutability: "view"
|
|
2708
|
+
},
|
|
2709
|
+
{
|
|
2710
|
+
type: "function",
|
|
2711
|
+
name: "confirmUpgrade",
|
|
2712
|
+
inputs: [
|
|
2713
|
+
{
|
|
2714
|
+
name: "app",
|
|
2715
|
+
type: "address",
|
|
2716
|
+
internalType: "contractIApp"
|
|
2717
|
+
}
|
|
2718
|
+
],
|
|
2719
|
+
outputs: [],
|
|
2720
|
+
stateMutability: "nonpayable"
|
|
2721
|
+
},
|
|
2722
|
+
{
|
|
2723
|
+
type: "function",
|
|
2724
|
+
name: "createApp",
|
|
2725
|
+
inputs: [
|
|
2726
|
+
{
|
|
2727
|
+
name: "salt",
|
|
2728
|
+
type: "bytes32",
|
|
2729
|
+
internalType: "bytes32"
|
|
2730
|
+
},
|
|
2731
|
+
{
|
|
2732
|
+
name: "release",
|
|
2733
|
+
type: "tuple",
|
|
2734
|
+
internalType: "structIAppController.Release",
|
|
2735
|
+
components: [
|
|
2736
|
+
{
|
|
2737
|
+
name: "rmsRelease",
|
|
2738
|
+
type: "tuple",
|
|
2739
|
+
internalType: "structIReleaseManagerTypes.Release",
|
|
2740
|
+
components: [
|
|
2741
|
+
{
|
|
2742
|
+
name: "artifacts",
|
|
2743
|
+
type: "tuple[]",
|
|
2744
|
+
internalType: "structIReleaseManagerTypes.Artifact[]",
|
|
2745
|
+
components: [
|
|
2746
|
+
{
|
|
2747
|
+
name: "digest",
|
|
2748
|
+
type: "bytes32",
|
|
2749
|
+
internalType: "bytes32"
|
|
2750
|
+
},
|
|
2751
|
+
{
|
|
2752
|
+
name: "registry",
|
|
2753
|
+
type: "string",
|
|
2754
|
+
internalType: "string"
|
|
2755
|
+
}
|
|
2756
|
+
]
|
|
2757
|
+
},
|
|
2758
|
+
{
|
|
2759
|
+
name: "upgradeByTime",
|
|
2760
|
+
type: "uint32",
|
|
2761
|
+
internalType: "uint32"
|
|
2762
|
+
}
|
|
2763
|
+
]
|
|
2764
|
+
},
|
|
2765
|
+
{
|
|
2766
|
+
name: "publicEnv",
|
|
2767
|
+
type: "bytes",
|
|
2768
|
+
internalType: "bytes"
|
|
2769
|
+
},
|
|
2770
|
+
{
|
|
2771
|
+
name: "encryptedEnv",
|
|
2772
|
+
type: "bytes",
|
|
2773
|
+
internalType: "bytes"
|
|
2774
|
+
},
|
|
2775
|
+
{
|
|
2776
|
+
name: "containerPolicy",
|
|
2777
|
+
type: "tuple",
|
|
2778
|
+
internalType: "structIAppController.ContainerPolicy",
|
|
2779
|
+
components: [
|
|
2780
|
+
{
|
|
2781
|
+
name: "args",
|
|
2782
|
+
type: "string[]",
|
|
2783
|
+
internalType: "string[]"
|
|
2784
|
+
},
|
|
2785
|
+
{
|
|
2786
|
+
name: "cmdOverride",
|
|
2787
|
+
type: "string[]",
|
|
2788
|
+
internalType: "string[]"
|
|
2789
|
+
},
|
|
2790
|
+
{
|
|
2791
|
+
name: "env",
|
|
2792
|
+
type: "tuple[]",
|
|
2793
|
+
internalType: "structIAppController.EnvVar[]",
|
|
2794
|
+
components: [
|
|
2795
|
+
{
|
|
2796
|
+
name: "key",
|
|
2797
|
+
type: "string",
|
|
2798
|
+
internalType: "string"
|
|
2799
|
+
},
|
|
2800
|
+
{
|
|
2801
|
+
name: "value",
|
|
2802
|
+
type: "string",
|
|
2803
|
+
internalType: "string"
|
|
2804
|
+
}
|
|
2805
|
+
]
|
|
2806
|
+
},
|
|
2807
|
+
{
|
|
2808
|
+
name: "envOverride",
|
|
2809
|
+
type: "tuple[]",
|
|
2810
|
+
internalType: "structIAppController.EnvVar[]",
|
|
2811
|
+
components: [
|
|
2812
|
+
{
|
|
2813
|
+
name: "key",
|
|
2814
|
+
type: "string",
|
|
2815
|
+
internalType: "string"
|
|
2816
|
+
},
|
|
2817
|
+
{
|
|
2818
|
+
name: "value",
|
|
2819
|
+
type: "string",
|
|
2820
|
+
internalType: "string"
|
|
2821
|
+
}
|
|
2822
|
+
]
|
|
2823
|
+
},
|
|
2824
|
+
{
|
|
2825
|
+
name: "restartPolicy",
|
|
2826
|
+
type: "string",
|
|
2827
|
+
internalType: "string"
|
|
2828
|
+
}
|
|
2829
|
+
]
|
|
2830
|
+
}
|
|
2831
|
+
]
|
|
2832
|
+
}
|
|
2833
|
+
],
|
|
2834
|
+
outputs: [
|
|
2835
|
+
{
|
|
2836
|
+
name: "app",
|
|
2837
|
+
type: "address",
|
|
2838
|
+
internalType: "contractIApp"
|
|
2839
|
+
}
|
|
2840
|
+
],
|
|
2841
|
+
stateMutability: "nonpayable"
|
|
2842
|
+
},
|
|
2843
|
+
{
|
|
2844
|
+
type: "function",
|
|
2845
|
+
name: "createAppWithIsolatedBilling",
|
|
2846
|
+
inputs: [
|
|
2847
|
+
{
|
|
2848
|
+
name: "salt",
|
|
2849
|
+
type: "bytes32",
|
|
2850
|
+
internalType: "bytes32"
|
|
2851
|
+
},
|
|
2852
|
+
{
|
|
2853
|
+
name: "release",
|
|
2854
|
+
type: "tuple",
|
|
2855
|
+
internalType: "structIAppController.Release",
|
|
2856
|
+
components: [
|
|
2857
|
+
{
|
|
2858
|
+
name: "rmsRelease",
|
|
2859
|
+
type: "tuple",
|
|
2860
|
+
internalType: "structIReleaseManagerTypes.Release",
|
|
2861
|
+
components: [
|
|
2862
|
+
{
|
|
2863
|
+
name: "artifacts",
|
|
2864
|
+
type: "tuple[]",
|
|
2865
|
+
internalType: "structIReleaseManagerTypes.Artifact[]",
|
|
2866
|
+
components: [
|
|
2867
|
+
{
|
|
2868
|
+
name: "digest",
|
|
2869
|
+
type: "bytes32",
|
|
2870
|
+
internalType: "bytes32"
|
|
2871
|
+
},
|
|
2872
|
+
{
|
|
2873
|
+
name: "registry",
|
|
2874
|
+
type: "string",
|
|
2875
|
+
internalType: "string"
|
|
2876
|
+
}
|
|
2877
|
+
]
|
|
2878
|
+
},
|
|
2879
|
+
{
|
|
2880
|
+
name: "upgradeByTime",
|
|
2881
|
+
type: "uint32",
|
|
2882
|
+
internalType: "uint32"
|
|
2883
|
+
}
|
|
2884
|
+
]
|
|
2885
|
+
},
|
|
2886
|
+
{
|
|
2887
|
+
name: "publicEnv",
|
|
2888
|
+
type: "bytes",
|
|
2889
|
+
internalType: "bytes"
|
|
2890
|
+
},
|
|
2891
|
+
{
|
|
2892
|
+
name: "encryptedEnv",
|
|
2893
|
+
type: "bytes",
|
|
2894
|
+
internalType: "bytes"
|
|
2895
|
+
},
|
|
2896
|
+
{
|
|
2897
|
+
name: "containerPolicy",
|
|
2898
|
+
type: "tuple",
|
|
2899
|
+
internalType: "structIAppController.ContainerPolicy",
|
|
2900
|
+
components: [
|
|
2901
|
+
{
|
|
2902
|
+
name: "args",
|
|
2903
|
+
type: "string[]",
|
|
2904
|
+
internalType: "string[]"
|
|
2905
|
+
},
|
|
2906
|
+
{
|
|
2907
|
+
name: "cmdOverride",
|
|
2908
|
+
type: "string[]",
|
|
2909
|
+
internalType: "string[]"
|
|
2910
|
+
},
|
|
2911
|
+
{
|
|
2912
|
+
name: "env",
|
|
2913
|
+
type: "tuple[]",
|
|
2914
|
+
internalType: "structIAppController.EnvVar[]",
|
|
2915
|
+
components: [
|
|
2916
|
+
{
|
|
2917
|
+
name: "key",
|
|
2918
|
+
type: "string",
|
|
2919
|
+
internalType: "string"
|
|
2920
|
+
},
|
|
2921
|
+
{
|
|
2922
|
+
name: "value",
|
|
2923
|
+
type: "string",
|
|
2924
|
+
internalType: "string"
|
|
2925
|
+
}
|
|
2926
|
+
]
|
|
2927
|
+
},
|
|
2928
|
+
{
|
|
2929
|
+
name: "envOverride",
|
|
2930
|
+
type: "tuple[]",
|
|
2931
|
+
internalType: "structIAppController.EnvVar[]",
|
|
2932
|
+
components: [
|
|
2933
|
+
{
|
|
2934
|
+
name: "key",
|
|
2935
|
+
type: "string",
|
|
2936
|
+
internalType: "string"
|
|
2937
|
+
},
|
|
2938
|
+
{
|
|
2939
|
+
name: "value",
|
|
2940
|
+
type: "string",
|
|
2941
|
+
internalType: "string"
|
|
2942
|
+
}
|
|
2943
|
+
]
|
|
2944
|
+
},
|
|
2945
|
+
{
|
|
2946
|
+
name: "restartPolicy",
|
|
2947
|
+
type: "string",
|
|
2948
|
+
internalType: "string"
|
|
2949
|
+
}
|
|
2950
|
+
]
|
|
2951
|
+
}
|
|
2952
|
+
]
|
|
2953
|
+
}
|
|
2954
|
+
],
|
|
2955
|
+
outputs: [
|
|
2956
|
+
{
|
|
2957
|
+
name: "app",
|
|
2958
|
+
type: "address",
|
|
2959
|
+
internalType: "contractIApp"
|
|
2960
|
+
}
|
|
2961
|
+
],
|
|
2962
|
+
stateMutability: "nonpayable"
|
|
2963
|
+
},
|
|
2964
|
+
{
|
|
2965
|
+
type: "function",
|
|
2966
|
+
name: "createEmptyApp",
|
|
2967
|
+
inputs: [
|
|
2968
|
+
{
|
|
2969
|
+
name: "salt",
|
|
2970
|
+
type: "bytes32",
|
|
2971
|
+
internalType: "bytes32"
|
|
2972
|
+
}
|
|
2973
|
+
],
|
|
2974
|
+
outputs: [
|
|
2975
|
+
{
|
|
2976
|
+
name: "app",
|
|
2977
|
+
type: "address",
|
|
2978
|
+
internalType: "contractIApp"
|
|
2979
|
+
}
|
|
2980
|
+
],
|
|
2981
|
+
stateMutability: "nonpayable"
|
|
2982
|
+
},
|
|
2983
|
+
{
|
|
2984
|
+
type: "function",
|
|
2985
|
+
name: "createEmptyAppWithIsolatedBilling",
|
|
2986
|
+
inputs: [
|
|
2987
|
+
{
|
|
2988
|
+
name: "salt",
|
|
2989
|
+
type: "bytes32",
|
|
2990
|
+
internalType: "bytes32"
|
|
2991
|
+
}
|
|
2992
|
+
],
|
|
2993
|
+
outputs: [
|
|
2994
|
+
{
|
|
2995
|
+
name: "app",
|
|
2996
|
+
type: "address",
|
|
2997
|
+
internalType: "contractIApp"
|
|
2998
|
+
}
|
|
2999
|
+
],
|
|
3000
|
+
stateMutability: "nonpayable"
|
|
3001
|
+
},
|
|
3002
|
+
{
|
|
3003
|
+
type: "function",
|
|
3004
|
+
name: "domainSeparator",
|
|
3005
|
+
inputs: [],
|
|
3006
|
+
outputs: [
|
|
3007
|
+
{
|
|
3008
|
+
name: "",
|
|
3009
|
+
type: "bytes32",
|
|
3010
|
+
internalType: "bytes32"
|
|
3011
|
+
}
|
|
3012
|
+
],
|
|
3013
|
+
stateMutability: "view"
|
|
3014
|
+
},
|
|
3015
|
+
{
|
|
3016
|
+
type: "function",
|
|
3017
|
+
name: "getActiveAppCount",
|
|
3018
|
+
inputs: [
|
|
3019
|
+
{
|
|
3020
|
+
name: "user",
|
|
3021
|
+
type: "address",
|
|
3022
|
+
internalType: "address"
|
|
3023
|
+
}
|
|
3024
|
+
],
|
|
3025
|
+
outputs: [
|
|
3026
|
+
{
|
|
3027
|
+
name: "",
|
|
3028
|
+
type: "uint32",
|
|
3029
|
+
internalType: "uint32"
|
|
3030
|
+
}
|
|
3031
|
+
],
|
|
3032
|
+
stateMutability: "view"
|
|
3033
|
+
},
|
|
3034
|
+
{
|
|
3035
|
+
type: "function",
|
|
3036
|
+
name: "getAppCreator",
|
|
3037
|
+
inputs: [
|
|
3038
|
+
{
|
|
3039
|
+
name: "app",
|
|
3040
|
+
type: "address",
|
|
3041
|
+
internalType: "contractIApp"
|
|
3042
|
+
}
|
|
3043
|
+
],
|
|
3044
|
+
outputs: [
|
|
3045
|
+
{
|
|
3046
|
+
name: "",
|
|
3047
|
+
type: "address",
|
|
3048
|
+
internalType: "address"
|
|
3049
|
+
}
|
|
3050
|
+
],
|
|
3051
|
+
stateMutability: "view"
|
|
3052
|
+
},
|
|
3053
|
+
{
|
|
3054
|
+
type: "function",
|
|
3055
|
+
name: "getAppLatestReleaseBlockNumber",
|
|
3056
|
+
inputs: [
|
|
3057
|
+
{
|
|
3058
|
+
name: "app",
|
|
3059
|
+
type: "address",
|
|
3060
|
+
internalType: "contractIApp"
|
|
3061
|
+
}
|
|
3062
|
+
],
|
|
3063
|
+
outputs: [
|
|
3064
|
+
{
|
|
3065
|
+
name: "",
|
|
3066
|
+
type: "uint32",
|
|
3067
|
+
internalType: "uint32"
|
|
3068
|
+
}
|
|
3069
|
+
],
|
|
3070
|
+
stateMutability: "view"
|
|
3071
|
+
},
|
|
3072
|
+
{
|
|
3073
|
+
type: "function",
|
|
3074
|
+
name: "getAppOperatorSetId",
|
|
3075
|
+
inputs: [
|
|
3076
|
+
{
|
|
3077
|
+
name: "app",
|
|
3078
|
+
type: "address",
|
|
3079
|
+
internalType: "contractIApp"
|
|
3080
|
+
}
|
|
3081
|
+
],
|
|
3082
|
+
outputs: [
|
|
3083
|
+
{
|
|
3084
|
+
name: "",
|
|
3085
|
+
type: "uint32",
|
|
3086
|
+
internalType: "uint32"
|
|
3087
|
+
}
|
|
3088
|
+
],
|
|
3089
|
+
stateMutability: "view"
|
|
3090
|
+
},
|
|
3091
|
+
{
|
|
3092
|
+
type: "function",
|
|
3093
|
+
name: "getAppPendingReleaseBlockNumber",
|
|
3094
|
+
inputs: [
|
|
3095
|
+
{
|
|
3096
|
+
name: "app",
|
|
3097
|
+
type: "address",
|
|
3098
|
+
internalType: "contractIApp"
|
|
3099
|
+
}
|
|
3100
|
+
],
|
|
3101
|
+
outputs: [
|
|
3102
|
+
{
|
|
3103
|
+
name: "",
|
|
3104
|
+
type: "uint32",
|
|
3105
|
+
internalType: "uint32"
|
|
3106
|
+
}
|
|
3107
|
+
],
|
|
3108
|
+
stateMutability: "view"
|
|
3109
|
+
},
|
|
3110
|
+
{
|
|
3111
|
+
type: "function",
|
|
3112
|
+
name: "getAppStatus",
|
|
3113
|
+
inputs: [
|
|
3114
|
+
{
|
|
3115
|
+
name: "app",
|
|
3116
|
+
type: "address",
|
|
3117
|
+
internalType: "contractIApp"
|
|
3118
|
+
}
|
|
3119
|
+
],
|
|
3120
|
+
outputs: [
|
|
3121
|
+
{
|
|
3122
|
+
name: "",
|
|
3123
|
+
type: "uint8",
|
|
3124
|
+
internalType: "enumIAppController.AppStatus"
|
|
3125
|
+
}
|
|
3126
|
+
],
|
|
3127
|
+
stateMutability: "view"
|
|
3128
|
+
},
|
|
3129
|
+
{
|
|
3130
|
+
type: "function",
|
|
3131
|
+
name: "getApps",
|
|
3132
|
+
inputs: [
|
|
3133
|
+
{
|
|
3134
|
+
name: "offset",
|
|
3135
|
+
type: "uint256",
|
|
3136
|
+
internalType: "uint256"
|
|
3137
|
+
},
|
|
3138
|
+
{
|
|
3139
|
+
name: "limit",
|
|
3140
|
+
type: "uint256",
|
|
3141
|
+
internalType: "uint256"
|
|
3142
|
+
}
|
|
3143
|
+
],
|
|
3144
|
+
outputs: [
|
|
3145
|
+
{
|
|
3146
|
+
name: "apps",
|
|
3147
|
+
type: "address[]",
|
|
3148
|
+
internalType: "contractIApp[]"
|
|
3149
|
+
},
|
|
3150
|
+
{
|
|
3151
|
+
name: "appConfigsMem",
|
|
3152
|
+
type: "tuple[]",
|
|
3153
|
+
internalType: "structIAppController.AppConfig[]",
|
|
3154
|
+
components: [
|
|
3155
|
+
{
|
|
3156
|
+
name: "creator",
|
|
3157
|
+
type: "address",
|
|
3158
|
+
internalType: "address"
|
|
3159
|
+
},
|
|
3160
|
+
{
|
|
3161
|
+
name: "operatorSetId",
|
|
3162
|
+
type: "uint32",
|
|
3163
|
+
internalType: "uint32"
|
|
3164
|
+
},
|
|
3165
|
+
{
|
|
3166
|
+
name: "latestReleaseBlockNumber",
|
|
3167
|
+
type: "uint32",
|
|
3168
|
+
internalType: "uint32"
|
|
3169
|
+
},
|
|
3170
|
+
{
|
|
3171
|
+
name: "pendingReleaseBlockNumber",
|
|
3172
|
+
type: "uint32",
|
|
3173
|
+
internalType: "uint32"
|
|
3174
|
+
},
|
|
3175
|
+
{
|
|
3176
|
+
name: "status",
|
|
3177
|
+
type: "uint8",
|
|
3178
|
+
internalType: "enumIAppController.AppStatus"
|
|
3179
|
+
}
|
|
3180
|
+
]
|
|
3181
|
+
}
|
|
3182
|
+
],
|
|
3183
|
+
stateMutability: "view"
|
|
3184
|
+
},
|
|
3185
|
+
{
|
|
3186
|
+
type: "function",
|
|
3187
|
+
name: "getAppsByBillingAccount",
|
|
3188
|
+
inputs: [
|
|
3189
|
+
{
|
|
3190
|
+
name: "account",
|
|
3191
|
+
type: "address",
|
|
3192
|
+
internalType: "address"
|
|
3193
|
+
},
|
|
3194
|
+
{
|
|
3195
|
+
name: "offset",
|
|
3196
|
+
type: "uint256",
|
|
3197
|
+
internalType: "uint256"
|
|
3198
|
+
},
|
|
3199
|
+
{
|
|
3200
|
+
name: "limit",
|
|
3201
|
+
type: "uint256",
|
|
3202
|
+
internalType: "uint256"
|
|
3203
|
+
}
|
|
3204
|
+
],
|
|
3205
|
+
outputs: [
|
|
3206
|
+
{
|
|
3207
|
+
name: "apps",
|
|
3208
|
+
type: "address[]",
|
|
3209
|
+
internalType: "contractIApp[]"
|
|
3210
|
+
},
|
|
3211
|
+
{
|
|
3212
|
+
name: "appConfigsMem",
|
|
3213
|
+
type: "tuple[]",
|
|
3214
|
+
internalType: "structIAppController.AppConfig[]",
|
|
3215
|
+
components: [
|
|
3216
|
+
{
|
|
3217
|
+
name: "creator",
|
|
3218
|
+
type: "address",
|
|
3219
|
+
internalType: "address"
|
|
3220
|
+
},
|
|
3221
|
+
{
|
|
3222
|
+
name: "operatorSetId",
|
|
3223
|
+
type: "uint32",
|
|
3224
|
+
internalType: "uint32"
|
|
3225
|
+
},
|
|
3226
|
+
{
|
|
3227
|
+
name: "latestReleaseBlockNumber",
|
|
3228
|
+
type: "uint32",
|
|
3229
|
+
internalType: "uint32"
|
|
3230
|
+
},
|
|
3231
|
+
{
|
|
3232
|
+
name: "pendingReleaseBlockNumber",
|
|
3233
|
+
type: "uint32",
|
|
3234
|
+
internalType: "uint32"
|
|
3235
|
+
},
|
|
3236
|
+
{
|
|
3237
|
+
name: "status",
|
|
3238
|
+
type: "uint8",
|
|
3239
|
+
internalType: "enumIAppController.AppStatus"
|
|
3240
|
+
}
|
|
3241
|
+
]
|
|
3242
|
+
}
|
|
3243
|
+
],
|
|
3244
|
+
stateMutability: "view"
|
|
3245
|
+
},
|
|
3246
|
+
{
|
|
3247
|
+
type: "function",
|
|
3248
|
+
name: "getAppsByCreator",
|
|
3249
|
+
inputs: [
|
|
3250
|
+
{
|
|
3251
|
+
name: "creator",
|
|
3252
|
+
type: "address",
|
|
3253
|
+
internalType: "address"
|
|
3254
|
+
},
|
|
3255
|
+
{
|
|
3256
|
+
name: "offset",
|
|
3257
|
+
type: "uint256",
|
|
3258
|
+
internalType: "uint256"
|
|
3259
|
+
},
|
|
3260
|
+
{
|
|
3261
|
+
name: "limit",
|
|
3262
|
+
type: "uint256",
|
|
3263
|
+
internalType: "uint256"
|
|
3264
|
+
}
|
|
3265
|
+
],
|
|
3266
|
+
outputs: [
|
|
3267
|
+
{
|
|
3268
|
+
name: "apps",
|
|
3269
|
+
type: "address[]",
|
|
3270
|
+
internalType: "contractIApp[]"
|
|
3271
|
+
},
|
|
3272
|
+
{
|
|
3273
|
+
name: "appConfigsMem",
|
|
3274
|
+
type: "tuple[]",
|
|
3275
|
+
internalType: "structIAppController.AppConfig[]",
|
|
3276
|
+
components: [
|
|
3277
|
+
{
|
|
3278
|
+
name: "creator",
|
|
3279
|
+
type: "address",
|
|
3280
|
+
internalType: "address"
|
|
3281
|
+
},
|
|
3282
|
+
{
|
|
3283
|
+
name: "operatorSetId",
|
|
3284
|
+
type: "uint32",
|
|
3285
|
+
internalType: "uint32"
|
|
3286
|
+
},
|
|
3287
|
+
{
|
|
3288
|
+
name: "latestReleaseBlockNumber",
|
|
3289
|
+
type: "uint32",
|
|
3290
|
+
internalType: "uint32"
|
|
3291
|
+
},
|
|
3292
|
+
{
|
|
3293
|
+
name: "pendingReleaseBlockNumber",
|
|
3294
|
+
type: "uint32",
|
|
3295
|
+
internalType: "uint32"
|
|
3296
|
+
},
|
|
3297
|
+
{
|
|
3298
|
+
name: "status",
|
|
3299
|
+
type: "uint8",
|
|
3300
|
+
internalType: "enumIAppController.AppStatus"
|
|
3301
|
+
}
|
|
3302
|
+
]
|
|
3303
|
+
}
|
|
3304
|
+
],
|
|
3305
|
+
stateMutability: "view"
|
|
3306
|
+
},
|
|
3307
|
+
{
|
|
3308
|
+
type: "function",
|
|
3309
|
+
name: "getAppsByDeveloper",
|
|
3310
|
+
inputs: [
|
|
3311
|
+
{
|
|
3312
|
+
name: "developer",
|
|
3313
|
+
type: "address",
|
|
3314
|
+
internalType: "address"
|
|
3315
|
+
},
|
|
3316
|
+
{
|
|
3317
|
+
name: "offset",
|
|
3318
|
+
type: "uint256",
|
|
3319
|
+
internalType: "uint256"
|
|
3320
|
+
},
|
|
3321
|
+
{
|
|
3322
|
+
name: "limit",
|
|
3323
|
+
type: "uint256",
|
|
3324
|
+
internalType: "uint256"
|
|
3325
|
+
}
|
|
3326
|
+
],
|
|
3327
|
+
outputs: [
|
|
3328
|
+
{
|
|
3329
|
+
name: "apps",
|
|
3330
|
+
type: "address[]",
|
|
3331
|
+
internalType: "contractIApp[]"
|
|
3332
|
+
},
|
|
3333
|
+
{
|
|
3334
|
+
name: "appConfigsMem",
|
|
3335
|
+
type: "tuple[]",
|
|
3336
|
+
internalType: "structIAppController.AppConfig[]",
|
|
3337
|
+
components: [
|
|
3338
|
+
{
|
|
3339
|
+
name: "creator",
|
|
3340
|
+
type: "address",
|
|
3341
|
+
internalType: "address"
|
|
3342
|
+
},
|
|
3343
|
+
{
|
|
3344
|
+
name: "operatorSetId",
|
|
3345
|
+
type: "uint32",
|
|
3346
|
+
internalType: "uint32"
|
|
3347
|
+
},
|
|
3348
|
+
{
|
|
3349
|
+
name: "latestReleaseBlockNumber",
|
|
3350
|
+
type: "uint32",
|
|
3351
|
+
internalType: "uint32"
|
|
3352
|
+
},
|
|
3353
|
+
{
|
|
3354
|
+
name: "pendingReleaseBlockNumber",
|
|
3355
|
+
type: "uint32",
|
|
3356
|
+
internalType: "uint32"
|
|
3357
|
+
},
|
|
3358
|
+
{
|
|
3359
|
+
name: "status",
|
|
3360
|
+
type: "uint8",
|
|
3361
|
+
internalType: "enumIAppController.AppStatus"
|
|
3362
|
+
}
|
|
3363
|
+
]
|
|
3364
|
+
}
|
|
3365
|
+
],
|
|
3366
|
+
stateMutability: "view"
|
|
3367
|
+
},
|
|
3368
|
+
{
|
|
3369
|
+
type: "function",
|
|
3370
|
+
name: "getBillingAccount",
|
|
3371
|
+
inputs: [
|
|
3372
|
+
{
|
|
3373
|
+
name: "app",
|
|
3374
|
+
type: "address",
|
|
3375
|
+
internalType: "contractIApp"
|
|
3376
|
+
}
|
|
3377
|
+
],
|
|
3378
|
+
outputs: [
|
|
3379
|
+
{
|
|
3380
|
+
name: "",
|
|
3381
|
+
type: "address",
|
|
3382
|
+
internalType: "address"
|
|
3383
|
+
}
|
|
3384
|
+
],
|
|
3385
|
+
stateMutability: "view"
|
|
3386
|
+
},
|
|
3387
|
+
{
|
|
3388
|
+
type: "function",
|
|
3389
|
+
name: "getBillingType",
|
|
3390
|
+
inputs: [
|
|
3391
|
+
{
|
|
3392
|
+
name: "app",
|
|
3393
|
+
type: "address",
|
|
3394
|
+
internalType: "contractIApp"
|
|
3395
|
+
}
|
|
3396
|
+
],
|
|
3397
|
+
outputs: [
|
|
3398
|
+
{
|
|
3399
|
+
name: "",
|
|
3400
|
+
type: "uint8",
|
|
3401
|
+
internalType: "enumIAppController.BillingType"
|
|
3402
|
+
}
|
|
3403
|
+
],
|
|
3404
|
+
stateMutability: "view"
|
|
3405
|
+
},
|
|
3406
|
+
{
|
|
3407
|
+
type: "function",
|
|
3408
|
+
name: "getMaxActiveAppsPerUser",
|
|
3409
|
+
inputs: [
|
|
3410
|
+
{
|
|
3411
|
+
name: "user",
|
|
3412
|
+
type: "address",
|
|
3413
|
+
internalType: "address"
|
|
3414
|
+
}
|
|
3415
|
+
],
|
|
3416
|
+
outputs: [
|
|
3417
|
+
{
|
|
3418
|
+
name: "",
|
|
3419
|
+
type: "uint32",
|
|
3420
|
+
internalType: "uint32"
|
|
3421
|
+
}
|
|
3422
|
+
],
|
|
3423
|
+
stateMutability: "view"
|
|
3424
|
+
},
|
|
3425
|
+
{
|
|
3426
|
+
type: "function",
|
|
3427
|
+
name: "globalActiveAppCount",
|
|
3428
|
+
inputs: [],
|
|
3429
|
+
outputs: [
|
|
3430
|
+
{
|
|
3431
|
+
name: "",
|
|
3432
|
+
type: "uint32",
|
|
3433
|
+
internalType: "uint32"
|
|
3434
|
+
}
|
|
3435
|
+
],
|
|
3436
|
+
stateMutability: "view"
|
|
3437
|
+
},
|
|
3438
|
+
{
|
|
3439
|
+
type: "function",
|
|
3440
|
+
name: "initialize",
|
|
3441
|
+
inputs: [
|
|
3442
|
+
{
|
|
3443
|
+
name: "admin",
|
|
3444
|
+
type: "address",
|
|
3445
|
+
internalType: "address"
|
|
3446
|
+
}
|
|
3447
|
+
],
|
|
3448
|
+
outputs: [],
|
|
3449
|
+
stateMutability: "nonpayable"
|
|
3450
|
+
},
|
|
3451
|
+
{
|
|
3452
|
+
type: "function",
|
|
3453
|
+
name: "maxGlobalActiveApps",
|
|
3454
|
+
inputs: [],
|
|
3455
|
+
outputs: [
|
|
3456
|
+
{
|
|
3457
|
+
name: "",
|
|
3458
|
+
type: "uint32",
|
|
3459
|
+
internalType: "uint32"
|
|
3460
|
+
}
|
|
3461
|
+
],
|
|
3462
|
+
stateMutability: "view"
|
|
3463
|
+
},
|
|
3464
|
+
{
|
|
3465
|
+
type: "function",
|
|
3466
|
+
name: "permissionController",
|
|
3467
|
+
inputs: [],
|
|
3468
|
+
outputs: [
|
|
3469
|
+
{
|
|
3470
|
+
name: "",
|
|
3471
|
+
type: "address",
|
|
3472
|
+
internalType: "contractIPermissionController"
|
|
3473
|
+
}
|
|
3474
|
+
],
|
|
3475
|
+
stateMutability: "view"
|
|
3476
|
+
},
|
|
3477
|
+
{
|
|
3478
|
+
type: "function",
|
|
3479
|
+
name: "releaseManager",
|
|
3480
|
+
inputs: [],
|
|
3481
|
+
outputs: [
|
|
3482
|
+
{
|
|
3483
|
+
name: "",
|
|
3484
|
+
type: "address",
|
|
3485
|
+
internalType: "contractIReleaseManager"
|
|
3486
|
+
}
|
|
3487
|
+
],
|
|
3488
|
+
stateMutability: "view"
|
|
3489
|
+
},
|
|
3490
|
+
{
|
|
3491
|
+
type: "function",
|
|
3492
|
+
name: "setMaxActiveAppsPerUser",
|
|
3493
|
+
inputs: [
|
|
3494
|
+
{
|
|
3495
|
+
name: "user",
|
|
3496
|
+
type: "address",
|
|
3497
|
+
internalType: "address"
|
|
3498
|
+
},
|
|
3499
|
+
{
|
|
3500
|
+
name: "limit",
|
|
3501
|
+
type: "uint32",
|
|
3502
|
+
internalType: "uint32"
|
|
3503
|
+
}
|
|
3504
|
+
],
|
|
3505
|
+
outputs: [],
|
|
3506
|
+
stateMutability: "nonpayable"
|
|
3507
|
+
},
|
|
3508
|
+
{
|
|
3509
|
+
type: "function",
|
|
3510
|
+
name: "setMaxGlobalActiveApps",
|
|
3511
|
+
inputs: [
|
|
3512
|
+
{
|
|
3513
|
+
name: "limit",
|
|
3514
|
+
type: "uint32",
|
|
3515
|
+
internalType: "uint32"
|
|
3516
|
+
}
|
|
3517
|
+
],
|
|
3518
|
+
outputs: [],
|
|
3519
|
+
stateMutability: "nonpayable"
|
|
3520
|
+
},
|
|
3521
|
+
{
|
|
3522
|
+
type: "function",
|
|
3523
|
+
name: "startApp",
|
|
3524
|
+
inputs: [
|
|
3525
|
+
{
|
|
3526
|
+
name: "app",
|
|
3527
|
+
type: "address",
|
|
3528
|
+
internalType: "contractIApp"
|
|
3529
|
+
}
|
|
3530
|
+
],
|
|
3531
|
+
outputs: [],
|
|
3532
|
+
stateMutability: "nonpayable"
|
|
3533
|
+
},
|
|
3534
|
+
{
|
|
3535
|
+
type: "function",
|
|
3536
|
+
name: "stopApp",
|
|
3537
|
+
inputs: [
|
|
3538
|
+
{
|
|
3539
|
+
name: "app",
|
|
3540
|
+
type: "address",
|
|
3541
|
+
internalType: "contractIApp"
|
|
3542
|
+
}
|
|
3543
|
+
],
|
|
3544
|
+
outputs: [],
|
|
3545
|
+
stateMutability: "nonpayable"
|
|
3546
|
+
},
|
|
3547
|
+
{
|
|
3548
|
+
type: "function",
|
|
3549
|
+
name: "suspend",
|
|
3550
|
+
inputs: [
|
|
3551
|
+
{
|
|
3552
|
+
name: "account",
|
|
3553
|
+
type: "address",
|
|
3554
|
+
internalType: "address"
|
|
3555
|
+
},
|
|
3556
|
+
{
|
|
3557
|
+
name: "apps",
|
|
3558
|
+
type: "address[]",
|
|
3559
|
+
internalType: "contractIApp[]"
|
|
3560
|
+
}
|
|
3561
|
+
],
|
|
3562
|
+
outputs: [],
|
|
3563
|
+
stateMutability: "nonpayable"
|
|
3564
|
+
},
|
|
3565
|
+
{
|
|
3566
|
+
type: "function",
|
|
3567
|
+
name: "terminateApp",
|
|
3568
|
+
inputs: [
|
|
3569
|
+
{
|
|
3570
|
+
name: "app",
|
|
3571
|
+
type: "address",
|
|
3572
|
+
internalType: "contractIApp"
|
|
3573
|
+
}
|
|
3574
|
+
],
|
|
3575
|
+
outputs: [],
|
|
3576
|
+
stateMutability: "nonpayable"
|
|
3577
|
+
},
|
|
3578
|
+
{
|
|
3579
|
+
type: "function",
|
|
3580
|
+
name: "terminateAppByAdmin",
|
|
3581
|
+
inputs: [
|
|
3582
|
+
{
|
|
3583
|
+
name: "app",
|
|
3584
|
+
type: "address",
|
|
3585
|
+
internalType: "contractIApp"
|
|
3586
|
+
}
|
|
3587
|
+
],
|
|
3588
|
+
outputs: [],
|
|
3589
|
+
stateMutability: "nonpayable"
|
|
3590
|
+
},
|
|
3591
|
+
{
|
|
3592
|
+
type: "function",
|
|
3593
|
+
name: "updateAppMetadataURI",
|
|
3594
|
+
inputs: [
|
|
3595
|
+
{
|
|
3596
|
+
name: "app",
|
|
3597
|
+
type: "address",
|
|
3598
|
+
internalType: "contractIApp"
|
|
3599
|
+
},
|
|
3600
|
+
{
|
|
3601
|
+
name: "metadataURI",
|
|
3602
|
+
type: "string",
|
|
3603
|
+
internalType: "string"
|
|
3604
|
+
}
|
|
3605
|
+
],
|
|
3606
|
+
outputs: [],
|
|
3607
|
+
stateMutability: "nonpayable"
|
|
3608
|
+
},
|
|
3609
|
+
{
|
|
3610
|
+
type: "function",
|
|
3611
|
+
name: "upgradeApp",
|
|
3612
|
+
inputs: [
|
|
3613
|
+
{
|
|
3614
|
+
name: "app",
|
|
3615
|
+
type: "address",
|
|
3616
|
+
internalType: "contractIApp"
|
|
3617
|
+
},
|
|
3618
|
+
{
|
|
3619
|
+
name: "release",
|
|
3620
|
+
type: "tuple",
|
|
3621
|
+
internalType: "structIAppController.Release",
|
|
3622
|
+
components: [
|
|
3623
|
+
{
|
|
3624
|
+
name: "rmsRelease",
|
|
3625
|
+
type: "tuple",
|
|
3626
|
+
internalType: "structIReleaseManagerTypes.Release",
|
|
3627
|
+
components: [
|
|
3628
|
+
{
|
|
3629
|
+
name: "artifacts",
|
|
3630
|
+
type: "tuple[]",
|
|
3631
|
+
internalType: "structIReleaseManagerTypes.Artifact[]",
|
|
3632
|
+
components: [
|
|
3633
|
+
{
|
|
3634
|
+
name: "digest",
|
|
3635
|
+
type: "bytes32",
|
|
3636
|
+
internalType: "bytes32"
|
|
3637
|
+
},
|
|
3638
|
+
{
|
|
3639
|
+
name: "registry",
|
|
3640
|
+
type: "string",
|
|
3641
|
+
internalType: "string"
|
|
3642
|
+
}
|
|
3643
|
+
]
|
|
3644
|
+
},
|
|
3645
|
+
{
|
|
3646
|
+
name: "upgradeByTime",
|
|
3647
|
+
type: "uint32",
|
|
3648
|
+
internalType: "uint32"
|
|
3649
|
+
}
|
|
3650
|
+
]
|
|
3651
|
+
},
|
|
3652
|
+
{
|
|
3653
|
+
name: "publicEnv",
|
|
3654
|
+
type: "bytes",
|
|
3655
|
+
internalType: "bytes"
|
|
3656
|
+
},
|
|
3657
|
+
{
|
|
3658
|
+
name: "encryptedEnv",
|
|
3659
|
+
type: "bytes",
|
|
3660
|
+
internalType: "bytes"
|
|
3661
|
+
},
|
|
3662
|
+
{
|
|
3663
|
+
name: "containerPolicy",
|
|
3664
|
+
type: "tuple",
|
|
3665
|
+
internalType: "structIAppController.ContainerPolicy",
|
|
3666
|
+
components: [
|
|
3667
|
+
{
|
|
3668
|
+
name: "args",
|
|
3669
|
+
type: "string[]",
|
|
3670
|
+
internalType: "string[]"
|
|
3671
|
+
},
|
|
3672
|
+
{
|
|
3673
|
+
name: "cmdOverride",
|
|
3674
|
+
type: "string[]",
|
|
3675
|
+
internalType: "string[]"
|
|
3676
|
+
},
|
|
3677
|
+
{
|
|
3678
|
+
name: "env",
|
|
3679
|
+
type: "tuple[]",
|
|
3680
|
+
internalType: "structIAppController.EnvVar[]",
|
|
3681
|
+
components: [
|
|
3682
|
+
{
|
|
3683
|
+
name: "key",
|
|
3684
|
+
type: "string",
|
|
3685
|
+
internalType: "string"
|
|
3686
|
+
},
|
|
3687
|
+
{
|
|
3688
|
+
name: "value",
|
|
3689
|
+
type: "string",
|
|
3690
|
+
internalType: "string"
|
|
3691
|
+
}
|
|
3692
|
+
]
|
|
3693
|
+
},
|
|
3694
|
+
{
|
|
3695
|
+
name: "envOverride",
|
|
3696
|
+
type: "tuple[]",
|
|
3697
|
+
internalType: "structIAppController.EnvVar[]",
|
|
3698
|
+
components: [
|
|
3699
|
+
{
|
|
3700
|
+
name: "key",
|
|
3701
|
+
type: "string",
|
|
3702
|
+
internalType: "string"
|
|
3703
|
+
},
|
|
3704
|
+
{
|
|
3705
|
+
name: "value",
|
|
3706
|
+
type: "string",
|
|
3707
|
+
internalType: "string"
|
|
3708
|
+
}
|
|
3709
|
+
]
|
|
3710
|
+
},
|
|
3711
|
+
{
|
|
3712
|
+
name: "restartPolicy",
|
|
3713
|
+
type: "string",
|
|
3714
|
+
internalType: "string"
|
|
3715
|
+
}
|
|
3716
|
+
]
|
|
3717
|
+
}
|
|
3718
|
+
]
|
|
3719
|
+
}
|
|
3720
|
+
],
|
|
3721
|
+
outputs: [
|
|
3722
|
+
{
|
|
3723
|
+
name: "",
|
|
3724
|
+
type: "uint256",
|
|
3725
|
+
internalType: "uint256"
|
|
3726
|
+
}
|
|
3727
|
+
],
|
|
3728
|
+
stateMutability: "nonpayable"
|
|
3729
|
+
},
|
|
3730
|
+
{
|
|
3731
|
+
type: "function",
|
|
3732
|
+
name: "version",
|
|
3733
|
+
inputs: [],
|
|
3734
|
+
outputs: [
|
|
3735
|
+
{
|
|
3736
|
+
name: "",
|
|
3737
|
+
type: "string",
|
|
3738
|
+
internalType: "string"
|
|
3739
|
+
}
|
|
3740
|
+
],
|
|
3741
|
+
stateMutability: "view"
|
|
3742
|
+
},
|
|
3743
|
+
{
|
|
3744
|
+
type: "event",
|
|
3745
|
+
name: "AppCreated",
|
|
3746
|
+
inputs: [
|
|
3747
|
+
{
|
|
3748
|
+
name: "creator",
|
|
3749
|
+
type: "address",
|
|
3750
|
+
indexed: true,
|
|
3751
|
+
internalType: "address"
|
|
3752
|
+
},
|
|
3753
|
+
{
|
|
3754
|
+
name: "app",
|
|
3755
|
+
type: "address",
|
|
3756
|
+
indexed: true,
|
|
3757
|
+
internalType: "contractIApp"
|
|
3758
|
+
},
|
|
3759
|
+
{
|
|
3760
|
+
name: "operatorSetId",
|
|
3761
|
+
type: "uint32",
|
|
3762
|
+
indexed: false,
|
|
3763
|
+
internalType: "uint32"
|
|
3764
|
+
}
|
|
3765
|
+
],
|
|
3766
|
+
anonymous: false
|
|
3767
|
+
},
|
|
3768
|
+
{
|
|
3769
|
+
type: "event",
|
|
3770
|
+
name: "AppMetadataURIUpdated",
|
|
3771
|
+
inputs: [
|
|
3772
|
+
{
|
|
3773
|
+
name: "app",
|
|
3774
|
+
type: "address",
|
|
3775
|
+
indexed: true,
|
|
3776
|
+
internalType: "contractIApp"
|
|
3777
|
+
},
|
|
3778
|
+
{
|
|
3779
|
+
name: "metadataURI",
|
|
3780
|
+
type: "string",
|
|
3781
|
+
indexed: false,
|
|
3782
|
+
internalType: "string"
|
|
3783
|
+
}
|
|
3784
|
+
],
|
|
3785
|
+
anonymous: false
|
|
3786
|
+
},
|
|
3787
|
+
{
|
|
3788
|
+
type: "event",
|
|
3789
|
+
name: "AppStarted",
|
|
3790
|
+
inputs: [
|
|
3791
|
+
{
|
|
3792
|
+
name: "app",
|
|
3793
|
+
type: "address",
|
|
3794
|
+
indexed: true,
|
|
3795
|
+
internalType: "contractIApp"
|
|
3796
|
+
}
|
|
3797
|
+
],
|
|
3798
|
+
anonymous: false
|
|
3799
|
+
},
|
|
3800
|
+
{
|
|
3801
|
+
type: "event",
|
|
3802
|
+
name: "AppStopped",
|
|
3803
|
+
inputs: [
|
|
3804
|
+
{
|
|
3805
|
+
name: "app",
|
|
3806
|
+
type: "address",
|
|
3807
|
+
indexed: true,
|
|
3808
|
+
internalType: "contractIApp"
|
|
3809
|
+
}
|
|
3810
|
+
],
|
|
3811
|
+
anonymous: false
|
|
3812
|
+
},
|
|
3813
|
+
{
|
|
3814
|
+
type: "event",
|
|
3815
|
+
name: "AppSuspended",
|
|
3816
|
+
inputs: [
|
|
3817
|
+
{
|
|
3818
|
+
name: "app",
|
|
3819
|
+
type: "address",
|
|
3820
|
+
indexed: true,
|
|
3821
|
+
internalType: "contractIApp"
|
|
3822
|
+
}
|
|
3823
|
+
],
|
|
3824
|
+
anonymous: false
|
|
3825
|
+
},
|
|
3826
|
+
{
|
|
3827
|
+
type: "event",
|
|
3828
|
+
name: "AppTerminated",
|
|
3829
|
+
inputs: [
|
|
3830
|
+
{
|
|
3831
|
+
name: "app",
|
|
3832
|
+
type: "address",
|
|
3833
|
+
indexed: true,
|
|
3834
|
+
internalType: "contractIApp"
|
|
3835
|
+
}
|
|
3836
|
+
],
|
|
3837
|
+
anonymous: false
|
|
3838
|
+
},
|
|
3839
|
+
{
|
|
3840
|
+
type: "event",
|
|
3841
|
+
name: "AppTerminatedByAdmin",
|
|
3842
|
+
inputs: [
|
|
3843
|
+
{
|
|
3844
|
+
name: "app",
|
|
3845
|
+
type: "address",
|
|
3846
|
+
indexed: true,
|
|
3847
|
+
internalType: "contractIApp"
|
|
3848
|
+
}
|
|
3849
|
+
],
|
|
3850
|
+
anonymous: false
|
|
3851
|
+
},
|
|
3852
|
+
{
|
|
3853
|
+
type: "event",
|
|
3854
|
+
name: "AppUpgraded",
|
|
3855
|
+
inputs: [
|
|
3856
|
+
{
|
|
3857
|
+
name: "app",
|
|
3858
|
+
type: "address",
|
|
3859
|
+
indexed: true,
|
|
3860
|
+
internalType: "contractIApp"
|
|
3861
|
+
},
|
|
3862
|
+
{
|
|
3863
|
+
name: "rmsReleaseId",
|
|
3864
|
+
type: "uint256",
|
|
3865
|
+
indexed: false,
|
|
3866
|
+
internalType: "uint256"
|
|
3867
|
+
},
|
|
3868
|
+
{
|
|
3869
|
+
name: "release",
|
|
3870
|
+
type: "tuple",
|
|
3871
|
+
indexed: false,
|
|
3872
|
+
internalType: "structIAppController.Release",
|
|
3873
|
+
components: [
|
|
3874
|
+
{
|
|
3875
|
+
name: "rmsRelease",
|
|
3876
|
+
type: "tuple",
|
|
3877
|
+
internalType: "structIReleaseManagerTypes.Release",
|
|
3878
|
+
components: [
|
|
3879
|
+
{
|
|
3880
|
+
name: "artifacts",
|
|
3881
|
+
type: "tuple[]",
|
|
3882
|
+
internalType: "structIReleaseManagerTypes.Artifact[]",
|
|
3883
|
+
components: [
|
|
3884
|
+
{
|
|
3885
|
+
name: "digest",
|
|
3886
|
+
type: "bytes32",
|
|
3887
|
+
internalType: "bytes32"
|
|
3888
|
+
},
|
|
3889
|
+
{
|
|
3890
|
+
name: "registry",
|
|
3891
|
+
type: "string",
|
|
3892
|
+
internalType: "string"
|
|
3893
|
+
}
|
|
3894
|
+
]
|
|
3895
|
+
},
|
|
3896
|
+
{
|
|
3897
|
+
name: "upgradeByTime",
|
|
3898
|
+
type: "uint32",
|
|
3899
|
+
internalType: "uint32"
|
|
3900
|
+
}
|
|
3901
|
+
]
|
|
3902
|
+
},
|
|
3903
|
+
{
|
|
3904
|
+
name: "publicEnv",
|
|
3905
|
+
type: "bytes",
|
|
3906
|
+
internalType: "bytes"
|
|
3907
|
+
},
|
|
3908
|
+
{
|
|
3909
|
+
name: "encryptedEnv",
|
|
3910
|
+
type: "bytes",
|
|
3911
|
+
internalType: "bytes"
|
|
3912
|
+
},
|
|
3913
|
+
{
|
|
3914
|
+
name: "containerPolicy",
|
|
3915
|
+
type: "tuple",
|
|
3916
|
+
internalType: "structIAppController.ContainerPolicy",
|
|
3917
|
+
components: [
|
|
3918
|
+
{
|
|
3919
|
+
name: "args",
|
|
3920
|
+
type: "string[]",
|
|
3921
|
+
internalType: "string[]"
|
|
3922
|
+
},
|
|
3923
|
+
{
|
|
3924
|
+
name: "cmdOverride",
|
|
3925
|
+
type: "string[]",
|
|
3926
|
+
internalType: "string[]"
|
|
3927
|
+
},
|
|
3928
|
+
{
|
|
3929
|
+
name: "env",
|
|
3930
|
+
type: "tuple[]",
|
|
3931
|
+
internalType: "structIAppController.EnvVar[]",
|
|
3932
|
+
components: [
|
|
3933
|
+
{
|
|
3934
|
+
name: "key",
|
|
3935
|
+
type: "string",
|
|
3936
|
+
internalType: "string"
|
|
3937
|
+
},
|
|
3938
|
+
{
|
|
3939
|
+
name: "value",
|
|
3940
|
+
type: "string",
|
|
3941
|
+
internalType: "string"
|
|
3942
|
+
}
|
|
3943
|
+
]
|
|
3944
|
+
},
|
|
3945
|
+
{
|
|
3946
|
+
name: "envOverride",
|
|
3947
|
+
type: "tuple[]",
|
|
3948
|
+
internalType: "structIAppController.EnvVar[]",
|
|
3949
|
+
components: [
|
|
3950
|
+
{
|
|
3951
|
+
name: "key",
|
|
3952
|
+
type: "string",
|
|
3953
|
+
internalType: "string"
|
|
3954
|
+
},
|
|
3955
|
+
{
|
|
3956
|
+
name: "value",
|
|
3957
|
+
type: "string",
|
|
3958
|
+
internalType: "string"
|
|
3959
|
+
}
|
|
3960
|
+
]
|
|
3961
|
+
},
|
|
3962
|
+
{
|
|
3963
|
+
name: "restartPolicy",
|
|
3964
|
+
type: "string",
|
|
3965
|
+
internalType: "string"
|
|
3966
|
+
}
|
|
3967
|
+
]
|
|
3968
|
+
}
|
|
3969
|
+
]
|
|
3970
|
+
}
|
|
3971
|
+
],
|
|
3972
|
+
anonymous: false
|
|
3973
|
+
},
|
|
3974
|
+
{
|
|
3975
|
+
type: "event",
|
|
3976
|
+
name: "GlobalMaxActiveAppsSet",
|
|
3977
|
+
inputs: [
|
|
3978
|
+
{
|
|
3979
|
+
name: "limit",
|
|
3980
|
+
type: "uint32",
|
|
3981
|
+
indexed: false,
|
|
3982
|
+
internalType: "uint32"
|
|
3983
|
+
}
|
|
3984
|
+
],
|
|
3985
|
+
anonymous: false
|
|
3986
|
+
},
|
|
3987
|
+
{
|
|
3988
|
+
type: "event",
|
|
3989
|
+
name: "Initialized",
|
|
3990
|
+
inputs: [
|
|
3991
|
+
{
|
|
3992
|
+
name: "version",
|
|
3993
|
+
type: "uint8",
|
|
3994
|
+
indexed: false,
|
|
3995
|
+
internalType: "uint8"
|
|
3996
|
+
}
|
|
3997
|
+
],
|
|
3998
|
+
anonymous: false
|
|
3999
|
+
},
|
|
4000
|
+
{
|
|
4001
|
+
type: "event",
|
|
4002
|
+
name: "MaxActiveAppsSet",
|
|
4003
|
+
inputs: [
|
|
4004
|
+
{
|
|
4005
|
+
name: "user",
|
|
4006
|
+
type: "address",
|
|
4007
|
+
indexed: true,
|
|
4008
|
+
internalType: "address"
|
|
4009
|
+
},
|
|
4010
|
+
{
|
|
4011
|
+
name: "limit",
|
|
4012
|
+
type: "uint32",
|
|
4013
|
+
indexed: false,
|
|
4014
|
+
internalType: "uint32"
|
|
4015
|
+
}
|
|
4016
|
+
],
|
|
4017
|
+
anonymous: false
|
|
4018
|
+
},
|
|
4019
|
+
{
|
|
4020
|
+
type: "event",
|
|
4021
|
+
name: "UpgradeConfirmed",
|
|
4022
|
+
inputs: [
|
|
4023
|
+
{
|
|
4024
|
+
name: "app",
|
|
4025
|
+
type: "address",
|
|
4026
|
+
indexed: true,
|
|
4027
|
+
internalType: "contractIApp"
|
|
4028
|
+
},
|
|
4029
|
+
{
|
|
4030
|
+
name: "pendingReleaseBlockNumber",
|
|
4031
|
+
type: "uint32",
|
|
4032
|
+
indexed: false,
|
|
4033
|
+
internalType: "uint32"
|
|
4034
|
+
}
|
|
4035
|
+
],
|
|
4036
|
+
anonymous: false
|
|
4037
|
+
},
|
|
4038
|
+
{
|
|
4039
|
+
type: "error",
|
|
4040
|
+
name: "AccountHasActiveApps",
|
|
4041
|
+
inputs: []
|
|
4042
|
+
},
|
|
4043
|
+
{
|
|
4044
|
+
type: "error",
|
|
4045
|
+
name: "AppAlreadyExists",
|
|
4046
|
+
inputs: []
|
|
4047
|
+
},
|
|
4048
|
+
{
|
|
4049
|
+
type: "error",
|
|
4050
|
+
name: "AppDoesNotExist",
|
|
4051
|
+
inputs: []
|
|
4052
|
+
},
|
|
4053
|
+
{
|
|
4054
|
+
type: "error",
|
|
4055
|
+
name: "GlobalMaxActiveAppsExceeded",
|
|
4056
|
+
inputs: []
|
|
4057
|
+
},
|
|
4058
|
+
{
|
|
4059
|
+
type: "error",
|
|
4060
|
+
name: "InvalidAppStatus",
|
|
4061
|
+
inputs: []
|
|
4062
|
+
},
|
|
4063
|
+
{
|
|
4064
|
+
type: "error",
|
|
4065
|
+
name: "InvalidPermissions",
|
|
4066
|
+
inputs: []
|
|
4067
|
+
},
|
|
4068
|
+
{
|
|
4069
|
+
type: "error",
|
|
4070
|
+
name: "InvalidReleaseMetadataURI",
|
|
4071
|
+
inputs: []
|
|
4072
|
+
},
|
|
4073
|
+
{
|
|
4074
|
+
type: "error",
|
|
4075
|
+
name: "InvalidShortString",
|
|
4076
|
+
inputs: []
|
|
4077
|
+
},
|
|
4078
|
+
{
|
|
4079
|
+
type: "error",
|
|
4080
|
+
name: "InvalidSignature",
|
|
4081
|
+
inputs: []
|
|
4082
|
+
},
|
|
4083
|
+
{
|
|
4084
|
+
type: "error",
|
|
4085
|
+
name: "MaxActiveAppsExceeded",
|
|
4086
|
+
inputs: []
|
|
4087
|
+
},
|
|
4088
|
+
{
|
|
4089
|
+
type: "error",
|
|
4090
|
+
name: "MoreThanOneArtifact",
|
|
4091
|
+
inputs: []
|
|
4092
|
+
},
|
|
4093
|
+
{
|
|
4094
|
+
type: "error",
|
|
4095
|
+
name: "NoPendingUpgrade",
|
|
4096
|
+
inputs: []
|
|
4097
|
+
},
|
|
4098
|
+
{
|
|
4099
|
+
type: "error",
|
|
4100
|
+
name: "SignatureExpired",
|
|
4101
|
+
inputs: []
|
|
4102
|
+
},
|
|
4103
|
+
{
|
|
4104
|
+
type: "error",
|
|
4105
|
+
name: "StringTooLong",
|
|
4106
|
+
inputs: [
|
|
4107
|
+
{
|
|
4108
|
+
name: "str",
|
|
4109
|
+
type: "string",
|
|
4110
|
+
internalType: "string"
|
|
4111
|
+
}
|
|
4112
|
+
]
|
|
2943
4113
|
}
|
|
2944
|
-
|
|
2945
|
-
}
|
|
2946
|
-
|
|
2947
|
-
// src/client/common/contract/caller.ts
|
|
2948
|
-
import { encodeFunctionData as encodeFunctionData2, decodeErrorResult as decodeErrorResult2, bytesToHex } from "viem";
|
|
2949
|
-
|
|
2950
|
-
// src/client/common/utils/helpers.ts
|
|
2951
|
-
import { extractChain, createPublicClient, createWalletClient, http, fallback } from "viem";
|
|
2952
|
-
import { sepolia as sepolia2 } from "viem/chains";
|
|
2953
|
-
import { privateKeyToAccount } from "viem/accounts";
|
|
2954
|
-
function getChainFromID(chainID, fallback2 = sepolia2) {
|
|
2955
|
-
const id = Number(chainID);
|
|
2956
|
-
return extractChain({ chains: SUPPORTED_CHAINS, id }) || fallback2;
|
|
2957
|
-
}
|
|
2958
|
-
function addHexPrefix(value) {
|
|
2959
|
-
return value.startsWith("0x") ? value : `0x${value}`;
|
|
2960
|
-
}
|
|
2961
|
-
function stripHexPrefix(value) {
|
|
2962
|
-
return value.startsWith("0x") ? value.slice(2) : value;
|
|
2963
|
-
}
|
|
4114
|
+
];
|
|
2964
4115
|
|
|
2965
|
-
// src/client/common/abis/AppController.json
|
|
2966
|
-
var
|
|
4116
|
+
// src/client/common/abis/AppController.v1_4.json
|
|
4117
|
+
var AppController_v1_4_default = [
|
|
2967
4118
|
{
|
|
2968
4119
|
type: "constructor",
|
|
2969
4120
|
inputs: [
|
|
@@ -4647,6 +5798,38 @@ var PermissionController_default = [
|
|
|
4647
5798
|
];
|
|
4648
5799
|
|
|
4649
5800
|
// src/client/common/contract/caller.ts
|
|
5801
|
+
function appControllerAbiFor(environmentConfig) {
|
|
5802
|
+
return environmentConfig.releaseAbiVersion === "v1.4" ? AppController_v1_4_default : AppController_default;
|
|
5803
|
+
}
|
|
5804
|
+
function supportsContainerPolicy(environmentConfig) {
|
|
5805
|
+
return environmentConfig.releaseAbiVersion !== "v1.4";
|
|
5806
|
+
}
|
|
5807
|
+
function containerPolicyForViem(policy = EMPTY_CONTAINER_POLICY) {
|
|
5808
|
+
return {
|
|
5809
|
+
args: policy.args,
|
|
5810
|
+
cmdOverride: policy.cmdOverride,
|
|
5811
|
+
env: policy.env.map((e) => ({ key: e.key, value: e.value })),
|
|
5812
|
+
envOverride: policy.envOverride.map((e) => ({ key: e.key, value: e.value })),
|
|
5813
|
+
restartPolicy: policy.restartPolicy
|
|
5814
|
+
};
|
|
5815
|
+
}
|
|
5816
|
+
function releaseForViem(release, environmentConfig) {
|
|
5817
|
+
const base = {
|
|
5818
|
+
rmsRelease: {
|
|
5819
|
+
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
5820
|
+
digest: `0x${bytesToHex(artifact.digest).slice(2).padStart(64, "0")}`,
|
|
5821
|
+
registry: artifact.registry
|
|
5822
|
+
})),
|
|
5823
|
+
upgradeByTime: release.rmsRelease.upgradeByTime
|
|
5824
|
+
},
|
|
5825
|
+
publicEnv: bytesToHex(release.publicEnv),
|
|
5826
|
+
encryptedEnv: bytesToHex(release.encryptedEnv)
|
|
5827
|
+
};
|
|
5828
|
+
if (!supportsContainerPolicy(environmentConfig)) {
|
|
5829
|
+
return base;
|
|
5830
|
+
}
|
|
5831
|
+
return { ...base, containerPolicy: containerPolicyForViem(release.containerPolicy) };
|
|
5832
|
+
}
|
|
4650
5833
|
function formatETH(wei) {
|
|
4651
5834
|
const eth = Number(wei) / 1e18;
|
|
4652
5835
|
const costStr = eth.toFixed(6);
|
|
@@ -4663,7 +5846,7 @@ async function calculateAppID(options) {
|
|
|
4663
5846
|
const saltHex = `0x${paddedSaltHex}`;
|
|
4664
5847
|
const appID = await publicClient.readContract({
|
|
4665
5848
|
address: environmentConfig.appControllerAddress,
|
|
4666
|
-
abi:
|
|
5849
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
4667
5850
|
functionName: "calculateAppId",
|
|
4668
5851
|
args: [ownerAddress, saltHex]
|
|
4669
5852
|
});
|
|
@@ -4687,22 +5870,12 @@ async function prepareDeployBatch(options, logger = noopLogger) {
|
|
|
4687
5870
|
const saltHexString = bytesToHex(salt).slice(2);
|
|
4688
5871
|
const paddedSaltHex = saltHexString.padStart(64, "0");
|
|
4689
5872
|
const saltHex = `0x${paddedSaltHex}`;
|
|
4690
|
-
const
|
|
4691
|
-
rmsRelease: {
|
|
4692
|
-
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
4693
|
-
digest: `0x${bytesToHex(artifact.digest).slice(2).padStart(64, "0")}`,
|
|
4694
|
-
registry: artifact.registry
|
|
4695
|
-
})),
|
|
4696
|
-
upgradeByTime: release.rmsRelease.upgradeByTime
|
|
4697
|
-
},
|
|
4698
|
-
publicEnv: bytesToHex(release.publicEnv),
|
|
4699
|
-
encryptedEnv: bytesToHex(release.encryptedEnv)
|
|
4700
|
-
};
|
|
5873
|
+
const release_ = releaseForViem(release, environmentConfig);
|
|
4701
5874
|
const functionName = options.billTo === "app" ? "createAppWithIsolatedBilling" : "createApp";
|
|
4702
5875
|
const createData = encodeFunctionData2({
|
|
4703
|
-
abi:
|
|
5876
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
4704
5877
|
functionName,
|
|
4705
|
-
args: [saltHex,
|
|
5878
|
+
args: [saltHex, release_]
|
|
4706
5879
|
});
|
|
4707
5880
|
const acceptAdminData = encodeFunctionData2({
|
|
4708
5881
|
abi: PermissionController_default,
|
|
@@ -4790,21 +5963,11 @@ async function prepareUpgradeBatch(options) {
|
|
|
4790
5963
|
publicLogs,
|
|
4791
5964
|
needsPermissionChange
|
|
4792
5965
|
} = options;
|
|
4793
|
-
const
|
|
4794
|
-
rmsRelease: {
|
|
4795
|
-
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
4796
|
-
digest: `0x${bytesToHex(artifact.digest).slice(2).padStart(64, "0")}`,
|
|
4797
|
-
registry: artifact.registry
|
|
4798
|
-
})),
|
|
4799
|
-
upgradeByTime: release.rmsRelease.upgradeByTime
|
|
4800
|
-
},
|
|
4801
|
-
publicEnv: bytesToHex(release.publicEnv),
|
|
4802
|
-
encryptedEnv: bytesToHex(release.encryptedEnv)
|
|
4803
|
-
};
|
|
5966
|
+
const release_ = releaseForViem(release, environmentConfig);
|
|
4804
5967
|
const upgradeData = encodeFunctionData2({
|
|
4805
|
-
abi:
|
|
5968
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
4806
5969
|
functionName: "upgradeApp",
|
|
4807
|
-
args: [appID,
|
|
5970
|
+
args: [appID, release_]
|
|
4808
5971
|
});
|
|
4809
5972
|
const executions = [
|
|
4810
5973
|
{
|
|
@@ -4938,7 +6101,7 @@ ${pendingMessage}`);
|
|
|
4938
6101
|
if (callError.data) {
|
|
4939
6102
|
try {
|
|
4940
6103
|
const decoded = decodeErrorResult2({
|
|
4941
|
-
abi:
|
|
6104
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
4942
6105
|
data: callError.data
|
|
4943
6106
|
});
|
|
4944
6107
|
const formattedError = formatAppControllerError(decoded);
|
|
@@ -4991,7 +6154,7 @@ function formatAppControllerError(decoded) {
|
|
|
4991
6154
|
async function getActiveAppCount(publicClient, environmentConfig, user) {
|
|
4992
6155
|
const count = await publicClient.readContract({
|
|
4993
6156
|
address: environmentConfig.appControllerAddress,
|
|
4994
|
-
abi:
|
|
6157
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
4995
6158
|
functionName: "getActiveAppCount",
|
|
4996
6159
|
args: [user]
|
|
4997
6160
|
});
|
|
@@ -5000,7 +6163,7 @@ async function getActiveAppCount(publicClient, environmentConfig, user) {
|
|
|
5000
6163
|
async function getMaxActiveAppsPerUser(publicClient, environmentConfig, user) {
|
|
5001
6164
|
const quota = await publicClient.readContract({
|
|
5002
6165
|
address: environmentConfig.appControllerAddress,
|
|
5003
|
-
abi:
|
|
6166
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5004
6167
|
functionName: "getMaxActiveAppsPerUser",
|
|
5005
6168
|
args: [user]
|
|
5006
6169
|
});
|
|
@@ -5009,7 +6172,7 @@ async function getMaxActiveAppsPerUser(publicClient, environmentConfig, user) {
|
|
|
5009
6172
|
async function getBillingType(publicClient, environmentConfig, app) {
|
|
5010
6173
|
const result = await publicClient.readContract({
|
|
5011
6174
|
address: environmentConfig.appControllerAddress,
|
|
5012
|
-
abi:
|
|
6175
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5013
6176
|
functionName: "getBillingType",
|
|
5014
6177
|
args: [app]
|
|
5015
6178
|
});
|
|
@@ -5018,7 +6181,7 @@ async function getBillingType(publicClient, environmentConfig, app) {
|
|
|
5018
6181
|
async function getAppsByBillingAccount(publicClient, environmentConfig, account, offset, limit) {
|
|
5019
6182
|
const result = await publicClient.readContract({
|
|
5020
6183
|
address: environmentConfig.appControllerAddress,
|
|
5021
|
-
abi:
|
|
6184
|
+
abi: appControllerAbiFor(environmentConfig),
|
|
5022
6185
|
functionName: "getAppsByBillingAccount",
|
|
5023
6186
|
args: [account, offset, limit]
|
|
5024
6187
|
});
|
|
@@ -5072,6 +6235,35 @@ async function undelegate(options, logger = noopLogger) {
|
|
|
5072
6235
|
return hash;
|
|
5073
6236
|
}
|
|
5074
6237
|
|
|
6238
|
+
// src/client/common/gas/insufficientGas.ts
|
|
6239
|
+
import { formatEther } from "viem";
|
|
6240
|
+
var InsufficientGasError = class extends Error {
|
|
6241
|
+
constructor(args) {
|
|
6242
|
+
const requiredEth = formatEther(args.requiredWei);
|
|
6243
|
+
const availableEth = formatEther(args.availableWei);
|
|
6244
|
+
super(
|
|
6245
|
+
`Insufficient ETH for gas: wallet ${args.address} has ${availableEth} ETH but this transaction needs ~${requiredEth} ETH.
|
|
6246
|
+
Compute credits do not pay on-chain gas \u2014 fund the wallet with ETH and retry.`
|
|
6247
|
+
);
|
|
6248
|
+
this.name = "InsufficientGasError";
|
|
6249
|
+
this.address = args.address;
|
|
6250
|
+
this.requiredWei = args.requiredWei;
|
|
6251
|
+
this.availableWei = args.availableWei;
|
|
6252
|
+
this.requiredEth = requiredEth;
|
|
6253
|
+
this.availableEth = availableEth;
|
|
6254
|
+
}
|
|
6255
|
+
};
|
|
6256
|
+
async function assertSufficientGas(args) {
|
|
6257
|
+
const availableWei = await args.publicClient.getBalance({ address: args.address });
|
|
6258
|
+
if (availableWei < args.gasEstimate.maxCostWei) {
|
|
6259
|
+
throw new InsufficientGasError({
|
|
6260
|
+
address: args.address,
|
|
6261
|
+
requiredWei: args.gasEstimate.maxCostWei,
|
|
6262
|
+
availableWei
|
|
6263
|
+
});
|
|
6264
|
+
}
|
|
6265
|
+
}
|
|
6266
|
+
|
|
5075
6267
|
// src/client/common/utils/userapi.ts
|
|
5076
6268
|
import axios2 from "axios";
|
|
5077
6269
|
|
|
@@ -5098,43 +6290,13 @@ async function calculatePermissionSignature(options) {
|
|
|
5098
6290
|
});
|
|
5099
6291
|
return { signature, digest };
|
|
5100
6292
|
}
|
|
5101
|
-
var generateBillingSigData = (product, expiry) => {
|
|
5102
|
-
return {
|
|
5103
|
-
domain: {
|
|
5104
|
-
name: "EigenCloud Billing API",
|
|
5105
|
-
version: "1"
|
|
5106
|
-
},
|
|
5107
|
-
types: {
|
|
5108
|
-
BillingAuth: [
|
|
5109
|
-
{ name: "product", type: "string" },
|
|
5110
|
-
{ name: "expiry", type: "uint256" }
|
|
5111
|
-
]
|
|
5112
|
-
},
|
|
5113
|
-
primaryType: "BillingAuth",
|
|
5114
|
-
message: {
|
|
5115
|
-
product,
|
|
5116
|
-
expiry
|
|
5117
|
-
}
|
|
5118
|
-
};
|
|
5119
|
-
};
|
|
5120
|
-
async function calculateBillingAuthSignature(options) {
|
|
5121
|
-
const { walletClient, product, expiry } = options;
|
|
5122
|
-
const account = walletClient.account;
|
|
5123
|
-
if (!account) {
|
|
5124
|
-
throw new Error("WalletClient must have an account attached");
|
|
5125
|
-
}
|
|
5126
|
-
const signature = await walletClient.signTypedData({
|
|
5127
|
-
account,
|
|
5128
|
-
...generateBillingSigData(product, expiry)
|
|
5129
|
-
});
|
|
5130
|
-
return { signature, expiry };
|
|
5131
|
-
}
|
|
5132
6293
|
|
|
5133
6294
|
// src/client/common/utils/retry.ts
|
|
5134
6295
|
import axios from "axios";
|
|
5135
6296
|
var MAX_RETRIES = 5;
|
|
5136
6297
|
var INITIAL_BACKOFF_MS = 1e3;
|
|
5137
6298
|
var MAX_BACKOFF_MS = 3e4;
|
|
6299
|
+
var RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 502, 503, 504]);
|
|
5138
6300
|
function sleep(ms) {
|
|
5139
6301
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
5140
6302
|
}
|
|
@@ -5154,7 +6316,7 @@ async function requestWithRetry(config) {
|
|
|
5154
6316
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
5155
6317
|
const res = await axios({ ...config, validateStatus: () => true });
|
|
5156
6318
|
lastResponse = res;
|
|
5157
|
-
if (res.status
|
|
6319
|
+
if (!RETRYABLE_STATUSES.has(res.status)) {
|
|
5158
6320
|
return res;
|
|
5159
6321
|
}
|
|
5160
6322
|
if (attempt < MAX_RETRIES) {
|
|
@@ -5183,7 +6345,7 @@ var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
|
5183
6345
|
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
5184
6346
|
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
5185
6347
|
function getDefaultClientId() {
|
|
5186
|
-
const version = true ? "1.0.0
|
|
6348
|
+
const version = true ? "1.0.0" : "0.0.0";
|
|
5187
6349
|
return `ecloud-sdk/v${version}`;
|
|
5188
6350
|
}
|
|
5189
6351
|
var UserApiClient = class {
|
|
@@ -5218,7 +6380,6 @@ var UserApiClient = class {
|
|
|
5218
6380
|
status: app.app_status,
|
|
5219
6381
|
ip: app.ip,
|
|
5220
6382
|
machineType: app.machine_type,
|
|
5221
|
-
hostname: app.hostname,
|
|
5222
6383
|
profile: app.profile,
|
|
5223
6384
|
metrics: app.metrics,
|
|
5224
6385
|
evmAddresses,
|
|
@@ -5284,28 +6445,6 @@ var UserApiClient = class {
|
|
|
5284
6445
|
status: app.app_status || app.App_Status || ""
|
|
5285
6446
|
}));
|
|
5286
6447
|
}
|
|
5287
|
-
/**
|
|
5288
|
-
* Get deployments for an app from the gRPC-gateway endpoint.
|
|
5289
|
-
* Returns deployment records including upgrade_phase for tracking upgrade progress.
|
|
5290
|
-
*
|
|
5291
|
-
* Endpoint: GET /v1/apps/:appAddress/deployments
|
|
5292
|
-
*/
|
|
5293
|
-
async getDeployments(appAddress) {
|
|
5294
|
-
const endpoint = `${this.config.userApiServerURL}/v1/apps/${appAddress}/deployments`;
|
|
5295
|
-
const response = await this.makeEIP712AuthenticatedRequest(endpoint);
|
|
5296
|
-
const result = await response.json();
|
|
5297
|
-
const deployments = result.deployments || [];
|
|
5298
|
-
return deployments.map((dep) => ({
|
|
5299
|
-
id: dep.id || "",
|
|
5300
|
-
externalId: dep.external_id || dep.externalId || "",
|
|
5301
|
-
endpoint: dep.endpoint || "",
|
|
5302
|
-
releaseId: dep.release_id || dep.releaseId || "",
|
|
5303
|
-
upgradePhase: dep.upgrade_phase || dep.upgradePhase || "",
|
|
5304
|
-
replacesDeploymentId: dep.replaces_deployment_id || dep.replacesDeploymentId || "",
|
|
5305
|
-
createdAt: dep.created_at || dep.createdAt || "",
|
|
5306
|
-
updatedAt: dep.updated_at || dep.updatedAt || ""
|
|
5307
|
-
}));
|
|
5308
|
-
}
|
|
5309
6448
|
/**
|
|
5310
6449
|
* Upload app profile information with optional image
|
|
5311
6450
|
*
|
|
@@ -5439,48 +6578,6 @@ Please check:
|
|
|
5439
6578
|
"X-eigenx-expiry": expiry.toString()
|
|
5440
6579
|
};
|
|
5441
6580
|
}
|
|
5442
|
-
/**
|
|
5443
|
-
* Make an EIP-712 authenticated request to the gRPC-gateway endpoints.
|
|
5444
|
-
* Uses the billing/compute auth pattern: Authorization + X-Account + X-Expiry headers.
|
|
5445
|
-
*/
|
|
5446
|
-
async makeEIP712AuthenticatedRequest(url) {
|
|
5447
|
-
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
5448
|
-
const { signature } = await calculateBillingAuthSignature({
|
|
5449
|
-
walletClient: this.walletClient,
|
|
5450
|
-
product: "compute",
|
|
5451
|
-
expiry
|
|
5452
|
-
});
|
|
5453
|
-
const headers = {
|
|
5454
|
-
Authorization: `Bearer ${signature}`,
|
|
5455
|
-
"X-Account": this.address,
|
|
5456
|
-
"X-Expiry": expiry.toString(),
|
|
5457
|
-
"x-client-id": this.clientId
|
|
5458
|
-
};
|
|
5459
|
-
try {
|
|
5460
|
-
const response = await requestWithRetry({
|
|
5461
|
-
method: "GET",
|
|
5462
|
-
url,
|
|
5463
|
-
headers,
|
|
5464
|
-
maxRedirects: 0,
|
|
5465
|
-
withCredentials: true
|
|
5466
|
-
});
|
|
5467
|
-
const status = response.status;
|
|
5468
|
-
if (status < 200 || status >= 300) {
|
|
5469
|
-
const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
|
|
5470
|
-
throw new Error(`gRPC-gateway request failed: ${status} - ${body}`);
|
|
5471
|
-
}
|
|
5472
|
-
return {
|
|
5473
|
-
json: async () => response.data,
|
|
5474
|
-
text: async () => typeof response.data === "string" ? response.data : JSON.stringify(response.data)
|
|
5475
|
-
};
|
|
5476
|
-
} catch (error) {
|
|
5477
|
-
if (error.message?.includes("fetch failed") || error.message?.includes("ECONNREFUSED") || error.message?.includes("ENOTFOUND") || error.cause) {
|
|
5478
|
-
const cause = error.cause?.message || error.cause || error.message;
|
|
5479
|
-
throw new Error(`Failed to connect to API at ${url}: ${cause}`);
|
|
5480
|
-
}
|
|
5481
|
-
throw error;
|
|
5482
|
-
}
|
|
5483
|
-
}
|
|
5484
6581
|
// ==========================================================================
|
|
5485
6582
|
// SIWE Session Management
|
|
5486
6583
|
// ==========================================================================
|
|
@@ -5586,8 +6683,36 @@ function transformAppRelease(raw) {
|
|
|
5586
6683
|
|
|
5587
6684
|
// src/client/common/contract/watcher.ts
|
|
5588
6685
|
var WATCH_POLL_INTERVAL_SECONDS = 5;
|
|
6686
|
+
var WATCH_HEARTBEAT_INTERVAL_SECONDS = 30;
|
|
6687
|
+
var WATCH_DEFAULT_TIMEOUT_SECONDS = 10 * 60;
|
|
5589
6688
|
var APP_STATUS_RUNNING = "Running";
|
|
5590
6689
|
var APP_STATUS_FAILED = "Failed";
|
|
6690
|
+
var WatchTimeoutError = class extends Error {
|
|
6691
|
+
constructor(args) {
|
|
6692
|
+
super(
|
|
6693
|
+
args.message ?? `Timed out after ${args.elapsedSeconds}s waiting for app ${args.appId} (last status: ${args.lastStatus ?? "unknown"})`
|
|
6694
|
+
);
|
|
6695
|
+
this.name = "WatchTimeoutError";
|
|
6696
|
+
this.appId = args.appId;
|
|
6697
|
+
this.elapsedSeconds = args.elapsedSeconds;
|
|
6698
|
+
this.lastStatus = args.lastStatus;
|
|
6699
|
+
this.timeoutSeconds = args.timeoutSeconds;
|
|
6700
|
+
}
|
|
6701
|
+
};
|
|
6702
|
+
function resolveWatchTimeoutSeconds(explicit) {
|
|
6703
|
+
if (typeof explicit === "number" && Number.isFinite(explicit) && explicit > 0) {
|
|
6704
|
+
return Math.floor(explicit);
|
|
6705
|
+
}
|
|
6706
|
+
const raw = process.env.ECLOUD_WATCH_TIMEOUT_SECONDS;
|
|
6707
|
+
if (raw === void 0 || raw === "") {
|
|
6708
|
+
return WATCH_DEFAULT_TIMEOUT_SECONDS;
|
|
6709
|
+
}
|
|
6710
|
+
const parsed = Number(raw);
|
|
6711
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
6712
|
+
return WATCH_DEFAULT_TIMEOUT_SECONDS;
|
|
6713
|
+
}
|
|
6714
|
+
return Math.floor(parsed);
|
|
6715
|
+
}
|
|
5591
6716
|
async function watchUntilRunning(options, logger) {
|
|
5592
6717
|
const { walletClient, publicClient, environmentConfig, appId } = options;
|
|
5593
6718
|
const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
|
|
@@ -5618,8 +6743,20 @@ async function watchUntilRunning(options, logger) {
|
|
|
5618
6743
|
return false;
|
|
5619
6744
|
};
|
|
5620
6745
|
const startTime = Date.now();
|
|
6746
|
+
const timeoutSeconds = resolveWatchTimeoutSeconds(options.timeoutSeconds);
|
|
5621
6747
|
let lastLoggedStatus;
|
|
6748
|
+
let lastHeartbeatAt = startTime;
|
|
5622
6749
|
while (true) {
|
|
6750
|
+
const elapsedMs = Date.now() - startTime;
|
|
6751
|
+
const elapsed = Math.round(elapsedMs / 1e3);
|
|
6752
|
+
if (elapsed >= timeoutSeconds) {
|
|
6753
|
+
throw new WatchTimeoutError({
|
|
6754
|
+
appId,
|
|
6755
|
+
elapsedSeconds: elapsed,
|
|
6756
|
+
lastStatus: lastLoggedStatus,
|
|
6757
|
+
timeoutSeconds
|
|
6758
|
+
});
|
|
6759
|
+
}
|
|
5623
6760
|
try {
|
|
5624
6761
|
const info = await userApiClient.getInfos([appId], 1);
|
|
5625
6762
|
if (info.length === 0) {
|
|
@@ -5629,62 +6766,35 @@ async function watchUntilRunning(options, logger) {
|
|
|
5629
6766
|
const appInfo = info[0];
|
|
5630
6767
|
const currentStatus = appInfo.status;
|
|
5631
6768
|
const currentIP = appInfo.ip || "";
|
|
5632
|
-
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
5633
6769
|
if (currentStatus !== lastLoggedStatus) {
|
|
5634
6770
|
logger.info(`Status: ${currentStatus} (${elapsed}s)`);
|
|
5635
6771
|
lastLoggedStatus = currentStatus;
|
|
6772
|
+
lastHeartbeatAt = Date.now();
|
|
6773
|
+
} else if (Date.now() - lastHeartbeatAt >= WATCH_HEARTBEAT_INTERVAL_SECONDS * 1e3) {
|
|
6774
|
+
logger.info(`Status: ${currentStatus} (${elapsed}s)`);
|
|
6775
|
+
lastHeartbeatAt = Date.now();
|
|
5636
6776
|
}
|
|
5637
6777
|
if (stopCondition(currentStatus, currentIP)) {
|
|
5638
6778
|
return currentIP || void 0;
|
|
5639
6779
|
}
|
|
5640
6780
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
5641
6781
|
} catch (error) {
|
|
6782
|
+
if (error instanceof WatchTimeoutError) {
|
|
6783
|
+
throw error;
|
|
6784
|
+
}
|
|
5642
6785
|
logger.warn(`Failed to fetch app info: ${error.message}`);
|
|
5643
6786
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
5644
6787
|
}
|
|
5645
6788
|
}
|
|
5646
6789
|
}
|
|
5647
6790
|
var APP_STATUS_STOPPED = "Stopped";
|
|
5648
|
-
var UPGRADE_PHASE_LABELS = {
|
|
5649
|
-
provisioning: "Provisioning new instance",
|
|
5650
|
-
health_check: "Running health checks",
|
|
5651
|
-
draining: "Switching traffic & draining old instance",
|
|
5652
|
-
complete: "Complete",
|
|
5653
|
-
rolling_back: "Rolling back",
|
|
5654
|
-
rollback_done: "Rollback complete",
|
|
5655
|
-
db_handoff: "Database handoff",
|
|
5656
|
-
// Prewarm-detach phases
|
|
5657
|
-
awaiting_userdata: "Waiting for instance readiness",
|
|
5658
|
-
draining_old: "Draining old instance",
|
|
5659
|
-
detached: "Detaching storage",
|
|
5660
|
-
attached_to_new: "Attaching storage to new instance",
|
|
5661
|
-
finalizing: "Finalizing new instance",
|
|
5662
|
-
flipping: "Switching traffic",
|
|
5663
|
-
teardown_old: "Cleaning up old instance"
|
|
5664
|
-
};
|
|
5665
|
-
async function fetchUpgradePhase(userApiClient, appId) {
|
|
5666
|
-
try {
|
|
5667
|
-
const deployments = await userApiClient.getDeployments(appId);
|
|
5668
|
-
if (deployments.length === 0) return void 0;
|
|
5669
|
-
const sorted = [...deployments].sort((a, b) => {
|
|
5670
|
-
const ta = a.createdAt ? new Date(a.createdAt).getTime() : 0;
|
|
5671
|
-
const tb = b.createdAt ? new Date(b.createdAt).getTime() : 0;
|
|
5672
|
-
return tb - ta;
|
|
5673
|
-
});
|
|
5674
|
-
return sorted[0].upgradePhase || void 0;
|
|
5675
|
-
} catch {
|
|
5676
|
-
return void 0;
|
|
5677
|
-
}
|
|
5678
|
-
}
|
|
5679
6791
|
async function watchUntilUpgradeComplete(options, logger) {
|
|
5680
6792
|
const { walletClient, publicClient, environmentConfig, appId } = options;
|
|
6793
|
+
const timeoutSeconds = resolveWatchTimeoutSeconds(options.timeoutSeconds);
|
|
5681
6794
|
const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
|
|
5682
6795
|
let initialStatus;
|
|
5683
6796
|
let initialIP;
|
|
5684
6797
|
let hasChanged = false;
|
|
5685
|
-
const startTime = Date.now();
|
|
5686
|
-
let lastLoggedStatus;
|
|
5687
|
-
let lastLoggedPhase;
|
|
5688
6798
|
const stopCondition = (status, ip) => {
|
|
5689
6799
|
if (!initialStatus) {
|
|
5690
6800
|
initialStatus = status;
|
|
@@ -5718,37 +6828,44 @@ async function watchUntilUpgradeComplete(options, logger) {
|
|
|
5718
6828
|
}
|
|
5719
6829
|
return false;
|
|
5720
6830
|
};
|
|
6831
|
+
const startTime = Date.now();
|
|
6832
|
+
const deadline = startTime + timeoutSeconds * 1e3;
|
|
6833
|
+
let lastLoggedStatus;
|
|
6834
|
+
let lastObservedStatus;
|
|
5721
6835
|
while (true) {
|
|
6836
|
+
if (Date.now() >= deadline) {
|
|
6837
|
+
const elapsedSeconds = Math.round((Date.now() - startTime) / 1e3);
|
|
6838
|
+
throw new WatchTimeoutError({
|
|
6839
|
+
appId,
|
|
6840
|
+
lastStatus: lastObservedStatus,
|
|
6841
|
+
elapsedSeconds,
|
|
6842
|
+
timeoutSeconds
|
|
6843
|
+
});
|
|
6844
|
+
}
|
|
5722
6845
|
try {
|
|
5723
|
-
const
|
|
5724
|
-
|
|
5725
|
-
fetchUpgradePhase(userApiClient, appId)
|
|
5726
|
-
]);
|
|
5727
|
-
if (infoResult.length === 0) {
|
|
6846
|
+
const info = await userApiClient.getInfos([appId], 1);
|
|
6847
|
+
if (info.length === 0) {
|
|
5728
6848
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
5729
6849
|
continue;
|
|
5730
6850
|
}
|
|
5731
|
-
const appInfo =
|
|
6851
|
+
const appInfo = info[0];
|
|
5732
6852
|
const currentStatus = appInfo.status;
|
|
5733
6853
|
const currentIP = appInfo.ip || "";
|
|
6854
|
+
lastObservedStatus = currentStatus;
|
|
5734
6855
|
const elapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
5735
|
-
if (
|
|
5736
|
-
const label = UPGRADE_PHASE_LABELS[upgradePhase] || upgradePhase;
|
|
5737
|
-
logger.info(`Phase: ${label} (${elapsed}s)`);
|
|
5738
|
-
lastLoggedPhase = upgradePhase;
|
|
5739
|
-
}
|
|
5740
|
-
if (!upgradePhase && currentStatus !== lastLoggedStatus) {
|
|
6856
|
+
if (currentStatus !== lastLoggedStatus) {
|
|
5741
6857
|
logger.info(`Status: ${currentStatus} (${elapsed}s)`);
|
|
5742
6858
|
lastLoggedStatus = currentStatus;
|
|
5743
6859
|
}
|
|
5744
6860
|
if (stopCondition(currentStatus, currentIP)) {
|
|
5745
|
-
const totalElapsed = Math.round((Date.now() - startTime) / 1e3);
|
|
5746
|
-
logger.info(`Upgrade completed in ${totalElapsed}s`);
|
|
5747
6861
|
return;
|
|
5748
6862
|
}
|
|
5749
6863
|
await sleep2(WATCH_POLL_INTERVAL_SECONDS * 1e3);
|
|
5750
6864
|
} catch (error) {
|
|
5751
|
-
if (error
|
|
6865
|
+
if (error instanceof WatchTimeoutError) {
|
|
6866
|
+
throw error;
|
|
6867
|
+
}
|
|
6868
|
+
if (typeof error?.message === "string" && error.message.includes("Failed")) {
|
|
5752
6869
|
throw error;
|
|
5753
6870
|
}
|
|
5754
6871
|
logger.warn(`Failed to fetch app info: ${error.message}`);
|
|
@@ -5859,27 +6976,28 @@ var ChainAddresses = {
|
|
|
5859
6976
|
PermissionController: "0x44632dfBdCb6D3E21EF613B0ca8A6A0c618F5a37"
|
|
5860
6977
|
}
|
|
5861
6978
|
};
|
|
5862
|
-
var PLATFORM_ENV_TESTNET_SEPOLIA = "testnet-sepolia";
|
|
5863
|
-
var PLATFORM_ENV_MAINNET_ETHEREUM = "mainnet-ethereum";
|
|
5864
|
-
var DEFAULT_APP_BASE_DOMAIN = "eigencloud.xyz";
|
|
5865
6979
|
var ENVIRONMENTS = {
|
|
5866
6980
|
"sepolia-dev": {
|
|
5867
6981
|
name: "sepolia",
|
|
5868
6982
|
build: "dev",
|
|
5869
6983
|
appControllerAddress: "0xa86DC1C47cb2518327fB4f9A1627F51966c83B92",
|
|
6984
|
+
releaseAbiVersion: "v1.5",
|
|
6985
|
+
// AppController upgraded to v1.5.x (containerPolicy)
|
|
5870
6986
|
permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
|
|
5871
6987
|
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
5872
6988
|
kmsServerURL: "http://10.128.0.57:8080",
|
|
5873
6989
|
userApiServerURL: "https://userapi-compute-sepolia-dev.eigencloud.xyz",
|
|
5874
6990
|
defaultRPCURL: "https://ethereum-sepolia-rpc.publicnode.com",
|
|
5875
6991
|
usdcCreditsAddress: "0xbdA3897c3A428763B59015C64AB766c288C97376",
|
|
5876
|
-
|
|
5877
|
-
|
|
6992
|
+
baseUsdcCreditsAddress: "0x7673a47463F80c6a3553Db9E54c8cDcd5313d0ac",
|
|
6993
|
+
baseRPCURL: "https://base-sepolia-rpc.publicnode.com"
|
|
5878
6994
|
},
|
|
5879
6995
|
sepolia: {
|
|
5880
6996
|
name: "sepolia",
|
|
5881
6997
|
build: "prod",
|
|
5882
6998
|
appControllerAddress: "0x0dd810a6ffba6a9820a10d97b659f07d8d23d4E2",
|
|
6999
|
+
releaseAbiVersion: "v1.4",
|
|
7000
|
+
// prod still on AppController v1.4.0 (3-field Release)
|
|
5883
7001
|
permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
|
|
5884
7002
|
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
5885
7003
|
kmsServerURL: "http://10.128.15.203:8080",
|
|
@@ -5887,21 +7005,21 @@ var ENVIRONMENTS = {
|
|
|
5887
7005
|
defaultRPCURL: "https://ethereum-sepolia-rpc.publicnode.com",
|
|
5888
7006
|
billingRPCURL: "https://ethereum-rpc.publicnode.com",
|
|
5889
7007
|
usdcCreditsAddress: "0xed9c88640ca9149Bd9f7ee6620074af10F2E145d",
|
|
5890
|
-
|
|
5891
|
-
|
|
7008
|
+
baseUsdcCreditsAddress: "0x7673a47463F80c6a3553Db9E54c8cDcd5313d0ac",
|
|
7009
|
+
baseRPCURL: "https://base-sepolia-rpc.publicnode.com"
|
|
5892
7010
|
},
|
|
5893
7011
|
"mainnet-alpha": {
|
|
5894
7012
|
name: "mainnet-alpha",
|
|
5895
7013
|
build: "prod",
|
|
5896
7014
|
appControllerAddress: "0xc38d35Fc995e75342A21CBd6D770305b142Fbe67",
|
|
7015
|
+
releaseAbiVersion: "v1.4",
|
|
7016
|
+
// prod still on AppController v1.4.0 (3-field Release)
|
|
5897
7017
|
permissionControllerAddress: ChainAddresses[MAINNET_CHAIN_ID].PermissionController,
|
|
5898
7018
|
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
5899
7019
|
kmsServerURL: "http://10.128.0.2:8080",
|
|
5900
7020
|
userApiServerURL: "https://userapi-compute.eigencloud.xyz",
|
|
5901
7021
|
defaultRPCURL: "https://ethereum-rpc.publicnode.com",
|
|
5902
|
-
usdcCreditsAddress: "0xed9c88640ca9149Bd9f7ee6620074af10F2E145d"
|
|
5903
|
-
platformEnv: PLATFORM_ENV_MAINNET_ETHEREUM,
|
|
5904
|
-
appBaseDomain: DEFAULT_APP_BASE_DOMAIN
|
|
7022
|
+
usdcCreditsAddress: "0xed9c88640ca9149Bd9f7ee6620074af10F2E145d"
|
|
5905
7023
|
}
|
|
5906
7024
|
};
|
|
5907
7025
|
var CHAIN_ID_TO_ENVIRONMENT = {
|
|
@@ -5945,7 +7063,7 @@ function getEnvironmentConfig(environment, chainID) {
|
|
|
5945
7063
|
};
|
|
5946
7064
|
}
|
|
5947
7065
|
function getBuildType() {
|
|
5948
|
-
const buildTimeType = true ? "
|
|
7066
|
+
const buildTimeType = true ? "prod"?.toLowerCase() : void 0;
|
|
5949
7067
|
const runtimeType = process.env.BUILD_TYPE?.toLowerCase();
|
|
5950
7068
|
const buildType = buildTimeType || runtimeType;
|
|
5951
7069
|
if (buildType === "dev") {
|
|
@@ -6296,6 +7414,11 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
|
|
|
6296
7414
|
executions: batch.executions,
|
|
6297
7415
|
authorizationList
|
|
6298
7416
|
});
|
|
7417
|
+
await assertSufficientGas({
|
|
7418
|
+
publicClient: batch.publicClient,
|
|
7419
|
+
address: batch.walletClient.account.address,
|
|
7420
|
+
gasEstimate
|
|
7421
|
+
});
|
|
6299
7422
|
const data = {
|
|
6300
7423
|
appId: batch.appId,
|
|
6301
7424
|
salt: batch.salt,
|
|
@@ -6554,6 +7677,11 @@ async function prepareDeploy(options, logger = defaultLogger) {
|
|
|
6554
7677
|
executions: batch.executions,
|
|
6555
7678
|
authorizationList
|
|
6556
7679
|
});
|
|
7680
|
+
await assertSufficientGas({
|
|
7681
|
+
publicClient: batch.publicClient,
|
|
7682
|
+
address: batch.walletClient.account.address,
|
|
7683
|
+
gasEstimate
|
|
7684
|
+
});
|
|
6557
7685
|
const data = {
|
|
6558
7686
|
appId: batch.appId,
|
|
6559
7687
|
salt: batch.salt,
|
|
@@ -6590,7 +7718,7 @@ async function executeDeploy(options) {
|
|
|
6590
7718
|
}
|
|
6591
7719
|
);
|
|
6592
7720
|
}
|
|
6593
|
-
async function watchDeployment(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
|
|
7721
|
+
async function watchDeployment(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry, opts) {
|
|
6594
7722
|
return withSDKTelemetry(
|
|
6595
7723
|
{
|
|
6596
7724
|
functionName: "watchDeployment",
|
|
@@ -6606,7 +7734,8 @@ async function watchDeployment(appId, walletClient, publicClient, environmentCon
|
|
|
6606
7734
|
walletClient,
|
|
6607
7735
|
publicClient,
|
|
6608
7736
|
environmentConfig,
|
|
6609
|
-
appId
|
|
7737
|
+
appId,
|
|
7738
|
+
timeoutSeconds: opts?.timeoutSeconds
|
|
6610
7739
|
},
|
|
6611
7740
|
logger
|
|
6612
7741
|
);
|
|
@@ -6702,6 +7831,11 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
|
|
|
6702
7831
|
executions: batch.executions,
|
|
6703
7832
|
authorizationList
|
|
6704
7833
|
});
|
|
7834
|
+
await assertSufficientGas({
|
|
7835
|
+
publicClient: batch.publicClient,
|
|
7836
|
+
address: batch.walletClient.account.address,
|
|
7837
|
+
gasEstimate
|
|
7838
|
+
});
|
|
6705
7839
|
const data = {
|
|
6706
7840
|
appId: batch.appId,
|
|
6707
7841
|
executions: batch.executions,
|
|
@@ -6891,6 +8025,11 @@ async function prepareUpgrade(options, logger = defaultLogger) {
|
|
|
6891
8025
|
executions: batch.executions,
|
|
6892
8026
|
authorizationList
|
|
6893
8027
|
});
|
|
8028
|
+
await assertSufficientGas({
|
|
8029
|
+
publicClient: batch.publicClient,
|
|
8030
|
+
address: batch.walletClient.account.address,
|
|
8031
|
+
gasEstimate
|
|
8032
|
+
});
|
|
6894
8033
|
const data = {
|
|
6895
8034
|
appId: batch.appId,
|
|
6896
8035
|
executions: batch.executions,
|
|
@@ -6925,7 +8064,7 @@ async function executeUpgrade(options) {
|
|
|
6925
8064
|
}
|
|
6926
8065
|
);
|
|
6927
8066
|
}
|
|
6928
|
-
async function watchUpgrade(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
|
|
8067
|
+
async function watchUpgrade(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry, opts) {
|
|
6929
8068
|
return withSDKTelemetry(
|
|
6930
8069
|
{
|
|
6931
8070
|
functionName: "watchUpgrade",
|
|
@@ -6941,7 +8080,8 @@ async function watchUpgrade(appId, walletClient, publicClient, environmentConfig
|
|
|
6941
8080
|
walletClient,
|
|
6942
8081
|
publicClient,
|
|
6943
8082
|
environmentConfig,
|
|
6944
|
-
appId
|
|
8083
|
+
appId,
|
|
8084
|
+
timeoutSeconds: opts?.timeoutSeconds
|
|
6945
8085
|
},
|
|
6946
8086
|
logger
|
|
6947
8087
|
);
|
|
@@ -7633,7 +8773,7 @@ function createAppModule(ctx) {
|
|
|
7633
8773
|
}
|
|
7634
8774
|
const account = walletClient.account;
|
|
7635
8775
|
const environment = getEnvironmentConfig(ctx.environment);
|
|
7636
|
-
const logger = getLogger(ctx.verbose);
|
|
8776
|
+
const logger = ctx.logger ?? getLogger(ctx.verbose);
|
|
7637
8777
|
return {
|
|
7638
8778
|
async create(opts) {
|
|
7639
8779
|
return createApp(opts, logger);
|
|
@@ -7745,14 +8885,15 @@ function createAppModule(ctx) {
|
|
|
7745
8885
|
imageRef: result.imageRef
|
|
7746
8886
|
};
|
|
7747
8887
|
},
|
|
7748
|
-
async watchDeployment(appId) {
|
|
8888
|
+
async watchDeployment(appId, opts) {
|
|
7749
8889
|
return watchDeployment(
|
|
7750
8890
|
appId,
|
|
7751
8891
|
walletClient,
|
|
7752
8892
|
publicClient,
|
|
7753
8893
|
environment,
|
|
7754
8894
|
logger,
|
|
7755
|
-
skipTelemetry
|
|
8895
|
+
skipTelemetry,
|
|
8896
|
+
opts
|
|
7756
8897
|
);
|
|
7757
8898
|
},
|
|
7758
8899
|
// Granular upgrade control
|
|
@@ -7810,8 +8951,16 @@ function createAppModule(ctx) {
|
|
|
7810
8951
|
imageRef: result.imageRef
|
|
7811
8952
|
};
|
|
7812
8953
|
},
|
|
7813
|
-
async watchUpgrade(appId) {
|
|
7814
|
-
return watchUpgrade(
|
|
8954
|
+
async watchUpgrade(appId, opts) {
|
|
8955
|
+
return watchUpgrade(
|
|
8956
|
+
appId,
|
|
8957
|
+
walletClient,
|
|
8958
|
+
publicClient,
|
|
8959
|
+
environment,
|
|
8960
|
+
logger,
|
|
8961
|
+
skipTelemetry,
|
|
8962
|
+
opts
|
|
8963
|
+
);
|
|
7815
8964
|
},
|
|
7816
8965
|
// Profile management
|
|
7817
8966
|
async setProfile(appId, profile) {
|