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

Basic port-test capabilities before trying to bring up router, fixes #126, fixes #393 #483

Merged
merged 16 commits into from
Nov 2, 2017

Conversation

rfay
Copy link
Member

@rfay rfay commented Sep 27, 2017

The Problem/Issue/Bug:

#126 explains: we need to test ports 80 and 443 before we let docker-compose try to bring up the router. If we find that somebody is already listening on them, we need to explain the problem to the user gracefully and provide resources to resolve the problem.

This also fixes #393 (Stopped site, double notifications of broken router)

How this PR Solves The Problem:

  • Stop the router before starting it again.
  • Test our ports at that time
  • If there's a problem stop then and explain to the user, giving resources.

Manual Testing Instructions:

  • Stop all sites (or manually use docker to stop the router)
  • Occupy port 80 or 443 using a technique like docker run -p 80:80 -p 443:443 --entrypoint=/bin/cat -it --rm busybox You can also start netcat or apache or nginx or many other ways.
  • Run ddev start with or without, you should see correct behavior.

To test the fix for #393

  • Start one site
  • Stop the router using docker docker stop ddev-router
  • Use ddev list and ddev describe to look for the issue

This now has:

  • Documentation (troubleshooting) links to help people to resolve their issue.
  • An automated test to verify behavior.
  • A link to the troubleshooting docs when this problem happens.

Automated Testing Overview:

Added TestRouterPortsCheck() which occupies port 80 using a docker container and then tests to see if we can start the router.

Related Issue Link(s):

OP #126

Release/Deployment notes:

@rfay rfay self-assigned this Sep 27, 2017
@rfay rfay force-pushed the 20170926_test_port_80 branch 3 times, most recently from 74fa0cd to 78f2c56 Compare September 28, 2017 13:48
@rfay
Copy link
Member Author

rfay commented Sep 28, 2017

This should be ready for review. @rickmanelius it probably deserves manual testing from you to see if it accomplishes what we need at this point.

@rickmanelius
Copy link
Contributor

Happy to assist with a manual review.

Copy link
Contributor

@rickmanelius rickmanelius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preparation

  • git fetch --all
  • git checkout rfay/20170926_test_port_80
  • make clean && make darwin
  • Confirmed ddev version outputs v0.9.1-17-g78f2c569
  • Stop all ddev sites.

Review

Suggestions

  • At least on macOS, running lsof doesn't require sudo.
  • I'm guilty of using OS X and macOS interchangeably, but macOS is the accurate term.

@rickmanelius
Copy link
Contributor

@rfay I still think it would be of value for @tannerjfco to complete a code review, but manual end-user testing was a +1 from me.

or `sudo launchctl stop homebrew.mxcl.nginx`
* nginx (Ubuntu): `sudo service nginx stop`
* apache (often named "httpd") (many environments): `sudo apachectl stop` or on Ubuntu `sudo service apache2 stop`
* vpnkit (OSX): You likely have a docker container bound to port 80, do you have containers up for Kalabox or another docker-based development environment? If so, stop the other environment.
Copy link
Contributor

@beeradb beeradb Sep 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would put this "some suggestions" section at the top before the lsof stuff. Perhaps renaming it to "Common tools that use port 80" or similar. I feel like most people just want a fast solution, and if they see something like mamp/apache that they've previously used, would just jump right to that.

Also, a suggested addition:

  • Kalabox: If you have previously used Kalabox try running kbox poweroff

@rfay
Copy link
Member Author

rfay commented Sep 28, 2017

I went ahead and added a commit to fix all usages of OSX. Not actually legitimate to do here, but it seems pretty harmless. Didn't make sense to fix this PR without fixing other usages. I didn't change the sudo on lsof because it is required on Ubuntu and just seemed like it would muck things up to make the difference.

Copy link
Contributor

@tannerjfco tannerjfco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on this, thanks @rfay! A couple comments and questions here.

@@ -76,8 +79,20 @@ func StartDdevRouter() error {
_, err = f.WriteString(doc.String())
util.CheckErr(err)

// Stop router so we can test port. Of course, it may not be running.
err = dockerutil.ComposeCmd([]string{dest}, "-p", RouterProjectName, "down")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't we check for our healthy router instead? If we already have our router running, we already have the ports we require, so why stop it and start over? It seems like stopping it could also allow for breaking already-running sites, should the new site encounter an error that results in the router not returning successfully

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related idea: We could probably generally check running docker containers for ports occupied and report back if a specific container has our port. It's a nice idea from viewpoint of giving user most specific path to resolution, but not sure if it's worth it overall.

Copy link
Contributor

@beeradb beeradb Oct 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure we could create a FindContainerByName() and look for "ddev-router" and that would be a faster & more stable check.

Between GetDockerContainers():
https://github.com/drud/ddev/blob/a0ee2e90c0aa388659d721b4b3f316727fba5506/pkg/dockerutil/dockerutils.go#L55-L60

and ContainerName()

https://github.com/drud/ddev/blob/a0ee2e90c0aa388659d721b4b3f316727fba5506/pkg/dockerutil/dockerutils.go#L161-L164

we already have the primitives. just need to loop the containers and check the name and ensure they are running.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand all the comments here, the gist is "Let's not stop the router to test. If it's running, call it good and assume we have the ports." I'm good with that and can use the suggested techniques to do it. Slack link to full conversation: #483 (comment)

## Webserver ports are already occupied by another webserver

If you get a message from ddev about a port conflict on port 80 or 443, like this:
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

silly nit, but for best results w/ MkDocs' markdown parsing (what we're using on RTD), I suggest empty lines before and after formatting such as this. GitHub's markdown parsing is fantastic and doesn't seem to break much on this kind of thing anymore, but I've had to go back and fix little frustrations like this later in RTD.

