ArgoCD

Capsule Integration with ArgoCD

Integration

Resource Actions

You may provide Custom Resource Actions for Capsule specific resources and interactions.

Namespace Resource Actions

Namespace Resource Actions

With the following configuration, ArgoCD will show Cordon and Resume actions for the Namespace resource. The Cordon action will set the projectcapsule.dev/cordoned label to true, while the Resume action will set it to false. This is only for Namespaces part of a Capsule Tenant.

resource.customizations.actions.Namespace: |
  mergeBuiltinActions: true
  discovery.lua: |
    actions = {
      cordon = {
        iconClass = "fa fa-solid fa-pause",
        disabled = true,
      },
      uncordon = {
        iconClass = "fa fa-solid fa-play",
        disabled = true,
      },
    }

    local function has_managed_ownerref()
      if obj.metadata == nil or obj.metadata.ownerReferences == nil then
        return false
      end

      for _, ref in ipairs(obj.metadata.ownerReferences) do
        if ref.kind == "Tenant" and ref.apiVersion == "capsule.clastix.io/v1beta2" then
          return true
        end
      end

      return false
    end
    if not has_managed_ownerref() then
      return {}
    end
    local labels = {}
    if obj.metadata ~= nil and obj.metadata.labels ~= nil then
      labels = obj.metadata.labels
    end

    local cordoned = labels["projectcapsule.dev/cordoned"] == "true"

    if cordoned then
      actions["uncordon"].disabled = false
    else
      actions["cordon"].disabled = false
    end

    return actions

  definitions:
    - name: cordon
      action.lua: |
        if obj.metadata == nil then
          obj.metadata = {}
        end
        if obj.metadata.labels == nil then
          obj.metadata.labels = {}
        end

        obj.metadata.labels["projectcapsule.dev/cordoned"] = "true"
        return obj

    - name: uncordon
      action.lua: |
        if obj.metadata ~= nil and obj.metadata.labels ~= nil then
          obj.metadata.labels["projectcapsule.dev/cordoned"] = "false"
        end
        return obj  

Tenant Resource Actions

Tenant Resource Actions

With the following configuration, ArgoCD will show Cordon and Resume actions for the Tenant resource. The Cordon action will set the spec.cordon field to true, while the Resume action will set it to false.

resource.customizations.actions.capsule.clastix.io_Tenant: |
  mergeBuiltinActions: true
  discovery.lua: |
    actions = {}
    actions["cordon"] = {
      ["iconClass"] = "fa fa-solid fa-pause",
      ["disabled"] = true,
    }
    actions["uncordon"] = {
      ["iconClass"] = "fa fa-solid fa-play",
      ["disabled"] = true,
    }

    local suspend = false
    if obj.spec ~= nil and obj.spec.cordoned ~= nil then
      suspend = obj.spec.cordoned
    end

    if suspend then
      actions["uncordon"]["disabled"] = false
    else
      actions["cordon"]["disabled"] = false
    end

    return actions

  definitions:
    - name: cordon
      action.lua: |
        if obj.spec == nil then
          obj.spec = {}
        end
        obj.spec.cordoned = true
        return obj

    - name: uncordon
      action.lua: |
        if obj.spec ~= nil and obj.spec.cordoned ~= nil and obj.spec.cordoned then
          obj.spec.cordoned = false
        end
        return obj  

Resource Health

You may provide Custom Resource Health for Capsule specific resources and interactions.

Tenant Resource Health

Tenant Resource Actions

Suspends a Tenant when it’s Cordoned. Cordoning a Tenant will Cordon/Uncordon all it’s Namespaces.

resource.customizations.health.capsule.clastix.io_Tenant: |
  hs = {}
  if obj.status ~= nil then
    if obj.status.conditions ~= nil then
      for i, condition in ipairs(obj.status.conditions) do
        if condition.type == "Cordoned" and condition.status == "True" then
          hs.status = "Suspended"
          hs.message = condition.message
          return hs
        end
      end
      for i, condition in ipairs(obj.status.conditions) do
        if condition.type == "Ready" and condition.status == "False" then
          hs.status = "Degraded"
          hs.message = condition.message
          return hs
        end
        if condition.type == "Ready" and condition.status == "True" then
          hs.status = "Healthy"
          hs.message = condition.message
          return hs
        end
      end
    end
  end

  hs.status = "Progressing"
  hs.message = "Waiting for Status"
  return hs  

