github.com/argoproj/argo-cd/v3@v3.2.1/resource_customizations/promoter.argoproj.io/PromotionStrategy/health.lua (about)

     1  local hs = {}
     2  hs.status = "Progressing"
     3  hs.message = "Initializing promotion strategy"
     4  
     5  -- Check for deletion timestamp
     6  if obj.metadata.deletionTimestamp then
     7      hs.status = "Progressing"
     8      hs.message = "Promotion strategy is being deleted"
     9      return hs
    10  end
    11  
    12  -- Check if status exists
    13  if not obj.status then
    14      return hs
    15  end
    16  
    17  -- Check for reconciliation conditions
    18  local hasReadyCondition = false
    19  if obj.status.conditions then
    20      for _, condition in ipairs(obj.status.conditions) do
    21          if condition.type == "Ready" then
    22              hasReadyCondition = true
    23              -- Check observedGeneration vs metadata.generation within the reconciliation condition
    24              if condition.observedGeneration and obj.metadata.generation and condition.observedGeneration ~= obj.metadata.generation then
    25                  hs.status = "Progressing"
    26                  hs.message = "Waiting for promotion strategy spec update to be observed"
    27                  return hs
    28              end
    29              -- Check for any False condition status
    30              if condition.status == "False" then
    31                  hs.status = "Degraded"
    32                  local msg = condition.message or "Unknown error"
    33                  local reason = condition.reason or "Unknown"
    34                  -- Don't include ReconciliationError in the message since it's redundant
    35                  if reason == "ReconciliationError" then
    36                      hs.message = "Promotion strategy reconciliation failed: " .. msg
    37                  else
    38                      hs.message = "Promotion strategy reconciliation failed (" .. reason .. "): " .. msg
    39                  end
    40                  return hs
    41              end
    42          end
    43      end
    44  end
    45  
    46  -- If no Ready condition is found, return Progressing status
    47  if not hasReadyCondition then
    48      hs.status = "Progressing"
    49      hs.message = "Promotion strategy is not ready yet"
    50      return hs
    51  end
    52  
    53  if not obj.status.environments or #obj.status.environments == 0 then
    54      hs.status = "Degraded"
    55      hs.message = "Promotion strategy has no environments configured"
    56      return hs
    57  end
    58  
    59  -- Make sure there's a fully-populated status for both active and proposed commits in all environments. If anything is
    60  -- missing or empty, return a Progressing status.
    61  for _, env in ipairs(obj.status.environments) do
    62      if not env.active or not env.active.dry or not env.active.dry.sha or env.active.dry.sha == "" then
    63          hs.status = "Progressing"
    64          hs.message = "The active commit DRY SHA is missing or empty in environment '" .. env.branch .. "'."
    65          return hs
    66      end
    67      if not env.proposed or not env.proposed.dry or not env.proposed.dry.sha or env.proposed.dry.sha == "" then
    68          hs.status = "Progressing"
    69          hs.message = "The proposed commit DRY SHA is missing or empty in environment '" .. env.branch .. "'."
    70          return hs
    71      end
    72  end
    73  
    74  -- Check if all the proposed environments have the same proposed commit dry sha. If not, return a Progressing status.
    75  local proposedSha = obj.status.environments[1].proposed.dry.sha  -- Don't panic, Lua is 1-indexed.
    76  for _, env in ipairs(obj.status.environments) do
    77      if env.proposed.dry.sha ~= proposedSha then
    78          hs.status = "Progressing"
    79          hs.message = "Not all environments have the same proposed commit SHA. This likely means the hydrator has not run for all environments yet."
    80          return hs
    81      end
    82  end
    83  
    84  -- Helper function to get short SHA
    85  local function getShortSha(sha)
    86      if not sha or sha == "" then
    87          return ""
    88      end
    89      if string.len(sha) > 7 then
    90          return string.sub(sha, 1, 7)
    91      end
    92      return sha
    93  end
    94  
    95  -- Find the first environment with a proposed commit dry sha that doesn't match the active one. Loop over its commit
    96  -- statuses and build a summary about how many are pending, successful, or failed. Return a Progressing status for this
    97  -- in-progress environment.
    98  for _, env in ipairs(obj.status.environments) do
    99      if env.proposed.dry.sha ~= env.active.dry.sha then
   100          local pendingCount = 0
   101          local successCount = 0
   102          local failureCount = 0
   103          local pendingKeys = {}
   104          local failedKeys = {}
   105  
   106          -- pending, success, and failure are the only possible values
   107          -- https://github.com/argoproj-labs/gitops-promoter/blob/c58d55ef52f86ff84e4f8fa35d2edba520886e3b/api/v1alpha1/commitstatus_types.go#L44
   108          for _, status in ipairs(env.proposed.commitStatuses or {}) do
   109              if status.phase == "pending" then
   110                  pendingCount = pendingCount + 1
   111                  table.insert(pendingKeys, status.key)
   112              elseif status.phase == "success" then
   113                  successCount = successCount + 1
   114              elseif status.phase == "failure" then
   115                  failureCount = failureCount + 1
   116                  table.insert(failedKeys, status.key)
   117              end
   118          end
   119  
   120          hs.status = "Progressing"
   121          hs.message =
   122              "Promotion in progress for environment '" .. env.branch ..
   123              "' from '" .. getShortSha(env.active.dry.sha) ..
   124              "' to '" .. getShortSha(env.proposed.dry.sha) .. "': " ..
   125              pendingCount .. " pending, " .. successCount .. " successful, " .. failureCount .. " failed. "
   126  
   127          if pendingCount > 0 then
   128              hs.message = hs.message .. "Pending commit statuses: " .. table.concat(pendingKeys, ", ") .. ". "
   129          end
   130          if failureCount > 0 then
   131              hs.message = hs.message .. "Failed commit statuses: " .. table.concat(failedKeys, ", ") .. ". "
   132          end
   133          return hs
   134      end
   135  end
   136  
   137  -- Check all environments for active commit statuses that aren't successful. For each environment with a non-successful
   138  -- commit status, get a count of how many aren't successful. Write a summary of non-successful environments.
   139  local nonSuccessfulEnvironments = {}
   140  for _, env in ipairs(obj.status.environments) do
   141      local pendingCount = 0
   142      local failureCount = 0
   143  
   144      for _, status in ipairs(env.active.commitStatuses or {}) do
   145          if status.phase == "pending" then
   146              pendingCount = pendingCount + 1
   147          elseif status.phase == "failure" then
   148              failureCount = failureCount + 1
   149          end
   150      end
   151  
   152      if pendingCount > 0 or failureCount > 0 then
   153          nonSuccessfulEnvironments[env.branch] = {
   154              pending = pendingCount,
   155              failure = failureCount,
   156          }
   157      end
   158  end
   159  
   160  if next(nonSuccessfulEnvironments) then
   161      local envMessages = {}
   162      for branch, counts in pairs(nonSuccessfulEnvironments) do
   163          local msg = branch .. " (" .. counts.failure .. " failed, " .. counts.pending .. " pending)"
   164          table.insert(envMessages, msg)
   165      end
   166      hs.status = "Healthy"
   167      hs.message = "Environments are up-to-date, but some environments have non-successful commit statuses: " .. table.concat(envMessages, ", ") .. "."
   168      return hs
   169  end
   170  
   171  
   172  -- If all environments have the same proposed commit dry sha as the active one, we can consider the promotion strategy
   173  -- healthy. This means all environments are in sync and no further action is needed.
   174  hs.status = "Healthy"
   175  hs.message = "All environments are up-to-date on commit '" .. getShortSha(obj.status.environments[1].proposed.dry.sha) .. "'."
   176  return hs