Apply Type

This document describes the design of the apply resource type for composing manifests from smaller reusable manifests.

Overview

The apply resource resolves and executes a child manifest within the parent manifest’s execution context. The child manifest shares the parent’s manager and session, allowing resource ordering and subscribe relationships across manifest boundaries.

Key behaviors:

  • Noop strengthening: A parent in noop mode forces all children into noop mode, regardless of the child’s noop property
  • Health check strengthening: Same semantics as noop; health check mode can only be strengthened, never weakened
  • Recursion depth limiting: Nested apply resources are capped at a configurable maximum depth (default 10) to prevent infinite loops
  • Transitive trust control: The allow_apply property prevents a child manifest from containing its own apply resources

Provider Interface

Apply providers must implement the ApplyProvider interface:

type ApplyProvider interface {
    model.Provider

    ApplyManifest(ctx context.Context, mgr model.Manager, properties *model.ApplyResourceProperties, currentDepth int, healthCheckOnly bool, log model.Logger) (*model.ApplyState, error)
}

Method Responsibilities

MethodResponsibility
ApplyManifestResolve and execute a child manifest, handling state save/restore and overrides

State Response

The ApplyManifest method returns an ApplyState containing:

type ApplyState struct {
    CommonResourceState
    ResourceCount int // Number of resources in the child manifest
}

Available Providers

ProviderSourceDocumentation
ccmmanifestLocal manifest fileCCM Manifest

Ensure States

ValueDescription
presentResolve and execute the child manifest

Only present is valid. The ensure property defaults to present if not specified.

Properties

PropertyTypeDescription
namestringFile path to the child manifest
noopboolExecute child in noop mode (can only strengthen)
health_check_onlyboolExecute child in health check mode (can only strengthen)
allow_applyboolAllow the child manifest to contain apply resources (default true)
datamap[string]anyData to pass to the child manifest, merged with external data

Apply Logic

┌─────────────────────────────────────────┐
│ Save parent state (noop, data, wd)      │
│ (restored via defer on all paths)       │
└─────────────────┬───────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────┐
│ Strengthen noop and health_check_only   │
└─────────────────┬───────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────┐
│ Resolve child manifest                  │
│ (applies data overrides, sets wd)       │
└─────────────────┬───────────────────────┘
                  │
                  ▼
    ┌─────────────┴─────────────┐
    │ Recursion depth within    │
    │ limit?                    │
    └─────────────┬─────────────┘
              Yes │         No
                  │         │
                  ▼         ▼
    ┌─────────────┴───┐ ┌───────┐
    │ allow_apply     │ │ Error │
    │ satisfied?      │ └───────┘
    └─────────────┬───┘
              Yes │         No
                  │         │
                  ▼         ▼
    ┌─────────────┴───┐ ┌───────┐
    │ Execute child   │ │ Error │
    │ resources       │ └───────┘
    └─────────┬───────┘
              │
              ▼
┌─────────────────────────────────────────┐
│ Report resource count, changed, failed  │
└─────────────────────────────────────────┘

Noop Strengthening

Noop mode follows a strict strengthening rule: a child manifest can run in noop mode when the parent does not, but a child can never weaken noop mode.

Parent noopChild noop propertyEffective child noopBehavior
truefalsetrueWarning logged, parent noop applies
truetruetrueBoth agree
falsetruetrueChild strengthens to noop
falsefalsefalseNormal execution

Health check mode follows the same strengthening pattern.

State Save and Restore

The provider saves three pieces of manager state before manifest resolution and restores them after execution:

StateSave methodRestore methodReason
Noop modeNoopMode()SetNoopMode(saved)Child noop must not leak to subsequent resources
Working directoryWorkingDirectory()SetWorkingDirectory(wd)ResolveManifestUrl changes working directory
DataData()SetData(saved)Child data overrides must not persist

State is saved before calling any resolve functions because ResolveManifestUrl mutates the manager’s working directory and data during resolution.

Recursion Depth Limiting

Nested apply resources increment a depth counter passed through Execute() options. The default maximum depth is 10.

parent.yaml (depth 0)
  +-- child.yaml (depth 1)
        +-- grandchild.yaml (depth 2)
              +-- ... (up to depth 10)

Exceeding the maximum depth returns an error before iterating any child resources.

Transitive Trust

The allow_apply property controls whether a child manifest may contain its own apply resources. When allow_apply is false, the child manifest is scanned for apply resources after resolution but before execution. If any are found, an error is returned.

This provides a mechanism to limit the trust boundary when including manifests authored by others.

