Skip to content

Commit

Permalink
Change statusConfig to complianceConfig in CRD, change default values…
Browse files Browse the repository at this point in the history
…, add compliance changes on relatedObjects

Signed-off-by: Jeffrey Luo <jeluo@redhat.com>
  • Loading branch information
JeffeyL committed May 29, 2024
1 parent 75726b3 commit 949034e
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 125 deletions.
37 changes: 19 additions & 18 deletions api/v1beta1/operatorpolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@ import (
policyv1 "open-cluster-management.io/config-policy-controller/api/v1"
)

// StatusConfigAction : StatusMessageOnly or NonCompliant
// +kubebuilder:validation:Enum=StatusMessageOnly;NonCompliant
type StatusConfigAction string
// ComplianceConfigAction : Compliant or NonCompliant
// +kubebuilder:validation:Enum=Compliant;NonCompliant
type ComplianceConfigAction string

// RemovalAction : Keep, Delete, or DeleteIfUnused
type RemovalAction string

const (
// StatusMessageOnly is a StatusConfigAction that only shows the status message
StatusMessageOnly StatusConfigAction = "StatusMessageOnly"
// NonCompliant is a StatusConfigAction that shows the status message and sets
// Compliant is a ComplianceConfigAction that only shows the status message and
// sets thje compliance to Compliant
Compliant ComplianceConfigAction = "Compliant"
// NonCompliant is a ComplianceConfigAction that shows the status message and sets
// the compliance to NonCompliant
NonCompliant StatusConfigAction = "NonCompliant"
NonCompliant ComplianceConfigAction = "NonCompliant"
)

const (
Expand Down Expand Up @@ -98,14 +99,14 @@ func (rb RemovalBehavior) ApplyDefaults() RemovalBehavior {
return withDefaults
}

// StatusConfig defines how resource statuses affect the OperatorPolicy status and compliance
type StatusConfig struct {
// ComplianceConfig defines how resource statuses affect the OperatorPolicy status and compliance
type ComplianceConfig struct {
// +kubebuilder:default=Compliant
CatalogSourceUnhealthy ComplianceConfigAction `json:"catalogSourceUnhealthy,omitempty"`
// +kubebuilder:default=NonCompliant
CatalogSourceUnhealthy StatusConfigAction `json:"catalogSourceUnhealthy,omitempty"`
// +kubebuilder:default=NonCompliant
DeploymentsUnavailable StatusConfigAction `json:"deploymentsUnavailable,omitempty"`
// +kubebuilder:default=NonCompliant
UpgradesAvailable StatusConfigAction `json:"upgradesAvailable,omitempty"`
DeploymentsUnavailable ComplianceConfigAction `json:"deploymentsUnavailable,omitempty"`
// +kubebuilder:default=Compliant
UpgradesAvailable ComplianceConfigAction `json:"upgradesAvailable,omitempty"`
}

// OperatorPolicySpec defines the desired state of OperatorPolicy
Expand Down Expand Up @@ -147,10 +148,10 @@ type OperatorPolicySpec struct {
UpgradeApproval string `json:"upgradeApproval"`

// +kubebuilder:default={}
// StatusConfig defines how resource statuses affect the OperatorPolicy status and compliance.
// Options include StatusMessageOnly, which does not affect compliance but reports a Status,
// and NonCompliant, which will update the OperatorPolicy compliance as well.
StatusConfig StatusConfig `json:"statusConfig,omitempty"`
// ComplianceConfig defines how resource statuses affect the OperatorPolicy status and compliance.
// Options include Compliant, which will essentially ignore NonCompliance for certain cases,
// and NonCompliant, which will report NonCompliance for those cases.
ComplianceConfig ComplianceConfig `json:"complianceConfig,omitempty"`
}

// OperatorPolicyStatus defines the observed state of OperatorPolicy
Expand Down
32 changes: 16 additions & 16 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions controllers/operatorpolicy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1356,7 +1356,9 @@ func (r *OperatorPolicyReconciler) musthaveInstallPlan(
}
}

relatedInstallPlans = append(relatedInstallPlans, existingInstallPlanObj(&ownedInstallPlans[i], phase))
complianceConfig := policy.Spec.ComplianceConfig.UpgradesAvailable
relatedInstallPlans = append(relatedInstallPlans,
existingInstallPlanObj(&ownedInstallPlans[i], phase, string(complianceConfig)))
}

