Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Ijaz Ahmad
ksonnet
Commits
c904092f
Unverified
Commit
c904092f
authored
May 08, 2018
by
Bryan Liles
Committed by
GitHub
May 08, 2018
Browse files
Merge pull request #520 from bryanl/client-go-server-version
Use client-go to retrieve cluster version
parents
9bd5b3a2
8dfed428
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
113 additions
and
177 deletions
+113
-177
docs/cli-reference/ks_param_set.md
docs/cli-reference/ks_param_set.md
+1
-0
pkg/clicmd/apply.go
pkg/clicmd/apply.go
+1
-1
pkg/clicmd/delete.go
pkg/clicmd/delete.go
+1
-1
pkg/clicmd/env.go
pkg/clicmd/env.go
+1
-1
pkg/clicmd/env_add.go
pkg/clicmd/env_add.go
+1
-1
pkg/clicmd/init.go
pkg/clicmd/init.go
+2
-2
pkg/clicmd/init_test.go
pkg/clicmd/init_test.go
+1
-1
pkg/clicmd/validate.go
pkg/clicmd/validate.go
+1
-1
pkg/client/client.go
pkg/client/client.go
+30
-95
pkg/client/client_test.go
pkg/client/client_test.go
+74
-69
pkg/client/testdata/swagger.json
pkg/client/testdata/swagger.json
+0
-5
No files found.
docs/cli-reference/ks_param_set.md
View file @
c904092f
...
...
@@ -43,6 +43,7 @@ ks param set guestbook replicas 2 --env=dev
### Options
```
--as-string Force value to be interpreted as string
--env string Specify environment to set parameters for
-h, --help help for set
```
...
...
pkg/clicmd/apply.go
View file @
c904092f
...
...
@@ -42,7 +42,7 @@ const (
func
init
()
{
RootCmd
.
AddCommand
(
applyCmd
)
applyClientConfig
=
client
.
NewDefaultClientConfig
()
applyClientConfig
=
client
.
NewDefaultClientConfig
(
ka
)
applyClientConfig
.
BindClientGoFlags
(
applyCmd
)
bindJsonnetFlags
(
applyCmd
,
"apply"
)
...
...
pkg/clicmd/delete.go
View file @
c904092f
...
...
@@ -39,7 +39,7 @@ var (
func
init
()
{
RootCmd
.
AddCommand
(
deleteCmd
)
deleteClientConfig
=
client
.
NewDefaultClientConfig
()
deleteClientConfig
=
client
.
NewDefaultClientConfig
(
ka
)
deleteClientConfig
.
BindClientGoFlags
(
deleteCmd
)
bindJsonnetFlags
(
deleteCmd
,
"delete"
)
...
...
pkg/clicmd/env.go
View file @
c904092f
...
...
@@ -47,7 +47,7 @@ var (
func
init
()
{
RootCmd
.
AddCommand
(
envCmd
)
envClientConfig
=
client
.
NewDefaultClientConfig
()
envClientConfig
=
client
.
NewDefaultClientConfig
(
ka
)
envClientConfig
.
BindClientGoFlags
(
envCmd
)
envCmd
.
AddCommand
(
envAddCmd
)
...
...
pkg/clicmd/env_add.go
View file @
c904092f
...
...
@@ -51,7 +51,7 @@ var envAddCmd = &cobra.Command{
return
err
}
if
specFlag
==
""
{
specFlag
=
envClientConfig
.
GetAPISpec
(
server
)
specFlag
=
envClientConfig
.
GetAPISpec
()
}
isOverride
:=
viper
.
GetBool
(
vEnvAddOverride
)
...
...
pkg/clicmd/init.go
View file @
c904092f
...
...
@@ -43,7 +43,7 @@ var (
func
init
()
{
RootCmd
.
AddCommand
(
initCmd
)
initClientConfig
=
client
.
NewDefaultClientConfig
()
initClientConfig
=
client
.
NewDefaultClientConfig
(
ka
)
initClientConfig
.
BindClientGoFlags
(
initCmd
)
initCmd
.
Flags
()
.
String
(
flagDir
,
""
,
"Ksonnet application directory"
)
...
...
@@ -90,7 +90,7 @@ var initCmd = &cobra.Command{
specFlag
:=
viper
.
GetString
(
vInitAPISpec
)
if
specFlag
==
""
{
specFlag
=
initClientConfig
.
GetAPISpec
(
server
)
specFlag
=
initClientConfig
.
GetAPISpec
()
}
m
:=
map
[
string
]
interface
{}{
...
...
pkg/clicmd/init_test.go
View file @
c904092f
...
...
@@ -45,7 +45,7 @@ func Test_initCmd(t *testing.T) {
actions
.
OptionEnvName
:
"env-name"
,
actions
.
OptionRootPath
:
root
,
actions
.
OptionServer
:
"http://127.0.0.1"
,
actions
.
OptionSpecFlag
:
"version:v1.
7
.0"
,
actions
.
OptionSpecFlag
:
"version:v1.
8
.0"
,
actions
.
OptionNamespace
:
"new-namespace"
,
actions
.
OptionSkipDefaultRegistries
:
false
,
},
...
...
pkg/clicmd/validate.go
View file @
c904092f
...
...
@@ -38,7 +38,7 @@ func init() {
RootCmd
.
AddCommand
(
validateCmd
)
addEnvCmdFlags
(
validateCmd
)
bindJsonnetFlags
(
validateCmd
,
"validate"
)
validateClientConfig
=
client
.
NewDefaultClientConfig
()
validateClientConfig
=
client
.
NewDefaultClientConfig
(
ka
)
validateClientConfig
.
BindClientGoFlags
(
validateCmd
)
viper
.
BindPFlag
(
vValidateComponent
,
validateCmd
.
Flag
(
flagComponent
))
...
...
pkg/client/client.go
View file @
c904092f
...
...
@@ -16,17 +16,9 @@
package
client
import
(
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"path"
"reflect"
"time"
"github.com/ksonnet/ksonnet/pkg/app"
str
"github.com/ksonnet/ksonnet/pkg/util/strings"
...
...
@@ -40,7 +32,7 @@ import (
)
const
(
defaultVersion
=
"version:v1.
7
.0"
defaultVersion
=
"version:v1.
8
.0"
)
// Config is a wrapper around client-go's ClientConfig
...
...
@@ -49,122 +41,65 @@ type Config struct {
LoadingRules
*
clientcmd
.
ClientConfigLoadingRules
Config
clientcmd
.
ClientConfig
discoveryClient
func
()
(
discovery
.
DiscoveryInterface
,
error
)
}
func
defaultDiscoveryClient
(
config
clientcmd
.
ClientConfig
)
func
()
(
discovery
.
DiscoveryInterface
,
error
)
{
return
func
()
(
discovery
.
DiscoveryInterface
,
error
)
{
c
,
err
:=
config
.
ClientConfig
()
if
err
!=
nil
{
return
nil
,
errors
.
Wrap
(
err
,
"retrive client config"
)
}
return
discovery
.
NewDiscoveryClientForConfig
(
c
)
}
}
// NewClientConfig initializes a new client.Config with the provided loading rules and overrides.
func
NewClientConfig
(
a
app
.
App
,
overrides
clientcmd
.
ConfigOverrides
,
loadingRules
clientcmd
.
ClientConfigLoadingRules
)
*
Config
{
config
:=
clientcmd
.
NewInteractiveDeferredLoadingClientConfig
(
&
loadingRules
,
&
overrides
,
os
.
Stdin
)
return
&
Config
{
Overrides
:
&
overrides
,
LoadingRules
:
&
loadingRules
,
Config
:
config
,
Overrides
:
&
overrides
,
LoadingRules
:
&
loadingRules
,
Config
:
config
,
discoveryClient
:
defaultDiscoveryClient
(
config
),
}
}
// NewDefaultClientConfig initializes a new ClientConfig with default loading rules and no overrides.
func
NewDefaultClientConfig
()
*
Config
{
func
NewDefaultClientConfig
(
a
app
.
App
)
*
Config
{
overrides
:=
clientcmd
.
ConfigOverrides
{}
loadingRules
:=
*
clientcmd
.
NewDefaultClientConfigLoadingRules
()
loadingRules
.
DefaultClientConfig
=
&
clientcmd
.
DefaultClientConfig
config
:=
clientcmd
.
NewInteractiveDeferredLoadingClientConfig
(
&
loadingRules
,
&
overrides
,
os
.
Stdin
)
return
&
Config
{
Overrides
:
&
overrides
,
LoadingRules
:
&
loadingRules
,
Config
:
config
,
}
return
NewClientConfig
(
a
,
overrides
,
loadingRules
)
}
// InitClient initializes a new ClientConfig given the specified environment
// spec and returns the ClientPool, DiscoveryInterface, and namespace.
func
InitClient
(
a
app
.
App
,
env
string
)
(
dynamic
.
ClientPool
,
discovery
.
DiscoveryInterface
,
string
,
error
)
{
clientConfig
:=
NewDefaultClientConfig
()
clientConfig
:=
NewDefaultClientConfig
(
a
)
return
clientConfig
.
RestClient
(
a
,
&
env
)
}
// GetAPISpec reads the kubernetes API version from this client's swagger.json.
// We anticipate the swagger.json to be located at <server>/swagger.json.
// If no swagger is found, or we are unable to authenticate to the server, we
// will default to version:v1.7.0.
func
(
c
*
Config
)
GetAPISpec
(
server
string
)
string
{
type
Info
struct
{
Version
string
`json:"version"`
}
type
Spec
struct
{
Info
Info
`json:"info"`
}
u
,
err
:=
url
.
Parse
(
server
)
u
.
Path
=
path
.
Join
(
u
.
Path
,
"swagger.json"
)
url
:=
u
.
String
()
client
:=
http
.
Client
{
Timeout
:
time
.
Second
*
2
,
}
restConfig
,
err
:=
c
.
Config
.
ClientConfig
()
// GetAPISpec reads the kubernetes API version from this client's Open API schema.
// If there is an error retrieving the schema, return the default version.
func
(
c
*
Config
)
GetAPISpec
()
string
{
dc
,
err
:=
c
.
discoveryClient
()
if
err
!=
nil
{
log
.
Debugf
(
"Failed to retrieve REST config:
\n
%v"
,
err
)
}
if
len
(
restConfig
.
TLSClientConfig
.
CAData
)
>
0
{
log
.
Info
(
"Configuring TLS (from data) for retrieving cluster swagger.json"
)
client
.
Transport
=
buildTransportFromData
(
restConfig
.
TLSClientConfig
.
CAData
)
}
if
restConfig
.
TLSClientConfig
.
CAFile
!=
""
{
log
.
Info
(
"Configuring TLS (from file) for retrieving cluster swagger.json"
)
transport
,
err
:=
buildTransportFromFile
(
restConfig
.
TLSClientConfig
.
CAFile
)
if
err
!=
nil
{
log
.
Debugf
(
"Failed to read CA file: %v"
,
err
)
return
defaultVersion
}
client
.
Transport
=
transport
}
req
,
err
:=
http
.
NewRequest
(
http
.
MethodGet
,
url
,
nil
)
if
err
!=
nil
{
log
.
Debugf
(
"Failed to create request at %s
\n
%s"
,
url
,
err
.
Error
())
log
.
WithError
(
err
)
.
Debug
(
"Failed to create discovery client"
)
return
defaultVersion
}
res
,
err
:=
client
.
Do
(
req
)
openAPIDoc
,
err
:=
dc
.
OpenAPISchema
(
)
if
err
!=
nil
{
log
.
Debug
f
(
"Failed to
open swagger at %s
\n
%s"
,
url
,
err
.
Error
()
)
log
.
WithError
(
err
)
.
Debug
(
"Failed to
retrieve OpenAPI schema"
)
return
defaultVersion
}
body
,
err
:=
ioutil
.
ReadAll
(
res
.
Body
)
if
err
!=
nil
{
log
.
Debugf
(
"Failed to read swagger at %s
\n
%s"
,
url
,
err
.
Error
())
return
defaultVersion
}
spec
:=
Spec
{}
err
=
json
.
Unmarshal
(
body
,
&
spec
)
if
err
!=
nil
{
log
.
Debugf
(
"Failed to parse swagger at %s
\n
%s"
,
url
,
err
.
Error
())
return
defaultVersion
}
return
fmt
.
Sprintf
(
"version:%s"
,
spec
.
Info
.
Version
)
}
func
buildTransportFromData
(
data
[]
byte
)
*
http
.
Transport
{
tlsConfig
:=
&
tls
.
Config
{
RootCAs
:
x509
.
NewCertPool
()}
tlsConfig
.
RootCAs
.
AppendCertsFromPEM
(
data
)
return
&
http
.
Transport
{
TLSClientConfig
:
tlsConfig
}
}
func
buildTransportFromFile
(
file
string
)
(
*
http
.
Transport
,
error
)
{
data
,
err
:=
ioutil
.
ReadFile
(
file
)
if
err
!=
nil
{
return
nil
,
errors
.
Wrap
(
err
,
"unable to ready CA file"
)
}
return
buildTransportFromData
(
data
),
nil
return
fmt
.
Sprintf
(
"version:%s"
,
openAPIDoc
.
Info
.
Version
)
}
// Namespace returns the namespace for the provided ClientConfig.
...
...
pkg/client/client_test.go
View file @
c904092f
...
...
@@ -16,101 +16,61 @@
package
client
import
(
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"testing"
swagger
"github.com/emicklei/go-restful-swagger12"
"github.com/googleapis/gnostic/OpenAPIv2"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/discovery"
restclient
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi
"k8s.io/client-go/tools/clientcmd/api"
)
func
TestConfig_GetAPISpec
(
t
*
testing
.
T
)
{
b
,
err
:=
ioutil
.
ReadFile
(
"testdata/swagger.json"
)
require
.
NoError
(
t
,
err
)
handler
:=
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
fmt
.
Fprintln
(
w
,
string
(
b
))
})
ts
:=
httptest
.
NewServer
(
handler
)
defer
ts
.
Close
()
tsTLS
:=
httptest
.
NewTLSServer
(
handler
)
defer
tsTLS
.
Close
()
tmpfile
,
err
:=
ioutil
.
TempFile
(
""
,
""
)
require
.
NoError
(
t
,
err
)
defer
os
.
Remove
(
tmpfile
.
Name
())
certPEM
:=
buildPEM
(
tsTLS
.
Certificate
())
_
,
err
=
tmpfile
.
Write
(
certPEM
)
require
.
NoError
(
t
,
err
)
err
=
tmpfile
.
Close
()
require
.
NoError
(
t
,
err
)
cases
:=
[]
struct
{
name
string
serverURL
string
expected
string
caData
[]
byte
caFile
string
version
string
disc
discovery
.
DiscoveryInterface
createErr
error
}{
{
name
:
"invalid server URL"
,
serverURL
:
"http://+++"
,
expected
:
defaultVersion
,
},
{
name
:
"with a server"
,
serverURL
:
ts
.
URL
,
expected
:
"version:v1.9.3"
,
name
:
"in general"
,
version
:
"version:v1.9.3"
,
disc
:
&
fakeDiscovery
{},
},
{
name
:
"TLS with file cert"
,
serverURL
:
tsTLS
.
URL
,
expected
:
"version:v1.9.3"
,
caFile
:
tmpfile
.
Name
(),
name
:
"unable to create discovery client"
,
version
:
"version:v1.8.0"
,
createErr
:
errors
.
New
(
"failed"
),
},
{
name
:
"TLS with data cert"
,
serverURL
:
tsTLS
.
URL
,
expected
:
"version:v1.9.3"
,
caData
:
certPEM
,
name
:
"retrieve open api schema error"
,
version
:
"version:v1.8.0"
,
disc
:
&
fakeDiscovery
{
withOpenAPISchemaError
:
true
},
},
}
for
_
,
tc
:=
range
cases
{
t
.
Run
(
tc
.
name
,
func
(
t
*
testing
.
T
)
{
c
:=
Config
{
Config
:
&
clientConfig
{
caFile
:
tc
.
caFile
,
caData
:
tc
.
caData
,
Config
:
&
clientConfig
{
},
discoveryClient
:
func
()
(
discovery
.
DiscoveryInterface
,
error
)
{
return
tc
.
disc
,
tc
.
createErr
},
}
got
:=
c
.
GetAPISpec
(
tc
.
serverURL
)
require
.
Equal
(
t
,
tc
.
expected
,
got
)
got
:=
c
.
GetAPISpec
()
require
.
Equal
(
t
,
tc
.
version
,
got
)
})
}
}
func
buildPEM
(
cert
*
x509
.
Certificate
)
[]
byte
{
b
:=
&
pem
.
Block
{
Type
:
"CERTIFICATE"
,
Bytes
:
cert
.
Raw
}
return
pem
.
EncodeToMemory
(
b
)
}
type
clientConfig
struct
{
caFile
string
caData
[]
byte
}
var
_
clientcmd
.
ClientConfig
=
(
*
clientConfig
)(
nil
)
...
...
@@ -120,12 +80,7 @@ func (c *clientConfig) RawConfig() (clientcmdapi.Config, error) {
}
func
(
c
*
clientConfig
)
ClientConfig
()
(
*
restclient
.
Config
,
error
)
{
rc
:=
&
restclient
.
Config
{
TLSClientConfig
:
restclient
.
TLSClientConfig
{
CAData
:
c
.
caData
,
CAFile
:
c
.
caFile
,
},
}
rc
:=
&
restclient
.
Config
{}
return
rc
,
nil
}
...
...
@@ -139,3 +94,53 @@ func (c *clientConfig) ConfigAccess() clientcmd.ConfigAccess {
return
ca
}
type
fakeDiscovery
struct
{
withOpenAPISchemaError
bool
}
var
_
discovery
.
DiscoveryInterface
=
(
*
fakeDiscovery
)(
nil
)
func
(
c
*
fakeDiscovery
)
ServerResourcesForGroupVersion
(
groupVersion
string
)
(
*
metav1
.
APIResourceList
,
error
)
{
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
c
*
fakeDiscovery
)
ServerResources
()
([]
*
metav1
.
APIResourceList
,
error
)
{
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
c
*
fakeDiscovery
)
ServerPreferredResources
()
([]
*
metav1
.
APIResourceList
,
error
)
{
return
nil
,
nil
}
func
(
c
*
fakeDiscovery
)
ServerPreferredNamespacedResources
()
([]
*
metav1
.
APIResourceList
,
error
)
{
return
nil
,
nil
}
func
(
c
*
fakeDiscovery
)
ServerGroups
()
(
*
metav1
.
APIGroupList
,
error
)
{
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
c
*
fakeDiscovery
)
ServerVersion
()
(
*
version
.
Info
,
error
)
{
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
c
*
fakeDiscovery
)
OpenAPISchema
()
(
*
openapi_v2
.
Document
,
error
)
{
if
c
.
withOpenAPISchemaError
{
return
nil
,
errors
.
New
(
"schema error"
)
}
return
&
openapi_v2
.
Document
{
Info
:
&
openapi_v2
.
Info
{
Version
:
"v1.9.3"
,
},
},
nil
}
func
(
c
*
fakeDiscovery
)
SwaggerSchema
(
version
schema
.
GroupVersion
)
(
*
swagger
.
ApiDeclaration
,
error
)
{
return
nil
,
errors
.
New
(
"not implemented"
)
}
func
(
c
*
fakeDiscovery
)
RESTClient
()
restclient
.
Interface
{
return
nil
}
pkg/client/testdata/swagger.json
deleted
100644 → 0
View file @
9bd5b3a2
{
"info"
:
{
"version"
:
"v1.9.3"
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment