aboutsummaryrefslogtreecommitdiff
path: root/middleware/kubernetes/kubernetes.go
diff options
context:
space:
mode:
authorGravatar Michael Richmond <mrichmon@users.noreply.github.com> 2016-07-14 14:50:14 -0700
committerGravatar Miek Gieben <miek@miek.nl> 2016-07-14 23:50:14 +0200
commit3f4ec783d218d10b244487d463de5bb31284e3cf (patch)
treee9214e93511b36039a54462aba214b5f82387f93 /middleware/kubernetes/kubernetes.go
parent319d30697af07616be596fd4918dce3ce4bcfc84 (diff)
downloadcoredns-3f4ec783d218d10b244487d463de5bb31284e3cf.tar.gz
coredns-3f4ec783d218d10b244487d463de5bb31284e3cf.tar.zst
coredns-3f4ec783d218d10b244487d463de5bb31284e3cf.zip
Adding wildcard support (#190)
* Commenting out unused functions. TODO: remove when it is not needed * Update README with namespace and template example * Adding note about changing the record name format via a template * Adding test scripts to automate k8s startup * Automating k8s namespace creation * Adding automation to start 4 k8s services * Updating documentation for k8s tests * Avoid downloading kubectl if already exists * Adding debug statement when namespace is not exposed. * Adding basic kubernetes integration tests * Makefile now contains a "testk8s" target. This target requires k8s to be running. * Adding test/kubernetes_test.go file with a couple of basic A record tests. * Updating k8s integration tests to only run k8s integration tests * Adding support for namespace wildcards * Refactoring to move filtering logic to kubernetes.go file * go fmt fixes * Adding wildcard support for namespaces and service names * Kubernetes integration tests updated for A records. * Expanded record name assembly for answer section not yet implemented. * Refactoring to focus k8sclient code just on accessing k8s API. Filtering now handled in kubernetes.go * Adding wildcard test cases * Adding skydns startup script. (To allow side by side testing of wildcards.) * Commenting out record name assmebly based on NameTemplate. Need to improve template before this makes sense. * Adding basic SRV integration tests * Need to add verification for additional answer section * Fixing comments and formatting * Moving wildcard constants to vars * Travis test execution appears to be failing on access to these constants * Fixing access to util package * Trying to work around Travis test bug * Reverting to access kubernetes/util as "util" Travis breakage is due to "Infoblox-CTO" in src path
Diffstat (limited to 'middleware/kubernetes/kubernetes.go')
-rw-r--r--middleware/kubernetes/kubernetes.go105
1 files changed, 72 insertions, 33 deletions
diff --git a/middleware/kubernetes/kubernetes.go b/middleware/kubernetes/kubernetes.go
index d6d93f809..f9a0712fe 100644
--- a/middleware/kubernetes/kubernetes.go
+++ b/middleware/kubernetes/kubernetes.go
@@ -62,7 +62,7 @@ func (g Kubernetes) Records(name string, exact bool) ([]msg.Service, error) {
typeName string
)
- fmt.Println("enter Records('", name, "', ", exact, ")")
+ fmt.Println("[debug] enter Records('", name, "', ", exact, ")")
zone, serviceSegments := g.getZoneForName(name)
/*
@@ -83,6 +83,18 @@ func (g Kubernetes) Records(name string, exact bool) ([]msg.Service, error) {
serviceName = g.NameTemplate.GetServiceFromSegmentArray(serviceSegments)
typeName = g.NameTemplate.GetTypeFromSegmentArray(serviceSegments)
+ if namespace == "" {
+ err := errors.New("Parsing query string did not produce a namespace value. Assuming wildcard namespace.")
+ fmt.Printf("[WARN] %v\n", err)
+ namespace = util.WildcardStar
+ }
+
+ if serviceName == "" {
+ err := errors.New("Parsing query string did not produce a serviceName value. Assuming wildcard serviceName.")
+ fmt.Printf("[WARN] %v\n", err)
+ serviceName = util.WildcardStar
+ }
+
fmt.Println("[debug] exact: ", exact)
fmt.Println("[debug] zone: ", zone)
fmt.Println("[debug] servicename: ", serviceName)
@@ -90,21 +102,18 @@ func (g Kubernetes) Records(name string, exact bool) ([]msg.Service, error) {
fmt.Println("[debug] typeName: ", typeName)
fmt.Println("[debug] APIconn: ", g.APIConn)
- // TODO: Implement wildcard support to allow blank namespace value
- if namespace == "" {
- err := errors.New("Parsing query string did not produce a namespace value")
- fmt.Printf("[ERROR] %v\n", err)
- return nil, err
- }
+ nsWildcard := util.SymbolContainsWildcard(namespace)
+ serviceWildcard := util.SymbolContainsWildcard(serviceName)
- // Abort if the namespace is not published per CoreFile
- if g.Namespaces != nil && !util.StringInSlice(namespace, *g.Namespaces) {
+ // Abort if the namespace does not contain a wildcard, and namespace is not published per CoreFile
+ // Case where namespace contains a wildcard is handled in Get(...) method.
+ if (!nsWildcard) && (g.Namespaces != nil && !util.StringInSlice(namespace, *g.Namespaces)) {
+ fmt.Printf("[debug] Namespace '%v' is not published by Corefile\n", namespace)
return nil, nil
}
- k8sItems, err := g.APIConn.GetServiceItemsInNamespace(namespace, serviceName)
+ k8sItems, err := g.Get(namespace, nsWildcard, serviceName, serviceWildcard)
fmt.Println("[debug] k8s items:", k8sItems)
-
if err != nil {
fmt.Printf("[ERROR] Got error while looking up ServiceItems. Error is: %v\n", err)
return nil, err
@@ -114,29 +123,27 @@ func (g Kubernetes) Records(name string, exact bool) ([]msg.Service, error) {
return nil, nil
}
- // test := g.NameTemplate.GetRecordNameFromNameValues(nametemplate.NameValues{ServiceName: serviceName, TypeName: typeName, Namespace: namespace, Zone: zone})
- // fmt.Printf("[debug] got recordname %v\n", test)
-
- records := g.getRecordsForServiceItems(k8sItems, name)
-
+ records := g.getRecordsForServiceItems(k8sItems, nametemplate.NameValues{TypeName: typeName, ServiceName: serviceName, Namespace: namespace, Zone: zone})
return records, nil
}
// TODO: assemble name from parts found in k8s data based on name template rather than reusing query string
-func (g Kubernetes) getRecordsForServiceItems(serviceItems []*k8sc.ServiceItem, name string) []msg.Service {
+func (g Kubernetes) getRecordsForServiceItems(serviceItems []k8sc.ServiceItem, values nametemplate.NameValues) []msg.Service {
var records []msg.Service
for _, item := range serviceItems {
- fmt.Println("[debug] clusterIP:", item.Spec.ClusterIP)
- for _, p := range item.Spec.Ports {
- fmt.Println("[debug] port:", p.Port)
- }
-
clusterIP := item.Spec.ClusterIP
+ fmt.Println("[debug] clusterIP:", clusterIP)
+
+ // Create records by constructing record name from template...
+ //values.Namespace = item.Metadata.Namespace
+ //values.ServiceName = item.Metadata.Name
+ //s := msg.Service{Host: g.NameTemplate.GetRecordNameFromNameValues(values)}
+ //records = append(records, s)
- s := msg.Service{Host: name}
- records = append(records, s)
+ // Create records for each exposed port...
for _, p := range item.Spec.Ports {
+ fmt.Println("[debug] port:", p.Port)
s := msg.Service{Host: clusterIP, Port: p.Port}
records = append(records, s)
}
@@ -146,17 +153,50 @@ func (g Kubernetes) getRecordsForServiceItems(serviceItems []*k8sc.ServiceItem,
return records
}
-/*
// Get performs the call to the Kubernetes http API.
-func (g Kubernetes) Get(path string, recursive bool) (bool, error) {
+func (g Kubernetes) Get(namespace string, nsWildcard bool, servicename string, serviceWildcard bool) ([]k8sc.ServiceItem, error) {
+ serviceList, err := g.APIConn.GetServiceList()
- fmt.Println("[debug] in Get path: ", path)
- fmt.Println("[debug] in Get recursive: ", recursive)
+ if err != nil {
+ fmt.Printf("[ERROR] Getting service list produced error: %v", err)
+ return nil, err
+ }
- return false, nil
+ var resultItems []k8sc.ServiceItem
+
+ for _, item := range serviceList.Items {
+ if symbolMatches(namespace, item.Metadata.Namespace, nsWildcard) && symbolMatches(servicename, item.Metadata.Name, serviceWildcard) {
+ // If namespace has a wildcard, filter results against Corefile namespace list.
+ // (Namespaces without a wildcard were filtered before the call to this function.)
+ if nsWildcard && (g.Namespaces != nil && !util.StringInSlice(item.Metadata.Namespace, *g.Namespaces)) {
+ fmt.Printf("[debug] Namespace '%v' is not published by Corefile\n", item.Metadata.Namespace)
+ continue
+ }
+ resultItems = append(resultItems, item)
+ }
+ }
+
+ return resultItems, nil
}
-*/
+func symbolMatches(queryString string, candidateString string, wildcard bool) bool {
+ result := false
+ switch {
+ case !wildcard:
+ result = (queryString == candidateString)
+ case queryString == util.WildcardStar:
+ result = true
+ case queryString == util.WildcardAny:
+ result = true
+ }
+ return result
+}
+
+// TODO: Remove these unused functions. One is related to Ttl calculation
+// Implement Ttl and priority calculation based on service count before
+// removing this code.
+/*
+// splitDNSName separates the name into DNS segments and reverses the segments.
func (g Kubernetes) splitDNSName(name string) []string {
l := dns.SplitDomainName(name)
@@ -166,16 +206,15 @@ func (g Kubernetes) splitDNSName(name string) []string {
return l
}
-
+*/
// skydns/local/skydns/east/staging/web
// skydns/local/skydns/west/production/web
//
// skydns/local/skydns/*/*/web
// skydns/local/skydns/*/web
-
+/*
// loopNodes recursively loops through the nodes and returns all the values. The nodes' keyname
// will be match against any wildcards when star is true.
-/*
func (g Kubernetes) loopNodes(ns []*etcdc.Node, nameParts []string, star bool, bx map[msg.Service]bool) (sx []msg.Service, err error) {
if bx == nil {
bx = make(map[msg.Service]bool)