Namespace Resource Health

Namespace Resource Actions

Suspends a Namespace when it’s Cordoned. This is only for Namespaces part of a Capsule Tenant.

resource.customizations.health.Namespace: |
  hs = {}
  local function has_managed_ownerref()
    if obj.metadata == nil or obj.metadata.ownerReferences == nil then
      return false
    end

    for _, ref in ipairs(obj.metadata.ownerReferences) do
      if ref.kind == "Tenant" and ref.apiVersion == "capsule.clastix.io/v1beta2" then
        return true
      end
    end

    return false
  end

  local labels = {}
  if obj.metadata ~= nil and obj.metadata.labels ~= nil then
    labels = obj.metadata.labels
  end

  local cordoned = labels["projectcapsule.dev/cordoned"] == "true"

  if cordoned and has_managed_ownerref() then
    hs.status = "Suspended"
    hs.message = "Namespace is cordoned (tenant-managed)"
    return hs
  end

  if obj.status ~= nil and obj.status.phase ~= nil then
    if obj.status.phase == "Active" then
      hs.status = "Healthy"
      hs.message = "Namespace is Active"
      return hs
    else
      hs.status = "Progressing"
      hs.message = "Namespace phase is " .. obj.status.phase
      return hs
    end
  end

  hs.status = "Progressing"
  hs.message = "Waiting for Namespace status"
  return hs  

CapsuleConfiguration Resource Health

Reports health based on the Ready condition, with observedGeneration staleness detection.

resource.customizations.health.capsule.clastix.io_CapsuleConfiguration: |
  hs = {}
  if obj.status == nil or obj.status.conditions == nil then
    hs.status = "Progressing"
    hs.message = "Waiting for status"
    return hs
  end

  if obj.metadata.generation ~= nil and obj.status.observedGeneration ~= nil then
    if obj.status.observedGeneration < obj.metadata.generation then
      hs.status = "Progressing"
      hs.message = "Waiting for reconciliation (generation mismatch)"
      return hs
    end
  end

  for _, condition in ipairs(obj.status.conditions) do
    if condition.type == "Ready" and condition.status == "False" then
      hs.status = "Degraded"
      hs.message = condition.message
      return hs
    end
    if condition.type == "Ready" and condition.status == "True" then
      hs.status = "Healthy"
      hs.message = condition.message
      return hs
    end
  end

  hs.status = "Progressing"
  hs.message = "Waiting for Ready condition"
  return hs  

TenantOwner Resource Health

resource.customizations.health.capsule.clastix.io_TenantOwner: |
  hs = {}
  if obj.status == nil or obj.status.conditions == nil then
    hs.status = "Progressing"
    hs.message = "Waiting for status"
    return hs
  end

  if obj.metadata.generation ~= nil and obj.status.observedGeneration ~= nil then
    if obj.status.observedGeneration < obj.metadata.generation then
      hs.status = "Progressing"
      hs.message = "Waiting for reconciliation (generation mismatch)"
      return hs
    end
  end

  for _, condition in ipairs(obj.status.conditions) do
    if condition.type == "Ready" and condition.status == "False" then
      hs.status = "Degraded"
      hs.message = condition.message
      return hs
    end
    if condition.type == "Ready" and condition.status == "True" then
      hs.status = "Healthy"
      hs.message = condition.message
      return hs
    end
  end

  hs.status = "Progressing"
  hs.message = "Waiting for Ready condition"
  return hs  

ResourcePool Resource Health

Reports Degraded when any resource is exhausted or not ready, and Healthy when the pool is active and within limits.

resource.customizations.health.capsule.clastix.io_ResourcePool: |
  hs = {}
  if obj.status == nil or obj.status.conditions == nil then
    hs.status = "Progressing"
    hs.message = "Waiting for status"
    return hs
  end

  if obj.metadata.generation ~= nil and obj.status.observedGeneration ~= nil then
    if obj.status.observedGeneration < obj.metadata.generation then
      hs.status = "Progressing"
      hs.message = "Waiting for reconciliation (generation mismatch)"
      return hs
    end
  end

  if obj.status.exhaustions ~= nil then
    local exhausted = {}
    for resource, _ in pairs(obj.status.exhaustions) do
      table.insert(exhausted, resource)
    end
    if #exhausted > 0 then
      hs.status = "Degraded"
      hs.message = "Pool exhausted for: " .. table.concat(exhausted, ", ")
      return hs
    end
  end

  for _, condition in ipairs(obj.status.conditions) do
    if condition.type == "Ready" and condition.status == "False" then
      hs.status = "Degraded"
      hs.message = condition.message
      return hs
    end
    if condition.type == "Ready" and condition.status == "True" then
      hs.status = "Healthy"
      hs.message = condition.message
      return hs
    end
  end

  hs.status = "Progressing"
  hs.message = "Waiting for Ready condition"
  return hs  

ResourcePoolClaim Resource Health

Reports Suspended when unbound (waiting for a pool), Degraded when not ready, and Healthy when bound and ready.

resource.customizations.health.capsule.clastix.io_ResourcePoolClaim: |
  hs = {}
  if obj.status == nil or obj.status.conditions == nil then
    hs.status = "Progressing"
    hs.message = "Waiting for status"
    return hs
  end

  if obj.metadata.generation ~= nil and obj.status.observedGeneration ~= nil then
    if obj.status.observedGeneration < obj.metadata.generation then
      hs.status = "Progressing"
      hs.message = "Waiting for reconciliation (generation mismatch)"
      return hs
    end
  end

  for _, condition in ipairs(obj.status.conditions) do
    if condition.type == "Bound" and condition.status == "False" then
      hs.status = "Suspended"
      hs.message = condition.message
      return hs
    end
  end

  for _, condition in ipairs(obj.status.conditions) do
    if condition.type == "Ready" and condition.status == "False" then
      hs.status = "Degraded"
      hs.message = condition.message
      return hs
    end
    if condition.type == "Ready" and condition.status == "True" then
      hs.status = "Healthy"
      hs.message = condition.message
      return hs
    end
  end

  hs.status = "Progressing"
  hs.message = "Waiting for Ready condition"
  return hs  

CustomQuota Resource Health

resource.customizations.health.capsule.clastix.io_CustomQuota: |
  hs = {}
  if obj.status == nil or obj.status.conditions == nil then
    hs.status = "Progressing"
    hs.message = "Waiting for status"
    return hs
  end

  if obj.metadata.generation ~= nil and obj.status.observedGeneration ~= nil then
    if obj.status.observedGeneration < obj.metadata.generation then
      hs.status = "Progressing"
      hs.message = "Waiting for reconciliation (generation mismatch)"
      return hs
    end
  end

  for _, condition in ipairs(obj.status.conditions) do
    if condition.type == "Ready" and condition.status == "False" then
      hs.status = "Degraded"
      hs.message = condition.message
      return hs
    end
    if condition.type == "Ready" and condition.status == "True" then
      hs.status = "Healthy"
      hs.message = condition.message
      return hs
    end
  end

  hs.status = "Progressing"
  hs.message = "Waiting for Ready condition"
  return hs  

GlobalCustomQuota Resource Health

resource.customizations.health.capsule.clastix.io_GlobalCustomQuota: |
  hs = {}
  if obj.status == nil or obj.status.conditions == nil then
    hs.status = "Progressing"
    hs.message = "Waiting for status"
    return hs
  end

  if obj.metadata.generation ~= nil and obj.status.observedGeneration ~= nil then
    if obj.status.observedGeneration < obj.metadata.generation then
      hs.status = "Progressing"
      hs.message = "Waiting for reconciliation (generation mismatch)"
      return hs
    end
  end

  for _, condition in ipairs(obj.status.conditions) do
    if condition.type == "Ready" and condition.status == "False" then
      hs.status = "Degraded"
      hs.message = condition.message
      return hs
    end
    if condition.type == "Ready" and condition.status == "True" then
      hs.status = "Healthy"
      hs.message = condition.message
      return hs
    end
  end

  hs.status = "Progressing"
  hs.message = "Waiting for Ready condition"
  return hs  

