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 }