direxio-deployer 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -2
- package/README_zh.md +10 -2
- package/SKILL.md +32 -8
- package/bin/direxio-deployer.mjs +1 -2
- package/package.json +2 -3
- package/references/agent-targets.md +7 -1
- package/references/deployment-lessons.md +5 -7
- package/references/deployment-workflow.md +8 -4
- package/references/runtime-wiring.md +5 -5
- package/references/tooling.md +11 -12
- package/references/user-journey.md +2 -2
- package/references/voip-turn-runbook.md +2 -2
- package/references/windows-deployment-notes.md +2 -1
- package/scripts/destroy.sh +24 -43
- package/scripts/json.mjs +841 -0
- package/scripts/lib/aws.sh +5 -1
- package/scripts/lib/json.sh +114 -0
- package/scripts/lib/operation_report.sh +8 -195
- package/scripts/lib/ops.sh +8 -21
- package/scripts/lib/state.sh +18 -44
- package/scripts/mcp-tools-list.mjs +66 -5
- package/scripts/orchestrate.sh +166 -249
- package/scripts/phases/s3_provision.sh +5 -10
- package/scripts/phases/s5_init_tokens.sh +7 -17
- package/scripts/phases/s6_wire_local.sh +22 -42
- package/scripts/phases/s7_verify_e2e.sh +5 -5
- package/scripts/pricing-estimate.sh +36 -80
- package/tests/aws_credentials_test.sh +0 -139
- package/tests/connect_daemon_runtime_check_test.sh +0 -120
- package/tests/default_paths_test.sh +0 -58
- package/tests/destroy_local_bridge_test.sh +0 -154
- package/tests/destroy_root_identity_test.sh +0 -91
- package/tests/destroy_route53_zone_test.sh +0 -80
- package/tests/domain_authoritative_dns_test.sh +0 -49
- package/tests/mcp_doctor_runtime_check_test.sh +0 -86
- package/tests/mcp_smoke_runtime_check_test.sh +0 -121
- package/tests/mcp_tools_runtime_check_test.sh +0 -123
- package/tests/npm_skill_distribution_test.sh +0 -95
- package/tests/operation_report_test.sh +0 -258
- package/tests/orchestrate_status_recovery_test.sh +0 -91
- package/tests/phase_timeout_test.sh +0 -88
- package/tests/pricing_estimate_test.sh +0 -159
- package/tests/render_userdata_remote_nodes_test.sh +0 -40
- package/tests/root_volume_tracking_test.sh +0 -41
- package/tests/route53_overwrite_guard_test.sh +0 -86
- package/tests/route53_zone_auto_create_test.sh +0 -66
- package/tests/runtime_summary_check_test.sh +0 -203
- package/tests/s6_wire_local_test.sh +0 -405
- package/tests/skill_structure_test.sh +0 -298
- package/tests/update_reset_ops_test.sh +0 -230
- package/tests/user_confirmation_gates_test.sh +0 -152
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
ROOT=$(cd "$(dirname "$0")/.." && pwd)
|
|
5
|
-
tmp=$(mktemp -d)
|
|
6
|
-
trap 'rm -rf "$tmp"' EXIT
|
|
7
|
-
|
|
8
|
-
export HOME="$tmp/home"
|
|
9
|
-
mkdir -p "$HOME"
|
|
10
|
-
|
|
11
|
-
fakebin="$tmp/bin"
|
|
12
|
-
mkdir -p "$fakebin"
|
|
13
|
-
|
|
14
|
-
cat > "$fakebin/aws" <<'EOF'
|
|
15
|
-
#!/usr/bin/env bash
|
|
16
|
-
set -euo pipefail
|
|
17
|
-
printf 'aws' >> "$CALLS"
|
|
18
|
-
printf ' %q' "$@" >> "$CALLS"
|
|
19
|
-
printf '\n' >> "$CALLS"
|
|
20
|
-
|
|
21
|
-
if [ "${AWS_PRICING_FAIL:-0}" = "1" ]; then
|
|
22
|
-
exit 255
|
|
23
|
-
fi
|
|
24
|
-
|
|
25
|
-
case "${1:-} ${2:-}" in
|
|
26
|
-
"sts get-caller-identity")
|
|
27
|
-
if [ "${AWS_STS_OK:-0}" = "1" ]; then
|
|
28
|
-
printf '{"Account":"123456789012","Arn":"arn:aws:iam::123456789012:user/DirexioDeployer","UserId":"AIDAEXAMPLE"}\n'
|
|
29
|
-
exit 0
|
|
30
|
-
fi
|
|
31
|
-
exit 255
|
|
32
|
-
;;
|
|
33
|
-
esac
|
|
34
|
-
|
|
35
|
-
service=""
|
|
36
|
-
for ((i=1; i<=$#; i++)); do
|
|
37
|
-
arg="${!i}"
|
|
38
|
-
if [ "$arg" = "--service-code" ]; then
|
|
39
|
-
j=$((i+1))
|
|
40
|
-
service="${!j}"
|
|
41
|
-
fi
|
|
42
|
-
done
|
|
43
|
-
|
|
44
|
-
case "$service" in
|
|
45
|
-
AmazonEC2)
|
|
46
|
-
if printf '%s\n' "$*" | grep -q 'instanceType'; then
|
|
47
|
-
rate="0.025"
|
|
48
|
-
else
|
|
49
|
-
rate="0.096"
|
|
50
|
-
fi
|
|
51
|
-
;;
|
|
52
|
-
AmazonVPC)
|
|
53
|
-
rate="0.005"
|
|
54
|
-
;;
|
|
55
|
-
*)
|
|
56
|
-
rate="0.50"
|
|
57
|
-
;;
|
|
58
|
-
esac
|
|
59
|
-
|
|
60
|
-
jq -n --arg rate "$rate" '{
|
|
61
|
-
PriceList: [
|
|
62
|
-
({
|
|
63
|
-
terms: {
|
|
64
|
-
OnDemand: {
|
|
65
|
-
term: {
|
|
66
|
-
priceDimensions: {
|
|
67
|
-
dim: {
|
|
68
|
-
pricePerUnit: {
|
|
69
|
-
USD: $rate
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
} | tojson)
|
|
77
|
-
]
|
|
78
|
-
}'
|
|
79
|
-
EOF
|
|
80
|
-
chmod 700 "$fakebin/aws"
|
|
81
|
-
|
|
82
|
-
assert_file_exists() {
|
|
83
|
-
[ -s "$1" ] || {
|
|
84
|
-
echo "expected non-empty file: $1" >&2
|
|
85
|
-
exit 1
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
CALLS="$tmp/aws.calls"
|
|
90
|
-
export CALLS
|
|
91
|
-
export PATH="$fakebin:$PATH"
|
|
92
|
-
|
|
93
|
-
service_dir="$HOME/.direxio/nodes/pricing.example.test"
|
|
94
|
-
mkdir -p "$service_dir"
|
|
95
|
-
state="$service_dir/state.json"
|
|
96
|
-
jq -n '{
|
|
97
|
-
domain:"pricing.example.test",
|
|
98
|
-
region:"ap-northeast-1",
|
|
99
|
-
domain_mode:"route53",
|
|
100
|
-
instance_type:"t3.small",
|
|
101
|
-
resources:{root_volume_gb:"8"},
|
|
102
|
-
phases:{S7_VERIFY_E2E:{status:"done"}}
|
|
103
|
-
}' > "$state"
|
|
104
|
-
|
|
105
|
-
estimate=$(bash "$ROOT/scripts/pricing-estimate.sh" --state "$state" --write-state)
|
|
106
|
-
printf '%s\n' "$estimate" > "$tmp/estimate.json"
|
|
107
|
-
|
|
108
|
-
jq -e '
|
|
109
|
-
.pricing_status == "queried"
|
|
110
|
-
and .region == "ap-northeast-1"
|
|
111
|
-
and .location == "Asia Pacific (Tokyo)"
|
|
112
|
-
and .hours_per_month == 730
|
|
113
|
-
and .components.ec2_instance.hourly_usd == 0.025
|
|
114
|
-
and .components.ec2_instance.monthly_usd == 18.25
|
|
115
|
-
and .components.ebs_gp3.storage_gb == 8
|
|
116
|
-
and .components.public_ipv4.hourly_usd == 0.005
|
|
117
|
-
and .components.public_ipv4.monthly_usd == 3.65
|
|
118
|
-
and .components.route53_hosted_zone.monthly_usd == 0.5
|
|
119
|
-
and .components.public_ipv4.billed_even_when_attached == true
|
|
120
|
-
and (.recommendations | index("Set an AWS Budget or billing alert before leaving the node running.") != null)
|
|
121
|
-
and (.notes | index("AWS credits may reduce charges only when the account, plan, region, and service usage are eligible; verify in AWS Billing Console.") != null)
|
|
122
|
-
and .total_monthly_usd > 23
|
|
123
|
-
and .total_monthly_usd < 24
|
|
124
|
-
' "$tmp/estimate.json" >/dev/null
|
|
125
|
-
|
|
126
|
-
jq -e '.cost_estimate.pricing_status == "queried" and .cost_estimate.components.public_ipv4.billed_even_when_attached == true' "$state" >/dev/null
|
|
127
|
-
|
|
128
|
-
auto_workdir="$HOME/.direxio/nodes/auto-pricing.example.test"
|
|
129
|
-
set +e
|
|
130
|
-
AWS_DEFAULT_REGION=ap-northeast-1 \
|
|
131
|
-
DOMAIN=auto-pricing.example.test \
|
|
132
|
-
DOMAIN_MODE=user \
|
|
133
|
-
CONFIRM_DOMAIN_BINDING=1 \
|
|
134
|
-
P2P_WORKDIR="$auto_workdir" \
|
|
135
|
-
bash "$ROOT/scripts/orchestrate.sh" > "$tmp/orchestrate.out" 2> "$tmp/orchestrate.err"
|
|
136
|
-
auto_rc=$?
|
|
137
|
-
set -e
|
|
138
|
-
[ "$auto_rc" -ne 0 ] || {
|
|
139
|
-
echo "expected orchestrate test run to stop before real provisioning" >&2
|
|
140
|
-
exit 1
|
|
141
|
-
}
|
|
142
|
-
jq -e '.cost_estimate.pricing_status == "queried" and .cost_estimate.region == "ap-northeast-1"' "$auto_workdir/state.json" >/dev/null
|
|
143
|
-
|
|
144
|
-
report_output=$(P2P_WORKDIR="$service_dir" bash "$ROOT/scripts/orchestrate.sh" report new_deploy)
|
|
145
|
-
report_path=$(printf '%s\n' "$report_output" | sed -nE 's/^operation report: //p' | tail -n 1)
|
|
146
|
-
assert_file_exists "$report_path"
|
|
147
|
-
jq -e '.billing.cost_estimate.pricing_status == "queried" and .billing.cost_estimate.components.public_ipv4.billed_even_when_attached == true' "$report_path" >/dev/null
|
|
148
|
-
|
|
149
|
-
fallback=$(AWS_PRICING_FAIL=1 bash "$ROOT/scripts/pricing-estimate.sh" --region ap-southeast-1 --instance-type t3.small --disk-gb 8 --domain-mode user)
|
|
150
|
-
printf '%s\n' "$fallback" > "$tmp/fallback.json"
|
|
151
|
-
jq -e '
|
|
152
|
-
.pricing_status == "fallback"
|
|
153
|
-
and .region == "ap-southeast-1"
|
|
154
|
-
and (.warnings | index("AWS Pricing API unavailable; using conservative fallback estimates") != null)
|
|
155
|
-
and .components.public_ipv4.billed_even_when_attached == true
|
|
156
|
-
and .components.route53_hosted_zone.monthly_usd == 0
|
|
157
|
-
' "$tmp/fallback.json" >/dev/null
|
|
158
|
-
|
|
159
|
-
echo "pricing estimate ok"
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
ROOT=$(cd "$(dirname "$0")/.." && pwd)
|
|
5
|
-
tmp=$(mktemp -d)
|
|
6
|
-
trap 'rm -rf "$tmp"' EXIT
|
|
7
|
-
|
|
8
|
-
bash "$ROOT/scripts/render/render-userdata.sh" \
|
|
9
|
-
--domain service.example.test \
|
|
10
|
-
--acme ops@example.test \
|
|
11
|
-
--message-server-image direxio/message-server:test \
|
|
12
|
-
> "$tmp/user-data.yaml"
|
|
13
|
-
|
|
14
|
-
awk '/encoding: b64/ { getline; sub(/^ content: /, ""); print; exit }' "$tmp/user-data.yaml" \
|
|
15
|
-
| base64 -d > "$tmp/bundle.tar.gz"
|
|
16
|
-
mkdir "$tmp/bundle"
|
|
17
|
-
tar -xzf "$tmp/bundle.tar.gz" -C "$tmp/bundle"
|
|
18
|
-
|
|
19
|
-
if grep -q 'P2P_REMOTE_NODE_' "$tmp/user-data.yaml"; then
|
|
20
|
-
echo "rendered user-data must not configure fixed remote P2P nodes" >&2
|
|
21
|
-
exit 1
|
|
22
|
-
fi
|
|
23
|
-
|
|
24
|
-
grep -q '/etc/direxio-message-server/message-server.yaml' "$tmp/bundle/docker-compose.yml"
|
|
25
|
-
grep -q '/var/direxio-message-server/p2p/bootstrap.json' "$tmp/bundle/docker-compose.yml"
|
|
26
|
-
grep -q 'P2P_PORTAL_CREDENTIALS_FILE: /var/direxio-message-server/p2p/bootstrap.json' "$tmp/bundle/docker-compose.yml"
|
|
27
|
-
grep -q 'P2P_PORTAL_PASSWORD: ${P2P_PORTAL_PASSWORD}' "$tmp/bundle/docker-compose.yml"
|
|
28
|
-
grep -q '^ grep -q .*P2P_PORTAL_PASSWORD=' "$tmp/user-data.yaml"
|
|
29
|
-
grep -q '/var/direxio-message-server/p2p/bootstrap.json' "$tmp/bundle/init-tokens.sh"
|
|
30
|
-
grep -q 'portal.bootstrap' "$tmp/bundle/init-tokens.sh"
|
|
31
|
-
grep -q 'agent.matrix_session.create' "$tmp/bundle/init-tokens.sh"
|
|
32
|
-
grep -q '/_matrix/client/v3/createRoom' "$tmp/bundle/init-tokens.sh"
|
|
33
|
-
grep -q '/_matrix/client/v3/rooms/${room_path}/join' "$tmp/bundle/init-tokens.sh"
|
|
34
|
-
|
|
35
|
-
if grep -R -q '/etc/dendrite\|/var/dendrite\|dendrite.yaml' "$tmp/bundle"; then
|
|
36
|
-
echo "rendered bundle must use direxio-message-server paths, not legacy dendrite paths" >&2
|
|
37
|
-
exit 1
|
|
38
|
-
fi
|
|
39
|
-
|
|
40
|
-
echo "render userdata remote node config absent ok"
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
ROOT=$(cd "$(dirname "$0")/.." && pwd)
|
|
5
|
-
tmp=$(mktemp -d)
|
|
6
|
-
trap 'rm -rf "$tmp"' EXIT
|
|
7
|
-
|
|
8
|
-
export HOME="$tmp/home"
|
|
9
|
-
export P2P_WORKDIR="$tmp/work"
|
|
10
|
-
mkdir -p "$HOME" "$P2P_WORKDIR"
|
|
11
|
-
|
|
12
|
-
fakebin="$tmp/bin"
|
|
13
|
-
mkdir -p "$fakebin"
|
|
14
|
-
cat > "$fakebin/aws" <<'EOF'
|
|
15
|
-
#!/usr/bin/env bash
|
|
16
|
-
set -euo pipefail
|
|
17
|
-
case "${1:-} ${2:-}" in
|
|
18
|
-
"ec2 describe-instances")
|
|
19
|
-
printf 'vol-root-test\n'
|
|
20
|
-
;;
|
|
21
|
-
*)
|
|
22
|
-
echo "unexpected aws command: $*" >&2
|
|
23
|
-
exit 1
|
|
24
|
-
;;
|
|
25
|
-
esac
|
|
26
|
-
EOF
|
|
27
|
-
chmod 700 "$fakebin/aws"
|
|
28
|
-
export PATH="$fakebin:$PATH"
|
|
29
|
-
|
|
30
|
-
# shellcheck disable=SC1091
|
|
31
|
-
source "$ROOT/scripts/lib/state.sh"
|
|
32
|
-
state_init >/dev/null 2>&1
|
|
33
|
-
|
|
34
|
-
# shellcheck disable=SC1091
|
|
35
|
-
source "$ROOT/scripts/phases/s3_provision.sh"
|
|
36
|
-
|
|
37
|
-
_record_root_volume_id i-root-test
|
|
38
|
-
|
|
39
|
-
jq -e '.resources.root_volume_id == "vol-root-test"' "$STATE_JSON" >/dev/null
|
|
40
|
-
|
|
41
|
-
echo "root volume tracking ok"
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
ROOT=$(cd "$(dirname "$0")/.." && pwd)
|
|
5
|
-
tmp=$(mktemp -d)
|
|
6
|
-
trap 'rm -rf "$tmp"' EXIT
|
|
7
|
-
|
|
8
|
-
export HOME="$tmp/home"
|
|
9
|
-
export P2P_WORKDIR="$tmp/work"
|
|
10
|
-
mkdir -p "$HOME" "$P2P_WORKDIR"
|
|
11
|
-
|
|
12
|
-
fakebin="$tmp/bin"
|
|
13
|
-
mkdir -p "$fakebin"
|
|
14
|
-
cat > "$fakebin/aws" <<'EOF'
|
|
15
|
-
#!/usr/bin/env bash
|
|
16
|
-
set -euo pipefail
|
|
17
|
-
printf 'aws' >> "$CALLS"
|
|
18
|
-
printf ' %q' "$@" >> "$CALLS"
|
|
19
|
-
printf '\n' >> "$CALLS"
|
|
20
|
-
|
|
21
|
-
case "${1:-} ${2:-}" in
|
|
22
|
-
"route53 list-hosted-zones")
|
|
23
|
-
printf '{"HostedZones":[{"Id":"/hostedzone/ZEXISTING","Name":"overwrite.example.test."}]}\n'
|
|
24
|
-
;;
|
|
25
|
-
"route53 list-resource-record-sets")
|
|
26
|
-
printf '{"ResourceRecordSets":[{"Name":"overwrite.example.test.","Type":"A","TTL":60,"ResourceRecords":[{"Value":"198.51.100.10"}]}]}\n'
|
|
27
|
-
;;
|
|
28
|
-
"route53 change-resource-record-sets")
|
|
29
|
-
printf '{"ChangeInfo":{"Id":"/change/C123","Status":"PENDING"}}\n'
|
|
30
|
-
;;
|
|
31
|
-
"route53 wait")
|
|
32
|
-
exit 0
|
|
33
|
-
;;
|
|
34
|
-
*)
|
|
35
|
-
echo "unexpected aws command: $*" >&2
|
|
36
|
-
exit 1
|
|
37
|
-
;;
|
|
38
|
-
esac
|
|
39
|
-
EOF
|
|
40
|
-
chmod 700 "$fakebin/aws"
|
|
41
|
-
export PATH="$fakebin:$PATH"
|
|
42
|
-
|
|
43
|
-
# shellcheck disable=SC1091
|
|
44
|
-
source "$ROOT/scripts/lib/state.sh"
|
|
45
|
-
state_init >/dev/null 2>&1
|
|
46
|
-
state_set run_id route53-overwrite-test
|
|
47
|
-
state_set domain overwrite.example.test
|
|
48
|
-
state_set domain_mode route53
|
|
49
|
-
|
|
50
|
-
# shellcheck disable=SC1091
|
|
51
|
-
source "$ROOT/scripts/phases/s3_provision.sh"
|
|
52
|
-
|
|
53
|
-
CALLS="$tmp/blocked.calls"
|
|
54
|
-
export CALLS
|
|
55
|
-
set +e
|
|
56
|
-
_upsert_route53_record overwrite.example.test 203.0.113.88 > "$tmp/blocked.out" 2>&1
|
|
57
|
-
blocked_rc=$?
|
|
58
|
-
set -e
|
|
59
|
-
[ "$blocked_rc" -eq 2 ] || {
|
|
60
|
-
echo "Route53 overwrite without confirmation should return waiting_user rc=2" >&2
|
|
61
|
-
cat "$tmp/blocked.out" >&2
|
|
62
|
-
exit 1
|
|
63
|
-
}
|
|
64
|
-
grep -q 'Route53 A record overwrite requires confirmation' "$tmp/blocked.out"
|
|
65
|
-
if grep -q 'route53 change-resource-record-sets' "$CALLS"; then
|
|
66
|
-
echo "Route53 overwrite without confirmation must not change records" >&2
|
|
67
|
-
cat "$CALLS" >&2
|
|
68
|
-
exit 1
|
|
69
|
-
fi
|
|
70
|
-
jq -e '
|
|
71
|
-
.phases.S3_PROVISION.status == "waiting_user"
|
|
72
|
-
and .resources.route53_existing_a_value == "198.51.100.10"
|
|
73
|
-
and .resources.route53_pending_a_value == "203.0.113.88"
|
|
74
|
-
' "$STATE_JSON" >/dev/null
|
|
75
|
-
|
|
76
|
-
CALLS="$tmp/confirmed.calls"
|
|
77
|
-
export CALLS
|
|
78
|
-
DIREXIO_CONFIRM_DNS_OVERWRITE=1 _upsert_route53_record overwrite.example.test 203.0.113.88
|
|
79
|
-
grep -q 'route53 change-resource-record-sets' "$CALLS"
|
|
80
|
-
jq -e '
|
|
81
|
-
.resources.route53_existing_a_value == "198.51.100.10"
|
|
82
|
-
and .resources.route53_pending_a_value == "203.0.113.88"
|
|
83
|
-
and .resources.route53_overwrite_confirmed == "true"
|
|
84
|
-
' "$STATE_JSON" >/dev/null
|
|
85
|
-
|
|
86
|
-
echo "route53 overwrite guard ok"
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
ROOT=$(cd "$(dirname "$0")/.." && pwd)
|
|
5
|
-
tmp=$(mktemp -d)
|
|
6
|
-
trap 'rm -rf "$tmp"' EXIT
|
|
7
|
-
|
|
8
|
-
export HOME="$tmp/home"
|
|
9
|
-
export P2P_WORKDIR="$tmp/work"
|
|
10
|
-
mkdir -p "$HOME" "$P2P_WORKDIR"
|
|
11
|
-
|
|
12
|
-
fakebin="$tmp/bin"
|
|
13
|
-
mkdir -p "$fakebin"
|
|
14
|
-
cat > "$fakebin/aws" <<'EOF'
|
|
15
|
-
#!/usr/bin/env bash
|
|
16
|
-
set -euo pipefail
|
|
17
|
-
printf 'aws' >> "$CALLS"
|
|
18
|
-
printf ' %q' "$@" >> "$CALLS"
|
|
19
|
-
printf '\n' >> "$CALLS"
|
|
20
|
-
|
|
21
|
-
case "${1:-} ${2:-}" in
|
|
22
|
-
"route53 list-hosted-zones")
|
|
23
|
-
printf '{"HostedZones":[]}\n'
|
|
24
|
-
;;
|
|
25
|
-
"route53 create-hosted-zone")
|
|
26
|
-
printf '{"HostedZone":{"Id":"/hostedzone/ZCREATE","Name":"auto-zone.example.test."},"DelegationSet":{"NameServers":["ns-1.awsdns.test","ns-2.awsdns.test"]}}\n'
|
|
27
|
-
;;
|
|
28
|
-
"route53 change-resource-record-sets")
|
|
29
|
-
printf '{"ChangeInfo":{"Id":"/change/C123","Status":"PENDING"}}\n'
|
|
30
|
-
;;
|
|
31
|
-
"route53 wait")
|
|
32
|
-
exit 0
|
|
33
|
-
;;
|
|
34
|
-
*)
|
|
35
|
-
echo "unexpected aws command: $*" >&2
|
|
36
|
-
exit 1
|
|
37
|
-
;;
|
|
38
|
-
esac
|
|
39
|
-
EOF
|
|
40
|
-
chmod 700 "$fakebin/aws"
|
|
41
|
-
export CALLS="$tmp/aws.calls"
|
|
42
|
-
export PATH="$fakebin:$PATH"
|
|
43
|
-
|
|
44
|
-
# shellcheck disable=SC1091
|
|
45
|
-
source "$ROOT/scripts/lib/state.sh"
|
|
46
|
-
state_init >/dev/null 2>&1
|
|
47
|
-
state_set run_id route53-test
|
|
48
|
-
state_set domain auto-zone.example.test
|
|
49
|
-
state_set domain_mode route53
|
|
50
|
-
|
|
51
|
-
# shellcheck disable=SC1091
|
|
52
|
-
source "$ROOT/scripts/phases/s3_provision.sh"
|
|
53
|
-
|
|
54
|
-
_upsert_route53_record auto-zone.example.test 203.0.113.88
|
|
55
|
-
|
|
56
|
-
jq -e '
|
|
57
|
-
.resources.route53_zone_id == "ZCREATE"
|
|
58
|
-
and .resources.route53_zone_name == "auto-zone.example.test"
|
|
59
|
-
and .resources.route53_zone_created_by_deployer == "true"
|
|
60
|
-
and (.resources.route53_name_servers | contains("ns-1.awsdns.test"))
|
|
61
|
-
' "$STATE_JSON" >/dev/null
|
|
62
|
-
|
|
63
|
-
grep -q 'route53 create-hosted-zone' "$CALLS"
|
|
64
|
-
grep -q 'route53 change-resource-record-sets' "$CALLS"
|
|
65
|
-
|
|
66
|
-
echo "route53 zone auto create ok"
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
ROOT=$(cd "$(dirname "$0")/.." && pwd)
|
|
5
|
-
tmp=$(mktemp -d "$ROOT/.tmp-runtime-summary.XXXXXX")
|
|
6
|
-
trap 'rm -rf "$tmp"' EXIT
|
|
7
|
-
|
|
8
|
-
export HOME="$tmp/home"
|
|
9
|
-
mkdir -p "$HOME"
|
|
10
|
-
|
|
11
|
-
fakebin="$tmp/bin"
|
|
12
|
-
mkdir -p "$fakebin"
|
|
13
|
-
|
|
14
|
-
windows_path() {
|
|
15
|
-
local path=$1 drive rest
|
|
16
|
-
case "$path" in
|
|
17
|
-
/mnt/[A-Za-z]/*)
|
|
18
|
-
drive=${path#/mnt/}
|
|
19
|
-
drive=${drive%%/*}
|
|
20
|
-
rest=${path#/mnt/$drive/}
|
|
21
|
-
printf '%s:\\%s\n' "$(printf '%s' "$drive" | tr '[:lower:]' '[:upper:]')" "$(printf '%s' "$rest" | sed 's#/#\\#g')"
|
|
22
|
-
;;
|
|
23
|
-
/[A-Za-z]/*)
|
|
24
|
-
drive=${path#/}
|
|
25
|
-
drive=${drive%%/*}
|
|
26
|
-
rest=${path#/$drive/}
|
|
27
|
-
printf '%s:\\%s\n' "$(printf '%s' "$drive" | tr '[:lower:]' '[:upper:]')" "$(printf '%s' "$rest" | sed 's#/#\\#g')"
|
|
28
|
-
;;
|
|
29
|
-
*) printf '%s\n' "$path" ;;
|
|
30
|
-
esac
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
cat > "$fakebin/direxio-connect" <<'EOF'
|
|
34
|
-
#!/usr/bin/env bash
|
|
35
|
-
set -euo pipefail
|
|
36
|
-
[ "${1:-}" = "daemon" ]
|
|
37
|
-
[ "${2:-}" = "status" ]
|
|
38
|
-
[ "${3:-}" = "--service-name" ]
|
|
39
|
-
[ "${4:-}" = "runtime-summary.example.test" ]
|
|
40
|
-
cat <<STATUS
|
|
41
|
-
cc-connect daemon status
|
|
42
|
-
|
|
43
|
-
Status: Running
|
|
44
|
-
Platform: test
|
|
45
|
-
WorkDir: ${CONNECT_WORK_DIR:-}
|
|
46
|
-
STATUS
|
|
47
|
-
EOF
|
|
48
|
-
chmod 700 "$fakebin/direxio-connect"
|
|
49
|
-
|
|
50
|
-
cat > "$fakebin/direxio-mcp" <<'EOF'
|
|
51
|
-
#!/usr/bin/env bash
|
|
52
|
-
set -euo pipefail
|
|
53
|
-
if [ "${DIREXIO_CREDENTIALS_FILE:-}" != "${EXPECTED_CREDENTIALS_FILE:-}" ]; then
|
|
54
|
-
echo "wrong DIREXIO_CREDENTIALS_FILE" >&2
|
|
55
|
-
exit 1
|
|
56
|
-
fi
|
|
57
|
-
|
|
58
|
-
if [ "${1:-}" = "doctor" ] && [ "${2:-}" = "--json" ]; then
|
|
59
|
-
printf '{"ok":true,"domain":"runtime-summary.example.test","agent_room_id":"!agent:runtime-summary.example.test","token":"redacted"}\n'
|
|
60
|
-
exit 0
|
|
61
|
-
fi
|
|
62
|
-
|
|
63
|
-
frame() {
|
|
64
|
-
local body=$1
|
|
65
|
-
printf 'Content-Length: %s\r\n\r\n%s' "${#body}" "$body"
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
frame '{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"fake-direxio-mcp","version":"0.0.0"}}}'
|
|
69
|
-
frame '{"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"search_rooms"},{"name":"send_message"},{"name":"list_messages"}]}}'
|
|
70
|
-
EOF
|
|
71
|
-
chmod 700 "$fakebin/direxio-mcp"
|
|
72
|
-
|
|
73
|
-
cat > "$tmp/fake-mcp.ps1" <<'EOF'
|
|
74
|
-
if ($env:DIREXIO_CREDENTIALS_FILE -ne $env:EXPECTED_CREDENTIALS_FILE) {
|
|
75
|
-
[Console]::Error.WriteLine("wrong DIREXIO_CREDENTIALS_FILE")
|
|
76
|
-
exit 1
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (($args.Count -ge 2) -and ($args[0] -eq "doctor") -and ($args[1] -eq "--json")) {
|
|
80
|
-
[Console]::Out.WriteLine('{"ok":true,"domain":"runtime-summary.example.test","agent_room_id":"!agent:runtime-summary.example.test","token":"redacted"}')
|
|
81
|
-
exit 0
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function Frame($body) {
|
|
85
|
-
[Console]::Out.Write("Content-Length: $($body.Length)`r`n`r`n$body")
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
Frame '{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"fake-direxio-mcp","version":"0.0.0"}}}'
|
|
89
|
-
Frame '{"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"search_rooms"},{"name":"send_message"},{"name":"list_messages"}]}}'
|
|
90
|
-
EOF
|
|
91
|
-
|
|
92
|
-
mcp_command=direxio-mcp
|
|
93
|
-
case "$(uname -s)" in
|
|
94
|
-
MINGW*|MSYS*|CYGWIN*) use_windows_mcp=1 ;;
|
|
95
|
-
*) use_windows_mcp=0 ;;
|
|
96
|
-
esac
|
|
97
|
-
if { [ "$use_windows_mcp" = "1" ] || ! command -v node >/dev/null 2>&1; } && command -v node.exe >/dev/null 2>&1; then
|
|
98
|
-
fake_mcp_ps1=$(windows_path "$tmp/fake-mcp.ps1")
|
|
99
|
-
mcp_command="powershell.exe -NoProfile -ExecutionPolicy Bypass -File \"$fake_mcp_ps1\""
|
|
100
|
-
fi
|
|
101
|
-
|
|
102
|
-
cat > "$fakebin/curl" <<'EOF'
|
|
103
|
-
#!/usr/bin/env bash
|
|
104
|
-
set -euo pipefail
|
|
105
|
-
body_path=""
|
|
106
|
-
write_code=0
|
|
107
|
-
while [ "$#" -gt 0 ]; do
|
|
108
|
-
case "$1" in
|
|
109
|
-
-o) body_path=$2; shift 2 ;;
|
|
110
|
-
-w) write_code=1; shift 2 ;;
|
|
111
|
-
*) shift ;;
|
|
112
|
-
esac
|
|
113
|
-
done
|
|
114
|
-
payload='{"room_id":"!agent:runtime-summary.example.test","messages":[]}'
|
|
115
|
-
if [ -n "$body_path" ]; then
|
|
116
|
-
printf '%s\n' "$payload" > "$body_path"
|
|
117
|
-
else
|
|
118
|
-
printf '%s\n' "$payload"
|
|
119
|
-
fi
|
|
120
|
-
[ "$write_code" -eq 1 ] && printf '200'
|
|
121
|
-
EOF
|
|
122
|
-
chmod 700 "$fakebin/curl"
|
|
123
|
-
|
|
124
|
-
service_dir="$HOME/.direxio/nodes/runtime-summary.example.test"
|
|
125
|
-
mkdir -p "$service_dir/cc-connect"
|
|
126
|
-
credentials="$service_dir/credentials.json"
|
|
127
|
-
config="$service_dir/cc-connect/config.toml"
|
|
128
|
-
: > "$credentials"
|
|
129
|
-
: > "$config"
|
|
130
|
-
expected_credentials="$credentials"
|
|
131
|
-
if command -v cygpath >/dev/null 2>&1; then
|
|
132
|
-
expected_credentials=$(cygpath -m "$expected_credentials")
|
|
133
|
-
fi
|
|
134
|
-
state="$service_dir/state.json"
|
|
135
|
-
jq -n \
|
|
136
|
-
--arg service_dir "$service_dir" \
|
|
137
|
-
--arg credentials "$credentials" \
|
|
138
|
-
--arg config "$config" \
|
|
139
|
-
--arg mcp_command "$mcp_command" \
|
|
140
|
-
'{
|
|
141
|
-
run_id: "runtime-summary-test",
|
|
142
|
-
region: "ap-northeast-1",
|
|
143
|
-
domain_mode: "user",
|
|
144
|
-
domain: "runtime-summary.example.test",
|
|
145
|
-
as_url: "https://runtime-summary.example.test",
|
|
146
|
-
agent_service_id: "runtime-summary.example.test",
|
|
147
|
-
agent_service_dir: $service_dir,
|
|
148
|
-
agent_credentials_file: $credentials,
|
|
149
|
-
mcp_credentials_file: $credentials,
|
|
150
|
-
mcp_command: $mcp_command,
|
|
151
|
-
agent_token: "AGENT_TOKEN_RUNTIME",
|
|
152
|
-
agent_room_id: "!agent:runtime-summary.example.test",
|
|
153
|
-
cc_connect_config: $config,
|
|
154
|
-
cc_connect_binary: "direxio-connect",
|
|
155
|
-
phase: "S7_VERIFY_E2E",
|
|
156
|
-
phases: {
|
|
157
|
-
S0_PREREQ_AWS: {status: "done"},
|
|
158
|
-
S1_PREFLIGHT: {status: "done"},
|
|
159
|
-
S2_DOMAIN: {status: "done"},
|
|
160
|
-
S3_PROVISION: {status: "done"},
|
|
161
|
-
S4_BOOTSTRAP_STACK: {status: "done"},
|
|
162
|
-
S5_INIT_TOKENS: {status: "done"},
|
|
163
|
-
S6_WIRE_LOCAL: {status: "done"},
|
|
164
|
-
S7_VERIFY_E2E: {status: "done"}
|
|
165
|
-
},
|
|
166
|
-
resources: {}
|
|
167
|
-
}' > "$state"
|
|
168
|
-
|
|
169
|
-
verify_output=$(P2P_WORKDIR="$service_dir" PATH="$fakebin:$PATH" EXPECTED_CREDENTIALS_FILE="$expected_credentials" CONNECT_WORK_DIR="$service_dir/cc-connect" bash "$ROOT/scripts/orchestrate.sh" verify runtime)
|
|
170
|
-
printf '%s\n' "$verify_output" | grep -q 'verified runtime checks: passed'
|
|
171
|
-
|
|
172
|
-
jq -e '
|
|
173
|
-
.runtime_checks.summary.status == "passed"
|
|
174
|
-
and .runtime_checks.summary.failed_count == 0
|
|
175
|
-
and .runtime_checks.summary.checks.connect_daemon == "passed"
|
|
176
|
-
and .runtime_checks.summary.checks.mcp_doctor == "passed"
|
|
177
|
-
and .runtime_checks.summary.checks.mcp_tools == "passed"
|
|
178
|
-
and .runtime_checks.summary.checks.mcp_smoke == "passed"
|
|
179
|
-
and (.user_confirmations.agent_mcp_runtime | not)
|
|
180
|
-
' "$state" >/dev/null
|
|
181
|
-
|
|
182
|
-
report_output=$(P2P_WORKDIR="$service_dir" bash "$ROOT/scripts/orchestrate.sh" report new_deploy)
|
|
183
|
-
report_path=$(printf '%s\n' "$report_output" | sed -nE 's/^operation report: //p' | tail -n 1)
|
|
184
|
-
jq -e '.runtime_checks.summary.status == "passed"' "$report_path" >/dev/null
|
|
185
|
-
|
|
186
|
-
set +e
|
|
187
|
-
P2P_WORKDIR="$service_dir" PATH="$fakebin:$PATH" EXPECTED_CREDENTIALS_FILE="$expected_credentials" CONNECT_WORK_DIR="$HOME/.direxio/nodes/other.example.test/cc-connect" bash "$ROOT/scripts/orchestrate.sh" verify runtime > "$tmp/runtime-fail.out" 2>&1
|
|
188
|
-
fail_rc=$?
|
|
189
|
-
set -e
|
|
190
|
-
[ "$fail_rc" -ne 0 ] || {
|
|
191
|
-
echo "runtime summary must fail when any runtime check fails" >&2
|
|
192
|
-
exit 1
|
|
193
|
-
}
|
|
194
|
-
jq -e '
|
|
195
|
-
.runtime_checks.summary.status == "failed"
|
|
196
|
-
and .runtime_checks.summary.failed_count == 1
|
|
197
|
-
and .runtime_checks.summary.checks.connect_daemon == "failed"
|
|
198
|
-
and .runtime_checks.summary.checks.mcp_doctor == "passed"
|
|
199
|
-
and .runtime_checks.summary.checks.mcp_tools == "passed"
|
|
200
|
-
and .runtime_checks.summary.checks.mcp_smoke == "passed"
|
|
201
|
-
' "$state" >/dev/null
|
|
202
|
-
|
|
203
|
-
echo "runtime summary check ok"
|