github.com/verrazzano/verrazzano@v1.7.0/platform-operator/controllers/module/component-handler/common/vzcomponent_status.go (about)

     1  // Copyright (c) 2023, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package common
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"github.com/verrazzano/verrazzano-modules/pkg/controller/result"
    10  	"github.com/verrazzano/verrazzano-modules/pkg/controller/spi/handlerspi"
    11  	vzapi "github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1alpha1"
    12  	corev1 "k8s.io/api/core/v1"
    13  	"k8s.io/apimachinery/pkg/api/errors"
    14  	"k8s.io/apimachinery/pkg/types"
    15  	"time"
    16  )
    17  
    18  // StatusData contains the data for the component status field
    19  type StatusData struct {
    20  	Vznsn       types.NamespacedName
    21  	CondType    vzapi.ConditionType
    22  	CompName    string
    23  	CompVersion string
    24  	Msg         string
    25  	Ready       bool
    26  }
    27  
    28  // UpdateVerrazzanoComponentStatusToDisabled updates the component status to disabled
    29  func UpdateVerrazzanoComponentStatusToDisabled(ctx handlerspi.HandlerContext, Vznsn types.NamespacedName, compName string) result.Result {
    30  	// Always get the latest module from the controller-runtime cache to try and avoid conflict error
    31  	vzcr := &vzapi.Verrazzano{}
    32  	if err := ctx.Client.Get(context.TODO(), Vznsn, vzcr); err != nil {
    33  		ctx.Log.Progress("Failed getting Verrazzano CR, retrying...")
    34  		return result.NewResultShortRequeueDelay()
    35  	}
    36  	if vzcr.Status.Components == nil {
    37  		vzcr.Status.Components = vzapi.ComponentStatusMap{}
    38  	}
    39  	compStatus := &vzapi.ComponentStatusDetails{
    40  		Name:  compName,
    41  		State: vzapi.CompStateDisabled,
    42  	}
    43  	vzcr.Status.Components[compName] = compStatus
    44  
    45  	if err := ctx.Client.Status().Update(context.TODO(), vzcr); err != nil {
    46  		if !errors.IsConflict(err) {
    47  			ctx.Log.Progress("Failed to update Verrazzano component status, retrying: %v", err)
    48  		}
    49  		return result.NewResultShortRequeueDelay()
    50  	}
    51  	return result.NewResult()
    52  }
    53  
    54  // UpdateVerrazzanoComponentStatus updates the Verrazzano component status
    55  func UpdateVerrazzanoComponentStatus(ctx handlerspi.HandlerContext, sd StatusData) result.Result {
    56  	// Always get the latest module from the controller-runtime cache to try and avoid conflict error
    57  	vzcr := &vzapi.Verrazzano{}
    58  	if err := ctx.Client.Get(context.TODO(), sd.Vznsn, vzcr); err != nil {
    59  		ctx.Log.Progress("Failed getting Verrazzano CR, retrying...")
    60  		return result.NewResultShortRequeueDelay()
    61  	}
    62  	if vzcr.Status.Components == nil {
    63  		vzcr.Status.Components = vzapi.ComponentStatusMap{}
    64  	}
    65  	compStatus := vzcr.Status.Components[sd.CompName]
    66  	if compStatus == nil {
    67  		compStatus = &vzapi.ComponentStatusDetails{
    68  			Available:                getAvailPtr(vzapi.ComponentUnavailable),
    69  			LastReconciledGeneration: 0,
    70  			Name:                     sd.CompName,
    71  			State:                    vzapi.CompStateUninstalled,
    72  		}
    73  		vzcr.Status.Components[sd.CompName] = compStatus
    74  	}
    75  	if sd.Ready {
    76  		compStatus.Available = getAvailPtr(vzapi.ComponentAvailable)
    77  		compStatus.State = vzapi.CompStateReady
    78  		compStatus.LastReconciledGeneration = vzcr.Generation
    79  		compStatus.Version = sd.CompVersion
    80  	} else {
    81  		compStatus.State = vzapi.CompStateReconciling
    82  	}
    83  
    84  	// Append or replace the condition
    85  	cond := vzapi.Condition{
    86  		Type:    sd.CondType,
    87  		Status:  corev1.ConditionTrue,
    88  		Message: sd.Msg,
    89  	}
    90  	addOrReplaceCondition(compStatus, cond)
    91  
    92  	if err := ctx.Client.Status().Update(context.TODO(), vzcr); err != nil {
    93  		if !errors.IsConflict(err) {
    94  			ctx.Log.Progress("Failed to update Verrazzano component status, retrying: %v", err)
    95  		}
    96  		return result.NewResultShortRequeueDelay()
    97  	}
    98  	return result.NewResult()
    99  }
   100  
   101  // addOrReplaceCondition appends the condition to the list of conditions.
   102  // if the condition already exists, then remove it
   103  func addOrReplaceCondition(compStatus *vzapi.ComponentStatusDetails, cond vzapi.Condition) {
   104  	cond.LastTransitionTime = getCurrentTime()
   105  
   106  	// Copy conditions that have a different type than the input condition into a new list
   107  	var newConditions []vzapi.Condition
   108  	if compStatus.Conditions != nil {
   109  		for i, existing := range compStatus.Conditions {
   110  			if existing.Type != cond.Type {
   111  				newConditions = append(newConditions, compStatus.Conditions[i])
   112  			}
   113  		}
   114  	}
   115  
   116  	// Always put the new condition at the end of the list since the kubectl status display and
   117  	// some upgrade stuff depends on the most recent condition being the last one
   118  	compStatus.Conditions = append(newConditions, cond)
   119  }
   120  
   121  func getCurrentTime() string {
   122  	t := time.Now().UTC()
   123  	return fmt.Sprintf("%d-%02d-%02dT%02d:%02d:%02dZ",
   124  		t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second())
   125  }
   126  
   127  func getAvailPtr(avail vzapi.ComponentAvailability) *vzapi.ComponentAvailability {
   128  	return &avail
   129  }