allow_apply valueChild contains apply resourcesResult
true (default)YesAllowed
true (default)NoAllowed
falseYesError
falseNoAllowed

Data Handling

The data property provides key-value data to the child manifest. This data is passed through the WithOverridingResolvedData option and merged into the resolved data after the child manifest’s own data resolution.

External data (CLI overrides) always persists through the merge. The parent’s original data is restored after child execution via the state save/restore mechanism.

Subscribe Behavior

Apply resources support the standard subscribe property. Subscribe targets use the apply#name format:

- apply:
    - child.yaml:

- exec:
    - post-apply:
        command: /usr/local/bin/notify.sh
        refresh_only: true
        subscribe:
          - apply#child.yaml

Child Manifest Failures

After child manifest execution, the provider inspects the result to determine the outcome:

Child resultParent behavior
All resources succeededLog success, report unchanged
Some resources changedLog warning, report changed
Any resource failedReturn error with failure count

Subsections of Apply Type

CCM Manifest Provider

This document describes the implementation details of the CCM Manifest provider for resolving and executing child manifests.

Provider Selection

The CCM Manifest provider is the only apply provider. It is always available and returns priority 1 for all apply resources.

Operations

ApplyManifest

Process:

  1. Capture parent state (noop mode, working directory, data)
  2. Strengthen noop mode if the parent is in noop mode or the resource has noop: true
  3. Build execution options for the child manifest
  4. Resolve the child manifest via apply.ResolveManifestUrl()
  5. Execute the resolved manifest via resolvedApply.Execute()
  6. Inspect child resource outcomes (changed, failed, skipped)
  7. Restore parent state via deferred restore

Noop Strengthening:

The provider only strengthens noop mode, never weakens it. If the parent manager is already in noop mode, the child inherits that regardless of its own noop property. If the parent is not in noop mode and the resource sets noop: true, the provider enables noop on the manager before resolution.

Parent noopResource noopAction
truefalseNo change, parent noop already active
truetrueNo change, parent noop already active
falsetrueEnable noop on manager
falsefalseNo change

Health check mode follows the same strengthening pattern. The effective health check mode is true if either the parent or the resource sets it.

Execute Options:

The provider builds these options to control child manifest behavior:

OptionConditionPurpose
WithSkipSession()AlwaysReuse parent session instead of creating a new one
WithCurrentDepth(n)AlwaysTrack recursion depth for nested apply resources
WithOverridingResolvedDatadata property is setMerge resource data into the child’s resolved data
WithDenyApplyResources()allow_apply is falsePrevent child from containing apply resources

State Capture and Restore

The provider saves three pieces of manager state before manifest resolution and restores them after execution via defer. This ensures restoration runs even if resolution or execution fails.

FieldCaptureRestore
Noop modemgr.NoopMode()mgr.SetNoopMode(saved)
Working directorymgr.WorkingDirectory()mgr.SetWorkingDirectory(saved)
Datamgr.Data()mgr.SetData(saved)

State capture happens before any resolve or mutation calls. This ordering is critical because ResolveManifestUrl mutates the manager’s working directory and data during resolution.

Restoration ensures that subsequent resources in the parent manifest see the original manager state. Without it, a child manifest’s working directory and data changes would leak into sibling resources.

Path Resolution

The resource name property specifies a file path relative to the parent manifest’s directory. During resolution, ResolveManifestFilePath joins relative paths with the manager’s current working directory before opening the file.

For nested apply resources, each level sets the working directory to its own manifest’s parent directory. The state restore ensures the working directory returns to the correct value after each child completes.

/opt/ccm/manifest.yaml          WD = /opt/ccm/
  apply: sub/manifest.yaml       resolves to /opt/ccm/sub/manifest.yaml
                                  WD = /opt/ccm/sub/
    apply: lib/manifest.yaml     resolves to /opt/ccm/sub/lib/manifest.yaml
                                  WD = /opt/ccm/sub/lib/
                                  (restore WD to /opt/ccm/sub/)
                                (restore WD to /opt/ccm/)

Child Resource Inspection

After execution, the provider iterates over child resources to count outcomes using the shared session:

OutcomeDetection methodEffect
Failedmgr.IsResourceFailedIncrement fail count
Changedmgr.ShouldRefreshIncrement change count
SkippedNeitherRemainder

The provider builds an ApplyState with the total resource count and reports the outcome:

Child resultProvider behavior
All resources succeededLog informational message, return state
Some resources changedLog warning with counts, return state
Any resource failedLog error, return error with failure count

Logging

The provider creates a child user logger with a manifest key set to the resource name. All child resource log output includes this key, providing attribution for which parent apply resource triggered the execution.