Skip to content

Commit

Permalink
Add computing intermediate Explorer object statuses.
Browse files Browse the repository at this point in the history
Add `SuspendableAdapter` for computing the `Suspended` object status.

Update status and message tests for `FluxObject`.

Add UI icons for indicating Explorer object statuses.

Remove empty lines for consistency.
  • Loading branch information
opudrovs committed Dec 7, 2023
1 parent c94cfc7 commit 5eaeaeb
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 35 deletions.
4 changes: 2 additions & 2 deletions pkg/query/configuration/fluxobject_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import (
"github.com/fluxcd/helm-controller/api/v2beta1"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func TestStatusAndMessage(t *testing.T) {

tests := []struct {
name string
desiredStatus ObjectStatus
desiredMessage string
obj FluxObject
obj client.Object
}{
{
name: "HelmRelease with Ready condition",
Expand Down
109 changes: 86 additions & 23 deletions pkg/query/configuration/objectkind.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,12 @@ type ObjectKind struct {
type ObjectStatus string

const (
Success ObjectStatus = "Success"
Failed ObjectStatus = "Failed"
NoStatus ObjectStatus = "-"
Success ObjectStatus = "Success"
Failed ObjectStatus = "Failed"
Reconciling ObjectStatus = "Reconciling"
Suspended ObjectStatus = "Suspended"
PendingAction ObjectStatus = "PendingAction"
NoStatus ObjectStatus = "-"
)

func (ok ObjectKind) String() string {
Expand Down Expand Up @@ -101,11 +104,6 @@ func (o ObjectKind) Validate() error {
return nil
}

type FluxObject interface {
client.Object
GetConditions() []metav1.Condition
}

var (
HelmReleaseObjectKind = ObjectKind{
Gvk: helmv2beta1.GroupVersion.WithKind(helmv2beta1.HelmReleaseKind),
Expand Down Expand Up @@ -348,15 +346,29 @@ func defaultFluxObjectStatusFunc(obj client.Object) ObjectStatus {
return Failed
}

if fo.GetSuspended() {
return Suspended
}

for _, c := range fo.GetConditions() {
if ObjectStatus(c.Type) == NoStatus {
return NoStatus
}

if c.Type == "Ready" || c.Type == "Available" {
if c.Status == "True" {
return Success
}

if c.Status == "Unknown" {
if c.Reason == "Progressing" {
return Reconciling
}
if c.Reason == "TerraformPlannedWithChanges" {
return PendingAction
}
}

return Failed
}
}
Expand All @@ -380,35 +392,86 @@ func defaultFluxObjectMessageFunc(obj client.Object) string {
return ""
}

type AutomatedClusterDiscoveryAdaptor struct {
type FluxObject interface {
client.Object
GetConditions() []metav1.Condition
GetSuspended() bool
}

func (a *AutomatedClusterDiscoveryAdaptor) GetConditions() []metav1.Condition {
acd := a.Object.(*clusterreflectorv1alpha1.AutomatedClusterDiscovery)
return acd.Status.Conditions
type SuspendableAdapter struct {
client.Object
}

func ToFluxObject(obj client.Object) (FluxObject, error) {
switch t := obj.(type) {
func (o *SuspendableAdapter) GetConditions() []metav1.Condition {
switch t := o.Object.(type) {
case *helmv2beta1.HelmRelease:
return t, nil
return t.GetConditions()
case *kustomizev1.Kustomization:
return t, nil
return t.GetConditions()
case *sourcev1beta2.HelmRepository:
return t, nil
return t.GetConditions()
case *sourcev1beta2.HelmChart:
return t, nil
return t.GetConditions()
case *sourcev1beta2.Bucket:
return t, nil
return t.GetConditions()
case *sourcev1.GitRepository:
return t, nil
return t.GetConditions()
case *sourcev1beta2.OCIRepository:
return t, nil
return t.GetConditions()
case *gitopssets.GitOpsSet:
return t, nil
return t.GetConditions()
default:
return nil
}
}

func (a *SuspendableAdapter) GetSuspended() bool {
switch t := a.Object.(type) {
case *helmv2beta1.HelmRelease:
return t.Spec.Suspend
case *kustomizev1.Kustomization:
return t.Spec.Suspend
case *sourcev1beta2.HelmRepository:
return t.Spec.Suspend
case *sourcev1beta2.HelmChart:
return t.Spec.Suspend
case *sourcev1beta2.Bucket:
return t.Spec.Suspend
case *sourcev1.GitRepository:
return t.Spec.Suspend
case *sourcev1beta2.OCIRepository:
return t.Spec.Suspend
case *gitopssets.GitOpsSet:
return t.Spec.Suspend
case *clusterreflectorv1alpha1.AutomatedClusterDiscovery:
return t.Spec.Suspend
default:
return false
}
}

type AutomatedClusterDiscoveryAdapter struct {
client.Object
}

func (a *AutomatedClusterDiscoveryAdapter) GetConditions() []metav1.Condition {
acd := a.Object.(*clusterreflectorv1alpha1.AutomatedClusterDiscovery)
return acd.Status.Conditions
}

func ToFluxObject(obj client.Object) (FluxObject, error) {
switch t := obj.(type) {
case *helmv2beta1.HelmRelease,
*kustomizev1.Kustomization,
*sourcev1beta2.HelmRepository,
*sourcev1beta2.HelmChart,
*sourcev1beta2.Bucket,
*sourcev1.GitRepository,
*sourcev1beta2.OCIRepository,
*gitopssets.GitOpsSet:
return &SuspendableAdapter{Object: t}, nil
case *clusterreflectorv1alpha1.AutomatedClusterDiscovery:
return &AutomatedClusterDiscoveryAdaptor{Object: t}, nil
return &SuspendableAdapter{Object: &AutomatedClusterDiscoveryAdapter{Object: t}}, nil
}

return nil, fmt.Errorf("unknown object type: %T", obj)
Expand Down
1 change: 0 additions & 1 deletion pkg/query/configuration/objectkind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
// like being in the expected flux api version. For example, flux v1 available
// kinds should be using v1 api version
func TestObjectsKinds(t *testing.T) {

g := NewWithT(t)

t.Run("should contain v1 kustomizations", func(t *testing.T) {
Expand Down
61 changes: 52 additions & 9 deletions ui/src/components/Explorer/ExplorerTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,9 @@ export const defaultExplorerFields: ExplorerField[] = [
<Box marginRight={1}>
<Icon
size={24}
color={
o?.status === 'Success' ? 'successOriginal' : 'alertOriginal'
}
type={
o?.status === 'Success'
? IconType.SuccessIcon
: IconType.ErrorIcon
}
{...getIndicatorInfo(o?.status)}
/>
</Box>

{o?.status}
</Flex>
);
Expand Down Expand Up @@ -136,6 +128,57 @@ export function addFieldsWithIndex(
return newFields;
}

enum ObjectStatus {
Success = 'Success',
Failed = 'Failed',
Reconciling = 'Reconciling',
Suspended = 'Suspended',
PendingAction = 'PendingAction',
NoStatus = '-'
}

type IndicatorInfo = {
color: string;
type: IconType;
};

const getIndicatorInfo = (
status: string | undefined,
): IndicatorInfo => {
switch (status) {
case ObjectStatus.Success:
return {
color: 'successOriginal',
type: IconType.SuccessIcon,
};
case ObjectStatus.Reconciling:
return {
color: 'primary',
type: IconType.ReconcileIcon,
};
case ObjectStatus.Suspended:
return {
color: 'feedbackOriginal',
type: IconType.SuspendedIcon,
};
case ObjectStatus.PendingAction:
return {
color: 'feedbackOriginal',
type: IconType.PendingActionIcon,
};
case ObjectStatus.NoStatus:
return {
color: 'neutral20',
type: IconType.RemoveCircleIcon,
};
default:
return {
color: 'alertOriginal',
type: IconType.ErrorIcon,
};
}
};

function ExplorerTable({
className,
rows,
Expand Down

0 comments on commit 5eaeaeb

Please sign in to comment.