...

Source file src/sigs.k8s.io/cli-utils/pkg/kstatus/status/generic.go

Documentation: sigs.k8s.io/cli-utils/pkg/kstatus/status

     1  // Copyright 2019 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package status
     5  
     6  import (
     7  	"fmt"
     8  
     9  	corev1 "k8s.io/api/core/v1"
    10  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    11  )
    12  
    13  // checkGenericProperties looks at the properties that are available on
    14  // all or most of the Kubernetes resources. If a decision can be made based
    15  // on this information, there is no need to look at the resource-specidic
    16  // rules.
    17  // This also checks for the presence of the conditions defined in this package.
    18  // If any of these are set on the resource, a decision is made solely based
    19  // on this and none of the resource specific rules will be used. The goal here
    20  // is that if controllers, built-in or custom, use these conditions, we can easily
    21  // find status of resources.
    22  func checkGenericProperties(u *unstructured.Unstructured) (*Result, error) {
    23  	obj := u.UnstructuredContent()
    24  
    25  	// Check if the resource is scheduled for deletion
    26  	deletionTimestamp, found, err := unstructured.NestedString(obj, "metadata", "deletionTimestamp")
    27  	if err != nil {
    28  		return nil, fmt.Errorf("looking up metadata.deletionTimestamp from resource: %w", err)
    29  	}
    30  	if found && deletionTimestamp != "" {
    31  		return &Result{
    32  			Status:     TerminatingStatus,
    33  			Message:    "Resource scheduled for deletion",
    34  			Conditions: []Condition{},
    35  		}, nil
    36  	}
    37  
    38  	res, err := checkGeneration(u)
    39  	if res != nil || err != nil {
    40  		return res, err
    41  	}
    42  
    43  	// Check if the resource has any of the standard conditions. If so, we just use them
    44  	// and no need to look at anything else.
    45  	objWithConditions, err := GetObjectWithConditions(obj)
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  
    50  	for _, cond := range objWithConditions.Status.Conditions {
    51  		if cond.Type == string(ConditionReconciling) && cond.Status == corev1.ConditionTrue {
    52  			return newInProgressStatus(cond.Reason, cond.Message), nil
    53  		}
    54  		if cond.Type == string(ConditionStalled) && cond.Status == corev1.ConditionTrue {
    55  			return &Result{
    56  				Status:  FailedStatus,
    57  				Message: cond.Message,
    58  				Conditions: []Condition{
    59  					{
    60  						Type:    ConditionStalled,
    61  						Status:  corev1.ConditionTrue,
    62  						Reason:  cond.Reason,
    63  						Message: cond.Message,
    64  					},
    65  				},
    66  			}, nil
    67  		}
    68  	}
    69  
    70  	return nil, nil
    71  }
    72  
    73  func checkGeneration(u *unstructured.Unstructured) (*Result, error) {
    74  	// ensure that the meta generation is observed
    75  	generation, found, err := unstructured.NestedInt64(u.Object, "metadata", "generation")
    76  	if err != nil {
    77  		return nil, fmt.Errorf("looking up metadata.generation from resource: %w", err)
    78  	}
    79  	if !found {
    80  		return nil, nil
    81  	}
    82  	observedGeneration, found, err := unstructured.NestedInt64(u.Object, "status", "observedGeneration")
    83  	if err != nil {
    84  		return nil, fmt.Errorf("looking up status.observedGeneration from resource: %w", err)
    85  	}
    86  	if found {
    87  		// Resource does not have this field, so we can't do this check.
    88  		// TODO(mortent): Verify behavior of not set vs does not exist.
    89  		if observedGeneration != generation {
    90  			message := fmt.Sprintf("%s generation is %d, but latest observed generation is %d", u.GetKind(), generation, observedGeneration)
    91  			return &Result{
    92  				Status:     InProgressStatus,
    93  				Message:    message,
    94  				Conditions: []Condition{newReconcilingCondition("LatestGenerationNotObserved", message)},
    95  			}, nil
    96  		}
    97  	}
    98  	return nil, nil
    99  }
   100  

View as plain text