mirror of
https://github.com/notherealmarco/coredns-deployment.git
synced 2025-05-06 04:42:36 +02:00
groundwork (#140)
This commit is contained in:
parent
e6c1d12235
commit
ac020ac1bc
6 changed files with 1082 additions and 0 deletions
178
kubernetes/migration/corefile/corefile.go
Normal file
178
kubernetes/migration/corefile/corefile.go
Normal file
|
@ -0,0 +1,178 @@
|
|||
package corefile
|
||||
|
||||
import (
|
||||
"github.com/mholt/caddy"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Corefile struct {
|
||||
Servers []*Server
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
DomPorts []string
|
||||
Plugins []*Plugin
|
||||
}
|
||||
|
||||
type Plugin struct {
|
||||
Name string
|
||||
Args []string
|
||||
Options []*Option
|
||||
}
|
||||
|
||||
type Option struct {
|
||||
Name string
|
||||
Args []string
|
||||
}
|
||||
|
||||
func New(s string) (Corefile, error) {
|
||||
c := Corefile{}
|
||||
cc := caddy.NewTestController("migration", s)
|
||||
depth := 0
|
||||
var cSvr *Server
|
||||
var cPlg *Plugin
|
||||
for cc.Next() {
|
||||
if cc.Val() == "{" {
|
||||
depth += 1
|
||||
continue
|
||||
} else if cc.Val() == "}" {
|
||||
depth -= 1
|
||||
continue
|
||||
}
|
||||
val := cc.Val()
|
||||
args := cc.RemainingArgs()
|
||||
switch depth {
|
||||
case 0:
|
||||
c.Servers = append(c.Servers,
|
||||
&Server{
|
||||
DomPorts: append([]string{val}, args...),
|
||||
})
|
||||
cSvr = c.Servers[len(c.Servers)-1]
|
||||
case 1:
|
||||
cSvr.Plugins = append(cSvr.Plugins,
|
||||
&Plugin{
|
||||
Name: val,
|
||||
Args: args,
|
||||
})
|
||||
cPlg = cSvr.Plugins[len(cSvr.Plugins)-1]
|
||||
case 2:
|
||||
cPlg.Options = append(cPlg.Options,
|
||||
&Option{
|
||||
Name: val,
|
||||
Args: args,
|
||||
})
|
||||
}
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *Corefile) ToString() (out string) {
|
||||
strs := []string{}
|
||||
for _, s := range c.Servers {
|
||||
strs = append(strs, s.ToString())
|
||||
}
|
||||
return strings.Join(strs, "\n")
|
||||
}
|
||||
|
||||
func (s *Server) ToString() (out string) {
|
||||
str := strings.Join(s.DomPorts, " ")
|
||||
strs := []string{}
|
||||
for _, p := range s.Plugins {
|
||||
strs = append(strs, strings.Repeat(" ", indent)+p.ToString())
|
||||
}
|
||||
if len(strs) > 0 {
|
||||
str += " {\n" + strings.Join(strs, "\n") + "\n}\n"
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
func (p *Plugin) ToString() (out string) {
|
||||
str := strings.Join(append([]string{p.Name}, p.Args...), " ")
|
||||
strs := []string{}
|
||||
for _, o := range p.Options {
|
||||
strs = append(strs, strings.Repeat(" ", indent*2)+o.ToString())
|
||||
}
|
||||
if len(strs) > 0 {
|
||||
str += " {\n" + strings.Join(strs, "\n") + "\n" + strings.Repeat(" ", indent*1) + "}"
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
func (o *Option) ToString() (out string) {
|
||||
str := strings.Join(append([]string{o.Name}, o.Args...), " ")
|
||||
return str
|
||||
}
|
||||
|
||||
func (s *Server) FindMatch(def []*Server) (*Server, bool) {
|
||||
NextServer:
|
||||
for _, sDef := range def {
|
||||
for i, dp := range sDef.DomPorts {
|
||||
if dp == "*" {
|
||||
continue
|
||||
}
|
||||
if dp == "***" {
|
||||
return sDef, true
|
||||
}
|
||||
if i >= len(s.DomPorts) || dp != s.DomPorts[i] {
|
||||
continue NextServer
|
||||
}
|
||||
}
|
||||
if len(sDef.DomPorts) != len(s.DomPorts) {
|
||||
continue
|
||||
}
|
||||
return sDef, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (p *Plugin) FindMatch(def []*Plugin) (*Plugin, bool) {
|
||||
NextPlugin:
|
||||
for _, pDef := range def {
|
||||
if pDef.Name != p.Name {
|
||||
continue
|
||||
}
|
||||
for i, arg := range pDef.Args {
|
||||
if arg == "*" {
|
||||
continue
|
||||
}
|
||||
if arg == "***" {
|
||||
return pDef, true
|
||||
}
|
||||
if i >= len(p.Args) || arg != p.Args[i] {
|
||||
continue NextPlugin
|
||||
}
|
||||
}
|
||||
if len(pDef.Args) != len(p.Args) {
|
||||
continue
|
||||
}
|
||||
return pDef, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (o *Option) FindMatch(def []*Option) (*Option, bool) {
|
||||
NextPlugin:
|
||||
for _, oDef := range def {
|
||||
if oDef.Name != o.Name {
|
||||
continue
|
||||
}
|
||||
for i, arg := range oDef.Args {
|
||||
if arg == "*" {
|
||||
continue
|
||||
}
|
||||
if arg == "***" {
|
||||
return oDef, true
|
||||
}
|
||||
if i >= len(o.Args) || arg != o.Args[i] {
|
||||
continue NextPlugin
|
||||
}
|
||||
}
|
||||
if len(oDef.Args) != len(o.Args) {
|
||||
continue
|
||||
}
|
||||
return oDef, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
const indent = 4
|
121
kubernetes/migration/corefile/corefile_test.go
Normal file
121
kubernetes/migration/corefile/corefile_test.go
Normal file
|
@ -0,0 +1,121 @@
|
|||
package corefile
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCorefile(t *testing.T) {
|
||||
|
||||
startCorefile := `.:53 {
|
||||
error
|
||||
health
|
||||
kubernetes cluster.local in-addr.arpa ip6.arpa {
|
||||
pods insecure
|
||||
upstream
|
||||
fallthrough in-addr.arpa ip6.arpa
|
||||
}
|
||||
prometheus :9153
|
||||
proxy . /etc/resolv.conf
|
||||
cache 30
|
||||
loop
|
||||
reload
|
||||
loadbalance
|
||||
}
|
||||
|
||||
.:5353 {
|
||||
proxy . /etc/resolv.conf
|
||||
}
|
||||
`
|
||||
c, err := New(startCorefile)
|
||||
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
got := c.ToString()
|
||||
|
||||
if got != startCorefile {
|
||||
t.Errorf("Corefile did not match expected.\nExpected:\n%v\nGot:\n%v", startCorefile, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServer_FindMatch(t *testing.T) {
|
||||
tests := []struct{
|
||||
server *Server
|
||||
match bool
|
||||
}{
|
||||
{server: &Server{DomPorts: []string{".:53"}}, match: true},
|
||||
{server: &Server{DomPorts: []string{".:54"}}, match: false},
|
||||
{server: &Server{DomPorts: []string{"abc:53"}}, match: false},
|
||||
{server: &Server{DomPorts: []string{"abc:53", "blah"}}, match: true},
|
||||
{server: &Server{DomPorts: []string{"abc:53", "blah", "blah"}}, match: false},
|
||||
{server: &Server{DomPorts: []string{"xyz:53"}}, match: true},
|
||||
{server: &Server{DomPorts: []string{"xyz:53", "blah", "blah"}}, match: true},
|
||||
}
|
||||
|
||||
def := []*Server{
|
||||
{DomPorts: []string{".:53"}},
|
||||
{DomPorts: []string{"abc:53", "*"}},
|
||||
{DomPorts: []string{"xyz:53", "***"}},
|
||||
}
|
||||
for i, test := range tests {
|
||||
_, match := test.server.FindMatch(def)
|
||||
if match != test.match {
|
||||
t.Errorf("In test #%v, expected match to be %v but got %v.", i, test.match, match)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlugin_FindMatch(t *testing.T) {
|
||||
tests := []struct{
|
||||
plugin *Plugin
|
||||
match bool
|
||||
}{
|
||||
{plugin: &Plugin{Name: "plugin1", Args: []string{}}, match: true},
|
||||
{plugin: &Plugin{Name: "plugin2", Args: []string{"1","1.5","2"}}, match: true},
|
||||
{plugin: &Plugin{Name: "plugin3", Args: []string{"1","2","3","4"}}, match: true},
|
||||
{plugin: &Plugin{Name: "plugin1", Args: []string{"a"}}, match: false},
|
||||
{plugin: &Plugin{Name: "plugin2", Args: []string{"1","1.5","b"}}, match: false},
|
||||
{plugin: &Plugin{Name: "plugin3", Args: []string{"a","2","3","4"}}, match: false},
|
||||
{plugin: &Plugin{Name: "plugin4", Args: []string{}}, match: false},
|
||||
}
|
||||
|
||||
def := []*Plugin{
|
||||
{Name: "plugin1", Args: []string{}},
|
||||
{Name: "plugin2", Args: []string{"1", "*", "2"}},
|
||||
{Name: "plugin3", Args: []string{"1", "***"}},
|
||||
}
|
||||
for i, test := range tests {
|
||||
_, match := test.plugin.FindMatch(def)
|
||||
if match != test.match {
|
||||
t.Errorf("In test #%v, expected match to be %v but got %v.", i, test.match, match)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOption_FindMatch(t *testing.T) {
|
||||
tests := []struct{
|
||||
option *Plugin
|
||||
match bool
|
||||
}{
|
||||
{option: &Plugin{Name: "option1", Args: []string{}}, match: true},
|
||||
{option: &Plugin{Name: "option2", Args: []string{"1","1.5","2"}}, match: true},
|
||||
{option: &Plugin{Name: "option3", Args: []string{"1","2","3","4"}}, match: true},
|
||||
{option: &Plugin{Name: "option1", Args: []string{"a"}}, match: false},
|
||||
{option: &Plugin{Name: "option2", Args: []string{"1","1.5","b"}}, match: false},
|
||||
{option: &Plugin{Name: "option3", Args: []string{"a","2","3","4"}}, match: false},
|
||||
{option: &Plugin{Name: "option4", Args: []string{}}, match: false},
|
||||
}
|
||||
|
||||
def := []*Plugin{
|
||||
{Name: "option1", Args: []string{}},
|
||||
{Name: "option2", Args: []string{"1", "*", "2"}},
|
||||
{Name: "option3", Args: []string{"1", "***"}},
|
||||
}
|
||||
for i, test := range tests {
|
||||
_, match := test.option.FindMatch(def)
|
||||
if match != test.match {
|
||||
t.Errorf("In test #%v, expected match to be %v but got %v.", i, test.match, match)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue