@@ -109,3 +109,90 @@ clusterSelector:
109109 clusterGroup: {{ $g .name }}
110110{{- end -}}
111111{{- end -}} {{- /* acm.app.clusterSelector */ }}
112+
113+ {{/*
114+ Subscription health check Lua script for ArgoCD resource health checks
115+ */ }}
116+ {{- define " acm.subscription.healthcheck.lua" -}}
117+ local health_status = {}
118+ if obj.status ~= nil then
119+ if obj.status.conditions ~= nil then
120+ local numDegraded = 0
121+ local numPending = 0
122+ local msg = " "
123+
124+ -- Check if this is a manual approval scenario where InstallPlanPending is expected
125+ -- and the operator is already installed (upgrade pending, not initial install)
126+ local isManualApprovalPending = false
127+ if obj.spec ~= nil and obj.spec.installPlanApproval == " Manual" then
128+ for _, condition in pairs(obj.status.conditions ) do
129+ if condition.type == " InstallPlanPending" and condition.status == " True" and condition.reason == " RequiresApproval" then
130+ -- Only treat as expected healthy state if the operator is already installed
131+ -- (installedCSV is present), meaning this is an upgrade pending approval
132+ if obj.status.installedCSV ~= nil then
133+ isManualApprovalPending = true
134+ end
135+ break
136+ end
137+ end
138+ end
139+
140+ for i, condition in pairs(obj.status.conditions ) do
141+ -- Skip InstallPlanPending condition when manual approval is pending (expected behavior)
142+ if isManualApprovalPending and condition.type == " InstallPlanPending" then
143+ -- Do not include in message or count as pending
144+ else
145+ msg = msg .. i .. " : " .. condition.type .. " | " .. condition.status .. " \n "
146+ if condition.type == " InstallPlanPending" and condition.status == " True" then
147+ numPending = numPending + 1
148+ elseif (condition.type == " InstallPlanMissing" and condition.reason ~= " ReferencedInstallPlanNotFound" ) then
149+ numDegraded = numDegraded + 1
150+ elseif (condition.type == " CatalogSourcesUnhealthy" or condition.type == " InstallPlanFailed" or condition.type == " ResolutionFailed" ) and condition.status == " True" then
151+ numDegraded = numDegraded + 1
152+ end
153+ end
154+ end
155+
156+ -- Available states: undef/nil , UpgradeAvailable, UpgradePending, UpgradeFailed, AtLatestKnown
157+ -- Source: https://github.com /openshift/operator-framework-olm/blob/5e2c73b7663d0122c9dc3e59ea39e515a31e2719/staging/api/pkg/operators/v1alpha1/subscription_types.go #L17-L23
158+ if obj.status.state == nil then
159+ numPending = numPending + 1
160+ msg = msg .. " .status.state not yet known\n "
161+ elseif obj.status.state == " " or obj.status.state == " UpgradeAvailable" then
162+ numPending = numPending + 1
163+ msg = msg .. " .status.state is '" .. obj.status.state .. " '\n "
164+ elseif obj.status.state == " UpgradePending" then
165+ -- UpgradePending with manual approval is expected behavior, treat as healthy
166+ if isManualApprovalPending then
167+ msg = msg .. " .status.state is 'AtLatestKnown'\n "
168+ else
169+ numPending = numPending + 1
170+ msg = msg .. " .status.state is '" .. obj.status.state .. " '\n "
171+ end
172+ elseif obj.status.state == " UpgradeFailed" then
173+ numDegraded = numDegraded + 1
174+ msg = msg .. " .status.state is '" .. obj.status.state .. " '\n "
175+ else
176+ -- Last possiblity of .status.state : AtLatestKnown
177+ msg = msg .. " .status.state is '" .. obj.status.state .. " '\n "
178+ end
179+
180+ if numDegraded == 0 and numPending == 0 then
181+ health_status.status = " Healthy"
182+ health_status.message = msg
183+ return health_status
184+ elseif numPending > 0 and numDegraded == 0 then
185+ health_status.status = " Progressing"
186+ health_status.message = msg
187+ return health_status
188+ else
189+ health_status.status = " Degraded"
190+ health_status.message = msg
191+ return health_status
192+ end
193+ end
194+ end
195+ health_status.status = " Progressing"
196+ health_status.message = " An install plan for a subscription is pending installation"
197+ return health_status
198+ {{- end }} {{- /* acm.subscription.healthcheck.lua */ }}
0 commit comments