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
4ad5565c
Unverified
Commit
4ad5565c
authored
Apr 23, 2016
by
Clayton Coleman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
RecognizingDecoder didn't handle ambiguous input
YAML is not guaranteed to be recognizable, so we need to bump JSON and protobuf above it in the decoding order. Add a unit test.
parent
7e1089bb
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
101 additions
and
36 deletions
+101
-36
serialization_proto_test.go
pkg/api/serialization_proto_test.go
+23
-0
json.go
pkg/runtime/serializer/json/json.go
+5
-4
protobuf.go
pkg/runtime/serializer/protobuf/protobuf.go
+0
-6
recognizer.go
pkg/runtime/serializer/recognizer/recognizer.go
+73
-26
No files found.
pkg/api/serialization_proto_test.go
View file @
4ad5565c
...
@@ -17,6 +17,7 @@ limitations under the License.
...
@@ -17,6 +17,7 @@ limitations under the License.
package
api_test
package
api_test
import
(
import
(
"bytes"
"encoding/hex"
"encoding/hex"
"math/rand"
"math/rand"
"testing"
"testing"
...
@@ -41,6 +42,28 @@ func init() {
...
@@ -41,6 +42,28 @@ func init() {
})
})
}
}
func
TestUniversalDeserializer
(
t
*
testing
.
T
)
{
expected
:=
&
v1
.
Pod
{
ObjectMeta
:
v1
.
ObjectMeta
{
Name
:
"test"
}}
d
:=
api
.
Codecs
.
UniversalDeserializer
()
for
_
,
mediaType
:=
range
[]
string
{
"application/json"
,
"application/yaml"
,
"application/vnd.kubernetes.protobuf"
}
{
e
,
ok
:=
api
.
Codecs
.
SerializerForMediaType
(
mediaType
,
nil
)
if
!
ok
{
t
.
Fatal
(
mediaType
)
}
buf
:=
&
bytes
.
Buffer
{}
if
err
:=
e
.
EncodeToStream
(
expected
,
buf
);
err
!=
nil
{
t
.
Fatalf
(
"%s: %v"
,
mediaType
,
err
)
}
obj
,
_
,
err
:=
d
.
Decode
(
buf
.
Bytes
(),
&
unversioned
.
GroupVersionKind
{
Kind
:
"Pod"
,
Version
:
"v1"
},
nil
)
if
err
!=
nil
{
t
.
Fatalf
(
"%s: %v"
,
mediaType
,
err
)
}
if
!
api
.
Semantic
.
DeepEqual
(
expected
,
obj
)
{
t
.
Fatalf
(
"%s: %#v"
,
mediaType
,
obj
)
}
}
}
func
TestProtobufRoundTrip
(
t
*
testing
.
T
)
{
func
TestProtobufRoundTrip
(
t
*
testing
.
T
)
{
obj
:=
&
v1
.
Pod
{}
obj
:=
&
v1
.
Pod
{}
apitesting
.
FuzzerFor
(
t
,
v1
.
SchemeGroupVersion
,
rand
.
NewSource
(
benchmarkSeed
))
.
Fuzz
(
obj
)
apitesting
.
FuzzerFor
(
t
,
v1
.
SchemeGroupVersion
,
rand
.
NewSource
(
benchmarkSeed
))
.
Fuzz
(
obj
)
...
...
pkg/runtime/serializer/json/json.go
View file @
4ad5565c
...
@@ -186,12 +186,13 @@ func (s *Serializer) EncodeToStream(obj runtime.Object, w io.Writer, overrides .
...
@@ -186,12 +186,13 @@ func (s *Serializer) EncodeToStream(obj runtime.Object, w io.Writer, overrides .
}
}
// RecognizesData implements the RecognizingDecoder interface.
// RecognizesData implements the RecognizingDecoder interface.
func
(
s
*
Serializer
)
RecognizesData
(
peek
io
.
Reader
)
(
bool
,
error
)
{
func
(
s
*
Serializer
)
RecognizesData
(
peek
io
.
Reader
)
(
ok
,
unknown
bool
,
err
error
)
{
_
,
ok
:=
utilyaml
.
GuessJSONStream
(
peek
,
2048
)
if
s
.
yaml
{
if
s
.
yaml
{
return
!
ok
,
nil
// we could potentially look for '---'
return
false
,
true
,
nil
}
}
return
ok
,
nil
_
,
ok
=
utilyaml
.
GuessJSONStream
(
peek
,
2048
)
return
ok
,
false
,
nil
}
}
// EncodesAsText returns true because both JSON and YAML are considered textual representations
// EncodesAsText returns true because both JSON and YAML are considered textual representations
...
...
pkg/runtime/serializer/protobuf/protobuf.go
View file @
4ad5565c
...
@@ -419,12 +419,6 @@ func (s *RawSerializer) EncodeToStream(obj runtime.Object, w io.Writer, override
...
@@ -419,12 +419,6 @@ func (s *RawSerializer) EncodeToStream(obj runtime.Object, w io.Writer, override
}
}
}
}
// RecognizesData implements the RecognizingDecoder interface - objects encoded with this serializer
// have no innate identifying information and so cannot be recognized.
func
(
s
*
RawSerializer
)
RecognizesData
(
peek
io
.
Reader
)
(
bool
,
error
)
{
return
false
,
nil
}
var
LengthDelimitedFramer
=
lengthDelimitedFramer
{}
var
LengthDelimitedFramer
=
lengthDelimitedFramer
{}
type
lengthDelimitedFramer
struct
{}
type
lengthDelimitedFramer
struct
{}
...
...
pkg/runtime/serializer/recognizer/recognizer.go
View file @
4ad5565c
...
@@ -27,51 +27,98 @@ import (
...
@@ -27,51 +27,98 @@ import (
type
RecognizingDecoder
interface
{
type
RecognizingDecoder
interface
{
runtime
.
Decoder
runtime
.
Decoder
RecognizesData
(
peek
io
.
Reader
)
(
bool
,
error
)
// RecognizesData should return true if the input provided in the provided reader
// belongs to this decoder, or an error if the data could not be read or is ambiguous.
// Unknown is true if the data could not be determined to match the decoder type.
// Decoders should assume that they can read as much of peek as they need (as the caller
// provides) and may return unknown if the data provided is not sufficient to make a
// a determination. When peek returns EOF that may mean the end of the input or the
// end of buffered input - recognizers should return the best guess at that time.
RecognizesData
(
peek
io
.
Reader
)
(
ok
,
unknown
bool
,
err
error
)
}
}
// NewDecoder creates a decoder that will attempt multiple decoders in an order defined
// by:
//
// 1. The decoder implements RecognizingDecoder and identifies the data
// 2. All other decoders, and any decoder that returned true for unknown.
//
// The order passed to the constructor is preserved within those priorities.
func
NewDecoder
(
decoders
...
runtime
.
Decoder
)
runtime
.
Decoder
{
func
NewDecoder
(
decoders
...
runtime
.
Decoder
)
runtime
.
Decoder
{
recognizing
,
blind
:=
[]
RecognizingDecoder
{},
[]
runtime
.
Decoder
{}
for
_
,
d
:=
range
decoders
{
if
r
,
ok
:=
d
.
(
RecognizingDecoder
);
ok
{
recognizing
=
append
(
recognizing
,
r
)
}
else
{
blind
=
append
(
blind
,
d
)
}
}
return
&
decoder
{
return
&
decoder
{
recognizing
:
recognizing
,
decoders
:
decoders
,
blind
:
blind
,
}
}
}
}
type
decoder
struct
{
type
decoder
struct
{
recognizing
[]
RecognizingDecoder
decoders
[]
runtime
.
Decoder
blind
[]
runtime
.
Decoder
}
}
func
(
d
*
decoder
)
Decode
(
data
[]
byte
,
gvk
*
unversioned
.
GroupVersionKind
,
into
runtime
.
Object
)
(
runtime
.
Object
,
*
unversioned
.
GroupVersionKind
,
error
)
{
var
_
RecognizingDecoder
=
&
decoder
{}
var
lastErr
error
for
_
,
r
:=
range
d
.
recognizing
{
func
(
d
*
decoder
)
RecognizesData
(
peek
io
.
Reader
)
(
bool
,
bool
,
error
)
{
buf
:=
bytes
.
NewBuffer
(
data
)
var
(
ok
,
err
:=
r
.
RecognizesData
(
buf
)
lastErr
error
if
err
!=
nil
{
anyUnknown
bool
lastErr
=
err
)
continue
data
,
_
:=
bufio
.
NewReaderSize
(
peek
,
1024
)
.
Peek
(
1024
)
for
_
,
r
:=
range
d
.
decoders
{
switch
t
:=
r
.
(
type
)
{
case
RecognizingDecoder
:
ok
,
unknown
,
err
:=
t
.
RecognizesData
(
bytes
.
NewBuffer
(
data
))
if
err
!=
nil
{
lastErr
=
err
continue
}
anyUnknown
=
anyUnknown
||
unknown
if
!
ok
{
continue
}
return
true
,
false
,
nil
}
}
if
!
ok
{
}
continue
return
false
,
anyUnknown
,
lastErr
}
func
(
d
*
decoder
)
Decode
(
data
[]
byte
,
gvk
*
unversioned
.
GroupVersionKind
,
into
runtime
.
Object
)
(
runtime
.
Object
,
*
unversioned
.
GroupVersionKind
,
error
)
{
var
(
lastErr
error
skipped
[]
runtime
.
Decoder
)
// try recognizers, record any decoders we need to give a chance later
for
_
,
r
:=
range
d
.
decoders
{
switch
t
:=
r
.
(
type
)
{
case
RecognizingDecoder
:
buf
:=
bytes
.
NewBuffer
(
data
)
ok
,
unknown
,
err
:=
t
.
RecognizesData
(
buf
)
if
err
!=
nil
{
lastErr
=
err
continue
}
if
unknown
{
skipped
=
append
(
skipped
,
t
)
continue
}
if
!
ok
{
continue
}
return
r
.
Decode
(
data
,
gvk
,
into
)
default
:
skipped
=
append
(
skipped
,
t
)
}
}
return
r
.
Decode
(
data
,
gvk
,
into
)
}
}
for
_
,
d
:=
range
d
.
blind
{
out
,
actual
,
err
:=
d
.
Decode
(
data
,
gvk
,
into
)
// try recognizers that returned unknown or didn't recognize their data
for
_
,
r
:=
range
skipped
{
out
,
actual
,
err
:=
r
.
Decode
(
data
,
gvk
,
into
)
if
err
!=
nil
{
if
err
!=
nil
{
lastErr
=
err
lastErr
=
err
continue
continue
}
}
return
out
,
actual
,
nil
return
out
,
actual
,
nil
}
}
if
lastErr
==
nil
{
if
lastErr
==
nil
{
lastErr
=
fmt
.
Errorf
(
"no serialization format matched the provided data"
)
lastErr
=
fmt
.
Errorf
(
"no serialization format matched the provided data"
)
}
}
...
...
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