github.com/ddev/ddev@v1.23.2-0.20240519125000-d824ffe36ff3/pkg/ddevapp/list.go (about) 1 package ddevapp 2 3 import ( 4 "bytes" 5 "time" 6 7 "github.com/ddev/ddev/pkg/globalconfig" 8 "github.com/ddev/ddev/pkg/nodeps" 9 "github.com/ddev/ddev/pkg/output" 10 "github.com/ddev/ddev/pkg/styles" 11 "github.com/ddev/ddev/pkg/util" 12 "github.com/jedib0t/go-pretty/v6/table" 13 "github.com/jedib0t/go-pretty/v6/text" 14 ) 15 16 // ListCommandSettings conains all filters and settings of the `ddev list` command 17 type ListCommandSettings struct { 18 // ActiveOnly, if set, shows only running projects 19 ActiveOnly bool 20 21 // Continuous, if set, makes list continuously output 22 Continuous bool 23 24 // WrapListTable allow that the text in the table of ddev list wraps instead of cutting it to fit the terminal width 25 WrapTableText bool 26 27 // ContinuousSleepTime is time to sleep between reads with --continuous 28 ContinuousSleepTime int 29 30 // TypeFilter contains the project type which is then used to filter the project list 31 TypeFilter string 32 } 33 34 // List provides the functionality for `ddev list` 35 // activeOnly if true only shows projects that are currently Docker containers 36 // continuous if true keeps requesting and outputting continuously 37 // wrapTableText if true the text is wrapped instead of truncated to fit the row length 38 // continuousSleepTime is the time between reports 39 func List(settings ListCommandSettings) { 40 defer util.TimeTrack()() 41 42 var out bytes.Buffer 43 44 for { 45 apps, err := GetProjects(settings.ActiveOnly) 46 if err != nil { 47 util.Failed("Failed getting GetProjects: %v", err) 48 } 49 50 appDescs := make([]map[string]interface{}, 0) 51 52 if len(apps) < 1 { 53 output.UserOut.WithField("raw", appDescs).Println("No DDEV projects were found.") 54 } else { 55 t := CreateAppTable(&out, settings.WrapTableText) 56 for _, app := range apps { 57 // Filter by project type 58 if settings.TypeFilter != "" && settings.TypeFilter != app.Type { 59 continue 60 } 61 62 desc, err := app.Describe(true) 63 if err != nil { 64 util.Error("Failed to describe project %s: %v", app.GetName(), err) 65 } 66 appDescs = append(appDescs, desc) 67 RenderAppRow(t, desc) 68 } 69 70 routerStatus, _ := GetRouterStatus() 71 var extendedRouterStatus = RenderRouterStatus() 72 if nodeps.ArrayContainsString(globalconfig.DdevGlobalConfig.OmitContainersGlobal, globalconfig.DdevRouterContainer) { 73 extendedRouterStatus = "disabled" 74 } 75 router := globalconfig.DdevGlobalConfig.Router 76 t.AppendFooter(table.Row{ 77 "Router", routerStatus, "~/.ddev", globalconfig.GetRouterURL(), router}, 78 ) 79 t.Render() 80 output.UserOut.WithField("raw", appDescs).Print(out.String()) 81 if routerStatus != "healthy" { 82 rawResult := map[string]string{ 83 "routerStatus": routerStatus, 84 "extendedRouterStatus": extendedRouterStatus, 85 } 86 rawResult["routerStatus"] = routerStatus 87 rawResult["extendedStatus"] = extendedRouterStatus 88 output.UserOut.WithField("raw", rawResult) 89 } 90 } 91 92 if !settings.Continuous { 93 break 94 } 95 96 time.Sleep(time.Duration(settings.ContinuousSleepTime) * time.Second) 97 } 98 } 99 100 // CreateAppTable will create a new app table for describe and list output 101 func CreateAppTable(out *bytes.Buffer, wrapTableText bool) table.Writer { 102 t := table.NewWriter() 103 t.AppendHeader(table.Row{"Name", "Status", "Location", "URL", "Type"}) 104 termWidth, _ := nodeps.GetTerminalWidthHeight() 105 usableWidth := termWidth - 15 106 statusWidth := 7 // Maybe just "running" 107 nameWidth := 10 108 typeWidth := 9 // drupal7, magento2 or wordpress 109 locationWidth := 20 110 urlWidth := 20 111 if termWidth > 80 { 112 urlWidth = urlWidth + (termWidth-80)/2 113 locationWidth = locationWidth + (termWidth-80)/2 114 statusWidth = statusWidth + (termWidth-80)/3 115 } 116 totUsedWidth := nameWidth + statusWidth + locationWidth + urlWidth + typeWidth 117 if !wrapTableText { 118 t.SetAllowedRowLength(termWidth) 119 } 120 121 util.Debug("Detected terminal width=%v usableWidth=%d statusWidth=%d nameWidth=%d locationWidth=%d urlWidth=%d typeWidth=%d totUsedWidth=%d", termWidth, usableWidth, statusWidth, nameWidth, locationWidth, urlWidth, typeWidth, totUsedWidth) 122 t.SortBy([]table.SortBy{{Name: "Name"}}) 123 124 if !globalconfig.DdevGlobalConfig.SimpleFormatting { 125 126 t.SetColumnConfigs([]table.ColumnConfig{ 127 { 128 Name: "Name", 129 //WidthMax: nameWidth, 130 }, 131 { 132 Name: "Status", 133 WidthMax: statusWidth, 134 }, 135 { 136 Name: "Location", 137 //WidthMax: locationWidth, 138 }, 139 { 140 Name: "URL", 141 //WidthMax: urlWidth, 142 }, 143 { 144 Name: "Type", 145 WidthMax: int(typeWidth), 146 WidthMaxEnforcer: text.WrapText, 147 }, 148 }) 149 } 150 styles.SetGlobalTableStyle(t) 151 t.SetOutputMirror(out) 152 return t 153 }