Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement new ComplianceConfig field #252

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 33 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
// the compliance to NonCompliant
NonCompliant StatusConfigAction = "NonCompliant"
// Compliant is a ComplianceConfigAction that only shows the status message and
// does not affect the overall compliance
Compliant ComplianceConfigAction = "Compliant"
// NonCompliant is a ComplianceConfigAction that shows the status message and sets
// the overall compliance when the condition is met
NonCompliant ComplianceConfigAction = "NonCompliant"
)

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

// StatusConfig defines how resource statuses affect the OperatorPolicy status and compliance
type StatusConfig struct {
CatalogSourceUnhealthy StatusConfigAction `json:"catalogSourceUnhealthy,omitempty"`
DeploymentsUnavailable StatusConfigAction `json:"deploymentsUnavailable,omitempty"`
UpgradesAvailable StatusConfigAction `json:"upgradesAvailable,omitempty"`
UpgradesProgressing StatusConfigAction `json:"upgradesProgressing,omitempty"`
// ComplianceConfig defines how resource statuses affect the OperatorPolicy compliance
type ComplianceConfig struct {
//+kubebuilder:default=Compliant
// Specifies how the CatalogSourceUnhealthy typed condition should affect
// overall policy compliance. Defaults to 'Compliant'
CatalogSourceUnhealthy ComplianceConfigAction `json:"catalogSourceUnhealthy,omitempty"`
mprahl marked this conversation as resolved.
Show resolved Hide resolved
//+kubebuilder:default=NonCompliant
// Specifies how the DeploymentCompliant typed condition should affect
// overall policy compliance. Defaults to 'NonCompliant'
DeploymentsUnavailable ComplianceConfigAction `json:"deploymentsUnavailable,omitempty"`
//+kubebuilder:default=Compliant
// Specifies how the InstallPlanCompliant typed condition should affect
// overall policy compliance. Defaults to 'Compliant'
UpgradesAvailable ComplianceConfigAction `json:"upgradesAvailable,omitempty"`
}

// OperatorPolicySpec defines the desired state of OperatorPolicy
Expand All @@ -115,15 +124,15 @@ type OperatorPolicySpec struct {
// Include the name, namespace, and any `spec` fields for the OperatorGroup.
// For more info, see `kubectl explain operatorgroup.spec` or
// https://olm.operatorframework.io/docs/concepts/crds/operatorgroup/
// +kubebuilder:pruning:PreserveUnknownFields
// +optional
//+kubebuilder:pruning:PreserveUnknownFields
//+optional
OperatorGroup *runtime.RawExtension `json:"operatorGroup,omitempty"`

// Include the namespace, and any `spec` fields for the Subscription.
// For more info, see `kubectl explain subscription.spec` or
// https://olm.operatorframework.io/docs/concepts/crds/subscription/
// +kubebuilder:validation:Required
// +kubebuilder:pruning:PreserveUnknownFields
//+kubebuilder:validation:Required
//+kubebuilder:pruning:PreserveUnknownFields
Subscription runtime.RawExtension `json:"subscription"`

// Versions is a list of nonempty strings that specifies which installed versions are compliant when
Expand All @@ -143,6 +152,12 @@ type OperatorPolicySpec struct {
// approval is not affected by this setting. This setting has no effect when the policy is in
// 'mustnothave' mode. Allowed values are "None" or "Automatic".
UpgradeApproval string `json:"upgradeApproval"`

//+kubebuilder:default={}
// ComplianceConfig defines how resource statuses affect the OperatorPolicy status and compliance.
// When set to Compliant, the condition does not impact the OperatorPolicy compliance.
// When set to NonCompliant, the condition causes the OperatorPolicy to become NonCompliant.
ComplianceConfig ComplianceConfig `json:"complianceConfig,omitempty"`
}

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

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

27 changes: 17 additions & 10 deletions controllers/operatorpolicy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,7 @@ func (r *OperatorPolicyReconciler) musthaveInstallPlan(
ipsRequiringApproval := make([]unstructured.Unstructured, 0)
anyInstalling := false
currentPlanFailed := false
complianceConfig := policy.Spec.ComplianceConfig.UpgradesAvailable

// Construct the relevant relatedObjects, and collect any that might be considered for approval
for i, installPlan := range ownedInstallPlans {
Expand Down Expand Up @@ -1356,7 +1357,8 @@ func (r *OperatorPolicyReconciler) musthaveInstallPlan(
}
}

relatedInstallPlans = append(relatedInstallPlans, existingInstallPlanObj(&ownedInstallPlans[i], phase))
relatedInstallPlans = append(relatedInstallPlans,
existingInstallPlanObj(&ownedInstallPlans[i], phase, complianceConfig))
}

if currentPlanFailed {
Expand Down Expand Up @@ -1396,9 +1398,8 @@ 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
return updateStatus(policy, installPlanUpgradeCond(complianceConfig, allUpgradeVersions, nil),
relatedInstallPlans...), nil
}

approvedVersion := "" // this will only be accurate when there is only one approvable InstallPlan
Expand Down Expand Up @@ -1446,8 +1447,11 @@ func (r *OperatorPolicyReconciler) musthaveInstallPlan(
}

if len(approvableInstallPlans) != 1 {
changed := updateStatus(policy,
installPlanUpgradeCond(allUpgradeVersions, approvableInstallPlans), relatedInstallPlans...)
changed := updateStatus(
policy,
installPlanUpgradeCond(complianceConfig, allUpgradeVersions, approvableInstallPlans),
mprahl marked this conversation as resolved.
Show resolved Hide resolved
relatedInstallPlans...,
)

return changed, nil
}
Expand Down Expand Up @@ -1644,6 +1648,7 @@ func (r *OperatorPolicyReconciler) handleDeployment(
var relatedObjects []policyv1.RelatedObject
var unavailableDeployments []appsv1.Deployment

complianceConfig := policy.Spec.ComplianceConfig.DeploymentsUnavailable
depNum := 0

for _, dep := range csv.Spec.InstallStrategy.StrategySpec.DeploymentSpecs {
Expand Down Expand Up @@ -1680,15 +1685,16 @@ func (r *OperatorPolicyReconciler) handleDeployment(
if policy.Spec.ComplianceType.IsMustNotHave() {
relatedObjects = append(relatedObjects, foundNotApplicableObj(&dep))
} else {
relatedObjects = append(relatedObjects, existingDeploymentObj(&dep))
relatedObjects = append(relatedObjects, existingDeploymentObj(&dep, complianceConfig))
}
}

if policy.Spec.ComplianceType.IsMustNotHave() {
return updateStatus(policy, notApplicableCond("Deployment"), relatedObjects...), nil
}

return updateStatus(policy, buildDeploymentCond(depNum > 0, unavailableDeployments), relatedObjects...), nil
return updateStatus(policy, buildDeploymentCond(complianceConfig, depNum > 0, unavailableDeployments),
relatedObjects...), nil
}

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

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

return changed, nil
}
Expand Down
Loading