Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
4c58302b
Commit
4c58302b
authored
Jan 20, 2016
by
Kris
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adding dynamic client
parent
afc55647
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
560 additions
and
21 deletions
+560
-21
client.go
pkg/client/typed/dynamic/client.go
+217
-0
client_test.go
pkg/client/typed/dynamic/client_test.go
+0
-0
register.go
pkg/runtime/register.go
+1
-0
scheme.go
pkg/runtime/scheme.go
+1
-1
types.go
pkg/runtime/types.go
+14
-0
unstructured.go
pkg/runtime/unstructured.go
+103
-20
unstructured_test.go
pkg/runtime/unstructured_test.go
+75
-0
dynamic_client_test.go
test/integration/dynamic_client_test.go
+149
-0
No files found.
pkg/client/typed/dynamic/client.go
0 → 100644
View file @
4c58302b
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package dynamic provides a client interface to arbitrary Kubernetes
// APIs that exposes common high level operations and exposes common
// metadata.
package
dynamic
import
(
"encoding/json"
"errors"
"io"
"net/url"
"strings"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/v1"
client
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/conversion/queryparams"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/watch"
)
// Client is a Kubernetes client that allows you to access metadata
// and manipulate metadata of a Kubernetes API group.
type
Client
struct
{
cl
*
client
.
RESTClient
}
// NewClient returns a new client based on the passed in config. The
// codec is ignored, as the dynamic client uses it's own codec.
func
NewClient
(
conf
*
client
.
Config
)
(
*
Client
,
error
)
{
// avoid changing the original config
confCopy
:=
*
conf
conf
=
&
confCopy
conf
.
Codec
=
dynamicCodec
{}
if
conf
.
APIPath
==
""
{
conf
.
APIPath
=
"/api"
}
if
len
(
conf
.
UserAgent
)
==
0
{
conf
.
UserAgent
=
client
.
DefaultKubernetesUserAgent
()
}
if
conf
.
QPS
==
0.0
{
conf
.
QPS
=
5.0
}
if
conf
.
Burst
==
0
{
conf
.
Burst
=
10
}
cl
,
err
:=
client
.
RESTClientFor
(
conf
)
if
err
!=
nil
{
return
nil
,
err
}
return
&
Client
{
cl
:
cl
},
nil
}
// Resource returns an API interface to the specified resource for
// this client's group and version. If resource is not a namespaced
// resource, then namespace is ignored.
func
(
c
*
Client
)
Resource
(
resource
*
unversioned
.
APIResource
,
namespace
string
)
*
ResourceClient
{
return
&
ResourceClient
{
cl
:
c
.
cl
,
resource
:
resource
,
ns
:
namespace
,
}
}
// ResourceClient is an API interface to a specific resource under a
// dynamic client.
type
ResourceClient
struct
{
cl
*
client
.
RESTClient
resource
*
unversioned
.
APIResource
ns
string
}
// namespace applies a namespace to the request if the configured
// resource is a namespaced resource. Otherwise, it just returns the
// passed in request.
func
(
rc
*
ResourceClient
)
namespace
(
req
*
client
.
Request
)
*
client
.
Request
{
if
rc
.
resource
.
Namespaced
{
return
req
.
Namespace
(
rc
.
ns
)
}
return
req
}
// List returns a list of objects for this resource.
func
(
rc
*
ResourceClient
)
List
(
opts
v1
.
ListOptions
)
(
*
runtime
.
UnstructuredList
,
error
)
{
result
:=
new
(
runtime
.
UnstructuredList
)
err
:=
rc
.
namespace
(
rc
.
cl
.
Get
())
.
Resource
(
rc
.
resource
.
Name
)
.
VersionedParams
(
&
opts
,
parameterEncoder
)
.
Do
()
.
Into
(
result
)
return
result
,
err
}
// Get gets the resource with the specified name.
func
(
rc
*
ResourceClient
)
Get
(
name
string
)
(
*
runtime
.
Unstructured
,
error
)
{
result
:=
new
(
runtime
.
Unstructured
)
err
:=
rc
.
namespace
(
rc
.
cl
.
Get
())
.
Resource
(
rc
.
resource
.
Name
)
.
Name
(
name
)
.
Do
()
.
Into
(
result
)
return
result
,
err
}
// Delete deletes the resource with the specified name.
func
(
rc
*
ResourceClient
)
Delete
(
name
string
,
opts
*
v1
.
DeleteOptions
)
error
{
return
rc
.
namespace
(
rc
.
cl
.
Delete
())
.
Resource
(
rc
.
resource
.
Name
)
.
Name
(
name
)
.
Body
(
opts
)
.
Do
()
.
Error
()
}
// DeleteCollection deletes a collection of objects.
func
(
rc
*
ResourceClient
)
DeleteCollection
(
deleteOptions
*
v1
.
DeleteOptions
,
listOptions
v1
.
ListOptions
)
error
{
return
rc
.
namespace
(
rc
.
cl
.
Delete
())
.
Resource
(
rc
.
resource
.
Name
)
.
VersionedParams
(
&
listOptions
,
parameterEncoder
)
.
Body
(
deleteOptions
)
.
Do
()
.
Error
()
}
// Create creates the provided resource.
func
(
rc
*
ResourceClient
)
Create
(
obj
*
runtime
.
Unstructured
)
(
*
runtime
.
Unstructured
,
error
)
{
result
:=
new
(
runtime
.
Unstructured
)
err
:=
rc
.
namespace
(
rc
.
cl
.
Post
())
.
Resource
(
rc
.
resource
.
Name
)
.
Body
(
obj
)
.
Do
()
.
Into
(
result
)
return
result
,
err
}
// Update updates the provided resource.
func
(
rc
*
ResourceClient
)
Update
(
obj
*
runtime
.
Unstructured
)
(
*
runtime
.
Unstructured
,
error
)
{
result
:=
new
(
runtime
.
Unstructured
)
if
len
(
obj
.
Name
)
==
0
{
return
result
,
errors
.
New
(
"object missing name"
)
}
err
:=
rc
.
namespace
(
rc
.
cl
.
Put
())
.
Resource
(
rc
.
resource
.
Name
)
.
Name
(
obj
.
Name
)
.
Body
(
obj
)
.
Do
()
.
Into
(
result
)
return
result
,
err
}
// Watch returns a watch.Interface that watches the resource.
func
(
rc
*
ResourceClient
)
Watch
(
opts
v1
.
ListOptions
)
(
watch
.
Interface
,
error
)
{
return
rc
.
namespace
(
rc
.
cl
.
Get
()
.
Prefix
(
"watch"
))
.
Resource
(
rc
.
resource
.
Name
)
.
VersionedParams
(
&
opts
,
parameterEncoder
)
.
Watch
()
}
// dynamicCodec is a codec that wraps the standard unstructured codec
// with special handling for Status objects.
type
dynamicCodec
struct
{}
func
(
dynamicCodec
)
Decode
(
data
[]
byte
,
gvk
*
unversioned
.
GroupVersionKind
,
obj
runtime
.
Object
)
(
runtime
.
Object
,
*
unversioned
.
GroupVersionKind
,
error
)
{
obj
,
gvk
,
err
:=
runtime
.
UnstructuredJSONScheme
.
Decode
(
data
,
gvk
,
obj
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
if
_
,
ok
:=
obj
.
(
*
unversioned
.
Status
);
!
ok
&&
strings
.
ToLower
(
gvk
.
Kind
)
==
"status"
{
obj
=
&
unversioned
.
Status
{}
err
:=
json
.
Unmarshal
(
data
,
obj
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
}
return
obj
,
gvk
,
nil
}
func
(
dynamicCodec
)
EncodeToStream
(
obj
runtime
.
Object
,
w
io
.
Writer
,
overrides
...
unversioned
.
GroupVersion
)
error
{
return
runtime
.
UnstructuredJSONScheme
.
EncodeToStream
(
obj
,
w
,
overrides
...
)
}
// paramaterCodec is a codec converts an API object to query
// parameters without trying to convert to the target version.
type
parameterCodec
struct
{}
func
(
parameterCodec
)
EncodeParameters
(
obj
runtime
.
Object
,
to
unversioned
.
GroupVersion
)
(
url
.
Values
,
error
)
{
return
queryparams
.
Convert
(
obj
)
}
func
(
parameterCodec
)
DecodeParameters
(
parameters
url
.
Values
,
from
unversioned
.
GroupVersion
,
into
runtime
.
Object
)
error
{
return
errors
.
New
(
"DecodeParameters not implemented on dynamic parameterCodec"
)
}
var
parameterEncoder
runtime
.
ParameterCodec
=
parameterCodec
{}
pkg/client/typed/dynamic/client_test.go
0 → 100644
View file @
4c58302b
This diff is collapsed.
Click to expand it.
pkg/runtime/register.go
View file @
4c58302b
...
@@ -32,6 +32,7 @@ func (obj *TypeMeta) GroupVersionKind() *unversioned.GroupVersionKind {
...
@@ -32,6 +32,7 @@ func (obj *TypeMeta) GroupVersionKind() *unversioned.GroupVersionKind {
func
(
obj
*
Unknown
)
GetObjectKind
()
unversioned
.
ObjectKind
{
return
&
obj
.
TypeMeta
}
func
(
obj
*
Unknown
)
GetObjectKind
()
unversioned
.
ObjectKind
{
return
&
obj
.
TypeMeta
}
func
(
obj
*
Unstructured
)
GetObjectKind
()
unversioned
.
ObjectKind
{
return
&
obj
.
TypeMeta
}
func
(
obj
*
Unstructured
)
GetObjectKind
()
unversioned
.
ObjectKind
{
return
&
obj
.
TypeMeta
}
func
(
obj
*
UnstructuredList
)
GetObjectKind
()
unversioned
.
ObjectKind
{
return
&
obj
.
TypeMeta
}
// GetObjectKind implements Object for VersionedObjects, returning an empty ObjectKind
// GetObjectKind implements Object for VersionedObjects, returning an empty ObjectKind
// interface if no objects are provided, or the ObjectKind interface of the object in the
// interface if no objects are provided, or the ObjectKind interface of the object in the
...
...
pkg/runtime/scheme.go
View file @
4c58302b
...
@@ -474,7 +474,7 @@ func (s *Scheme) ConvertToVersion(in Object, outVersion string) (Object, error)
...
@@ -474,7 +474,7 @@ func (s *Scheme) ConvertToVersion(in Object, outVersion string) (Object, error)
return
nil
,
err
return
nil
,
err
}
}
switch
in
.
(
type
)
{
switch
in
.
(
type
)
{
case
*
Unknown
,
*
Unstructured
:
case
*
Unknown
,
*
Unstructured
,
*
UnstructuredList
:
old
:=
in
.
GetObjectKind
()
.
GroupVersionKind
()
old
:=
in
.
GetObjectKind
()
.
GroupVersionKind
()
defer
in
.
GetObjectKind
()
.
SetGroupVersionKind
(
old
)
defer
in
.
GetObjectKind
()
.
SetGroupVersionKind
(
old
)
setTargetVersion
(
in
,
s
,
gv
)
setTargetVersion
(
in
,
s
,
gv
)
...
...
pkg/runtime/types.go
View file @
4c58302b
...
@@ -109,11 +109,25 @@ type Unknown struct {
...
@@ -109,11 +109,25 @@ type Unknown struct {
// metadata and field mutatation.
// metadata and field mutatation.
type
Unstructured
struct
{
type
Unstructured
struct
{
TypeMeta
`json:",inline"`
TypeMeta
`json:",inline"`
// Name is populated from metadata (if present) upon deserialization
Name
string
// Object is a JSON compatible map with string, float, int, []interface{}, or map[string]interface{}
// Object is a JSON compatible map with string, float, int, []interface{}, or map[string]interface{}
// children.
// children.
Object
map
[
string
]
interface
{}
Object
map
[
string
]
interface
{}
}
}
// UnstructuredList allows lists that do not have Golang structs
// registered to be manipulated generically. This can be used to deal
// with the API lists from a plug-in.
type
UnstructuredList
struct
{
TypeMeta
`json:",inline"`
// Items is a list of unstructured objects.
Items
[]
*
Unstructured
`json:"items"`
}
// VersionedObjects is used by Decoders to give callers a way to access all versions
// VersionedObjects is used by Decoders to give callers a way to access all versions
// of an object during the decoding process.
// of an object during the decoding process.
type
VersionedObjects
struct
{
type
VersionedObjects
struct
{
...
...
pkg/runtime/unstructured.go
View file @
4c58302b
...
@@ -30,13 +30,87 @@ var UnstructuredJSONScheme Codec = unstructuredJSONScheme{}
...
@@ -30,13 +30,87 @@ var UnstructuredJSONScheme Codec = unstructuredJSONScheme{}
type
unstructuredJSONScheme
struct
{}
type
unstructuredJSONScheme
struct
{}
func
(
s
unstructuredJSONScheme
)
Decode
(
data
[]
byte
,
_
*
unversioned
.
GroupVersionKind
,
_
Object
)
(
Object
,
*
unversioned
.
GroupVersionKind
,
error
)
{
func
(
s
unstructuredJSONScheme
)
Decode
(
data
[]
byte
,
_
*
unversioned
.
GroupVersionKind
,
obj
Object
)
(
Object
,
*
unversioned
.
GroupVersionKind
,
error
)
{
var
err
error
if
obj
!=
nil
{
err
=
s
.
decodeInto
(
data
,
obj
)
}
else
{
obj
,
err
=
s
.
decode
(
data
)
}
if
err
!=
nil
{
return
nil
,
nil
,
err
}
gvk
:=
obj
.
GetObjectKind
()
.
GroupVersionKind
()
if
len
(
gvk
.
Kind
)
==
0
{
return
nil
,
gvk
,
NewMissingKindErr
(
string
(
data
))
}
return
obj
,
gvk
,
nil
}
func
(
unstructuredJSONScheme
)
EncodeToStream
(
obj
Object
,
w
io
.
Writer
,
overrides
...
unversioned
.
GroupVersion
)
error
{
switch
t
:=
obj
.
(
type
)
{
case
*
Unstructured
:
return
json
.
NewEncoder
(
w
)
.
Encode
(
t
.
Object
)
case
*
UnstructuredList
:
type
encodeList
struct
{
TypeMeta
`json:",inline"`
Items
[]
map
[
string
]
interface
{}
`json:"items"`
}
eList
:=
encodeList
{
TypeMeta
:
t
.
TypeMeta
,
}
for
_
,
i
:=
range
t
.
Items
{
eList
.
Items
=
append
(
eList
.
Items
,
i
.
Object
)
}
return
json
.
NewEncoder
(
w
)
.
Encode
(
eList
)
case
*
Unknown
:
_
,
err
:=
w
.
Write
(
t
.
RawJSON
)
return
err
default
:
return
json
.
NewEncoder
(
w
)
.
Encode
(
t
)
}
}
func
(
s
unstructuredJSONScheme
)
decode
(
data
[]
byte
)
(
Object
,
error
)
{
type
detector
struct
{
Items
json
.
RawMessage
}
var
det
detector
if
err
:=
json
.
Unmarshal
(
data
,
&
det
);
err
!=
nil
{
return
nil
,
err
}
if
det
.
Items
!=
nil
{
list
:=
&
UnstructuredList
{}
err
:=
s
.
decodeToList
(
data
,
list
)
return
list
,
err
}
// No Items field, so it wasn't a list.
unstruct
:=
&
Unstructured
{}
unstruct
:=
&
Unstructured
{}
err
:=
s
.
decodeToUnstructured
(
data
,
unstruct
)
return
unstruct
,
err
}
func
(
s
unstructuredJSONScheme
)
decodeInto
(
data
[]
byte
,
obj
Object
)
error
{
switch
x
:=
obj
.
(
type
)
{
case
*
Unstructured
:
return
s
.
decodeToUnstructured
(
data
,
x
)
case
*
UnstructuredList
:
return
s
.
decodeToList
(
data
,
x
)
default
:
return
json
.
Unmarshal
(
data
,
x
)
}
}
func
(
unstructuredJSONScheme
)
decodeToUnstructured
(
data
[]
byte
,
unstruct
*
Unstructured
)
error
{
m
:=
make
(
map
[
string
]
interface
{})
m
:=
make
(
map
[
string
]
interface
{})
if
err
:=
json
.
Unmarshal
(
data
,
&
m
);
err
!=
nil
{
if
err
:=
json
.
Unmarshal
(
data
,
&
m
);
err
!=
nil
{
return
nil
,
nil
,
err
return
err
}
}
if
v
,
ok
:=
m
[
"kind"
];
ok
{
if
v
,
ok
:=
m
[
"kind"
];
ok
{
if
s
,
ok
:=
v
.
(
string
);
ok
{
if
s
,
ok
:=
v
.
(
string
);
ok
{
unstruct
.
Kind
=
s
unstruct
.
Kind
=
s
...
@@ -47,30 +121,39 @@ func (s unstructuredJSONScheme) Decode(data []byte, _ *unversioned.GroupVersionK
...
@@ -47,30 +121,39 @@ func (s unstructuredJSONScheme) Decode(data []byte, _ *unversioned.GroupVersionK
unstruct
.
APIVersion
=
s
unstruct
.
APIVersion
=
s
}
}
}
}
if
metadata
,
ok
:=
m
[
"metadata"
];
ok
{
if
len
(
unstruct
.
APIVersion
)
==
0
{
if
metadata
,
ok
:=
metadata
.
(
map
[
string
]
interface
{});
ok
{
return
nil
,
nil
,
NewMissingVersionErr
(
string
(
data
))
if
name
,
ok
:=
metadata
[
"name"
];
ok
{
if
name
,
ok
:=
name
.
(
string
);
ok
{
unstruct
.
Name
=
name
}
}
}
gv
,
err
:=
unversioned
.
ParseGroupVersion
(
unstruct
.
APIVersion
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
}
gvk
:=
gv
.
WithKind
(
unstruct
.
Kind
)
if
len
(
unstruct
.
Kind
)
==
0
{
return
nil
,
&
gvk
,
NewMissingKindErr
(
string
(
data
))
}
}
unstruct
.
Object
=
m
unstruct
.
Object
=
m
return
unstruct
,
&
gvk
,
nil
return
nil
}
}
func
(
s
unstructuredJSONScheme
)
EncodeToStream
(
obj
Object
,
w
io
.
Writer
,
overrides
...
unversioned
.
GroupVersion
)
error
{
func
(
s
unstructuredJSONScheme
)
decodeToList
(
data
[]
byte
,
list
*
UnstructuredList
)
error
{
switch
t
:=
obj
.
(
type
)
{
type
decodeList
struct
{
case
*
Unstructured
:
TypeMeta
`json:",inline"`
return
json
.
NewEncoder
(
w
)
.
Encode
(
t
.
Object
)
Items
[]
json
.
RawMessage
case
*
Unknown
:
}
_
,
err
:=
w
.
Write
(
t
.
RawJSON
)
var
dList
decodeList
if
err
:=
json
.
Unmarshal
(
data
,
&
dList
);
err
!=
nil
{
return
err
return
err
default
:
return
json
.
NewEncoder
(
w
)
.
Encode
(
t
)
}
}
list
.
TypeMeta
=
dList
.
TypeMeta
list
.
Items
=
nil
for
_
,
i
:=
range
dList
.
Items
{
unstruct
:=
&
Unstructured
{}
if
err
:=
s
.
decodeToUnstructured
([]
byte
(
i
),
unstruct
);
err
!=
nil
{
return
err
}
list
.
Items
=
append
(
list
.
Items
,
unstruct
)
}
return
nil
}
}
pkg/runtime/unstructured_test.go
View file @
4c58302b
...
@@ -18,6 +18,7 @@ package runtime_test
...
@@ -18,6 +18,7 @@ package runtime_test
import
(
import
(
"fmt"
"fmt"
"reflect"
"testing"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
...
@@ -46,3 +47,77 @@ func TestDecodeUnstructured(t *testing.T) {
...
@@ -46,3 +47,77 @@ func TestDecodeUnstructured(t *testing.T) {
t
.
Errorf
(
"object not converted: %#v"
,
pl
.
Items
[
2
])
t
.
Errorf
(
"object not converted: %#v"
,
pl
.
Items
[
2
])
}
}
}
}
func
TestDecode
(
t
*
testing
.
T
)
{
tcs
:=
[]
struct
{
json
[]
byte
want
runtime
.
Object
}{
{
json
:
[]
byte
(
`{"apiVersion": "test", "kind": "test_kind"}`
),
want
:
&
runtime
.
Unstructured
{
TypeMeta
:
runtime
.
TypeMeta
{
APIVersion
:
"test"
,
Kind
:
"test_kind"
,
},
Object
:
map
[
string
]
interface
{}{
"apiVersion"
:
"test"
,
"kind"
:
"test_kind"
},
},
},
{
json
:
[]
byte
(
`{"apiVersion": "test", "kind": "test_list", "items": []}`
),
want
:
&
runtime
.
UnstructuredList
{
TypeMeta
:
runtime
.
TypeMeta
{
APIVersion
:
"test"
,
Kind
:
"test_list"
,
},
},
},
{
json
:
[]
byte
(
`{"items": [{"metadata": {"name": "object1"}, "apiVersion": "test", "kind": "test_kind"}, {"metadata": {"name": "object2"}, "apiVersion": "test", "kind": "test_kind"}], "apiVersion": "test", "kind": "test_list"}`
),
want
:
&
runtime
.
UnstructuredList
{
TypeMeta
:
runtime
.
TypeMeta
{
APIVersion
:
"test"
,
Kind
:
"test_list"
,
},
Items
:
[]
*
runtime
.
Unstructured
{
{
TypeMeta
:
runtime
.
TypeMeta
{
APIVersion
:
"test"
,
Kind
:
"test_kind"
,
},
Name
:
"object1"
,
Object
:
map
[
string
]
interface
{}{
"metadata"
:
map
[
string
]
interface
{}{
"name"
:
"object1"
},
"apiVersion"
:
"test"
,
"kind"
:
"test_kind"
,
},
},
{
TypeMeta
:
runtime
.
TypeMeta
{
APIVersion
:
"test"
,
Kind
:
"test_kind"
,
},
Name
:
"object2"
,
Object
:
map
[
string
]
interface
{}{
"metadata"
:
map
[
string
]
interface
{}{
"name"
:
"object2"
},
"apiVersion"
:
"test"
,
"kind"
:
"test_kind"
,
},
},
},
},
},
}
for
_
,
tc
:=
range
tcs
{
got
,
_
,
err
:=
runtime
.
UnstructuredJSONScheme
.
Decode
(
tc
.
json
,
nil
,
nil
)
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error for %q: %v"
,
string
(
tc
.
json
),
err
)
continue
}
if
!
reflect
.
DeepEqual
(
got
,
tc
.
want
)
{
t
.
Errorf
(
"Decode(%q) want: %v
\n
got: %v"
,
string
(
tc
.
json
),
tc
.
want
,
got
)
}
}
}
test/integration/dynamic_client_test.go
0 → 100644
View file @
4c58302b
// +build integration,!no-etcd
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
integration
import
(
"reflect"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/typed/dynamic"
uclient
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/test/integration/framework"
)
func
TestDynamicClient
(
t
*
testing
.
T
)
{
_
,
s
:=
framework
.
RunAMaster
(
t
)
defer
s
.
Close
()
framework
.
DeleteAllEtcdKeys
()
gv
:=
testapi
.
Default
.
GroupVersion
()
config
:=
&
uclient
.
Config
{
Host
:
s
.
URL
,
ContentConfig
:
uclient
.
ContentConfig
{
GroupVersion
:
gv
},
}
client
:=
uclient
.
NewOrDie
(
config
)
dynamicClient
,
err
:=
dynamic
.
NewClient
(
config
)
_
=
dynamicClient
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error creating dynamic client: %v"
,
err
)
}
// Find the Pod resource
resources
,
err
:=
client
.
Discovery
()
.
ServerResourcesForGroupVersion
(
gv
.
String
())
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error listing resources: %v"
,
err
)
}
var
resource
unversioned
.
APIResource
for
_
,
r
:=
range
resources
.
APIResources
{
if
r
.
Kind
==
"Pod"
{
resource
=
r
break
}
}
if
len
(
resource
.
Name
)
==
0
{
t
.
Fatalf
(
"could not find the pod resource in group/version %q"
,
gv
.
String
())
}
// Create a Pod with the normal client
pod
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
GenerateName
:
"test"
,
},
Spec
:
api
.
PodSpec
{
Containers
:
[]
api
.
Container
{
{
Name
:
"test"
,
Image
:
"test-image"
,
},
},
},
}
actual
,
err
:=
client
.
Pods
(
framework
.
TestNS
)
.
Create
(
pod
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error when creating pod: %v"
,
err
)
}
// check dynamic list
unstructuredList
,
err
:=
dynamicClient
.
Resource
(
&
resource
,
framework
.
TestNS
)
.
List
(
v1
.
ListOptions
{})
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error when listing pods: %v"
,
err
)
}
if
len
(
unstructuredList
.
Items
)
!=
1
{
t
.
Fatalf
(
"expected one pod, got %d"
,
len
(
unstructuredList
.
Items
))
}
got
,
err
:=
unstructuredToPod
(
unstructuredList
.
Items
[
0
])
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error converting Unstructured to api.Pod: %v"
,
err
)
}
if
!
reflect
.
DeepEqual
(
actual
,
got
)
{
t
.
Fatalf
(
"unexpected pod in list. wanted %#v, got %#v"
,
actual
,
got
)
}
// check dynamic get
unstruct
,
err
:=
dynamicClient
.
Resource
(
&
resource
,
framework
.
TestNS
)
.
Get
(
actual
.
Name
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error when getting pod %q: %v"
,
actual
.
Name
,
err
)
}
got
,
err
=
unstructuredToPod
(
unstruct
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error converting Unstructured to api.Pod: %v"
,
err
)
}
if
!
reflect
.
DeepEqual
(
actual
,
got
)
{
t
.
Fatalf
(
"unexpected pod in list. wanted %#v, got %#v"
,
actual
,
got
)
}
// delete the pod dynamically
err
=
dynamicClient
.
Resource
(
&
resource
,
framework
.
TestNS
)
.
Delete
(
actual
.
Name
,
nil
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error when deleting pod: %v"
,
err
)
}
list
,
err
:=
client
.
Pods
(
framework
.
TestNS
)
.
List
(
api
.
ListOptions
{})
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error when listing pods: %v"
,
err
)
}
if
len
(
list
.
Items
)
!=
0
{
t
.
Fatalf
(
"expected zero pods, got %d"
,
len
(
list
.
Items
))
}
}
func
unstructuredToPod
(
obj
*
runtime
.
Unstructured
)
(
*
api
.
Pod
,
error
)
{
json
,
err
:=
runtime
.
Encode
(
runtime
.
UnstructuredJSONScheme
,
obj
)
if
err
!=
nil
{
return
nil
,
err
}
pod
:=
new
(
api
.
Pod
)
err
=
runtime
.
DecodeInto
(
testapi
.
Default
.
Codec
(),
json
,
pod
)
return
pod
,
err
}
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