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
1a8845af
Commit
1a8845af
authored
May 01, 2015
by
Clayton Coleman
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #7490 from smarterclayton/alter_list
Do not automatically decode runtime.RawExtension
parents
8c4705fa
12ba4e24
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
391 additions
and
61 deletions
+391
-61
fuzzer.go
pkg/api/testing/fuzzer.go
+4
-2
fixture.go
pkg/client/testclient/fixture.go
+15
-18
testclient.go
pkg/client/testclient/testclient.go
+1
-1
testclient_test.go
pkg/client/testclient/testclient_test.go
+3
-3
error.go
pkg/conversion/error.go
+8
-0
scheme.go
pkg/conversion/scheme.go
+11
-0
get_test.go
pkg/kubectl/cmd/get_test.go
+11
-0
visitor.go
pkg/kubectl/resource/visitor.go
+6
-0
namespace_controller_test.go
pkg/namespace/namespace_controller_test.go
+1
-1
codec.go
pkg/runtime/codec.go
+4
-4
embedded_test.go
pkg/runtime/embedded_test.go
+36
-6
helper.go
pkg/runtime/helper.go
+38
-2
helper_test.go
pkg/runtime/helper_test.go
+17
-0
interfaces.go
pkg/runtime/interfaces.go
+57
-0
scheme.go
pkg/runtime/scheme.go
+24
-16
types.go
pkg/runtime/types.go
+14
-0
unstructured.go
pkg/runtime/unstructured.go
+89
-0
unstructured_test.go
pkg/runtime/unstructured_test.go
+44
-0
persistent_claim_test.go
pkg/volume/persistent_claim/persistent_claim_test.go
+2
-2
persistent_volume_claim_binder_test.go
pkg/volumeclaimbinder/persistent_volume_claim_binder_test.go
+6
-6
No files found.
pkg/api/testing/fuzzer.go
View file @
1a8845af
...
...
@@ -115,12 +115,14 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
},
func
(
j
*
api
.
List
,
c
fuzz
.
Continue
)
{
c
.
FuzzNoCustom
(
j
)
// fuzz self without calling this function again
if
j
.
Items
==
nil
{
// TODO: uncomment when round trip starts from a versioned object
if
false
{
//j.Items == nil {
j
.
Items
=
[]
runtime
.
Object
{}
}
},
func
(
j
*
runtime
.
Object
,
c
fuzz
.
Continue
)
{
if
c
.
RandBool
()
{
// TODO: uncomment when round trip starts from a versioned object
if
true
{
//c.RandBool() {
*
j
=
&
runtime
.
Unknown
{
TypeMeta
:
runtime
.
TypeMeta
{
Kind
:
"Something"
,
APIVersion
:
"unknown"
},
RawJSON
:
[]
byte
(
`{"apiVersion":"unknown","kind":"Something","someKey":"someValue"}`
),
...
...
pkg/client/testclient/fixture.go
View file @
1a8845af
...
...
@@ -81,7 +81,7 @@ func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc {
// AddObjectsFromPath loads the JSON or YAML file containing Kubernetes API resources
// and adds them to the provided ObjectRetriever.
func
AddObjectsFromPath
(
path
string
,
o
ObjectRetriever
)
error
{
func
AddObjectsFromPath
(
path
string
,
o
ObjectRetriever
,
decoder
runtime
.
Decoder
)
error
{
data
,
err
:=
ioutil
.
ReadFile
(
path
)
if
err
!=
nil
{
return
err
...
...
@@ -90,7 +90,7 @@ func AddObjectsFromPath(path string, o ObjectRetriever) error {
if
err
!=
nil
{
return
err
}
obj
,
err
:=
api
.
Codec
.
Decode
(
data
)
obj
,
err
:=
decoder
.
Decode
(
data
)
if
err
!=
nil
{
return
err
}
...
...
@@ -103,17 +103,12 @@ func AddObjectsFromPath(path string, o ObjectRetriever) error {
type
objects
struct
{
types
map
[
string
][]
runtime
.
Object
last
map
[
string
]
int
typer
runtime
.
ObjectTyper
creater
runtime
.
ObjectCreater
copier
copier
scheme
runtime
.
ObjectScheme
decoder
runtime
.
ObjectDecoder
}
var
_
ObjectRetriever
=
&
objects
{}
type
copier
interface
{
Copy
(
obj
runtime
.
Object
)
(
runtime
.
Object
,
error
)
}
// NewObjects implements the ObjectRetriever interface by introspecting the
// objects provided to Add() and returning them when the Kind method is invoked.
// If an api.List object is provided to Add(), each child item is added. If an
...
...
@@ -124,18 +119,17 @@ type copier interface {
// as a runtime.Object if Status == Success). If multiple PodLists are provided, they
// will be returned in order by the Kind call, and the last PodList will be reused for
// subsequent calls.
func
NewObjects
(
scheme
*
runtime
.
Scheme
)
ObjectRetriever
{
func
NewObjects
(
scheme
runtime
.
ObjectScheme
,
decoder
runtime
.
ObjectDecoder
)
ObjectRetriever
{
return
objects
{
types
:
make
(
map
[
string
][]
runtime
.
Object
),
last
:
make
(
map
[
string
]
int
),
typer
:
scheme
,
creater
:
scheme
,
copier
:
scheme
,
scheme
:
scheme
,
decoder
:
decoder
,
}
}
func
(
o
objects
)
Kind
(
kind
,
name
string
)
(
runtime
.
Object
,
error
)
{
empty
,
_
:=
o
.
creater
.
New
(
""
,
kind
)
empty
,
_
:=
o
.
scheme
.
New
(
""
,
kind
)
nilValue
:=
reflect
.
Zero
(
reflect
.
TypeOf
(
empty
))
.
Interface
()
.
(
runtime
.
Object
)
arr
,
ok
:=
o
.
types
[
kind
]
...
...
@@ -146,14 +140,14 @@ func (o objects) Kind(kind, name string) (runtime.Object, error) {
if
!
ok
{
return
empty
,
nil
}
out
,
err
:=
o
.
creater
.
New
(
""
,
kind
)
out
,
err
:=
o
.
scheme
.
New
(
""
,
kind
)
if
err
!=
nil
{
return
nilValue
,
err
}
if
err
:=
runtime
.
SetList
(
out
,
arr
);
err
!=
nil
{
return
nilValue
,
err
}
if
out
,
err
=
o
.
copier
.
Copy
(
out
);
err
!=
nil
{
if
out
,
err
=
o
.
scheme
.
Copy
(
out
);
err
!=
nil
{
return
nilValue
,
err
}
return
out
,
nil
...
...
@@ -168,7 +162,7 @@ func (o objects) Kind(kind, name string) (runtime.Object, error) {
if
index
<
0
{
return
nilValue
,
errors
.
NewNotFound
(
kind
,
name
)
}
out
,
err
:=
o
.
copier
.
Copy
(
arr
[
index
])
out
,
err
:=
o
.
scheme
.
Copy
(
arr
[
index
])
if
err
!=
nil
{
return
nilValue
,
err
}
...
...
@@ -187,7 +181,7 @@ func (o objects) Kind(kind, name string) (runtime.Object, error) {
}
func
(
o
objects
)
Add
(
obj
runtime
.
Object
)
error
{
_
,
kind
,
err
:=
o
.
typer
.
ObjectVersionAndKind
(
obj
)
_
,
kind
,
err
:=
o
.
scheme
.
ObjectVersionAndKind
(
obj
)
if
err
!=
nil
{
return
err
}
...
...
@@ -202,6 +196,9 @@ func (o objects) Add(obj runtime.Object) error {
if
err
!=
nil
{
return
err
}
if
errs
:=
runtime
.
DecodeList
(
list
,
o
.
decoder
);
len
(
errs
)
>
0
{
return
errs
[
0
]
}
for
_
,
obj
:=
range
list
{
if
err
:=
o
.
Add
(
obj
);
err
!=
nil
{
return
err
...
...
pkg/client/testclient/testclient.go
View file @
1a8845af
...
...
@@ -27,7 +27,7 @@ import (
// NewSimpleFake returns a client that will respond with the provided objects
func
NewSimpleFake
(
objects
...
runtime
.
Object
)
*
Fake
{
o
:=
NewObjects
(
api
.
Scheme
)
o
:=
NewObjects
(
api
.
Scheme
,
api
.
Scheme
)
for
_
,
obj
:=
range
objects
{
if
err
:=
o
.
Add
(
obj
);
err
!=
nil
{
panic
(
err
)
...
...
pkg/client/testclient/testclient_test.go
View file @
1a8845af
...
...
@@ -27,8 +27,8 @@ import (
)
func
TestNewClient
(
t
*
testing
.
T
)
{
o
:=
NewObjects
(
api
.
Scheme
)
if
err
:=
AddObjectsFromPath
(
"../../../examples/guestbook/frontend-service.json"
,
o
);
err
!=
nil
{
o
:=
NewObjects
(
api
.
Scheme
,
api
.
Scheme
)
if
err
:=
AddObjectsFromPath
(
"../../../examples/guestbook/frontend-service.json"
,
o
,
api
.
Scheme
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
client
:=
&
Fake
{
ReactFn
:
ObjectReaction
(
o
,
latest
.
RESTMapper
)}
...
...
@@ -52,7 +52,7 @@ func TestNewClient(t *testing.T) {
}
func
TestErrors
(
t
*
testing
.
T
)
{
o
:=
NewObjects
(
api
.
Scheme
)
o
:=
NewObjects
(
api
.
Scheme
,
api
.
Scheme
)
o
.
Add
(
&
api
.
List
{
Items
:
[]
runtime
.
Object
{
// This first call to List will return this error
...
...
pkg/conversion/error.go
View file @
1a8845af
...
...
@@ -54,6 +54,10 @@ type missingKindErr struct {
data
string
}
func
NewMissingKindErr
(
data
string
)
error
{
return
&
missingKindErr
{
data
}
}
func
(
k
*
missingKindErr
)
Error
()
string
{
return
fmt
.
Sprintf
(
"Object 'Kind' is missing in '%s'"
,
k
.
data
)
}
...
...
@@ -70,6 +74,10 @@ type missingVersionErr struct {
data
string
}
func
NewMissingVersionErr
(
data
string
)
error
{
return
&
missingVersionErr
{
data
}
}
func
(
k
*
missingVersionErr
)
Error
()
string
{
return
fmt
.
Sprintf
(
"Object 'apiVersion' is missing in '%s'"
,
k
.
data
)
}
...
...
pkg/conversion/scheme.go
View file @
1a8845af
...
...
@@ -238,6 +238,17 @@ func (s *Scheme) AddDefaultingFuncs(defaultingFuncs ...interface{}) error {
return
nil
}
// Recognizes returns true if the scheme is able to handle the provided version and kind
// of an object.
func
(
s
*
Scheme
)
Recognizes
(
version
,
kind
string
)
bool
{
m
,
ok
:=
s
.
versionMap
[
version
]
if
!
ok
{
return
false
}
_
,
ok
=
m
[
kind
]
return
ok
}
// RegisterInputDefaults sets the provided field mapping function and field matching
// as the defaults for the provided input type. The fn may be nil, in which case no
// mapping will happen by default. Use this method to register a mechanism for handling
...
...
pkg/kubectl/cmd/get_test.go
View file @
1a8845af
...
...
@@ -393,6 +393,17 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) {
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
list
,
err
:=
runtime
.
ExtractList
(
out
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
if
errs
:=
runtime
.
DecodeList
(
list
,
api
.
Scheme
);
len
(
errs
)
>
0
{
t
.
Fatalf
(
"unexpected error: %v"
,
errs
)
}
if
err
:=
runtime
.
SetList
(
out
,
list
);
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
expected
:=
&
api
.
List
{
Items
:
[]
runtime
.
Object
{
&
pods
.
Items
[
0
],
...
...
pkg/kubectl/resource/visitor.go
View file @
1a8845af
...
...
@@ -347,6 +347,12 @@ func (v FlattenListVisitor) Visit(fn VisitorFunc) error {
if
err
!=
nil
{
return
fn
(
info
)
}
if
errs
:=
runtime
.
DecodeList
(
items
,
struct
{
runtime
.
ObjectTyper
runtime
.
Decoder
}{
v
.
Mapper
,
info
.
Mapping
.
Codec
});
len
(
errs
)
>
0
{
return
errors
.
NewAggregate
(
errs
)
}
for
i
:=
range
items
{
item
,
err
:=
v
.
InfoForObject
(
items
[
i
])
if
err
!=
nil
{
...
...
pkg/namespace/namespace_controller_test.go
View file @
1a8845af
...
...
@@ -135,7 +135,7 @@ func TestSyncNamespaceThatIsActive(t *testing.T) {
}
func
TestRunStop
(
t
*
testing
.
T
)
{
o
:=
testclient
.
NewObjects
(
api
.
Scheme
)
o
:=
testclient
.
NewObjects
(
api
.
Scheme
,
api
.
Scheme
)
client
:=
&
testclient
.
Fake
{
ReactFn
:
testclient
.
ObjectReaction
(
o
,
latest
.
RESTMapper
)}
nsMgr
:=
NewNamespaceManager
(
client
,
1
*
time
.
Second
)
...
...
pkg/runtime/codec.go
View file @
1a8845af
...
...
@@ -21,8 +21,8 @@ import (
)
// CodecFor returns a Codec that invokes Encode with the provided version.
func
CodecFor
(
scheme
*
Scheme
,
version
string
)
Codec
{
return
&
codecWrapper
{
scheme
,
version
}
func
CodecFor
(
codec
ObjectCodec
,
version
string
)
Codec
{
return
&
codecWrapper
{
codec
,
version
}
}
// yamlCodec converts YAML passed to the Decoder methods to JSON.
...
...
@@ -69,11 +69,11 @@ func EncodeOrDie(codec Codec, obj Object) string {
// codecWrapper implements encoding to an alternative
// default version for a scheme.
type
codecWrapper
struct
{
*
Scheme
ObjectCodec
version
string
}
// Encode implements Codec
func
(
c
*
codecWrapper
)
Encode
(
obj
Object
)
([]
byte
,
error
)
{
return
c
.
Scheme
.
EncodeToVersion
(
obj
,
c
.
version
)
return
c
.
EncodeToVersion
(
obj
,
c
.
version
)
}
pkg/runtime/embedded_test.go
View file @
1a8845af
...
...
@@ -63,9 +63,22 @@ func TestDecodeEmptyRawExtensionAsObject(t *testing.T) {
s
.
AddKnownTypes
(
""
,
&
ObjectTest
{})
s
.
AddKnownTypeWithName
(
"v1test"
,
"ObjectTest"
,
&
ObjectTestExternal
{})
_
,
err
:=
s
.
Decode
([]
byte
(
`{"kind":"ObjectTest","apiVersion":"v1test","items":[{}]}`
))
if
err
==
nil
{
t
.
Fatalf
(
"unexpected non-error"
)
obj
,
err
:=
s
.
Decode
([]
byte
(
`{"kind":"ObjectTest","apiVersion":"v1test","items":[{}]}`
))
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
test
:=
obj
.
(
*
ObjectTest
)
if
unk
,
ok
:=
test
.
Items
[
0
]
.
(
*
runtime
.
Unknown
);
!
ok
||
unk
.
Kind
!=
""
||
unk
.
APIVersion
!=
""
||
string
(
unk
.
RawJSON
)
!=
"{}"
{
t
.
Fatalf
(
"unexpected object: %#v"
,
test
.
Items
[
0
])
}
obj
,
err
=
s
.
Decode
([]
byte
(
`{"kind":"ObjectTest","apiVersion":"v1test","items":[{"kind":"Other","apiVersion":"v1"}]}`
))
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
test
=
obj
.
(
*
ObjectTest
)
if
unk
,
ok
:=
test
.
Items
[
0
]
.
(
*
runtime
.
Unknown
);
!
ok
||
unk
.
Kind
!=
"Other"
||
unk
.
APIVersion
!=
"v1"
||
string
(
unk
.
RawJSON
)
!=
`{"kind":"Other","apiVersion":"v1"}`
{
t
.
Fatalf
(
"unexpected object: %#v"
,
test
.
Items
[
0
])
}
}
...
...
@@ -99,17 +112,34 @@ func TestArrayOfRuntimeObject(t *testing.T) {
if
err
:=
json
.
Unmarshal
(
wire
,
obj
);
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
t
.
Logf
(
"exact wire is: %
#v
"
,
string
(
obj
.
Items
[
0
]
.
RawJSON
))
t
.
Logf
(
"exact wire is: %
s
"
,
string
(
obj
.
Items
[
0
]
.
RawJSON
))
decoded
,
err
:=
s
.
Decode
(
wire
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
list
,
err
:=
runtime
.
ExtractList
(
decoded
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
if
errs
:=
runtime
.
DecodeList
(
list
,
s
);
len
(
errs
)
>
0
{
t
.
Fatalf
(
"unexpected error: %v"
,
errs
)
}
list2
,
err
:=
runtime
.
ExtractList
(
list
[
3
])
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
if
errs
:=
runtime
.
DecodeList
(
list2
,
s
);
len
(
errs
)
>
0
{
t
.
Fatalf
(
"unexpected error: %v"
,
errs
)
}
if
err
:=
runtime
.
SetList
(
list
[
3
],
list2
);
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
internal
.
Items
[
2
]
.
(
*
runtime
.
Unknown
)
.
Kind
=
"OtherTest"
internal
.
Items
[
2
]
.
(
*
runtime
.
Unknown
)
.
APIVersion
=
"unknown"
if
e
,
a
:=
internal
,
decoded
;
!
reflect
.
DeepEqual
(
e
,
a
)
{
t
.
Log
(
string
(
decoded
.
(
*
ObjectTest
)
.
Items
[
2
]
.
(
*
runtime
.
Unknown
)
.
RawJSON
))
if
e
,
a
:=
internal
.
Items
,
list
;
!
reflect
.
DeepEqual
(
e
,
a
)
{
t
.
Errorf
(
"mismatched decoded: %s"
,
util
.
ObjectDiff
(
e
,
a
))
}
}
...
...
pkg/runtime/helper.go
View file @
1a8845af
...
...
@@ -23,7 +23,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
)
//
TODO: move me to pkg/api/meta
//
IsListType returns true if the provided Object has a slice called Items
func
IsListType
(
obj
Object
)
bool
{
_
,
err
:=
GetItemsPtr
(
obj
)
return
err
==
nil
...
...
@@ -33,7 +33,6 @@ func IsListType(obj Object) bool {
// If 'list' doesn't have an Items member, it's not really a list type
// and an error will be returned.
// This function will either return a pointer to a slice, or an error, but not both.
// TODO: move me to pkg/api/meta
func
GetItemsPtr
(
list
Object
)
(
interface
{},
error
)
{
v
,
err
:=
conversion
.
EnforcePtr
(
list
)
if
err
!=
nil
{
...
...
@@ -150,9 +149,36 @@ func FieldPtr(v reflect.Value, fieldName string, dest interface{}) error {
return
fmt
.
Errorf
(
"couldn't assign/convert %v to %v"
,
field
.
Type
(),
v
.
Type
())
}
// DecodeList alters the list in place, attempting to decode any objects found in
// the list that have the runtime.Unknown type. Any errors that occur are returned
// after the entire list is processed. Decoders are tried in order.
func
DecodeList
(
objects
[]
Object
,
decoders
...
ObjectDecoder
)
[]
error
{
errs
:=
[]
error
(
nil
)
for
i
,
obj
:=
range
objects
{
switch
t
:=
obj
.
(
type
)
{
case
*
Unknown
:
for
_
,
decoder
:=
range
decoders
{
if
!
decoder
.
Recognizes
(
t
.
APIVersion
,
t
.
Kind
)
{
continue
}
obj
,
err
:=
decoder
.
Decode
(
t
.
RawJSON
)
if
err
!=
nil
{
errs
=
append
(
errs
,
err
)
break
}
objects
[
i
]
=
obj
break
}
}
}
return
errs
}
// MultiObjectTyper returns the types of objects across multiple schemes in order.
type
MultiObjectTyper
[]
ObjectTyper
var
_
ObjectTyper
=
MultiObjectTyper
{}
func
(
m
MultiObjectTyper
)
DataVersionAndKind
(
data
[]
byte
)
(
version
,
kind
string
,
err
error
)
{
for
_
,
t
:=
range
m
{
version
,
kind
,
err
=
t
.
DataVersionAndKind
(
data
)
...
...
@@ -162,6 +188,7 @@ func (m MultiObjectTyper) DataVersionAndKind(data []byte) (version, kind string,
}
return
}
func
(
m
MultiObjectTyper
)
ObjectVersionAndKind
(
obj
Object
)
(
version
,
kind
string
,
err
error
)
{
for
_
,
t
:=
range
m
{
version
,
kind
,
err
=
t
.
ObjectVersionAndKind
(
obj
)
...
...
@@ -171,3 +198,12 @@ func (m MultiObjectTyper) ObjectVersionAndKind(obj Object) (version, kind string
}
return
}
func
(
m
MultiObjectTyper
)
Recognizes
(
version
,
kind
string
)
bool
{
for
_
,
t
:=
range
m
{
if
t
.
Recognizes
(
version
,
kind
)
{
return
true
}
}
return
false
}
pkg/runtime/helper_test.go
View file @
1a8845af
...
...
@@ -21,6 +21,7 @@ import (
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
_
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta3"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
...
...
@@ -132,6 +133,22 @@ func TestExtractListOfValuePtrs(t *testing.T) {
}
}
func
TestDecodeList
(
t
*
testing
.
T
)
{
pl
:=
&
api
.
List
{
Items
:
[]
runtime
.
Object
{
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"1"
}},
&
runtime
.
Unknown
{
TypeMeta
:
runtime
.
TypeMeta
{
Kind
:
"Pod"
,
APIVersion
:
"v1beta3"
},
RawJSON
:
[]
byte
(
`{"kind":"Pod","apiVersion":"v1beta3","metadata":{"name":"test"}}`
)},
&
runtime
.
Unstructured
{
TypeMeta
:
runtime
.
TypeMeta
{
Kind
:
"Foo"
,
APIVersion
:
"Bar"
},
Object
:
map
[
string
]
interface
{}{
"test"
:
"value"
}},
},
}
if
errs
:=
runtime
.
DecodeList
(
pl
.
Items
,
api
.
Scheme
);
len
(
errs
)
!=
0
{
t
.
Fatalf
(
"unexpected error %v"
,
errs
)
}
if
pod
,
ok
:=
pl
.
Items
[
1
]
.
(
*
api
.
Pod
);
!
ok
||
pod
.
Name
!=
"test"
{
t
.
Errorf
(
"object not converted: %#v"
,
pl
.
Items
[
1
])
}
}
func
TestSetList
(
t
*
testing
.
T
)
{
pl
:=
&
api
.
PodList
{}
list
:=
[]
runtime
.
Object
{
...
...
pkg/runtime/interfaces.go
View file @
1a8845af
...
...
@@ -16,6 +16,24 @@ limitations under the License.
package
runtime
// ObjectScheme represents common conversions between formal external API versions
// and the internal Go structs. ObjectScheme is typically used with ObjectCodec to
// transform internal Go structs into serialized versions. There may be many valid
// ObjectCodecs for each ObjectScheme.
type
ObjectScheme
interface
{
ObjectConvertor
ObjectTyper
ObjectCreater
ObjectCopier
}
// ObjectCodec represents the common mechanisms for converting to and from a particular
// binary representation of an object.
type
ObjectCodec
interface
{
ObjectEncoder
Decoder
}
// Decoder defines methods for deserializing API objects into a given type
type
Decoder
interface
{
Decode
(
data
[]
byte
)
(
Object
,
error
)
...
...
@@ -33,6 +51,22 @@ type Codec interface {
Encoder
}
// ObjectCopier duplicates an object.
type
ObjectCopier
interface
{
// Copy returns an exact copy of the provided Object, or an error if the
// copy could not be completed.
Copy
(
Object
)
(
Object
,
error
)
}
// ObjectEncoder turns an object into a byte array. This interface is a
// general form of the Encoder interface
type
ObjectEncoder
interface
{
// EncodeToVersion convert and serializes an object in the internal format
// to a specified output version. An error is returned if the object
// cannot be converted for any reason.
EncodeToVersion
(
obj
Object
,
outVersion
string
)
([]
byte
,
error
)
}
// ObjectConvertor converts an object to a different version.
type
ObjectConvertor
interface
{
Convert
(
in
,
out
interface
{})
error
...
...
@@ -43,8 +77,17 @@ type ObjectConvertor interface {
// ObjectTyper contains methods for extracting the APIVersion and Kind
// of objects.
type
ObjectTyper
interface
{
// DataVersionAndKind returns the version and kind of the provided data, or an error
// if another problem is detected. In many cases this method can be as expensive to
// invoke as the Decode method.
DataVersionAndKind
([]
byte
)
(
version
,
kind
string
,
err
error
)
// ObjectVersionAndKind returns the version and kind of the provided object, or an
// error if the object is not recognized (IsNotRegisteredError will return true).
ObjectVersionAndKind
(
Object
)
(
version
,
kind
string
,
err
error
)
// Recognizes returns true if the scheme is able to handle the provided version and kind,
// or more precisely that the provided version is a possible conversion or decoding
// target.
Recognizes
(
version
,
kind
string
)
bool
}
// ObjectCreater contains methods for instantiating an object by kind and version.
...
...
@@ -52,6 +95,20 @@ type ObjectCreater interface {
New
(
version
,
kind
string
)
(
out
Object
,
err
error
)
}
// ObjectDecoder is a convenience interface for identifying serialized versions of objects
// and transforming them into Objects. It intentionally overlaps with ObjectTyper and
// Decoder for use in decode only paths.
type
ObjectDecoder
interface
{
Decoder
// DataVersionAndKind returns the version and kind of the provided data, or an error
// if another problem is detected. In many cases this method can be as expensive to
// invoke as the Decode method.
DataVersionAndKind
([]
byte
)
(
version
,
kind
string
,
err
error
)
// Recognizes returns true if the scheme is able to handle the provided version and kind
// of an object.
Recognizes
(
version
,
kind
string
)
bool
}
// ResourceVersioner provides methods for setting and retrieving
// the resource version from an API object.
type
ResourceVersioner
interface
{
...
...
pkg/runtime/scheme.go
View file @
1a8845af
...
...
@@ -17,6 +17,7 @@ limitations under the License.
package
runtime
import
(
"encoding/json"
"fmt"
"net/url"
"reflect"
...
...
@@ -164,7 +165,15 @@ func (self *Scheme) runtimeObjectToRawExtensionArray(in *[]Object, out *[]RawExt
for
i
:=
range
src
{
switch
t
:=
src
[
i
]
.
(
type
)
{
case
*
Unknown
:
// TODO: this should be decoupled from the scheme (since it is JSON specific)
dest
[
i
]
.
RawJSON
=
t
.
RawJSON
case
*
Unstructured
:
// TODO: this should be decoupled from the scheme (since it is JSON specific)
data
,
err
:=
json
.
Marshal
(
t
.
Object
)
if
err
!=
nil
{
return
err
}
dest
[
i
]
.
RawJSON
=
data
default
:
version
:=
outVersion
// if the object exists
...
...
@@ -192,24 +201,17 @@ func (self *Scheme) rawExtensionToRuntimeObjectArray(in *[]RawExtension, out *[]
for
i
:=
range
src
{
data
:=
src
[
i
]
.
RawJSON
obj
,
err
:=
scheme
.
Decode
(
data
)
version
,
kind
,
err
:=
scheme
.
raw
.
DataVersionAndKind
(
data
)
if
err
!=
nil
{
if
!
IsNotRegisteredError
(
err
)
{
return
err
}
version
,
kind
,
err
:=
scheme
.
raw
.
DataVersionAndKind
(
data
)
if
err
!=
nil
{
return
err
}
obj
=
&
Unknown
{
TypeMeta
:
TypeMeta
{
APIVersion
:
version
,
Kind
:
kind
,
},
RawJSON
:
data
,
}
return
err
}
dest
[
i
]
=
&
Unknown
{
TypeMeta
:
TypeMeta
{
APIVersion
:
version
,
Kind
:
kind
,
},
RawJSON
:
data
,
}
dest
[
i
]
=
obj
}
*
out
=
dest
return
nil
...
...
@@ -275,6 +277,12 @@ func (s *Scheme) ObjectVersionAndKind(obj Object) (version, kind string, err err
return
s
.
raw
.
ObjectVersionAndKind
(
obj
)
}
// Recognizes returns true if the scheme is able to handle the provided version and kind
// of an object.
func
(
s
*
Scheme
)
Recognizes
(
version
,
kind
string
)
bool
{
return
s
.
raw
.
Recognizes
(
version
,
kind
)
}
// New returns a new API object of the given version ("" for internal
// representation) and name, or an error if it hasn't been registered.
func
(
s
*
Scheme
)
New
(
versionName
,
typeName
string
)
(
Object
,
error
)
{
...
...
pkg/runtime/types.go
View file @
1a8845af
...
...
@@ -116,3 +116,17 @@ type Unknown struct {
}
func
(
*
Unknown
)
IsAnAPIObject
()
{}
// Unstructured allows objects that do not have Golang structs registered to be manipulated
// generically. This can be used to deal with the API objects from a plug-in. Unstructured
// objects still have functioning TypeMeta features-- kind, version, etc.
// TODO: Make this object have easy access to field based accessors and settors for
// metadata and field mutatation.
type
Unstructured
struct
{
TypeMeta
`json:",inline"`
// Object is a JSON compatible map with string, float, int, []interface{}, or map[string]interface{}
// children.
Object
map
[
string
]
interface
{}
}
func
(
*
Unstructured
)
IsAnAPIObject
()
{}
pkg/runtime/unstructured.go
0 → 100644
View file @
1a8845af
/*
Copyright 2015 Google Inc. 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
runtime
import
(
"encoding/json"
"fmt"
"reflect"
"github.com/GoogleCloudPlatform/kubernetes/pkg/conversion"
)
// UnstructuredJSONScheme is capable of converting JSON data into the Unstructured
// type, which can be used for generic access to objects without a predefined scheme.
var
UnstructuredJSONScheme
ObjectDecoder
=
unstructuredJSONScheme
{}
type
unstructuredJSONScheme
struct
{}
// Recognizes returns true for any version or kind that is specified (internal
// versions are specifically excluded).
func
(
unstructuredJSONScheme
)
Recognizes
(
version
,
kind
string
)
bool
{
return
len
(
version
)
>
0
&&
len
(
kind
)
>
0
}
func
(
s
unstructuredJSONScheme
)
Decode
(
data
[]
byte
)
(
Object
,
error
)
{
unstruct
:=
&
Unstructured
{}
if
err
:=
s
.
DecodeInto
(
data
,
unstruct
);
err
!=
nil
{
return
nil
,
err
}
return
unstruct
,
nil
}
func
(
unstructuredJSONScheme
)
DecodeInto
(
data
[]
byte
,
obj
Object
)
error
{
unstruct
,
ok
:=
obj
.
(
*
Unstructured
)
if
!
ok
{
return
fmt
.
Errorf
(
"the unstructured JSON scheme does not recognize %v"
,
reflect
.
TypeOf
(
obj
))
}
m
:=
make
(
map
[
string
]
interface
{})
if
err
:=
json
.
Unmarshal
(
data
,
&
m
);
err
!=
nil
{
return
err
}
if
v
,
ok
:=
m
[
"kind"
];
ok
{
if
s
,
ok
:=
v
.
(
string
);
ok
{
unstruct
.
Kind
=
s
}
}
if
v
,
ok
:=
m
[
"apiVersion"
];
ok
{
if
s
,
ok
:=
v
.
(
string
);
ok
{
unstruct
.
APIVersion
=
s
}
}
if
len
(
unstruct
.
APIVersion
)
==
0
{
return
conversion
.
NewMissingVersionErr
(
string
(
data
))
}
if
len
(
unstruct
.
Kind
)
==
0
{
return
conversion
.
NewMissingKindErr
(
string
(
data
))
}
unstruct
.
Object
=
m
return
nil
}
func
(
unstructuredJSONScheme
)
DataVersionAndKind
(
data
[]
byte
)
(
version
,
kind
string
,
err
error
)
{
obj
:=
TypeMeta
{}
if
err
:=
json
.
Unmarshal
(
data
,
&
obj
);
err
!=
nil
{
return
""
,
""
,
err
}
if
len
(
obj
.
APIVersion
)
==
0
{
return
""
,
""
,
conversion
.
NewMissingVersionErr
(
string
(
data
))
}
if
len
(
obj
.
Kind
)
==
0
{
return
""
,
""
,
conversion
.
NewMissingKindErr
(
string
(
data
))
}
return
obj
.
APIVersion
,
obj
.
Kind
,
nil
}
pkg/runtime/unstructured_test.go
0 → 100644
View file @
1a8845af
/*
Copyright 2014 Google Inc. 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
runtime_test
import
(
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
)
func
TestDecodeUnstructured
(
t
*
testing
.
T
)
{
pl
:=
&
api
.
List
{
Items
:
[]
runtime
.
Object
{
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"1"
}},
&
runtime
.
Unknown
{
TypeMeta
:
runtime
.
TypeMeta
{
Kind
:
"Pod"
,
APIVersion
:
"v1beta3"
},
RawJSON
:
[]
byte
(
`{"kind":"Pod","apiVersion":"v1beta3","metadata":{"name":"test"}}`
)},
&
runtime
.
Unknown
{
TypeMeta
:
runtime
.
TypeMeta
{
Kind
:
""
,
APIVersion
:
"v1beta3"
},
RawJSON
:
[]
byte
(
`{"kind":"Pod","apiVersion":"v1beta3","metadata":{"name":"test"}}`
)},
&
runtime
.
Unstructured
{
TypeMeta
:
runtime
.
TypeMeta
{
Kind
:
"Foo"
,
APIVersion
:
"Bar"
},
Object
:
map
[
string
]
interface
{}{
"test"
:
"value"
}},
},
}
if
errs
:=
runtime
.
DecodeList
(
pl
.
Items
,
runtime
.
UnstructuredJSONScheme
);
len
(
errs
)
==
1
{
t
.
Fatalf
(
"unexpected error %v"
,
errs
)
}
if
pod
,
ok
:=
pl
.
Items
[
1
]
.
(
*
runtime
.
Unstructured
);
!
ok
||
pod
.
Object
[
"kind"
]
!=
"Pod"
||
pod
.
Object
[
"metadata"
]
.
(
map
[
string
]
interface
{})[
"name"
]
!=
"test"
{
t
.
Errorf
(
"object not converted: %#v"
,
pl
.
Items
[
1
])
}
if
_
,
ok
:=
pl
.
Items
[
2
]
.
(
*
runtime
.
Unknown
);
!
ok
{
t
.
Errorf
(
"object should not have been converted: %#v"
,
pl
.
Items
[
2
])
}
}
pkg/volume/persistent_claim/persistent_claim_test.go
View file @
1a8845af
...
...
@@ -153,7 +153,7 @@ func TestNewBuilder(t *testing.T) {
}
for
_
,
item
:=
range
tests
{
o
:=
testclient
.
NewObjects
(
api
.
Scheme
)
o
:=
testclient
.
NewObjects
(
api
.
Scheme
,
api
.
Scheme
)
o
.
Add
(
item
.
pv
)
o
.
Add
(
item
.
claim
)
client
:=
&
testclient
.
Fake
{
ReactFn
:
testclient
.
ObjectReaction
(
o
,
latest
.
RESTMapper
)}
...
...
@@ -213,7 +213,7 @@ func TestNewBuilderClaimNotBound(t *testing.T) {
ClaimName
:
"claimC"
,
},
}
o
:=
testclient
.
NewObjects
(
api
.
Scheme
)
o
:=
testclient
.
NewObjects
(
api
.
Scheme
,
api
.
Scheme
)
o
.
Add
(
pv
)
o
.
Add
(
claim
)
client
:=
&
testclient
.
Fake
{
ReactFn
:
testclient
.
ObjectReaction
(
o
,
latest
.
RESTMapper
)}
...
...
pkg/volumeclaimbinder/persistent_volume_claim_binder_test.go
View file @
1a8845af
...
...
@@ -29,7 +29,7 @@ import (
)
func
TestRunStop
(
t
*
testing
.
T
)
{
o
:=
testclient
.
NewObjects
(
api
.
Scheme
)
o
:=
testclient
.
NewObjects
(
api
.
Scheme
,
api
.
Scheme
)
client
:=
&
testclient
.
Fake
{
ReactFn
:
testclient
.
ObjectReaction
(
o
,
latest
.
RESTMapper
)}
binder
:=
NewPersistentVolumeClaimBinder
(
client
,
1
*
time
.
Second
)
...
...
@@ -111,8 +111,8 @@ func TestExampleObjects(t *testing.T) {
}
for
name
,
scenario
:=
range
scenarios
{
o
:=
testclient
.
NewObjects
(
api
.
Scheme
)
if
err
:=
testclient
.
AddObjectsFromPath
(
"../../examples/persistent-volumes/"
+
name
,
o
);
err
!=
nil
{
o
:=
testclient
.
NewObjects
(
api
.
Scheme
,
api
.
Scheme
)
if
err
:=
testclient
.
AddObjectsFromPath
(
"../../examples/persistent-volumes/"
+
name
,
o
,
api
.
Scheme
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -168,11 +168,11 @@ func TestExampleObjects(t *testing.T) {
func
TestBindingWithExamples
(
t
*
testing
.
T
)
{
api
.
ForTesting_ReferencesAllowBlankSelfLinks
=
true
o
:=
testclient
.
NewObjects
(
api
.
Scheme
)
if
err
:=
testclient
.
AddObjectsFromPath
(
"../../examples/persistent-volumes/claims/claim-01.yaml"
,
o
);
err
!=
nil
{
o
:=
testclient
.
NewObjects
(
api
.
Scheme
,
api
.
Scheme
)
if
err
:=
testclient
.
AddObjectsFromPath
(
"../../examples/persistent-volumes/claims/claim-01.yaml"
,
o
,
api
.
Scheme
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
err
:=
testclient
.
AddObjectsFromPath
(
"../../examples/persistent-volumes/volumes/local-01.yaml"
,
o
);
err
!=
nil
{
if
err
:=
testclient
.
AddObjectsFromPath
(
"../../examples/persistent-volumes/volumes/local-01.yaml"
,
o
,
api
.
Scheme
);
err
!=
nil
{
t
.
Fatal
(
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