1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
package k8sclient
import (
"errors"
"fmt"
"net/url"
"strings"
)
// API strings
const (
apiBase = "/api/v1"
apiNamespaces = "/namespaces"
apiServices = "/services"
)
// Defaults
const (
defaultBaseURL = "http://localhost:8080"
)
type K8sConnector struct {
baseURL string
}
func (c *K8sConnector) SetBaseURL(u string) error {
url, error := url.Parse(u)
if error != nil {
return error
}
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
}
// 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)
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
}
return resources, nil
}
func (c *K8sConnector) GetNamespaceList() (*NamespaceList, error) {
namespaces := new(NamespaceList)
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
}
return namespaces, nil
}
func (c *K8sConnector) GetServiceList() (*ServiceList, error) {
services := new(ServiceList)
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
}
return services, nil
}
// GetServicesByNamespace returns a map of
// namespacename :: [ kubernetesServiceItem ]
func (c *K8sConnector) GetServicesByNamespace() (map[string][]ServiceItem, error) {
items := make(map[string][]ServiceItem)
k8sServiceList, err := c.GetServiceList()
if err != nil {
fmt.Printf("[ERROR] Getting service list produced error: %v", err)
return nil, err
}
// TODO: handle no response from k8s
if k8sServiceList == nil {
return nil, 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) {
itemMap, err := c.GetServicesByNamespace()
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
}
|