Skip to content

Commit

Permalink
Track and list stopped/removed projects, fixes #642 (#1600)
Browse files Browse the repository at this point in the history
* Add stopped projects to ddev list, fixes #642
* Make list, start, stop, etc work with global
* add stop --unlist command
* Make ddev list --all work
* Refactor GetProjects() to include docker label view
* Add interval config to ddev list --continuous --continuous-sleep-interval
* Don't wholesale destroy running projects, just Test projects
  • Loading branch information
rfay committed May 29, 2019
1 parent a517b1c commit d3201a6
Show file tree
Hide file tree
Showing 34 changed files with 594 additions and 358 deletions.
2 changes: 1 addition & 1 deletion .buildkite/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ set -o pipefail
set -o nounset
set -x

rm -rf ~/.ddev/Test*
rm -rf ~/.ddev/Test* ~/.ddev/global_config.yaml

# There are discrepancies in golang hash checking in 1.11+, so kill off modcache to solve.
# See https://github.com/golang/go/issues/27925
Expand Down
1 change: 0 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ testpkg: setup
DDEV_NO_SENTRY=true CGO_ENABLED=0 go test $(USEMODVENDOR) -p 1 -timeout $(TEST_TIMEOUT) -v -installsuffix static -ldflags '$(LDFLAGS)' ./pkg/... $(TESTARGS)

setup:
@(mv -f ~/.ddev/global_config.yaml ~/.ddev/global_config.yaml.bak 2>/dev/null && echo "Warning: Removed your global ddev config file") || true
@mkdir -p $(GOTMP)/{src,pkg/mod/cache,.cache}
@mkdir -p $(TESTTMP)

Expand Down
4 changes: 2 additions & 2 deletions cmd/ddev/cmd/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ func TestConfigSetValues(t *testing.T) {
"--mailhog-port", mailhogPort,
}

_, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
out, err := exec.RunCommand(DdevBin, args)
assert.NoError(err, "error running ddev %v: %v, output=%s", args, err, out)

configFile := filepath.Join(tmpdir, ".ddev", "config.yaml")
configContents, err := ioutil.ReadFile(configFile)
Expand Down
2 changes: 1 addition & 1 deletion cmd/ddev/cmd/debug-nfsmount_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestDebugNFSMount(t *testing.T) {

// Running config creates a line in global config
//nolint: errcheck
defer exec.RunCommand("remove", []string{"--remove-data"})
defer exec.RunCommand(DdevBin, []string{"stop", "-RO"})

// Test basic `ddev debug nfsmount`
args = []string{"debug", "nfsmount"}
Expand Down
39 changes: 16 additions & 23 deletions cmd/ddev/cmd/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,6 @@ running 'ddev stop <projectname>.`,
util.Failed("Failed to describe %s: %v", project.Name, err)
}

project, err = ddevapp.GetActiveApp(project.Name)
if err != nil {
util.Failed("Unable to find any active project named %s: %v", project.Name, err)
}

// Do not show any describe output if we can't find the project.
if project.SiteStatus() == ddevapp.SiteNotFound {
util.Failed("no project found. have you run 'ddev start'?")
}