if currentPlanFailed {
Expand Down Expand Up @@ -1396,8 +1398,6 @@ func (r *OperatorPolicyReconciler) musthaveInstallPlan(
// Only report this status when not approving an InstallPlan, because otherwise it could easily
// oscillate between this and another condition.
if policy.Spec.RemediationAction.IsInform() || (!initialInstall && !autoUpgrade) {
// FUTURE: check policy.spec.statusConfig.upgradesAvailable to determine `compliant`.
// For now this condition assumes it is set to 'NonCompliant'
return updateStatus(policy, installPlanUpgradeCond(allUpgradeVersions, nil), relatedInstallPlans...), nil
}

Expand Down Expand Up @@ -1680,7 +1680,8 @@ func (r *OperatorPolicyReconciler) handleDeployment(
if policy.Spec.ComplianceType.IsMustNotHave() {
relatedObjects = append(relatedObjects, foundNotApplicableObj(&dep))
} else {
relatedObjects = append(relatedObjects, existingDeploymentObj(&dep))
complianceConfig := policy.Spec.ComplianceConfig.DeploymentsUnavailable
relatedObjects = append(relatedObjects, existingDeploymentObj(&dep, string(complianceConfig)))
}
}

Expand Down Expand Up @@ -1888,8 +1889,9 @@ func (r *OperatorPolicyReconciler) musthaveCatalogSource(
isUnhealthy = (CatalogSrcState != CatalogSourceReady)
}

complianceConfig := policy.Spec.ComplianceConfig.CatalogSourceUnhealthy
changed := updateStatus(policy, catalogSourceFindCond(isUnhealthy, isMissing, catalogName),
catalogSourceObj(catalogName, catalogNS, isUnhealthy, isMissing))
catalogSourceObj(catalogName, catalogNS, isUnhealthy, isMissing, string(complianceConfig)))

return changed, nil
}
Expand Down
36 changes: 24 additions & 12 deletions controllers/operatorpolicy_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ func calculateComplianceCondition(policy *policyv1beta1.OperatorPolicy) metav1.C
}
}

modifyCompliance := policy.Spec.StatusConfig.UpgradesAvailable == "NonCompliant"
modifyCompliance := policy.Spec.ComplianceConfig.UpgradesAvailable == "NonCompliant"
idx, cond = policy.Status.GetCondition(installPlanConditionType)

if idx == -1 {
Expand Down Expand Up @@ -251,7 +251,7 @@ func calculateComplianceCondition(policy *policyv1beta1.OperatorPolicy) metav1.C
}
}

modifyCompliance = policy.Spec.StatusConfig.DeploymentsUnavailable == "NonCompliant"
modifyCompliance = policy.Spec.ComplianceConfig.DeploymentsUnavailable == "NonCompliant"
idx, cond = policy.Status.GetCondition(deploymentConditionType)

if idx == -1 {
Expand All @@ -268,7 +268,7 @@ func calculateComplianceCondition(policy *policyv1beta1.OperatorPolicy) metav1.C
}
}

modifyCompliance = policy.Spec.StatusConfig.CatalogSourceUnhealthy == "NonCompliant"
modifyCompliance = policy.Spec.ComplianceConfig.CatalogSourceUnhealthy == "NonCompliant"
idx, cond = policy.Status.GetCondition(catalogSrcConditionType)

