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
72db883b
Commit
72db883b
authored
Jul 29, 2015
by
Brendan Burns
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #11050 from marekbiskup/dns-example-e2e
e2e test for dns example
parents
1367076d
86082243
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
192 additions
and
12 deletions
+192
-12
examples.go
test/e2e/examples.go
+133
-1
resize_nodes.go
test/e2e/resize_nodes.go
+0
-8
util.go
test/e2e/util.go
+59
-3
No files found.
test/e2e/examples.go
View file @
72db883b
...
@@ -18,6 +18,8 @@ package e2e
...
@@ -18,6 +18,8 @@ package e2e
import
(
import
(
"fmt"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"path/filepath"
"strings"
"strings"
"time"
"time"
...
@@ -34,8 +36,17 @@ import (
...
@@ -34,8 +36,17 @@ import (
const
(
const
(
podListTimeout
=
time
.
Minute
podListTimeout
=
time
.
Minute
serverStartTimeout
=
podStartTimeout
+
3
*
time
.
Minute
serverStartTimeout
=
podStartTimeout
+
3
*
time
.
Minute
dnsReadyTimeout
=
time
.
Minute
)
)
const
queryDnsPythonTemplate
string
=
`
import socket
try:
socket.gethostbyname('%s')
print 'ok'
except:
print 'err'`
var
_
=
Describe
(
"Examples e2e"
,
func
()
{
var
_
=
Describe
(
"Examples e2e"
,
func
()
{
var
c
*
client
.
Client
var
c
*
client
.
Client
var
ns
string
var
ns
string
...
@@ -412,6 +423,103 @@ var _ = Describe("Examples e2e", func() {
...
@@ -412,6 +423,103 @@ var _ = Describe("Examples e2e", func() {
})
})
})
})
})
})
Describe
(
"[Example]ClusterDns"
,
func
()
{
It
(
"should create pod that uses dns"
,
func
()
{
mkpath
:=
func
(
file
string
)
string
{
return
filepath
.
Join
(
testContext
.
RepoRoot
,
"examples/cluster-dns"
,
file
)
}
// contrary to the example, this test does not use contexts, for simplicity
// namespaces are passed directly.
// Also, for simplicity, we don't use yamls with namespaces, but we
// create testing namespaces instead.
backendRcYaml
:=
mkpath
(
"dns-backend-rc.yaml"
)
backendRcName
:=
"dns-backend"
backendSvcYaml
:=
mkpath
(
"dns-backend-service.yaml"
)
backendSvcName
:=
"dns-backend"
backendPodName
:=
"dns-backend"
frontendPodYaml
:=
mkpath
(
"dns-frontend-pod.yaml"
)
frontendPodName
:=
"dns-frontend"
frontendPodContainerName
:=
"dns-frontend"
podOutput
:=
"Hello World!"
// we need two namespaces anyway, so let's forget about
// the one created in BeforeEach and create two new ones.
namespaces
:=
[]
*
api
.
Namespace
{
nil
,
nil
}
for
i
:=
range
namespaces
{
var
err
error
namespaces
[
i
],
err
=
createTestingNS
(
fmt
.
Sprintf
(
"dnsexample%d"
,
i
),
c
)
if
namespaces
[
i
]
!=
nil
{
defer
c
.
Namespaces
()
.
Delete
(
namespaces
[
i
]
.
Name
)
}
Expect
(
err
)
.
NotTo
(
HaveOccurred
())
}
for
_
,
ns
:=
range
namespaces
{
runKubectl
(
"create"
,
"-f"
,
backendRcYaml
,
getNsCmdFlag
(
ns
))
}
for
_
,
ns
:=
range
namespaces
{
runKubectl
(
"create"
,
"-f"
,
backendSvcYaml
,
getNsCmdFlag
(
ns
))
}
// wait for objects
for
_
,
ns
:=
range
namespaces
{
waitForRCPodsRunning
(
c
,
ns
.
Name
,
backendRcName
)
waitForService
(
c
,
ns
.
Name
,
backendSvcName
,
true
,
poll
,
serviceStartTimeout
)
}
// it is not enough that pods are running because they may be set to running, but
// the application itself may have not been initialized. Just query the application.
for
_
,
ns
:=
range
namespaces
{
label
:=
labels
.
SelectorFromSet
(
labels
.
Set
(
map
[
string
]
string
{
"name"
:
backendRcName
}))
pods
,
err
:=
c
.
Pods
(
ns
.
Name
)
.
List
(
label
,
fields
.
Everything
())
Expect
(
err
)
.
NotTo
(
HaveOccurred
())
err
=
podsResponding
(
c
,
ns
.
Name
,
backendPodName
,
false
,
pods
)
Expect
(
err
)
.
NotTo
(
HaveOccurred
(),
"waiting for all pods to respond"
)
Logf
(
"found %d backend pods responding in namespace %s"
,
len
(
pods
.
Items
),
ns
.
Name
)
err
=
serviceResponding
(
c
,
ns
.
Name
,
backendSvcName
)
Expect
(
err
)
.
NotTo
(
HaveOccurred
(),
"waiting for the service to respond"
)
}
// Now another tricky part:
// It may happen that the service name is not yet in DNS.
// So if we start our pod, it will fail. We must make sure
// the name is already resolvable. So let's try to query DNS from
// the pod we have, until we find our service name.
// This complicated code may be removed if the pod itself retried after
// dns error or timeout.
// This code is probably unnecessary, but let's stay on the safe side.
label
:=
labels
.
SelectorFromSet
(
labels
.
Set
(
map
[
string
]
string
{
"name"
:
backendPodName
}))
pods
,
err
:=
c
.
Pods
(
namespaces
[
0
]
.
Name
)
.
List
(
label
,
fields
.
Everything
())
if
err
!=
nil
||
pods
==
nil
||
len
(
pods
.
Items
)
==
0
{
Failf
(
"no running pods found"
)
}
podName
:=
pods
.
Items
[
0
]
.
Name
queryDns
:=
fmt
.
Sprintf
(
queryDnsPythonTemplate
,
backendSvcName
+
"."
+
namespaces
[
0
]
.
Name
)
_
,
err
=
lookForStringInPodExec
(
namespaces
[
0
]
.
Name
,
podName
,
[]
string
{
"python"
,
"-c"
,
queryDns
},
"ok"
,
dnsReadyTimeout
)
Expect
(
err
)
.
NotTo
(
HaveOccurred
(),
"waiting for output from pod exec"
)
updatedPodYaml
:=
prepareResourceWithReplacedString
(
frontendPodYaml
,
"dns-backend.development.cluster.local"
,
fmt
.
Sprintf
(
"dns-backend.%s.cluster.local"
,
namespaces
[
0
]
.
Name
))
// create a pod in each namespace
for
_
,
ns
:=
range
namespaces
{
newKubectlCommand
(
"create"
,
"-f"
,
"-"
,
getNsCmdFlag
(
ns
))
.
withStdinData
(
updatedPodYaml
)
.
exec
()
}
// remember that we cannot wait for the pods to be running because our pods terminate by themselves.
// wait for pods to print their result
for
_
,
ns
:=
range
namespaces
{
_
,
err
:=
lookForStringInLog
(
ns
.
Name
,
frontendPodName
,
frontendPodContainerName
,
podOutput
,
podStartTimeout
)
Expect
(
err
)
.
NotTo
(
HaveOccurred
())
}
})
})
})
})
func
makeHttpRequestToService
(
c
*
client
.
Client
,
ns
,
service
,
path
string
)
(
string
,
error
)
{
func
makeHttpRequestToService
(
c
*
client
.
Client
,
ns
,
service
,
path
string
)
(
string
,
error
)
{
...
@@ -426,6 +534,21 @@ func makeHttpRequestToService(c *client.Client, ns, service, path string) (strin
...
@@ -426,6 +534,21 @@ func makeHttpRequestToService(c *client.Client, ns, service, path string) (strin
return
string
(
result
),
err
return
string
(
result
),
err
}
}
func
getNsCmdFlag
(
ns
*
api
.
Namespace
)
string
{
return
fmt
.
Sprintf
(
"--namespace=%v"
,
ns
.
Name
)
}
// pass enough context with the 'old' parameter so that it replaces what your really intended.
func
prepareResourceWithReplacedString
(
inputFile
,
old
,
new
string
)
string
{
f
,
err
:=
os
.
Open
(
inputFile
)
Expect
(
err
)
.
NotTo
(
HaveOccurred
())
defer
f
.
Close
()
data
,
err
:=
ioutil
.
ReadAll
(
f
)
Expect
(
err
)
.
NotTo
(
HaveOccurred
())
podYaml
:=
strings
.
Replace
(
string
(
data
),
old
,
new
,
1
)
return
podYaml
}
func
forEachPod
(
c
*
client
.
Client
,
ns
,
selectorKey
,
selectorValue
string
,
fn
func
(
api
.
Pod
))
{
func
forEachPod
(
c
*
client
.
Client
,
ns
,
selectorKey
,
selectorValue
string
,
fn
func
(
api
.
Pod
))
{
var
pods
*
api
.
PodList
var
pods
*
api
.
PodList
var
err
error
var
err
error
...
@@ -458,6 +581,15 @@ func lookForStringInFile(ns, podName, container, file, expectedString string, ti
...
@@ -458,6 +581,15 @@ func lookForStringInFile(ns, podName, container, file, expectedString string, ti
})
})
}
}
func
lookForStringInPodExec
(
ns
,
podName
string
,
command
[]
string
,
expectedString
string
,
timeout
time
.
Duration
)
(
result
string
,
err
error
)
{
return
lookForString
(
expectedString
,
timeout
,
func
()
string
{
// use the first container
args
:=
[]
string
{
"exec"
,
podName
,
fmt
.
Sprintf
(
"--namespace=%v"
,
ns
),
"--"
}
args
=
append
(
args
,
command
...
)
return
runKubectl
(
args
...
)
})
}
// Looks for the given string in the output of fn, repeatedly calling fn until
// Looks for the given string in the output of fn, repeatedly calling fn until
// the timeout is reached or the string is found. Returns last log and possibly
// the timeout is reached or the string is found. Returns last log and possibly
// error if the string was not found.
// error if the string was not found.
...
@@ -468,6 +600,6 @@ func lookForString(expectedString string, timeout time.Duration, fn func() strin
...
@@ -468,6 +600,6 @@ func lookForString(expectedString string, timeout time.Duration, fn func() strin
return
return
}
}
}
}
err
=
fmt
.
Errorf
(
"Failed to find
\"
%s
\"
"
,
expectedString
)
err
=
fmt
.
Errorf
(
"Failed to find
\"
%s
\"
, last result:
\"
%s
\"
"
,
expectedString
,
result
)
return
return
}
}
test/e2e/resize_nodes.go
View file @
72db883b
...
@@ -290,14 +290,6 @@ func podsRunning(c *client.Client, pods *api.PodList) []error {
...
@@ -290,14 +290,6 @@ func podsRunning(c *client.Client, pods *api.PodList) []error {
return
e
return
e
}
}
func
podsResponding
(
c
*
client
.
Client
,
ns
,
name
string
,
wantName
bool
,
pods
*
api
.
PodList
)
error
{
By
(
"trying to dial each unique pod"
)
retryTimeout
:=
2
*
time
.
Minute
retryInterval
:=
5
*
time
.
Second
label
:=
labels
.
SelectorFromSet
(
labels
.
Set
(
map
[
string
]
string
{
"name"
:
name
}))
return
wait
.
Poll
(
retryInterval
,
retryTimeout
,
podResponseChecker
{
c
,
ns
,
label
,
name
,
wantName
,
pods
}
.
checkAllResponses
)
}
func
verifyPods
(
c
*
client
.
Client
,
ns
,
name
string
,
wantName
bool
,
replicas
int
)
error
{
func
verifyPods
(
c
*
client
.
Client
,
ns
,
name
string
,
wantName
bool
,
replicas
int
)
error
{
pods
,
err
:=
podsCreated
(
c
,
ns
,
name
,
replicas
)
pods
,
err
:=
podsCreated
(
c
,
ns
,
name
,
replicas
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
test/e2e/util.go
View file @
72db883b
...
@@ -87,6 +87,9 @@ const (
...
@@ -87,6 +87,9 @@ const (
// be "ready" before the test starts, so this is small.
// be "ready" before the test starts, so this is small.
podReadyBeforeTimeout
=
20
*
time
.
Second
podReadyBeforeTimeout
=
20
*
time
.
Second
podRespondingTimeout
=
2
*
time
.
Minute
serviceRespondingTimeout
=
2
*
time
.
Minute
// How wide to print pod names, by default. Useful for aligning printing to
// How wide to print pod names, by default. Useful for aligning printing to
// quickly scan through output.
// quickly scan through output.
podPrintWidth
=
55
podPrintWidth
=
55
...
@@ -700,6 +703,37 @@ func (r podResponseChecker) checkAllResponses() (done bool, err error) {
...
@@ -700,6 +703,37 @@ func (r podResponseChecker) checkAllResponses() (done bool, err error) {
return
true
,
nil
return
true
,
nil
}
}
func
podsResponding
(
c
*
client
.
Client
,
ns
,
name
string
,
wantName
bool
,
pods
*
api
.
PodList
)
error
{
By
(
"trying to dial each unique pod"
)
label
:=
labels
.
SelectorFromSet
(
labels
.
Set
(
map
[
string
]
string
{
"name"
:
name
}))
return
wait
.
Poll
(
poll
,
podRespondingTimeout
,
podResponseChecker
{
c
,
ns
,
label
,
name
,
wantName
,
pods
}
.
checkAllResponses
)
}
func
serviceResponding
(
c
*
client
.
Client
,
ns
,
name
string
)
error
{
By
(
fmt
.
Sprintf
(
"trying to dial the service %s.%s via the proxy"
,
ns
,
name
))
return
wait
.
Poll
(
poll
,
serviceRespondingTimeout
,
func
()
(
done
bool
,
err
error
)
{
body
,
err
:=
c
.
Get
()
.
Prefix
(
"proxy"
)
.
Namespace
(
ns
)
.
Resource
(
"services"
)
.
Name
(
name
)
.
Do
()
.
Raw
()
if
err
!=
nil
{
Logf
(
"Failed to GET from service %s: %v:"
,
name
,
err
)
return
false
,
nil
}
got
:=
string
(
body
)
if
len
(
got
)
==
0
{
Logf
(
"Service %s: expected non-empty response"
,
name
)
return
false
,
err
// stop polling
}
Logf
(
"Service %s: found nonempty answer: %s"
,
name
,
got
)
return
true
,
nil
})
}
func
loadConfig
()
(
*
client
.
Config
,
error
)
{
func
loadConfig
()
(
*
client
.
Config
,
error
)
{
switch
{
switch
{
case
testContext
.
KubeConfig
!=
""
:
case
testContext
.
KubeConfig
!=
""
:
...
@@ -861,12 +895,29 @@ func kubectlCmd(args ...string) *exec.Cmd {
...
@@ -861,12 +895,29 @@ func kubectlCmd(args ...string) *exec.Cmd {
return
cmd
return
cmd
}
}
func
runKubectl
(
args
...
string
)
string
{
// kubectlBuilder is used to build, custimize and execute a kubectl Command.
// Add more functions to customize the builder as needed.
type
kubectlBuilder
struct
{
cmd
*
exec
.
Cmd
}
func
newKubectlCommand
(
args
...
string
)
*
kubectlBuilder
{
b
:=
new
(
kubectlBuilder
)
b
.
cmd
=
kubectlCmd
(
args
...
)
return
b
}
func
(
b
kubectlBuilder
)
withStdinData
(
data
string
)
*
kubectlBuilder
{
b
.
cmd
.
Stdin
=
strings
.
NewReader
(
data
)
return
&
b
}
func
(
b
kubectlBuilder
)
exec
()
string
{
var
stdout
,
stderr
bytes
.
Buffer
var
stdout
,
stderr
bytes
.
Buffer
cmd
:=
kubectlCmd
(
args
...
)
cmd
:=
b
.
cmd
cmd
.
Stdout
,
cmd
.
Stderr
=
&
stdout
,
&
stderr
cmd
.
Stdout
,
cmd
.
Stderr
=
&
stdout
,
&
stderr
Logf
(
"Running '%s %s'"
,
cmd
.
Path
,
strings
.
Join
(
cmd
.
Args
,
" "
))
Logf
(
"Running '%s %s'"
,
cmd
.
Path
,
strings
.
Join
(
cmd
.
Args
[
1
:
],
" "
))
// skip arg[0] as it is printed separately
if
err
:=
cmd
.
Run
();
err
!=
nil
{
if
err
:=
cmd
.
Run
();
err
!=
nil
{
Failf
(
"Error running %v:
\n
Command stdout:
\n
%v
\n
stderr:
\n
%v
\n
"
,
cmd
,
cmd
.
Stdout
,
cmd
.
Stderr
)
Failf
(
"Error running %v:
\n
Command stdout:
\n
%v
\n
stderr:
\n
%v
\n
"
,
cmd
,
cmd
.
Stdout
,
cmd
.
Stderr
)
return
""
return
""
...
@@ -876,6 +927,11 @@ func runKubectl(args ...string) string {
...
@@ -876,6 +927,11 @@ func runKubectl(args ...string) string {
return
strings
.
TrimSpace
(
stdout
.
String
())
return
strings
.
TrimSpace
(
stdout
.
String
())
}
}
// runKubectl is a convenience wrapper over kubectlBuilder
func
runKubectl
(
args
...
string
)
string
{
return
newKubectlCommand
(
args
...
)
.
exec
()
}
func
startCmdAndStreamOutput
(
cmd
*
exec
.
Cmd
)
(
stdout
,
stderr
io
.
ReadCloser
,
err
error
)
{
func
startCmdAndStreamOutput
(
cmd
*
exec
.
Cmd
)
(
stdout
,
stderr
io
.
ReadCloser
,
err
error
)
{
stdout
,
err
=
cmd
.
StdoutPipe
()
stdout
,
err
=
cmd
.
StdoutPipe
()
if
err
!=
nil
{
if
err
!=
nil
{
...
...
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