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

     1  package v3action
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"time"
     7  
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    10  )
    11  
    12  // Application represents a V3 actor application.
    13  type Application ccv3.Application
    14  
    15  // ApplicationNotFoundError represents the error that occurs when the
    16  // application is not found.
    17  type ApplicationNotFoundError struct {
    18  	Name string
    19  }
    20  
    21  func (e ApplicationNotFoundError) Error() string {
    22  	return fmt.Sprintf("Application '%s' not found.", e.Name)
    23  }
    24  
    25  // ApplicationAlreadyExistsError represents the error that occurs when the
    26  // application already exists.
    27  type ApplicationAlreadyExistsError struct {
    28  	Name string
    29  }
    30  
    31  func (e ApplicationAlreadyExistsError) Error() string {
    32  	return fmt.Sprintf("Application '%s' already exists.", e.Name)
    33  }
    34  
    35  // GetApplicationByNameAndSpace returns the application with the given
    36  // name in the given space.
    37  func (actor Actor) GetApplicationByNameAndSpace(appName string, spaceGUID string) (Application, Warnings, error) {
    38  	apps, warnings, err := actor.CloudControllerClient.GetApplications(url.Values{
    39  		"space_guids": []string{spaceGUID},
    40  		"names":       []string{appName},
    41  	})
    42  	if err != nil {
    43  		return Application{}, Warnings(warnings), err
    44  	}
    45  
    46  	if len(apps) == 0 {
    47  		return Application{}, Warnings(warnings), ApplicationNotFoundError{Name: appName}
    48  	}
    49  
    50  	return Application(apps[0]), Warnings(warnings), nil
    51  }
    52  
    53  // CreateApplicationByNameAndSpace creates and returns the application with the given
    54  // name in the given space.
    55  func (actor Actor) CreateApplicationByNameAndSpace(appName string, spaceGUID string) (Application, Warnings, error) {
    56  	app, warnings, err := actor.CloudControllerClient.CreateApplication(
    57  		ccv3.Application{
    58  			Name: appName,
    59  			Relationships: ccv3.Relationships{
    60  				ccv3.SpaceRelationship: ccv3.Relationship{GUID: spaceGUID},
    61  			},
    62  		})
    63  
    64  	if _, ok := err.(ccerror.UnprocessableEntityError); ok {
    65  		return Application{}, Warnings(warnings), ApplicationAlreadyExistsError{Name: appName}
    66  	}
    67  
    68  	return Application(app), Warnings(warnings), err
    69  }
    70  
    71  // StopApplication stops an application.
    72  func (actor Actor) StopApplication(appName string, spaceGUID string) (Warnings, error) {
    73  	allWarnings := Warnings{}
    74  	application, warnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID)
    75  	allWarnings = append(allWarnings, warnings...)
    76  	if err != nil {
    77  		return allWarnings, err
    78  	}
    79  	apiWarnings, err := actor.CloudControllerClient.StopApplication(application.GUID)
    80  	allWarnings = append(allWarnings, apiWarnings...)
    81  
    82  	return allWarnings, err
    83  }
    84  
    85  // StartApplication starts an application.
    86  func (actor Actor) StartApplication(appName string, spaceGUID string) (Application, Warnings, error) {
    87  	allWarnings := Warnings{}
    88  	application, warnings, err := actor.GetApplicationByNameAndSpace(appName, spaceGUID)
    89  	allWarnings = append(allWarnings, warnings...)
    90  	if err != nil {
    91  		return Application{}, allWarnings, err
    92  	}
    93  	updatedApp, apiWarnings, err := actor.CloudControllerClient.StartApplication(application.GUID)
    94  	allWarnings = append(allWarnings, apiWarnings...)
    95  
    96  	return Application(updatedApp), allWarnings, err
    97  }
    98  
    99  func (actor Actor) PollStart(appGUID string, warningsChannel chan<- Warnings) error {
   100  	processes, warnings, err := actor.CloudControllerClient.GetApplicationProcesses(appGUID)
   101  	warningsChannel <- Warnings(warnings)
   102  	if err != nil {
   103  		return err
   104  	}
   105  
   106  	timeout := time.Now().Add(actor.Config.StartupTimeout())
   107  	for time.Now().Before(timeout) {
   108  		readyProcs := 0
   109  		for _, process := range processes {
   110  			ready, err := actor.processReady(process, warningsChannel)
   111  			if err != nil {
   112  				return err
   113  			}
   114  
   115  			if ready {
   116  				readyProcs++
   117  			}
   118  		}
   119  
   120  		if readyProcs == len(processes) {
   121  			return nil
   122  		}
   123  		time.Sleep(actor.Config.PollingInterval())
   124  	}
   125  
   126  	return StartupTimeoutError{}
   127  }
   128  
   129  // StartupTimeoutError is returned when startup timeout is reached waiting for
   130  // an application to start.
   131  type StartupTimeoutError struct {
   132  }
   133  
   134  func (e StartupTimeoutError) Error() string {
   135  	return fmt.Sprintf("Timed out waiting for application to start")
   136  }
   137  
   138  func (actor Actor) processReady(process ccv3.Process, warningsChannel chan<- Warnings) (bool, error) {
   139  	instances, warnings, err := actor.CloudControllerClient.GetProcessInstances(process.GUID)
   140  	warningsChannel <- Warnings(warnings)
   141  	if err != nil {
   142  		return false, err
   143  	}
   144  	if len(instances) == 0 {
   145  		return true, nil
   146  	}
   147  
   148  	for _, instance := range instances {
   149  		if instance.State == "RUNNING" {
   150  			return true, nil
   151  		}
   152  	}
   153  
   154  	return false, nil
   155  }