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
75617e87
Commit
75617e87
authored
May 13, 2015
by
Tim Hockin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Better kubelet logging for probes
Log when we actually run probes and event when they fail. Print the output of a probe, too.
parent
d85dc7b2
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
161 additions
and
113 deletions
+161
-113
integration.go
cmd/integration/integration.go
+2
-2
kubelet.go
pkg/client/kubelet.go
+5
-5
kubelet_test.go
pkg/client/kubelet_test.go
+3
-3
manager_test.go
pkg/kubelet/dockertools/manager_test.go
+12
-11
prober.go
pkg/kubelet/prober/prober.go
+67
-42
exec.go
pkg/probe/exec/exec.go
+7
-7
exec_test.go
pkg/probe/exec/exec_test.go
+22
-20
http.go
pkg/probe/http/http.go
+14
-8
http_test.go
pkg/probe/http/http_test.go
+14
-6
tcp.go
pkg/probe/tcp/tcp.go
+7
-6
tcp_test.go
pkg/probe/tcp/tcp_test.go
+8
-3
No files found.
cmd/integration/integration.go
View file @
75617e87
...
@@ -81,8 +81,8 @@ func (fakeKubeletClient) GetConnectionInfo(host string) (string, uint, http.Roun
...
@@ -81,8 +81,8 @@ func (fakeKubeletClient) GetConnectionInfo(host string) (string, uint, http.Roun
return
""
,
0
,
nil
,
errors
.
New
(
"Not Implemented"
)
return
""
,
0
,
nil
,
errors
.
New
(
"Not Implemented"
)
}
}
func
(
fakeKubeletClient
)
HealthCheck
(
host
string
)
(
probe
.
Result
,
error
)
{
func
(
fakeKubeletClient
)
HealthCheck
(
host
string
)
(
probe
.
Result
,
string
,
error
)
{
return
probe
.
Success
,
nil
return
probe
.
Success
,
""
,
nil
}
}
type
delegateHandler
struct
{
type
delegateHandler
struct
{
...
...
pkg/client/kubelet.go
View file @
75617e87
...
@@ -35,11 +35,11 @@ type KubeletClient interface {
...
@@ -35,11 +35,11 @@ type KubeletClient interface {
// KubeletHealthchecker is an interface for healthchecking kubelets
// KubeletHealthchecker is an interface for healthchecking kubelets
type
KubeletHealthChecker
interface
{
type
KubeletHealthChecker
interface
{
HealthCheck
(
host
string
)
(
probe
.
Result
,
error
)
HealthCheck
(
host
string
)
(
result
probe
.
Result
,
output
string
,
err
error
)
}
}
type
ConnectionInfoGetter
interface
{
type
ConnectionInfoGetter
interface
{
GetConnectionInfo
(
host
string
)
(
scheme
string
,
port
uint
,
transport
http
.
RoundTripper
,
err
or
error
)
GetConnectionInfo
(
host
string
)
(
scheme
string
,
port
uint
,
transport
http
.
RoundTripper
,
err
error
)
}
}
// HTTPKubeletClient is the default implementation of KubeletHealthchecker, accesses the kubelet over HTTP.
// HTTPKubeletClient is the default implementation of KubeletHealthchecker, accesses the kubelet over HTTP.
...
@@ -103,7 +103,7 @@ func (c *HTTPKubeletClient) url(host, path, query string) string {
...
@@ -103,7 +103,7 @@ func (c *HTTPKubeletClient) url(host, path, query string) string {
})
.
String
()
})
.
String
()
}
}
func
(
c
*
HTTPKubeletClient
)
HealthCheck
(
host
string
)
(
probe
.
Result
,
error
)
{
func
(
c
*
HTTPKubeletClient
)
HealthCheck
(
host
string
)
(
probe
.
Result
,
string
,
error
)
{
return
httprobe
.
DoHTTPProbe
(
c
.
url
(
host
,
"/healthz"
,
""
),
c
.
Client
)
return
httprobe
.
DoHTTPProbe
(
c
.
url
(
host
,
"/healthz"
,
""
),
c
.
Client
)
}
}
...
@@ -112,8 +112,8 @@ func (c *HTTPKubeletClient) HealthCheck(host string) (probe.Result, error) {
...
@@ -112,8 +112,8 @@ func (c *HTTPKubeletClient) HealthCheck(host string) (probe.Result, error) {
// no kubelets.
// no kubelets.
type
FakeKubeletClient
struct
{}
type
FakeKubeletClient
struct
{}
func
(
c
FakeKubeletClient
)
HealthCheck
(
host
string
)
(
probe
.
Result
,
error
)
{
func
(
c
FakeKubeletClient
)
HealthCheck
(
host
string
)
(
probe
.
Result
,
string
,
error
)
{
return
probe
.
Unknown
,
errors
.
New
(
"Not Implemented"
)
return
probe
.
Unknown
,
""
,
errors
.
New
(
"Not Implemented"
)
}
}
func
(
c
FakeKubeletClient
)
GetConnectionInfo
(
host
string
)
(
string
,
uint
,
http
.
RoundTripper
,
error
)
{
func
(
c
FakeKubeletClient
)
GetConnectionInfo
(
host
string
)
(
string
,
uint
,
http
.
RoundTripper
,
error
)
{
...
...
pkg/client/kubelet_test.go
View file @
75617e87
...
@@ -59,7 +59,7 @@ func TestHTTPKubeletClient(t *testing.T) {
...
@@ -59,7 +59,7 @@ func TestHTTPKubeletClient(t *testing.T) {
Client
:
http
.
DefaultClient
,
Client
:
http
.
DefaultClient
,
Port
:
uint
(
port
),
Port
:
uint
(
port
),
}
}
gotObj
,
err
:=
c
.
HealthCheck
(
parts
[
0
])
gotObj
,
_
,
err
:=
c
.
HealthCheck
(
parts
[
0
])
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error: %v"
,
err
)
t
.
Errorf
(
"unexpected error: %v"
,
err
)
}
}
...
@@ -93,7 +93,7 @@ func TestHTTPKubeletClientError(t *testing.T) {
...
@@ -93,7 +93,7 @@ func TestHTTPKubeletClientError(t *testing.T) {
Client
:
http
.
DefaultClient
,
Client
:
http
.
DefaultClient
,
Port
:
uint
(
port
),
Port
:
uint
(
port
),
}
}
gotObj
,
err
:=
c
.
HealthCheck
(
parts
[
0
])
gotObj
,
_
,
err
:=
c
.
HealthCheck
(
parts
[
0
])
if
gotObj
!=
expectObj
{
if
gotObj
!=
expectObj
{
t
.
Errorf
(
"expected: %#v, got %#v"
,
expectObj
,
gotObj
)
t
.
Errorf
(
"expected: %#v, got %#v"
,
expectObj
,
gotObj
)
}
}
...
@@ -114,7 +114,7 @@ func TestNewKubeletClient(t *testing.T) {
...
@@ -114,7 +114,7 @@ func TestNewKubeletClient(t *testing.T) {
}
}
host
:=
"127.0.0.1"
host
:=
"127.0.0.1"
healthStatus
,
err
:=
client
.
HealthCheck
(
host
)
healthStatus
,
_
,
err
:=
client
.
HealthCheck
(
host
)
if
healthStatus
!=
probe
.
Failure
{
if
healthStatus
!=
probe
.
Failure
{
t
.
Errorf
(
"Expected %v and got %v."
,
probe
.
Failure
,
healthStatus
)
t
.
Errorf
(
"Expected %v and got %v."
,
probe
.
Failure
,
healthStatus
)
}
}
...
...
pkg/kubelet/dockertools/manager_test.go
View file @
75617e87
...
@@ -414,11 +414,12 @@ func TestKillContainerInPodWithError(t *testing.T) {
...
@@ -414,11 +414,12 @@ func TestKillContainerInPodWithError(t *testing.T) {
type
fakeExecProber
struct
{
type
fakeExecProber
struct
{
result
probe
.
Result
result
probe
.
Result
output
string
err
error
err
error
}
}
func
(
p
fakeExecProber
)
Probe
(
_
uexec
.
Cmd
)
(
probe
.
Result
,
error
)
{
func
(
p
fakeExecProber
)
Probe
(
_
uexec
.
Cmd
)
(
probe
.
Result
,
string
,
error
)
{
return
p
.
result
,
p
.
err
return
p
.
result
,
p
.
output
,
p
.
err
}
}
func
replaceProber
(
dm
*
DockerManager
,
result
probe
.
Result
,
err
error
)
{
func
replaceProber
(
dm
*
DockerManager
,
result
probe
.
Result
,
err
error
)
{
...
@@ -530,14 +531,14 @@ func TestProbeContainer(t *testing.T) {
...
@@ -530,14 +531,14 @@ func TestProbeContainer(t *testing.T) {
testContainer
:
api
.
Container
{
testContainer
:
api
.
Container
{
ReadinessProbe
:
&
api
.
Probe
{
InitialDelaySeconds
:
100
},
ReadinessProbe
:
&
api
.
Probe
{
InitialDelaySeconds
:
100
},
},
},
expectedResult
:
probe
.
Success
,
expectedResult
:
probe
.
Failure
,
expectedReadiness
:
false
,
expectedReadiness
:
false
,
},
},
{
{
testContainer
:
api
.
Container
{
testContainer
:
api
.
Container
{
ReadinessProbe
:
&
api
.
Probe
{
InitialDelaySeconds
:
-
100
},
ReadinessProbe
:
&
api
.
Probe
{
InitialDelaySeconds
:
-
100
},
},
},
expectedResult
:
probe
.
Success
,
expectedResult
:
probe
.
Unknown
,
expectedReadiness
:
false
,
expectedReadiness
:
false
,
},
},
{
{
...
@@ -595,7 +596,7 @@ func TestProbeContainer(t *testing.T) {
...
@@ -595,7 +596,7 @@ func TestProbeContainer(t *testing.T) {
LivenessProbe
:
&
api
.
Probe
{
InitialDelaySeconds
:
100
},
LivenessProbe
:
&
api
.
Probe
{
InitialDelaySeconds
:
100
},
ReadinessProbe
:
&
api
.
Probe
{
InitialDelaySeconds
:
100
},
ReadinessProbe
:
&
api
.
Probe
{
InitialDelaySeconds
:
100
},
},
},
expectedResult
:
probe
.
Success
,
expectedResult
:
probe
.
Failure
,
expectedReadiness
:
false
,
expectedReadiness
:
false
,
},
},
{
{
...
@@ -603,7 +604,7 @@ func TestProbeContainer(t *testing.T) {
...
@@ -603,7 +604,7 @@ func TestProbeContainer(t *testing.T) {
LivenessProbe
:
&
api
.
Probe
{
InitialDelaySeconds
:
100
},
LivenessProbe
:
&
api
.
Probe
{
InitialDelaySeconds
:
100
},
ReadinessProbe
:
&
api
.
Probe
{
InitialDelaySeconds
:
-
100
},
ReadinessProbe
:
&
api
.
Probe
{
InitialDelaySeconds
:
-
100
},
},
},
expectedResult
:
probe
.
Success
,
expectedResult
:
probe
.
Unknown
,
expectedReadiness
:
false
,
expectedReadiness
:
false
,
},
},
{
{
...
@@ -668,7 +669,7 @@ func TestProbeContainer(t *testing.T) {
...
@@ -668,7 +669,7 @@ func TestProbeContainer(t *testing.T) {
},
},
}
}
for
_
,
test
:=
range
tests
{
for
i
,
test
:=
range
tests
{
if
test
.
expectError
{
if
test
.
expectError
{
replaceProber
(
manager
,
test
.
expectedResult
,
errors
.
New
(
"error"
))
replaceProber
(
manager
,
test
.
expectedResult
,
errors
.
New
(
"error"
))
}
else
{
}
else
{
...
@@ -676,16 +677,16 @@ func TestProbeContainer(t *testing.T) {
...
@@ -676,16 +677,16 @@ func TestProbeContainer(t *testing.T) {
}
}
result
,
err
:=
manager
.
prober
.
Probe
(
&
api
.
Pod
{},
api
.
PodStatus
{},
test
.
testContainer
,
dc
.
ID
,
dc
.
Created
)
result
,
err
:=
manager
.
prober
.
Probe
(
&
api
.
Pod
{},
api
.
PodStatus
{},
test
.
testContainer
,
dc
.
ID
,
dc
.
Created
)
if
test
.
expectError
&&
err
==
nil
{
if
test
.
expectError
&&
err
==
nil
{
t
.
Error
(
"
Expected error but did no error was returned."
)
t
.
Error
(
"
[%d] Expected error but did no error was returned."
,
i
)
}
}
if
!
test
.
expectError
&&
err
!=
nil
{
if
!
test
.
expectError
&&
err
!=
nil
{
t
.
Errorf
(
"
Expected error but got: %v"
,
err
)
t
.
Errorf
(
"
[%d] Expected error but got: %v"
,
i
,
err
)
}
}
if
test
.
expectedResult
!=
result
{
if
test
.
expectedResult
!=
result
{
t
.
Errorf
(
"
Expected result was %v but probeContainer() returned %v"
,
test
.
expectedResult
,
result
)
t
.
Errorf
(
"
[%d] Expected result was %v but probeContainer() returned %v"
,
i
,
test
.
expectedResult
,
result
)
}
}
if
test
.
expectedReadiness
!=
manager
.
readinessManager
.
GetReadiness
(
dc
.
ID
)
{
if
test
.
expectedReadiness
!=
manager
.
readinessManager
.
GetReadiness
(
dc
.
ID
)
{
t
.
Errorf
(
"
Expected readiness was %v but probeContainer() set %v"
,
test
.
expectedReadiness
,
manager
.
readinessManager
.
GetReadiness
(
dc
.
ID
))
t
.
Errorf
(
"
[%d] Expected readiness was %v but probeContainer() set %v"
,
i
,
test
.
expectedReadiness
,
manager
.
readinessManager
.
GetReadiness
(
dc
.
ID
))
}
}
}
}
}
}
...
...
pkg/kubelet/prober/prober.go
View file @
75617e87
...
@@ -92,84 +92,109 @@ func NewTestProber(
...
@@ -92,84 +92,109 @@ func NewTestProber(
// If the container's liveness probe is unsuccessful, set readiness to false.
// If the container's liveness probe is unsuccessful, set readiness to false.
// If liveness is successful, do a readiness check and set readiness accordingly.
// If liveness is successful, do a readiness check and set readiness accordingly.
func
(
pb
*
prober
)
Probe
(
pod
*
api
.
Pod
,
status
api
.
PodStatus
,
container
api
.
Container
,
containerID
string
,
createdAt
int64
)
(
probe
.
Result
,
error
)
{
func
(
pb
*
prober
)
Probe
(
pod
*
api
.
Pod
,
status
api
.
PodStatus
,
container
api
.
Container
,
containerID
string
,
createdAt
int64
)
(
probe
.
Result
,
error
)
{
// Build a name string for logs.
ctrName
:=
fmt
.
Sprintf
(
"%s:%s"
,
kubecontainer
.
GetPodFullName
(
pod
),
container
.
Name
)
// Probe liveness.
// Probe liveness.
live
,
err
:=
pb
.
probeLiveness
(
pod
,
status
,
container
,
containerID
,
createdAt
)
if
container
.
LivenessProbe
!=
nil
{
if
err
!=
nil
{
live
,
output
,
err
:=
pb
.
probeLiveness
(
pod
,
status
,
container
,
containerID
,
createdAt
)
glog
.
V
(
1
)
.
Infof
(
"Liveness probe errored: %v"
,
err
)
if
err
!=
nil
||
live
!=
probe
.
Success
{
pb
.
readinessManager
.
SetReadiness
(
containerID
,
false
)
// Liveness failed in one way or another.
return
probe
.
Unknown
,
err
pb
.
readinessManager
.
SetReadiness
(
containerID
,
false
)
}
ref
,
ok
:=
pb
.
refManager
.
GetRef
(
containerID
)
if
live
!=
probe
.
Success
{
if
!
ok
{
glog
.
V
(
1
)
.
Infof
(
"Liveness probe unsuccessful: %v"
,
live
)
glog
.
Warningf
(
"No ref for pod %q - '%v'"
,
containerID
,
container
.
Name
)
pb
.
readinessManager
.
SetReadiness
(
containerID
,
false
)
}
return
live
,
nil
if
err
!=
nil
{
glog
.
V
(
1
)
.
Infof
(
"Liveness probe for %q errored: %v"
,
ctrName
,
err
)
if
ok
{
pb
.
recorder
.
Eventf
(
ref
,
"unhealthy"
,
"Liveness probe errored: %v"
,
err
)
}
return
probe
.
Unknown
,
err
}
else
{
// live != probe.Success
glog
.
V
(
1
)
.
Infof
(
"Liveness probe for %q failed (%v): %s"
,
ctrName
,
live
,
output
)
if
ok
{
pb
.
recorder
.
Eventf
(
ref
,
"unhealthy"
,
"Liveness probe failed: %s"
,
output
)
}
return
live
,
nil
}
}
glog
.
V
(
3
)
.
Infof
(
"Liveness probe for %q succeeded"
,
ctrName
)
}
}
// Probe readiness.
// Probe readiness.
ready
,
err
:=
pb
.
probeReadiness
(
pod
,
status
,
container
,
containerID
,
createdAt
)
if
container
.
ReadinessProbe
!=
nil
{
if
err
==
nil
&&
ready
==
probe
.
Success
{
ready
,
output
,
err
:=
pb
.
probeReadiness
(
pod
,
status
,
container
,
containerID
,
createdAt
)
glog
.
V
(
3
)
.
Infof
(
"Readiness probe successful: %v"
,
ready
)
if
err
!=
nil
||
ready
!=
probe
.
Success
{
pb
.
readinessManager
.
SetReadiness
(
containerID
,
true
)
// Readiness failed in one way or another.
return
probe
.
Success
,
nil
pb
.
readinessManager
.
SetReadiness
(
containerID
,
false
)
}
ref
,
ok
:=
pb
.
refManager
.
GetRef
(
containerID
)
if
!
ok
{
glog
.
V
(
1
)
.
Infof
(
"Readiness probe failed/errored: %v, %v"
,
ready
,
err
)
glog
.
Warningf
(
"No ref for pod '%v' - '%v'"
,
containerID
,
container
.
Name
)
pb
.
readinessManager
.
SetReadiness
(
containerID
,
false
)
}
if
err
!=
nil
{
ref
,
ok
:=
pb
.
refManager
.
GetRef
(
containerID
)
glog
.
V
(
1
)
.
Infof
(
"readiness probe for %q errored: %v"
,
ctrName
,
err
)
if
!
ok
{
if
ok
{
glog
.
Warningf
(
"No ref for pod '%v' - '%v'"
,
containerID
,
container
.
Name
)
pb
.
recorder
.
Eventf
(
ref
,
"unhealthy"
,
"Readiness probe errored: %v"
,
err
)
return
probe
.
Success
,
err
}
}
return
probe
.
Unknown
,
err
}
else
{
// ready != probe.Success
if
ready
!=
probe
.
Success
{
glog
.
V
(
1
)
.
Infof
(
"Readiness probe for %q failed (%v): %s"
,
ctrName
,
ready
,
output
)
pb
.
recorder
.
Eventf
(
ref
,
"unhealthy"
,
"Readiness Probe Failed %v - %v"
,
containerID
,
container
.
Name
)
if
ok
{
pb
.
recorder
.
Eventf
(
ref
,
"unhealthy"
,
"Readiness probe failed: %s"
,
output
)
}
return
ready
,
nil
}
}
glog
.
V
(
1
)
.
Infof
(
"Readiness probe for %q succeeded"
,
ctrName
)
}
}
pb
.
readinessManager
.
SetReadiness
(
containerID
,
true
)
return
probe
.
Success
,
nil
return
probe
.
Success
,
nil
}
}
// probeLiveness probes the liveness of a container.
// probeLiveness probes the liveness of a container.
// If the initalDelay since container creation on liveness probe has not passed the probe will return probe.Success.
// If the initalDelay since container creation on liveness probe has not passed the probe will return probe.Success.
func
(
pb
*
prober
)
probeLiveness
(
pod
*
api
.
Pod
,
status
api
.
PodStatus
,
container
api
.
Container
,
containerID
string
,
createdAt
int64
)
(
probe
.
Result
,
error
)
{
func
(
pb
*
prober
)
probeLiveness
(
pod
*
api
.
Pod
,
status
api
.
PodStatus
,
container
api
.
Container
,
containerID
string
,
createdAt
int64
)
(
probe
.
Result
,
string
,
error
)
{
p
:=
container
.
LivenessProbe
p
:=
container
.
LivenessProbe
if
p
==
nil
{
if
p
==
nil
{
return
probe
.
Success
,
nil
return
probe
.
Success
,
""
,
nil
}
}
if
time
.
Now
()
.
Unix
()
-
createdAt
<
p
.
InitialDelaySeconds
{
if
time
.
Now
()
.
Unix
()
-
createdAt
<
p
.
InitialDelaySeconds
{
return
probe
.
Success
,
nil
return
probe
.
Success
,
""
,
nil
}
}
return
pb
.
runProbeWithRetries
(
p
,
pod
,
status
,
container
,
containerID
,
maxProbeRetries
)
return
pb
.
runProbeWithRetries
(
p
,
pod
,
status
,
container
,
containerID
,
maxProbeRetries
)
}
}
// probeReadiness probes the readiness of a container.
// probeReadiness probes the readiness of a container.
// If the initial delay on the readiness probe has not passed the probe will return probe.Failure.
// If the initial delay on the readiness probe has not passed the probe will return probe.Failure.
func
(
pb
*
prober
)
probeReadiness
(
pod
*
api
.
Pod
,
status
api
.
PodStatus
,
container
api
.
Container
,
containerID
string
,
createdAt
int64
)
(
probe
.
Result
,
error
)
{
func
(
pb
*
prober
)
probeReadiness
(
pod
*
api
.
Pod
,
status
api
.
PodStatus
,
container
api
.
Container
,
containerID
string
,
createdAt
int64
)
(
probe
.
Result
,
string
,
error
)
{
p
:=
container
.
ReadinessProbe
p
:=
container
.
ReadinessProbe
if
p
==
nil
{
if
p
==
nil
{
return
probe
.
Success
,
nil
return
probe
.
Success
,
""
,
nil
}
}
if
time
.
Now
()
.
Unix
()
-
createdAt
<
p
.
InitialDelaySeconds
{
if
time
.
Now
()
.
Unix
()
-
createdAt
<
p
.
InitialDelaySeconds
{
return
probe
.
Failure
,
nil
return
probe
.
Failure
,
""
,
nil
}
}
return
pb
.
runProbeWithRetries
(
p
,
pod
,
status
,
container
,
containerID
,
maxProbeRetries
)
return
pb
.
runProbeWithRetries
(
p
,
pod
,
status
,
container
,
containerID
,
maxProbeRetries
)
}
}
// runProbeWithRetries tries to probe the container in a finite loop, it returns the last result
// runProbeWithRetries tries to probe the container in a finite loop, it returns the last result
// if it never succeeds.
// if it never succeeds.
func
(
pb
*
prober
)
runProbeWithRetries
(
p
*
api
.
Probe
,
pod
*
api
.
Pod
,
status
api
.
PodStatus
,
container
api
.
Container
,
containerID
string
,
retries
int
)
(
probe
.
Result
,
error
)
{
func
(
pb
*
prober
)
runProbeWithRetries
(
p
*
api
.
Probe
,
pod
*
api
.
Pod
,
status
api
.
PodStatus
,
container
api
.
Container
,
containerID
string
,
retries
int
)
(
probe
.
Result
,
string
,
error
)
{
var
err
error
var
err
error
var
result
probe
.
Result
var
result
probe
.
Result
var
output
string
for
i
:=
0
;
i
<
retries
;
i
++
{
for
i
:=
0
;
i
<
retries
;
i
++
{
result
,
err
=
pb
.
runProbe
(
p
,
pod
,
status
,
container
,
containerID
)
result
,
output
,
err
=
pb
.
runProbe
(
p
,
pod
,
status
,
container
,
containerID
)
if
result
==
probe
.
Success
{
if
result
==
probe
.
Success
{
return
probe
.
Success
,
nil
return
probe
.
Success
,
output
,
nil
}
}
}
}
return
result
,
err
return
result
,
output
,
err
}
}
func
(
pb
*
prober
)
runProbe
(
p
*
api
.
Probe
,
pod
*
api
.
Pod
,
status
api
.
PodStatus
,
container
api
.
Container
,
containerID
string
)
(
probe
.
Result
,
error
)
{
func
(
pb
*
prober
)
runProbe
(
p
*
api
.
Probe
,
pod
*
api
.
Pod
,
status
api
.
PodStatus
,
container
api
.
Container
,
containerID
string
)
(
probe
.
Result
,
string
,
error
)
{
timeout
:=
time
.
Duration
(
p
.
TimeoutSeconds
)
*
time
.
Second
timeout
:=
time
.
Duration
(
p
.
TimeoutSeconds
)
*
time
.
Second
if
p
.
Exec
!=
nil
{
if
p
.
Exec
!=
nil
{
glog
.
V
(
4
)
.
Infof
(
"Exec-Probe Pod: %v, Container: %v, Command: %v"
,
pod
,
container
,
p
.
Exec
.
Command
)
glog
.
V
(
4
)
.
Infof
(
"Exec-Probe Pod: %v, Container: %v, Command: %v"
,
pod
,
container
,
p
.
Exec
.
Command
)
...
@@ -178,7 +203,7 @@ func (pb *prober) runProbe(p *api.Probe, pod *api.Pod, status api.PodStatus, con
...
@@ -178,7 +203,7 @@ func (pb *prober) runProbe(p *api.Probe, pod *api.Pod, status api.PodStatus, con
if
p
.
HTTPGet
!=
nil
{
if
p
.
HTTPGet
!=
nil
{
port
,
err
:=
extractPort
(
p
.
HTTPGet
.
Port
,
container
)
port
,
err
:=
extractPort
(
p
.
HTTPGet
.
Port
,
container
)
if
err
!=
nil
{
if
err
!=
nil
{
return
probe
.
Unknown
,
err
return
probe
.
Unknown
,
""
,
err
}
}
host
,
port
,
path
:=
extractGetParams
(
p
.
HTTPGet
,
status
,
port
)
host
,
port
,
path
:=
extractGetParams
(
p
.
HTTPGet
,
status
,
port
)
glog
.
V
(
4
)
.
Infof
(
"HTTP-Probe Host: %v, Port: %v, Path: %v"
,
host
,
port
,
path
)
glog
.
V
(
4
)
.
Infof
(
"HTTP-Probe Host: %v, Port: %v, Path: %v"
,
host
,
port
,
path
)
...
@@ -187,13 +212,13 @@ func (pb *prober) runProbe(p *api.Probe, pod *api.Pod, status api.PodStatus, con
...
@@ -187,13 +212,13 @@ func (pb *prober) runProbe(p *api.Probe, pod *api.Pod, status api.PodStatus, con
if
p
.
TCPSocket
!=
nil
{
if
p
.
TCPSocket
!=
nil
{
port
,
err
:=
extractPort
(
p
.
TCPSocket
.
Port
,
container
)
port
,
err
:=
extractPort
(
p
.
TCPSocket
.
Port
,
container
)
if
err
!=
nil
{
if
err
!=
nil
{
return
probe
.
Unknown
,
err
return
probe
.
Unknown
,
""
,
err
}
}
glog
.
V
(
4
)
.
Infof
(
"TCP-Probe PodIP: %v, Port: %v, Timeout: %v"
,
status
.
PodIP
,
port
,
timeout
)
glog
.
V
(
4
)
.
Infof
(
"TCP-Probe PodIP: %v, Port: %v, Timeout: %v"
,
status
.
PodIP
,
port
,
timeout
)
return
pb
.
tcp
.
Probe
(
status
.
PodIP
,
port
,
timeout
)
return
pb
.
tcp
.
Probe
(
status
.
PodIP
,
port
,
timeout
)
}
}
glog
.
Warningf
(
"Failed to find probe builder for container: %v"
,
container
)
glog
.
Warningf
(
"Failed to find probe builder for container: %v"
,
container
)
return
probe
.
Unknown
,
nil
return
probe
.
Unknown
,
""
,
nil
}
}
func
extractGetParams
(
action
*
api
.
HTTPGetAction
,
status
api
.
PodStatus
,
port
int
)
(
string
,
int
,
string
)
{
func
extractGetParams
(
action
*
api
.
HTTPGetAction
,
status
api
.
PodStatus
,
port
int
)
(
string
,
int
,
string
)
{
...
...
pkg/probe/exec/exec.go
View file @
75617e87
...
@@ -28,24 +28,24 @@ func New() ExecProber {
...
@@ -28,24 +28,24 @@ func New() ExecProber {
}
}
type
ExecProber
interface
{
type
ExecProber
interface
{
Probe
(
e
exec
.
Cmd
)
(
probe
.
Result
,
error
)
Probe
(
e
exec
.
Cmd
)
(
probe
.
Result
,
string
,
error
)
}
}
type
execProber
struct
{}
type
execProber
struct
{}
func
(
pr
execProber
)
Probe
(
e
exec
.
Cmd
)
(
probe
.
Result
,
error
)
{
func
(
pr
execProber
)
Probe
(
e
exec
.
Cmd
)
(
probe
.
Result
,
string
,
error
)
{
data
,
err
:=
e
.
CombinedOutput
()
data
,
err
:=
e
.
CombinedOutput
()
glog
.
V
(
4
)
.
Infof
(
"
health check response: %s
"
,
string
(
data
))
glog
.
V
(
4
)
.
Infof
(
"
Exec probe response: %q
"
,
string
(
data
))
if
err
!=
nil
{
if
err
!=
nil
{
exit
,
ok
:=
err
.
(
exec
.
ExitError
)
exit
,
ok
:=
err
.
(
exec
.
ExitError
)
if
ok
{
if
ok
{
if
exit
.
ExitStatus
()
==
0
{
if
exit
.
ExitStatus
()
==
0
{
return
probe
.
Success
,
nil
return
probe
.
Success
,
string
(
data
),
nil
}
else
{
}
else
{
return
probe
.
Failure
,
nil
return
probe
.
Failure
,
string
(
data
),
nil
}
}
}
}
return
probe
.
Unknown
,
err
return
probe
.
Unknown
,
""
,
err
}
}
return
probe
.
Success
,
nil
return
probe
.
Success
,
string
(
data
),
nil
}
}
pkg/probe/exec/exec_test.go
View file @
75617e87
...
@@ -34,13 +34,6 @@ func (f *FakeCmd) CombinedOutput() ([]byte, error) {
...
@@ -34,13 +34,6 @@ func (f *FakeCmd) CombinedOutput() ([]byte, error) {
func
(
f
*
FakeCmd
)
SetDir
(
dir
string
)
{}
func
(
f
*
FakeCmd
)
SetDir
(
dir
string
)
{}
type
healthCheckTest
struct
{
expectedStatus
probe
.
Result
expectError
bool
output
[]
byte
err
error
}
type
fakeExitError
struct
{
type
fakeExitError
struct
{
exited
bool
exited
bool
statusCode
int
statusCode
int
...
@@ -64,30 +57,39 @@ func (f *fakeExitError) ExitStatus() int {
...
@@ -64,30 +57,39 @@ func (f *fakeExitError) ExitStatus() int {
func
TestExec
(
t
*
testing
.
T
)
{
func
TestExec
(
t
*
testing
.
T
)
{
prober
:=
New
()
prober
:=
New
()
fake
:=
FakeCmd
{}
tests
:=
[]
healthCheckTest
{
tests
:=
[]
struct
{
expectedStatus
probe
.
Result
expectError
bool
output
string
err
error
}{
// Ok
// Ok
{
probe
.
Success
,
false
,
[]
byte
(
"OK"
)
,
nil
},
{
probe
.
Success
,
false
,
"OK"
,
nil
},
// Ok
// Ok
{
probe
.
Success
,
false
,
[]
byte
(
"OK"
)
,
&
fakeExitError
{
true
,
0
}},
{
probe
.
Success
,
false
,
"OK"
,
&
fakeExitError
{
true
,
0
}},
// Run returns error
// Run returns error
{
probe
.
Unknown
,
true
,
[]
byte
(
"OK, NOT"
)
,
fmt
.
Errorf
(
"test error"
)},
{
probe
.
Unknown
,
true
,
""
,
fmt
.
Errorf
(
"test error"
)},
// Unhealthy
// Unhealthy
{
probe
.
Failure
,
false
,
[]
byte
(
"Fail"
)
,
&
fakeExitError
{
true
,
1
}},
{
probe
.
Failure
,
false
,
"Fail"
,
&
fakeExitError
{
true
,
1
}},
}
}
for
_
,
test
:=
range
tests
{
for
i
,
test
:=
range
tests
{
fake
.
out
=
test
.
output
fake
:=
FakeCmd
{
fake
.
err
=
test
.
err
out
:
[]
byte
(
test
.
output
),
status
,
err
:=
prober
.
Probe
(
&
fake
)
err
:
test
.
err
,
}
status
,
output
,
err
:=
prober
.
Probe
(
&
fake
)
if
status
!=
test
.
expectedStatus
{
if
status
!=
test
.
expectedStatus
{
t
.
Errorf
(
"
expected %v, got %v"
,
test
.
expectedStatus
,
status
)
t
.
Errorf
(
"
[%d] expected %v, got %v"
,
i
,
test
.
expectedStatus
,
status
)
}
}
if
err
!=
nil
&&
test
.
expectError
==
false
{
if
err
!=
nil
&&
test
.
expectError
==
false
{
t
.
Errorf
(
"
unexpected error: %v"
,
err
)
t
.
Errorf
(
"
[%d] unexpected error: %v"
,
i
,
err
)
}
}
if
err
==
nil
&&
test
.
expectError
==
true
{
if
err
==
nil
&&
test
.
expectError
==
true
{
t
.
Errorf
(
"unexpected non-error"
)
t
.
Errorf
(
"[%d] unexpected non-error"
,
i
)
}
if
test
.
output
!=
output
{
t
.
Errorf
(
"[%d] expected %s, got %s"
,
i
,
test
.
output
,
output
)
}
}
}
}
}
}
pkg/probe/http/http.go
View file @
75617e87
...
@@ -17,6 +17,7 @@ limitations under the License.
...
@@ -17,6 +17,7 @@ limitations under the License.
package
http
package
http
import
(
import
(
"io/ioutil"
"net"
"net"
"net/http"
"net/http"
"net/url"
"net/url"
...
@@ -34,7 +35,7 @@ func New() HTTPProber {
...
@@ -34,7 +35,7 @@ func New() HTTPProber {
}
}
type
HTTPProber
interface
{
type
HTTPProber
interface
{
Probe
(
host
string
,
port
int
,
path
string
,
timeout
time
.
Duration
)
(
probe
.
Result
,
error
)
Probe
(
host
string
,
port
int
,
path
string
,
timeout
time
.
Duration
)
(
probe
.
Result
,
string
,
error
)
}
}
type
httpProber
struct
{
type
httpProber
struct
{
...
@@ -42,7 +43,7 @@ type httpProber struct {
...
@@ -42,7 +43,7 @@ type httpProber struct {
}
}
// Probe returns a ProbeRunner capable of running an http check.
// Probe returns a ProbeRunner capable of running an http check.
func
(
pr
httpProber
)
Probe
(
host
string
,
port
int
,
path
string
,
timeout
time
.
Duration
)
(
probe
.
Result
,
error
)
{
func
(
pr
httpProber
)
Probe
(
host
string
,
port
int
,
path
string
,
timeout
time
.
Duration
)
(
probe
.
Result
,
string
,
error
)
{
return
DoHTTPProbe
(
formatURL
(
host
,
port
,
path
),
&
http
.
Client
{
Timeout
:
timeout
,
Transport
:
pr
.
transport
})
return
DoHTTPProbe
(
formatURL
(
host
,
port
,
path
),
&
http
.
Client
{
Timeout
:
timeout
,
Transport
:
pr
.
transport
})
}
}
...
@@ -54,18 +55,23 @@ type HTTPGetInterface interface {
...
@@ -54,18 +55,23 @@ type HTTPGetInterface interface {
// If the HTTP response code is successful (i.e. 400 > code >= 200), it returns Success.
// If the HTTP response code is successful (i.e. 400 > code >= 200), it returns Success.
// If the HTTP response code is unsuccessful or HTTP communication fails, it returns Failure.
// If the HTTP response code is unsuccessful or HTTP communication fails, it returns Failure.
// This is exported because some other packages may want to do direct HTTP probes.
// This is exported because some other packages may want to do direct HTTP probes.
func
DoHTTPProbe
(
url
string
,
client
HTTPGetInterface
)
(
probe
.
Result
,
error
)
{
func
DoHTTPProbe
(
url
string
,
client
HTTPGetInterface
)
(
probe
.
Result
,
string
,
error
)
{
res
,
err
:=
client
.
Get
(
url
)
res
,
err
:=
client
.
Get
(
url
)
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
V
(
1
)
.
Infof
(
"HTTP probe error: %v"
,
err
)
// Convert errors into failures to catch timeouts.
return
probe
.
Failure
,
nil
return
probe
.
Failure
,
err
.
Error
(),
nil
}
}
defer
res
.
Body
.
Close
()
defer
res
.
Body
.
Close
()
b
,
err
:=
ioutil
.
ReadAll
(
res
.
Body
)
if
err
!=
nil
{
return
probe
.
Failure
,
""
,
err
}
body
:=
string
(
b
)
if
res
.
StatusCode
>=
http
.
StatusOK
&&
res
.
StatusCode
<
http
.
StatusBadRequest
{
if
res
.
StatusCode
>=
http
.
StatusOK
&&
res
.
StatusCode
<
http
.
StatusBadRequest
{
return
probe
.
Success
,
nil
return
probe
.
Success
,
body
,
nil
}
}
glog
.
V
(
1
)
.
Infof
(
"Health check
failed for %s, Response: %v"
,
url
,
*
res
)
glog
.
V
(
4
)
.
Infof
(
"Probe
failed for %s, Response: %v"
,
url
,
*
res
)
return
probe
.
Failure
,
nil
return
probe
.
Failure
,
body
,
nil
}
}
// formatURL formats a URL from args. For testability.
// formatURL formats a URL from args. For testability.
...
...
pkg/probe/http/http_test.go
View file @
75617e87
...
@@ -22,6 +22,7 @@ import (
...
@@ -22,6 +22,7 @@ import (
"net/http/httptest"
"net/http/httptest"
"net/url"
"net/url"
"strconv"
"strconv"
"strings"
"testing"
"testing"
"time"
"time"
...
@@ -47,19 +48,23 @@ func TestFormatURL(t *testing.T) {
...
@@ -47,19 +48,23 @@ func TestFormatURL(t *testing.T) {
}
}
func
TestHTTPProbeChecker
(
t
*
testing
.
T
)
{
func
TestHTTPProbeChecker
(
t
*
testing
.
T
)
{
handleReq
:=
func
(
s
int
)
func
(
w
http
.
ResponseWriter
)
{
handleReq
:=
func
(
s
int
,
body
string
)
func
(
w
http
.
ResponseWriter
)
{
return
func
(
w
http
.
ResponseWriter
)
{
w
.
WriteHeader
(
s
)
}
return
func
(
w
http
.
ResponseWriter
)
{
w
.
WriteHeader
(
s
)
w
.
Write
([]
byte
(
body
))
}
}
}
prober
:=
New
()
prober
:=
New
()
testCases
:=
[]
struct
{
testCases
:=
[]
struct
{
handler
func
(
w
http
.
ResponseWriter
)
handler
func
(
w
http
.
ResponseWriter
)
health
probe
.
Result
health
probe
.
Result
body
string
}{
}{
// The probe will be filled in below. This is primarily testing that an HTTP GET happens.
// The probe will be filled in below. This is primarily testing that an HTTP GET happens.
{
handleReq
(
http
.
StatusOK
),
probe
.
Success
},
{
handleReq
(
http
.
StatusOK
,
"ok body"
),
probe
.
Success
,
"ok body"
},
{
handleReq
(
-
1
),
probe
.
Failure
},
{
handleReq
(
-
1
,
"fail body"
),
probe
.
Failure
,
"fail body"
},
{
func
(
w
http
.
ResponseWriter
)
{
time
.
Sleep
(
3
*
time
.
Second
)
},
probe
.
Failure
},
{
func
(
w
http
.
ResponseWriter
)
{
time
.
Sleep
(
3
*
time
.
Second
)
},
probe
.
Failure
,
"use of closed network connection"
},
}
}
for
_
,
test
:=
range
testCases
{
for
_
,
test
:=
range
testCases
{
server
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
server
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
@@ -77,7 +82,7 @@ func TestHTTPProbeChecker(t *testing.T) {
...
@@ -77,7 +82,7 @@ func TestHTTPProbeChecker(t *testing.T) {
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
}
health
,
err
:=
prober
.
Probe
(
host
,
p
,
""
,
1
*
time
.
Second
)
health
,
output
,
err
:=
prober
.
Probe
(
host
,
p
,
""
,
1
*
time
.
Second
)
if
test
.
health
==
probe
.
Unknown
&&
err
==
nil
{
if
test
.
health
==
probe
.
Unknown
&&
err
==
nil
{
t
.
Errorf
(
"Expected error"
)
t
.
Errorf
(
"Expected error"
)
}
}
...
@@ -87,5 +92,8 @@ func TestHTTPProbeChecker(t *testing.T) {
...
@@ -87,5 +92,8 @@ func TestHTTPProbeChecker(t *testing.T) {
if
health
!=
test
.
health
{
if
health
!=
test
.
health
{
t
.
Errorf
(
"Expected %v, got %v"
,
test
.
health
,
health
)
t
.
Errorf
(
"Expected %v, got %v"
,
test
.
health
,
health
)
}
}
if
!
strings
.
Contains
(
output
,
test
.
body
)
{
t
.
Errorf
(
"Expected %v, got %v"
,
test
.
body
,
output
)
}
}
}
}
}
pkg/probe/tcp/tcp.go
View file @
75617e87
...
@@ -31,12 +31,12 @@ func New() TCPProber {
...
@@ -31,12 +31,12 @@ func New() TCPProber {
}
}
type
TCPProber
interface
{
type
TCPProber
interface
{
Probe
(
host
string
,
port
int
,
timeout
time
.
Duration
)
(
probe
.
Result
,
error
)
Probe
(
host
string
,
port
int
,
timeout
time
.
Duration
)
(
probe
.
Result
,
string
,
error
)
}
}
type
tcpProber
struct
{}
type
tcpProber
struct
{}
func
(
pr
tcpProber
)
Probe
(
host
string
,
port
int
,
timeout
time
.
Duration
)
(
probe
.
Result
,
error
)
{
func
(
pr
tcpProber
)
Probe
(
host
string
,
port
int
,
timeout
time
.
Duration
)
(
probe
.
Result
,
string
,
error
)
{
return
DoTCPProbe
(
net
.
JoinHostPort
(
host
,
strconv
.
Itoa
(
port
)),
timeout
)
return
DoTCPProbe
(
net
.
JoinHostPort
(
host
,
strconv
.
Itoa
(
port
)),
timeout
)
}
}
...
@@ -44,14 +44,15 @@ func (pr tcpProber) Probe(host string, port int, timeout time.Duration) (probe.R
...
@@ -44,14 +44,15 @@ func (pr tcpProber) Probe(host string, port int, timeout time.Duration) (probe.R
// If the socket can be opened, it returns Success
// If the socket can be opened, it returns Success
// If the socket fails to open, it returns Failure.
// If the socket fails to open, it returns Failure.
// This is exported because some other packages may want to do direct TCP probes.
// This is exported because some other packages may want to do direct TCP probes.
func
DoTCPProbe
(
addr
string
,
timeout
time
.
Duration
)
(
probe
.
Result
,
error
)
{
func
DoTCPProbe
(
addr
string
,
timeout
time
.
Duration
)
(
probe
.
Result
,
string
,
error
)
{
conn
,
err
:=
net
.
DialTimeout
(
"tcp"
,
addr
,
timeout
)
conn
,
err
:=
net
.
DialTimeout
(
"tcp"
,
addr
,
timeout
)
if
err
!=
nil
{
if
err
!=
nil
{
return
probe
.
Failure
,
nil
// Convert errors to failures to handle timeouts.
return
probe
.
Failure
,
err
.
Error
(),
nil
}
}
err
=
conn
.
Close
()
err
=
conn
.
Close
()
if
err
!=
nil
{
if
err
!=
nil
{
glog
.
Errorf
(
"
unexpected error closing health check
socket: %v (%#v)"
,
err
,
err
)
glog
.
Errorf
(
"
Unexpected error closing TCP probe
socket: %v (%#v)"
,
err
,
err
)
}
}
return
probe
.
Success
,
nil
return
probe
.
Success
,
""
,
nil
}
}
pkg/probe/tcp/tcp_test.go
View file @
75617e87
...
@@ -22,6 +22,7 @@ import (
...
@@ -22,6 +22,7 @@ import (
"net/http/httptest"
"net/http/httptest"
"net/url"
"net/url"
"strconv"
"strconv"
"strings"
"testing"
"testing"
"time"
"time"
...
@@ -34,10 +35,11 @@ func TestTcpHealthChecker(t *testing.T) {
...
@@ -34,10 +35,11 @@ func TestTcpHealthChecker(t *testing.T) {
expectedStatus
probe
.
Result
expectedStatus
probe
.
Result
usePort
bool
usePort
bool
expectError
bool
expectError
bool
output
string
}{
}{
// The probe will be filled in below. This is primarily testing that a connection is made.
// The probe will be filled in below. This is primarily testing that a connection is made.
{
probe
.
Success
,
true
,
false
},
{
probe
.
Success
,
true
,
false
,
""
},
{
probe
.
Failure
,
false
,
false
},
{
probe
.
Failure
,
false
,
false
,
"tcp: unknown port"
},
}
}
server
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
server
:=
httptest
.
NewServer
(
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
...
@@ -60,7 +62,7 @@ func TestTcpHealthChecker(t *testing.T) {
...
@@ -60,7 +62,7 @@ func TestTcpHealthChecker(t *testing.T) {
if
!
test
.
usePort
{
if
!
test
.
usePort
{
p
=
-
1
p
=
-
1
}
}
status
,
err
:=
prober
.
Probe
(
host
,
p
,
1
*
time
.
Second
)
status
,
output
,
err
:=
prober
.
Probe
(
host
,
p
,
1
*
time
.
Second
)
if
status
!=
test
.
expectedStatus
{
if
status
!=
test
.
expectedStatus
{
t
.
Errorf
(
"expected: %v, got: %v"
,
test
.
expectedStatus
,
status
)
t
.
Errorf
(
"expected: %v, got: %v"
,
test
.
expectedStatus
,
status
)
}
}
...
@@ -70,5 +72,8 @@ func TestTcpHealthChecker(t *testing.T) {
...
@@ -70,5 +72,8 @@ func TestTcpHealthChecker(t *testing.T) {
if
err
==
nil
&&
test
.
expectError
{
if
err
==
nil
&&
test
.
expectError
{
t
.
Errorf
(
"unexpected non-error."
)
t
.
Errorf
(
"unexpected non-error."
)
}
}
if
!
strings
.
Contains
(
output
,
test
.
output
)
{
t
.
Errorf
(
"expected %s, got %s"
,
test
.
output
,
output
)
}
}
}
}
}
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