56 lines
2.3 KiB
Text
56 lines
2.3 KiB
Text
|
|
# backup-policy-binding domain contract v0.1.0
|
||
|
|
#
|
||
|
|
# Backup targets with scope and retention, delivered to cloudatasave or
|
||
|
|
# any backup-capable integration mode participant.
|
||
|
|
|
||
|
|
let _RetentionPreset = [| 'bronze, 'silver, 'gold |] in
|
||
|
|
# bronze: 7d daily; silver: 30d daily + 12w weekly; gold: 90d daily + 52w weekly + 3y monthly
|
||
|
|
|
||
|
|
let _BackupScope = std.contract.custom (fun label value =>
|
||
|
|
if !std.is_record value then
|
||
|
|
std.contract.blame_with_message "BackupScope must be a record with a 'kind' field" label
|
||
|
|
else if !std.record.has_field "kind" value then
|
||
|
|
std.contract.blame_with_message "BackupScope missing required field 'kind'" label
|
||
|
|
else
|
||
|
|
match {
|
||
|
|
"per_domain" =>
|
||
|
|
if std.record.has_field "domains" value then 'Ok value
|
||
|
|
else std.contract.blame_with_message "BackupScope kind='per_domain' requires field: domains (Array String)" label,
|
||
|
|
"per_mailbox" =>
|
||
|
|
if std.record.has_field "domain" value then 'Ok value
|
||
|
|
else std.contract.blame_with_message "BackupScope kind='per_mailbox' requires field: domain (String)" label,
|
||
|
|
"database" =>
|
||
|
|
if std.record.has_field "database" value && std.record.has_field "host" value then 'Ok value
|
||
|
|
else std.contract.blame_with_message "BackupScope kind='database' requires fields: database, host" label,
|
||
|
|
"service_full" => 'Ok value,
|
||
|
|
_ => std.contract.blame_with_message
|
||
|
|
"Unknown BackupScope kind. Valid: per_domain, per_mailbox, database, service_full"
|
||
|
|
label,
|
||
|
|
} value.kind
|
||
|
|
) in
|
||
|
|
|
||
|
|
let _BackupTarget = {
|
||
|
|
component | String
|
||
|
|
| doc "Component name as declared in infra/<ws>/components/<name>.ncl",
|
||
|
|
scope | _BackupScope,
|
||
|
|
retention | _RetentionPreset,
|
||
|
|
tags | { _ | String } | optional
|
||
|
|
| doc "Extra restic tags injected into every snapshot for this target",
|
||
|
|
} in
|
||
|
|
|
||
|
|
let _BackupPolicyBindingContext = {
|
||
|
|
schema_version | String | default = "0.1.0",
|
||
|
|
workspace | String,
|
||
|
|
mode_id | String,
|
||
|
|
targets | Array _BackupTarget,
|
||
|
|
repo_endpoint | String | optional
|
||
|
|
| doc "Restic repository endpoint override; absent means use component default",
|
||
|
|
} in
|
||
|
|
|
||
|
|
{
|
||
|
|
RetentionPreset = _RetentionPreset,
|
||
|
|
BackupScope = _BackupScope,
|
||
|
|
BackupTarget = _BackupTarget,
|
||
|
|
BackupPolicyBindingContext = _BackupPolicyBindingContext,
|
||
|
|
}
|