alchemy-effect 0.3.0 → 0.4.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/bin/alchemy-effect.js +539 -223
- package/bin/alchemy-effect.js.map +1 -1
- package/lib/apply.d.ts +4 -4
- package/lib/apply.d.ts.map +1 -1
- package/lib/apply.js +411 -131
- package/lib/apply.js.map +1 -1
- package/lib/aws/dynamodb/table.provider.d.ts.map +1 -1
- package/lib/aws/dynamodb/table.provider.js +1 -0
- package/lib/aws/dynamodb/table.provider.js.map +1 -1
- package/lib/aws/ec2/index.d.ts +8 -0
- package/lib/aws/ec2/index.d.ts.map +1 -1
- package/lib/aws/ec2/index.js +8 -0
- package/lib/aws/ec2/index.js.map +1 -1
- package/lib/aws/ec2/internet-gateway.d.ts +65 -0
- package/lib/aws/ec2/internet-gateway.d.ts.map +1 -0
- package/lib/aws/ec2/internet-gateway.js +4 -0
- package/lib/aws/ec2/internet-gateway.js.map +1 -0
- package/lib/aws/ec2/internet-gateway.provider.d.ts +6 -0
- package/lib/aws/ec2/internet-gateway.provider.d.ts.map +1 -0
- package/lib/aws/ec2/internet-gateway.provider.js +193 -0
- package/lib/aws/ec2/internet-gateway.provider.js.map +1 -0
- package/lib/aws/ec2/route-table-association.d.ts +63 -0
- package/lib/aws/ec2/route-table-association.d.ts.map +1 -0
- package/lib/aws/ec2/route-table-association.js +4 -0
- package/lib/aws/ec2/route-table-association.js.map +1 -0
- package/lib/aws/ec2/route-table-association.provider.d.ts +4 -0
- package/lib/aws/ec2/route-table-association.provider.d.ts.map +1 -0
- package/lib/aws/ec2/route-table-association.provider.js +121 -0
- package/lib/aws/ec2/route-table-association.provider.js.map +1 -0
- package/lib/aws/ec2/route-table.d.ts +159 -0
- package/lib/aws/ec2/route-table.d.ts.map +1 -0
- package/lib/aws/ec2/route-table.js +4 -0
- package/lib/aws/ec2/route-table.js.map +1 -0
- package/lib/aws/ec2/route-table.provider.d.ts +6 -0
- package/lib/aws/ec2/route-table.provider.d.ts.map +1 -0
- package/lib/aws/ec2/route-table.provider.js +213 -0
- package/lib/aws/ec2/route-table.provider.js.map +1 -0
- package/lib/aws/ec2/route.d.ts +155 -0
- package/lib/aws/ec2/route.d.ts.map +1 -0
- package/lib/aws/ec2/route.js +3 -0
- package/lib/aws/ec2/route.js.map +1 -0
- package/lib/aws/ec2/route.provider.d.ts +4 -0
- package/lib/aws/ec2/route.provider.d.ts.map +1 -0
- package/lib/aws/ec2/route.provider.js +166 -0
- package/lib/aws/ec2/route.provider.js.map +1 -0
- package/lib/aws/ec2/subnet.provider.d.ts.map +1 -1
- package/lib/aws/ec2/subnet.provider.js +1 -1
- package/lib/aws/ec2/subnet.provider.js.map +1 -1
- package/lib/aws/ec2/vpc.d.ts +1 -0
- package/lib/aws/ec2/vpc.d.ts.map +1 -1
- package/lib/aws/ec2/vpc.provider.d.ts +2 -2
- package/lib/aws/ec2/vpc.provider.d.ts.map +1 -1
- package/lib/aws/ec2/vpc.provider.js +38 -15
- package/lib/aws/ec2/vpc.provider.js.map +1 -1
- package/lib/aws/index.d.ts +2 -3
- package/lib/aws/index.d.ts.map +1 -1
- package/lib/aws/index.js +2 -1
- package/lib/aws/index.js.map +1 -1
- package/lib/aws/lambda/function.provider.d.ts +2 -2
- package/lib/aws/lambda/function.provider.d.ts.map +1 -1
- package/lib/aws/lambda/function.provider.js +21 -20
- package/lib/aws/lambda/function.provider.js.map +1 -1
- package/lib/aws/sqs/queue.provider.d.ts +2 -2
- package/lib/aws/sqs/queue.provider.d.ts.map +1 -1
- package/lib/aws/sqs/queue.provider.js +3 -2
- package/lib/aws/sqs/queue.provider.js.map +1 -1
- package/lib/cli/index.d.ts +178 -99
- package/lib/cli/index.d.ts.map +1 -1
- package/lib/cloudflare/kv/namespace.client.d.ts +1 -1
- package/lib/cloudflare/kv/namespace.provider.d.ts.map +1 -1
- package/lib/cloudflare/kv/namespace.provider.js +1 -0
- package/lib/cloudflare/kv/namespace.provider.js.map +1 -1
- package/lib/cloudflare/r2/bucket.provider.d.ts.map +1 -1
- package/lib/cloudflare/r2/bucket.provider.js +6 -1
- package/lib/cloudflare/r2/bucket.provider.js.map +1 -1
- package/lib/cloudflare/worker/worker.provider.d.ts +1 -1
- package/lib/cloudflare/worker/worker.provider.d.ts.map +1 -1
- package/lib/cloudflare/worker/worker.provider.js +6 -2
- package/lib/cloudflare/worker/worker.provider.js.map +1 -1
- package/lib/diff.d.ts +8 -6
- package/lib/diff.d.ts.map +1 -1
- package/lib/diff.js +13 -0
- package/lib/diff.js.map +1 -1
- package/lib/event.d.ts +1 -1
- package/lib/event.d.ts.map +1 -1
- package/lib/instance-id.d.ts +8 -0
- package/lib/instance-id.d.ts.map +1 -0
- package/lib/instance-id.js +12 -0
- package/lib/instance-id.js.map +1 -0
- package/lib/output.d.ts +4 -2
- package/lib/output.d.ts.map +1 -1
- package/lib/output.js +18 -4
- package/lib/output.js.map +1 -1
- package/lib/physical-name.d.ts +14 -1
- package/lib/physical-name.d.ts.map +1 -1
- package/lib/physical-name.js +41 -2
- package/lib/physical-name.js.map +1 -1
- package/lib/plan.d.ts +49 -42
- package/lib/plan.d.ts.map +1 -1
- package/lib/plan.js +359 -127
- package/lib/plan.js.map +1 -1
- package/lib/provider.d.ts +26 -9
- package/lib/provider.d.ts.map +1 -1
- package/lib/provider.js +9 -0
- package/lib/provider.js.map +1 -1
- package/lib/resource.d.ts +2 -2
- package/lib/resource.d.ts.map +1 -1
- package/lib/resource.js.map +1 -1
- package/lib/state.d.ts +86 -9
- package/lib/state.d.ts.map +1 -1
- package/lib/state.js +21 -18
- package/lib/state.js.map +1 -1
- package/lib/tags.d.ts +15 -0
- package/lib/tags.d.ts.map +1 -1
- package/lib/tags.js +27 -0
- package/lib/tags.js.map +1 -1
- package/lib/test.d.ts +2 -2
- package/lib/test.d.ts.map +1 -1
- package/lib/test.js +4 -4
- package/lib/test.js.map +1 -1
- package/lib/todo.d.ts +3 -0
- package/lib/todo.d.ts.map +1 -0
- package/lib/todo.js +3 -0
- package/lib/todo.js.map +1 -0
- package/lib/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/apply.ts +758 -374
- package/src/aws/dynamodb/table.provider.ts +1 -0
- package/src/aws/ec2/index.ts +8 -0
- package/src/aws/ec2/internet-gateway.provider.ts +316 -0
- package/src/aws/ec2/internet-gateway.ts +79 -0
- package/src/aws/ec2/route-table-association.provider.ts +214 -0
- package/src/aws/ec2/route-table-association.ts +82 -0
- package/src/aws/ec2/route-table.provider.ts +306 -0
- package/src/aws/ec2/route-table.ts +175 -0
- package/src/aws/ec2/route.provider.ts +213 -0
- package/src/aws/ec2/route.ts +192 -0
- package/src/aws/ec2/subnet.provider.ts +2 -2
- package/src/aws/ec2/vpc.provider.ts +43 -19
- package/src/aws/ec2/vpc.ts +2 -0
- package/src/aws/index.ts +4 -1
- package/src/aws/lambda/function.provider.ts +25 -23
- package/src/aws/sqs/queue.provider.ts +3 -2
- package/src/cloudflare/kv/namespace.provider.ts +1 -0
- package/src/cloudflare/r2/bucket.provider.ts +7 -1
- package/src/cloudflare/worker/worker.provider.ts +6 -2
- package/src/diff.ts +35 -17
- package/src/event.ts +6 -0
- package/src/instance-id.ts +16 -0
- package/src/output.ts +29 -5
- package/src/physical-name.ts +57 -2
- package/src/plan.ts +488 -197
- package/src/provider.ts +46 -9
- package/src/resource.ts +50 -4
- package/src/state.ts +150 -35
- package/src/tags.ts +31 -0
- package/src/test.ts +5 -5
- package/src/todo.ts +4 -0
package/lib/plan.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"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"}
|
package/lib/plan.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import * as Context from "effect/Context";
|
|
2
|
-
import { App } from "./app.js";
|
|
3
2
|
import * as Data from "effect/Data";
|
|
4
3
|
import * as Effect from "effect/Effect";
|
|
5
4
|
import { omit } from "effect/Struct";
|
|
5
|
+
import { App } from "./app.js";
|
|
6
6
|
import * as Output from "./output.js";
|
|
7
|
-
import {} from "./provider.js";
|
|
7
|
+
import { getProviderByType } from "./provider.js";
|
|
8
8
|
import { isService } from "./service.js";
|
|
9
|
-
import { State, StateStoreError } from "./state.js";
|
|
9
|
+
import { State, StateStoreError, } from "./state.js";
|
|
10
|
+
import { asEffect } from "./util.js";
|
|
10
11
|
export const isBindNode = (node) => {
|
|
11
12
|
return (node &&
|
|
12
13
|
typeof node === "object" &&
|
|
@@ -22,34 +23,30 @@ export const isCRUD = (node) => {
|
|
|
22
23
|
node.action === "replace" ||
|
|
23
24
|
node.action === "noop"));
|
|
24
25
|
};
|
|
25
|
-
const
|
|
26
|
-
...node,
|
|
27
|
-
toString() {
|
|
28
|
-
return `${this.action.charAt(0).toUpperCase()}${this.action.slice(1)}(${this.resource})`;
|
|
29
|
-
},
|
|
30
|
-
[Symbol.toStringTag]() {
|
|
31
|
-
return this.toString();
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
export const plan = (...resources) => Effect.gen(function* () {
|
|
26
|
+
export const plan = (..._resources) => Effect.gen(function* () {
|
|
35
27
|
const state = yield* State;
|
|
28
|
+
const findResources = (resource, visited) => {
|
|
29
|
+
if (visited.has(resource.id)) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
visited.add(resource.id);
|
|
33
|
+
const upstream = Object.values(Output.upstreamAny(resource.props));
|
|
34
|
+
return [
|
|
35
|
+
resource,
|
|
36
|
+
...upstream,
|
|
37
|
+
...upstream.flatMap((r) => findResources(r, visited)),
|
|
38
|
+
];
|
|
39
|
+
};
|
|
40
|
+
const resources = _resources
|
|
41
|
+
.flatMap((r) => findResources(r, new Set()))
|
|
42
|
+
.filter((r, i, arr) => arr.findIndex((r2) => r2.id === r.id) === i);
|
|
36
43
|
// TODO(sam): rename terminology to Stack
|
|
37
44
|
const app = yield* App;
|
|
38
45
|
const resourceIds = yield* state.list({
|
|
39
46
|
stack: app.name,
|
|
40
47
|
stage: app.stage,
|
|
41
48
|
});
|
|
42
|
-
const
|
|
43
|
-
// map of resource ID -> its downstream dependencies (resources that depend on it)
|
|
44
|
-
const downstream = resourcesState
|
|
45
|
-
.filter((resource) => !!resource?.bindings)
|
|
46
|
-
.flatMap((resource) => resource.bindings.flatMap(({ binding }) => [
|
|
47
|
-
[binding.capability.resource.id, binding.capability.resource],
|
|
48
|
-
]))
|
|
49
|
-
.reduce((acc, [id, resourceId]) => ({
|
|
50
|
-
...acc,
|
|
51
|
-
[id]: [...(acc[id] ?? []), resourceId],
|
|
52
|
-
}), {});
|
|
49
|
+
const oldResources = yield* Effect.all(resourceIds.map((id) => state.get({ stack: app.name, stage: app.stage, resourceId: id })));
|
|
53
50
|
const resolvedResources = {};
|
|
54
51
|
const resolveResource = (resourceExpr) => Effect.gen(function* () {
|
|
55
52
|
return yield* (resolvedResources[resourceExpr.src.id] ??=
|
|
@@ -62,37 +59,60 @@ export const plan = (...resources) => Effect.gen(function* () {
|
|
|
62
59
|
stage: app.stage,
|
|
63
60
|
resourceId: resource.id,
|
|
64
61
|
});
|
|
65
|
-
if (!oldState) {
|
|
62
|
+
if (!oldState || oldState.status === "creating") {
|
|
66
63
|
return resourceExpr;
|
|
67
64
|
}
|
|
65
|
+
const oldProps = oldState.status === "created" ||
|
|
66
|
+
oldState.status === "updated" ||
|
|
67
|
+
oldState.status === "replaced"
|
|
68
|
+
? // if we're in a stable state, then just use the props
|
|
69
|
+
oldState.props
|
|
70
|
+
: // if we failed to update or replace, compare with the last known stable props
|
|
71
|
+
oldState.status === "updating" ||
|
|
72
|
+
oldState.status === "replacing"
|
|
73
|
+
? oldState.old.props
|
|
74
|
+
: // TODO(sam): it kinda doesn't make sense to diff with a "deleting" state
|
|
75
|
+
oldState.props;
|
|
68
76
|
const diff = yield* provider.diff
|
|
69
77
|
? provider.diff({
|
|
70
78
|
id: resource.id,
|
|
71
|
-
olds:
|
|
79
|
+
olds: oldProps,
|
|
80
|
+
instanceId: oldState.instanceId,
|
|
72
81
|
news: props,
|
|
73
|
-
output: oldState.
|
|
82
|
+
output: oldState.attr,
|
|
74
83
|
})
|
|
75
84
|
: Effect.succeed(undefined);
|
|
85
|
+
const stables = [
|
|
86
|
+
...(provider.stables ?? []),
|
|
87
|
+
...(diff?.stables ?? []),
|
|
88
|
+
];
|
|
89
|
+
const withStables = (output) => stables.length > 0
|
|
90
|
+
? new Output.ResourceExpr(resourceExpr.src, Object.fromEntries(stables.map((stable) => [stable, output?.[stable]])))
|
|
91
|
+
: // if there are no stable properties, treat every property as changed
|
|
92
|
+
resourceExpr;
|
|
76
93
|
if (diff == null) {
|
|
77
|
-
if (arePropsChanged(
|
|
94
|
+
if (arePropsChanged(oldProps, props)) {
|
|
78
95
|
// the props have changed but the provider did not provide any hints as to what is stable
|
|
79
96
|
// so we must assume everything has changed
|
|
80
|
-
return
|
|
97
|
+
return withStables(oldState?.attr);
|
|
81
98
|
}
|
|
82
99
|
}
|
|
83
100
|
else if (diff.action === "update") {
|
|
84
|
-
|
|
85
|
-
if (diff.stables) {
|
|
86
|
-
return new Output.ResourceExpr(resourceExpr.src, Object.fromEntries(diff.stables.map((stable) => [stable, output?.[stable]])));
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
// if there are no stable properties, treat every property as changed
|
|
90
|
-
return resourceExpr;
|
|
91
|
-
}
|
|
101
|
+
return withStables(oldState?.attr);
|
|
92
102
|
}
|
|
93
103
|
else if (diff.action === "replace") {
|
|
104
|
+
return resourceExpr;
|
|
105
|
+
}
|
|
106
|
+
if (oldState.status === "created" ||
|
|
107
|
+
oldState.status === "updated" ||
|
|
108
|
+
oldState.status === "replaced") {
|
|
109
|
+
// we can safely return the attributes if we know they have stabilized
|
|
110
|
+
return oldState?.attr;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// we must assume the resource doesn't exist if it hasn't stabilized
|
|
114
|
+
return resourceExpr;
|
|
94
115
|
}
|
|
95
|
-
return oldState?.output;
|
|
96
116
|
})));
|
|
97
117
|
});
|
|
98
118
|
const resolveInput = (input) => Effect.gen(function* () {
|
|
@@ -120,36 +140,42 @@ export const plan = (...resources) => Effect.gen(function* () {
|
|
|
120
140
|
}
|
|
121
141
|
else if (Output.isApplyExpr(expr)) {
|
|
122
142
|
const upstream = yield* resolveOutput(expr.expr);
|
|
123
|
-
return Output.
|
|
143
|
+
return Output.hasOutputs(upstream) ? expr : expr.f(upstream);
|
|
124
144
|
}
|
|
125
145
|
else if (Output.isEffectExpr(expr)) {
|
|
126
146
|
const upstream = yield* resolveOutput(expr.expr);
|
|
127
|
-
return Output.
|
|
147
|
+
return Output.hasOutputs(upstream) ? expr : yield* expr.f(upstream);
|
|
128
148
|
}
|
|
129
149
|
else if (Output.isAllExpr(expr)) {
|
|
130
150
|
return yield* Effect.all(expr.outs.map(resolveOutput));
|
|
131
151
|
}
|
|
132
152
|
return yield* Effect.die(new Error("Not implemented yet"));
|
|
133
153
|
});
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
154
|
+
// map of resource ID -> its downstream dependencies (resources that depend on it)
|
|
155
|
+
const oldDownstreamDependencies = Object.fromEntries(oldResources
|
|
156
|
+
.filter((resource) => !!resource)
|
|
157
|
+
.map((resource) => [resource.logicalId, resource.downstream]));
|
|
158
|
+
const newUpstreamDependencies = Object.fromEntries(resources.map((resource) => [
|
|
159
|
+
resource.id,
|
|
160
|
+
[
|
|
161
|
+
...Object.values(Output.upstreamAny(resource.props)).map((r) => r.id),
|
|
162
|
+
...(isService(resource)
|
|
163
|
+
? resource.props.bindings.capabilities.map((cap) => cap.resource.id)
|
|
164
|
+
: []),
|
|
165
|
+
],
|
|
166
|
+
]));
|
|
167
|
+
const newDownstreamDependencies = Object.fromEntries(resources.map((resource) => [
|
|
168
|
+
resource.id,
|
|
169
|
+
Object.entries(newUpstreamDependencies)
|
|
170
|
+
.filter(([_, downstream]) => downstream.includes(resource.id))
|
|
171
|
+
.map(([id]) => id),
|
|
172
|
+
]));
|
|
147
173
|
const resourceGraph = Object.fromEntries((yield* Effect.all(resources
|
|
148
174
|
.flatMap((resource) => [
|
|
149
175
|
...(isService(resource)
|
|
150
176
|
? resource.props.bindings.capabilities.map((cap) => cap.resource)
|
|
151
177
|
: []),
|
|
152
|
-
...Object.values(
|
|
178
|
+
...Object.values(Output.upstreamAny(resource.props)),
|
|
153
179
|
resource,
|
|
154
180
|
])
|
|
155
181
|
.filter((node, i, arr) => arr.findIndex((n) => n.id === node.id) === i)
|
|
@@ -163,6 +189,7 @@ export const plan = (...resources) => Effect.gen(function* () {
|
|
|
163
189
|
resourceId: id,
|
|
164
190
|
});
|
|
165
191
|
const provider = yield* resource.provider.tag;
|
|
192
|
+
const downstream = newDownstreamDependencies[id] ?? [];
|
|
166
193
|
const bindings = isService(node)
|
|
167
194
|
? yield* diffBindings({
|
|
168
195
|
oldState,
|
|
@@ -170,79 +197,197 @@ export const plan = (...resources) => Effect.gen(function* () {
|
|
|
170
197
|
target: {
|
|
171
198
|
id: node.id,
|
|
172
199
|
props: node.props,
|
|
173
|
-
|
|
200
|
+
// TODO(sam): pick the right ones based on old status
|
|
201
|
+
oldAttr: oldState?.attr,
|
|
174
202
|
oldProps: oldState?.props,
|
|
175
203
|
},
|
|
176
204
|
})
|
|
177
205
|
: []; // TODO(sam): return undefined instead of empty array
|
|
178
|
-
|
|
206
|
+
const Node = (node) => ({
|
|
207
|
+
...node,
|
|
208
|
+
provider,
|
|
209
|
+
resource,
|
|
210
|
+
bindings,
|
|
211
|
+
downstream,
|
|
212
|
+
});
|
|
213
|
+
// handle empty and intermediate (non-final) states:
|
|
214
|
+
if (oldState === undefined) {
|
|
179
215
|
return Node({
|
|
180
216
|
action: "create",
|
|
181
|
-
news,
|
|
182
|
-
|
|
183
|
-
resource,
|
|
184
|
-
bindings,
|
|
185
|
-
// phantom
|
|
186
|
-
attributes: undefined,
|
|
217
|
+
props: news,
|
|
218
|
+
state: oldState,
|
|
187
219
|
});
|
|
188
220
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
221
|
+
// TODO(sam): is this correct for all possible states a resource can be in?
|
|
222
|
+
const oldProps = oldState.props;
|
|
223
|
+
const diff = yield* asEffect(provider.diff
|
|
224
|
+
? provider.diff({
|
|
225
|
+
id,
|
|
226
|
+
olds: oldProps,
|
|
227
|
+
instanceId: oldState.instanceId,
|
|
228
|
+
output: oldState.attr,
|
|
229
|
+
news,
|
|
230
|
+
})
|
|
231
|
+
: undefined).pipe(Effect.map((diff) => diff ??
|
|
232
|
+
{
|
|
233
|
+
action: arePropsChanged(oldProps, news)
|
|
234
|
+
? "update"
|
|
235
|
+
: "noop",
|
|
236
|
+
}));
|
|
237
|
+
if (oldState.status === "creating") {
|
|
238
|
+
if (diff.action === "noop") {
|
|
239
|
+
// we're in the creating state and props are un-changed
|
|
240
|
+
// let's just continue where we left off
|
|
241
|
+
return Node({
|
|
242
|
+
action: "create",
|
|
243
|
+
props: news,
|
|
244
|
+
state: oldState,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
else if (diff.action === "update") {
|
|
248
|
+
// props have changed in a way that is updatable
|
|
249
|
+
// again, just continue with the create
|
|
250
|
+
// TODO(sam): should we maybe try an update instead?
|
|
251
|
+
return Node({
|
|
252
|
+
action: "create",
|
|
253
|
+
props: news,
|
|
254
|
+
state: oldState,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
// props have changed in an incompatible way
|
|
259
|
+
// because it's possible that an un-updatable resource has already been created
|
|
260
|
+
// we must use a replace step to create a new one and delete the potential old one
|
|
261
|
+
return Node({
|
|
262
|
+
action: "replace",
|
|
263
|
+
props: news,
|
|
264
|
+
deleteFirst: diff.deleteFirst ?? false,
|
|
265
|
+
state: oldState,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else if (oldState.status === "updating") {
|
|
270
|
+
// we started to update a resource but did not complete
|
|
271
|
+
if (diff.action === "update" || diff.action === "noop") {
|
|
272
|
+
return Node({
|
|
273
|
+
action: "update",
|
|
274
|
+
props: news,
|
|
275
|
+
state: oldState,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
// we started to update a resource but now believe we should replace it
|
|
280
|
+
return Node({
|
|
281
|
+
action: "replace",
|
|
282
|
+
deleteFirst: diff.deleteFirst ?? false,
|
|
283
|
+
props: news,
|
|
284
|
+
// TODO(sam): can Apply handle replacements when the oldState is UpdatingResourceState?
|
|
285
|
+
// -> or is there we do a provider.read to try and reconcile back to UpdatedResourceState?
|
|
286
|
+
state: oldState,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
else if (oldState.status === "replacing") {
|
|
291
|
+
// resource replacement started, but the replacement may or may not have been created
|
|
292
|
+
if (diff.action === "noop") {
|
|
293
|
+
// this is the stable case - noop means just continue with the replacement
|
|
294
|
+
return Node({
|
|
295
|
+
action: "replace",
|
|
296
|
+
deleteFirst: oldState.deleteFirst,
|
|
297
|
+
props: news,
|
|
298
|
+
state: oldState,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
else if (diff.action === "update") {
|
|
302
|
+
// potential problem here - the props have changed since we tried to replace,
|
|
303
|
+
// but not enough to trigger another replacement. the resource provider should
|
|
304
|
+
// be designed as idempotent to converge to the right state when creating the new resource
|
|
305
|
+
// the newly generated instanceId is intended to assist with this
|
|
306
|
+
return Node({
|
|
307
|
+
action: "replace",
|
|
308
|
+
deleteFirst: oldState.deleteFirst,
|
|
309
|
+
props: news,
|
|
310
|
+
state: oldState,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
// ah shit, so we tried to replace the resource and then crashed
|
|
315
|
+
// now the props have changed again in such a way that the (maybe, maybe not)
|
|
316
|
+
// created resource should also be replaced
|
|
317
|
+
// TODO(sam): what should we do?
|
|
318
|
+
// 1. trigger a deletion of the potentially created resource
|
|
319
|
+
// 2. expect the resource provider to handle it idempotently?
|
|
320
|
+
// -> i don't think this case is fair to put on the resource provider
|
|
321
|
+
// because if the resource was created, it's in a state that can't be updated
|
|
322
|
+
return yield* Effect.fail(new CannotReplacePartiallyReplacedResource(id));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
else if (oldState.status === "replaced") {
|
|
326
|
+
// replacement has been created but we're not done cleaning up the old state
|
|
327
|
+
if (diff.action === "noop") {
|
|
328
|
+
// this is the stable case - noop means just continue cleaning up the replacement
|
|
329
|
+
return Node({
|
|
330
|
+
action: "replace",
|
|
331
|
+
deleteFirst: oldState.deleteFirst,
|
|
332
|
+
props: news,
|
|
333
|
+
state: oldState,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
else if (diff.action === "update") {
|
|
337
|
+
// the replacement has been created but now also needs to be updated
|
|
338
|
+
// the resource provider should:
|
|
339
|
+
// 1. Update the newly created replacement resource
|
|
340
|
+
// 2. Then proceed as normal to delete the replaced resources (after all downstream references are updated)
|
|
341
|
+
return Node({
|
|
342
|
+
action: "update",
|
|
343
|
+
props: news,
|
|
344
|
+
state: oldState,
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
// the replacement has been created but now it needs to be replaced
|
|
349
|
+
// this is the worst-case scenario because downstream resources
|
|
350
|
+
// could have been been updated to point to the replaced resources
|
|
351
|
+
return yield* Effect.fail(new CannotReplacePartiallyReplacedResource(id));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
else if (oldState.status === "deleting") {
|
|
355
|
+
if (diff.action === "noop" || diff.action === "update") {
|
|
356
|
+
// we're in a partially deleted state, it is unclear whether it was or was not deleted
|
|
357
|
+
// it should be safe to re-create it with the same instanceId?
|
|
358
|
+
return Node({
|
|
359
|
+
action: "create",
|
|
360
|
+
props: news,
|
|
361
|
+
state: {
|
|
362
|
+
...oldState,
|
|
363
|
+
status: "creating",
|
|
364
|
+
props: news,
|
|
365
|
+
},
|
|
196
366
|
});
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
return yield* Effect.fail(new CannotReplacePartiallyReplacedResource(id));
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
else if (diff.action === "update") {
|
|
201
373
|
return Node({
|
|
202
374
|
action: "update",
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
output: oldState.output,
|
|
206
|
-
provider,
|
|
207
|
-
resource,
|
|
208
|
-
bindings,
|
|
209
|
-
// phantom
|
|
210
|
-
attributes: undefined,
|
|
375
|
+
props: news,
|
|
376
|
+
state: oldState,
|
|
211
377
|
});
|
|
212
378
|
}
|
|
213
|
-
else if (diff
|
|
379
|
+
else if (diff.action === "replace") {
|
|
214
380
|
return Node({
|
|
215
381
|
action: "replace",
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
provider,
|
|
220
|
-
resource,
|
|
221
|
-
bindings,
|
|
222
|
-
// phantom
|
|
223
|
-
attributes: undefined,
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
else if (diff?.action === "update") {
|
|
227
|
-
return Node({
|
|
228
|
-
action: "update",
|
|
229
|
-
olds: oldState.props,
|
|
230
|
-
news,
|
|
231
|
-
output: oldState.output,
|
|
232
|
-
provider,
|
|
233
|
-
resource,
|
|
234
|
-
bindings,
|
|
235
|
-
// phantom
|
|
236
|
-
attributes: undefined,
|
|
382
|
+
props: news,
|
|
383
|
+
state: oldState,
|
|
384
|
+
deleteFirst: diff?.deleteFirst ?? false,
|
|
237
385
|
});
|
|
238
386
|
}
|
|
239
387
|
else {
|
|
240
388
|
return Node({
|
|
241
389
|
action: "noop",
|
|
242
|
-
|
|
243
|
-
bindings,
|
|
244
|
-
// phantom
|
|
245
|
-
attributes: undefined,
|
|
390
|
+
state: oldState,
|
|
246
391
|
});
|
|
247
392
|
}
|
|
248
393
|
})))).map((update) => [update.resource.id, update]));
|
|
@@ -255,35 +400,30 @@ export const plan = (...resources) => Effect.gen(function* () {
|
|
|
255
400
|
stage: app.stage,
|
|
256
401
|
resourceId: id,
|
|
257
402
|
});
|
|
258
|
-
const context = yield* Effect.context();
|
|
259
403
|
if (oldState) {
|
|
260
|
-
const provider =
|
|
261
|
-
if (!provider) {
|
|
262
|
-
yield* Effect.die(new Error(`Provider not found for ${oldState?.type}`));
|
|
263
|
-
}
|
|
404
|
+
const provider = yield* getProviderByType(oldState.resourceType);
|
|
264
405
|
return [
|
|
265
406
|
id,
|
|
266
407
|
{
|
|
267
408
|
action: "delete",
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
provider,
|
|
271
|
-
attributes: oldState?.output,
|
|
272
|
-
// TODO(sam): Support Detach Bindings
|
|
409
|
+
state: oldState,
|
|
410
|
+
// // TODO(sam): Support Detach Bindings
|
|
273
411
|
bindings: [],
|
|
412
|
+
provider,
|
|
274
413
|
resource: {
|
|
275
414
|
id: id,
|
|
276
|
-
type: oldState.
|
|
277
|
-
attr: oldState.
|
|
415
|
+
type: oldState.resourceType,
|
|
416
|
+
attr: oldState.attr,
|
|
278
417
|
props: oldState.props,
|
|
279
418
|
},
|
|
280
|
-
|
|
419
|
+
// TODO(sam): is it enough to just pass through oldState?
|
|
420
|
+
downstream: oldDownstreamDependencies[id] ?? [],
|
|
281
421
|
},
|
|
282
422
|
];
|
|
283
423
|
}
|
|
284
424
|
})))).filter((v) => !!v));
|
|
285
425
|
for (const [resourceId, deletion] of Object.entries(deletions)) {
|
|
286
|
-
const dependencies = deletion.downstream.filter((d) => d in resourceGraph);
|
|
426
|
+
const dependencies = deletion.state.downstream.filter((d) => d in resourceGraph);
|
|
287
427
|
if (dependencies.length > 0) {
|
|
288
428
|
return yield* Effect.fail(new DeleteResourceHasDownstreamDependencies({
|
|
289
429
|
message: `Resource ${resourceId} has downstream dependencies`,
|
|
@@ -297,16 +437,29 @@ export const plan = (...resources) => Effect.gen(function* () {
|
|
|
297
437
|
deletions,
|
|
298
438
|
};
|
|
299
439
|
});
|
|
300
|
-
class
|
|
440
|
+
export class CannotReplacePartiallyReplacedResource extends Data.TaggedError("CannotReplacePartiallyReplacedResource") {
|
|
441
|
+
constructor(logicalId) {
|
|
442
|
+
super({
|
|
443
|
+
message: `Resource '${logicalId}' did not finish being replaced in a previous deployment ` +
|
|
444
|
+
`and is expected to be replaced again in this deployment. ` +
|
|
445
|
+
`You should revert its properties and try again after a successful deployment.`,
|
|
446
|
+
logicalId,
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
export class DeleteResourceHasDownstreamDependencies extends Data.TaggedError("DeleteResourceHasDownstreamDependencies") {
|
|
301
451
|
}
|
|
302
|
-
const arePropsChanged = (
|
|
303
|
-
return (
|
|
304
|
-
JSON.stringify(omit((
|
|
452
|
+
const arePropsChanged = (oldProps, newProps) => {
|
|
453
|
+
return (Output.hasOutputs(newProps) ||
|
|
454
|
+
JSON.stringify(omit((oldProps ?? {}), "bindings")) !==
|
|
455
|
+
JSON.stringify(omit((newProps ?? {}), "bindings")));
|
|
305
456
|
};
|
|
306
457
|
const diffBindings = Effect.fn(function* ({ oldState, bindings, target, }) {
|
|
307
458
|
// const actions: BindNode[] = [];
|
|
308
459
|
const oldBindings = oldState?.bindings;
|
|
309
|
-
const oldSids = new Set(
|
|
460
|
+
// const oldSids = new Set(
|
|
461
|
+
// oldBindings?.map(({ binding }) => binding.capability.sid),
|
|
462
|
+
// );
|
|
310
463
|
const diffBinding = Effect.fn(function* (binding) {
|
|
311
464
|
const cap = binding.capability;
|
|
312
465
|
const sid = cap.sid ?? `${cap.action}:${cap.resource.ID}`;
|
|
@@ -383,7 +536,7 @@ const isBindingDiff = Effect.fn(function* ({ target, oldBinding: { binding: oldB
|
|
|
383
536
|
id: oldCap.resource.id,
|
|
384
537
|
props: newCap.resource.props,
|
|
385
538
|
oldProps: oldState?.props,
|
|
386
|
-
oldAttr: oldState?.
|
|
539
|
+
oldAttr: oldState?.attr,
|
|
387
540
|
},
|
|
388
541
|
props: newBinding.props,
|
|
389
542
|
attr: oldBinding.attr,
|
|
@@ -403,4 +556,83 @@ const isBindingDiff = Effect.fn(function* ({ target, oldBinding: { binding: oldB
|
|
|
403
556
|
});
|
|
404
557
|
// TODO(sam): compare props
|
|
405
558
|
// oldBinding.props !== newBinding.props;
|
|
559
|
+
/**
|
|
560
|
+
* Print a plan in a human-readable format that shows the graph topology.
|
|
561
|
+
*/
|
|
562
|
+
export const printPlan = (plan) => {
|
|
563
|
+
const lines = [];
|
|
564
|
+
const allNodes = { ...plan.resources, ...plan.deletions };
|
|
565
|
+
// Build reverse mapping: upstream -> downstream
|
|
566
|
+
const upstreamMap = {};
|
|
567
|
+
for (const [id] of Object.entries(allNodes)) {
|
|
568
|
+
upstreamMap[id] = [];
|
|
569
|
+
}
|
|
570
|
+
for (const [id, node] of Object.entries(allNodes)) {
|
|
571
|
+
if (!node)
|
|
572
|
+
continue;
|
|
573
|
+
for (const downstreamId of node.state?.downstream ?? []) {
|
|
574
|
+
if (upstreamMap[downstreamId]) {
|
|
575
|
+
upstreamMap[downstreamId].push(id);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
// Action symbols
|
|
580
|
+
const actionSymbol = (action) => {
|
|
581
|
+
switch (action) {
|
|
582
|
+
case "create":
|
|
583
|
+
return "+";
|
|
584
|
+
case "update":
|
|
585
|
+
return "~";
|
|
586
|
+
case "delete":
|
|
587
|
+
return "-";
|
|
588
|
+
case "replace":
|
|
589
|
+
return "±";
|
|
590
|
+
case "noop":
|
|
591
|
+
return "=";
|
|
592
|
+
default:
|
|
593
|
+
return "?";
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
// Print header
|
|
597
|
+
lines.push("╔════════════════════════════════════════════════════════════════╗");
|
|
598
|
+
lines.push("║ PLAN ║");
|
|
599
|
+
lines.push("╠════════════════════════════════════════════════════════════════╣");
|
|
600
|
+
lines.push("║ Legend: + create, ~ update, - delete, ± replace, = noop ║");
|
|
601
|
+
lines.push("╚════════════════════════════════════════════════════════════════╝");
|
|
602
|
+
lines.push("");
|
|
603
|
+
// Print resources section
|
|
604
|
+
lines.push("┌─ Resources ────────────────────────────────────────────────────┐");
|
|
605
|
+
const resourceIds = Object.keys(plan.resources).sort();
|
|
606
|
+
for (const id of resourceIds) {
|
|
607
|
+
const node = plan.resources[id];
|
|
608
|
+
const symbol = actionSymbol(node.action);
|
|
609
|
+
const type = node.resource?.type ?? "unknown";
|
|
610
|
+
const downstream = node.state?.downstream?.length
|
|
611
|
+
? ` → [${node.state?.downstream.join(", ")}]`
|
|
612
|
+
: "";
|
|
613
|
+
lines.push(`│ [${symbol}] ${id} (${type})${downstream}`);
|
|
614
|
+
}
|
|
615
|
+
if (resourceIds.length === 0) {
|
|
616
|
+
lines.push("│ (none)");
|
|
617
|
+
}
|
|
618
|
+
lines.push("└────────────────────────────────────────────────────────────────┘");
|
|
619
|
+
lines.push("");
|
|
620
|
+
// Print deletions section
|
|
621
|
+
lines.push("┌─ Deletions ────────────────────────────────────────────────────┐");
|
|
622
|
+
const deletionIds = Object.keys(plan.deletions).sort();
|
|
623
|
+
for (const id of deletionIds) {
|
|
624
|
+
const node = plan.deletions[id];
|
|
625
|
+
const type = node.resource?.type ?? "unknown";
|
|
626
|
+
const downstream = node.state.downstream?.length
|
|
627
|
+
? ` → [${node.state.downstream.join(", ")}]`
|
|
628
|
+
: "";
|
|
629
|
+
lines.push(`│ [-] ${id} (${type})${downstream}`);
|
|
630
|
+
}
|
|
631
|
+
if (deletionIds.length === 0) {
|
|
632
|
+
lines.push("│ (none)");
|
|
633
|
+
}
|
|
634
|
+
lines.push("└────────────────────────────────────────────────────────────────┘");
|
|
635
|
+
lines.push("");
|
|
636
|
+
return lines.join("\n");
|
|
637
|
+
};
|
|
406
638
|
//# sourceMappingURL=plan.js.map
|