github.com/dcarley/cf-cli@v6.24.1-0.20170220111324-4225ff346898+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"
    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  	// Memory is the instance's memory usage in bytes.
    30  	Memory int
    31  
    32  	// MemoryQuota is the instance's allowed memory usage in bytes.
    33  	MemoryQuota int
    34  
    35  	// Since is the Unix time stamp that represents the time the instance was
    36  	// created.
    37  	Since float64
    38  
    39  	// State is the instance's state.
    40  	State ApplicationInstanceState
    41  }
    42  
    43  // newApplicationInstanceWithStats returns a pointer to a new
    44  // ApplicationInstance.
    45  func newApplicationInstanceWithStats(id int) ApplicationInstanceWithStats {
    46  	return ApplicationInstanceWithStats{ID: id}
    47  }
    48  
    49  func (instance ApplicationInstanceWithStats) TimeSinceCreation() time.Time {
    50  	return time.Unix(int64(instance.Since), 0)
    51  }
    52  
    53  func (instance *ApplicationInstanceWithStats) setInstance(ccAppInstance ApplicationInstance) {
    54  	instance.Details = ccAppInstance.Details
    55  	instance.Since = ccAppInstance.Since
    56  	instance.State = ApplicationInstanceState(ccAppInstance.State)
    57  }
    58  
    59  func (instance *ApplicationInstanceWithStats) setStats(ccAppStats ccv2.ApplicationInstanceStatus) {
    60  	instance.CPU = ccAppStats.CPU
    61  	instance.Disk = ccAppStats.Disk
    62  	instance.DiskQuota = ccAppStats.DiskQuota
    63  	instance.Memory = ccAppStats.Memory
    64  	instance.MemoryQuota = ccAppStats.MemoryQuota
    65  }
    66  
    67  func (instance *ApplicationInstanceWithStats) incomplete() {
    68  	instance.Details = strings.TrimSpace(fmt.Sprintf("%s (%s)", instance.Details, "Unable to retrieve information"))
    69  }
    70  
    71  type applicationInstances []ApplicationInstanceWithStats
    72  
    73  func (a applicationInstances) Len() int               { return len(a) }
    74  func (a applicationInstances) Swap(i int, j int)      { a[i], a[j] = a[j], a[i] }
    75  func (a applicationInstances) Less(i int, j int) bool { return a[i].ID < a[j].ID }
    76  
    77  // ApplicationInstancesNotFoundError is returned when the application does not
    78  // have running instances.
    79  type ApplicationInstancesNotFoundError struct {
    80  	ApplicationGUID string
    81  }
    82  
    83  func (e ApplicationInstancesNotFoundError) Error() string {
    84  	return fmt.Sprintf("Application instances '%s' not found.", e.ApplicationGUID)
    85  }
    86  
    87  func (actor Actor) GetApplicationInstancesWithStatsByApplication(guid string) ([]ApplicationInstanceWithStats, Warnings, error) {
    88  	var allWarnings Warnings
    89  
    90  	appInstanceStats, apiWarnings, err := actor.CloudControllerClient.GetApplicationInstanceStatusesByApplication(guid)
    91  	allWarnings = append(allWarnings, apiWarnings...)
    92  
    93  	switch err.(type) {
    94  	case cloudcontroller.ResourceNotFoundError, ccv2.AppStoppedStatsError:
    95  		return nil, allWarnings, ApplicationInstancesNotFoundError{ApplicationGUID: guid}
    96  	case nil:
    97  		// continue
    98  	default:
    99  		return nil, allWarnings, err
   100  	}
   101  
   102  	appInstances, warnings, err := actor.GetApplicationInstancesByApplication(guid)
   103  	allWarnings = append(allWarnings, warnings...)
   104  	if err != nil {
   105  		return nil, allWarnings, err
   106  	}
   107  
   108  	returnedInstances := combineStatsAndInstances(appInstanceStats, appInstances)
   109  
   110  	sort.Sort(returnedInstances)
   111  
   112  	return returnedInstances, allWarnings, err
   113  }
   114  
   115  func combineStatsAndInstances(appInstanceStats map[int]ccv2.ApplicationInstanceStatus, appInstances map[int]ApplicationInstance) applicationInstances {
   116  	returnedInstances := applicationInstances{}
   117  	seenStatuses := make(map[int]bool, len(appInstanceStats))
   118  
   119  	for id, appInstanceStat := range appInstanceStats {
   120  		seenStatuses[id] = true
   121  
   122  		returnedInstance := newApplicationInstanceWithStats(id)
   123  		returnedInstance.setStats(appInstanceStat)
   124  
   125  		if appInstance, found := appInstances[id]; found {
   126  			returnedInstance.setInstance(appInstance)
   127  		} else {
   128  			returnedInstance.incomplete()
   129  		}
   130  
   131  		returnedInstances = append(returnedInstances, returnedInstance)
   132  	}
   133  
   134  	// add instances that are missing stats
   135  	for index, appInstance := range appInstances {
   136  		if _, found := seenStatuses[index]; !found {
   137  			returnedInstance := newApplicationInstanceWithStats(index)
   138  			returnedInstance.setInstance(appInstance)
   139  			returnedInstance.incomplete()
   140  
   141  			returnedInstances = append(returnedInstances, returnedInstance)
   142  		}
   143  	}
   144  
   145  	return returnedInstances
   146  }