Skip to content

Commit

Permalink
Merge pull request #46 from controlplaneio-fluxcd/flux-report
Browse files Browse the repository at this point in the history
Implement reporting for Flux installation status and statistics
  • Loading branch information
stefanprodan authored Jun 21, 2024
2 parents aca33f2 + 8add4c8 commit 7fe2562
Show file tree
Hide file tree
Showing 31 changed files with 1,956 additions and 13 deletions.
9 changes: 9 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,13 @@ resources:
kind: FluxInstance
path: github.com/controlplaneio-fluxcd/flux-operator/api/v1
version: v1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: controlplane.io
group: fluxcd
kind: FluxReport
path: github.com/controlplaneio-fluxcd/flux-operator/api/v1
version: v1
version: "3"
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ the lifecycle of CNCF [Flux CD](https://fluxcd.io) and the
- Automates the patching of hotfixes and CVEs affecting the Flux controllers container images.
- Simplifies the configuration of multi-tenancy lockdown on shared Kubernetes clusters.
- Allows syncing the cluster state from Git repositories, OCI artifacts and S3-compatible storage.
- Generates detailed reports about the Flux deployment readiness status and reconcilers statistics.
- Provides a security-first approach to the Flux deployment and FIPS compliance.
- Incorporates best practices for running Flux at scale with persistent storage and vertical scaling.
- Manages the update of Flux custom resources and prevents disruption during the upgrade process.
Expand All @@ -32,6 +33,7 @@ the lifecycle of CNCF [Flux CD](https://fluxcd.io) and the

- [Flux operator installation](https://fluxcd.control-plane.io/operator/install/)
- [Flux controllers configuration](https://fluxcd.control-plane.io/operator/flux-config/)
- [Flux instance customization](https://fluxcd.control-plane.io/operator/flux-kustomize/)
- [Cluster sync configuration](https://fluxcd.control-plane.io/operator/flux-sync/)
- [Migration of bootstrapped clusters](https://fluxcd.control-plane.io/operator/flux-bootstrap-migration/)
- [FluxInstance API reference](https://fluxcd.control-plane.io/operator/fluxinstance/)
Expand All @@ -55,7 +57,7 @@ helm install flux-operator oci://ghcr.io/controlplaneio-fluxcd/charts/flux-opera
### Install the Flux Controllers

Create a [FluxInstance](https://fluxcd.control-plane.io/operator/fluxinstance/) resource
in the `flux-system` namespace to install the latest Flux stable version:
named `flux` in the `flux-system` namespace to install the latest Flux stable version:

```yaml
apiVersion: fluxcd.controlplane.io/v1
Expand Down Expand Up @@ -136,6 +138,20 @@ flux create secret git flux-system \
> container registries and S3-compatible storage, refer to the
> [cluster sync guide](https://fluxcd.control-plane.io/operator/flux-sync/).

### Monitor the Flux Installation

To monitor the Flux deployment status, check the
[FluxReport](https://fluxcd.control-plane.io/operator/fluxreport/)
resource in the `flux-system` namespace:

```shell
kubectl get fluxreport/flux -n flux-system -o yaml
```

The report is update at regular intervals and contains information about the deployment
readiness status, the distribution details, reconcilers statistics, Flux CRDs versions,
the cluster sync status and more.

## License

The Flux Operator is an open-source project licensed under the
Expand Down
8 changes: 5 additions & 3 deletions api/v1/fluxinstance_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ import (
)

const (
FluxInstanceKind = "FluxInstance"
EnabledValue = "enabled"
DisabledValue = "disabled"
DefaultInstanceName = "flux"
DefaultNamespace = "flux-system"
FluxInstanceKind = "FluxInstance"
EnabledValue = "enabled"
DisabledValue = "disabled"
)

var (
Expand Down
211 changes: 211 additions & 0 deletions api/v1/fluxreport_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
// Copyright 2024 Stefan Prodan.
// SPDX-License-Identifier: AGPL-3.0

package v1

import (
"strings"
"time"

"github.com/fluxcd/pkg/apis/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const FluxReportKind = "FluxReport"

// FluxReportSpec defines the observed state of a Flux installation.
type FluxReportSpec struct {
// Distribution is the version information of the Flux installation.
// +required
Distribution FluxDistributionStatus `json:"distribution"`

// ComponentsStatus is the status of the Flux controller deployments.
// +optional
ComponentsStatus []FluxComponentStatus `json:"components,omitempty"`

// ReconcilersStatus is the list of Flux reconcilers and
// their statistics grouped by API kind.
// +optional
ReconcilersStatus []FluxReconcilerStatus `json:"reconcilers,omitempty"`

// SyncStatus is the status of the cluster sync
// Source and Kustomization resources.
// +optional
SyncStatus *FluxSyncStatus `json:"sync,omitempty"`
}

// FluxDistributionStatus defines the version information of the Flux instance.
type FluxDistributionStatus struct {
// Entitlement is the entitlement verification status.
// +required
Entitlement string `json:"entitlement"`

// Status is a human-readable message indicating details
// about the distribution observed state.
// +required
Status string `json:"status"`

// Version is the version of the Flux instance.
// +optional
Version string `json:"version,omitempty"`

// ManagedBy is the name of the operator managing the Flux instance.
// +optional
ManagedBy string `json:"managedBy,omitempty"`
}

// FluxComponentStatus defines the observed state of a Flux component.
type FluxComponentStatus struct {
// Name is the name of the Flux component.
// +required
Name string `json:"name"`

// Ready is the readiness status of the Flux component.
// +required
Ready bool `json:"ready"`

// Status is a human-readable message indicating details
// about the Flux component observed state.
// +required
Status string `json:"status"`

// Image is the container image of the Flux component.
// +required
Image string `json:"image"`
}

// FluxReconcilerStatus defines the observed state of a Flux reconciler.
type FluxReconcilerStatus struct {
// APIVersion is the API version of the Flux resource.
// +required
APIVersion string `json:"apiVersion"`

// Kind is the kind of the Flux resource.
// +required
Kind string `json:"kind"`

// Stats is the reconcile statics of the Flux resource kind.
// +optional
Stats FluxReconcilerStats `json:"stats,omitempty"`
}

// FluxReconcilerStats defines the reconcile statistics.
type FluxReconcilerStats struct {
// Running is the number of reconciled
// resources in the Running state.
// +required
Running int `json:"running"`

// Failing is the number of reconciled
// resources in the Failing state.
// +required
Failing int `json:"failing"`

// Suspended is the number of reconciled
// resources in the Suspended state.
// +required
Suspended int `json:"suspended"`

// TotalSize is the total size of the artifacts in storage.
// +optional
TotalSize string `json:"totalSize,omitempty"`
}

// FluxSyncStatus defines the observed state of the cluster sync.
type FluxSyncStatus struct {
// ID is the identifier of the sync.
// +required
ID string `json:"id"`

// Path is the kustomize path of the sync.
// +optional
Path string `json:"path,omitempty"`

// Ready is the readiness status of the sync.
// +required
Ready bool `json:"ready"`

// Status is a human-readable message indicating details
// about the sync observed state.
// +required
Status string `json:"status"`

// Source is the URL of the source repository.
// +optional
Source string `json:"source,omitempty"`
}

// FluxReportStatus defines the readiness of a FluxReport.
type FluxReportStatus struct {
meta.ReconcileRequestStatus `json:",inline"`

// Conditions contains the readiness conditions of the object.
// +optional
Conditions []metav1.Condition `json:"conditions,omitempty"`
}

// +kubebuilder:storageversion
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Entitlement",type="string",JSONPath=".spec.distribution.entitlement",description="",priority=10
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description=""
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description=""
// +kubebuilder:printcolumn:name="LastUpdated",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].lastTransitionTime",description=""

// FluxReport is the Schema for the fluxreports API.
type FluxReport struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec FluxReportSpec `json:"spec,omitempty"`
Status FluxReportStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// FluxReportList contains a list of FluxReport.
type FluxReportList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []FluxReport `json:"items"`
}

// GetConditions returns the status conditions of the object.
func (in *FluxReport) GetConditions() []metav1.Condition {
return in.Status.Conditions
}

// SetConditions sets the status conditions on the object.
func (in *FluxReport) SetConditions(conditions []metav1.Condition) {
in.Status.Conditions = conditions
}

// IsDisabled returns true if the object has the reconcile annotation set to 'disabled'.
func (in *FluxReport) IsDisabled() bool {
val, ok := in.GetAnnotations()[ReconcileAnnotation]
return ok && strings.ToLower(val) == DisabledValue
}

// GetInterval returns the interval at which the object should be reconciled.
// If no interval is set, the default is 10 minutes.
func (in *FluxReport) GetInterval() time.Duration {
val, ok := in.GetAnnotations()[ReconcileAnnotation]
if ok && strings.ToLower(val) == DisabledValue {
return 0
}
defaultInterval := 10 * time.Minute
val, ok = in.GetAnnotations()[ReconcileEveryAnnotation]
if !ok {
return defaultInterval
}
interval, err := time.ParseDuration(val)
if err != nil {
return defaultInterval
}
return interval
}

func init() {
SchemeBuilder.Register(&FluxReport{}, &FluxReportList{})
}
Loading

0 comments on commit 7fe2562

Please sign in to comment.