252 lines
8.3 KiB
Go
252 lines
8.3 KiB
Go
/*
|
|
Copyright 2022 The Kubernetes Authors.
|
|
|
|
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 pod_test
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/onsi/ginkgo/v2"
|
|
"github.com/onsi/ginkgo/v2/reporters"
|
|
|
|
v1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/kubernetes/fake"
|
|
"k8s.io/kubernetes/test/e2e/framework"
|
|
"k8s.io/kubernetes/test/e2e/framework/internal/output"
|
|
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
|
|
)
|
|
|
|
// The line number of the following code is checked in TestFailureOutput below.
|
|
// Be careful when moving it around or changing the import statements above.
|
|
// Here are some intentionally blank lines that can be removed to compensate
|
|
// for future additional import statements.
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
//
|
|
// This must be line #50.
|
|
|
|
var _ = ginkgo.Describe("pod", func() {
|
|
ginkgo.It("not found", func(ctx context.Context) {
|
|
framework.ExpectNoError(e2epod.WaitTimeoutForPodRunningInNamespace(ctx, clientSet, "no-such-pod", "default", timeout /* no explanation here to cover that code path */))
|
|
})
|
|
|
|
ginkgo.It("not running", func(ctx context.Context) {
|
|
framework.ExpectNoError(e2epod.WaitTimeoutForPodRunningInNamespace(ctx, clientSet, podName, podNamespace, timeout), "wait for pod %s running", podName /* tests printf formatting */)
|
|
})
|
|
})
|
|
|
|
const (
|
|
podName = "pending-pod"
|
|
podNamespace = "default"
|
|
timeout = 5 * time.Second
|
|
)
|
|
|
|
var (
|
|
clientSet = fake.NewSimpleClientset(&v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: podName, Namespace: podNamespace}})
|
|
)
|
|
|
|
func TestFailureOutput(t *testing.T) {
|
|
|
|
expected := output.TestResult{
|
|
// "INFO: Ignoring ..." or "INFO: Pod ..." will normally occur
|
|
// every two seconds, but we reduce it to one line because it
|
|
// might occur less often on a loaded system.
|
|
NormalizeOutput: func(output string) string {
|
|
return trimDuplicateLines(output, "INFO: ")
|
|
},
|
|
Suite: reporters.JUnitTestSuite{
|
|
Tests: 2,
|
|
Failures: 2,
|
|
Errors: 0,
|
|
Disabled: 0,
|
|
Skipped: 0,
|
|
TestCases: []reporters.JUnitTestCase{
|
|
{
|
|
Name: "[It] pod not found",
|
|
Status: "failed",
|
|
Failure: &reporters.JUnitFailure{
|
|
Type: "failed",
|
|
Description: `[FAILED] error while waiting for pod default/no-such-pod to be running: pods "no-such-pod" not found
|
|
In [It] at: wait_test.go:54 <time>
|
|
`,
|
|
},
|
|
SystemErr: `> Enter [It] not found - wait_test.go:53 <time>
|
|
INFO: Waiting up to 5s for pod "no-such-pod" in namespace "default" to be "running"
|
|
INFO: Ignoring NotFound error while getting pod default/no-such-pod
|
|
INFO: Unexpected error:
|
|
<*fmt.wrapError>: {
|
|
msg: "error while waiting for pod default/no-such-pod to be running: pods \"no-such-pod\" not found",
|
|
err: <*errors.StatusError>{
|
|
ErrStatus: {
|
|
TypeMeta: {Kind: "", APIVersion: ""},
|
|
ListMeta: {
|
|
SelfLink: "",
|
|
ResourceVersion: "",
|
|
Continue: "",
|
|
RemainingItemCount: nil,
|
|
},
|
|
Status: "Failure",
|
|
Message: "pods \"no-such-pod\" not found",
|
|
Reason: "NotFound",
|
|
Details: {Name: "no-such-pod", Group: "", Kind: "pods", UID: "", Causes: nil, RetryAfterSeconds: 0},
|
|
Code: 404,
|
|
},
|
|
},
|
|
}
|
|
[FAILED] error while waiting for pod default/no-such-pod to be running: pods "no-such-pod" not found
|
|
In [It] at: wait_test.go:54 <time>
|
|
< Exit [It] not found - wait_test.go:53 <time>
|
|
`,
|
|
},
|
|
{
|
|
Name: "[It] pod not running",
|
|
Status: "failed",
|
|
Failure: &reporters.JUnitFailure{
|
|
Description: `[FAILED] wait for pod pending-pod running: timed out while waiting for pod default/pending-pod to be running
|
|
In [It] at: wait_test.go:58 <time>
|
|
`,
|
|
Type: "failed",
|
|
},
|
|
SystemErr: `> Enter [It] not running - wait_test.go:57 <time>
|
|
INFO: Waiting up to 5s for pod "pending-pod" in namespace "default" to be "running"
|
|
INFO: Pod "pending-pod": Phase="", Reason="", readiness=false. Elapsed: <elapsed>
|
|
INFO: Unexpected error: wait for pod pending-pod running:
|
|
<*pod.timeoutError>: {
|
|
msg: "timed out while waiting for pod default/pending-pod to be running",
|
|
observedObjects: [
|
|
<*v1.Pod>{
|
|
TypeMeta: {Kind: "", APIVersion: ""},
|
|
ObjectMeta: {
|
|
Name: "pending-pod",
|
|
GenerateName: "",
|
|
Namespace: "default",
|
|
SelfLink: "",
|
|
UID: "",
|
|
ResourceVersion: "",
|
|
Generation: 0,
|
|
CreationTimestamp: {
|
|
Time: {wall: 0, ext: 0, loc: nil},
|
|
},
|
|
DeletionTimestamp: nil,
|
|
DeletionGracePeriodSeconds: nil,
|
|
Labels: nil,
|
|
Annotations: nil,
|
|
OwnerReferences: nil,
|
|
Finalizers: nil,
|
|
ManagedFields: nil,
|
|
},
|
|
Spec: {
|
|
Volumes: nil,
|
|
InitContainers: nil,
|
|
Containers: nil,
|
|
EphemeralContainers: nil,
|
|
RestartPolicy: "",
|
|
TerminationGracePeriodSeconds: nil,
|
|
ActiveDeadlineSeconds: nil,
|
|
DNSPolicy: "",
|
|
NodeSelector: nil,
|
|
ServiceAccountName: "",
|
|
DeprecatedServiceAccount: "",
|
|
AutomountServiceAccountToken: nil,
|
|
NodeName: "",
|
|
HostNetwork: false,
|
|
HostPID: false,
|
|
HostIPC: false,
|
|
ShareProcessNamespace: nil,
|
|
SecurityContext: nil,
|
|
ImagePullSecrets: nil,
|
|
Hostname: "",
|
|
Subdomain: "",
|
|
Affinity: nil,
|
|
SchedulerName: "",
|
|
Tolerations: nil,
|
|
HostAliases: nil,
|
|
PriorityClassName: "",
|
|
Priority: nil,
|
|
DNSConfig: nil,
|
|
ReadinessGates: nil,
|
|
RuntimeClassName: nil,
|
|
EnableServiceLinks: nil,
|
|
PreemptionPolicy: nil,
|
|
Overhead: nil,
|
|
TopologySpreadConstraints: nil,
|
|
SetHostnameAsFQDN: nil,
|
|
OS: nil,
|
|
HostUsers: nil,
|
|
SchedulingGates: nil,
|
|
ResourceClaims: nil,
|
|
},
|
|
Status: {
|
|
Phase: "",
|
|
Conditions: nil,
|
|
Message: "",
|
|
Reason: "",
|
|
NominatedNodeName: "",
|
|
HostIP: "",
|
|
PodIP: "",
|
|
PodIPs: nil,
|
|
StartTime: nil,
|
|
InitContainerStatuses: nil,
|
|
ContainerStatuses: nil,
|
|
QOSClass: "",
|
|
EphemeralContainerStatuses: nil,
|
|
},
|
|
},
|
|
],
|
|
}
|
|
[FAILED] wait for pod pending-pod running: timed out while waiting for pod default/pending-pod to be running
|
|
In [It] at: wait_test.go:58 <time>
|
|
< Exit [It] not running - wait_test.go:57 <time>
|
|
`,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
output.TestGinkgoOutput(t, expected)
|
|
}
|
|
|
|
func trimDuplicateLines(output, prefix string) string {
|
|
lines := strings.Split(output, "\n")
|
|
trimming := false
|
|
validLines := 0
|
|
for i := 0; i < len(lines); i++ {
|
|
if strings.HasPrefix(lines[i], prefix) {
|
|
// Keep the first line, and only that one.
|
|
if !trimming {
|
|
trimming = true
|
|
lines[validLines] = lines[i]
|
|
validLines++
|
|
}
|
|
} else {
|
|
trimming = false
|
|
lines[validLines] = lines[i]
|
|
validLines++
|
|
}
|
|
}
|
|
return strings.Join(lines[0:validLines], "\n")
|
|
}
|