github.com/liamawhite/cli-with-i18n@v6.32.1-0.20171122084555-dede0a5c3448+incompatible/cf/commands/application/app.go (about) 1 package application 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/liamawhite/cli-with-i18n/cf/flags" 8 . "github.com/liamawhite/cli-with-i18n/cf/i18n" 9 "github.com/liamawhite/cli-with-i18n/plugin/models" 10 11 "github.com/liamawhite/cli-with-i18n/cf/api" 12 "github.com/liamawhite/cli-with-i18n/cf/api/appinstances" 13 "github.com/liamawhite/cli-with-i18n/cf/api/stacks" 14 "github.com/liamawhite/cli-with-i18n/cf/commandregistry" 15 "github.com/liamawhite/cli-with-i18n/cf/configuration/coreconfig" 16 "github.com/liamawhite/cli-with-i18n/cf/errors" 17 "github.com/liamawhite/cli-with-i18n/cf/formatters" 18 "github.com/liamawhite/cli-with-i18n/cf/models" 19 "github.com/liamawhite/cli-with-i18n/cf/requirements" 20 "github.com/liamawhite/cli-with-i18n/cf/terminal" 21 "github.com/liamawhite/cli-with-i18n/cf/uihelpers" 22 ) 23 24 //go:generate counterfeiter . Displayer 25 26 type Displayer interface { 27 ShowApp(app models.Application, orgName string, spaceName string) error 28 } 29 30 type ShowApp struct { 31 ui terminal.UI 32 config coreconfig.Reader 33 appSummaryRepo api.AppSummaryRepository 34 appInstancesRepo appinstances.Repository 35 stackRepo stacks.StackRepository 36 appReq requirements.ApplicationRequirement 37 pluginAppModel *plugin_models.GetAppModel 38 pluginCall bool 39 } 40 41 func init() { 42 commandregistry.Register(&ShowApp{}) 43 } 44 45 func (cmd *ShowApp) MetaData() commandregistry.CommandMetadata { 46 fs := make(map[string]flags.FlagSet) 47 fs["guid"] = &flags.BoolFlag{Name: "guid", Usage: T("Retrieve and display the given app's guid. All other health and status output for the app is suppressed.")} 48 49 return commandregistry.CommandMetadata{ 50 Name: "app", 51 Description: T("Display health and status for an app"), 52 Usage: []string{ 53 T("CF_NAME app APP_NAME"), 54 }, 55 Flags: fs, 56 } 57 } 58 59 func (cmd *ShowApp) Requirements(requirementsFactory requirements.Factory, fc flags.FlagContext) ([]requirements.Requirement, error) { 60 if len(fc.Args()) != 1 { 61 cmd.ui.Failed(T("Incorrect Usage. Requires an argument\n\n") + commandregistry.Commands.CommandUsage("app")) 62 return nil, fmt.Errorf("Incorrect usage: %d arguments of %d required", len(fc.Args()), 1) 63 } 64 65 cmd.appReq = requirementsFactory.NewApplicationRequirement(fc.Args()[0]) 66 67 reqs := []requirements.Requirement{ 68 requirementsFactory.NewLoginRequirement(), 69 requirementsFactory.NewTargetedSpaceRequirement(), 70 cmd.appReq, 71 } 72 73 return reqs, nil 74 } 75 76 func (cmd *ShowApp) SetDependency(deps commandregistry.Dependency, pluginCall bool) commandregistry.Command { 77 cmd.ui = deps.UI 78 cmd.config = deps.Config 79 cmd.appSummaryRepo = deps.RepoLocator.GetAppSummaryRepository() 80 cmd.appInstancesRepo = deps.RepoLocator.GetAppInstancesRepository() 81 cmd.stackRepo = deps.RepoLocator.GetStackRepository() 82 83 cmd.pluginAppModel = deps.PluginModels.Application 84 cmd.pluginCall = pluginCall 85 86 return cmd 87 } 88 89 func (cmd *ShowApp) Execute(c flags.FlagContext) error { 90 app := cmd.appReq.GetApplication() 91 92 if c.Bool("guid") { 93 cmd.ui.Say(app.GUID) 94 } else { 95 err := cmd.ShowApp(app, cmd.config.OrganizationFields().Name, cmd.config.SpaceFields().Name) 96 if err != nil { 97 return err 98 } 99 } 100 return nil 101 } 102 103 func (cmd *ShowApp) ShowApp(app models.Application, orgName, spaceName string) error { 104 cmd.ui.Say(T("Showing health and status for app {{.AppName}} in org {{.OrgName}} / space {{.SpaceName}} as {{.Username}}...", 105 map[string]interface{}{ 106 "AppName": terminal.EntityNameColor(app.Name), 107 "OrgName": terminal.EntityNameColor(orgName), 108 "SpaceName": terminal.EntityNameColor(spaceName), 109 "Username": terminal.EntityNameColor(cmd.config.Username())})) 110 111 application, err := cmd.appSummaryRepo.GetSummary(app.GUID) 112 113 appIsStopped := (application.State == "stopped") 114 if assertionErr, ok := err.(errors.HTTPError); ok { 115 if assertionErr.ErrorCode() == errors.InstancesError || assertionErr.ErrorCode() == errors.NotStaged { 116 appIsStopped = true 117 } 118 } 119 120 if err != nil && !appIsStopped { 121 return err 122 } 123 124 var instances []models.AppInstanceFields 125 instances, err = cmd.appInstancesRepo.GetInstances(app.GUID) 126 if err != nil && !appIsStopped { 127 return err 128 } 129 130 if cmd.pluginCall { 131 cmd.populatePluginModel(application, app.Stack, instances) 132 } 133 134 cmd.ui.Ok() 135 cmd.ui.Say("\n%s %s", terminal.HeaderColor(T("requested state:")), uihelpers.ColoredAppState(application.ApplicationFields)) 136 cmd.ui.Say("%s %s", terminal.HeaderColor(T("instances:")), uihelpers.ColoredAppInstances(application.ApplicationFields)) 137 138 // Commented to hide app-ports for release #117189491 139 // if len(application.AppPorts) > 0 { 140 // appPorts := make([]string, len(application.AppPorts)) 141 // for i, p := range application.AppPorts { 142 // appPorts[i] = strconv.Itoa(p) 143 // } 144 145 // cmd.ui.Say("%s %s", terminal.HeaderColor(T("app ports:")), strings.Join(appPorts, ", ")) 146 // } 147 148 cmd.ui.Say(T("{{.Usage}} {{.FormattedMemory}} x {{.InstanceCount}} instances", 149 map[string]interface{}{ 150 "Usage": terminal.HeaderColor(T("usage:")), 151 "FormattedMemory": formatters.ByteSize(application.Memory * formatters.MEGABYTE), 152 "InstanceCount": application.InstanceCount})) 153 154 var urls []string 155 for _, route := range application.Routes { 156 urls = append(urls, route.URL()) 157 } 158 159 cmd.ui.Say("%s %s", terminal.HeaderColor(T("urls:")), strings.Join(urls, ", ")) 160 var lastUpdated string 161 if application.PackageUpdatedAt != nil { 162 lastUpdated = application.PackageUpdatedAt.Format("Mon Jan 2 15:04:05 MST 2006") 163 } else { 164 lastUpdated = "unknown" 165 } 166 cmd.ui.Say("%s %s", terminal.HeaderColor(T("last uploaded:")), lastUpdated) 167 168 appStack, err := cmd.stackRepo.FindByGUID(application.ApplicationFields.StackGUID) 169 if appStack.Name != "" && err == nil { 170 cmd.ui.Say("%s %s", terminal.HeaderColor(T("stack:")), appStack.Name) 171 } else { 172 cmd.ui.Say("%s %s", terminal.HeaderColor(T("stack:")), "unknown") 173 } 174 175 if app.Buildpack != "" { 176 cmd.ui.Say("%s %s\n", terminal.HeaderColor(T("buildpack:")), app.Buildpack) 177 } else if app.DetectedBuildpack != "" { 178 cmd.ui.Say("%s %s\n", terminal.HeaderColor(T("buildpack:")), app.DetectedBuildpack) 179 } else { 180 cmd.ui.Say("%s %s\n", terminal.HeaderColor(T("buildpack:")), "unknown") 181 } 182 183 if appIsStopped { 184 cmd.ui.Say(T("There are no running instances of this app.")) 185 return nil 186 } 187 188 table := cmd.ui.Table([]string{"", T("state"), T("since"), T("cpu"), T("memory"), T("disk"), T("details")}) 189 190 for index, instance := range instances { 191 table.Add( 192 fmt.Sprintf("#%d", index), 193 uihelpers.ColoredInstanceState(instance), 194 instance.Since.Format("2006-01-02 03:04:05 PM"), 195 fmt.Sprintf("%.1f%%", instance.CPUUsage*100), 196 fmt.Sprintf(T("{{.MemUsage}} of {{.MemQuota}}", 197 map[string]interface{}{ 198 "MemUsage": formatters.ByteSize(instance.MemUsage), 199 "MemQuota": formatters.ByteSize(instance.MemQuota)})), 200 fmt.Sprintf(T("{{.DiskUsage}} of {{.DiskQuota}}", 201 map[string]interface{}{ 202 "DiskUsage": formatters.ByteSize(instance.DiskUsage), 203 "DiskQuota": formatters.ByteSize(instance.DiskQuota)})), 204 fmt.Sprintf("%s", instance.Details), 205 ) 206 } 207 208 err = table.Print() 209 if err != nil { 210 return err 211 } 212 if err != nil { 213 return err 214 } 215 return nil 216 } 217 218 func (cmd *ShowApp) populatePluginModel( 219 getSummaryApp models.Application, 220 stack *models.Stack, 221 instances []models.AppInstanceFields, 222 ) { 223 cmd.pluginAppModel.BuildpackUrl = getSummaryApp.BuildpackURL 224 cmd.pluginAppModel.Command = getSummaryApp.Command 225 cmd.pluginAppModel.DetectedStartCommand = getSummaryApp.DetectedStartCommand 226 cmd.pluginAppModel.Diego = getSummaryApp.Diego 227 cmd.pluginAppModel.DiskQuota = getSummaryApp.DiskQuota 228 cmd.pluginAppModel.EnvironmentVars = getSummaryApp.EnvironmentVars 229 cmd.pluginAppModel.Guid = getSummaryApp.GUID 230 cmd.pluginAppModel.HealthCheckTimeout = getSummaryApp.HealthCheckTimeout 231 cmd.pluginAppModel.InstanceCount = getSummaryApp.InstanceCount 232 cmd.pluginAppModel.Memory = getSummaryApp.Memory 233 cmd.pluginAppModel.Name = getSummaryApp.Name 234 cmd.pluginAppModel.PackageState = getSummaryApp.PackageState 235 cmd.pluginAppModel.PackageUpdatedAt = getSummaryApp.PackageUpdatedAt 236 cmd.pluginAppModel.RunningInstances = getSummaryApp.RunningInstances 237 cmd.pluginAppModel.SpaceGuid = getSummaryApp.SpaceGUID 238 cmd.pluginAppModel.AppPorts = getSummaryApp.AppPorts 239 cmd.pluginAppModel.Stack = &plugin_models.GetApp_Stack{ 240 Name: stack.Name, 241 Guid: stack.GUID, 242 } 243 cmd.pluginAppModel.StagingFailedReason = getSummaryApp.StagingFailedReason 244 cmd.pluginAppModel.State = getSummaryApp.State 245 246 for _, instance := range instances { 247 instanceFields := plugin_models.GetApp_AppInstanceFields{ 248 State: string(instance.State), 249 Details: instance.Details, 250 Since: instance.Since, 251 CpuUsage: instance.CPUUsage, 252 DiskQuota: instance.DiskQuota, 253 DiskUsage: instance.DiskUsage, 254 MemQuota: instance.MemQuota, 255 MemUsage: instance.MemUsage, 256 } 257 cmd.pluginAppModel.Instances = append(cmd.pluginAppModel.Instances, instanceFields) 258 } 259 if cmd.pluginAppModel.Instances == nil { 260 cmd.pluginAppModel.Instances = []plugin_models.GetApp_AppInstanceFields{} 261 } 262 263 for i := range getSummaryApp.Routes { 264 routeSummary := plugin_models.GetApp_RouteSummary{ 265 Host: getSummaryApp.Routes[i].Host, 266 Guid: getSummaryApp.Routes[i].GUID, 267 Domain: plugin_models.GetApp_DomainFields{ 268 Name: getSummaryApp.Routes[i].Domain.Name, 269 Guid: getSummaryApp.Routes[i].Domain.GUID, 270 }, 271 Path: getSummaryApp.Routes[i].Path, 272 Port: getSummaryApp.Routes[i].Port, 273 } 274 cmd.pluginAppModel.Routes = append(cmd.pluginAppModel.Routes, routeSummary) 275 } 276 if cmd.pluginAppModel.Routes == nil { 277 cmd.pluginAppModel.Routes = []plugin_models.GetApp_RouteSummary{} 278 } 279 280 for i := range getSummaryApp.Services { 281 serviceSummary := plugin_models.GetApp_ServiceSummary{ 282 Name: getSummaryApp.Services[i].Name, 283 Guid: getSummaryApp.Services[i].GUID, 284 } 285 cmd.pluginAppModel.Services = append(cmd.pluginAppModel.Services, serviceSummary) 286 } 287 if cmd.pluginAppModel.Services == nil { 288 cmd.pluginAppModel.Services = []plugin_models.GetApp_ServiceSummary{} 289 } 290 }