@homeflare/alchemy 0.34.0 → 0.35.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/dist/grafana/alert-rule-group-drop-warning.d.ts +25 -0
- package/dist/grafana/alert-rule-group-drop-warning.d.ts.map +1 -0
- package/dist/grafana/alert-rule-group-fixtures.d.ts +73 -0
- package/dist/grafana/alert-rule-group-fixtures.d.ts.map +1 -0
- package/dist/grafana/alert-rule-group-model.d.ts +28 -0
- package/dist/grafana/alert-rule-group-model.d.ts.map +1 -0
- package/dist/grafana/alert-rule-group.d.ts +60 -0
- package/dist/grafana/alert-rule-group.d.ts.map +1 -0
- package/dist/grafana/index.d.ts +5 -4
- package/dist/grafana/index.d.ts.map +1 -1
- package/dist/grafana/index.js +241 -139
- package/dist/grafana/index.js.map +11 -8
- package/dist/grafana/providers.d.ts +1 -1
- package/dist/grafana/providers.d.ts.map +1 -1
- package/dist/proxmox/index.js +349 -287
- package/dist/proxmox/index.js.map +8 -7
- package/dist/proxmox/network-apply-read.d.ts +12 -0
- package/dist/proxmox/network-apply-read.d.ts.map +1 -1
- package/dist/proxmox/network-apply.d.ts +2 -0
- package/dist/proxmox/network-apply.d.ts.map +1 -1
- package/dist/proxmox/node-network-form.d.ts +86 -54
- package/dist/proxmox/node-network-form.d.ts.map +1 -1
- package/dist/proxmox/node-network-wire.d.ts +100 -0
- package/dist/proxmox/node-network-wire.d.ts.map +1 -0
- package/dist/proxmox/node-network.d.ts +21 -106
- package/dist/proxmox/node-network.d.ts.map +1 -1
- package/docs/grafana-alerting-rules.md +143 -0
- package/docs/grafana-alerting.md +5 -3
- package/docs/grafana.md +4 -2
- package/docs/upstream-conformance.md +16 -4
- package/package.json +1 -1
- package/src/grafana/alert-rule-group-drop-warning.test.ts +107 -0
- package/src/grafana/alert-rule-group-drop-warning.ts +41 -0
- package/src/grafana/alert-rule-group-fixtures.ts +46 -0
- package/src/grafana/alert-rule-group-model.test.ts +75 -0
- package/src/grafana/alert-rule-group-model.ts +66 -0
- package/src/grafana/alert-rule-group-provenance.test.ts +116 -0
- package/src/grafana/alert-rule-group.test.ts +164 -0
- package/src/grafana/alert-rule-group.ts +231 -0
- package/src/grafana/index.ts +11 -4
- package/src/grafana/providers.ts +2 -0
- package/src/proxmox/constraints-host-forms.test.ts +2 -2
- package/src/proxmox/network-apply-read.ts +12 -0
- package/src/proxmox/network-apply.ts +2 -0
- package/src/proxmox/node-network-form.ts +93 -99
- package/src/proxmox/node-network-read-failure.test.ts +206 -0
- package/src/proxmox/node-network-wire.ts +239 -0
- package/src/proxmox/node-network.ts +155 -167
package/dist/proxmox/index.js
CHANGED
|
@@ -3372,10 +3372,14 @@ var handlers10 = {
|
|
|
3372
3372
|
var ProxmoxNetworkApplyProvider = () => Provider15.effect(ProxmoxNetworkApply, Effect38.succeed(ProxmoxNetworkApply.Provider.of(handlers10)));
|
|
3373
3373
|
// src/proxmox/node-network.ts
|
|
3374
3374
|
import { Resource as Resource16 } from "alchemy";
|
|
3375
|
+
import { isResolved as isResolved10 } from "alchemy/Diff";
|
|
3375
3376
|
import * as Provider16 from "alchemy/Provider";
|
|
3376
|
-
import * as
|
|
3377
|
+
import * as nodes2 from "@distilled.cloud/proxmox/nodes";
|
|
3378
|
+
import * as Effect40 from "effect/Effect";
|
|
3377
3379
|
|
|
3378
3380
|
// src/proxmox/node-network-form.ts
|
|
3381
|
+
var NODE_NETWORK_CREATE = "pve:POST /nodes/{node}/network";
|
|
3382
|
+
var NODE_NETWORK_UPDATE = "pve:PUT /nodes/{node}/network/{iface}";
|
|
3379
3383
|
var UNSET3 = -1;
|
|
3380
3384
|
var ifaceList = (value) => text(value).split(/[\s,;]+/).filter((part) => part !== "").sort().join(" ");
|
|
3381
3385
|
var comment2 = (value) => text(value).replace(/\s+$/, "");
|
|
@@ -3400,72 +3404,130 @@ var body4 = (props) => ({
|
|
|
3400
3404
|
...field3("vlan-raw-device", props["vlan-raw-device"]),
|
|
3401
3405
|
type: props.type
|
|
3402
3406
|
});
|
|
3403
|
-
var
|
|
3407
|
+
var createForm5 = (props) => ({
|
|
3404
3408
|
...body4(props),
|
|
3405
3409
|
iface: props.iface
|
|
3406
3410
|
});
|
|
3407
|
-
var
|
|
3411
|
+
var updateForm2 = (props) => {
|
|
3408
3412
|
const clear = [
|
|
3409
3413
|
...props.cidr === undefined ? ["cidr"] : [],
|
|
3410
3414
|
...props.bridge_vlan_aware === false ? ["bridge_vlan_aware"] : []
|
|
3411
3415
|
];
|
|
3412
|
-
|
|
3413
|
-
return withClears(fields, clear);
|
|
3416
|
+
return withClears(body4(props), clear);
|
|
3414
3417
|
};
|
|
3415
|
-
|
|
3416
|
-
|
|
3418
|
+
|
|
3419
|
+
// src/proxmox/node-network-wire.ts
|
|
3420
|
+
import * as nodes from "@distilled.cloud/proxmox/nodes";
|
|
3421
|
+
import * as Effect39 from "effect/Effect";
|
|
3422
|
+
var attributesOf5 = (live, props) => {
|
|
3423
|
+
const data = live;
|
|
3424
|
+
const liveType = text(data["type"]);
|
|
3417
3425
|
if (liveType !== "" && liveType !== props.type)
|
|
3418
3426
|
return;
|
|
3419
3427
|
return {
|
|
3420
|
-
active: bool(
|
|
3421
|
-
autostart: bool(
|
|
3422
|
-
"bond-primary": text(
|
|
3423
|
-
bond_miimon: text(
|
|
3424
|
-
bond_mode: text(
|
|
3425
|
-
bond_xmit_hash_policy: text(
|
|
3426
|
-
bridge_fd: text(
|
|
3427
|
-
bridge_ports: ifaceList(
|
|
3428
|
-
bridge_stp: text(
|
|
3429
|
-
bridge_vids: ifaceList(
|
|
3430
|
-
bridge_vlan_aware: bool(
|
|
3431
|
-
cidr: text(
|
|
3432
|
-
comments: comment2(
|
|
3433
|
-
exists: bool(
|
|
3434
|
-
families: Array.isArray(
|
|
3435
|
-
gateway: text(
|
|
3428
|
+
active: bool(data["active"]),
|
|
3429
|
+
autostart: bool(data["autostart"]),
|
|
3430
|
+
"bond-primary": text(data["bond-primary"]),
|
|
3431
|
+
bond_miimon: text(data["bond_miimon"]),
|
|
3432
|
+
bond_mode: text(data["bond_mode"]),
|
|
3433
|
+
bond_xmit_hash_policy: text(data["bond_xmit_hash_policy"]),
|
|
3434
|
+
bridge_fd: text(data["bridge_fd"]),
|
|
3435
|
+
bridge_ports: ifaceList(data["bridge_ports"]),
|
|
3436
|
+
bridge_stp: text(data["bridge_stp"]),
|
|
3437
|
+
bridge_vids: ifaceList(data["bridge_vids"]),
|
|
3438
|
+
bridge_vlan_aware: bool(data["bridge_vlan_aware"]),
|
|
3439
|
+
cidr: text(data["cidr"]),
|
|
3440
|
+
comments: comment2(data["comments"]),
|
|
3441
|
+
exists: bool(data["exists"]),
|
|
3442
|
+
families: Array.isArray(data["families"]) ? data["families"].join(",") : "",
|
|
3443
|
+
gateway: text(data["gateway"]),
|
|
3436
3444
|
iface: props.iface,
|
|
3437
|
-
method: text(
|
|
3438
|
-
mtu: int(
|
|
3445
|
+
method: text(data["method"]),
|
|
3446
|
+
mtu: int(data["mtu"], UNSET3),
|
|
3439
3447
|
node: props.node,
|
|
3440
|
-
priority: int(
|
|
3441
|
-
slaves: ifaceList(
|
|
3448
|
+
priority: int(data["priority"], UNSET3),
|
|
3449
|
+
slaves: ifaceList(data["slaves"]),
|
|
3442
3450
|
type: liveType === "" ? props.type : liveType,
|
|
3443
|
-
"vlan-id": int(
|
|
3444
|
-
"vlan-raw-device": text(
|
|
3451
|
+
"vlan-id": int(data["vlan-id"], UNSET3),
|
|
3452
|
+
"vlan-raw-device": text(data["vlan-raw-device"])
|
|
3445
3453
|
};
|
|
3446
3454
|
};
|
|
3455
|
+
var readInterfaceOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false, nodes.getNodeNetwork({ iface: props.iface, node: props.node })).pipe(Effect39.catchTag("ParameterVerificationFailed", (error) => error.errors["iface"] === "interface does not exist" ? Effect39.succeed(undefined) : Effect39.fail(error)))).pipe(Effect39.map((live) => {
|
|
3456
|
+
if (live === UNREADABLE)
|
|
3457
|
+
return UNREADABLE;
|
|
3458
|
+
return live === undefined ? undefined : attributesOf5(live, props);
|
|
3459
|
+
}));
|
|
3460
|
+
var readInterface = (props) => readInterfaceOrFail(props).pipe(Effect39.orElseSucceed(() => {
|
|
3461
|
+
return;
|
|
3462
|
+
}));
|
|
3463
|
+
var dropUnreadable4 = (live) => live === UNREADABLE ? undefined : live;
|
|
3464
|
+
var matches4 = (attributes, props) => attributes.cidr === (props.cidr ?? "") && same2(props.gateway, attributes.gateway) && same2(props.autostart, attributes.autostart) && same2(props.mtu, attributes.mtu) && sameComment(props.comments, attributes.comments) && sameList(props.bridge_ports, attributes.bridge_ports) && sameList(props.bridge_vids, attributes.bridge_vids) && same2(props.bridge_vlan_aware, attributes.bridge_vlan_aware) && sameList(props.slaves, attributes.slaves) && same2(props.bond_mode, attributes.bond_mode) && same2(props.bond_xmit_hash_policy, attributes.bond_xmit_hash_policy) && same2(props["bond-primary"], attributes["bond-primary"]) && same2(props["vlan-id"], attributes["vlan-id"]) && same2(props["vlan-raw-device"], attributes["vlan-raw-device"]);
|
|
3447
3465
|
|
|
3448
3466
|
// src/proxmox/node-network.ts
|
|
3449
3467
|
var ProxmoxNodeNetwork = Resource16("Proxmox.NodeNetwork", {
|
|
3450
3468
|
defaultRemovalPolicy: "retain"
|
|
3451
3469
|
});
|
|
3452
|
-
var
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3470
|
+
var RENAMED = {
|
|
3471
|
+
"bond-primary": "bond_primary",
|
|
3472
|
+
"vlan-id": "vlan_id",
|
|
3473
|
+
"vlan-raw-device": "vlan_raw_device"
|
|
3474
|
+
};
|
|
3475
|
+
var toDistilled = (form) => Object.fromEntries(Object.entries(form).map(([key, value]) => [RENAMED[key] ?? key, value]));
|
|
3476
|
+
var toDistilledCreate = (props) => ({
|
|
3477
|
+
...toDistilled(createForm5(props)),
|
|
3478
|
+
node: props.node
|
|
3479
|
+
});
|
|
3480
|
+
var toDistilledUpdate = (props) => ({
|
|
3481
|
+
...toDistilled(updateForm2(props)),
|
|
3482
|
+
iface: props.iface,
|
|
3483
|
+
node: props.node
|
|
3484
|
+
});
|
|
3485
|
+
var ProxmoxNodeNetworkProvider = () => Provider16.effect(ProxmoxNodeNetwork, Effect40.succeed(ProxmoxNodeNetwork.Provider.of({
|
|
3486
|
+
list: () => Effect40.succeed([]),
|
|
3487
|
+
read: Effect40.fn(function* ({ olds, output }) {
|
|
3488
|
+
return dropUnreadable4(yield* output === undefined ? readInterface(olds) : readInterfaceOrFail(olds));
|
|
3489
|
+
}),
|
|
3490
|
+
diff: Effect40.fn(function* ({ news, output }) {
|
|
3491
|
+
if (!isResolved10(news))
|
|
3492
|
+
return;
|
|
3493
|
+
yield* guardWrite2(NODE_NETWORK_CREATE, createForm5(news), output === undefined);
|
|
3494
|
+
yield* guardWrite2(NODE_NETWORK_UPDATE, updateForm2(news), false);
|
|
3495
|
+
if (output === undefined)
|
|
3496
|
+
return;
|
|
3497
|
+
const live = yield* readInterfaceOrFail(news);
|
|
3498
|
+
if (live === UNREADABLE) {
|
|
3499
|
+
yield* unreadableWarning("Proxmox.NodeNetwork", `${news.node}/${news.iface}`);
|
|
3500
|
+
return { action: "noop" };
|
|
3501
|
+
}
|
|
3502
|
+
if (live === undefined) {
|
|
3503
|
+
yield* guardWrite2(NODE_NETWORK_CREATE, createForm5(news), true);
|
|
3504
|
+
return { action: "update" };
|
|
3505
|
+
}
|
|
3506
|
+
return matches4(live, news) ? { action: "noop" } : { action: "update" };
|
|
3507
|
+
}),
|
|
3508
|
+
reconcile: Effect40.fn(function* ({ news }) {
|
|
3509
|
+
const before = dropUnreadable4(yield* readInterface(news));
|
|
3510
|
+
yield* guardWrite2(NODE_NETWORK_CREATE, createForm5(news), before === undefined);
|
|
3511
|
+
yield* guardWrite2(NODE_NETWORK_UPDATE, updateForm2(news), false);
|
|
3512
|
+
if (before === undefined) {
|
|
3513
|
+
yield* runPve(news.target, "provision", true, nodes2.createNodeNetwork(toDistilledCreate(news)));
|
|
3514
|
+
} else if (!matches4(before, news)) {
|
|
3515
|
+
yield* runPve(news.target, "provision", true, nodes2.putNodeNetwork2(toDistilledUpdate(news)));
|
|
3516
|
+
}
|
|
3517
|
+
const after = dropUnreadable4(yield* readInterface(news));
|
|
3518
|
+
if (after === undefined) {
|
|
3519
|
+
return yield* Effect40.die(new Error(`nodes/${news.node}/network/${news.iface}: wrote with no error, but the ` + 'interface is still absent -- PVE wraps every answer in {"data":...} and can ' + "report success on a call that did nothing, so read back rather than trust it."));
|
|
3520
|
+
}
|
|
3521
|
+
return after;
|
|
3522
|
+
}),
|
|
3523
|
+
delete: Effect40.fn(function* ({ olds }) {
|
|
3524
|
+
yield* runPve(olds.target, "provision", true, nodes2.deleteNodeNetwork2({ iface: olds.iface, node: olds.node }));
|
|
3525
|
+
})
|
|
3526
|
+
})));
|
|
3465
3527
|
// src/proxmox/notification-matcher.ts
|
|
3466
3528
|
import { Resource as Resource17 } from "alchemy";
|
|
3467
3529
|
import * as Provider17 from "alchemy/Provider";
|
|
3468
|
-
import * as
|
|
3530
|
+
import * as Effect41 from "effect/Effect";
|
|
3469
3531
|
|
|
3470
3532
|
// src/proxmox/notification-matcher-form.ts
|
|
3471
3533
|
var list = (value) => Array.isArray(value) ? value.map((item) => String(item)) : [];
|
|
@@ -3543,7 +3605,7 @@ var matcherUpdateForm = (fields) => {
|
|
|
3543
3605
|
|
|
3544
3606
|
// src/proxmox/notification-matcher.ts
|
|
3545
3607
|
var ProxmoxNotificationMatcher = Resource17("Proxmox.NotificationMatcher");
|
|
3546
|
-
var
|
|
3608
|
+
var handlers11 = pveHandlers({
|
|
3547
3609
|
attributes: (live, props) => matcherAttributes(live, props.name),
|
|
3548
3610
|
collection: () => "cluster/notifications/matchers",
|
|
3549
3611
|
createForm: matcherCreateForm,
|
|
@@ -3555,11 +3617,11 @@ var handlers12 = pveHandlers({
|
|
|
3555
3617
|
path: (props) => `cluster/notifications/matchers/${props.name}`,
|
|
3556
3618
|
updateForm: matcherUpdateForm
|
|
3557
3619
|
});
|
|
3558
|
-
var ProxmoxNotificationMatcherProvider = () => Provider17.effect(ProxmoxNotificationMatcher,
|
|
3620
|
+
var ProxmoxNotificationMatcherProvider = () => Provider17.effect(ProxmoxNotificationMatcher, Effect41.succeed(ProxmoxNotificationMatcher.Provider.of(handlers11)));
|
|
3559
3621
|
// src/proxmox/notification-target.ts
|
|
3560
3622
|
import { Resource as Resource18 } from "alchemy";
|
|
3561
3623
|
import * as Provider18 from "alchemy/Provider";
|
|
3562
|
-
import * as
|
|
3624
|
+
import * as Effect42 from "effect/Effect";
|
|
3563
3625
|
|
|
3564
3626
|
// src/proxmox/notification-target-endpoint.ts
|
|
3565
3627
|
var ENDPOINTS = {
|
|
@@ -3615,7 +3677,7 @@ var createShape = (props) => ({
|
|
|
3615
3677
|
|
|
3616
3678
|
// src/proxmox/notification-target.ts
|
|
3617
3679
|
var ProxmoxNotificationTarget = Resource18("Proxmox.NotificationTarget");
|
|
3618
|
-
var
|
|
3680
|
+
var handlers12 = pveHandlers({
|
|
3619
3681
|
attributes: (live, props) => ({
|
|
3620
3682
|
author: text(live["author"]),
|
|
3621
3683
|
body: text(live["body"]),
|
|
@@ -3641,15 +3703,15 @@ var handlers13 = pveHandlers({
|
|
|
3641
3703
|
path: (props) => `cluster/notifications/endpoints/${props.type}/${props.name}`,
|
|
3642
3704
|
updateForm: shape4
|
|
3643
3705
|
});
|
|
3644
|
-
var ProxmoxNotificationTargetProvider = () => Provider18.effect(ProxmoxNotificationTarget,
|
|
3706
|
+
var ProxmoxNotificationTargetProvider = () => Provider18.effect(ProxmoxNotificationTarget, Effect42.succeed(ProxmoxNotificationTarget.Provider.of(handlers12)));
|
|
3645
3707
|
// src/proxmox/pbs-datastore.ts
|
|
3646
3708
|
import { Resource as Resource19 } from "alchemy";
|
|
3647
|
-
import { isResolved as
|
|
3709
|
+
import { isResolved as isResolved11 } from "alchemy/Diff";
|
|
3648
3710
|
import * as Provider19 from "alchemy/Provider";
|
|
3649
|
-
import * as
|
|
3711
|
+
import * as Effect46 from "effect/Effect";
|
|
3650
3712
|
|
|
3651
3713
|
// src/proxmox/pbs-datastore-form.ts
|
|
3652
|
-
import * as
|
|
3714
|
+
import * as Effect43 from "effect/Effect";
|
|
3653
3715
|
var attributes = (live, props) => ({
|
|
3654
3716
|
backend: propertyString(live["backend"]),
|
|
3655
3717
|
comment: text(live["comment"]),
|
|
@@ -3672,7 +3734,7 @@ var attributes = (live, props) => ({
|
|
|
3672
3734
|
"verify-new": bool(live["verify-new"])
|
|
3673
3735
|
});
|
|
3674
3736
|
var same4 = (declared, live) => declared === undefined || declared === live;
|
|
3675
|
-
var
|
|
3737
|
+
var matches5 = (live, props) => same4(props.comment, live.comment) && same4(props["gc-schedule"]?.trim(), live["gc-schedule"]) && same4(props["prune-schedule"]?.trim(), live["prune-schedule"]) && same4(props["keep-last"], live["keep-last"]) && same4(props["keep-hourly"], live["keep-hourly"]) && same4(props["keep-daily"], live["keep-daily"]) && same4(props["keep-weekly"], live["keep-weekly"]) && same4(props["keep-monthly"], live["keep-monthly"]) && same4(props["keep-yearly"], live["keep-yearly"]) && same4(props["notify-user"], live["notify-user"]) && same4(props["counter-reset-schedule"]?.trim(), live["counter-reset-schedule"]) && (props["notification-thresholds"] === undefined || propertyString(props["notification-thresholds"]) === live["notification-thresholds"]) && same4(props["verify-new"], live["verify-new"]) && (props.notify === undefined || propertyString(props.notify) === live.notify) && (props.tuning === undefined || propertyString(props.tuning) === live.tuning) && (props["maintenance-mode"] === undefined || propertyString(props["maintenance-mode"], "type") === live["maintenance-mode"]);
|
|
3676
3738
|
var set2 = (key, value) => value === undefined ? {} : { [key]: value };
|
|
3677
3739
|
var count = (value) => value === undefined ? undefined : String(value);
|
|
3678
3740
|
var mutable = (props) => ({
|
|
@@ -3693,56 +3755,56 @@ var mutable = (props) => ({
|
|
|
3693
3755
|
...set2("tuning", props.tuning),
|
|
3694
3756
|
...set2("verify-new", flag(props["verify-new"]))
|
|
3695
3757
|
});
|
|
3696
|
-
var
|
|
3758
|
+
var createForm6 = (props) => ({
|
|
3697
3759
|
...mutable(props),
|
|
3698
3760
|
name: props.name,
|
|
3699
3761
|
path: props.path,
|
|
3700
3762
|
...props.backend === undefined ? {} : { backend: props.backend }
|
|
3701
3763
|
});
|
|
3702
|
-
var
|
|
3764
|
+
var updateForm3 = (props) => mutable(props);
|
|
3703
3765
|
var object2 = (props) => `config/datastore/${props.name}`;
|
|
3704
|
-
var readOne = (props) => pve(props.target, "read", "GET", object2(props)).pipe(
|
|
3766
|
+
var readOne = (props) => pve(props.target, "read", "GET", object2(props)).pipe(Effect43.map((live) => live === undefined || typeof live["name"] !== "string" ? undefined : attributes(live, props)), Effect43.orElseSucceed(() => {
|
|
3705
3767
|
return;
|
|
3706
3768
|
}));
|
|
3707
3769
|
|
|
3708
3770
|
// src/proxmox/pbs-datastore-guard.ts
|
|
3709
|
-
import * as
|
|
3771
|
+
import * as Effect44 from "effect/Effect";
|
|
3710
3772
|
var samePath = (left, right) => {
|
|
3711
3773
|
const trim = (value) => value.length > 1 ? value.replace(/\/+$/, "") : value;
|
|
3712
3774
|
return trim(left) === trim(right);
|
|
3713
3775
|
};
|
|
3714
|
-
var guardPath = (live, props) => live.path === "" || samePath(live.path, props.path) ?
|
|
3715
|
-
var guardBackend = (live, props) => props.backend === undefined || propertyString(props.backend) === live.backend ?
|
|
3716
|
-
var settle3 = (read3, done) =>
|
|
3776
|
+
var guardPath = (live, props) => live.path === "" || samePath(live.path, props.path) ? Effect44.void : Effect44.die(new Error(`${object2(props)}: declared path ${props.path} but PBS holds ${live.path}. \`path\` ` + "is create-only, so this cannot be reconciled and will NOT be planned as a silent " + "noop: backups would keep landing in the old directory behind a green plan. Correct " + "the declaration, or remove the datastore and declare a new one -- the contents live, " + "because `destroy-data` is never sent."));
|
|
3777
|
+
var guardBackend = (live, props) => props.backend === undefined || propertyString(props.backend) === live.backend ? Effect44.void : Effect44.die(new Error(`${object2(props)}: declared backend ${props.backend} but PBS holds ` + `${live.backend === "" ? "(none — a local datastore)" : live.backend}. \`backend\` ` + "is create-only: PBS has no update for it, so this cannot be reconciled and will NOT " + "be planned as a silent noop. Correct the declaration to match what is really there, " + "or remove the datastore and declare a new one -- the contents live, because " + "`destroy-data` is never sent."));
|
|
3778
|
+
var settle3 = (read3, done) => Effect44.gen(function* () {
|
|
3717
3779
|
for (let attempt = 0;attempt < 60; attempt += 1) {
|
|
3718
3780
|
const live = yield* read3;
|
|
3719
3781
|
if (done(live))
|
|
3720
3782
|
return live;
|
|
3721
|
-
yield*
|
|
3783
|
+
yield* Effect44.sleep("2 seconds");
|
|
3722
3784
|
}
|
|
3723
3785
|
return yield* read3;
|
|
3724
3786
|
});
|
|
3725
3787
|
|
|
3726
3788
|
// src/proxmox/pbs-datastore-endpoint.ts
|
|
3727
|
-
import * as
|
|
3789
|
+
import * as Effect45 from "effect/Effect";
|
|
3728
3790
|
var DATASTORE_ENDPOINT = {
|
|
3729
3791
|
create: "pbs:POST /config/datastore",
|
|
3730
3792
|
update: "pbs:PUT /config/datastore/{name}"
|
|
3731
3793
|
};
|
|
3732
|
-
var guardDatastoreForms = (props) =>
|
|
3733
|
-
yield* guardForm(DATASTORE_ENDPOINT.create,
|
|
3734
|
-
yield* guardForm(DATASTORE_ENDPOINT.update,
|
|
3794
|
+
var guardDatastoreForms = (props) => Effect45.gen(function* () {
|
|
3795
|
+
yield* guardForm(DATASTORE_ENDPOINT.create, createForm6(props), true);
|
|
3796
|
+
yield* guardForm(DATASTORE_ENDPOINT.update, updateForm3(props), false);
|
|
3735
3797
|
});
|
|
3736
3798
|
|
|
3737
3799
|
// src/proxmox/pbs-datastore.ts
|
|
3738
3800
|
var PbsDatastore = Resource19("Pbs.Datastore", {
|
|
3739
3801
|
defaultRemovalPolicy: "retain"
|
|
3740
3802
|
});
|
|
3741
|
-
var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore,
|
|
3742
|
-
list: () =>
|
|
3803
|
+
var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore, Effect46.succeed(PbsDatastore.Provider.of({
|
|
3804
|
+
list: () => Effect46.succeed([]),
|
|
3743
3805
|
read: ({ olds }) => readOne(olds),
|
|
3744
|
-
diff: ({ news, output }) =>
|
|
3745
|
-
if (!
|
|
3806
|
+
diff: ({ news, output }) => Effect46.gen(function* () {
|
|
3807
|
+
if (!isResolved11(news))
|
|
3746
3808
|
return;
|
|
3747
3809
|
yield* guardDatastoreForms(news);
|
|
3748
3810
|
if (output === undefined)
|
|
@@ -3752,42 +3814,42 @@ var PbsDatastoreProvider = () => Provider19.effect(PbsDatastore, Effect45.succee
|
|
|
3752
3814
|
return { action: "update" };
|
|
3753
3815
|
yield* guardPath(live, news);
|
|
3754
3816
|
yield* guardBackend(live, news);
|
|
3755
|
-
return
|
|
3817
|
+
return matches5(live, news) ? { action: "noop" } : { action: "update" };
|
|
3756
3818
|
}),
|
|
3757
|
-
reconcile:
|
|
3819
|
+
reconcile: Effect46.fn(function* ({ news }) {
|
|
3758
3820
|
yield* guardDatastoreForms(news);
|
|
3759
3821
|
const live = yield* readOne(news);
|
|
3760
3822
|
let upid;
|
|
3761
3823
|
if (live === undefined) {
|
|
3762
|
-
upid = yield* pve(news.target, "provision", "POST", "config/datastore",
|
|
3824
|
+
upid = yield* pve(news.target, "provision", "POST", "config/datastore", createForm6(news));
|
|
3763
3825
|
} else {
|
|
3764
3826
|
yield* guardPath(live, news);
|
|
3765
3827
|
yield* guardBackend(live, news);
|
|
3766
|
-
const form = formToSend(
|
|
3828
|
+
const form = formToSend(matches5, live, news, updateForm3(news));
|
|
3767
3829
|
if (form !== undefined) {
|
|
3768
3830
|
yield* pve(news.target, "provision", "PUT", object2(news), form);
|
|
3769
3831
|
}
|
|
3770
3832
|
}
|
|
3771
|
-
const after = yield* settle3(readOne(news), (row) => row !== undefined &&
|
|
3772
|
-
if (after === undefined || !
|
|
3773
|
-
return yield*
|
|
3833
|
+
const after = yield* settle3(readOne(news), (row) => row !== undefined && matches5(row, news));
|
|
3834
|
+
if (after === undefined || !matches5(after, news)) {
|
|
3835
|
+
return yield* Effect46.die(new Error(`${object2(news)}: the write returned no error but the datastore still does not ` + `match the declaration after 120s. PBS answered with task ${upid ?? "(none)"} ` + "-- read it with `proxmox-backup-manager task log <upid>`. A slow disk is a " + "plausible cause (see `settle`); a create over an existing chunk store is not, " + "because PBS refuses that outright rather than timing out."));
|
|
3774
3836
|
}
|
|
3775
3837
|
return after;
|
|
3776
3838
|
}),
|
|
3777
|
-
delete:
|
|
3839
|
+
delete: Effect46.fn(function* ({ olds }) {
|
|
3778
3840
|
yield* pve(olds.target, "provision", "DELETE", object2(olds));
|
|
3779
3841
|
const left = yield* settle3(readOne(olds), (row) => row === undefined);
|
|
3780
3842
|
if (left !== undefined) {
|
|
3781
|
-
return yield*
|
|
3843
|
+
return yield* Effect46.die(new Error(`${object2(olds)}: the DELETE returned no error but the datastore is still in ` + "datastore.cfg after 120s. Either a backup, verify or GC task still holds it, " + "or the provision role lacks Datastore.Allocate on /datastore/" + `${olds.name}. Read the task log with \`proxmox-backup-manager task log <upid>\`.`));
|
|
3782
3844
|
}
|
|
3783
3845
|
})
|
|
3784
3846
|
})));
|
|
3785
3847
|
// src/proxmox/pbs-notification-matcher.ts
|
|
3786
3848
|
import { Resource as Resource20 } from "alchemy";
|
|
3787
3849
|
import * as Provider20 from "alchemy/Provider";
|
|
3788
|
-
import * as
|
|
3850
|
+
import * as Effect47 from "effect/Effect";
|
|
3789
3851
|
var PbsNotificationMatcher = Resource20("Pbs.NotificationMatcher");
|
|
3790
|
-
var
|
|
3852
|
+
var handlers13 = pveHandlers({
|
|
3791
3853
|
attributes: (live, props) => matcherAttributes(live, props.name),
|
|
3792
3854
|
collection: () => "config/notifications/matchers",
|
|
3793
3855
|
createForm: matcherCreateForm,
|
|
@@ -3799,15 +3861,15 @@ var handlers14 = pveHandlers({
|
|
|
3799
3861
|
path: (props) => `config/notifications/matchers/${props.name}`,
|
|
3800
3862
|
updateForm: matcherUpdateForm
|
|
3801
3863
|
});
|
|
3802
|
-
var PbsNotificationMatcherProvider = () => Provider20.effect(PbsNotificationMatcher,
|
|
3864
|
+
var PbsNotificationMatcherProvider = () => Provider20.effect(PbsNotificationMatcher, Effect47.succeed(PbsNotificationMatcher.Provider.of(handlers13)));
|
|
3803
3865
|
// src/proxmox/pbs-notification-target.ts
|
|
3804
3866
|
import { Resource as Resource21 } from "alchemy";
|
|
3805
3867
|
import * as Provider21 from "alchemy/Provider";
|
|
3806
|
-
import * as
|
|
3868
|
+
import * as Effect49 from "effect/Effect";
|
|
3807
3869
|
|
|
3808
3870
|
// src/proxmox/pbs-notification-target-lifecycle.ts
|
|
3809
|
-
import { isResolved as
|
|
3810
|
-
import * as
|
|
3871
|
+
import { isResolved as isResolved12 } from "alchemy/Diff";
|
|
3872
|
+
import * as Effect48 from "effect/Effect";
|
|
3811
3873
|
|
|
3812
3874
|
// src/proxmox/pbs-notification-target-endpoint.ts
|
|
3813
3875
|
var ENDPOINTS2 = {
|
|
@@ -4084,12 +4146,12 @@ var targetForm = (props, groups, carry, mode) => {
|
|
|
4084
4146
|
|
|
4085
4147
|
// src/proxmox/pbs-notification-target-lifecycle.ts
|
|
4086
4148
|
var path = (props) => `config/notifications/endpoints/${props.type}/${props.name}`;
|
|
4087
|
-
var readLive2 = (props) => pve(props.target, "read", "GET", path(props)).pipe(
|
|
4149
|
+
var readLive2 = (props) => pve(props.target, "read", "GET", path(props)).pipe(Effect48.map((data) => data == null ? undefined : targetAttributes(data, props)), Effect48.orElseSucceed(() => {
|
|
4088
4150
|
return;
|
|
4089
4151
|
}));
|
|
4090
4152
|
var refuse2 = (props) => {
|
|
4091
4153
|
const reasons = refusals(props);
|
|
4092
|
-
return reasons.length === 0 ?
|
|
4154
|
+
return reasons.length === 0 ? Effect48.void : Effect48.die(new Error(`${path(props)}: ${reasons.join("; ")}.`));
|
|
4093
4155
|
};
|
|
4094
4156
|
var toCarry = (live, props, groups, sealed) => {
|
|
4095
4157
|
const header = headerState(live, props, groups) === "stale";
|
|
@@ -4101,17 +4163,17 @@ var requireValues = (props, groups, carry) => {
|
|
|
4101
4163
|
...carry.header ? groups.header.missing : [],
|
|
4102
4164
|
...carry.sealed ? groups.sealed.missing : []
|
|
4103
4165
|
];
|
|
4104
|
-
return missing.length === 0 ?
|
|
4166
|
+
return missing.length === 0 ? Effect48.void : Effect48.die(new Error(`${path(props)}: this write must send write-only values, and ${missing.join(", ")} ` + "is unset or empty in the deploying environment. Export it and deploy again."));
|
|
4105
4167
|
};
|
|
4106
|
-
var
|
|
4107
|
-
list: () =>
|
|
4108
|
-
read: ({ olds, output }) => (output === undefined ? refuse2(olds) :
|
|
4168
|
+
var handlers14 = {
|
|
4169
|
+
list: () => Effect48.succeed([]),
|
|
4170
|
+
read: ({ olds, output }) => (output === undefined ? refuse2(olds) : Effect48.void).pipe(Effect48.andThen(readLive2(olds)), Effect48.map((live) => live === undefined ? undefined : { ...live, sealed: output?.sealed ?? "" })),
|
|
4109
4171
|
diff: ({
|
|
4110
4172
|
news,
|
|
4111
4173
|
olds,
|
|
4112
4174
|
output
|
|
4113
|
-
}) =>
|
|
4114
|
-
if (output === undefined || !
|
|
4175
|
+
}) => Effect48.gen(function* () {
|
|
4176
|
+
if (output === undefined || !isResolved12(news))
|
|
4115
4177
|
return;
|
|
4116
4178
|
if (olds !== undefined && (olds.type !== news.type || olds.name !== news.name)) {
|
|
4117
4179
|
return { action: "replace", deleteFirst: olds.name === news.name };
|
|
@@ -4122,7 +4184,7 @@ var handlers15 = {
|
|
|
4122
4184
|
return { action: "update" };
|
|
4123
4185
|
return toCarry(live, news, resolveGroups(news), output.sealed) === undefined ? { action: "noop" } : { action: "update" };
|
|
4124
4186
|
}),
|
|
4125
|
-
reconcile: ({ news, output }) =>
|
|
4187
|
+
reconcile: ({ news, output }) => Effect48.gen(function* () {
|
|
4126
4188
|
yield* refuse2(news);
|
|
4127
4189
|
const groups = resolveGroups(news);
|
|
4128
4190
|
const live = yield* readLive2(news);
|
|
@@ -4148,7 +4210,7 @@ var handlers15 = {
|
|
|
4148
4210
|
}
|
|
4149
4211
|
const after = yield* readLive2(news);
|
|
4150
4212
|
if (after === undefined) {
|
|
4151
|
-
return yield*
|
|
4213
|
+
return yield* Effect48.die(new Error(`${path(news)}: the write returned no error but the target is still absent.`));
|
|
4152
4214
|
}
|
|
4153
4215
|
return { ...after, sealed };
|
|
4154
4216
|
}),
|
|
@@ -4157,11 +4219,11 @@ var handlers15 = {
|
|
|
4157
4219
|
|
|
4158
4220
|
// src/proxmox/pbs-notification-target.ts
|
|
4159
4221
|
var PbsNotificationTarget = Resource21("Pbs.NotificationTarget");
|
|
4160
|
-
var PbsNotificationTargetProvider = () => Provider21.effect(PbsNotificationTarget,
|
|
4222
|
+
var PbsNotificationTargetProvider = () => Provider21.effect(PbsNotificationTarget, Effect49.succeed(PbsNotificationTarget.Provider.of(handlers14)));
|
|
4161
4223
|
// src/proxmox/pbs-prune-job.ts
|
|
4162
4224
|
import { Resource as Resource22 } from "alchemy";
|
|
4163
4225
|
import * as Provider22 from "alchemy/Provider";
|
|
4164
|
-
import * as
|
|
4226
|
+
import * as Effect50 from "effect/Effect";
|
|
4165
4227
|
|
|
4166
4228
|
// src/proxmox/pbs-prune-job-form.ts
|
|
4167
4229
|
var KEEP_KEYS = [
|
|
@@ -4207,11 +4269,11 @@ var shape5 = (props) => ({
|
|
|
4207
4269
|
schedule: props.schedule,
|
|
4208
4270
|
store: props.store
|
|
4209
4271
|
});
|
|
4210
|
-
var
|
|
4272
|
+
var createBody3 = (props) => {
|
|
4211
4273
|
requireKeeps(props);
|
|
4212
4274
|
return { ...shape5(props), id: props.id };
|
|
4213
4275
|
};
|
|
4214
|
-
var
|
|
4276
|
+
var updateBody2 = (props) => {
|
|
4215
4277
|
requireKeeps(props);
|
|
4216
4278
|
return shape5(props);
|
|
4217
4279
|
};
|
|
@@ -4219,7 +4281,7 @@ var updateBody3 = (props) => {
|
|
|
4219
4281
|
// src/proxmox/pbs-prune-job.ts
|
|
4220
4282
|
var PbsPruneJob = Resource22("Pbs.PruneJob");
|
|
4221
4283
|
var same6 = (declared2, live) => declared2 === undefined || declared2 === live;
|
|
4222
|
-
var
|
|
4284
|
+
var handlers15 = pveHandlers({
|
|
4223
4285
|
attributes: (live, props) => ({
|
|
4224
4286
|
comment: text(live["comment"], ""),
|
|
4225
4287
|
disable: bool(live["disable"], false),
|
|
@@ -4231,17 +4293,17 @@ var handlers16 = pveHandlers({
|
|
|
4231
4293
|
store: text(live["store"], props.store)
|
|
4232
4294
|
}),
|
|
4233
4295
|
collection: () => "config/prune",
|
|
4234
|
-
createForm:
|
|
4296
|
+
createForm: createBody3,
|
|
4235
4297
|
endpoint: { create: "pbs:POST /config/prune", update: "pbs:PUT /config/prune/{id}" },
|
|
4236
4298
|
matches: (attributes2, props) => attributes2.schedule === props.schedule && attributes2.store === props.store && same6(props.ns, attributes2.ns) && same6(props["max-depth"], attributes2["max-depth"]) && same6(props.disable, attributes2.disable) && same6(props.comment, attributes2.comment) && keepsMatch(attributes2, props),
|
|
4237
4299
|
path: (props) => `config/prune/${props.id}`,
|
|
4238
|
-
updateForm:
|
|
4300
|
+
updateForm: updateBody2
|
|
4239
4301
|
});
|
|
4240
|
-
var PbsPruneJobProvider = () => Provider22.effect(PbsPruneJob,
|
|
4302
|
+
var PbsPruneJobProvider = () => Provider22.effect(PbsPruneJob, Effect50.succeed(PbsPruneJob.Provider.of(handlers15)));
|
|
4241
4303
|
// src/proxmox/pbs-sync-job.ts
|
|
4242
4304
|
import { Resource as Resource23 } from "alchemy";
|
|
4243
4305
|
import * as Provider23 from "alchemy/Provider";
|
|
4244
|
-
import * as
|
|
4306
|
+
import * as Effect51 from "effect/Effect";
|
|
4245
4307
|
|
|
4246
4308
|
// src/proxmox/pbs-sync-job-form.ts
|
|
4247
4309
|
var UNSET4 = -1;
|
|
@@ -4283,13 +4345,13 @@ var shape6 = (props) => ({
|
|
|
4283
4345
|
...props["verified-only"] === undefined ? {} : { "verified-only": props["verified-only"] ? "1" : "0" },
|
|
4284
4346
|
...props["transfer-last"] === undefined ? {} : { "transfer-last": String(props["transfer-last"]) }
|
|
4285
4347
|
});
|
|
4286
|
-
var
|
|
4348
|
+
var createBody4 = (props) => ({
|
|
4287
4349
|
...shape6(props),
|
|
4288
4350
|
id: props.id,
|
|
4289
4351
|
...props["sync-direction"] === undefined ? {} : { "sync-direction": props["sync-direction"] }
|
|
4290
4352
|
});
|
|
4291
|
-
var
|
|
4292
|
-
var
|
|
4353
|
+
var updateBody3 = (props) => shape6(props);
|
|
4354
|
+
var handlers16 = pveHandlers({
|
|
4293
4355
|
attributes: (live, props) => ({
|
|
4294
4356
|
comment: text(live["comment"], ""),
|
|
4295
4357
|
"group-filter": filters(live["group-filter"]),
|
|
@@ -4309,20 +4371,20 @@ var handlers17 = pveHandlers({
|
|
|
4309
4371
|
"transfer-last": int(live["transfer-last"], UNSET4)
|
|
4310
4372
|
}),
|
|
4311
4373
|
collection: () => "config/sync",
|
|
4312
|
-
createForm:
|
|
4374
|
+
createForm: createBody4,
|
|
4313
4375
|
endpoint: { create: "pbs:POST /config/sync", update: "pbs:PUT /config/sync/{id}" },
|
|
4314
4376
|
matches: (attributes2, props) => attributes2["remove-vanished"] === (props["remove-vanished"] === true) && attributes2.store === props.store && attributes2["remote-store"] === props["remote-store"] && (props.remote === undefined || attributes2.remote === props.remote) && (props.ns === undefined || attributes2.ns === props.ns) && (props["remote-ns"] === undefined || attributes2["remote-ns"] === props["remote-ns"]) && (props.schedule === undefined || attributes2.schedule === props.schedule) && (props.comment === undefined || attributes2.comment === props.comment) && (props.owner === undefined || attributes2.owner === props.owner) && (props["verified-only"] === undefined || attributes2["verified-only"] === props["verified-only"]) && (props["rate-in"] === undefined || attributes2["rate-in"] === props["rate-in"]) && (props["max-depth"] === undefined || attributes2["max-depth"] === props["max-depth"]) && (props["transfer-last"] === undefined || attributes2["transfer-last"] === props["transfer-last"]),
|
|
4315
4377
|
path: (props) => `config/sync/${props.id}`,
|
|
4316
|
-
updateForm:
|
|
4378
|
+
updateForm: updateBody3
|
|
4317
4379
|
});
|
|
4318
4380
|
|
|
4319
4381
|
// src/proxmox/pbs-sync-job.ts
|
|
4320
4382
|
var PbsSyncJob = Resource23("Pbs.SyncJob");
|
|
4321
|
-
var PbsSyncJobProvider = () => Provider23.effect(PbsSyncJob,
|
|
4383
|
+
var PbsSyncJobProvider = () => Provider23.effect(PbsSyncJob, Effect51.succeed(PbsSyncJob.Provider.of(handlers16)));
|
|
4322
4384
|
// src/proxmox/pbs-verify-job.ts
|
|
4323
4385
|
import { Resource as Resource24 } from "alchemy";
|
|
4324
4386
|
import * as Provider24 from "alchemy/Provider";
|
|
4325
|
-
import * as
|
|
4387
|
+
import * as Effect52 from "effect/Effect";
|
|
4326
4388
|
|
|
4327
4389
|
// src/proxmox/pbs-verify-job-form.ts
|
|
4328
4390
|
var rechecks = (ignoreVerified, outdatedAfter) => {
|
|
@@ -4344,7 +4406,7 @@ var shape7 = (props) => ({
|
|
|
4344
4406
|
|
|
4345
4407
|
// src/proxmox/pbs-verify-job.ts
|
|
4346
4408
|
var PbsVerifyJob = Resource24("Pbs.VerifyJob");
|
|
4347
|
-
var
|
|
4409
|
+
var handlers17 = pveHandlers({
|
|
4348
4410
|
attributes: (live, props) => {
|
|
4349
4411
|
const ignoreVerified = bool(live["ignore-verified"], true);
|
|
4350
4412
|
const outdatedAfter = int(live["outdated-after"], -1);
|
|
@@ -4367,11 +4429,11 @@ var handlers18 = pveHandlers({
|
|
|
4367
4429
|
path: (props) => `config/verify/${props.id}`,
|
|
4368
4430
|
updateForm: shape7
|
|
4369
4431
|
});
|
|
4370
|
-
var PbsVerifyJobProvider = () => Provider24.effect(PbsVerifyJob,
|
|
4432
|
+
var PbsVerifyJobProvider = () => Provider24.effect(PbsVerifyJob, Effect52.succeed(PbsVerifyJob.Provider.of(handlers17)));
|
|
4371
4433
|
// src/proxmox/pool.ts
|
|
4372
4434
|
import { Resource as Resource25 } from "alchemy";
|
|
4373
4435
|
import * as Provider25 from "alchemy/Provider";
|
|
4374
|
-
import * as
|
|
4436
|
+
import * as Effect53 from "effect/Effect";
|
|
4375
4437
|
var ProxmoxPool = Resource25("Proxmox.Pool");
|
|
4376
4438
|
var poolCreateForm = (props) => ({
|
|
4377
4439
|
comment: props.comment ?? "",
|
|
@@ -4380,7 +4442,7 @@ var poolCreateForm = (props) => ({
|
|
|
4380
4442
|
var poolUpdateForm = (props) => ({
|
|
4381
4443
|
comment: props.comment ?? ""
|
|
4382
4444
|
});
|
|
4383
|
-
var
|
|
4445
|
+
var handlers18 = pveHandlers({
|
|
4384
4446
|
attributes: (live, props) => {
|
|
4385
4447
|
const row = live;
|
|
4386
4448
|
return {
|
|
@@ -4396,7 +4458,7 @@ var handlers19 = pveHandlers({
|
|
|
4396
4458
|
path: (props) => `pools/${props.poolid}`,
|
|
4397
4459
|
updateForm: poolUpdateForm
|
|
4398
4460
|
});
|
|
4399
|
-
var ProxmoxPoolProvider = () => Provider25.effect(ProxmoxPool,
|
|
4461
|
+
var ProxmoxPoolProvider = () => Provider25.effect(ProxmoxPool, Effect53.succeed(ProxmoxPool.Provider.of(handlers18)));
|
|
4400
4462
|
// src/proxmox/provision-baseline.ts
|
|
4401
4463
|
var PROVISION_PRIVILEGES = Object.freeze([
|
|
4402
4464
|
"Datastore.Allocate",
|
|
@@ -4589,53 +4651,53 @@ echo 'provision baseline: done. Next: point the OpenBao proxmox mount at these u
|
|
|
4589
4651
|
// src/proxmox/provision-declare.ts
|
|
4590
4652
|
import { adopt } from "alchemy/AdoptPolicy";
|
|
4591
4653
|
import * as RemovalPolicy from "alchemy/RemovalPolicy";
|
|
4592
|
-
import * as
|
|
4654
|
+
import * as Effect57 from "effect/Effect";
|
|
4593
4655
|
|
|
4594
4656
|
// src/proxmox/role.ts
|
|
4595
4657
|
import { Resource as Resource26 } from "alchemy";
|
|
4596
|
-
import { isResolved as
|
|
4658
|
+
import { isResolved as isResolved13 } from "alchemy/Diff";
|
|
4597
4659
|
import * as Provider26 from "alchemy/Provider";
|
|
4598
4660
|
import * as access5 from "@distilled.cloud/proxmox/access";
|
|
4599
|
-
import * as
|
|
4661
|
+
import * as Effect54 from "effect/Effect";
|
|
4600
4662
|
|
|
4601
4663
|
// src/proxmox/role-wire.ts
|
|
4602
4664
|
var ROLE_CREATE = "pve:POST /access/roles";
|
|
4603
4665
|
var ROLE_UPDATE = "pve:PUT /access/roles/{roleid}";
|
|
4604
4666
|
var canonical2 = (privs) => [...new Set(privs.map((priv) => priv.trim()).filter((priv) => priv.length > 0))].sort();
|
|
4605
|
-
var
|
|
4667
|
+
var createForm7 = (props) => ({
|
|
4606
4668
|
privs: canonical2(props.privs).join(","),
|
|
4607
4669
|
roleid: props.roleid
|
|
4608
4670
|
});
|
|
4609
|
-
var
|
|
4671
|
+
var updateForm4 = (props) => ({
|
|
4610
4672
|
privs: canonical2(props.privs).join(","),
|
|
4611
4673
|
roleid: props.roleid
|
|
4612
4674
|
});
|
|
4613
4675
|
var find2 = (rows, roleid) => rows.find((row) => row.roleid === roleid);
|
|
4614
|
-
var
|
|
4676
|
+
var attributesOf6 = (row, props) => ({
|
|
4615
4677
|
privs: canonical2(row.privs === undefined ? [] : row.privs.split(",")),
|
|
4616
4678
|
roleid: props.roleid
|
|
4617
4679
|
});
|
|
4618
|
-
var
|
|
4680
|
+
var matches6 = (attributes2, props) => canonical2(attributes2.privs).join(",") === canonical2(props.privs).join(",");
|
|
4619
4681
|
|
|
4620
4682
|
// src/proxmox/role.ts
|
|
4621
4683
|
var ProxmoxRole = Resource26("Proxmox.Role");
|
|
4622
|
-
var readRole = (props) => readOrUnreadable(runPve(props.target, "read", false, access5.listAccessRoles({}))).pipe(
|
|
4684
|
+
var readRole = (props) => readOrUnreadable(runPve(props.target, "read", false, access5.listAccessRoles({}))).pipe(Effect54.map((rows) => {
|
|
4623
4685
|
if (rows === UNREADABLE)
|
|
4624
4686
|
return UNREADABLE;
|
|
4625
4687
|
const row = find2(rows, props.roleid);
|
|
4626
|
-
return row === undefined ? undefined :
|
|
4688
|
+
return row === undefined ? undefined : attributesOf6(row, props);
|
|
4627
4689
|
}));
|
|
4628
|
-
var
|
|
4629
|
-
var ProxmoxRoleProvider = () => Provider26.effect(ProxmoxRole,
|
|
4630
|
-
list: () =>
|
|
4631
|
-
read:
|
|
4632
|
-
return
|
|
4690
|
+
var dropUnreadable5 = (live) => live === UNREADABLE ? undefined : live;
|
|
4691
|
+
var ProxmoxRoleProvider = () => Provider26.effect(ProxmoxRole, Effect54.succeed(ProxmoxRole.Provider.of({
|
|
4692
|
+
list: () => Effect54.succeed([]),
|
|
4693
|
+
read: Effect54.fn(function* ({ olds }) {
|
|
4694
|
+
return dropUnreadable5(yield* readRole(olds));
|
|
4633
4695
|
}),
|
|
4634
|
-
diff:
|
|
4635
|
-
if (!
|
|
4696
|
+
diff: Effect54.fn(function* ({ news, output }) {
|
|
4697
|
+
if (!isResolved13(news))
|
|
4636
4698
|
return;
|
|
4637
|
-
yield* guardWrite2(ROLE_CREATE,
|
|
4638
|
-
yield* guardWrite2(ROLE_UPDATE,
|
|
4699
|
+
yield* guardWrite2(ROLE_CREATE, createForm7(news), output === undefined);
|
|
4700
|
+
yield* guardWrite2(ROLE_UPDATE, updateForm4(news), false);
|
|
4639
4701
|
if (output === undefined)
|
|
4640
4702
|
return;
|
|
4641
4703
|
const live = yield* readRole(news);
|
|
@@ -4644,41 +4706,41 @@ var ProxmoxRoleProvider = () => Provider26.effect(ProxmoxRole, Effect53.succeed(
|
|
|
4644
4706
|
return { action: "noop" };
|
|
4645
4707
|
}
|
|
4646
4708
|
if (live === undefined) {
|
|
4647
|
-
yield* guardWrite2(ROLE_CREATE,
|
|
4709
|
+
yield* guardWrite2(ROLE_CREATE, createForm7(news), true);
|
|
4648
4710
|
return { action: "update" };
|
|
4649
4711
|
}
|
|
4650
|
-
return
|
|
4712
|
+
return matches6(live, news) ? { action: "noop" } : { action: "update" };
|
|
4651
4713
|
}),
|
|
4652
|
-
reconcile:
|
|
4653
|
-
const before =
|
|
4654
|
-
yield* guardWrite2(ROLE_CREATE,
|
|
4655
|
-
yield* guardWrite2(ROLE_UPDATE,
|
|
4714
|
+
reconcile: Effect54.fn(function* ({ news }) {
|
|
4715
|
+
const before = dropUnreadable5(yield* readRole(news));
|
|
4716
|
+
yield* guardWrite2(ROLE_CREATE, createForm7(news), before === undefined);
|
|
4717
|
+
yield* guardWrite2(ROLE_UPDATE, updateForm4(news), false);
|
|
4656
4718
|
if (before === undefined) {
|
|
4657
|
-
yield* runPve(news.target, "provision", true, access5.createAccessRole(
|
|
4658
|
-
} else if (!
|
|
4659
|
-
yield* runPve(news.target, "provision", true, access5.putAccessRole(
|
|
4719
|
+
yield* runPve(news.target, "provision", true, access5.createAccessRole(createForm7(news)));
|
|
4720
|
+
} else if (!matches6(before, news)) {
|
|
4721
|
+
yield* runPve(news.target, "provision", true, access5.putAccessRole(updateForm4(news)));
|
|
4660
4722
|
}
|
|
4661
|
-
const after =
|
|
4723
|
+
const after = dropUnreadable5(yield* readRole(news));
|
|
4662
4724
|
if (after === undefined) {
|
|
4663
|
-
return yield*
|
|
4725
|
+
return yield* Effect54.die(new Error(`access/roles/${news.roleid}: the write returned no error but the role is ` + 'still absent. PVE wraps every answer in {"data":...} and can report success ' + "on a call that did nothing -- read back rather than trusting the status code."));
|
|
4664
4726
|
}
|
|
4665
4727
|
return after;
|
|
4666
4728
|
}),
|
|
4667
|
-
delete:
|
|
4729
|
+
delete: Effect54.fn(function* ({ olds }) {
|
|
4668
4730
|
yield* runPve(olds.target, "provision", true, access5.deleteAccessRole({ roleid: olds.roleid }));
|
|
4669
4731
|
})
|
|
4670
4732
|
})));
|
|
4671
4733
|
|
|
4672
4734
|
// src/proxmox/user.ts
|
|
4673
4735
|
import { Resource as Resource27 } from "alchemy";
|
|
4674
|
-
import { isResolved as
|
|
4736
|
+
import { isResolved as isResolved14 } from "alchemy/Diff";
|
|
4675
4737
|
import * as Provider27 from "alchemy/Provider";
|
|
4676
4738
|
import * as access7 from "@distilled.cloud/proxmox/access";
|
|
4677
|
-
import * as
|
|
4739
|
+
import * as Effect56 from "effect/Effect";
|
|
4678
4740
|
|
|
4679
4741
|
// src/proxmox/user-wire.ts
|
|
4680
4742
|
import * as access6 from "@distilled.cloud/proxmox/access";
|
|
4681
|
-
import * as
|
|
4743
|
+
import * as Effect55 from "effect/Effect";
|
|
4682
4744
|
var USER_CREATE = "pve:POST /access/users";
|
|
4683
4745
|
var USER_UPDATE = "pve:PUT /access/users/{userid}";
|
|
4684
4746
|
var int2 = (value) => {
|
|
@@ -4700,15 +4762,15 @@ var shape8 = (props) => ({
|
|
|
4700
4762
|
groups: groupSet(props.groups).join(","),
|
|
4701
4763
|
lastname: props.lastname ?? ""
|
|
4702
4764
|
});
|
|
4703
|
-
var
|
|
4765
|
+
var createForm8 = (props) => ({
|
|
4704
4766
|
...shape8(props),
|
|
4705
4767
|
userid: props.userid
|
|
4706
4768
|
});
|
|
4707
|
-
var
|
|
4769
|
+
var updateForm5 = (props) => ({
|
|
4708
4770
|
...shape8(props),
|
|
4709
4771
|
userid: props.userid
|
|
4710
4772
|
});
|
|
4711
|
-
var
|
|
4773
|
+
var attributesOf7 = (live, props) => ({
|
|
4712
4774
|
comment: text(live.comment),
|
|
4713
4775
|
email: text(live.email),
|
|
4714
4776
|
enable: bool(live.enable, true),
|
|
@@ -4719,25 +4781,25 @@ var attributesOf6 = (live, props) => ({
|
|
|
4719
4781
|
tokens: tokenNames(live.tokens),
|
|
4720
4782
|
userid: props.userid
|
|
4721
4783
|
});
|
|
4722
|
-
var
|
|
4723
|
-
var readUserOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false, access6.getAccessUser({ userid: props.userid }))).pipe(
|
|
4724
|
-
var readUser = (props) => readUserOrFail(props).pipe(
|
|
4784
|
+
var matches7 = (attributes2, props) => attributes2.comment === (props.comment ?? "") && attributes2.email === (props.email ?? "") && attributes2.enable === (props.enable !== false) && attributes2.expire === (props.expire ?? 0) && attributes2.firstname === (props.firstname ?? "") && attributes2.lastname === (props.lastname ?? "") && attributes2.groups.join(",") === groupSet(props.groups).join(",");
|
|
4785
|
+
var readUserOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false, access6.getAccessUser({ userid: props.userid }))).pipe(Effect55.map((live) => live === UNREADABLE ? UNREADABLE : attributesOf7(live, props)));
|
|
4786
|
+
var readUser = (props) => readUserOrFail(props).pipe(Effect55.orElseSucceed(() => {
|
|
4725
4787
|
return;
|
|
4726
4788
|
}));
|
|
4727
|
-
var
|
|
4789
|
+
var dropUnreadable6 = (live) => live === UNREADABLE ? undefined : live;
|
|
4728
4790
|
|
|
4729
4791
|
// src/proxmox/user.ts
|
|
4730
4792
|
var ProxmoxUser = Resource27("Proxmox.User");
|
|
4731
|
-
var ProxmoxUserProvider = () => Provider27.effect(ProxmoxUser,
|
|
4732
|
-
list: () =>
|
|
4733
|
-
read:
|
|
4734
|
-
return
|
|
4793
|
+
var ProxmoxUserProvider = () => Provider27.effect(ProxmoxUser, Effect56.succeed(ProxmoxUser.Provider.of({
|
|
4794
|
+
list: () => Effect56.succeed([]),
|
|
4795
|
+
read: Effect56.fn(function* ({ olds, output }) {
|
|
4796
|
+
return dropUnreadable6(yield* output === undefined ? readUser(olds) : readUserOrFail(olds));
|
|
4735
4797
|
}),
|
|
4736
|
-
diff:
|
|
4737
|
-
if (!
|
|
4798
|
+
diff: Effect56.fn(function* ({ news, output }) {
|
|
4799
|
+
if (!isResolved14(news))
|
|
4738
4800
|
return;
|
|
4739
|
-
yield* guardWrite2(USER_CREATE,
|
|
4740
|
-
yield* guardWrite2(USER_UPDATE,
|
|
4801
|
+
yield* guardWrite2(USER_CREATE, createForm8(news), output === undefined);
|
|
4802
|
+
yield* guardWrite2(USER_UPDATE, updateForm5(news), false);
|
|
4741
4803
|
if (output === undefined)
|
|
4742
4804
|
return;
|
|
4743
4805
|
const live = yield* readUserOrFail(news);
|
|
@@ -4746,34 +4808,34 @@ var ProxmoxUserProvider = () => Provider27.effect(ProxmoxUser, Effect55.succeed(
|
|
|
4746
4808
|
return { action: "noop" };
|
|
4747
4809
|
}
|
|
4748
4810
|
if (live === undefined) {
|
|
4749
|
-
yield* guardWrite2(USER_CREATE,
|
|
4811
|
+
yield* guardWrite2(USER_CREATE, createForm8(news), true);
|
|
4750
4812
|
return { action: "update" };
|
|
4751
4813
|
}
|
|
4752
|
-
return
|
|
4814
|
+
return matches7(live, news) ? { action: "noop" } : { action: "update" };
|
|
4753
4815
|
}),
|
|
4754
|
-
reconcile:
|
|
4755
|
-
const before =
|
|
4756
|
-
yield* guardWrite2(USER_CREATE,
|
|
4757
|
-
yield* guardWrite2(USER_UPDATE,
|
|
4816
|
+
reconcile: Effect56.fn(function* ({ news }) {
|
|
4817
|
+
const before = dropUnreadable6(yield* readUser(news));
|
|
4818
|
+
yield* guardWrite2(USER_CREATE, createForm8(news), before === undefined);
|
|
4819
|
+
yield* guardWrite2(USER_UPDATE, updateForm5(news), false);
|
|
4758
4820
|
if (before === undefined) {
|
|
4759
|
-
yield* runPve(news.target, "provision", true, access7.createAccessUser(
|
|
4760
|
-
} else if (!
|
|
4761
|
-
yield* runPve(news.target, "provision", true, access7.putAccessUser(
|
|
4821
|
+
yield* runPve(news.target, "provision", true, access7.createAccessUser(createForm8(news)));
|
|
4822
|
+
} else if (!matches7(before, news)) {
|
|
4823
|
+
yield* runPve(news.target, "provision", true, access7.putAccessUser(updateForm5(news)));
|
|
4762
4824
|
}
|
|
4763
|
-
const after =
|
|
4825
|
+
const after = dropUnreadable6(yield* readUser(news));
|
|
4764
4826
|
if (after === undefined) {
|
|
4765
|
-
return yield*
|
|
4827
|
+
return yield* Effect56.die(new Error(`access/users/${news.userid}: the write returned no error but the account is ` + 'still absent. PVE wraps every answer in {"data":...} and can report success ' + "on a call that did nothing -- read back rather than trusting the status code."));
|
|
4766
4828
|
}
|
|
4767
4829
|
return after;
|
|
4768
4830
|
}),
|
|
4769
|
-
delete:
|
|
4831
|
+
delete: Effect56.fn(function* ({ olds }) {
|
|
4770
4832
|
yield* runPve(olds.target, "provision", true, access7.deleteAccessUser({ userid: olds.userid }));
|
|
4771
4833
|
})
|
|
4772
4834
|
})));
|
|
4773
4835
|
|
|
4774
4836
|
// src/proxmox/provision-declare.ts
|
|
4775
|
-
var declareProvisionBaseline = (id, target, names2 = {}, options = {}) =>
|
|
4776
|
-
const baseline = yield*
|
|
4837
|
+
var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect57.gen(function* () {
|
|
4838
|
+
const baseline = yield* Effect57.try({
|
|
4777
4839
|
catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)),
|
|
4778
4840
|
try: () => provisionBaseline(names2)
|
|
4779
4841
|
});
|
|
@@ -4787,13 +4849,13 @@ var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect
|
|
|
4787
4849
|
target
|
|
4788
4850
|
}));
|
|
4789
4851
|
const group = yield* owned(ProxmoxGroup(`${id}-mint-group`, { ...baseline.group, target }));
|
|
4790
|
-
const users = yield*
|
|
4852
|
+
const users = yield* Effect57.all(baseline.users.map((user) => owned(ProxmoxUser(`${id}-${user.lane}-user`, {
|
|
4791
4853
|
comment: user.comment,
|
|
4792
4854
|
groups: [...user.groups],
|
|
4793
4855
|
target,
|
|
4794
4856
|
userid: user.userid
|
|
4795
4857
|
}))));
|
|
4796
|
-
const grants = yield*
|
|
4858
|
+
const grants = yield* Effect57.all(baseline.grants.map((grant) => owned(ProxmoxAcl(`${id}-${grant.lane}-grant`, {
|
|
4797
4859
|
path: "/",
|
|
4798
4860
|
propagate: true,
|
|
4799
4861
|
roleid: grant.roleid,
|
|
@@ -4806,9 +4868,9 @@ var declareProvisionBaseline = (id, target, names2 = {}, options = {}) => Effect
|
|
|
4806
4868
|
// src/proxmox/qemu.ts
|
|
4807
4869
|
import { Resource as Resource28 } from "alchemy";
|
|
4808
4870
|
import * as Provider28 from "alchemy/Provider";
|
|
4809
|
-
import * as
|
|
4871
|
+
import * as Effect58 from "effect/Effect";
|
|
4810
4872
|
var ProxmoxVm = Resource28("Proxmox.Vm");
|
|
4811
|
-
var
|
|
4873
|
+
var createForm9 = (props) => ({ ...shape9(props), vmid: String(props.vmid) });
|
|
4812
4874
|
var shape9 = (props) => ({
|
|
4813
4875
|
cores: String(props.cores ?? 1),
|
|
4814
4876
|
memory: String(props.memory ?? 512),
|
|
@@ -4817,7 +4879,7 @@ var shape9 = (props) => ({
|
|
|
4817
4879
|
sockets: String(props.sockets ?? 1),
|
|
4818
4880
|
...props.net0 === undefined ? {} : { net0: props.net0 }
|
|
4819
4881
|
});
|
|
4820
|
-
var
|
|
4882
|
+
var handlers19 = pveHandlers({
|
|
4821
4883
|
attributes: (live, props) => ({
|
|
4822
4884
|
cores: num(live["cores"], 1),
|
|
4823
4885
|
memory: num(live["memory"], 512),
|
|
@@ -4828,7 +4890,7 @@ var handlers20 = pveHandlers({
|
|
|
4828
4890
|
vmid: props.vmid
|
|
4829
4891
|
}),
|
|
4830
4892
|
collection: (props) => `nodes/${props.node}/qemu`,
|
|
4831
|
-
createForm:
|
|
4893
|
+
createForm: createForm9,
|
|
4832
4894
|
endpoint: {
|
|
4833
4895
|
create: "pve:POST /nodes/{node}/qemu",
|
|
4834
4896
|
update: "pve:PUT /nodes/{node}/qemu/{vmid}/config"
|
|
@@ -4837,11 +4899,11 @@ var handlers20 = pveHandlers({
|
|
|
4837
4899
|
path: (props) => `nodes/${props.node}/qemu/${String(props.vmid)}/config`,
|
|
4838
4900
|
updateForm: shape9
|
|
4839
4901
|
});
|
|
4840
|
-
var ProxmoxVmProvider = () => Provider28.effect(ProxmoxVm,
|
|
4902
|
+
var ProxmoxVmProvider = () => Provider28.effect(ProxmoxVm, Effect58.succeed(ProxmoxVm.Provider.of(handlers19)));
|
|
4841
4903
|
// src/proxmox/replication-job.ts
|
|
4842
4904
|
import { Resource as Resource29 } from "alchemy";
|
|
4843
4905
|
import * as Provider29 from "alchemy/Provider";
|
|
4844
|
-
import * as
|
|
4906
|
+
import * as Effect59 from "effect/Effect";
|
|
4845
4907
|
|
|
4846
4908
|
// src/proxmox/replication-job-form.ts
|
|
4847
4909
|
var DEFAULT_SCHEDULE = "*/15";
|
|
@@ -4852,13 +4914,13 @@ var shape10 = (props) => ({
|
|
|
4852
4914
|
schedule: props.schedule ?? DEFAULT_SCHEDULE,
|
|
4853
4915
|
...props.rate === undefined ? {} : { rate: String(props.rate) }
|
|
4854
4916
|
});
|
|
4855
|
-
var
|
|
4917
|
+
var createBody5 = (props) => ({
|
|
4856
4918
|
...shape10(props),
|
|
4857
4919
|
id: jobId(props),
|
|
4858
4920
|
target: props.targetNode,
|
|
4859
4921
|
type: "local"
|
|
4860
4922
|
});
|
|
4861
|
-
var
|
|
4923
|
+
var updateBody4 = (props) => ({
|
|
4862
4924
|
...shape10(props),
|
|
4863
4925
|
delete: "remove_job"
|
|
4864
4926
|
});
|
|
@@ -4871,7 +4933,7 @@ var rateOf = (value) => {
|
|
|
4871
4933
|
const parsed = Number.parseFloat(text(value));
|
|
4872
4934
|
return Number.isFinite(parsed) ? parsed : 0;
|
|
4873
4935
|
};
|
|
4874
|
-
var
|
|
4936
|
+
var handlers20 = pveHandlers({
|
|
4875
4937
|
attributes: (live, props) => ({
|
|
4876
4938
|
comment: text(live["comment"], ""),
|
|
4877
4939
|
disable: bool(live["disable"], false),
|
|
@@ -4886,24 +4948,24 @@ var handlers21 = pveHandlers({
|
|
|
4886
4948
|
type: text(live["type"], "local")
|
|
4887
4949
|
}),
|
|
4888
4950
|
collection: () => "cluster/replication",
|
|
4889
|
-
createForm:
|
|
4951
|
+
createForm: createBody5,
|
|
4890
4952
|
endpoint: {
|
|
4891
4953
|
create: "pve:POST /cluster/replication",
|
|
4892
4954
|
update: "pve:PUT /cluster/replication/{id}"
|
|
4893
4955
|
},
|
|
4894
4956
|
matches: (attributes2, props) => attributes2.remove_job === "" && attributes2.schedule === (props.schedule ?? DEFAULT_SCHEDULE) && attributes2.disable === (props.disable === true) && attributes2.comment === (props.comment ?? "") && (props.rate === undefined || attributes2.rate === props.rate),
|
|
4895
4957
|
path: (props) => `cluster/replication/${jobId(props)}`,
|
|
4896
|
-
updateForm:
|
|
4958
|
+
updateForm: updateBody4
|
|
4897
4959
|
});
|
|
4898
|
-
var ProxmoxReplicationJobProvider = () => Provider29.effect(ProxmoxReplicationJob,
|
|
4960
|
+
var ProxmoxReplicationJobProvider = () => Provider29.effect(ProxmoxReplicationJob, Effect59.succeed(ProxmoxReplicationJob.Provider.of(handlers20)));
|
|
4899
4961
|
// src/proxmox/sdn-apply.ts
|
|
4900
4962
|
import { Resource as Resource30 } from "alchemy";
|
|
4901
|
-
import { isResolved as
|
|
4963
|
+
import { isResolved as isResolved15 } from "alchemy/Diff";
|
|
4902
4964
|
import * as Provider30 from "alchemy/Provider";
|
|
4903
|
-
import * as
|
|
4965
|
+
import * as Effect61 from "effect/Effect";
|
|
4904
4966
|
|
|
4905
4967
|
// src/proxmox/sdn-apply-read.ts
|
|
4906
|
-
import * as
|
|
4968
|
+
import * as Effect60 from "effect/Effect";
|
|
4907
4969
|
var MARKED = [
|
|
4908
4970
|
"cluster/sdn/zones",
|
|
4909
4971
|
"cluster/sdn/vnets",
|
|
@@ -4912,7 +4974,7 @@ var MARKED = [
|
|
|
4912
4974
|
"cluster/sdn/route-maps"
|
|
4913
4975
|
];
|
|
4914
4976
|
var subsystemAbsent = (error) => error instanceof PveError && error.status === 501;
|
|
4915
|
-
var markedPending = (target) =>
|
|
4977
|
+
var markedPending = (target) => Effect60.all(MARKED.map((collection2) => pve(target, "read", "GET", `${collection2}?pending=1`).pipe(Effect60.map((rows) => (rows ?? []).filter((row) => row.state !== undefined).length), Effect60.catchIf(subsystemAbsent, () => Effect60.succeed(0)))), { concurrency: "unbounded" }).pipe(Effect60.map((counts) => counts.reduce((total, count2) => total + count2, 0)));
|
|
4916
4978
|
var fabricStaged = (staged, running) => {
|
|
4917
4979
|
if (staged === undefined && running === undefined)
|
|
4918
4980
|
return 0;
|
|
@@ -4920,9 +4982,9 @@ var fabricStaged = (staged, running) => {
|
|
|
4920
4982
|
return "inconsistent";
|
|
4921
4983
|
return staged === running ? 0 : 1;
|
|
4922
4984
|
};
|
|
4923
|
-
var fabricPending = (target) =>
|
|
4985
|
+
var fabricPending = (target) => Effect60.all(["pending", "running"].map((view) => pve(target, "read", "GET", `cluster/sdn/fabrics/all?${view}=1`).pipe(Effect60.map(canonical3), Effect60.catchIf(subsystemAbsent, () => Effect60.succeed(undefined)))), { concurrency: "unbounded" }).pipe(Effect60.flatMap(([staged, running]) => {
|
|
4924
4986
|
const verdict = fabricStaged(staged, running);
|
|
4925
|
-
return verdict === "inconsistent" ?
|
|
4987
|
+
return verdict === "inconsistent" ? Effect60.die(new Error("cluster/sdn/fabrics/all answered 501 for one of ?pending=1 and ?running=1 and not " + "the other. Refusing to read that as a staged fabric change.")) : Effect60.succeed(verdict);
|
|
4926
4988
|
}));
|
|
4927
4989
|
var canonical3 = (value) => JSON.stringify(sortDeep(value));
|
|
4928
4990
|
var sortDeep = (value) => {
|
|
@@ -4935,23 +4997,23 @@ var sortDeep = (value) => {
|
|
|
4935
4997
|
}
|
|
4936
4998
|
return value;
|
|
4937
4999
|
};
|
|
4938
|
-
var sdnPendingCount = (target) =>
|
|
5000
|
+
var sdnPendingCount = (target) => Effect60.all([markedPending(target), fabricPending(target)], { concurrency: "unbounded" }).pipe(Effect60.map(([marked, fabric]) => marked + fabric));
|
|
4939
5001
|
|
|
4940
5002
|
// src/proxmox/sdn-apply.ts
|
|
4941
5003
|
var ProxmoxSdnApply = Resource30("Proxmox.SdnApply");
|
|
4942
|
-
var read3 = (props) => sdnPendingCount(props.target).pipe(
|
|
4943
|
-
var ProxmoxSdnApplyProvider = () => Provider30.effect(ProxmoxSdnApply,
|
|
4944
|
-
list: () =>
|
|
4945
|
-
read:
|
|
5004
|
+
var read3 = (props) => sdnPendingCount(props.target).pipe(Effect61.map((pending) => ({ pending })));
|
|
5005
|
+
var ProxmoxSdnApplyProvider = () => Provider30.effect(ProxmoxSdnApply, Effect61.succeed(ProxmoxSdnApply.Provider.of({
|
|
5006
|
+
list: () => Effect61.succeed([]),
|
|
5007
|
+
read: Effect61.fn(function* ({ olds }) {
|
|
4946
5008
|
return yield* read3(olds);
|
|
4947
5009
|
}),
|
|
4948
|
-
diff:
|
|
4949
|
-
if (!
|
|
5010
|
+
diff: Effect61.fn(function* ({ news }) {
|
|
5011
|
+
if (!isResolved15(news))
|
|
4950
5012
|
return;
|
|
4951
5013
|
const { pending } = yield* read3(news);
|
|
4952
5014
|
return pending === 0 ? { action: "noop" } : { action: "update" };
|
|
4953
5015
|
}),
|
|
4954
|
-
reconcile:
|
|
5016
|
+
reconcile: Effect61.fn(function* ({ news }) {
|
|
4955
5017
|
const staged = yield* read3(news);
|
|
4956
5018
|
if (staged.pending === 0)
|
|
4957
5019
|
return staged;
|
|
@@ -4959,16 +5021,16 @@ var ProxmoxSdnApplyProvider = () => Provider30.effect(ProxmoxSdnApply, Effect60.
|
|
|
4959
5021
|
yield* pve(news.target, "provision", "PUT", "cluster/sdn");
|
|
4960
5022
|
const after = yield* read3(news);
|
|
4961
5023
|
if (after.pending !== 0) {
|
|
4962
|
-
return yield*
|
|
5024
|
+
return yield* Effect61.die(new Error(`PUT /cluster/sdn returned no error but ${String(after.pending)} SDN object(s) ` + "are still staged. The running config does not match the declared one -- check " + "`pvesh get /cluster/sdn/zones --pending 1` for the objects PVE refused."));
|
|
4963
5025
|
}
|
|
4964
5026
|
return after;
|
|
4965
5027
|
}),
|
|
4966
|
-
delete: () =>
|
|
5028
|
+
delete: () => Effect61.void
|
|
4967
5029
|
})));
|
|
4968
5030
|
// src/proxmox/sdn-subnet.ts
|
|
4969
5031
|
import { Resource as Resource31 } from "alchemy";
|
|
4970
5032
|
import * as Provider31 from "alchemy/Provider";
|
|
4971
|
-
import * as
|
|
5033
|
+
import * as Effect62 from "effect/Effect";
|
|
4972
5034
|
|
|
4973
5035
|
// src/proxmox/sdn-subnet-form.ts
|
|
4974
5036
|
var subnetId = (props) => `${props.zone}-${props.cidr.replace("/", "-")}`;
|
|
@@ -4987,19 +5049,19 @@ var body5 = (props) => ({
|
|
|
4987
5049
|
vnet: props.vnet,
|
|
4988
5050
|
...Object.fromEntries(Object.entries(optional3(props)).filter((entry) => entry[1] !== undefined))
|
|
4989
5051
|
});
|
|
4990
|
-
var
|
|
5052
|
+
var createForm10 = (props) => ({
|
|
4991
5053
|
...body5(props),
|
|
4992
5054
|
subnet: props.cidr,
|
|
4993
5055
|
type: "subnet"
|
|
4994
5056
|
});
|
|
4995
|
-
var
|
|
5057
|
+
var updateForm6 = (props) => {
|
|
4996
5058
|
const clear = Object.entries(optional3(props)).filter(([, value]) => value === undefined).map(([key]) => key);
|
|
4997
5059
|
return withClears(body5(props), clear);
|
|
4998
5060
|
};
|
|
4999
5061
|
|
|
5000
5062
|
// src/proxmox/sdn-subnet.ts
|
|
5001
5063
|
var ProxmoxSdnSubnet = Resource31("Proxmox.SdnSubnet");
|
|
5002
|
-
var
|
|
5064
|
+
var handlers21 = pveHandlers({
|
|
5003
5065
|
attributes: (live, props) => {
|
|
5004
5066
|
const liveVnet = text(live["vnet"]);
|
|
5005
5067
|
if (liveVnet !== "" && liveVnet !== props.vnet)
|
|
@@ -5019,20 +5081,20 @@ var handlers22 = pveHandlers({
|
|
|
5019
5081
|
};
|
|
5020
5082
|
},
|
|
5021
5083
|
collection: (props) => `cluster/sdn/vnets/${props.vnet}/subnets`,
|
|
5022
|
-
createForm:
|
|
5084
|
+
createForm: createForm10,
|
|
5023
5085
|
endpoint: {
|
|
5024
5086
|
create: "pve:POST /cluster/sdn/vnets/{vnet}/subnets",
|
|
5025
5087
|
update: "pve:PUT /cluster/sdn/vnets/{vnet}/subnets/{subnet}"
|
|
5026
5088
|
},
|
|
5027
5089
|
matches: (attributes2, props) => attributes2.gateway === (props.gateway ?? "") && attributes2.snat === (props.snat === true) && attributes2.dnszoneprefix === (props.dnszoneprefix ?? "") && attributes2.dhcpDnsServer === (props.dhcpDnsServer ?? "") && attributes2.dhcpRange === declaredRanges(props.dhcpRange),
|
|
5028
5090
|
path: (props) => `cluster/sdn/vnets/${props.vnet}/subnets/${subnetId(props)}`,
|
|
5029
|
-
updateForm:
|
|
5091
|
+
updateForm: updateForm6
|
|
5030
5092
|
});
|
|
5031
|
-
var ProxmoxSdnSubnetProvider = () => Provider31.effect(ProxmoxSdnSubnet,
|
|
5093
|
+
var ProxmoxSdnSubnetProvider = () => Provider31.effect(ProxmoxSdnSubnet, Effect62.succeed(ProxmoxSdnSubnet.Provider.of(handlers21)));
|
|
5032
5094
|
// src/proxmox/sdn-vnet.ts
|
|
5033
5095
|
import { Resource as Resource32 } from "alchemy";
|
|
5034
5096
|
import * as Provider32 from "alchemy/Provider";
|
|
5035
|
-
import * as
|
|
5097
|
+
import * as Effect63 from "effect/Effect";
|
|
5036
5098
|
var ProxmoxSdnVnet = Resource32("Proxmox.SdnVnet");
|
|
5037
5099
|
var tagOf = (value) => typeof value === "number" ? value : undefined;
|
|
5038
5100
|
var shape11 = (props) => {
|
|
@@ -5045,14 +5107,14 @@ var shape11 = (props) => {
|
|
|
5045
5107
|
...props.tag === undefined ? {} : { tag: String(props.tag) }
|
|
5046
5108
|
};
|
|
5047
5109
|
};
|
|
5048
|
-
var
|
|
5110
|
+
var updateForm7 = (props) => {
|
|
5049
5111
|
const unset2 = [
|
|
5050
5112
|
...(props.alias ?? "") === "" ? ["alias"] : [],
|
|
5051
5113
|
...props.tag === undefined ? ["tag"] : []
|
|
5052
5114
|
];
|
|
5053
5115
|
return withClears(shape11(props), unset2);
|
|
5054
5116
|
};
|
|
5055
|
-
var
|
|
5117
|
+
var handlers22 = pveHandlers({
|
|
5056
5118
|
readRole: "provision",
|
|
5057
5119
|
attributes: (live, props) => ({
|
|
5058
5120
|
alias: typeof live["alias"] === "string" ? live["alias"] : "",
|
|
@@ -5068,13 +5130,13 @@ var handlers23 = pveHandlers({
|
|
|
5068
5130
|
endpoint: { create: "pve:POST /cluster/sdn/vnets", update: "pve:PUT /cluster/sdn/vnets/{vnet}" },
|
|
5069
5131
|
matches: (attributes2, props) => attributes2.zone === props.zone && attributes2.alias === (props.alias ?? "") && attributes2.tag === props.tag && attributes2.vlanaware === (props.vlanaware === true) && attributes2.isolatePorts === (props.isolatePorts === true),
|
|
5070
5132
|
path: (props) => `cluster/sdn/vnets/${props.vnet}`,
|
|
5071
|
-
updateForm:
|
|
5133
|
+
updateForm: updateForm7
|
|
5072
5134
|
});
|
|
5073
|
-
var ProxmoxSdnVnetProvider = () => Provider32.effect(ProxmoxSdnVnet,
|
|
5135
|
+
var ProxmoxSdnVnetProvider = () => Provider32.effect(ProxmoxSdnVnet, Effect63.succeed(ProxmoxSdnVnet.Provider.of(handlers22)));
|
|
5074
5136
|
// src/proxmox/sdn-zone.ts
|
|
5075
5137
|
import { Resource as Resource33 } from "alchemy";
|
|
5076
5138
|
import * as Provider33 from "alchemy/Provider";
|
|
5077
|
-
import * as
|
|
5139
|
+
import * as Effect64 from "effect/Effect";
|
|
5078
5140
|
var ProxmoxSdnZone = Resource33("Proxmox.SdnZone");
|
|
5079
5141
|
var sameIpam = (live, declared2) => (live === "" ? "pve" : live) === (declared2 === undefined || declared2 === "" ? "pve" : declared2);
|
|
5080
5142
|
var body6 = (props) => ({
|
|
@@ -5095,7 +5157,7 @@ var clearable = {
|
|
|
5095
5157
|
vlan: ["dns", "dnszone", "ipam", "mtu", "nodes"],
|
|
5096
5158
|
vxlan: ["dns", "dnszone", "ipam", "mtu", "nodes"]
|
|
5097
5159
|
};
|
|
5098
|
-
var
|
|
5160
|
+
var handlers23 = pveHandlers({
|
|
5099
5161
|
readRole: "provision",
|
|
5100
5162
|
attributes: (live, props) => {
|
|
5101
5163
|
const liveType = text(live["type"]);
|
|
@@ -5127,13 +5189,13 @@ var handlers24 = pveHandlers({
|
|
|
5127
5189
|
return withClears(fields, clear);
|
|
5128
5190
|
}
|
|
5129
5191
|
});
|
|
5130
|
-
var ProxmoxSdnZoneProvider = () => Provider33.effect(ProxmoxSdnZone,
|
|
5192
|
+
var ProxmoxSdnZoneProvider = () => Provider33.effect(ProxmoxSdnZone, Effect64.succeed(ProxmoxSdnZone.Provider.of(handlers23)));
|
|
5131
5193
|
// src/proxmox/storage.ts
|
|
5132
5194
|
import { Resource as Resource34 } from "alchemy";
|
|
5133
|
-
import { isResolved as
|
|
5195
|
+
import { isResolved as isResolved16 } from "alchemy/Diff";
|
|
5134
5196
|
import * as Provider34 from "alchemy/Provider";
|
|
5135
5197
|
import * as storage2 from "@distilled.cloud/proxmox/storage";
|
|
5136
|
-
import * as
|
|
5198
|
+
import * as Effect66 from "effect/Effect";
|
|
5137
5199
|
|
|
5138
5200
|
// src/proxmox/storage-form.ts
|
|
5139
5201
|
var STORAGE_CREATE = "pve:POST /storage";
|
|
@@ -5150,27 +5212,27 @@ var mutable2 = (props) => ({
|
|
|
5150
5212
|
...field6("prune-backups", props["prune-backups"]),
|
|
5151
5213
|
...field6("shared", flag(props.shared))
|
|
5152
5214
|
});
|
|
5153
|
-
var
|
|
5215
|
+
var createForm11 = (props) => ({
|
|
5154
5216
|
...locatorForm(props.locator),
|
|
5155
5217
|
...mutable2(props),
|
|
5156
5218
|
storage: props.storage,
|
|
5157
5219
|
type: props.type
|
|
5158
5220
|
});
|
|
5159
|
-
var
|
|
5221
|
+
var updateForm8 = (props) => ({
|
|
5160
5222
|
...mutable2(props),
|
|
5161
5223
|
storage: props.storage
|
|
5162
5224
|
});
|
|
5163
|
-
var
|
|
5164
|
-
var
|
|
5225
|
+
var toDistilledCreate2 = (props) => underscored(createForm11(props));
|
|
5226
|
+
var toDistilledUpdate2 = (props) => underscored(updateForm8(props));
|
|
5165
5227
|
|
|
5166
5228
|
// src/proxmox/storage-wire.ts
|
|
5167
5229
|
import * as storage from "@distilled.cloud/proxmox/storage";
|
|
5168
|
-
import * as
|
|
5230
|
+
import * as Effect65 from "effect/Effect";
|
|
5169
5231
|
var str2 = (value, fallback = "") => typeof value === "string" ? value : fallback;
|
|
5170
5232
|
var tokens = (value) => value.split(",").map((part) => part.trim()).filter((part) => part !== "").sort().join(",");
|
|
5171
5233
|
var sameList2 = (declared2, live) => declared2 === undefined || tokens(declared2) === tokens(live);
|
|
5172
5234
|
var same7 = (declared2, live) => declared2 === undefined || declared2 === live;
|
|
5173
|
-
var
|
|
5235
|
+
var attributesOf8 = (live, props) => {
|
|
5174
5236
|
const data = live;
|
|
5175
5237
|
return {
|
|
5176
5238
|
comment: str2(data["comment"]),
|
|
@@ -5184,27 +5246,27 @@ var attributesOf7 = (live, props) => {
|
|
|
5184
5246
|
type: str2(data["type"], props.type)
|
|
5185
5247
|
};
|
|
5186
5248
|
};
|
|
5187
|
-
var readStorageOrFail = (props) => readOrUnreadable(runPve(props.target, "provision", false, storage.getStorage({ storage: props.storage }))).pipe(
|
|
5188
|
-
var readStorage = (props) => readStorageOrFail(props).pipe(
|
|
5249
|
+
var readStorageOrFail = (props) => readOrUnreadable(runPve(props.target, "provision", false, storage.getStorage({ storage: props.storage }))).pipe(Effect65.map((live) => live === UNREADABLE ? UNREADABLE : attributesOf8(live, props)));
|
|
5250
|
+
var readStorage = (props) => readStorageOrFail(props).pipe(Effect65.orElseSucceed(() => {
|
|
5189
5251
|
return;
|
|
5190
5252
|
}));
|
|
5191
|
-
var
|
|
5192
|
-
var
|
|
5253
|
+
var dropUnreadable7 = (live) => live === UNREADABLE ? undefined : live;
|
|
5254
|
+
var matches8 = (attributes2, props) => sameList2(props.content, attributes2.content) && sameList2(props.nodes, attributes2.nodes) && sameList2(props["prune-backups"], attributes2["prune-backups"]) && same7(props.disable, attributes2.disable) && same7(props.shared, attributes2.shared) && same7(props.preallocation, attributes2.preallocation) && same7(props.comment, attributes2.comment);
|
|
5193
5255
|
|
|
5194
5256
|
// src/proxmox/storage.ts
|
|
5195
5257
|
var ProxmoxStorage = Resource34("Proxmox.Storage", {
|
|
5196
5258
|
defaultRemovalPolicy: "retain"
|
|
5197
5259
|
});
|
|
5198
|
-
var ProxmoxStorageProvider = () => Provider34.effect(ProxmoxStorage,
|
|
5199
|
-
list: () =>
|
|
5200
|
-
read:
|
|
5201
|
-
return
|
|
5260
|
+
var ProxmoxStorageProvider = () => Provider34.effect(ProxmoxStorage, Effect66.succeed(ProxmoxStorage.Provider.of({
|
|
5261
|
+
list: () => Effect66.succeed([]),
|
|
5262
|
+
read: Effect66.fn(function* ({ olds, output }) {
|
|
5263
|
+
return dropUnreadable7(yield* output === undefined ? readStorage(olds) : readStorageOrFail(olds));
|
|
5202
5264
|
}),
|
|
5203
|
-
diff:
|
|
5204
|
-
if (!
|
|
5265
|
+
diff: Effect66.fn(function* ({ news, output }) {
|
|
5266
|
+
if (!isResolved16(news))
|
|
5205
5267
|
return;
|
|
5206
|
-
yield* guardWrite2(STORAGE_CREATE,
|
|
5207
|
-
yield* guardWrite2(STORAGE_UPDATE,
|
|
5268
|
+
yield* guardWrite2(STORAGE_CREATE, createForm11(news), output === undefined);
|
|
5269
|
+
yield* guardWrite2(STORAGE_UPDATE, updateForm8(news), false);
|
|
5208
5270
|
if (output === undefined)
|
|
5209
5271
|
return;
|
|
5210
5272
|
const live = yield* readStorageOrFail(news);
|
|
@@ -5213,67 +5275,67 @@ var ProxmoxStorageProvider = () => Provider34.effect(ProxmoxStorage, Effect65.su
|
|
|
5213
5275
|
return { action: "noop" };
|
|
5214
5276
|
}
|
|
5215
5277
|
if (live === undefined) {
|
|
5216
|
-
yield* guardWrite2(STORAGE_CREATE,
|
|
5278
|
+
yield* guardWrite2(STORAGE_CREATE, createForm11(news), true);
|
|
5217
5279
|
return { action: "update" };
|
|
5218
5280
|
}
|
|
5219
|
-
return
|
|
5281
|
+
return matches8(live, news) ? { action: "noop" } : { action: "update" };
|
|
5220
5282
|
}),
|
|
5221
|
-
reconcile:
|
|
5222
|
-
const before =
|
|
5223
|
-
yield* guardWrite2(STORAGE_CREATE,
|
|
5224
|
-
yield* guardWrite2(STORAGE_UPDATE,
|
|
5283
|
+
reconcile: Effect66.fn(function* ({ news }) {
|
|
5284
|
+
const before = dropUnreadable7(yield* readStorage(news));
|
|
5285
|
+
yield* guardWrite2(STORAGE_CREATE, createForm11(news), before === undefined);
|
|
5286
|
+
yield* guardWrite2(STORAGE_UPDATE, updateForm8(news), false);
|
|
5225
5287
|
if (before === undefined) {
|
|
5226
|
-
yield* runPve(news.target, "provision", true, storage2.createStorage(
|
|
5227
|
-
} else if (!
|
|
5228
|
-
yield* runPve(news.target, "provision", true, storage2.putStorage(
|
|
5288
|
+
yield* runPve(news.target, "provision", true, storage2.createStorage(toDistilledCreate2(news)));
|
|
5289
|
+
} else if (!matches8(before, news)) {
|
|
5290
|
+
yield* runPve(news.target, "provision", true, storage2.putStorage(toDistilledUpdate2(news)));
|
|
5229
5291
|
}
|
|
5230
|
-
const after =
|
|
5292
|
+
const after = dropUnreadable7(yield* readStorage(news));
|
|
5231
5293
|
if (after === undefined) {
|
|
5232
|
-
return yield*
|
|
5294
|
+
return yield* Effect66.die(new Error(`storage/${news.storage}: the write returned no error but the storage is still ` + 'absent. PVE wraps every answer in {"data":...} and can report success on a ' + "call that did nothing -- read back rather than trusting the status code."));
|
|
5233
5295
|
}
|
|
5234
5296
|
return after;
|
|
5235
5297
|
}),
|
|
5236
|
-
delete:
|
|
5298
|
+
delete: Effect66.fn(function* ({ olds }) {
|
|
5237
5299
|
yield* runPve(olds.target, "provision", true, storage2.deleteStorage({ storage: olds.storage }));
|
|
5238
5300
|
})
|
|
5239
5301
|
})));
|
|
5240
5302
|
// src/proxmox/zfs-pool.ts
|
|
5241
5303
|
import { Resource as Resource35 } from "alchemy";
|
|
5242
|
-
import { isResolved as
|
|
5304
|
+
import { isResolved as isResolved17 } from "alchemy/Diff";
|
|
5243
5305
|
import * as Provider35 from "alchemy/Provider";
|
|
5244
|
-
import * as
|
|
5306
|
+
import * as Effect69 from "effect/Effect";
|
|
5245
5307
|
|
|
5246
5308
|
// src/proxmox/zfs-pool-wire.ts
|
|
5247
|
-
import * as
|
|
5248
|
-
import * as
|
|
5309
|
+
import * as nodes3 from "@distilled.cloud/proxmox/nodes";
|
|
5310
|
+
import * as Effect67 from "effect/Effect";
|
|
5249
5311
|
var leafDevices = (children) => Array.isArray(children) ? children.flatMap((entry) => {
|
|
5250
5312
|
const vdev = entry;
|
|
5251
5313
|
const nested = leafDevices(vdev.children);
|
|
5252
5314
|
return nested.length > 0 ? nested : [text(vdev.name)].filter((name) => name !== "");
|
|
5253
5315
|
}) : [];
|
|
5254
|
-
var
|
|
5316
|
+
var attributesOf9 = (live, props) => ({
|
|
5255
5317
|
devices: leafDevices(live.children).join(","),
|
|
5256
5318
|
errors: text(live.errors, "unknown"),
|
|
5257
5319
|
name: props.name,
|
|
5258
5320
|
node: props.node,
|
|
5259
5321
|
state: text(live.state, "unknown")
|
|
5260
5322
|
});
|
|
5261
|
-
var readPoolOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false,
|
|
5323
|
+
var readPoolOrFail = (props) => readOrUnreadable(runPve(props.target, "read", false, nodes3.getNodeDiskZfs({ name: props.name, node: props.node }))).pipe(Effect67.map((live) => {
|
|
5262
5324
|
if (live === UNREADABLE)
|
|
5263
5325
|
return UNREADABLE;
|
|
5264
|
-
return text(live.name) === "" ? undefined :
|
|
5326
|
+
return text(live.name) === "" ? undefined : attributesOf9(live, props);
|
|
5265
5327
|
}));
|
|
5266
|
-
var readPool = (props) => readPoolOrFail(props).pipe(
|
|
5328
|
+
var readPool = (props) => readPoolOrFail(props).pipe(Effect67.orElseSucceed(() => {
|
|
5267
5329
|
return;
|
|
5268
5330
|
}));
|
|
5269
|
-
var
|
|
5331
|
+
var dropUnreadable8 = (live) => live === UNREADABLE ? undefined : live;
|
|
5270
5332
|
|
|
5271
5333
|
// src/proxmox/zfs-pool-form.ts
|
|
5272
|
-
import * as
|
|
5273
|
-
import * as
|
|
5334
|
+
import * as Effect68 from "effect/Effect";
|
|
5335
|
+
import * as nodes4 from "@distilled.cloud/proxmox/nodes";
|
|
5274
5336
|
var ZFS_POOL_CREATE = "pve:POST /nodes/{node}/disks/zfs";
|
|
5275
5337
|
var zfsPoolCreateEndpoint = (props) => props.devices === undefined || props.raidlevel === undefined ? undefined : ZFS_POOL_CREATE;
|
|
5276
|
-
var
|
|
5338
|
+
var createForm12 = (props) => ({
|
|
5277
5339
|
...props.devices === undefined ? {} : { devices: props.devices.join(",") },
|
|
5278
5340
|
name: props.name,
|
|
5279
5341
|
...props.raidlevel === undefined ? {} : { raidlevel: props.raidlevel },
|
|
@@ -5281,8 +5343,8 @@ var createForm11 = (props) => ({
|
|
|
5281
5343
|
...props.compression === undefined ? {} : { compression: props.compression },
|
|
5282
5344
|
...props["draid-config"] === undefined ? {} : { "draid-config": props["draid-config"] }
|
|
5283
5345
|
});
|
|
5284
|
-
var
|
|
5285
|
-
const form =
|
|
5346
|
+
var toDistilledCreate3 = (props) => {
|
|
5347
|
+
const form = createForm12(props);
|
|
5286
5348
|
return {
|
|
5287
5349
|
...form,
|
|
5288
5350
|
draid_config: form["draid-config"],
|
|
@@ -5290,43 +5352,43 @@ var toDistilledCreate2 = (props) => {
|
|
|
5290
5352
|
};
|
|
5291
5353
|
};
|
|
5292
5354
|
var SETTLE_ATTEMPTS = 30;
|
|
5293
|
-
var createPool = (props, read4) =>
|
|
5355
|
+
var createPool = (props, read4) => Effect68.gen(function* () {
|
|
5294
5356
|
const existing = yield* read4(props);
|
|
5295
5357
|
if (existing !== undefined)
|
|
5296
5358
|
return existing;
|
|
5297
5359
|
if (props.devices === undefined || props.raidlevel === undefined) {
|
|
5298
|
-
return yield*
|
|
5360
|
+
return yield* Effect68.die(new Error(`${props.node}/${props.name}: this is an adopt-only declaration (no \`devices\` or ` + "`raidlevel`) and the pool is not there to adopt. An adopt-only Proxmox.ZfsPool never " + "creates -- declare both fields for a pool this resource should build, or point this " + "declaration at a pool that already exists on this node."));
|
|
5299
5361
|
}
|
|
5300
|
-
yield* guardForm(zfsPoolCreateEndpoint(props), asForm2(
|
|
5301
|
-
const upid = yield* runPve(props.target, "provision", true,
|
|
5302
|
-
const settle4 = (attempts) =>
|
|
5362
|
+
yield* guardForm(zfsPoolCreateEndpoint(props), asForm2(createForm12(props)), true);
|
|
5363
|
+
const upid = yield* runPve(props.target, "provision", true, nodes4.createNodeDiskZfs(toDistilledCreate3(props)));
|
|
5364
|
+
const settle4 = (attempts) => Effect68.gen(function* () {
|
|
5303
5365
|
const live = yield* read4(props);
|
|
5304
5366
|
if (live !== undefined || attempts <= 0)
|
|
5305
5367
|
return live;
|
|
5306
|
-
yield*
|
|
5368
|
+
yield* Effect68.sleep("2 seconds");
|
|
5307
5369
|
return yield* settle4(attempts - 1);
|
|
5308
5370
|
});
|
|
5309
5371
|
const after = yield* settle4(SETTLE_ATTEMPTS);
|
|
5310
5372
|
if (after === undefined) {
|
|
5311
|
-
return yield*
|
|
5373
|
+
return yield* Effect68.die(new Error(`nodes/${props.node}/disks/zfs/${props.name}: POST returned ${text(upid, "(no UPID)")} ` + "but the pool has not appeared. That POST only forks a `zfscreate` worker, so the task " + `holds the real error -- read it with \`pvesh get /nodes/${props.node}/tasks/<upid>/log\`. ` + "NOTHING WAS RETRIED AND NOTHING WAS CLEANED UP: if the worker reached `zpool create`, " + "the declared devices have already been written to. DO NOT RE-RUN THIS DEPLOY BEFORE " + 'READING THAT LOG: `read` cannot tell "the worker is still running" from "the pool is ' + 'genuinely gone", so a re-run this soon can POST a SECOND `zpool create` at the SAME ' + "devices while the first one is still mid-write -- confirm the task finished (one way " + "or the other) before trying again."));
|
|
5312
5374
|
}
|
|
5313
5375
|
return after;
|
|
5314
5376
|
});
|
|
5315
|
-
var destroyPool = (props) => runPve(props.target, "provision", true,
|
|
5377
|
+
var destroyPool = (props) => runPve(props.target, "provision", true, nodes4.deleteNodeDiskZfs({ name: props.name, node: props.node }));
|
|
5316
5378
|
|
|
5317
5379
|
// src/proxmox/zfs-pool.ts
|
|
5318
5380
|
var ProxmoxZfsPool = Resource35("Proxmox.ZfsPool", {
|
|
5319
5381
|
defaultRemovalPolicy: "retain"
|
|
5320
5382
|
});
|
|
5321
|
-
var ProxmoxZfsPoolProvider = () => Provider35.effect(ProxmoxZfsPool,
|
|
5322
|
-
list: () =>
|
|
5323
|
-
read:
|
|
5324
|
-
return
|
|
5383
|
+
var ProxmoxZfsPoolProvider = () => Provider35.effect(ProxmoxZfsPool, Effect69.succeed(ProxmoxZfsPool.Provider.of({
|
|
5384
|
+
list: () => Effect69.succeed([]),
|
|
5385
|
+
read: Effect69.fn(function* ({ olds, output }) {
|
|
5386
|
+
return dropUnreadable8(yield* output === undefined ? readPool(olds) : readPoolOrFail(olds));
|
|
5325
5387
|
}),
|
|
5326
|
-
diff:
|
|
5327
|
-
if (!
|
|
5388
|
+
diff: Effect69.fn(function* ({ news, output }) {
|
|
5389
|
+
if (!isResolved17(news))
|
|
5328
5390
|
return;
|
|
5329
|
-
yield* guardForm(zfsPoolCreateEndpoint(news), asForm2(
|
|
5391
|
+
yield* guardForm(zfsPoolCreateEndpoint(news), asForm2(createForm12(news)), output === undefined);
|
|
5330
5392
|
if (output === undefined)
|
|
5331
5393
|
return;
|
|
5332
5394
|
const live = yield* readPoolOrFail(news);
|
|
@@ -5335,15 +5397,15 @@ var ProxmoxZfsPoolProvider = () => Provider35.effect(ProxmoxZfsPool, Effect68.su
|
|
|
5335
5397
|
return { action: "noop" };
|
|
5336
5398
|
}
|
|
5337
5399
|
if (live === undefined) {
|
|
5338
|
-
yield* guardForm(zfsPoolCreateEndpoint(news), asForm2(
|
|
5400
|
+
yield* guardForm(zfsPoolCreateEndpoint(news), asForm2(createForm12(news)), true);
|
|
5339
5401
|
return { action: "update" };
|
|
5340
5402
|
}
|
|
5341
5403
|
return { action: "noop" };
|
|
5342
5404
|
}),
|
|
5343
|
-
reconcile:
|
|
5344
|
-
return yield* createPool(news, (props) => readPool(props).pipe(
|
|
5405
|
+
reconcile: Effect69.fn(function* ({ news }) {
|
|
5406
|
+
return yield* createPool(news, (props) => readPool(props).pipe(Effect69.map(dropUnreadable8)));
|
|
5345
5407
|
}),
|
|
5346
|
-
delete:
|
|
5408
|
+
delete: Effect69.fn(function* ({ olds }) {
|
|
5347
5409
|
yield* destroyPool(olds);
|
|
5348
5410
|
})
|
|
5349
5411
|
})));
|
|
@@ -5423,5 +5485,5 @@ export {
|
|
|
5423
5485
|
violations
|
|
5424
5486
|
};
|
|
5425
5487
|
|
|
5426
|
-
//# debugId=
|
|
5488
|
+
//# debugId=AF866CF2F0A2718F64756E2164756E21
|
|
5427
5489
|
//# sourceMappingURL=index.js.map
|