github.com/jghiloni/cli@v6.28.1-0.20170628223758-0ce05fe032a2+incompatible/actor/v2action/application_instance_with_stats.go (about)

     1  package v2action
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strings"
     7  	"time"
     8  
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2"
    11  )
    12  
    13  type ApplicationInstanceWithStats struct {
    14  	// CPU is the instance's CPU utilization percentage.
    15  	CPU float64
    16  
    17  	// Details are arbitrary information about the instance.
    18  	Details string
    19  
    20  	// Disk is the instance's disk usage in bytes.
    21  	Disk int
    22  
    23  	// DiskQuota is the instance's allowed disk usage in bytes.
    24  	DiskQuota int
    25  
    26  	// ID is the instance ID.
    27  	ID int
    28  
    29  	// IsolationSegment that the app instance is currently running on.
    30  	IsolationSegment string
    31  
    32  	// Memory is the instance's memory usage in bytes.
    33  	Memory int
    34  
    35  	// MemoryQuota is the instance's allowed memory usage in bytes.
    36  	MemoryQuota int
    37  
    38  	// Since is the Unix time stamp that represents the time the instance was
    39  	// created.
    40  	Since float64
    41  
    42  	// State is the instance's state.
    43  	State ApplicationInstanceState
    44  }
    45  
    46  // newApplicationInstanceWithStats returns a pointer to a new
    47  // ApplicationInstance.
    48  func newApplicationInstanceWithStats(id int) ApplicationInstanceWithStats {
    49  	return ApplicationInstanceWithStats{ID: id}
    50  }
    51  
    52  func (instance ApplicationInstanceWithStats) TimeSinceCreation() time.Time {
    53  	return time.Unix(int64(instance.Since), 0)
    54  }
    55  
    56  func (instance *ApplicationInstanceWithStats) setInstance(ccAppInstance ApplicationInstance) {
    57  	instance.Details = ccAppInstance.Details
    58  	instance.Since = ccAppInstance.Since
    59  	instance.State = ApplicationInstanceState(ccAppInstance.State)
    60  }
    61  
    62  func (instance *ApplicationInstanceWithStats) setStats(ccAppStats ccv2.ApplicationInstanceStatus) {
    63  	instance.CPU = ccAppStats.CPU
    64  	instance.Disk = ccAppStats.Disk
    65  	instance.DiskQuota = ccAppStats.DiskQuota
    66  	instance.Memory = ccAppStats.Memory
    67  	instance.MemoryQuota = ccAppStats.MemoryQuota
    68  	instance.IsolationSegment = ccAppStats.IsolationSegment
    69  }
    70  
    71  func (instance *ApplicationInstanceWithStats) incomplete() {
    72  	instance.Details = strings.TrimSpace(fmt.Sprintf("%s (%s)", instance.Details, "Unable to retrieve information"))
    73  }
    74  
    75  // ApplicationInstancesNotFoundError is returned when the application does not
    76  // have running instances.
    77  type ApplicationInstancesNotFoundError struct {
    78  	ApplicationGUID string
    79  }
    80  
    81  func (e ApplicationInstancesNotFoundError) Error() string {
    82  	return fmt.Sprintf("Application instances '%s' not found.", e.ApplicationGUID)
    83  }
    84  
    85  func (actor Actor) GetApplicationInstancesWithStatsByApplication(guid string) ([]ApplicationInstanceWithStats, Warnings, error) {
    86  	var allWarnings Warnings
    87  
    88  	appInstanceStats, apiWarnings, err := actor.CloudControllerClient.GetApplicationInstanceStatusesByApplication(guid)
    89  	allWarnings = append(allWarnings, apiWarnings...)
    90  
    91  	switch err.(type) {
    92  	case ccerror.ResourceNotFoundError, ccerror.ApplicationStoppedStatsError:
    93  		return nil, allWarnings, ApplicationInstancesNotFoundError{ApplicationGUID: guid}
    94  	case nil:
    95  		// continue
    96  	default:
    97  		return nil, allWarnings, err
    98  	}
    99  
   100  	appInstances, warnings, err := actor.GetApplicationInstancesByApplication(guid)
   101  	allWarnings = append(allWarnings, warnings...)
   102  	if err != nil {
   103  		return nil, allWarnings, err
   104  	}
   105  
   106  	returnedInstances := combineStatsAndInstances(appInstanceStats, appInstances)
   107  
   108  	sort.Slice(returnedInstances, func(i int, j int) bool { return returnedInstances[i].ID < returnedInstances[j].ID })
   109  
   110  	return returnedInstances, allWarnings, err
   111  }
   112  
   113  func combineStatsAndInstances(appInstanceStats map[int]ccv2.ApplicationInstanceStatus, appInstances map[int]ApplicationInstance) []ApplicationInstanceWithStats {
   114  	returnedInstances := []ApplicationInstanceWithStats{}
   115  	seenStatuses := make(map[int]bool, len(appInstanceStats))
   116  
   117  	for id, appInstanceStat := range appInstanceStats {
   118  		seenStatuses[id] = true
   119  
   120  		returnedInstance := newApplicationInstanceWithStats(id)
   121  		returnedInstance.setStats(appInstanceStat)
   122  
   123  		if appInstance, found := appInstances[id]; found {
   124  			returnedInstance.setInstance(appInstance)
   125  		} else {
   126  			returnedInstance.incomplete()
   127  		}
   128  
   129  		returnedInstances = append(returnedInstances, returnedInstance)
   130  	}
   131  
   132  	// add instances that are missing stats
   133  	for index, appInstance := range appInstances {
   134  		if _, found := seenStatuses[index]; !found {
   135  			returnedInstance := newApplicationInstanceWithStats(index)
   136  			returnedInstance.setInstance(appInstance)
   137  			returnedInstance.incomplete()
   138  
   139  			returnedInstances = append(returnedInstances, returnedInstance)
   140  		}
   141  	}
   142  
   143  	return returnedInstances
   144  }