§ Concepts

What a plan reaches

Change one setting, replace a root key, add a zone or run two applies on one estate, and see which resources each plan reaches and which locks each apply holds.

View as Markdown

pravo records which resource reads which. A plan starts at the change and follows the edges for as long as a value changes. The resources it does not reach are neither validated nor planned, and their records are not read from the providers: a plan reads the records of the resources it reaches and of the resources they read, and only when a record is older than its refresh age. The Graph: line counts what was planned, skipped, read and not read.

An apply locks the resources that its plan writes, and nothing else. Two applies that write different resources run at the same time. The estate below is a small certificate authority with several zones, planned by the real binary.

Dependency graph of the estate 39 resources in 10 module instances. Each node is a resource. An edge runs from the resource that is read to the resource that reads it. The drawing leaves out an edge that a longer path already implies: 38 edges are drawn of the 53 that pravo state graph prints. Use the arrow keys to move between nodes. rootzone azone bzone czone d root.key, tls_private_key, skippedroot.cert, tls_self_signed_cert, skippedroot.file, local_file, skippedzone.a.key, tls_private_key, skippedzone.a.csr, tls_cert_request, skippedzone.a.cert, tls_locally_signed_cert, skippedzone.a.file, local_file, skippedservice.a.api.key, tls_private_key, skippedservice.a.api.csr, tls_cert_request, skippedservice.a.api.cert, tls_locally_signed_cert, skippedservice.a.api.file, local_file, skippedservice.a.web.key, tls_private_key, skippedservice.a.web.csr, tls_cert_request, skippedservice.a.web.cert, tls_locally_signed_cert, skippedservice.a.web.file, local_file, skippedzone.b.key, tls_private_key, skippedzone.b.csr, tls_cert_request, skippedzone.b.cert, tls_locally_signed_cert, skippedzone.b.file, local_file, skippedservice.b.api.key, tls_private_key, skippedservice.b.api.csr, tls_cert_request, skippedservice.b.api.cert, tls_locally_signed_cert, skippedservice.b.api.file, local_file, skippedservice.b.web.key, tls_private_key, skippedservice.b.web.csr, tls_cert_request, skippedservice.b.web.cert, tls_locally_signed_cert, updated in placeservice.b.web.file, local_file, skippedzone.c.key, tls_private_key, skippedzone.c.csr, tls_cert_request, skippedzone.c.cert, tls_locally_signed_cert, skippedzone.c.file, local_file, skippedservice.c.api.key, tls_private_key, skippedservice.c.api.csr, tls_cert_request, skippedservice.c.api.cert, tls_locally_signed_cert, skippedservice.c.api.file, local_file, skippedservice.c.web.key, tls_private_key, skippedservice.c.web.csr, tls_cert_request, skippedservice.c.web.cert, tls_locally_signed_cert, skippedservice.c.web.file, local_file, skippedzone.d.key, tls_private_key, not yet in the specificationzone.d.csr, tls_cert_request, not yet in the specificationzone.d.cert, tls_locally_signed_cert, not yet in the specificationzone.d.file, local_file, not yet in the specification
  • created
  • updated in place
  • replaced
  • skipped
  • locked
main.cue
15a: services: {api: {}, web: {}}
16+b: services: {api: {}, web: {renewal_hours: 48}}
16-b: services: {api: {}, web: {}}
17c: services: {api: {}, web: {}}
terminal
$pravo plan | grep -E '^( #|Plan|Graph)'
  # service.b.web.cert (tls_locally_signed_cert) will be updated in-place
Plan: 0 to add, 1 to change, 0 to destroy.
Graph: planned 1 of 39, 38 unchanged and skipped, 4 refreshed, 35 not read.
pki/service.cue:26-33updated in place
cert: tls.#Resource.tls_locally_signed_cert & {
    cert_request_pem:      csr.cert_request_pem
    ca_private_key_pem:    issuer_key
    ca_cert_pem:           issuer_cert
    validity_period_hours: 2160
    early_renewal_hours:   renewal_hours
    allowed_uses: ["server_auth"]
}

service.b.web.cert tls_locally_signed_cert

# service.b.web.cert (tls_locally_signed_cert) will be updated in-place

reads zone.b.key, zone.b.cert, service.b.web.csr · a change here can reach 1 node

1of 39

nodes planned

Graph: planned 1 of 39, 38 unchanged and skipped, 4 refreshed, 35 not read.

fig. 3 One certificate gets a longer renewal window, an attribute that the provider updates in place. 1 of 39 nodes are planned. The file that holds the certificate and the 37 other nodes are skipped.

The four changes

  1. Change a setting. One certificate gets a longer renewal window, an attribute that the provider updates in place. 1 of 39 nodes are planned. The file that holds the certificate and the 37 other nodes are skipped. Graph: planned 1 of 39, 38 unchanged and skipped, 4 refreshed, 35 not read.
  2. Replace a root key. The root key changes its curve, which cannot change in place. The key is replaced, and the replacement follows the edges to every certificate below it and to the files that hold them: 21 of 39 nodes. The 18 keys and certificate requests that do not read the root are skipped. Graph: planned 21 of 39, 18 unchanged and skipped, 33 refreshed, 6 not read.
  3. Add a zone. A fourth zone, d, joins the specification. Its 4 resources are created, and the 39 existing nodes are skipped: planned 4 of 43. Graph: planned 4 of 43, 39 unchanged and skipped, 2 refreshed, 37 not read.
  4. Two applies at once. Ana replaces the key of zone a and Bob replaces the key of zone b. The two plans share no node and no output, so both applies hold their locks at once: 16 locks, two holders. Both applies complete.

Plans explains the rule with the commands that print each result. State describes the locks, and Lab 2 runs two applies at once.