@fairmint/canton-node-sdk 0.0.225 → 0.0.227
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/package.json +1 -1
- package/scripts/localnet-cloud.sh +369 -73
package/package.json
CHANGED
|
@@ -10,6 +10,11 @@ DOCKERD_LOG_FILE="/tmp/localnet-dockerd.log"
|
|
|
10
10
|
HOSTS_ENTRY="127.0.0.1 scan.localhost sv.localhost wallet.localhost"
|
|
11
11
|
CURL_CONNECT_TIMEOUT=2
|
|
12
12
|
CURL_MAX_TIME=5
|
|
13
|
+
LOCALNET_SPLICE_VERSION="${CANTON_LOCALNET_SPLICE_VERSION:-}"
|
|
14
|
+
LOCALNET_SCRIBE_VERSION="${CANTON_LOCALNET_SCRIBE_VERSION:-}"
|
|
15
|
+
LOCALNET_PROTOCOL_VERSION="${CANTON_LOCALNET_PROTOCOL_VERSION:-}"
|
|
16
|
+
VALIDATOR_READY_ATTEMPTS="${CANTON_LOCALNET_VALIDATOR_READY_ATTEMPTS:-90}"
|
|
17
|
+
SCAN_READY_ATTEMPTS="${CANTON_LOCALNET_SCAN_READY_ATTEMPTS:-90}"
|
|
13
18
|
|
|
14
19
|
log() {
|
|
15
20
|
printf '[localnet] %s\n' "$*"
|
|
@@ -34,6 +39,21 @@ require_command() {
|
|
|
34
39
|
fi
|
|
35
40
|
}
|
|
36
41
|
|
|
42
|
+
require_positive_integer() {
|
|
43
|
+
local name="$1"
|
|
44
|
+
local value="$2"
|
|
45
|
+
|
|
46
|
+
if [[ ! "${value}" =~ ^[1-9][0-9]*$ ]]; then
|
|
47
|
+
log "${name} must be a positive integer; received '${value}'."
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
validate_configuration() {
|
|
53
|
+
require_positive_integer "CANTON_LOCALNET_VALIDATOR_READY_ATTEMPTS" "${VALIDATOR_READY_ATTEMPTS}"
|
|
54
|
+
require_positive_integer "CANTON_LOCALNET_SCAN_READY_ATTEMPTS" "${SCAN_READY_ATTEMPTS}"
|
|
55
|
+
}
|
|
56
|
+
|
|
37
57
|
ensure_sudo() {
|
|
38
58
|
if ! sudo_noninteractive_available; then
|
|
39
59
|
log "Passwordless sudo is required in this cloud environment."
|
|
@@ -147,6 +167,7 @@ run_quickstart_command() {
|
|
|
147
167
|
local command="$1"
|
|
148
168
|
local docker_shim_dir=""
|
|
149
169
|
local quickstart_image_tag=""
|
|
170
|
+
local quickstart_path="${HOME}/.dpm/bin:${HOME}/.daml/bin:${PATH}"
|
|
150
171
|
local status=0
|
|
151
172
|
|
|
152
173
|
quickstart_image_tag="$(resolve_quickstart_image_tag)"
|
|
@@ -161,28 +182,20 @@ EOF
|
|
|
161
182
|
log "Using sudo docker shim for quickstart command."
|
|
162
183
|
fi
|
|
163
184
|
|
|
164
|
-
set +e
|
|
165
185
|
if [[ -n "${docker_shim_dir}" ]]; then
|
|
166
|
-
|
|
167
|
-
cd "${QUICKSTART_DIR}"
|
|
168
|
-
MODULES_DIR="${QUICKSTART_DIR}/docker/modules" \
|
|
169
|
-
LOCALNET_DIR="${QUICKSTART_DIR}/docker/modules/localnet" \
|
|
170
|
-
IMAGE_TAG="${quickstart_image_tag}" \
|
|
171
|
-
PATH="${docker_shim_dir}:${HOME}/.daml/bin:${PATH}" \
|
|
172
|
-
bash -lc "${command}"
|
|
173
|
-
)
|
|
174
|
-
status=$?
|
|
175
|
-
else
|
|
176
|
-
(
|
|
177
|
-
cd "${QUICKSTART_DIR}"
|
|
178
|
-
MODULES_DIR="${QUICKSTART_DIR}/docker/modules" \
|
|
179
|
-
LOCALNET_DIR="${QUICKSTART_DIR}/docker/modules/localnet" \
|
|
180
|
-
IMAGE_TAG="${quickstart_image_tag}" \
|
|
181
|
-
PATH="${HOME}/.daml/bin:${PATH}" \
|
|
182
|
-
bash -lc "${command}"
|
|
183
|
-
)
|
|
184
|
-
status=$?
|
|
186
|
+
quickstart_path="${docker_shim_dir}:${quickstart_path}"
|
|
185
187
|
fi
|
|
188
|
+
|
|
189
|
+
set +e
|
|
190
|
+
(
|
|
191
|
+
cd "${QUICKSTART_DIR}"
|
|
192
|
+
MODULES_DIR="${QUICKSTART_DIR}/docker/modules" \
|
|
193
|
+
LOCALNET_DIR="${QUICKSTART_DIR}/docker/modules/localnet" \
|
|
194
|
+
IMAGE_TAG="${quickstart_image_tag}" \
|
|
195
|
+
PATH="${quickstart_path}" \
|
|
196
|
+
bash -lc "${command}"
|
|
197
|
+
)
|
|
198
|
+
status=$?
|
|
186
199
|
set -e
|
|
187
200
|
|
|
188
201
|
if [[ -n "${docker_shim_dir}" ]]; then
|
|
@@ -199,19 +212,28 @@ run_quickstart_make() {
|
|
|
199
212
|
|
|
200
213
|
run_infra_compose() {
|
|
201
214
|
local compose_args="$1"
|
|
215
|
+
local keycloak_compose_file=""
|
|
216
|
+
local keycloak_env_file=""
|
|
217
|
+
local keycloak_profile=""
|
|
218
|
+
|
|
219
|
+
if [[ "$(current_auth_mode)" == "oauth2" ]]; then
|
|
220
|
+
keycloak_compose_file='-f "${MODULES_DIR}/keycloak/compose.yaml"'
|
|
221
|
+
keycloak_env_file='--env-file "${MODULES_DIR}/keycloak/compose.env"'
|
|
222
|
+
keycloak_profile='--profile keycloak'
|
|
223
|
+
fi
|
|
202
224
|
|
|
203
225
|
run_quickstart_command "docker compose \
|
|
204
226
|
-f \"\${LOCALNET_DIR}/compose.yaml\" \
|
|
205
|
-
|
|
227
|
+
${keycloak_compose_file} \
|
|
206
228
|
--env-file .env \
|
|
207
229
|
--env-file .env.local \
|
|
208
230
|
--env-file \"\${LOCALNET_DIR}/compose.env\" \
|
|
209
231
|
--env-file \"\${LOCALNET_DIR}/env/common.env\" \
|
|
210
|
-
|
|
232
|
+
${keycloak_env_file} \
|
|
211
233
|
--profile app-provider \
|
|
212
234
|
--profile app-user \
|
|
213
235
|
--profile sv \
|
|
214
|
-
|
|
236
|
+
${keycloak_profile} \
|
|
215
237
|
${compose_args}"
|
|
216
238
|
}
|
|
217
239
|
|
|
@@ -308,25 +330,276 @@ ensure_hosts_entries() {
|
|
|
308
330
|
fi
|
|
309
331
|
}
|
|
310
332
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
333
|
+
set_quickstart_env_value() {
|
|
334
|
+
local file="$1"
|
|
335
|
+
local key="$2"
|
|
336
|
+
local value="$3"
|
|
337
|
+
|
|
338
|
+
if [[ ! -f "${file}" ]]; then
|
|
339
|
+
return
|
|
340
|
+
fi
|
|
341
|
+
|
|
342
|
+
if grep -Eq "^${key}=" "${file}"; then
|
|
343
|
+
KEY="${key}" VALUE="${value}" perl -0pi -e '
|
|
344
|
+
my $key = $ENV{"KEY"};
|
|
345
|
+
my $value = $ENV{"VALUE"};
|
|
346
|
+
s/^\Q$key\E=.*/$key=$value/m;
|
|
347
|
+
' "${file}"
|
|
348
|
+
else
|
|
349
|
+
printf '\n%s=%s\n' "${key}" "${value}" >>"${file}"
|
|
350
|
+
fi
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
patch_quickstart_canton_healthcheck() {
|
|
354
|
+
local healthcheck="${QUICKSTART_DIR}/docker/modules/localnet/docker/canton/health-check.sh"
|
|
355
|
+
|
|
356
|
+
if [[ ! -f "${healthcheck}" ]]; then
|
|
357
|
+
log "Canton quickstart healthcheck not found: ${healthcheck}"
|
|
358
|
+
exit 1
|
|
359
|
+
fi
|
|
360
|
+
|
|
361
|
+
cat >"${healthcheck}" <<'EOF'
|
|
362
|
+
#!/bin/bash
|
|
363
|
+
set -eou pipefail
|
|
364
|
+
|
|
365
|
+
http_check() {
|
|
366
|
+
local port="$1"
|
|
367
|
+
local path="$2"
|
|
368
|
+
local status=""
|
|
369
|
+
|
|
370
|
+
echo "Checking http://localhost:${port}${path}"
|
|
371
|
+
exec 3<>"/dev/tcp/127.0.0.1/${port}"
|
|
372
|
+
printf 'GET %s HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n' "${path}" >&3
|
|
373
|
+
IFS=$'\r' read -r status <&3 || true
|
|
374
|
+
exec 3<&-
|
|
375
|
+
exec 3>&-
|
|
376
|
+
|
|
377
|
+
case "${status}" in
|
|
378
|
+
HTTP/*\ 2*) ;;
|
|
379
|
+
*)
|
|
380
|
+
echo "Unexpected status from ${port}${path}: ${status}"
|
|
381
|
+
return 1
|
|
382
|
+
;;
|
|
383
|
+
esac
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if [ "${APP_USER_PROFILE:-off}" = "on" ]; then
|
|
387
|
+
http_check "2${CANTON_HTTP_HEALTHCHECK_PORT_SUFFIX}" "/health"
|
|
388
|
+
fi
|
|
389
|
+
if [ "${APP_PROVIDER_PROFILE:-off}" = "on" ]; then
|
|
390
|
+
http_check "3${CANTON_HTTP_HEALTHCHECK_PORT_SUFFIX}" "/health"
|
|
391
|
+
fi
|
|
392
|
+
if [ "${SV_PROFILE:-off}" = "on" ]; then
|
|
393
|
+
http_check "4${CANTON_HTTP_HEALTHCHECK_PORT_SUFFIX}" "/health"
|
|
394
|
+
fi
|
|
395
|
+
EOF
|
|
396
|
+
chmod +x "${healthcheck}"
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
patch_quickstart_splice_healthcheck() {
|
|
400
|
+
local healthcheck="${QUICKSTART_DIR}/docker/modules/localnet/docker/splice/health-check.sh"
|
|
401
|
+
|
|
402
|
+
if [[ ! -f "${healthcheck}" ]]; then
|
|
403
|
+
log "Splice quickstart healthcheck not found: ${healthcheck}"
|
|
404
|
+
exit 1
|
|
405
|
+
fi
|
|
406
|
+
|
|
407
|
+
cat >"${healthcheck}" <<'EOF'
|
|
408
|
+
#!/bin/bash
|
|
409
|
+
set -eou pipefail
|
|
410
|
+
|
|
411
|
+
http_check() {
|
|
412
|
+
local port="$1"
|
|
413
|
+
local path="$2"
|
|
414
|
+
local status=""
|
|
415
|
+
|
|
416
|
+
echo "Checking http://localhost:${port}${path}"
|
|
417
|
+
exec 3<>"/dev/tcp/127.0.0.1/${port}"
|
|
418
|
+
printf 'GET %s HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n' "${path}" >&3
|
|
419
|
+
IFS=$'\r' read -r status <&3 || true
|
|
420
|
+
exec 3<&-
|
|
421
|
+
exec 3>&-
|
|
422
|
+
|
|
423
|
+
case "${status}" in
|
|
424
|
+
HTTP/*\ 2*) ;;
|
|
425
|
+
*)
|
|
426
|
+
echo "Unexpected status from ${port}${path}: ${status}"
|
|
427
|
+
return 1
|
|
428
|
+
;;
|
|
429
|
+
esac
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if [ "${APP_USER_PROFILE:-off}" = "on" ]; then
|
|
433
|
+
http_check "2${VALIDATOR_ADMIN_API_PORT_SUFFIX}" "/api/validator/readyz"
|
|
434
|
+
fi
|
|
435
|
+
if [ "${APP_PROVIDER_PROFILE:-off}" = "on" ]; then
|
|
436
|
+
http_check "3${VALIDATOR_ADMIN_API_PORT_SUFFIX}" "/api/validator/readyz"
|
|
437
|
+
fi
|
|
438
|
+
if [ "${SV_PROFILE:-off}" = "on" ]; then
|
|
439
|
+
http_check "4${VALIDATOR_ADMIN_API_PORT_SUFFIX}" "/api/validator/readyz"
|
|
440
|
+
http_check "5012" "/api/scan/readyz"
|
|
441
|
+
http_check "5014" "/api/sv/readyz"
|
|
442
|
+
fi
|
|
443
|
+
EOF
|
|
444
|
+
chmod +x "${healthcheck}"
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
configure_quickstart_localnet() {
|
|
448
|
+
local env_file=""
|
|
449
|
+
local canton_conf="${QUICKSTART_DIR}/docker/modules/localnet/conf/canton/app.conf"
|
|
450
|
+
|
|
451
|
+
for env_file in "${QUICKSTART_DIR}/.env" "${QUICKSTART_DIR}/.env.local"; do
|
|
452
|
+
if [[ -n "${LOCALNET_SPLICE_VERSION}" ]]; then
|
|
453
|
+
set_quickstart_env_value "${env_file}" "SPLICE_VERSION" "${LOCALNET_SPLICE_VERSION}"
|
|
454
|
+
fi
|
|
455
|
+
if [[ -n "${LOCALNET_SCRIBE_VERSION}" ]]; then
|
|
456
|
+
set_quickstart_env_value "${env_file}" "SCRIBE_VERSION" "${LOCALNET_SCRIBE_VERSION}"
|
|
457
|
+
fi
|
|
458
|
+
if [[ -n "${CANTON_LOCALNET_DAML_RUNTIME_VERSION:-}" ]]; then
|
|
459
|
+
set_quickstart_env_value "${env_file}" "DAML_RUNTIME_VERSION" "${CANTON_LOCALNET_DAML_RUNTIME_VERSION}"
|
|
460
|
+
fi
|
|
461
|
+
done
|
|
462
|
+
|
|
463
|
+
if [[ ! -f "${canton_conf}" ]]; then
|
|
464
|
+
log "Canton quickstart config not found: ${canton_conf}"
|
|
465
|
+
exit 1
|
|
466
|
+
fi
|
|
467
|
+
|
|
468
|
+
if [[ -n "${LOCALNET_PROTOCOL_VERSION}" ]]; then
|
|
469
|
+
PROTOCOL_VERSION="${LOCALNET_PROTOCOL_VERSION}" perl -0pi -e '
|
|
470
|
+
my $protocol_version = $ENV{"PROTOCOL_VERSION"};
|
|
471
|
+
s/initial-protocol-version = \d+/initial-protocol-version = $protocol_version/g;
|
|
472
|
+
s/(non-standard-config = yes\n)(?![[:space:]]*alpha-version-support = yes)/$1 alpha-version-support = yes\n/;
|
|
473
|
+
s/(initial-protocol-version = \d+\n)(?![[:space:]]*alpha-version-support = yes)/$1 alpha-version-support = yes\n/;
|
|
474
|
+
' "${canton_conf}"
|
|
475
|
+
fi
|
|
476
|
+
|
|
477
|
+
patch_quickstart_canton_healthcheck
|
|
478
|
+
patch_quickstart_splice_healthcheck
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
requested_auth_mode() {
|
|
482
|
+
printf '%s' "${CANTON_LOCALNET_AUTH_MODE:-oauth2}"
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
quickstart_env_value() {
|
|
486
|
+
local key="$1"
|
|
487
|
+
local parsed_value=""
|
|
488
|
+
|
|
489
|
+
if [[ -f "${QUICKSTART_DIR}/.env.local" ]]; then
|
|
490
|
+
parsed_value="$(awk -F= -v key="${key}" '
|
|
491
|
+
$0 ~ /^[[:space:]]*#/ { next }
|
|
492
|
+
$1 == key {
|
|
493
|
+
value = substr($0, index($0, "=") + 1)
|
|
494
|
+
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
|
|
495
|
+
gsub(/^"|"$/, "", value)
|
|
496
|
+
gsub(/^'\''|'\''$/, "", value)
|
|
497
|
+
parsed = value
|
|
498
|
+
}
|
|
499
|
+
END {
|
|
500
|
+
if (parsed != "") {
|
|
501
|
+
print parsed
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
' "${QUICKSTART_DIR}/.env.local")"
|
|
505
|
+
fi
|
|
506
|
+
|
|
507
|
+
printf '%s' "${parsed_value}"
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
configured_auth_mode() {
|
|
511
|
+
quickstart_env_value "AUTH_MODE"
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
quickstart_profile_config_complete() {
|
|
515
|
+
local key=""
|
|
516
|
+
|
|
517
|
+
for key in OBSERVABILITY_ENABLED AUTH_MODE PARTY_HINT TEST_MODE; do
|
|
518
|
+
if [[ -z "$(quickstart_env_value "${key}")" ]]; then
|
|
519
|
+
return 1
|
|
520
|
+
fi
|
|
521
|
+
done
|
|
522
|
+
|
|
523
|
+
return 0
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
verify_configured_auth_mode() {
|
|
527
|
+
local expected_auth_mode="$1"
|
|
528
|
+
local actual_auth_mode=""
|
|
529
|
+
|
|
530
|
+
actual_auth_mode="$(configured_auth_mode)"
|
|
531
|
+
if [[ "${actual_auth_mode}" != "${expected_auth_mode}" ]]; then
|
|
532
|
+
log "cn-quickstart setup did not configure AUTH_MODE=${expected_auth_mode}; found '${actual_auth_mode:-unset}'."
|
|
533
|
+
exit 1
|
|
534
|
+
fi
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
current_auth_mode() {
|
|
538
|
+
local configured=""
|
|
539
|
+
|
|
540
|
+
configured="$(configured_auth_mode)"
|
|
541
|
+
if [[ -n "${configured}" ]]; then
|
|
542
|
+
printf '%s' "${configured}"
|
|
543
|
+
return
|
|
544
|
+
fi
|
|
545
|
+
|
|
546
|
+
requested_auth_mode
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
run_quickstart_setup() {
|
|
550
|
+
local auth_mode=""
|
|
551
|
+
|
|
552
|
+
auth_mode="$(requested_auth_mode)"
|
|
553
|
+
case "${auth_mode}" in
|
|
554
|
+
shared-secret)
|
|
555
|
+
log "Running cn-quickstart setup (shared-secret mode)..."
|
|
556
|
+
(
|
|
557
|
+
cd "${QUICKSTART_DIR}"
|
|
558
|
+
printf 'Y\nn\n\n' | make setup || true
|
|
559
|
+
)
|
|
560
|
+
verify_configured_auth_mode "shared-secret"
|
|
561
|
+
;;
|
|
562
|
+
oauth2)
|
|
316
563
|
log "Running cn-quickstart setup (OAuth2 enabled)..."
|
|
317
564
|
(
|
|
318
565
|
cd "${QUICKSTART_DIR}"
|
|
319
566
|
# Match CI behavior first, then fall back to prompt-based answers for newer setup flows.
|
|
320
567
|
echo "2" | make setup || true
|
|
321
|
-
if
|
|
568
|
+
if [[ "$(configured_auth_mode)" != "oauth2" ]]; then
|
|
322
569
|
printf 'y\ny\n\nn\n' | make setup
|
|
323
570
|
fi
|
|
324
571
|
)
|
|
325
|
-
|
|
572
|
+
verify_configured_auth_mode "oauth2"
|
|
573
|
+
;;
|
|
574
|
+
*)
|
|
575
|
+
log "Unsupported CANTON_LOCALNET_AUTH_MODE: ${auth_mode}"
|
|
576
|
+
exit 1
|
|
577
|
+
;;
|
|
578
|
+
esac
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
quickstart_setup() {
|
|
582
|
+
if [[ ! -f "${QUICKSTART_DIR}/.env.local" ]]; then
|
|
583
|
+
run_quickstart_setup
|
|
584
|
+
elif ! quickstart_profile_config_complete; then
|
|
585
|
+
log "Regenerating incomplete cn-quickstart config."
|
|
586
|
+
rm -f "${QUICKSTART_DIR}/.env.local"
|
|
587
|
+
run_quickstart_setup
|
|
588
|
+
elif [[ -n "${CANTON_LOCALNET_AUTH_MODE:-}" && "$(configured_auth_mode)" != "${CANTON_LOCALNET_AUTH_MODE}" ]]; then
|
|
589
|
+
log "Regenerating cn-quickstart config for CANTON_LOCALNET_AUTH_MODE=${CANTON_LOCALNET_AUTH_MODE}."
|
|
590
|
+
rm -f "${QUICKSTART_DIR}/.env.local"
|
|
591
|
+
run_quickstart_setup
|
|
326
592
|
else
|
|
327
593
|
log "Reusing existing ${QUICKSTART_DIR}/.env.local."
|
|
328
594
|
fi
|
|
329
595
|
|
|
596
|
+
if [[ ! -f "${QUICKSTART_DIR}/.env.local" ]]; then
|
|
597
|
+
log "cn-quickstart setup failed: ${QUICKSTART_DIR}/.env.local was not created."
|
|
598
|
+
exit 1
|
|
599
|
+
fi
|
|
600
|
+
|
|
601
|
+
configure_quickstart_localnet
|
|
602
|
+
|
|
330
603
|
if quickstart_infra_only_enabled; then
|
|
331
604
|
log "Skipping Daml SDK install for infrastructure-only localnet."
|
|
332
605
|
return
|
|
@@ -343,37 +616,6 @@ quickstart_setup() {
|
|
|
343
616
|
fi
|
|
344
617
|
}
|
|
345
618
|
|
|
346
|
-
default_party_hint() {
|
|
347
|
-
local clean_user=""
|
|
348
|
-
local raw_user="${USER:-runner}"
|
|
349
|
-
|
|
350
|
-
clean_user="$(printf '%s' "${raw_user}" | tr -cd '[:alpha:]')"
|
|
351
|
-
if [[ -z "${clean_user}" ]]; then
|
|
352
|
-
clean_user="runner"
|
|
353
|
-
fi
|
|
354
|
-
|
|
355
|
-
printf 'quickstart-%s-1' "${clean_user,,}"
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
write_quickstart_env_local() {
|
|
359
|
-
local auth_mode="${CANTON_LOCALNET_AUTH_MODE:-oauth2}"
|
|
360
|
-
local observability_enabled="${CANTON_LOCALNET_OBSERVABILITY_ENABLED:-false}"
|
|
361
|
-
local party_hint="${CANTON_LOCALNET_PARTY_HINT:-}"
|
|
362
|
-
local test_mode="${CANTON_LOCALNET_TEST_MODE:-off}"
|
|
363
|
-
|
|
364
|
-
if [[ -z "${party_hint}" ]]; then
|
|
365
|
-
party_hint="$(default_party_hint)"
|
|
366
|
-
fi
|
|
367
|
-
|
|
368
|
-
log "Writing non-interactive cn-quickstart localnet config."
|
|
369
|
-
cat >"${QUICKSTART_DIR}/.env.local" <<EOF
|
|
370
|
-
OBSERVABILITY_ENABLED=${observability_enabled}
|
|
371
|
-
AUTH_MODE=${auth_mode}
|
|
372
|
-
PARTY_HINT=${party_hint}
|
|
373
|
-
TEST_MODE=${test_mode}
|
|
374
|
-
EOF
|
|
375
|
-
}
|
|
376
|
-
|
|
377
619
|
quickstart_fast_start_enabled() {
|
|
378
620
|
is_truthy "${CANTON_LOCALNET_FAST_START:-true}"
|
|
379
621
|
}
|
|
@@ -448,20 +690,37 @@ stop_infra_only_localnet() {
|
|
|
448
690
|
}
|
|
449
691
|
|
|
450
692
|
wait_for_services() {
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
693
|
+
local auth_mode=""
|
|
694
|
+
local code=""
|
|
695
|
+
local ledger_code=""
|
|
696
|
+
|
|
697
|
+
auth_mode="$(current_auth_mode)"
|
|
698
|
+
|
|
699
|
+
if [[ "${auth_mode}" == "oauth2" ]]; then
|
|
700
|
+
log "Waiting for Keycloak..."
|
|
701
|
+
for _ in $(seq 1 30); do
|
|
702
|
+
if curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -fsS http://localhost:8082/realms/AppProvider >/dev/null 2>&1; then
|
|
703
|
+
break
|
|
704
|
+
fi
|
|
705
|
+
sleep 2
|
|
706
|
+
done
|
|
707
|
+
if ! curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -fsS http://localhost:8082/realms/AppProvider >/dev/null 2>&1; then
|
|
708
|
+
log "Keycloak did not become ready."
|
|
709
|
+
exit 1
|
|
455
710
|
fi
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
711
|
+
else
|
|
712
|
+
log "Checking for Keycloak (optional in ${auth_mode} mode)..."
|
|
713
|
+
for _ in $(seq 1 5); do
|
|
714
|
+
if curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -fsS http://localhost:8082/realms/AppProvider >/dev/null 2>&1; then
|
|
715
|
+
log "Keycloak is ready."
|
|
716
|
+
break
|
|
717
|
+
fi
|
|
718
|
+
sleep 2
|
|
719
|
+
done
|
|
461
720
|
fi
|
|
462
721
|
|
|
463
722
|
log "Waiting for Validator API..."
|
|
464
|
-
for _ in $(seq 1
|
|
723
|
+
for _ in $(seq 1 "${VALIDATOR_READY_ATTEMPTS}"); do
|
|
465
724
|
code="$(curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -sS -o /dev/null -w '%{http_code}' http://localhost:3903/api/validator/v0/wallet/user-status || true)"
|
|
466
725
|
if [[ "${code}" == "200" || "${code}" == "401" ]]; then
|
|
467
726
|
break
|
|
@@ -475,7 +734,7 @@ wait_for_services() {
|
|
|
475
734
|
fi
|
|
476
735
|
|
|
477
736
|
log "Waiting for Scan API..."
|
|
478
|
-
for _ in $(seq 1
|
|
737
|
+
for _ in $(seq 1 "${SCAN_READY_ATTEMPTS}"); do
|
|
479
738
|
if curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -fsS http://scan.localhost:4000/api/scan/v0/dso-party-id >/dev/null 2>&1; then
|
|
480
739
|
break
|
|
481
740
|
fi
|
|
@@ -486,6 +745,20 @@ wait_for_services() {
|
|
|
486
745
|
exit 1
|
|
487
746
|
fi
|
|
488
747
|
|
|
748
|
+
log "Waiting for Ledger JSON API..."
|
|
749
|
+
for _ in $(seq 1 60); do
|
|
750
|
+
ledger_code="$(curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -sS -o /dev/null -w '%{http_code}' http://localhost:3975/v2/version || true)"
|
|
751
|
+
if [[ "${ledger_code}" == "200" || "${ledger_code}" == "401" ]]; then
|
|
752
|
+
break
|
|
753
|
+
fi
|
|
754
|
+
sleep 2
|
|
755
|
+
done
|
|
756
|
+
ledger_code="$(curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -sS -o /dev/null -w '%{http_code}' http://localhost:3975/v2/version || true)"
|
|
757
|
+
if [[ "${ledger_code}" != "200" && "${ledger_code}" != "401" ]]; then
|
|
758
|
+
log "Ledger JSON API did not become ready (HTTP ${ledger_code})."
|
|
759
|
+
exit 1
|
|
760
|
+
fi
|
|
761
|
+
|
|
489
762
|
log "All localnet services are ready."
|
|
490
763
|
}
|
|
491
764
|
|
|
@@ -592,6 +865,7 @@ status_localnet() {
|
|
|
592
865
|
keycloak_ok="no"
|
|
593
866
|
validator_ok="no"
|
|
594
867
|
scan_ok="no"
|
|
868
|
+
ledger_ok="no"
|
|
595
869
|
if curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -fsS http://localhost:8082/realms/AppProvider >/dev/null 2>&1; then
|
|
596
870
|
keycloak_ok="yes"
|
|
597
871
|
fi
|
|
@@ -602,10 +876,15 @@ status_localnet() {
|
|
|
602
876
|
if curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -fsS http://scan.localhost:4000/api/scan/v0/dso-party-id >/dev/null 2>&1; then
|
|
603
877
|
scan_ok="yes"
|
|
604
878
|
fi
|
|
879
|
+
ledger_code="$(curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -sS -o /dev/null -w '%{http_code}' http://localhost:3975/v2/version || true)"
|
|
880
|
+
if [[ "${ledger_code}" == "200" || "${ledger_code}" == "401" ]]; then
|
|
881
|
+
ledger_ok="yes"
|
|
882
|
+
fi
|
|
605
883
|
|
|
606
884
|
printf 'Keycloak ready: %s\n' "${keycloak_ok}"
|
|
607
885
|
printf 'Validator ready: %s (HTTP %s)\n' "${validator_ok}" "${validator_code:-n/a}"
|
|
608
886
|
printf 'Scan ready: %s\n' "${scan_ok}"
|
|
887
|
+
printf 'Ledger JSON API ready: %s (HTTP %s)\n' "${ledger_ok}" "${ledger_code:-n/a}"
|
|
609
888
|
}
|
|
610
889
|
|
|
611
890
|
show_localnet_logs() {
|
|
@@ -642,13 +921,20 @@ show_localnet_logs() {
|
|
|
642
921
|
}
|
|
643
922
|
|
|
644
923
|
run_smoke() {
|
|
924
|
+
local auth_mode=""
|
|
645
925
|
local validator_code=""
|
|
926
|
+
local ledger_code=""
|
|
646
927
|
|
|
647
928
|
log "Running localnet smoke checks..."
|
|
929
|
+
auth_mode="$(current_auth_mode)"
|
|
648
930
|
|
|
649
|
-
if
|
|
931
|
+
if curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -fsS http://localhost:8082/realms/AppProvider >/dev/null 2>&1; then
|
|
932
|
+
log "Keycloak is reachable."
|
|
933
|
+
elif [[ "${auth_mode}" == "oauth2" ]]; then
|
|
650
934
|
log "Keycloak is not reachable."
|
|
651
935
|
exit 1
|
|
936
|
+
else
|
|
937
|
+
log "Keycloak not detected (expected in ${auth_mode} mode)."
|
|
652
938
|
fi
|
|
653
939
|
|
|
654
940
|
validator_code="$(curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -sS -o /dev/null -w '%{http_code}' http://localhost:3903/api/validator/v0/wallet/user-status || true)"
|
|
@@ -662,6 +948,12 @@ run_smoke() {
|
|
|
662
948
|
exit 1
|
|
663
949
|
fi
|
|
664
950
|
|
|
951
|
+
ledger_code="$(curl --connect-timeout "${CURL_CONNECT_TIMEOUT}" --max-time "${CURL_MAX_TIME}" -sS -o /dev/null -w '%{http_code}' http://localhost:3975/v2/version || true)"
|
|
952
|
+
if [[ "${ledger_code}" != "200" && "${ledger_code}" != "401" ]]; then
|
|
953
|
+
log "Ledger JSON API is not reachable (HTTP ${ledger_code})."
|
|
954
|
+
exit 1
|
|
955
|
+
fi
|
|
956
|
+
|
|
665
957
|
log "Smoke checks passed."
|
|
666
958
|
}
|
|
667
959
|
|
|
@@ -751,6 +1043,7 @@ Environment:
|
|
|
751
1043
|
CANTON_LOCALNET_FAST_START=true|false Enable fast startup path (default: true)
|
|
752
1044
|
CANTON_LOCALNET_FORCE_FULL_START=true|false Force full startup with rebuild
|
|
753
1045
|
CANTON_LOCALNET_INFRA_ONLY=true|false Start only LocalNet + Keycloak infrastructure
|
|
1046
|
+
CANTON_LOCALNET_AUTH_MODE=oauth2|shared-secret
|
|
754
1047
|
CANTON_LOCALNET_QUICKSTART_DIR=<path> Use an existing cn-quickstart/quickstart directory
|
|
755
1048
|
USAGE
|
|
756
1049
|
}
|
|
@@ -763,6 +1056,7 @@ main() {
|
|
|
763
1056
|
|
|
764
1057
|
case "$1" in
|
|
765
1058
|
setup)
|
|
1059
|
+
validate_configuration
|
|
766
1060
|
ensure_docker_packages
|
|
767
1061
|
start_docker_daemon
|
|
768
1062
|
ensure_submodules
|
|
@@ -770,6 +1064,7 @@ main() {
|
|
|
770
1064
|
quickstart_setup
|
|
771
1065
|
;;
|
|
772
1066
|
start)
|
|
1067
|
+
validate_configuration
|
|
773
1068
|
require_command curl
|
|
774
1069
|
ensure_docker_packages
|
|
775
1070
|
start_docker_daemon
|
|
@@ -796,6 +1091,7 @@ main() {
|
|
|
796
1091
|
run_integration_tests
|
|
797
1092
|
;;
|
|
798
1093
|
verify)
|
|
1094
|
+
validate_configuration
|
|
799
1095
|
require_command curl
|
|
800
1096
|
ensure_docker_packages
|
|
801
1097
|
start_docker_daemon
|