desc, err := project.Describe()
if err != nil {
util.Failed("Failed to describe project %s: %v", project.Name, err)
Expand All @@ -64,22 +54,25 @@ func renderAppDescribe(desc map[string]interface{}) (string, error) {
maxWidth := uint(200)
var output string

status := desc["status"]

appTable := ddevapp.CreateAppTable()
ddevapp.RenderAppRow(appTable, desc)
output = fmt.Sprint(appTable)

output = output + "\n\nProject Information\n-----------------\n"
siteInfo := uitable.New()
siteInfo.AddRow("PHP version:", desc["php_version"])
siteInfo.AddRow("URLs:", strings.Join(desc["urls"].([]string), ", "))
output = output + fmt.Sprint(siteInfo)
dockerIP, err := dockerutil.GetDockerIP()
if err != nil {
return "", err
}

// Only show extended status for running sites.
if desc["status"] == ddevapp.SiteRunning {
if status == ddevapp.SiteRunning {
output = output + "\n\nProject Information\n-----------------\n"
siteInfo := uitable.New()
siteInfo.AddRow("PHP version:", desc["php_version"])

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()

Expand All @@ -103,9 +96,9 @@ func renderAppDescribe(desc map[string]interface{}) (string, error) {
other.AddRow("phpMyAdmin:", desc["phpmyadmin_url"])
}
output = output + fmt.Sprint(other)
}

output = output + "\n" + ddevapp.RenderRouterStatus() + "\t" + ddevapp.RenderSSHAuthStatus()
output = output + "\n" + ddevapp.RenderRouterStatus() + "\t" + ddevapp.RenderSSHAuthStatus()
}

return output, nil
}
Expand Down
22 changes: 11 additions & 11 deletions cmd/ddev/cmd/describe_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"github.com/drud/ddev/pkg/dockerutil"
"strings"
"testing"

Expand Down Expand Up @@ -112,36 +113,35 @@ func TestCmdDescribe(t *testing.T) {
// TestCmdDescribeAppFunction performs unit tests on the describeApp function from the working directory.
func TestCmdDescribeAppFunction(t *testing.T) {
assert := asrt.New(t)
for _, v := range DevTestSites {
for i, v := range DevTestSites {
cleanup := v.Chdir()

app, err := ddevapp.GetActiveApp("")
assert.NoError(err)

desc, err := app.Describe()
assert.NoError(err)
assert.EqualValues(desc["status"], ddevapp.SiteRunning)
assert.EqualValues(ddevapp.SiteRunning, desc["status"])
assert.EqualValues(app.GetName(), desc["name"])
assert.EqualValues(ddevapp.RenderHomeRootedDir(v.Dir), desc["shortroot"].(string))
assert.EqualValues(v.Dir, desc["approot"].(string))

out, _ := json.Marshal(desc)
assert.Contains(string(out), app.GetHTTPURL())
assert.Contains(string(out), app.GetName())
assert.Contains(string(out), "\"router_status\":\"healthy\"")
assert.Contains(string(out), ddevapp.RenderHomeRootedDir(v.Dir))
assert.Equal(app.GetHTTPURL(), desc["httpurl"])
assert.Equal(app.GetName(), desc["name"])
assert.Equal("healthy", desc["router_status"], "project #%d %s desc does not have healthy router status", i, app.Name)
assert.Equal(v.Dir, desc["approot"])

// Stop the router using docker and then check the describe
_, err = exec.RunCommand("docker", []string{"stop", "ddev-router"})
assert.NoError(err)
desc, err = app.Describe()
assert.NoError(err)
out, _ = json.Marshal(desc)
assert.NoError(err)
assert.Contains(string(out), "router_status\":\"exited")
assert.Equal("exited", desc["router_status"])
_, err = exec.RunCommand("docker", []string{"start", "ddev-router"})
assert.NoError(err)

_, err = dockerutil.ContainerWait(10, map[string]string{"com.docker.compose.service": "ddev-router"})
assert.NoError(err)

cleanup()
}
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/ddev/cmd/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ var DdevExecCmd = &cobra.Command{
util.Failed("Failed to exec command: %v", err)
}

if strings.Contains(app.SiteStatus(), ddevapp.SiteNotFound) {
if strings.Contains(app.SiteStatus(), ddevapp.SiteStopped) {
util.Failed("Project is not currently running. Try 'ddev start'.")
}

Expand Down
111 changes: 55 additions & 56 deletions cmd/ddev/cmd/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,60 +24,59 @@ func TestCmdExecBadArgs(t *testing.T) {
func TestCmdExec(t *testing.T) {

assert := asrt.New(t)
for _, v := range DevTestSites {
cleanup := v.Chdir()

// Test default invocation
args := []string{"exec", "pwd"}
out, err := exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.Contains(out, "/var/www/html")

// Test specifying service
args = []string{"-s", "db", "exec", "pwd"}
out, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.Contains(out, "/")

// Test specifying working directory
args = []string{"exec", "-d", "/bin", "pwd"}
out, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.Contains(out, "/bin")

// Test specifying service and working directory
args = []string{"exec", "-s", "db", "-d", "/var", "pwd"}
out, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.Contains(out, "/var")

// Test sudo
args = []string{"exec", "sudo", "whoami"}
out, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.Contains(out, "root")

// Test that an nonexistant working directory generates an error
args = []string{"exec", "-d", "/does/not/exist", "pwd"}
out, err = exec.RunCommand(DdevBin, args)
assert.Error(err)
assert.Contains(out, "no such file or directory")

args = []string{"exec", "ls >/var/www/html/TestCmdExec-${OSTYPE}.txt"}
_, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.FileExists(filepath.Join(v.Dir, "TestCmdExec-linux-gnu.txt"))

args = []string{"exec", "ls >/dev/null && touch /var/www/html/TestCmdExec-touch-all-in-one.txt"}
_, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.FileExists(filepath.Join(v.Dir, "TestCmdExec-touch-all-in-one.txt"))

args = []string{"exec", "true", "&&", "touch", "/var/www/html/TestCmdExec-touch-separate-args.txt"}
_, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.FileExists(filepath.Join(v.Dir, "TestCmdExec-touch-separate-args.txt"))

cleanup()
}
v := DevTestSites[0]
cleanup := v.Chdir()

// Test default invocation
args := []string{"exec", "pwd"}
out, err := exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.Contains(out, "/var/www/html")

// Test specifying service
args = []string{"-s", "db", "exec", "pwd"}
out, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.Contains(out, "/")

// Test specifying working directory
args = []string{"exec", "-d", "/bin", "pwd"}
out, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.Contains(out, "/bin")

// Test specifying service and working directory
args = []string{"exec", "-s", "db", "-d", "/var", "pwd"}
out, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.Contains(out, "/var")

// Test sudo
args = []string{"exec", "sudo", "whoami"}
out, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.Contains(out, "root")

// Test that an nonexistant working directory generates an error
args = []string{"exec", "-d", "/does/not/exist", "pwd"}
out, err = exec.RunCommand(DdevBin, args)
assert.Error(err)
assert.Contains(out, "no such file or directory")

args = []string{"exec", "ls >/var/www/html/TestCmdExec-${OSTYPE}.txt"}
_, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.FileExists(filepath.Join(v.Dir, "TestCmdExec-linux-gnu.txt"))

args = []string{"exec", "ls >/dev/null && touch /var/www/html/TestCmdExec-touch-all-in-one.txt"}
_, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.FileExists(filepath.Join(v.Dir, "TestCmdExec-touch-all-in-one.txt"))

args = []string{"exec", "true", "&&", "touch", "/var/www/html/TestCmdExec-touch-separate-args.txt"}
_, err = exec.RunCommand(DdevBin, args)
assert.NoError(err)
assert.FileExists(filepath.Join(v.Dir, "TestCmdExec-touch-separate-args.txt"))

cleanup()
}
2 changes: 1 addition & 1 deletion cmd/ddev/cmd/hostname.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func removeInactiveHostnames(hosts goodhosts.Hosts) {

// Get the list active hosts names to preserve
activeHostNames := make(map[string]bool)
for _, app := range ddevapp.GetDockerProjects() {
for _, app := range ddevapp.GetActiveProjects() {
for _, h := range app.GetHostnames() {
activeHostNames[h] = true
}
Expand Down
61 changes: 30 additions & 31 deletions cmd/ddev/cmd/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,38 +16,37 @@ import (
func TestImportTilde(t *testing.T) {
assert := asrt.New(t)

for _, site := range DevTestSites {

homedir, err := gohomedir.Dir()
assert.NoError(err)
cwd, _ := os.Getwd()
testFile := filepath.Join(homedir, "testfile.tar.gz")
err = fileutil.CopyFile(filepath.Join(cwd, "testdata", "testfile.tar.gz"), testFile)
assert.NoError(err)

cleanup := site.Chdir()
defer rmFile(testFile)

// this ~ should be expanded by shell
args := []string{"import-files", "--src", "~/testfile.tar.gz"}
out, err := exec.RunCommand(DdevBin, args)
if err != nil {
t.Log("Error Output from ddev import-files:", out, site)
}
assert.NoError(err)
assert.Contains(string(out), "Successfully imported files")

// this ~ is not expanded by shell, ddev should convert it to a valid path
args = []string{"import-files", "--src=~/testfile.tar.gz"}
out, err = exec.RunCommand(DdevBin, args)
if err != nil {
t.Log("Error Output from ddev import-files:", out, site)
}
assert.NoError(err)
assert.Contains(string(out), "Successfully imported files")

cleanup()
site := DevTestSites[0]

homedir, err := gohomedir.Dir()
assert.NoError(err)
cwd, _ := os.Getwd()
testFile := filepath.Join(homedir, "testfile.tar.gz")
err = fileutil.CopyFile(filepath.Join(cwd, "testdata", "testfile.tar.gz"), testFile)
assert.NoError(err)

cleanup := site.Chdir()
defer rmFile(testFile)

// this ~ should be expanded by shell
args := []string{"import-files", "--src", "~/testfile.tar.gz"}
out, err := exec.RunCommand(DdevBin, args)
if err != nil {
t.Log("Error Output from ddev import-files:", out, site)
}
assert.NoError(err)
assert.Contains(string(out), "Successfully imported files")

// this ~ is not expanded by shell, ddev should convert it to a valid path
args = []string{"import-files", "--src=~/testfile.tar.gz"}
out, err = exec.RunCommand(DdevBin, args)
if err != nil {
t.Log("Error Output from ddev import-files:", out, site)
}
assert.NoError(err)
assert.Contains(string(out), "Successfully imported files")

cleanup()

assert.NoError(nil)
}
Expand Down

0 comments on commit d3201a6

Please sign in to comment.