Skip to content

Commit

Permalink
Improve URL presentation in start/restart/describe, fixes #1711, fixes
Browse files Browse the repository at this point in the history
…#1685 (#1720)

* Refactor to allow access to both http and https URLs
* Change describe to add table of URLs, fixes #1685
* Also adds better db credentials descriptions
  • Loading branch information
rfay committed Jul 23, 2019
1 parent 663194b commit 2148548
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 50 deletions.
41 changes: 21 additions & 20 deletions cmd/ddev/cmd/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package cmd

import (
"fmt"
"strings"

"github.com/drud/ddev/pkg/ddevapp"
"github.com/drud/ddev/pkg/dockerutil"
"github.com/drud/ddev/pkg/output"
Expand Down Expand Up @@ -51,7 +49,6 @@ running 'ddev describe <projectname>.`,
// renderAppDescribe takes the map describing the app and renders it for plain-text output
func renderAppDescribe(desc map[string]interface{}) (string, error) {

maxWidth := uint(200)
var output string

status := desc["status"]
Expand All @@ -62,33 +59,37 @@ func renderAppDescribe(desc map[string]interface{}) (string, error) {

// Only show extended status for running sites.
if status == ddevapp.SiteRunning {
output = output + "\n\nProject Information\n-----------------\n"
dbinfo := desc["dbinfo"].(map[string]interface{})

output = output + "\n\nProject Information\n-------------------\n"
siteInfo := uitable.New()
siteInfo.AddRow("PHP version:", desc["php_version"])
siteInfo.AddRow("MariaDB version", dbinfo["mariadb_version"])

output = output + fmt.Sprintln(siteInfo)
urlTable := uitable.New()
urlTable.MaxColWidth = 80
for _, url := range desc["urls"].([]string) {
urlTable.AddRow(url)
}
output = output + "\nURLs\n----\n"

output = output + fmt.Sprintln(urlTable)

siteInfo.AddRow("URLs:", strings.Join(desc["urls"].([]string), ", "))
output = output + fmt.Sprint(siteInfo)
dockerIP, err := dockerutil.GetDockerIP()
if err != nil {
return "", err
}

output = output + "\n\nMySQL Credentials\n-----------------\n"
dbTable := uitable.New()
output = output + "\n\n" + "MySQL/MariaDB Credentials\n-------------------------\n" + `Username: "db", Password: "db", Default database: "db"` + "\n"
output = output + "\n" + `or use root credentials when needed: Username: "root", Password: "root"` + "\n\n"

dbinfo := desc["dbinfo"].(map[string]interface{})
output = output + "Database hostname and port INSIDE container: db:3306\n"
output = output + fmt.Sprintf("To connect to db server inside container or in project settings files: \nmysql --host=db --user=db --password=db --database=db\n")

output = output + fmt.Sprintf("Database hostname and port from HOST: %s:%d\n", dockerIP, dbinfo["published_port"])
output = output + fmt.Sprintf("To connect to mysql from your host machine, \nmysql --host=%s --port=%d --user=db --password=db --database=db\n", dockerIP, dbinfo["published_port"])

if _, ok := dbinfo["username"].(string); ok {
dbTable.MaxColWidth = maxWidth
dbTable.AddRow("Username:", dbinfo["username"])
dbTable.AddRow("Password:", dbinfo["password"])
dbTable.AddRow("Database name:", dbinfo["dbname"])
dbTable.AddRow("Host:", dbinfo["host"])
dbTable.AddRow("Port:", dbinfo["port"])
dbTable.AddRow("MariaDB version", dbinfo["mariadb_version"])
output = output + fmt.Sprint(dbTable)
output = output + fmt.Sprintf("\nTo connect to mysql from your host machine, use port %d on %s.\nFor example: mysql --host=%s --port=%d --user=db --password=db --database=db", dbinfo["published_port"], dockerIP, dockerIP, dbinfo["published_port"])
}
output = output + "\n\nOther Services\n--------------\n"
other := uitable.New()
other.AddRow("MailHog:", desc["mailhog_url"])
Expand Down
8 changes: 7 additions & 1 deletion cmd/ddev/cmd/restart.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"github.com/drud/ddev/pkg/ddevapp"
"strings"

"github.com/drud/ddev/pkg/dockerutil"
Expand Down Expand Up @@ -39,7 +40,12 @@ var RestartCmd = &cobra.Command{
}

util.Success("Restarted %s", app.GetName())
util.Success("Your project can be reached at %s", strings.Join(app.GetAllURLs(), ", "))
httpURLs, urlList, _ := app.GetAllURLs()
if ddevapp.GetCAROOT() == "" {
urlList = httpURLs
}

util.Success("Your project can be reached at %s", strings.Join(urlList, " "))
}
},
}
Expand Down
9 changes: 4 additions & 5 deletions cmd/ddev/cmd/restart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,12 @@ func TestDevRestart(t *testing.T) {
out, err := exec.RunCommand(DdevBin, args)
assert.NoError(err)

app, err := ddevapp.GetActiveApp("")
_, err = ddevapp.GetActiveApp("")
if err != nil {
assert.Fail("Could not find an active ddev configuration: %v", err)
}

assert.Contains(string(out), "Your project can be reached at")
assert.Contains(string(out), strings.Join(app.GetAllURLs(), ", "))
cleanup()
}

Expand All @@ -37,7 +36,7 @@ func TestDevRestartJSON(t *testing.T) {
cleanup := site.Chdir()
defer cleanup()

app, err := ddevapp.GetActiveApp("")
_, err := ddevapp.GetActiveApp("")
if err != nil {
assert.Fail("Could not find an active ddev configuration: %v", err)
}
Expand All @@ -54,9 +53,9 @@ func TestDevRestartJSON(t *testing.T) {

var item map[string]interface{}
for _, item = range logItems {
if item["level"] == "info" && item["msg"] != nil && strings.Contains(item["msg"].(string), "Your project can be reached at "+strings.Join(app.GetAllURLs(), ", ")) {
if item["level"] == "info" && item["msg"] != nil && strings.Contains(item["msg"].(string), "Your project can be reached at") {
break
}
}
assert.Contains(item["msg"], "Your project can be reached at "+strings.Join(app.GetAllURLs(), ", "))
assert.Contains(item["msg"], "Your project can be reached at")
}
7 changes: 6 additions & 1 deletion cmd/ddev/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ any directory by running 'ddev start projectname [projectname ...]'`,
}

util.Success("Successfully started %s", project.GetName())
util.Success("Project can be reached at %s", strings.Join(project.GetAllURLs(), ", "))
httpURLs, urlList, _ := project.GetAllURLs()
if ddevapp.GetCAROOT() == "" {
urlList = httpURLs
}

util.Success("Project can be reached at %s", strings.Join(urlList, " "))
if project.WebcacheEnabled {
util.Warning("All contents were copied to fast docker filesystem,\nbut bidirectional sync operation may not be fully functional for a few minutes.")
}
Expand Down
24 changes: 10 additions & 14 deletions pkg/ddevapp/ddevapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,10 @@ func (app *DdevApp) Describe() (map[string]interface{}, error) {
appDesc["shortroot"] = shortRoot
appDesc["httpurl"] = app.GetHTTPURL()
appDesc["httpsurl"] = app.GetHTTPSURL()
appDesc["urls"] = app.GetAllURLs()
httpURLs, httpsURLs, allURLs := app.GetAllURLs()
appDesc["httpURLs"] = httpURLs
appDesc["httpsURLs"] = httpsURLs
appDesc["urls"] = allURLs

// Only show extended status for running sites.
if app.SiteStatus() == SiteRunning {
Expand Down Expand Up @@ -1378,8 +1381,7 @@ func (app *DdevApp) GetHTTPSURL() string {
}

// GetAllURLs returns an array of all the URLs for the project
func (app *DdevApp) GetAllURLs() []string {
var URLs []string
func (app *DdevApp) GetAllURLs() (httpURLs []string, httpsURLs []string, allURLs []string) {

// Get configured URLs
for _, name := range app.GetHostnames() {
Expand All @@ -1392,20 +1394,14 @@ func (app *DdevApp) GetAllURLs() []string {
httpsPort = ":" + app.RouterHTTPSPort
}

var url = "https://" + name + httpsPort
if GetCAROOT() == "" {
url = "http://" + name + httpPort
}
URLs = append(URLs, url)
httpsURLs = append(httpsURLs, "https://"+name+httpsPort)
httpURLs = append(httpURLs, "http://"+name+httpPort)
}

if GetCAROOT() != "" {
URLs = append(URLs, app.GetWebContainerDirectHTTPSURL())
} else {
URLs = append(URLs, app.GetWebContainerDirectHTTPURL())
}
httpsURLs = append(httpsURLs, app.GetWebContainerDirectHTTPSURL())
httpURLs = append(httpURLs, app.GetWebContainerDirectHTTPURL())

return URLs
return httpURLs, httpsURLs, append(httpURLs, httpsURLs...)
}

// GetWebContainerDirectHTTPURL returns the URL that can be used without the router to get to web container.
Expand Down
21 changes: 12 additions & 9 deletions pkg/ddevapp/ddevapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,10 @@ func TestDdevStartMultipleHostnames(t *testing.T) {
assert.True(check, "Container check on %s failed", containerType)
}

t.Logf("Testing these URLs: %v", app.GetAllURLs())
for _, url := range app.GetAllURLs() {
_, _, urls := app.GetAllURLs()
t.Logf("Testing these URLs: %v", urls)
_, _, allURLs := app.GetAllURLs()
for _, url := range allURLs {
_, _ = testcommon.EnsureLocalHTTPContent(t, url+site.Safe200URIWithExpectation.URI, site.Safe200URIWithExpectation.Expect)
}

Expand Down Expand Up @@ -2153,16 +2155,16 @@ func TestGetAllURLs(t *testing.T) {
err = app.StartAndWaitForSync(0)
require.NoError(t, err)

urls := app.GetAllURLs()
_, _, urls := app.GetAllURLs()

// Convert URLs to map[string]bool
urlMap := make(map[string]bool)
for _, u := range urls {
urlMap[u] = true
}

// We expect two URLs for each hostname (http/https) and one direct web container address.
expectedNumUrls := len(app.GetHostnames()) + 1
// We expect two URLs for each hostname (http/https) and two direct web container address.
expectedNumUrls := len(app.GetHostnames())*2 + 2
assert.Equal(len(urlMap), expectedNumUrls, "Unexpected number of URLs returned: %d", len(urlMap))

// Ensure urlMap contains direct address of the web container
Expand Down Expand Up @@ -2256,7 +2258,7 @@ func TestWebserverType(t *testing.T) {
func TestInternalAndExternalAccessToURL(t *testing.T) {
assert := asrt.New(t)

runTime := testcommon.TimeTrack(time.Now(), fmt.Sprintf("TestInternalAndExternalAccessToURL"))
runTime := testcommon.TimeTrack(time.Now(), t.Name())

site := TestSites[0]
app := new(ddevapp.DdevApp)
Expand All @@ -2282,7 +2284,7 @@ func TestInternalAndExternalAccessToURL(t *testing.T) {
err = app.StartAndWaitForSync(5)
assert.NoError(err)

urls := app.GetAllURLs()
_, _, urls := app.GetAllURLs()

// Convert URLs to map[string]bool
urlMap := make(map[string]bool)
Expand All @@ -2291,10 +2293,11 @@ func TestInternalAndExternalAccessToURL(t *testing.T) {
}

// We expect two URLs for each hostname (http/https) and two direct web container addresses.
expectedNumUrls := len(app.GetHostnames()) + 1
expectedNumUrls := len(app.GetHostnames())*2 + 2
assert.Equal(len(urlMap), expectedNumUrls, "Unexpected number of URLs returned: %d", len(urlMap))

URLList := append(app.GetAllURLs(), "http://localhost", "http://localhost")
_, _, URLList := app.GetAllURLs()
URLList = append(URLList, "http://localhost", "http://localhost")
for _, item := range URLList {
// Make sure internal (web container) access is successful
parts, err := url.Parse(item)
Expand Down

0 comments on commit 2148548

Please sign in to comment.