Inheritance

Block inheritance in Polycrate: how block instances in workspace.poly inherit from template blocks via from:, config deep merge, overriding actions, inventory and kubeconfig conventions and best practices.

Inheritance

What is block inheritance?

Block inheritance enables the reuse and customization of existing blocks. A block instantiated in workspace.poly can inherit from a template block and take over its properties:

  • Configuration (config) – merged via deep merge
  • Actions – can be overridden or extended
  • Working directory – set to the template block

Inheritance hierarchy

+-----------------------------+
| blocks/  Template block     |
| postgres-base/block.poly    |
+-----------------------------+
               |
               |  from: postgres-base
               v
+-----------------------------+
| workspace.poly              |
| Block instance: my-postgres |
+-----------------------------+

Important: There is only ONE level of inheritance:

  • Template block (blocks/postgres-base/block.poly) – defines actions, config defaults, playbooks
  • Block instance (workspace.poly) – inherits via from: and overrides where needed

Defining inheritance

Template block (block.poly)

A template block defines the base functionality:

# blocks/postgres-base/block.poly
name: postgres-base
kind: k8sapp
version: 1.0.0

config:
  namespace: default
  app:
    persistence:
      size: 10Gi
      storageClass: standard
    replicas: 1

actions:
  - name: install
    playbook: install.yml
  - name: backup
    playbook: backup.yml

Block instance (workspace.poly)

In workspace.poly the template block is instantiated and customized:

# workspace.poly
blocks:
  - name: my-postgres
    from: postgres-base  # Inherits from local template block
    config:
      namespace: production  # Override
      app:
        persistence:
          size: 100Gi  # Override

  - name: harbor
    from: registry.my-org.com/blocks/k8s/harbor:1.2.0  # Inherits from registry block
    config:
      namespace: harbor-prod

Merge behavior

When merging the configurations, the following applies:

  Template block config              Block instance config
           \                               /
            \                             /
             --------  Deep Merge  --------
                           |
                           v
                 Resulting config

Important: Instance values override template values!

Example: config merge

Template block (blocks/postgres-base/block.poly):

name: postgres-base
config:
  namespace: default
  app:
    persistence:
      size: 10Gi
      storageClass: standard
    replicas: 1

Block instance (workspace.poly):

blocks:
  - name: my-postgres
    from: postgres-base
    config:
      namespace: production
      app:
        persistence:
          size: 50Gi

Resulting config (workspace snapshot):

# my-postgres after merge
config:
  namespace: production      # overridden
  app:
    persistence:
      size: 50Gi             # overridden
      storageClass: standard # inherited
    replicas: 1              # inherited

Inheriting and overriding actions

Actions are inherited as well, but can be overridden in the block instance:

Template block (blocks/postgres-base/block.poly):

actions:
  - name: install
    playbook: install.yml

  - name: backup
    playbook: backup.yml

Block instance (workspace.poly):

blocks:
  - name: my-postgres
    from: postgres-base
    actions:
      - name: install
        playbook: custom-install.yml  # Overrides the template action

      - name: migrate
        playbook: migrate.yml  # New action

Result: The block instance my-postgres has three actions:

  • install (overridden with custom-install.yml)
  • backup (inherited from the template block)
  • migrate (newly added)

Inventory and Kubeconfig

Recommended convention (current)

  • inventory.yml in the workspace root – one shared Ansible inventory for the entire workspace (default file name, see workspace configuration for deviations).
  • artifacts/secrets/kubeconfig.yml – one workspace-wide kubeconfig; the CLI detects the file and provides the paths in the snapshot.

This keeps the scope per workspace clearly delimited. → Best practices: Inventory and Kubeconfig

kubeconfig.from / inventory.from (legacy)

Optionally, block instances in workspace.poly can set kubeconfig.from or inventory.from and thereby refer to the artifacts of other block instances (not to their config: – that is a different mechanism than from:).

# workspace.poly (pattern – not recommended from a best-practice perspective)
blocks:
  - name: my-cluster
    from: registry.acme.corp/acme/k8s/cluster:1.0.0

  - name: my-app
    from: registry.acme.corp/acme/k8s/my-app:1.0.0
    kubeconfig:
      from: my-cluster  # Kubeconfig artifact from block "my-cluster"

Best practices

1. Create template blocks

Create reusable template blocks in the blocks/ directory:

# blocks/postgres-template/block.poly
name: postgres-template
kind: k8sapp
version: 1.0.0

config:
  # Sensible defaults
  namespace: default
  persistence:
    enabled: true
    size: 10Gi
  monitoring:
    enabled: true

actions:
  - name: install
    playbook: install.yml
  - name: backup
    playbook: backup.yml

2. Sensible overrides in workspace.poly

Override only what is necessary:

# workspace.poly
blocks:
  # ✅ Good: override only specific values
  - name: my-postgres-prod
    from: postgres-template
    config:
      namespace: production
      persistence:
        size: 100Gi

  # ❌ Bad: repeat the entire config
  - name: my-postgres-bad
    from: postgres-template
    config:
      namespace: production
      persistence:
        enabled: true   # Unnecessary, is inherited
        size: 100Gi
      monitoring:
        enabled: true   # Unnecessary, is inherited

3. Use registry blocks

For production-ready blocks we recommend using registry blocks:

# workspace.poly
blocks:
  - name: my-harbor
    from: registry.my-org.com/blocks/k8s/harbor:1.2.0
    config:
      namespace: harbor-production

Polycrate automatically pulls the block from the registry and uses it as the template.