Copy link
Member Author

@rfay rfay Oct 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 278c462, thanks.

```
sudo apachectl stop
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(suggestion) Just a little more text here would help it flow: e.g. "There are many applications that could be using port 80. Here are some more common tools and how to stop them".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also fixed in 278c462

@@ -33,7 +33,7 @@ provide a working environment for development.`,
func appStart() {
app, err := platform.GetActiveApp("")
if err != nil {
util.Failed("Failed to start: %s", err)
util.Failed("Failed to GetActiveApp err: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this error carries a bit more meaning for us, but less meaning for users. we also lose the context of what command produced the failure. I'd prefer to keep the original error message. If we need better identification of GetActiveApp errors, maybe we could address that in the error messages it returns?

Copy link
Member Author

@rfay rfay Oct 31, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 40cfd5b, good point.

@@ -96,6 +111,7 @@ func StartDdevRouter() error {

// PrintRouterStatus outputs router status and warning if not
// running or healthy, as applicable.
// An easy way to make these ports unavailable: sudo netcat -l -p 80 (brew install netcat)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment seems out of place.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's actually intended here, but I added to it "In order to test this". The comment was to remind anybody how you'd test the port being occupied without a major effort of setting up apache or something.

}
err = CheckRouterPorts()
if err != nil {
return fmt.Errorf("Unable to listen on required ports, %v,\nTroubleshooting suggestions at https://github.com/drud/ddev/blob/master/docs/users/troubleshooting.md", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please link to an anchor just for troubleshooting ports in this. Right now, the entire troubleshooting doc is great, but as it grows we don't we want to avoid sending people to a sea of information, particularly if we have already identified their problem.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The actual usage is like this in StartDdevRouter():

	err = CheckRouterPorts()
	if err != nil {
		return fmt.Errorf("Unable to listen on required ports, %v,\nTroubleshooting suggestions at https://github.com/drud/ddev/blob/master/docs/users/troubleshooting.md", err)
	}

I assume that's what you'd want.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I may not have been clear enough. Sorry!

As you know, this PR introduces a new troubleshooting.md document. We're linking to it right here.

This works well for now, as the document is small, and finding information in it is very easy. However, this troubleshooting.md document is likely to grow over time. As such, it would be great to create anchors in it and link directly to those. That way if we add 3 more pages of information to the troubleshooting document over time, the user is still getting sent to an anchor that covers their specific issue. In this case, we'd want to link directly to the "Webserver ports are already occupied by another webserver" section of that file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added anchor in 4ccd462

Copy link
Contributor

@beeradb beeradb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works as intended but there are some small improvements to the code and messaging that could be made.

@rfay
Copy link
Member Author

rfay commented Oct 17, 2017

Rebased to current master.

@rfay rfay changed the title Basic port-test capabilities before trying to bring up router, fixes #126 Basic port-test capabilities before trying to bring up router, fixes #126, fixes #393 Oct 31, 2017
@rfay
Copy link
Member Author

rfay commented Oct 31, 2017

I think everybody's requests are addressed, most importantly, we don't stop the router just to see if we can start it again.

if err != nil || container.State != "running" {
err = CheckRouterPorts()
if err != nil {
return fmt.Errorf("Unable to listen on required ports, %v,\nTroubleshooting suggestions at https://github.com/drud/ddev/blob/master/docs/users/troubleshooting.md#unable-listen", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Troubleshooting link should be to our readthedocs site vs github.

Copy link
Contributor

@tannerjfco tannerjfco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@rickmanelius
Copy link
Contributor

Given that I believe a bulk of the requested changes were on @beeradb, I think once we get a 👍 from him we are good to go.

Copy link
Contributor

@beeradb beeradb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works as advertised and the code looks good. Thanks!

@rfay rfay merged commit d500dab into ddev:master Nov 2, 2017
@rfay rfay deleted the 20170926_test_port_80 branch November 2, 2017 19:36
@rickmanelius rickmanelius mentioned this pull request Nov 20, 2017
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Stopped site can result in double notifications about router
4 participants