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
ea59b4c7
Commit
ea59b4c7
authored
Feb 17, 2016
by
Jordan Liggitt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix sinceTime pod log options
parent
63c85691
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
216 additions
and
3 deletions
+216
-3
conversion.go
pkg/api/conversion.go
+11
-0
time.go
pkg/api/unversioned/time.go
+31
-0
conversion_test.go
pkg/api/v1/conversion_test.go
+92
-0
convert.go
pkg/conversion/queryparams/convert.go
+41
-1
convert_test.go
pkg/conversion/queryparams/convert_test.go
+38
-1
kubelet_test.go
test/e2e_node/kubelet_test.go
+3
-1
No files found.
pkg/api/conversion.go
View file @
ea59b4c7
...
@@ -41,6 +41,7 @@ func init() {
...
@@ -41,6 +41,7 @@ func init() {
Convert_unversioned_ListMeta_To_unversioned_ListMeta
,
Convert_unversioned_ListMeta_To_unversioned_ListMeta
,
Convert_intstr_IntOrString_To_intstr_IntOrString
,
Convert_intstr_IntOrString_To_intstr_IntOrString
,
Convert_unversioned_Time_To_unversioned_Time
,
Convert_unversioned_Time_To_unversioned_Time
,
Convert_string_slice_To_unversioned_Time
,
Convert_string_To_labels_Selector
,
Convert_string_To_labels_Selector
,
Convert_string_To_fields_Selector
,
Convert_string_To_fields_Selector
,
Convert_bool_ref_To_bool
,
Convert_bool_ref_To_bool
,
...
@@ -116,6 +117,16 @@ func Convert_unversioned_Time_To_unversioned_Time(in *unversioned.Time, out *unv
...
@@ -116,6 +117,16 @@ func Convert_unversioned_Time_To_unversioned_Time(in *unversioned.Time, out *unv
*
out
=
*
in
*
out
=
*
in
return
nil
return
nil
}
}
// Convert_string_slice_To_unversioned_Time allows converting a URL query parameter value
func
Convert_string_slice_To_unversioned_Time
(
input
*
[]
string
,
out
*
unversioned
.
Time
,
s
conversion
.
Scope
)
error
{
str
:=
""
if
len
(
*
input
)
>
0
{
str
=
(
*
input
)[
0
]
}
return
out
.
UnmarshalQueryParameter
(
str
)
}
func
Convert_string_To_labels_Selector
(
in
*
string
,
out
*
labels
.
Selector
,
s
conversion
.
Scope
)
error
{
func
Convert_string_To_labels_Selector
(
in
*
string
,
out
*
labels
.
Selector
,
s
conversion
.
Scope
)
error
{
selector
,
err
:=
labels
.
Parse
(
*
in
)
selector
,
err
:=
labels
.
Parse
(
*
in
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
pkg/api/unversioned/time.go
View file @
ea59b4c7
...
@@ -97,6 +97,27 @@ func (t *Time) UnmarshalJSON(b []byte) error {
...
@@ -97,6 +97,27 @@ func (t *Time) UnmarshalJSON(b []byte) error {
return
nil
return
nil
}
}
// UnmarshalQueryParameter converts from a URL query parameter value to an object
func
(
t
*
Time
)
UnmarshalQueryParameter
(
str
string
)
error
{
if
len
(
str
)
==
0
{
t
.
Time
=
time
.
Time
{}
return
nil
}
// Tolerate requests from older clients that used JSON serialization to build query params
if
len
(
str
)
==
4
&&
str
==
"null"
{
t
.
Time
=
time
.
Time
{}
return
nil
}
pt
,
err
:=
time
.
Parse
(
time
.
RFC3339
,
str
)
if
err
!=
nil
{
return
err
}
t
.
Time
=
pt
.
Local
()
return
nil
}
// MarshalJSON implements the json.Marshaler interface.
// MarshalJSON implements the json.Marshaler interface.
func
(
t
Time
)
MarshalJSON
()
([]
byte
,
error
)
{
func
(
t
Time
)
MarshalJSON
()
([]
byte
,
error
)
{
if
t
.
IsZero
()
{
if
t
.
IsZero
()
{
...
@@ -107,6 +128,16 @@ func (t Time) MarshalJSON() ([]byte, error) {
...
@@ -107,6 +128,16 @@ func (t Time) MarshalJSON() ([]byte, error) {
return
json
.
Marshal
(
t
.
UTC
()
.
Format
(
time
.
RFC3339
))
return
json
.
Marshal
(
t
.
UTC
()
.
Format
(
time
.
RFC3339
))
}
}
// MarshalQueryParameter converts to a URL query parameter value
func
(
t
Time
)
MarshalQueryParameter
()
(
string
,
error
)
{
if
t
.
IsZero
()
{
// Encode unset/nil objects as an empty string
return
""
,
nil
}
return
t
.
UTC
()
.
Format
(
time
.
RFC3339
),
nil
}
// Fuzz satisfies fuzz.Interface.
// Fuzz satisfies fuzz.Interface.
func
(
t
*
Time
)
Fuzz
(
c
fuzz
.
Continue
)
{
func
(
t
*
Time
)
Fuzz
(
c
fuzz
.
Continue
)
{
if
t
==
nil
{
if
t
==
nil
{
...
...
pkg/api/v1/conversion_test.go
View file @
ea59b4c7
...
@@ -17,13 +17,105 @@ limitations under the License.
...
@@ -17,13 +17,105 @@ limitations under the License.
package
v1_test
package
v1_test
import
(
import
(
"net/url"
"reflect"
"testing"
"testing"
"time"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/unversioned"
versioned
"k8s.io/kubernetes/pkg/api/v1"
versioned
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util"
)
)
func
TestPodLogOptions
(
t
*
testing
.
T
)
{
sinceSeconds
:=
int64
(
1
)
sinceTime
:=
unversioned
.
NewTime
(
time
.
Date
(
2000
,
1
,
1
,
12
,
34
,
56
,
0
,
time
.
UTC
)
.
Local
())
tailLines
:=
int64
(
2
)
limitBytes
:=
int64
(
3
)
versionedLogOptions
:=
&
versioned
.
PodLogOptions
{
Container
:
"mycontainer"
,
Follow
:
true
,
Previous
:
true
,
SinceSeconds
:
&
sinceSeconds
,
SinceTime
:
&
sinceTime
,
Timestamps
:
true
,
TailLines
:
&
tailLines
,
LimitBytes
:
&
limitBytes
,
}
unversionedLogOptions
:=
&
api
.
PodLogOptions
{
Container
:
"mycontainer"
,
Follow
:
true
,
Previous
:
true
,
SinceSeconds
:
&
sinceSeconds
,
SinceTime
:
&
sinceTime
,
Timestamps
:
true
,
TailLines
:
&
tailLines
,
LimitBytes
:
&
limitBytes
,
}
expectedParameters
:=
url
.
Values
{
"container"
:
{
"mycontainer"
},
"follow"
:
{
"true"
},
"previous"
:
{
"true"
},
"sinceSeconds"
:
{
"1"
},
"sinceTime"
:
{
"2000-01-01T12:34:56Z"
},
"timestamps"
:
{
"true"
},
"tailLines"
:
{
"2"
},
"limitBytes"
:
{
"3"
},
}
codec
:=
runtime
.
NewParameterCodec
(
api
.
Scheme
)
// unversioned -> query params
{
actualParameters
,
err
:=
codec
.
EncodeParameters
(
unversionedLogOptions
,
versioned
.
SchemeGroupVersion
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
reflect
.
DeepEqual
(
actualParameters
,
expectedParameters
)
{
t
.
Fatalf
(
"Expected
\n
%#v
\n
got
\n
%#v"
,
expectedParameters
,
actualParameters
)
}
}
// versioned -> query params
{
actualParameters
,
err
:=
codec
.
EncodeParameters
(
versionedLogOptions
,
versioned
.
SchemeGroupVersion
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
reflect
.
DeepEqual
(
actualParameters
,
expectedParameters
)
{
t
.
Fatalf
(
"Expected
\n
%#v
\n
got
\n
%#v"
,
expectedParameters
,
actualParameters
)
}
}
// query params -> versioned
{
convertedLogOptions
:=
&
versioned
.
PodLogOptions
{}
err
:=
codec
.
DecodeParameters
(
expectedParameters
,
versioned
.
SchemeGroupVersion
,
convertedLogOptions
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
reflect
.
DeepEqual
(
convertedLogOptions
,
versionedLogOptions
)
{
t
.
Fatalf
(
"Unexpected deserialization:
\n
%s"
,
util
.
ObjectGoPrintSideBySide
(
versionedLogOptions
,
convertedLogOptions
))
}
}
// query params -> unversioned
{
convertedLogOptions
:=
&
api
.
PodLogOptions
{}
err
:=
codec
.
DecodeParameters
(
expectedParameters
,
versioned
.
SchemeGroupVersion
,
convertedLogOptions
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
reflect
.
DeepEqual
(
convertedLogOptions
,
unversionedLogOptions
)
{
t
.
Fatalf
(
"Unexpected deserialization:
\n
%s"
,
util
.
ObjectGoPrintSideBySide
(
unversionedLogOptions
,
convertedLogOptions
))
}
}
}
// TestPodSpecConversion tests that ServiceAccount is an alias for
// TestPodSpecConversion tests that ServiceAccount is an alias for
// ServiceAccountName.
// ServiceAccountName.
func
TestPodSpecConversion
(
t
*
testing
.
T
)
{
func
TestPodSpecConversion
(
t
*
testing
.
T
)
{
...
...
pkg/conversion/queryparams/convert.go
View file @
ea59b4c7
...
@@ -23,6 +23,16 @@ import (
...
@@ -23,6 +23,16 @@ import (
"strings"
"strings"
)
)
// Marshaler converts an object to a query parameter string representation
type
Marshaler
interface
{
MarshalQueryParameter
()
(
string
,
error
)
}
// Unmarshaler converts a string representation to an object
type
Unmarshaler
interface
{
UnmarshalQueryParameter
(
string
)
error
}
func
jsonTag
(
field
reflect
.
StructField
)
(
string
,
bool
)
{
func
jsonTag
(
field
reflect
.
StructField
)
(
string
,
bool
)
{
structTag
:=
field
.
Tag
.
Get
(
"json"
)
structTag
:=
field
.
Tag
.
Get
(
"json"
)
if
len
(
structTag
)
==
0
{
if
len
(
structTag
)
==
0
{
...
@@ -72,6 +82,31 @@ func zeroValue(value reflect.Value) bool {
...
@@ -72,6 +82,31 @@ func zeroValue(value reflect.Value) bool {
return
reflect
.
DeepEqual
(
reflect
.
Zero
(
value
.
Type
())
.
Interface
(),
value
.
Interface
())
return
reflect
.
DeepEqual
(
reflect
.
Zero
(
value
.
Type
())
.
Interface
(),
value
.
Interface
())
}
}
func
customMarshalValue
(
value
reflect
.
Value
)
(
reflect
.
Value
,
bool
)
{
// Return unless we implement a custom query marshaler
if
!
value
.
CanInterface
()
{
return
reflect
.
Value
{},
false
}
marshaler
,
ok
:=
value
.
Interface
()
.
(
Marshaler
)
if
!
ok
{
return
reflect
.
Value
{},
false
}
// Don't invoke functions on nil pointers
// If the type implements MarshalQueryParameter, AND the tag is not omitempty, AND the value is a nil pointer, "" seems like a reasonable response
if
isPointerKind
(
value
.
Kind
())
&&
zeroValue
(
value
)
{
return
reflect
.
ValueOf
(
""
),
true
}
// Get the custom marshalled value
v
,
err
:=
marshaler
.
MarshalQueryParameter
()
if
err
!=
nil
{
return
reflect
.
Value
{},
false
}
return
reflect
.
ValueOf
(
v
),
true
}
func
addParam
(
values
url
.
Values
,
tag
string
,
omitempty
bool
,
value
reflect
.
Value
)
{
func
addParam
(
values
url
.
Values
,
tag
string
,
omitempty
bool
,
value
reflect
.
Value
)
{
if
omitempty
&&
zeroValue
(
value
)
{
if
omitempty
&&
zeroValue
(
value
)
{
return
return
...
@@ -128,7 +163,8 @@ func convertStruct(result url.Values, st reflect.Type, sv reflect.Value) {
...
@@ -128,7 +163,8 @@ func convertStruct(result url.Values, st reflect.Type, sv reflect.Value) {
kind
:=
ft
.
Kind
()
kind
:=
ft
.
Kind
()
if
isPointerKind
(
kind
)
{
if
isPointerKind
(
kind
)
{
kind
=
ft
.
Elem
()
.
Kind
()
ft
=
ft
.
Elem
()
kind
=
ft
.
Kind
()
if
!
field
.
IsNil
()
{
if
!
field
.
IsNil
()
{
field
=
reflect
.
Indirect
(
field
)
field
=
reflect
.
Indirect
(
field
)
}
}
...
@@ -142,7 +178,11 @@ func convertStruct(result url.Values, st reflect.Type, sv reflect.Value) {
...
@@ -142,7 +178,11 @@ func convertStruct(result url.Values, st reflect.Type, sv reflect.Value) {
addListOfParams
(
result
,
tag
,
omitempty
,
field
)
addListOfParams
(
result
,
tag
,
omitempty
,
field
)
}
}
case
isStructKind
(
kind
)
&&
!
(
zeroValue
(
field
)
&&
omitempty
)
:
case
isStructKind
(
kind
)
&&
!
(
zeroValue
(
field
)
&&
omitempty
)
:
if
marshalValue
,
ok
:=
customMarshalValue
(
field
);
ok
{
addParam
(
result
,
tag
,
omitempty
,
marshalValue
)
}
else
{
convertStruct
(
result
,
ft
,
field
)
convertStruct
(
result
,
ft
,
field
)
}
}
}
}
}
}
}
pkg/conversion/queryparams/convert_test.go
View file @
ea59b4c7
...
@@ -20,6 +20,7 @@ import (
...
@@ -20,6 +20,7 @@ import (
"net/url"
"net/url"
"reflect"
"reflect"
"testing"
"testing"
"time"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/conversion/queryparams"
"k8s.io/kubernetes/pkg/conversion/queryparams"
...
@@ -61,6 +62,19 @@ type baz struct {
...
@@ -61,6 +62,19 @@ type baz struct {
func
(
obj
*
baz
)
GetObjectKind
()
unversioned
.
ObjectKind
{
return
unversioned
.
EmptyObjectKind
}
func
(
obj
*
baz
)
GetObjectKind
()
unversioned
.
ObjectKind
{
return
unversioned
.
EmptyObjectKind
}
// childStructs tests some of the types we serialize to query params for log API calls
// notably, the nested time struct
type
childStructs
struct
{
Container
string
`json:"container,omitempty"`
Follow
bool
`json:"follow,omitempty"`
Previous
bool
`json:"previous,omitempty"`
SinceSeconds
*
int64
`json:"sinceSeconds,omitempty"`
SinceTime
*
unversioned
.
Time
`json:"sinceTime,omitempty"`
EmptyTime
*
unversioned
.
Time
`json:"emptyTime"`
}
func
(
obj
*
childStructs
)
GetObjectKind
()
unversioned
.
ObjectKind
{
return
unversioned
.
EmptyObjectKind
}
func
validateResult
(
t
*
testing
.
T
,
input
interface
{},
actual
,
expected
url
.
Values
)
{
func
validateResult
(
t
*
testing
.
T
,
input
interface
{},
actual
,
expected
url
.
Values
)
{
local
:=
url
.
Values
{}
local
:=
url
.
Values
{}
for
k
,
v
:=
range
expected
{
for
k
,
v
:=
range
expected
{
...
@@ -73,7 +87,6 @@ func validateResult(t *testing.T, input interface{}, actual, expected url.Values
...
@@ -73,7 +87,6 @@ func validateResult(t *testing.T, input interface{}, actual, expected url.Values
}
else
{
}
else
{
t
.
Errorf
(
"%#v: values don't match: actual: %#v, expected: %#v"
,
input
,
v
,
ev
)
t
.
Errorf
(
"%#v: values don't match: actual: %#v, expected: %#v"
,
input
,
v
,
ev
)
}
}
break
}
}
delete
(
local
,
k
)
delete
(
local
,
k
)
}
}
...
@@ -83,6 +96,9 @@ func validateResult(t *testing.T, input interface{}, actual, expected url.Values
...
@@ -83,6 +96,9 @@ func validateResult(t *testing.T, input interface{}, actual, expected url.Values
}
}
func
TestConvert
(
t
*
testing
.
T
)
{
func
TestConvert
(
t
*
testing
.
T
)
{
sinceSeconds
:=
int64
(
123
)
sinceTime
:=
unversioned
.
Date
(
2000
,
1
,
1
,
12
,
34
,
56
,
0
,
time
.
UTC
)
tests
:=
[]
struct
{
tests
:=
[]
struct
{
input
interface
{}
input
interface
{}
expected
url
.
Values
expected
url
.
Values
...
@@ -158,6 +174,27 @@ func TestConvert(t *testing.T) {
...
@@ -158,6 +174,27 @@ func TestConvert(t *testing.T) {
},
},
expected
:
url
.
Values
{
"ptr"
:
{
"5"
}},
expected
:
url
.
Values
{
"ptr"
:
{
"5"
}},
},
},
{
input
:
&
childStructs
{
Container
:
"mycontainer"
,
Follow
:
true
,
Previous
:
true
,
SinceSeconds
:
&
sinceSeconds
,
SinceTime
:
&
sinceTime
,
// test a custom marshaller
EmptyTime
:
nil
,
// test a nil custom marshaller without omitempty
},
expected
:
url
.
Values
{
"container"
:
{
"mycontainer"
},
"follow"
:
{
"true"
},
"previous"
:
{
"true"
},
"sinceSeconds"
:
{
"123"
},
"sinceTime"
:
{
"2000-01-01T12:34:56Z"
},
"emptyTime"
:
{
""
}},
},
{
input
:
&
childStructs
{
Container
:
"mycontainer"
,
Follow
:
true
,
Previous
:
true
,
SinceSeconds
:
&
sinceSeconds
,
SinceTime
:
nil
,
// test a nil custom marshaller with omitempty
},
expected
:
url
.
Values
{
"container"
:
{
"mycontainer"
},
"follow"
:
{
"true"
},
"previous"
:
{
"true"
},
"sinceSeconds"
:
{
"123"
},
"emptyTime"
:
{
""
}},
},
}
}
for
_
,
test
:=
range
tests
{
for
_
,
test
:=
range
tests
{
...
...
test/e2e_node/kubelet_test.go
View file @
ea59b4c7
...
@@ -26,6 +26,7 @@ import (
...
@@ -26,6 +26,7 @@ import (
"time"
"time"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
client
"k8s.io/kubernetes/pkg/client/unversioned"
client
"k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/stats"
"k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/stats"
...
@@ -69,7 +70,8 @@ var _ = Describe("Kubelet", func() {
...
@@ -69,7 +70,8 @@ var _ = Describe("Kubelet", func() {
It
(
"it should print the output to logs"
,
func
()
{
It
(
"it should print the output to logs"
,
func
()
{
Eventually
(
func
()
string
{
Eventually
(
func
()
string
{
rc
,
err
:=
cl
.
Pods
(
api
.
NamespaceDefault
)
.
GetLogs
(
"busybox"
,
&
api
.
PodLogOptions
{})
.
Stream
()
sinceTime
:=
unversioned
.
NewTime
(
time
.
Now
()
.
Add
(
time
.
Duration
(
-
1
*
time
.
Hour
)))
rc
,
err
:=
cl
.
Pods
(
api
.
NamespaceDefault
)
.
GetLogs
(
"busybox"
,
&
api
.
PodLogOptions
{
SinceTime
:
&
sinceTime
})
.
Stream
()
if
err
!=
nil
{
if
err
!=
nil
{
return
""
return
""
}
}
...
...
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