k8s.io/perf-tests/clusterloader2@v0.0.0-20240304094227-64bdb12da87e/pkg/measurement/util/pvcs.go (about)

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package util
    18  
    19  import (
    20  	"fmt"
    21  
    22  	corev1 "k8s.io/api/core/v1"
    23  	"k8s.io/apimachinery/pkg/util/sets"
    24  )
    25  
    26  // PVCsStartupStatus represents phase of a pvc group.
    27  type PVCsStartupStatus struct {
    28  	Pending  int
    29  	Bound    int
    30  	Lost     int
    31  	Expected int
    32  	Created  int
    33  }
    34  
    35  // String returns string representation for PVCsStartupStatus.
    36  func (s *PVCsStartupStatus) String() string {
    37  	return fmt.Sprintf("PVCs: %d out of %d created, %d bound, %d pending, %d lost", s.Created, s.Expected, s.Bound, s.Pending, s.Lost)
    38  }
    39  
    40  // ComputePVCsStartupStatus computes PVCsStartupStatus for a group of PVCs.
    41  func ComputePVCsStartupStatus(pvcs []*corev1.PersistentVolumeClaim, expected int) PVCsStartupStatus {
    42  	startupStatus := PVCsStartupStatus{
    43  		Expected: expected,
    44  	}
    45  	for _, p := range pvcs {
    46  		startupStatus.Created++
    47  		if p.Status.Phase == corev1.ClaimPending {
    48  			startupStatus.Pending++
    49  		} else if p.Status.Phase == corev1.ClaimBound {
    50  			startupStatus.Bound++
    51  		} else if p.Status.Phase == corev1.ClaimLost {
    52  			startupStatus.Lost++
    53  		}
    54  	}
    55  	return startupStatus
    56  }
    57  
    58  type pvcInfo struct {
    59  	oldPhase string
    60  	phase    string
    61  }
    62  
    63  // PVCDiff represets diff between old and new group of pvcs.
    64  type PVCDiff map[string]*pvcInfo
    65  
    66  // Print formats and prints the give PVCDiff.
    67  func (p PVCDiff) String(ignorePhases sets.String) string {
    68  	ret := ""
    69  	for name, info := range p {
    70  		if ignorePhases.Has(info.phase) {
    71  			continue
    72  		}
    73  		if info.phase == nonExist {
    74  			ret += fmt.Sprintf("PVC %v was deleted, had phase %v\n", name, info.oldPhase)
    75  			continue
    76  		}
    77  		msg := fmt.Sprintf("PVC %v ", name)
    78  		if info.oldPhase != info.phase {
    79  			if info.oldPhase == nonExist {
    80  				msg += fmt.Sprintf("in phase %v ", info.phase)
    81  			} else {
    82  				msg += fmt.Sprintf("went from phase: %v -> %v ", info.oldPhase, info.phase)
    83  			}
    84  			ret += msg + "\n"
    85  		}
    86  	}
    87  	return ret
    88  }
    89  
    90  // DeletedPVCs returns a slice of PVCs that were present at the beginning
    91  // and then disappeared.
    92  func (p PVCDiff) DeletedPVCs() []string {
    93  	var deletedPVCs []string
    94  	for pvcName, pvcInfo := range p {
    95  		if pvcInfo.phase == nonExist {
    96  			deletedPVCs = append(deletedPVCs, pvcName)
    97  		}
    98  	}
    99  	return deletedPVCs
   100  }
   101  
   102  // AddedPVCs returns a slice of PVCs that were added.
   103  func (p PVCDiff) AddedPVCs() []string {
   104  	var addedPVCs []string
   105  	for pvcName, pvcInfo := range p {
   106  		if pvcInfo.oldPhase == nonExist {
   107  			addedPVCs = append(addedPVCs, pvcName)
   108  		}
   109  	}
   110  	return addedPVCs
   111  }
   112  
   113  // DiffPVCs computes a PVCDiff given 2 lists of PVCs.
   114  func DiffPVCs(oldPVCs []*corev1.PersistentVolumeClaim, curPVCs []*corev1.PersistentVolumeClaim) PVCDiff {
   115  	pvcInfoMap := PVCDiff{}
   116  
   117  	// New PVCs will show up in the curPVCs list but not in oldPVCs. They have oldhostname/phase == nonexist.
   118  	for _, pvc := range curPVCs {
   119  		pvcInfoMap[pvc.Name] = &pvcInfo{phase: string(pvc.Status.Phase), oldPhase: nonExist}
   120  	}
   121  
   122  	// Deleted PVCs will show up in the oldPVCs list but not in curPVCs. They have a hostname/phase == nonexist.
   123  	for _, pvc := range oldPVCs {
   124  		if info, ok := pvcInfoMap[pvc.Name]; ok {
   125  			info.oldPhase = string(pvc.Status.Phase)
   126  		} else {
   127  			pvcInfoMap[pvc.Name] = &pvcInfo{phase: nonExist, oldPhase: string(pvc.Status.Phase)}
   128  		}
   129  	}
   130  	return pvcInfoMap
   131  }