mirror of
https://github.com/coredns/coredns.git
synced 2025-10-30 01:34:21 -04:00
k8s middleware cleanup, testcases, basic SRV (#181)
* Removing unnecessary gitignore pattern
* Updating Makefile to run unittests for subpackages
* Adding Corefile validation to ignore overlapping zones
* Fixing SRV query handling
* Updating README.md now that SRV works
* Fixing debug message, adding code comment
* Clarifying implementation of zone normalization
* "Overlapping zones" is ill-defined. Reimplemented zone overlap/subzone
checking to contain these functions in k8s middleware and provide
better code comments explaining the normalization.
* Separate build verbosity from test verbosity
* Cleaning up comments to match repo code style
* Merging warning messages into single message
* Moving function docs to before function declaration
* Adding test cases for k8sclient connector
* Tests cover connector create and setting base url
* Fixed bugs in connector create and setting base url functions
* Updaing README to group and order development work
* Priority focused on achieving functional parity with SkyDNS.
* Adding work items to README and cleaning up formatting
* More README format cleaning
* List formating
* Refactoring k8s API call to allow dependency injection
* Add test cases for data parsing from k8s into dataobject structures
* URL is dependency-injected to allow replacement with a mock http
server during test execution
* Adding more data validation for JSON parsing tests
* Adding test case for GetResourceList()
* Adding notes about SkyDNS embedded IP and port record names
* Marked test case implemented.
* Fixing formatting for example command.
* Fixing formatting
* Adding notes about Docker image building.
* Adding SkyDNS work item
* Updating TODO list
* Adding name template to Corefile to specify how k8s record names are assembled
* Adding template support for multi-segment zones
* Updating example CoreFile for k8s with template comment
* Misc whitespace cleanup
* Adding SkyDNS naming notes
* Adding namespace filtering to CoreFile config
* Updating example k8sCoreFile to specify namespaces
* Removing unused codepath
* Adding check for valid namespace
* More README TODO restructuring to focus effort
* Adding template validation while parsing CoreFile
* Record name template is considered invalid if it contains a symbol of the form ${bar} where the symbol
"${bar}" is not an accepted template symbol.
* Refactoring generation of answer records
* Parse typeName out of query string
* Refactor answer record creation as operation over list of ServiceItems
* Moving k8s API caching into SkyDNS equivalency segment
* Adding function to assemble record names from template
* Warning: This commit may be broken. Syncing to get laptop code over to dev machine.
* More todo notes
* Adding comment describing sample test data.
* Update k8sCorefile
* Adding comment
* Adding filtering support for kubernetes "type"
* Required refactoring to support reuse of the StringInSlice function.
* Cleaning up formatting
* Adding note about SkyDNS supporting word "any".
* baseUrl -> baseURL
* Also removed debug statement from core/setup/kubernetes.go
* Fixing test breaking from Url -> URL naming changes
* Changing record name template language ${...} -> {...}
* Fix formatting with go fmt
* Updating all k8sclient data getters to return error value
* Adding error message to k8sclient data accessors
* Cleaning up setup for kubernetes
* Removed verbose nils in initial k8s middleware instance
* Set reasonable defaults if CoreFile has no parameters in the
kubernetes block. (k8s endpoint, and name template)
* Formatting cleanup -- go fmt
This commit is contained in:
committed by
Miek Gieben
parent
558c34a23e
commit
289f53d386
@@ -1,117 +1,157 @@
|
||||
package k8sclient
|
||||
|
||||
import (
|
||||
// "fmt"
|
||||
"net/url"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// API strings
|
||||
const (
|
||||
apiBase = "/api/v1"
|
||||
apiNamespaces = "/namespaces"
|
||||
apiServices = "/services"
|
||||
apiBase = "/api/v1"
|
||||
apiNamespaces = "/namespaces"
|
||||
apiServices = "/services"
|
||||
)
|
||||
|
||||
// Defaults
|
||||
const (
|
||||
defaultBaseUrl = "http://localhost:8080"
|
||||
defaultBaseURL = "http://localhost:8080"
|
||||
)
|
||||
|
||||
|
||||
type K8sConnector struct {
|
||||
baseUrl string
|
||||
baseURL string
|
||||
}
|
||||
|
||||
func (c *K8sConnector) SetBaseUrl(u string) error {
|
||||
validUrl, error := url.Parse(u)
|
||||
func (c *K8sConnector) SetBaseURL(u string) error {
|
||||
url, error := url.Parse(u)
|
||||
|
||||
if error != nil {
|
||||
return error
|
||||
}
|
||||
c.baseUrl = validUrl.String()
|
||||
if error != nil {
|
||||
return error
|
||||
}
|
||||
|
||||
return nil
|
||||
if !url.IsAbs() {
|
||||
return errors.New("k8sclient: Kubernetes endpoint url must be an absolute URL")
|
||||
}
|
||||
|
||||
c.baseURL = url.String()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *K8sConnector) GetBaseUrl() string {
|
||||
return c.baseUrl
|
||||
func (c *K8sConnector) GetBaseURL() string {
|
||||
return c.baseURL
|
||||
}
|
||||
|
||||
|
||||
func (c *K8sConnector) GetResourceList() *ResourceList {
|
||||
resources := new(ResourceList)
|
||||
|
||||
error := getJson((c.baseUrl + apiBase), resources)
|
||||
if error != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return resources
|
||||
// URL constructor separated from code to support dependency injection
|
||||
// for unit tests.
|
||||
var makeURL = func(parts []string) string {
|
||||
return strings.Join(parts, "")
|
||||
}
|
||||
|
||||
func (c *K8sConnector) GetResourceList() (*ResourceList, error) {
|
||||
resources := new(ResourceList)
|
||||
|
||||
func (c *K8sConnector) GetNamespaceList() *NamespaceList {
|
||||
namespaces := new(NamespaceList)
|
||||
url := makeURL([]string{c.baseURL, apiBase})
|
||||
err := parseJson(url, resources)
|
||||
// TODO: handle no response from k8s
|
||||
if err != nil {
|
||||
fmt.Printf("[ERROR] Response from kubernetes API for GetResourceList() is: %v\n", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
error := getJson((c.baseUrl + apiBase + apiNamespaces), namespaces)
|
||||
if error != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return namespaces
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func (c *K8sConnector) GetNamespaceList() (*NamespaceList, error) {
|
||||
namespaces := new(NamespaceList)
|
||||
|
||||
func (c *K8sConnector) GetServiceList() *ServiceList {
|
||||
services := new(ServiceList)
|
||||
url := makeURL([]string{c.baseURL, apiBase, apiNamespaces})
|
||||
err := parseJson(url, namespaces)
|
||||
if err != nil {
|
||||
fmt.Printf("[ERROR] Response from kubernetes API for GetNamespaceList() is: %v\n", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
error := getJson((c.baseUrl + apiBase + apiServices), services)
|
||||
if error != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return services
|
||||
return namespaces, nil
|
||||
}
|
||||
|
||||
func (c *K8sConnector) GetServiceList() (*ServiceList, error) {
|
||||
services := new(ServiceList)
|
||||
|
||||
func (c *K8sConnector) GetServicesByNamespace() map[string][]ServiceItem {
|
||||
// GetServicesByNamespace returns a map of namespacename :: [ kubernetesServiceItem ]
|
||||
url := makeURL([]string{c.baseURL, apiBase, apiServices})
|
||||
err := parseJson(url, services)
|
||||
// TODO: handle no response from k8s
|
||||
if err != nil {
|
||||
fmt.Printf("[ERROR] Response from kubernetes API for GetServiceList() is: %v\n", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
items := make(map[string][]ServiceItem)
|
||||
|
||||
k8sServiceList := c.GetServiceList()
|
||||
k8sItemList := k8sServiceList.Items
|
||||
|
||||
for _, i := range k8sItemList {
|
||||
namespace := i.Metadata.Namespace
|
||||
items[namespace] = append(items[namespace], i)
|
||||
}
|
||||
|
||||
return items
|
||||
return services, nil
|
||||
}
|
||||
|
||||
// GetServicesByNamespace returns a map of
|
||||
// namespacename :: [ kubernetesServiceItem ]
|
||||
func (c *K8sConnector) GetServicesByNamespace() (map[string][]ServiceItem, error) {
|
||||
|
||||
func (c *K8sConnector) GetServiceItemInNamespace(namespace string, servicename string) *ServiceItem {
|
||||
// GetServiceItemInNamespace returns the ServiceItem that matches servicename in the namespace
|
||||
items := make(map[string][]ServiceItem)
|
||||
|
||||
itemMap := c.GetServicesByNamespace()
|
||||
k8sServiceList, err := c.GetServiceList()
|
||||
|
||||
// TODO: Handle case where namesapce == nil
|
||||
if err != nil {
|
||||
fmt.Printf("[ERROR] Getting service list produced error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, x := range itemMap[namespace] {
|
||||
if x.Metadata.Name == servicename {
|
||||
return &x
|
||||
}
|
||||
}
|
||||
// TODO: handle no response from k8s
|
||||
if k8sServiceList == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// No matching item found in namespace
|
||||
return nil
|
||||
k8sItemList := k8sServiceList.Items
|
||||
|
||||
for _, i := range k8sItemList {
|
||||
namespace := i.Metadata.Namespace
|
||||
items[namespace] = append(items[namespace], i)
|
||||
}
|
||||
|
||||
return items, nil
|
||||
}
|
||||
|
||||
// GetServiceItemsInNamespace returns the ServiceItems that match
|
||||
// servicename in the namespace
|
||||
func (c *K8sConnector) GetServiceItemsInNamespace(namespace string, servicename string) ([]*ServiceItem, error) {
|
||||
|
||||
func NewK8sConnector(baseurl string) *K8sConnector {
|
||||
k := new(K8sConnector)
|
||||
k.SetBaseUrl(baseurl)
|
||||
itemMap, err := c.GetServicesByNamespace()
|
||||
|
||||
return k
|
||||
if err != nil {
|
||||
fmt.Printf("[ERROR] Getting service list produced error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: Handle case where namespace == nil
|
||||
|
||||
var serviceItems []*ServiceItem
|
||||
|
||||
for _, x := range itemMap[namespace] {
|
||||
if x.Metadata.Name == servicename {
|
||||
serviceItems = append(serviceItems, &x)
|
||||
}
|
||||
}
|
||||
|
||||
return serviceItems, nil
|
||||
}
|
||||
|
||||
func NewK8sConnector(baseURL string) *K8sConnector {
|
||||
k := new(K8sConnector)
|
||||
|
||||
if baseURL == "" {
|
||||
baseURL = defaultBaseURL
|
||||
}
|
||||
|
||||
err := k.SetBaseURL(baseURL)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return k
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user