Skip to content

Commit

Permalink
Allow wildcard additional_hostnames, fixes #2391 (#2393)
Browse files Browse the repository at this point in the history
  • Loading branch information
rfay committed Sep 4, 2020
1 parent 186190f commit 2ea1def
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -133,7 +133,7 @@ staticrequired: setup golangci-lint markdownlint mkdocs
markdownlint:
@echo "markdownlint: "
@sleep 1 && $(DOCKERTESTCMD) \
bash -c "markdownlint *.md docs >/dev/null 2>&1"
bash -c "markdownlint *.md docs 2>&1"
mkdocs:
@echo "mkdocs: "
@sleep 1 && $(DOCKERTESTCMD) \
Expand Down
11 changes: 7 additions & 4 deletions docs/users/extend/additional-hostnames.md
Expand Up @@ -6,14 +6,17 @@ Add additional hostnames to a project in the project's .ddev/config.yaml:
name: mysite
additional_hostnames:
- extraname
- fr.mysite
- es.mysite
- it.mysite
- "extraname"
- "fr.mysite"
- "es.mysite"
- "it.mysite"
- "*.lotsofnames"
```

This configuration would result in working hostnames of mysite.ddev.site, extraname.ddev.site, fr.mysite.ddev.site, es.mysite.ddev.site, and it.mysite.ddev.site (with full http and https URLs for each).

In addition, the wildcard `*.lotsofnames` will result in anything `*.lotsofnames.ddev.site` being recognized by the project. This works only if you're connected to the internet, using "ddev.site" for your top-level-domain, and using DNS for name lookups. (These are all the defaults.)

**Although we recommend extreme care with this feature**, you can also provide additional_fqdn entries, which don't use the ".ddev.site" top-level domain. **This feature populates your hosts file with entries which may hide the real DNS entries on the internet, causing way too much head-scratching.**

**If you use a FQDN which is resolvable on the internet, you must use `use_dns_when_possible: false` or configure that with `ddev config --use-dns-when-possible=false`.
Expand Down
2 changes: 1 addition & 1 deletion docs/users/extend/config_yaml.md
Expand Up @@ -23,7 +23,7 @@ the .ddev/config.yaml is the primary configuration for the project.
| xdebug_enabled | "true" enables xdebug | Most people use `ddev xdebug` and `ddev xdebug off` instead of configuring this, because xdebug has a significant performance impact. |
| webserver_type | nginx-fpm or apache-fpm | The default is nginx-fpm, and it works best for many projects.|
| timezone | timezone to use in container and in PHP configuration | It can be set to any valid timezone, see [timezone list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). For example "Europe/Dublin" or "MST7MDT". The default is UTC. |
| additional_hostnames | array of extra hostnames | `additional_hostnames: ["somename", "someothername"]` would provide http and https URLs for "somename.ddev.site" and "someothername.ddev.site". |
| additional_hostnames | array of extra hostnames | `additional_hostnames: ["somename", "someothername", "*.thirdname"]` would provide http and https URLs for "somename.ddev.site" and "someothername.ddev.site", as well as "one.thirdname.ddev.site" and "two.thirdname.ddev.site". Note that the wildcard/asterisk setting only works if you're using DNS to resolve hostnames (which is the default) and you're connected to the internet. |
| additional_fqdns | extra fully-qualified domain names | `additional_fqdns: ["example.com", "sub1.example.com"]` would provide http and https URLs for "example.com" and "sub1.example.com". Please take care with this because it can cause great confusion and adds extraneous items to your /etc/hosts file. |
| upload_dir | Relative path to upload directory used by `ddev import-files` | |
| working_dir | explicitly specify the working directory used by `ddev exec` and `ddev ssh` | `working_dir: { web: "/var/www", db: "/etc" }` would set the working directories for the web and db containers. |
Expand Down
5 changes: 5 additions & 0 deletions pkg/ddevapp/config.go
Expand Up @@ -413,6 +413,11 @@ func (app *DdevApp) ValidateConfig() error {

// validate hostnames
for _, hn := range app.GetHostnames() {
// If they have provided "*.<hostname>" then ignore the *. part.
hn = strings.TrimPrefix(hn, "*.")
if hn == "ddev.site" {
return fmt.Errorf("wildcaring the full hostname or using 'ddev.site' as fqdn is not allowed because other projects would not work in that case")
}
if !hostRegex.MatchString(hn) {
return fmt.Errorf("invalid hostname: %s. See https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_hostnames for valid hostname requirements", hn).(invalidHostname)
}
Expand Down
48 changes: 32 additions & 16 deletions pkg/ddevapp/config_test.go
Expand Up @@ -524,21 +524,20 @@ func TestReadConfigCRLF(t *testing.T) {
func TestConfigValidate(t *testing.T) {
assert := asrt.New(t)

cwd, err := os.Getwd()
//pwd, err := os.Getwd()
//assert.NoError(err)

site := TestSites[0]
app, err := NewApp(site.Dir, false, "")
assert.NoError(err)

app := &DdevApp{
Name: "TestConfigValidate",
ConfigPath: filepath.Join("testdata", "config.yaml"),
AppRoot: cwd,
Docroot: "testdata",
Type: nodeps.AppTypeWordPress,
PHPVersion: nodeps.PHPDefault,
MariaDBVersion: version.MariaDBDefaultVersion,
WebserverType: nodeps.WebserverDefault,
ProjectTLD: nodeps.DdevDefaultTLD,
Provider: nodeps.ProviderDefault,
}
t.Cleanup(func() {
err = app.Stop(true, false)
assert.NoError(err)
})

appName := app.Name
appType := app.Type

err = app.ValidateConfig()
if err != nil {
Expand All @@ -550,14 +549,13 @@ func TestConfigValidate(t *testing.T) {
assert.Error(err)
assert.Contains(err.Error(), "not a valid project name")

app.Docroot = "testdata"
app.Name = "valid"
app.Name = appName
app.Type = "potato"
err = app.ValidateConfig()
assert.Error(err)
assert.Contains(err.Error(), "invalid app type")

app.Type = nodeps.AppTypeWordPress
app.Type = appType
app.PHPVersion = "1.1"
err = app.ValidateConfig()
assert.Error(err)
Expand Down Expand Up @@ -591,6 +589,23 @@ func TestConfigValidate(t *testing.T) {
err = app.ValidateConfig()
assert.NoError(err)
}

// Make sure that wildcards work
app.AdditionalHostnames = []string{"x", "*.any"}
err = app.ValidateConfig()
assert.NoError(err)
err = app.Start()
assert.NoError(err)
staticURI := site.Safe200URIWithExpectation.URI
_, _, err = testcommon.GetLocalHTTPResponse(t, "http://x.ddev.site/"+staticURI, 1)
assert.NoError(err)
_, _, err = testcommon.GetLocalHTTPResponse(t, "http://somethjingrandom.any.ddev.site/"+staticURI, 1)
assert.NoError(err)

// Make sure that a bare "*" in the additional_hostnames does *not* work
app.AdditionalHostnames = []string{"x", "*"}
err = app.ValidateConfig()
assert.Error(err)
}

// TestWriteConfig tests writing config values to file
Expand Down Expand Up @@ -653,6 +668,7 @@ func TestConfigOverrideDetection(t *testing.T) {

// Copy test overrides into the project .ddev directory
for _, item := range []string{"nginx", "nginx_full", "apache", "php", "mysql"} {
_ = os.RemoveAll(filepath.Join(site.Dir, ".ddev", item))
err := fileutil.CopyDir(filepath.Join(testDir, testDataDdevDir, item), filepath.Join(site.Dir, ".ddev", item))
assert.NoError(err)
}
Expand Down
5 changes: 4 additions & 1 deletion pkg/ddevapp/ddevapp.go
Expand Up @@ -1785,7 +1785,10 @@ func (app *DdevApp) AddHostsEntriesIfNeeded() error {

for _, name := range app.GetHostnames() {
if app.UseDNSWhenPossible && globalconfig.IsInternetActive() {
hostIPs, err := net.LookupHost(name)
// If they have provided "*.<name>" then look up the suffix
checkName := strings.TrimPrefix(name, "*.")
hostIPs, err := net.LookupHost(checkName)

// If we had successful lookup and dockerIP matches
// with adding to hosts file.
if err == nil && len(hostIPs) > 0 && hostIPs[0] == dockerIP {
Expand Down

0 comments on commit 2ea1def

Please sign in to comment.