16
16
package client
17
17
18
18
import (
19
-
"crypto/tls"
20
-
"crypto/x509"
21
-
"encoding/json"
22
19
"fmt"
23
-
"io/ioutil"
24
-
"net/http"
25
-
"net/url"
26
20
"os"
27
-
"path"
28
21
"reflect"
29
-
"time"
30
22
31
23
"github.com/ksonnet/ksonnet/pkg/app"
32
24
str "github.com/ksonnet/ksonnet/pkg/util/strings"
@@ -40,7 +32,7 @@ import (
40
32
)
41
33
42
34
const (
43
-
defaultVersion = "version:v1.7.0"
35
+
defaultVersion = "version:v1.8.0"
44
36
)
45
37
46
38
// Config is a wrapper around client-go's ClientConfig
@@ -49,122 +41,65 @@ type Config struct {
49
41
LoadingRules *clientcmd.ClientConfigLoadingRules
50
42
51
43
Config clientcmd.ClientConfig
44
+
45
+
discoveryClient func() (discovery.DiscoveryInterface, error)
46
+
}
47
+
48
+
func defaultDiscoveryClient(config clientcmd.ClientConfig) func() (discovery.DiscoveryInterface, error) {
49
+
return func() (discovery.DiscoveryInterface, error) {
50
+
51
+
c, err := config.ClientConfig()
52
+
if err != nil {
53
+
return nil, errors.Wrap(err, "retrive client config")
54
+
}
55
+
56
+
return discovery.NewDiscoveryClientForConfig(c)
57
+
}
52
58
}
53
59
54
60
// NewClientConfig initializes a new client.Config with the provided loading rules and overrides.
55
61
func NewClientConfig(a app.App, overrides clientcmd.ConfigOverrides, loadingRules clientcmd.ClientConfigLoadingRules) *Config {
56
62
config := clientcmd.NewInteractiveDeferredLoadingClientConfig(&loadingRules, &overrides, os.Stdin)
57
63
return &Config{
58
-
Overrides: &overrides,
59
-
LoadingRules: &loadingRules,
60
-
Config: config,
64
+
Overrides: &overrides,
65
+
LoadingRules: &loadingRules,
66
+
Config: config,
67
+
discoveryClient: defaultDiscoveryClient(config),
61
68
}
62
69
}
63
70
64
71
// NewDefaultClientConfig initializes a new ClientConfig with default loading rules and no overrides.
65
-
func NewDefaultClientConfig() *Config {
72
+
func NewDefaultClientConfig(a app.App) *Config {
66
73
overrides := clientcmd.ConfigOverrides{}
67
74
loadingRules := *clientcmd.NewDefaultClientConfigLoadingRules()
68
75
loadingRules.DefaultClientConfig = &clientcmd.DefaultClientConfig
69
-
config := clientcmd.NewInteractiveDeferredLoadingClientConfig(&loadingRules, &overrides, os.Stdin)
70
76
71
-
return &Config{
72
-
Overrides: &overrides,
73
-
LoadingRules: &loadingRules,
74
-
Config: config,
75
-
}
77
+
return NewClientConfig(a, overrides, loadingRules)
76
78
}
77
79
78
80
// InitClient initializes a new ClientConfig given the specified environment
79
81
// spec and returns the ClientPool, DiscoveryInterface, and namespace.
80
82
func InitClient(a app.App, env string) (dynamic.ClientPool, discovery.DiscoveryInterface, string, error) {
81
-
clientConfig := NewDefaultClientConfig()
83
+
clientConfig := NewDefaultClientConfig(a)
82
84
return clientConfig.RestClient(a, &env)
83
85
}
84
86
85
-
// GetAPISpec reads the kubernetes API version from this client's swagger.json.
86
-
// We anticipate the swagger.json to be located at <server>/swagger.json.
87
-
// If no swagger is found, or we are unable to authenticate to the server, we
88
-
// will default to version:v1.7.0.
89
-
func (c *Config) GetAPISpec(server string) string {
90
-
type Info struct {
91
-
Version string `json:"version"`
92
-
}
93
-
94
-
type Spec struct {
95
-
Info Info `json:"info"`
96
-
}
97
-
98
-
u, err := url.Parse(server)
99
-
u.Path = path.Join(u.Path, "swagger.json")
100
-
url := u.String()
101
-
102
-
client := http.Client{
103
-
Timeout: time.Second * 2,
104
-
}
105
-
106
-
restConfig, err := c.Config.ClientConfig()
87
+
// GetAPISpec reads the kubernetes API version from this client's Open API schema.
88
+
// If there is an error retrieving the schema, return the default version.
89
+
func (c *Config) GetAPISpec() string {
90
+
dc, err := c.discoveryClient()
107
91
if err != nil {
108
-
log.Debugf("Failed to retrieve REST config:\n%v", err)
109
-
}
110
-
111
-
if len(restConfig.TLSClientConfig.CAData) > 0 {
112
-
log.Info("Configuring TLS (from data) for retrieving cluster swagger.json")
113
-
client.Transport = buildTransportFromData(restConfig.TLSClientConfig.CAData)
114
-
}
115
-
116
-
if restConfig.TLSClientConfig.CAFile != "" {
117
-
log.Info("Configuring TLS (from file) for retrieving cluster swagger.json")
118
-
transport, err := buildTransportFromFile(restConfig.TLSClientConfig.CAFile)
119
-
if err != nil {
120
-
log.Debugf("Failed to read CA file: %v", err)
121
-
return defaultVersion
122
-
}
123
-
124
-
client.Transport = transport
125
-
}
126
-
127
-
req, err := http.NewRequest(http.MethodGet, url, nil)
128
-
if err != nil {
129
-
log.Debugf("Failed to create request at %s\n%s", url, err.Error())
92
+
log.WithError(err).Debug("Failed to create discovery client")
130
93
return defaultVersion
131
94
}
132
95
133
-
res, err := client.Do(req)
96
+
openAPIDoc, err := dc.OpenAPISchema()
134
97
if err != nil {
135
-
log.Debugf("Failed to open swagger at %s\n%s", url, err.Error())
98
+
log.WithError(err).Debug("Failed to retrieve OpenAPI schema")
136
99
return defaultVersion
137
100
}
138
101
139
-
body, err := ioutil.ReadAll(res.Body)
140
-
if err != nil {
141
-
log.Debugf("Failed to read swagger at %s\n%s", url, err.Error())
142
-
return defaultVersion
143
-
}
144
-
145
-
spec := Spec{}
146
-
err = json.Unmarshal(body, &spec)
147
-
if err != nil {
148
-
log.Debugf("Failed to parse swagger at %s\n%s", url, err.Error())
149
-
return defaultVersion
150
-
}
151
-
152
-
return fmt.Sprintf("version:%s", spec.Info.Version)
153
-
}
154
-
155
-
func buildTransportFromData(data []byte) *http.Transport {
156
-
tlsConfig := &tls.Config{RootCAs: x509.NewCertPool()}
157
-
tlsConfig.RootCAs.AppendCertsFromPEM(data)
158
-
return &http.Transport{TLSClientConfig: tlsConfig}
159
-
}
160
-
161
-
func buildTransportFromFile(file string) (*http.Transport, error) {
162
-
data, err := ioutil.ReadFile(file)
163
-
if err != nil {
164
-
return nil, errors.Wrap(err, "unable to ready CA file")
165
-
}
166
-
167
-
return buildTransportFromData(data), nil
102
+
return fmt.Sprintf("version:%s", openAPIDoc.Info.Version)
168
103
}
169
104
170
105
// Namespace returns the namespace for the provided ClientConfig.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4