Repository: StackExchange/dnscontrol
Pull request #1983 (2023-01-25 16:37:32)

Domains flag should accept simple wildcards
The `preview` and `push` commands accept a flag `--domains` which restricts which domains are processed.  Currently they are exact matches.  This PR permits a wildcard at the start of the string.  In other words `--domains foo.com,*.10.in-addr.arpa` will match `foo.com`, `0.0.0.10.in-arpa.com`, but not `0.0.0.6.in-addr.arpa.com`.

The goal here isn't to add a complete glob match. We can add that later.

tlimoncelli: NOTE: I haven't updated the docs.  This is a hidden feature.  I want to document it when it supports full globs.

Patch:
diff --git a/commands/commands.go b/commands/commands.go
index b01f043a..82043545 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -294,8 +294,15 @@ func (args *FilterArgs) shouldRunDomain(d string) bool {
 	if args.Domains == "" {
 		return true
 	}
-	for _, dom := range strings.Split(args.Domains, ",") {
-		if dom == d {
+	return domainInList(d, strings.Split(args.Domains, ","))
+}
+
+func domainInList(domain string, list []string) bool {
+	for _, item := range list {
+		if strings.HasPrefix(item, "*") && strings.HasSuffix(domain, item[1:]) {
+			return true
+		}
+		if item == domain {
 			return true
 		}
 	}
diff --git a/documentation/functions/global/D.md b/documentation/functions/global/D.md
index 33a6f315..d6cb9dfd 100644
--- a/documentation/functions/global/D.md
+++ b/documentation/functions/global/D.md
@@ -85,7 +85,7 @@ and `domain.tld!external` you now require humans to remember that
 may have noticed this mistake, but will your coworkers?  Will you in
 six months? You get the idea.
 
-DNSControl command line flag `--domains` is an exact match.  If you
+DNSControl command line flag `--domains` matches the full name (with the "!").  If you
 define domains `example.com!george` and `example.com!john` then:
 
 * `--domains=example.com` will not match either domain.


Test patch:
diff --git a/commands/commands_test.go b/commands/commands_test.go
new file mode 100644
index 00000000..04688973
--- /dev/null
+++ b/commands/commands_test.go
@@ -0,0 +1,63 @@
+package commands
+
+import "testing"
+
+func Test_domainInList(t *testing.T) {
+	type args struct {
+		domain string
+		list   []string
+	}
+	tests := []struct {
+		name string
+		args args
+		want bool
+	}{
+		{
+			name: "small",
+			args: args{
+				domain: "foo.com",
+				list:   []string{"foo.com"},
+			},
+			want: true,
+		},
+		{
+			name: "big",
+			args: args{
+				domain: "foo.com",
+				list:   []string{"example.com", "foo.com", "baz.com"},
+			},
+			want: true,
+		},
+		{
+			name: "missing",
+			args: args{
+				domain: "foo.com",
+				list:   []string{"bar.com"},
+			},
+			want: false,
+		},
+		{
+			name: "wildcard",
+			args: args{
+				domain: "*.10.in-addr.arpa",
+				list:   []string{"bar.com", "10.in-addr.arpa", "example.com"},
+			},
+			want: false,
+		},
+		{
+			name: "wildcardmissing",
+			args: args{
+				domain: "*.10.in-addr.arpa",
+				list:   []string{"bar.com", "6.in-addr.arpa", "example.com"},
+			},
+			want: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := domainInList(tt.args.domain, tt.args.list); got != tt.want {
+				t.Errorf("domainInList() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}