@intentius/behold 0.17.0 → 0.18.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.
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env bash
2
+ # Stand up the choudoufu-estate demo (behold#372, M4 of #366): a scratch floci
3
+ # (the AWS emulator), provider schemas in each estate copy, and the terralith
4
+ # applied — one estate with three teams' worth of IAM and log groups in it,
5
+ # the shape the live-mv workbench splits. The team estates start empty: their
6
+ # declared resources are the monolith's, and the plan in monolith/carve.json
7
+ # says which move where.
8
+ #
9
+ # Scratch discipline (behold's src/scratch.ts): the container is named
10
+ # behold-*, this script refuses to adopt an existing one, and only
11
+ # choudoufu-down.sh removes it — by this name and no other. The port is not
12
+ # the shared emulator's (:4566); nothing here can reach a floci that another
13
+ # tool runs.
14
+ #
15
+ # `choudoufu init` runs here, in behold's OWN copy of the estates (the demo
16
+ # target), never in a served project: that is #366's decision, and this is
17
+ # the one place it holds.
18
+ set -euo pipefail
19
+ cd "$(dirname "$0")/.."
20
+
21
+ CONTAINER=behold-choudoufu-floci
22
+ PORT=4650
23
+ # The image the live-mv workbench measures against (choudoufu's live/floci-image).
24
+ IMAGE="ghcr.io/lex00/floci@sha256:a39185cc3971d0188663d61043cb038dff1260d8a975b1aa72c4e2bb1feac3cb"
25
+
26
+ if ! docker info >/dev/null 2>&1; then
27
+ echo "choudoufu-estate demo: Docker is not running — start Docker and re-run." >&2
28
+ exit 1
29
+ fi
30
+ # behold#388: the same binary behold itself spawns — the Homebrew release is
31
+ # below the 0.16.0 floor, so a build from main is named by CHOUDOUFU_BIN and
32
+ # every script that runs choudoufu has to honour it or the demo's `init` and
33
+ # behold's own reads would be two different tools.
34
+ CHOUDOUFU="${CHOUDOUFU_BIN:-choudoufu}"
35
+ if ! command -v "$CHOUDOUFU" >/dev/null 2>&1; then
36
+ echo "choudoufu-estate demo: ${CHOUDOUFU} is not on PATH — https://github.com/INTENTIUS/choudoufu (0.16.0 or newer), or set CHOUDOUFU_BIN." >&2
37
+ exit 1
38
+ fi
39
+
40
+ if docker ps -a --format '{{.Names}}' | grep -qx "$CONTAINER"; then
41
+ echo "choudoufu-estate demo: container ${CONTAINER} already exists — a previous run didn't tear down. \`bash scripts/choudoufu-down.sh\` and re-run." >&2
42
+ exit 1
43
+ fi
44
+ echo "→ floci on 127.0.0.1:${PORT} (${CONTAINER})"
45
+ docker run -d --name "$CONTAINER" -p "127.0.0.1:${PORT}:4566" "$IMAGE" >/dev/null
46
+ for _ in $(seq 1 40); do
47
+ curl -fs -o /dev/null "http://127.0.0.1:${PORT}/" && break
48
+ sleep 1
49
+ done
50
+
51
+ export AWS_ENDPOINT_URL="http://127.0.0.1:${PORT}"
52
+ export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test AWS_REGION=us-east-1
53
+
54
+ for estate in monolith team-a team-b team-c; do
55
+ echo "→ choudoufu init in ${estate} (provider schemas — what makes the rungs real)"
56
+ (cd "$estate" && "$CHOUDOUFU" init -input=false -no-color >/dev/null)
57
+ done
58
+
59
+ echo "→ choudoufu apply in monolith (the terralith: 21 resources, three teams in one estate)"
60
+ (cd monolith && "$CHOUDOUFU" apply -auto-approve -input=false -no-color | tail -1)
61
+
62
+ echo "choudoufu-estate demo: up. behold serves it next; the plan in monolith/carve.json moves team-a's resources out."
@@ -0,0 +1,179 @@
1
+ {
2
+ "meta": {
3
+ "engine": "behold-fixture",
4
+ "version": "0",
5
+ "at": {
6
+ "traffic": "100 rps, p50"
7
+ }
8
+ },
9
+ "entities": {
10
+ "aws_iam_role.team_a": {
11
+ "at": {
12
+ "traffic": "100 rps, p50"
13
+ },
14
+ "cost": {
15
+ "perHour": 0.0004,
16
+ "currency": "USD"
17
+ },
18
+ "headroom": {
19
+ "cpu": 0.9,
20
+ "latency": 0.85
21
+ },
22
+ "errorRate": 0.001,
23
+ "resilience": {
24
+ "failure": "one zone lost",
25
+ "verdict": "survives"
26
+ },
27
+ "provenance": {
28
+ "engine": "behold-fixture",
29
+ "version": "0",
30
+ "tolerance": "fixture",
31
+ "basis": "modeled"
32
+ }
33
+ },
34
+ "aws_iam_role_policy.team_a_inline": {
35
+ "at": {
36
+ "traffic": "100 rps, p50"
37
+ },
38
+ "cost": {
39
+ "perHour": 0.0002,
40
+ "currency": "USD"
41
+ },
42
+ "headroom": {
43
+ "cpu": 0.84,
44
+ "latency": 0.76
45
+ },
46
+ "errorRate": 0.001,
47
+ "resilience": {
48
+ "failure": "one zone lost",
49
+ "verdict": "survives"
50
+ },
51
+ "provenance": {
52
+ "engine": "behold-fixture",
53
+ "version": "0",
54
+ "tolerance": "fixture",
55
+ "basis": "modeled"
56
+ }
57
+ },
58
+ "aws_iam_policy.team_a": {
59
+ "at": {
60
+ "traffic": "100 rps, p50"
61
+ },
62
+ "cost": {
63
+ "perHour": 0.0002,
64
+ "currency": "USD"
65
+ },
66
+ "headroom": {
67
+ "cpu": 0.78,
68
+ "latency": 0.67
69
+ },
70
+ "errorRate": 0.001,
71
+ "resilience": {
72
+ "failure": "one zone lost",
73
+ "verdict": "survives"
74
+ },
75
+ "provenance": {
76
+ "engine": "behold-fixture",
77
+ "version": "0",
78
+ "tolerance": "fixture",
79
+ "basis": "modeled"
80
+ }
81
+ },
82
+ "aws_iam_role_policy_attachment.team_a": {
83
+ "at": {
84
+ "traffic": "100 rps, p50"
85
+ },
86
+ "cost": {
87
+ "perHour": 0.0001,
88
+ "currency": "USD"
89
+ },
90
+ "headroom": {
91
+ "cpu": 0.72,
92
+ "latency": 0.58
93
+ },
94
+ "errorRate": 0.001,
95
+ "resilience": {
96
+ "failure": "one zone lost",
97
+ "verdict": "survives"
98
+ },
99
+ "provenance": {
100
+ "engine": "behold-fixture",
101
+ "version": "0",
102
+ "tolerance": "fixture",
103
+ "basis": "modeled"
104
+ }
105
+ },
106
+ "aws_cloudwatch_log_group.team_a_0": {
107
+ "at": {
108
+ "traffic": "100 rps, p50"
109
+ },
110
+ "cost": {
111
+ "perHour": 0.0416,
112
+ "currency": "USD"
113
+ },
114
+ "headroom": {
115
+ "cpu": 0.66,
116
+ "latency": 0.49
117
+ },
118
+ "errorRate": 0.0004,
119
+ "resilience": {
120
+ "failure": "one zone lost",
121
+ "verdict": "survives"
122
+ },
123
+ "provenance": {
124
+ "engine": "behold-fixture",
125
+ "version": "0",
126
+ "tolerance": "fixture",
127
+ "basis": "modeled"
128
+ }
129
+ },
130
+ "aws_cloudwatch_log_group.team_a_1": {
131
+ "at": {
132
+ "traffic": "100 rps, p50"
133
+ },
134
+ "cost": {
135
+ "perHour": 0.0312,
136
+ "currency": "USD"
137
+ },
138
+ "headroom": {
139
+ "cpu": 0.6,
140
+ "latency": 0.85
141
+ },
142
+ "errorRate": 0.0004,
143
+ "resilience": {
144
+ "failure": "one zone lost",
145
+ "verdict": "survives"
146
+ },
147
+ "provenance": {
148
+ "engine": "behold-fixture",
149
+ "version": "0",
150
+ "tolerance": "fixture",
151
+ "basis": "modeled"
152
+ }
153
+ },
154
+ "aws_cloudwatch_log_group.team_a_2": {
155
+ "at": {
156
+ "traffic": "100 rps, p50"
157
+ },
158
+ "cost": {
159
+ "perHour": 0.0208,
160
+ "currency": "USD"
161
+ },
162
+ "headroom": {
163
+ "cpu": 0.54,
164
+ "latency": 0.76
165
+ },
166
+ "errorRate": 0.0004,
167
+ "resilience": {
168
+ "failure": "one zone lost",
169
+ "verdict": "survives"
170
+ },
171
+ "provenance": {
172
+ "engine": "behold-fixture",
173
+ "version": "0",
174
+ "tolerance": "fixture",
175
+ "basis": "modeled"
176
+ }
177
+ }
178
+ }
179
+ }
@@ -0,0 +1,58 @@
1
+ terraform {
2
+ required_providers {
3
+ aws = {
4
+ source = "hashicorp/aws"
5
+ version = "= 6.58.0"
6
+ }
7
+ }
8
+ live {
9
+ estate = "tlmig-sample-team-a"
10
+ }
11
+ }
12
+
13
+ provider "aws" {
14
+ region = "us-east-1"
15
+ }
16
+
17
+ resource "aws_iam_role" "team_a" {
18
+ name = "tlmig-sample-team-a-role"
19
+ assume_role_policy = jsonencode({ Version = "2012-10-17", Statement = [{ Effect = "Allow", Principal = { Service = "ec2.amazonaws.com" }, Action = "sts:AssumeRole" }] })
20
+ }
21
+
22
+ resource "aws_iam_role_policy" "team_a_inline" {
23
+ name = "tlmig-sample-team-a-inline"
24
+ role = aws_iam_role.team_a.id
25
+ policy = jsonencode({ Version = "2012-10-17", Statement = [{ Effect = "Allow", Action = ["logs:CreateLogStream"], Resource = "*" }] })
26
+ }
27
+
28
+ resource "aws_iam_policy" "team_a" {
29
+ name = "tlmig-sample-team-a-policy"
30
+ policy = jsonencode({ Version = "2012-10-17", Statement = [{ Effect = "Allow", Action = ["logs:PutLogEvents"], Resource = "*" }] })
31
+ }
32
+
33
+ resource "aws_iam_role_policy_attachment" "team_a" {
34
+ role = aws_iam_role.team_a.name
35
+ policy_arn = aws_iam_policy.team_a.arn
36
+ }
37
+
38
+ resource "aws_cloudwatch_log_group" "team_a_0" {
39
+ name = "/tlmig-sample/team-a/svc-0"
40
+ retention_in_days = 1
41
+ }
42
+
43
+ resource "aws_cloudwatch_log_group" "team_a_1" {
44
+ name = "/tlmig-sample/team-a/svc-1"
45
+ retention_in_days = 1
46
+ }
47
+
48
+ resource "aws_cloudwatch_log_group" "team_a_2" {
49
+ name = "/tlmig-sample/team-a/svc-2"
50
+ retention_in_days = 1
51
+ }
52
+
53
+ # The producer half of the cross-estate read below. team-b reaches this VPC
54
+ # by its markers, so moving it out of this estate is not free: see the data
55
+ # source in tlmig-sample-team-b.
56
+ resource "aws_vpc" "main" {
57
+ cidr_block = "10.77.0.0/16"
58
+ }
@@ -0,0 +1,179 @@
1
+ {
2
+ "meta": {
3
+ "engine": "behold-fixture",
4
+ "version": "0",
5
+ "at": {
6
+ "traffic": "100 rps, p50"
7
+ }
8
+ },
9
+ "entities": {
10
+ "aws_iam_role.team_b": {
11
+ "at": {
12
+ "traffic": "100 rps, p50"
13
+ },
14
+ "cost": {
15
+ "perHour": 0.0004,
16
+ "currency": "USD"
17
+ },
18
+ "headroom": {
19
+ "cpu": 0.9,
20
+ "latency": 0.85
21
+ },
22
+ "errorRate": 0.001,
23
+ "resilience": {
24
+ "failure": "one zone lost",
25
+ "verdict": "survives"
26
+ },
27
+ "provenance": {
28
+ "engine": "behold-fixture",
29
+ "version": "0",
30
+ "tolerance": "fixture",
31
+ "basis": "modeled"
32
+ }
33
+ },
34
+ "aws_iam_role_policy.team_b_inline": {
35
+ "at": {
36
+ "traffic": "100 rps, p50"
37
+ },
38
+ "cost": {
39
+ "perHour": 0.0002,
40
+ "currency": "USD"
41
+ },
42
+ "headroom": {
43
+ "cpu": 0.84,
44
+ "latency": 0.76
45
+ },
46
+ "errorRate": 0.001,
47
+ "resilience": {
48
+ "failure": "one zone lost",
49
+ "verdict": "survives"
50
+ },
51
+ "provenance": {
52
+ "engine": "behold-fixture",
53
+ "version": "0",
54
+ "tolerance": "fixture",
55
+ "basis": "modeled"
56
+ }
57
+ },
58
+ "aws_iam_policy.team_b": {
59
+ "at": {
60
+ "traffic": "100 rps, p50"
61
+ },
62
+ "cost": {
63
+ "perHour": 0.0002,
64
+ "currency": "USD"
65
+ },
66
+ "headroom": {
67
+ "cpu": 0.78,
68
+ "latency": 0.67
69
+ },
70
+ "errorRate": 0.001,
71
+ "resilience": {
72
+ "failure": "one zone lost",
73
+ "verdict": "survives"
74
+ },
75
+ "provenance": {
76
+ "engine": "behold-fixture",
77
+ "version": "0",
78
+ "tolerance": "fixture",
79
+ "basis": "modeled"
80
+ }
81
+ },
82
+ "aws_iam_role_policy_attachment.team_b": {
83
+ "at": {
84
+ "traffic": "100 rps, p50"
85
+ },
86
+ "cost": {
87
+ "perHour": 0.0001,
88
+ "currency": "USD"
89
+ },
90
+ "headroom": {
91
+ "cpu": 0.72,
92
+ "latency": 0.58
93
+ },
94
+ "errorRate": 0.001,
95
+ "resilience": {
96
+ "failure": "one zone lost",
97
+ "verdict": "survives"
98
+ },
99
+ "provenance": {
100
+ "engine": "behold-fixture",
101
+ "version": "0",
102
+ "tolerance": "fixture",
103
+ "basis": "modeled"
104
+ }
105
+ },
106
+ "aws_cloudwatch_log_group.team_b_0": {
107
+ "at": {
108
+ "traffic": "100 rps, p50"
109
+ },
110
+ "cost": {
111
+ "perHour": 0.0416,
112
+ "currency": "USD"
113
+ },
114
+ "headroom": {
115
+ "cpu": 0.66,
116
+ "latency": 0.49
117
+ },
118
+ "errorRate": 0.0004,
119
+ "resilience": {
120
+ "failure": "one zone lost",
121
+ "verdict": "survives"
122
+ },
123
+ "provenance": {
124
+ "engine": "behold-fixture",
125
+ "version": "0",
126
+ "tolerance": "fixture",
127
+ "basis": "modeled"
128
+ }
129
+ },
130
+ "aws_cloudwatch_log_group.team_b_1": {
131
+ "at": {
132
+ "traffic": "100 rps, p50"
133
+ },
134
+ "cost": {
135
+ "perHour": 0.0312,
136
+ "currency": "USD"
137
+ },
138
+ "headroom": {
139
+ "cpu": 0.6,
140
+ "latency": 0.85
141
+ },
142
+ "errorRate": 0.0004,
143
+ "resilience": {
144
+ "failure": "one zone lost",
145
+ "verdict": "survives"
146
+ },
147
+ "provenance": {
148
+ "engine": "behold-fixture",
149
+ "version": "0",
150
+ "tolerance": "fixture",
151
+ "basis": "modeled"
152
+ }
153
+ },
154
+ "aws_cloudwatch_log_group.team_b_2": {
155
+ "at": {
156
+ "traffic": "100 rps, p50"
157
+ },
158
+ "cost": {
159
+ "perHour": 0.0208,
160
+ "currency": "USD"
161
+ },
162
+ "headroom": {
163
+ "cpu": 0.54,
164
+ "latency": 0.76
165
+ },
166
+ "errorRate": 0.0004,
167
+ "resilience": {
168
+ "failure": "one zone lost",
169
+ "verdict": "survives"
170
+ },
171
+ "provenance": {
172
+ "engine": "behold-fixture",
173
+ "version": "0",
174
+ "tolerance": "fixture",
175
+ "basis": "modeled"
176
+ }
177
+ }
178
+ }
179
+ }
@@ -0,0 +1,73 @@
1
+ terraform {
2
+ required_providers {
3
+ aws = {
4
+ source = "hashicorp/aws"
5
+ version = "= 6.58.0"
6
+ }
7
+ }
8
+ live {
9
+ estate = "tlmig-sample-team-b"
10
+ }
11
+ }
12
+
13
+ provider "aws" {
14
+ region = "us-east-1"
15
+ }
16
+
17
+ resource "aws_iam_role" "team_b" {
18
+ name = "tlmig-sample-team-b-role"
19
+ assume_role_policy = jsonencode({ Version = "2012-10-17", Statement = [{ Effect = "Allow", Principal = { Service = "ec2.amazonaws.com" }, Action = "sts:AssumeRole" }] })
20
+ }
21
+
22
+ resource "aws_iam_role_policy" "team_b_inline" {
23
+ name = "tlmig-sample-team-b-inline"
24
+ role = aws_iam_role.team_b.id
25
+ policy = jsonencode({ Version = "2012-10-17", Statement = [{ Effect = "Allow", Action = ["logs:CreateLogStream"], Resource = "*" }] })
26
+ }
27
+
28
+ resource "aws_iam_policy" "team_b" {
29
+ name = "tlmig-sample-team-b-policy"
30
+ policy = jsonencode({ Version = "2012-10-17", Statement = [{ Effect = "Allow", Action = ["logs:PutLogEvents"], Resource = "*" }] })
31
+ }
32
+
33
+ resource "aws_iam_role_policy_attachment" "team_b" {
34
+ role = aws_iam_role.team_b.name
35
+ policy_arn = aws_iam_policy.team_b.arn
36
+ }
37
+
38
+ resource "aws_cloudwatch_log_group" "team_b_0" {
39
+ name = "/tlmig-sample/team-b/svc-0"
40
+ retention_in_days = 1
41
+ }
42
+
43
+ resource "aws_cloudwatch_log_group" "team_b_1" {
44
+ name = "/tlmig-sample/team-b/svc-1"
45
+ retention_in_days = 1
46
+ }
47
+
48
+ resource "aws_cloudwatch_log_group" "team_b_2" {
49
+ name = "/tlmig-sample/team-b/svc-2"
50
+ retention_in_days = 1
51
+ }
52
+
53
+ # ---- read across the estate boundary ----
54
+ # live/OUTPUTS.md's pattern, which replaces the banned terraform_remote_state:
55
+ # a data source filtered on the producer's two marker tags. This is what
56
+ # `choudoufu live-check -json` reports as references[], with read_by naming
57
+ # aws_subnet.app below - and what the planner prices, because moving
58
+ # aws_vpc.main out of tlmig-sample-team-a means rewriting this filter.
59
+ data "aws_vpc" "team_a_network" {
60
+ filter {
61
+ name = "tag:tofu-estate"
62
+ values = ["tlmig-sample-team-a"]
63
+ }
64
+ filter {
65
+ name = "tag:tofu-address"
66
+ values = ["aws_vpc.main"]
67
+ }
68
+ }
69
+
70
+ resource "aws_subnet" "app" {
71
+ vpc_id = data.aws_vpc.team_a_network.id
72
+ cidr_block = "10.77.1.0/24"
73
+ }