if idx == -1 {
Expand Down Expand Up @@ -685,8 +685,6 @@ var installPlansNoApprovals = metav1.Condition{
// installPlanUpgradeCond is a NonCompliant condition with Reason 'InstallPlanRequiresApproval'
// and a message detailing which possible updates are available
func installPlanUpgradeCond(versions []string, approvableIPs []unstructured.Unstructured) metav1.Condition {
// FUTURE: check policy.spec.statusConfig.upgradesAvailable to determine `compliant`.
// For now this condition assumes it is set to 'NonCompliant'
cond := metav1.Condition{
Type: installPlanConditionType,
Status: metav1.ConditionFalse,
Expand Down Expand Up @@ -1059,7 +1057,7 @@ func noInstallPlansObj(namespace string) policyv1.RelatedObject {
// existingInstallPlanObj returns a RelatedObject for the InstallPlan, with a reason
// like 'The InstallPlan is ____' based on the phase. When the InstallPlan is in phase
// 'Complete', the object will be Compliant, otherwise it will be NonCompliant.
func existingInstallPlanObj(ip client.Object, phase string) policyv1.RelatedObject {
func existingInstallPlanObj(ip client.Object, phase string, complianceConfig string) policyv1.RelatedObject {
relObj := policyv1.RelatedObject{
Object: policyv1.ObjectResourceFromObj(ip),
Properties: &policyv1.ObjectProperties{
Expand All @@ -1075,9 +1073,12 @@ func existingInstallPlanObj(ip client.Object, phase string) policyv1.RelatedObje

switch phase {
case string(operatorv1alpha1.InstallPlanPhaseRequiresApproval):
// FUTURE: check policy.spec.statusConfig.upgradesAvailable to determine `compliant`.
// For now, assume it is set to 'NonCompliant'
relObj.Compliant = string(policyv1.NonCompliant)
// Check policy.spec.statusConfig.upgradesAvailable to determine `compliant`.
if complianceConfig != string(policyv1.Compliant) {
relObj.Compliant = string(policyv1.NonCompliant)
} else {
relObj.Compliant = string(policyv1.Compliant)
}
case string(operatorv1alpha1.InstallPlanPhaseComplete):
relObj.Compliant = string(policyv1.Compliant)
default:
Expand Down Expand Up @@ -1170,13 +1171,15 @@ var noExistingCRDObj = policyv1.RelatedObject{

// existingDeploymentObj returns a RelatedObject for a Deployment, which will
// be Compliant if there are no unavailable replicas on the deployment.
func existingDeploymentObj(dep *appsv1.Deployment) policyv1.RelatedObject {
func existingDeploymentObj(dep *appsv1.Deployment, complianceConfig string) policyv1.RelatedObject {
compliance := policyv1.NonCompliant
reason := "Deployment Unavailable"

if dep.Status.UnavailableReplicas == 0 {
compliance = policyv1.Compliant
reason = "Deployment Available"
} else if complianceConfig == string(policyv1.Compliant) {
compliance = policyv1.Compliant
}

return policyv1.RelatedObject{
Expand Down Expand Up @@ -1204,12 +1207,21 @@ var noExistingDeploymentObj = policyv1.RelatedObject{

// catalogSourceObj returns a conditionally compliant RelatedObject with reason based on the
// `isUnhealthy` and `isMissing` parameters
func catalogSourceObj(catalogName string, catalogNS string, isUnhealthy bool, isMissing bool) policyv1.RelatedObject {
func catalogSourceObj(
catalogName string,
catalogNS string,
isUnhealthy bool,
isMissing bool,
complianceConfig string,
) policyv1.RelatedObject {
compliance := string(policyv1.Compliant)
reason := reasonWantFoundExists

if isUnhealthy {
compliance = string(policyv1.NonCompliant)
if complianceConfig != string(policyv1.Compliant) {
compliance = string(policyv1.NonCompliant)
}

reason = reasonWantFoundExists + " but is unhealthy"
}

Expand Down
Loading

0 comments on commit 949034e

Please sign in to comment.