Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doctor Database, Reloading and Command Checks #1334

Merged
merged 7 commits into from
Oct 26, 2016
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/convox/convox.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func init() {
stdcli.DefaultWriter.Tags["release"] = stdcli.RenderAttributes(39)
stdcli.DefaultWriter.Tags["security"] = stdcli.RenderAttributes(226)
stdcli.DefaultWriter.Tags["service"] = stdcli.RenderAttributes(39)
stdcli.DefaultWriter.Tags["resource"] = stdcli.RenderAttributes(141)
stdcli.DefaultWriter.Tags["database"] = stdcli.RenderAttributes(141)
stdcli.DefaultWriter.Tags["success"] = stdcli.RenderAttributes(10)
stdcli.DefaultWriter.Tags["unsupported"] = stdcli.RenderAttributes(220)
stdcli.DefaultWriter.Tags["warning"] = stdcli.RenderAttributes(172)
Expand Down
184 changes: 34 additions & 150 deletions cmd/convox/doctor.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ var (
checkAppExposesPorts,
}

runResourceChecks = []func(*manifest.Manifest) error{
checkAppDefinesResource,
checkValidResources,
runDatabaseChecks = []func(*manifest.Manifest) error{
checkAppDefinesDatabase,
checkValidDatabases,
}

runLinkChecks = []func(*manifest.Manifest) error{
Expand Down Expand Up @@ -146,7 +146,7 @@ func cmdDoctor(c *cli.Context) error {
Title: "<file>docker-compose.yml</file> found",
Description: "<fail>A docker-compose.yml file is required to define Services</fail>",
Kind: "fail",
DocsLink: "https://convox.com/guide/service/",
DocsLink: "https://convox.com/guide/services/",
})
} else {
diagnose(Diagnosis{
Expand Down Expand Up @@ -177,8 +177,8 @@ func cmdDoctor(c *cli.Context) error {
}
}

stdcli.Writef("\n\n### Run: Resource\n")
for _, check := range runResourceChecks {
stdcli.Writef("\n\n### Run: Database\n")
for _, check := range runDatabaseChecks {
if err := check(m); err != nil {
return stdcli.Error(err)
}
Expand Down Expand Up @@ -336,7 +336,7 @@ func checkDockerfile() error {
Title: title,
Description: "<fail>A Dockerfile is required to build an Image</fail>",
Kind: "fail",
DocsLink: "https://convox.com/guide/build/",
DocsLink: "https://convox.com/guide/builds/",
})
} else {
diagnose(Diagnosis{
Expand Down Expand Up @@ -748,34 +748,6 @@ func checkMissingEnv(m *manifest.Manifest) error {
return nil
}

// func syncVolumeConflict(m *manifest.Manifest) error {
// for _, s := range m.Services {
// sps, err := s.SyncPaths()
// if err != nil {
// return err
// }

// for _, v := range s.Volumes {
// parts := strings.Split(v, ":")
// if len(parts) == 2 {
// for k, _ := range sps {
// if k == parts[0] {
// // diagnose(Diagnosis{
// // Kind: "warning",
// // DocsLink: "#TODO",
// // Description: fmt.Sprintf(
// // "<description>service: %s has a sync path conflict with volume %s</description>",
// // s.Name,
// // v),
// // })
// }
// }
// }
// }
// }
// return nil
// }

func checkMissingDockerFiles(m *manifest.Manifest) error {
title := "Dockerfiles found"
startCheck(title)
Expand All @@ -789,7 +761,7 @@ func checkMissingDockerFiles(m *manifest.Manifest) error {
diagnose(Diagnosis{
Title: title,
Kind: "fail",
DocsLink: "https://convox.com/guide/image/",
DocsLink: "https://convox.com/guide/images/",
Description: fmt.Sprintf("<fail>Service <service>%s</service> is missing a Dockerfile</fail>", s.Name),
})
}
Expand Down Expand Up @@ -839,7 +811,7 @@ func checkValidServices(m *manifest.Manifest) error {
diagnose(Diagnosis{
Title: title,
Kind: "fail",
DocsLink: "http://convox.com/guide/service/",
DocsLink: "http://convox.com/guide/services/",
Description: fmt.Sprintf("<fail>Service <service>%s</service> doesn't have a valid command</fail>", s.Name),
})
}
Expand All @@ -862,17 +834,17 @@ func checkAppExposesPorts(m *manifest.Manifest) error {
diagnose(Diagnosis{
Title: title,
Kind: "warning",
DocsLink: "http://convox.com/guide/balancer/",
DocsLink: "http://convox.com/guide/balancers/",
Description: "<warning>This app does not expose any ports</warning>",
})
return nil
}

func checkAppDefinesResource(m *manifest.Manifest) error {
title := "App defines Resources"
func checkAppDefinesDatabase(m *manifest.Manifest) error {
title := "App defines Database"
startCheck(title)

if len(manifestResources(m)) > 0 {
if len(manifestDatabases(m)) > 0 {
diagnose(Diagnosis{
Title: title,
Kind: "success",
Expand All @@ -883,21 +855,21 @@ func checkAppDefinesResource(m *manifest.Manifest) error {
diagnose(Diagnosis{
Title: title,
Kind: "warning",
DocsLink: "http://convox.com/guide/resource/",
Description: "<warning>This app does not define any Resources</warning>",
DocsLink: "http://convox.com/guide/databases/",
Description: "<warning>This app does not define any Databases</warning>",
})
return nil
}

func checkValidResources(m *manifest.Manifest) error {
rs := manifestResources(m)
func checkValidDatabases(m *manifest.Manifest) error {
rs := manifestDatabases(m)

if len(rs) == 0 {
return nil
}

for _, s := range rs {
title := fmt.Sprintf("Resource <resource>%s</resource> is valid", s.Name)
title := fmt.Sprintf("Database <database>%s</database> is valid", s.Name)
startCheck(title)

diagnose(Diagnosis{
Expand All @@ -912,15 +884,15 @@ func checkValidResources(m *manifest.Manifest) error {
func manifestServices(m *manifest.Manifest) []manifest.Service {
services := []manifest.Service{}

resources := manifestResources(m)
resourceNames := map[string]bool{}
databases := manifestDatabases(m)
databaseNames := map[string]bool{}

for _, r := range resources {
resourceNames[r.Name] = true
for _, d := range databases {
databaseNames[d.Name] = true
}

for _, s := range m.Services {
if _, ok := resourceNames[s.Name]; ok {
if _, ok := databaseNames[s.Name]; ok {
continue
}
services = append(services, s)
Expand All @@ -929,18 +901,18 @@ func manifestServices(m *manifest.Manifest) []manifest.Service {
return services
}

func manifestResources(m *manifest.Manifest) []manifest.Service {
resources := []manifest.Service{}
func manifestDatabases(m *manifest.Manifest) []manifest.Service {
databases := []manifest.Service{}

for _, s := range m.Services {
prebuiltImage := strings.HasPrefix(s.Image, "convox/")
noCommand := s.Command.String == "" && s.Command.Array == nil
if prebuiltImage && noCommand {
resources = append(resources, s)
databases = append(databases, s)
}
}

return resources
return databases
}

func checkAppDefinesLink(m *manifest.Manifest) error {
Expand All @@ -960,7 +932,7 @@ func checkAppDefinesLink(m *manifest.Manifest) error {
diagnose(Diagnosis{
Title: title,
Kind: "warning",
DocsLink: "http://convox.com/guide/link/",
DocsLink: "http://convox.com/guide/links/",
Description: "<warning>This app does not define any Links</warning>",
})
return nil
Expand Down Expand Up @@ -1001,7 +973,7 @@ func checkValidLinks(m *manifest.Manifest) error {
diagnose(Diagnosis{
Title: title,
Kind: "fail",
DocsLink: "https://convox.com/guide/link/",
DocsLink: "https://convox.com/guide/links/",
Description: fmt.Sprintf("<fail>Service <service>%s</service> not expecting %s</fail>", s.Name, strings.Join(missingEnv, ", ")),
})
}
Expand All @@ -1011,18 +983,18 @@ func checkValidLinks(m *manifest.Manifest) error {
})
}

resources := manifestResources(m)
databases := manifestDatabases(m)

for _, r := range resources {
title := fmt.Sprintf("Resource <resource>%s</resource> exposes internal port", r.Name)
for _, r := range databases {
title := fmt.Sprintf("Database <database>%s</database> exposes internal port", r.Name)

if _, ok := resourceNames[r.Name]; ok {
if len(r.InternalPorts()) == 0 {
diagnose(Diagnosis{
Title: title,
Kind: "error",
DocsLink: "http://convox.com/guide/link/",
Description: fmt.Sprintf("<warning>Resource <resource>%s</resource> does not expose an internal port</warning>", r.Name),
DocsLink: "http://convox.com/guide/links/",
Description: fmt.Sprintf("<warning>Database <database>%s</database> does not expose an internal port</warning>", r.Name),
})
} else {
diagnose(Diagnosis{
Expand All @@ -1035,91 +1007,3 @@ func checkValidLinks(m *manifest.Manifest) error {

return nil
}

// func checkUnsupportedFeatures(m *manifest.Manifest) error {
// dc, err := ioutil.ReadFile("docker-compose.yml")
// if err != nil {
// return err
// }

// r, err := m.Raw()
// if err != nil {
// return err
// }

// dcLines := strings.Split(string(dc), "\n")
// rLines := strings.Split(string(r), "\n")

// adds := 0
// discoveries := make([][]int, 0)
// current := make([]int, 0)
// removes := 0

// d := difflib.Diff(rLines, dcLines)

// for x, dr := range d {
// switch dr.Delta {
// case 0:
// if len(current) > 0 {
// discoveries = append(discoveries, []int{current[0], len(current)})
// current = []int{}
// }
// removes = 0
// case 1:
// adds++
// removes++
// case 2:
// if removes == 0 {
// current = append(current, x-adds)
// } else {
// removes--
// }
// }
// }

// for _, d := range discoveries {
// parts := []string{}

// head := dcLines[:d[0]]
// tail := dcLines[d[0]+d[1]:]
// max := len(dcLines)

// switch {
// case len(head) == 1:
// num := d[0] - 1
// parts = append(parts, numberedLine(fmt.Sprintf("<description>%s</description>", dcLines[num]), num, max))
// case len(head) >= 2:
// num1 := d[0] - 2
// num2 := d[0] - 1
// parts = append(parts, numberedLine(fmt.Sprintf("<description>%s</description>", dcLines[num1]), num1, max))
// parts = append(parts, numberedLine(fmt.Sprintf("<description>%s</description>", dcLines[num2]), num2, max))
// }

// for x := d[0]; x < (d[0] + d[1]); x++ {
// parts = append(parts, numberedLine(fmt.Sprintf("<warning>%s</warning>", dcLines[x]), x, max))
// }

// switch {
// case len(tail) == 1:
// parts = append(parts, numberedLine(fmt.Sprintf("<description>%s</description>", tail[0]), d[0]+d[1], max))
// case len(tail) >= 2:
// parts = append(parts, numberedLine(fmt.Sprintf("<description>%s</description>", tail[0]), d[0]+d[1], max))
// parts = append(parts, numberedLine(fmt.Sprintf("<description>%s</description>", tail[1]), d[0]+d[1]+1, max))
// }

// // diagnose(Diagnosis{
// // Title: "It looks like you are using docker-compose features that convox doesn't support",
// // Kind: "warning",
// // Description: strings.Join(parts, "\n"),
// // DocsLink: "#TODO",
// // })
// }

// return nil
// }

// func numberedLine(line string, num, maxNum int) string {
// b := len(fmt.Sprintf("%d", maxNum))
// format := fmt.Sprintf("<linenumber>%%0%dd:</linenumber> %%s", b)
// return fmt.Sprintf(format, num+1, line)
// }