TenantResource Resource Health

resource.customizations.health.capsule.clastix.io_TenantResource: |
  hs = {}
  if obj.status == nil or obj.status.conditions == nil then
    hs.status = "Progressing"
    hs.message = "Waiting for status"
    return hs
  end

  if obj.metadata.generation ~= nil and obj.status.observedGeneration ~= nil then
    if obj.status.observedGeneration < obj.metadata.generation then
      hs.status = "Progressing"
      hs.message = "Waiting for reconciliation (generation mismatch)"
      return hs
    end
  end

  for _, condition in ipairs(obj.status.conditions) do
    if condition.type == "Ready" and condition.status == "False" then
      hs.status = "Degraded"
      hs.message = condition.message
      return hs
    end
    if condition.type == "Ready" and condition.status == "True" then
      hs.status = "Healthy"
      hs.message = condition.message
      return hs
    end
  end

  hs.status = "Progressing"
  hs.message = "Waiting for Ready condition"
  return hs  

GlobalTenantResource Resource Health

resource.customizations.health.capsule.clastix.io_GlobalTenantResource: |
  hs = {}
  if obj.status == nil or obj.status.conditions == nil then
    hs.status = "Progressing"
    hs.message = "Waiting for status"
    return hs
  end

  if obj.metadata.generation ~= nil and obj.status.observedGeneration ~= nil then
    if obj.status.observedGeneration < obj.metadata.generation then
      hs.status = "Progressing"
      hs.message = "Waiting for reconciliation (generation mismatch)"
      return hs
    end
  end

  for _, condition in ipairs(obj.status.conditions) do
    if condition.type == "Ready" and condition.status == "False" then
      hs.status = "Degraded"
      hs.message = condition.message
      return hs
    end
    if condition.type == "Ready" and condition.status == "True" then
      hs.status = "Healthy"
      hs.message = condition.message
      return hs
    end
  end

  hs.status = "Progressing"
  hs.message = "Waiting for Ready condition"
  return hs  

Capsule Proxy

The following health checks apply to Capsule Proxy CRDs.

ProxySetting Resource Health

resource.customizations.health.capsule.clastix.io_ProxySetting: |
  hs = {}
  if obj.status == nil or obj.status.conditions == nil then
    hs.status = "Progressing"
    hs.message = "Waiting for status"
    return hs
  end

  if obj.metadata.generation ~= nil and obj.status.observedGeneration ~= nil then
    if obj.status.observedGeneration < obj.metadata.generation then
      hs.status = "Progressing"
      hs.message = "Waiting for reconciliation (generation mismatch)"
      return hs
    end
  end

  for _, condition in ipairs(obj.status.conditions) do
    if condition.type == "Ready" and condition.status == "False" then
      hs.status = "Degraded"
      hs.message = condition.message
      return hs
    end
    if condition.type == "Ready" and condition.status == "True" then
      hs.status = "Healthy"
      hs.message = condition.message
      return hs
    end
  end

  hs.status = "Progressing"
  hs.message = "Waiting for Ready condition"
  return hs  

GlobalProxySettings Resource Health

resource.customizations.health.capsule.clastix.io_GlobalProxySettings: |
  hs = {}
  if obj.status == nil or obj.status.conditions == nil then
    hs.status = "Progressing"
    hs.message = "Waiting for status"
    return hs
  end

  if obj.metadata.generation ~= nil and obj.status.observedGeneration ~= nil then
    if obj.status.observedGeneration < obj.metadata.generation then
      hs.status = "Progressing"
      hs.message = "Waiting for reconciliation (generation mismatch)"
      return hs
    end
  end

  for _, condition in ipairs(obj.status.conditions) do
    if condition.type == "Ready" and condition.status == "False" then
      hs.status = "Degraded"
      hs.message = condition.message
      return hs
    end
    if condition.type == "Ready" and condition.status == "True" then
      hs.status = "Healthy"
      hs.message = condition.message
      return hs
    end
  end

  hs.status = "Progressing"
  hs.message = "Waiting for Ready condition"
  return hs  
Last modified June 5, 2026: feat: add argocd health checks (5885e74)