Skip to content

Commit

Permalink
UPSTREAM: <carry>: crd: add ClusterOperator condition message table c…
Browse files Browse the repository at this point in the history
…olumn

The logic is not exressible via JSONPath. Hence, if we want this, we have to help a little with this custom column writer.

OpenShift-Rebase-Source: 633a422
  • Loading branch information
sttts authored and bertinatto committed Jul 25, 2023
1 parent ae21134 commit 70eabaa
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 6 deletions.
Expand Up @@ -789,7 +789,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
utilruntime.HandleError(err)
return nil, fmt.Errorf("the server could not properly serve the CR columns")
}
table, err := tableconvertor.New(columns)
table, err := tableconvertor.New(columns, schema.GroupVersionKind{crd.Spec.Group, v.Name, crd.Spec.Names.Kind})
if err != nil {
klog.V(2).Infof("The CRD for %v has an invalid printer specification, falling back to default printing: %v", kind, err)
}
Expand Down Expand Up @@ -890,7 +890,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
if err != nil {
return nil, fmt.Errorf("the server could not properly serve the CR scale subresource columns %w", err)
}
scaleTable, _ := tableconvertor.New(scaleColumns)
scaleTable, _ := tableconvertor.New(scaleColumns, schema.GroupVersionKind{crd.Spec.Group, v.Name, crd.Spec.Names.Kind})

// override scale subresource values
// shallow copy
Expand Down
Expand Up @@ -90,7 +90,7 @@ func newStorage(t *testing.T) (customresource.CustomResourceStorage, *etcd3testi
{Name: "Float64", Type: "number", JSONPath: ".spec.float64"},
{Name: "Bool", Type: "boolean", JSONPath: ".spec.bool"},
}
table, _ := tableconvertor.New(headers)
table, _ := tableconvertor.New(headers, schema.GroupVersionKind{Group: "mygroup.example.com", Version: "v1beta1", Kind: "NoxuItemList"})

storage := customresource.NewStorage(
groupResource,
Expand Down
@@ -0,0 +1,94 @@
package tableconvertor

import (
"encoding/json"
"io"
"reflect"

configv1 "github.com/openshift/api/config/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/registry/rest"
)

var clusterOperatorGVK = schema.GroupVersionKind{configv1.GroupName, "v1", "ClusterOperator"}

func withClusterOperatorColumns(c *convertor, gvk schema.GroupVersionKind) rest.TableConvertor {
if gvk != clusterOperatorGVK {
return c
}

c.headers = append(c.headers, metav1.TableColumnDefinition{
Name: "Message",
Type: "string",
Description: "A message describing the status of the operator",
Priority: 0,
})
c.additionalColumns = append(c.additionalColumns, clusterOperatorConditionMessage{})

return c
}

type clusterOperatorConditionMessage struct {
}

func (c clusterOperatorConditionMessage) FindResults(data interface{}) ([][]reflect.Value, error) {
obj := data.(map[string]interface{})
unstructuredConds, _, _ := unstructured.NestedFieldNoCopy(obj, "status", "conditions")
var conds []configv1.ClusterOperatorStatusCondition
bs, err := json.Marshal(unstructuredConds)
if err != nil {
return nil, err
}
if err := json.Unmarshal(bs, &conds); err != nil {
return nil, err
}

var available, degraded, progressing *configv1.ClusterOperatorStatusCondition
for i := range conds {
cond := &conds[i]
switch {
case cond.Type == configv1.OperatorAvailable && cond.Status == configv1.ConditionFalse:
available = cond
case cond.Type == configv1.OperatorDegraded && cond.Status == configv1.ConditionTrue:
degraded = cond
case cond.Type == configv1.OperatorProgressing && cond.Status == configv1.ConditionTrue:
progressing = cond
}
}

mostCritical := progressing
if degraded != nil {
mostCritical = degraded
}
if available != nil {
mostCritical = available
}

if mostCritical != nil {
if len(mostCritical.Message) > 0 {
return [][]reflect.Value{{reflect.ValueOf(mostCritical.Message)}}, nil
}
if len(mostCritical.Reason) > 0 {
return [][]reflect.Value{{reflect.ValueOf(mostCritical.Reason)}}, nil
}
}

return nil, nil
}

func (c clusterOperatorConditionMessage) PrintResults(wr io.Writer, results []reflect.Value) error {
first := true
for _, r := range results {
if !first {
wr.Write([]byte("; ")) // should never happen as we only return one result
}
if _, err := wr.Write([]byte(r.String())); err != nil {
return err
}
first = false
}

return nil
}
Expand Up @@ -29,7 +29,8 @@ import (
metatable "k8s.io/apimachinery/pkg/api/meta/table"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
runtime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/client-go/util/jsonpath"
)
Expand All @@ -38,7 +39,7 @@ var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()

// New creates a new table convertor for the provided CRD column definition. If the printer definition cannot be parsed,
// error will be returned along with a default table convertor.
func New(crdColumns []apiextensionsv1.CustomResourceColumnDefinition) (rest.TableConvertor, error) {
func New(crdColumns []apiextensionsv1.CustomResourceColumnDefinition, gvk schema.GroupVersionKind) (rest.TableConvertor, error) {
headers := []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]},
}
Expand Down Expand Up @@ -68,7 +69,12 @@ func New(crdColumns []apiextensionsv1.CustomResourceColumnDefinition) (rest.Tabl
})
}

return c, nil
return withClusterOperatorColumns(c, gvk), nil
}

type column interface {
FindResults(data interface{}) ([][]reflect.Value, error)
PrintResults(wr io.Writer, results []reflect.Value) error
}

type columnPrinter interface {
Expand Down

0 comments on commit 70eabaa

Please sign in to comment.