|
10 | 10 | - [Extracting a specific version of Kubernetes](#extracting-a-specific-version-of-kubernetes)
|
11 | 11 | - [Bringing up a cluster for testing](#bringing-up-a-cluster-for-testing)
|
12 | 12 | - [Debugging clusters](#debugging-clusters)
|
| 13 | + - [Debugging an E2E test with a debugger (delve)](#debugging-an-e2e-test-with-a-debugger-delve) |
13 | 14 | - [Local clusters](#local-clusters)
|
14 | 15 | - [Testing against local clusters](#testing-against-local-clusters)
|
15 | 16 | - [Version-skewed and upgrade testing](#version-skewed-and-upgrade-testing)
|
@@ -229,6 +230,7 @@ stale permissions can cause problems.
|
229 | 230 | - `sudo iptables -F`, clear ip tables rules left by the kube-proxy.
|
230 | 231 |
|
231 | 232 | ### Reproducing failures in flaky tests
|
| 233 | + |
232 | 234 | You can run a test repeatedly until it fails. This is useful when debugging
|
233 | 235 | flaky tests. In order to do so, you need to set the following environment
|
234 | 236 | variable:
|
@@ -259,6 +261,121 @@ the provided directory (which should already exist).
|
259 | 261 | The Google-run Jenkins builds automatically collected these logs for every
|
260 | 262 | build, saving them in the `artifacts` directory uploaded to GCS.
|
261 | 263 |
|
| 264 | +### Debugging an E2E test with a debugger (delve) |
| 265 | + |
| 266 | +When debugging E2E tests it's sometimes useful to pause in the middle of an E2E test |
| 267 | +to check the value of a variable or to check something in the cluster, instead of adding |
| 268 | +`time.Sleep(...)` we can run the E2E test with `delve` |
| 269 | + |
| 270 | +Requirements: |
| 271 | + |
| 272 | +- delve (https://github.com/go-delve/delve/tree/master/Documentation/installation) |
| 273 | + |
| 274 | +For this example we'll debug a [sig-storage test that will provision storage from a snapshot](https://github.com/kubernetes/kubernetes/blob/3ed71cf190a3d6a6dcb965cf73224538059e8e5e/test/e2e/storage/testsuites/provisioning.go#L200-L236) |
| 275 | + |
| 276 | +First, compile the E2E test suite with additional compiler flags |
| 277 | + |
| 278 | +```sh |
| 279 | +# -N Disable optimizations. |
| 280 | +# -l Disable inlining. |
| 281 | +make WHAT=test/e2e/e2e.test GOGCFLAGS="all=-N -l" GOLDFLAGS="" |
| 282 | +``` |
| 283 | + |
| 284 | +Then set the env var `E2E_TEST_DEBUG_TOOL=delve` and then run the test with `./hack/gingko.sh` instead of `kubetest`, you should see the delve command line prompt |
| 285 | + |
| 286 | +```sh |
| 287 | +E2E_TEST_DEBUG_TOOL=delve ./hack/ginkgo-e2e.sh --ginkgo.focus="sig-storage.*csi-hostpath.*Dynamic.PV.*default.fs.*provisioning.should.provision.storage.with.snapshot.data.source" --allowed-not-ready-nodes=10 |
| 288 | +--- |
| 289 | +Setting up for KUBERNETES_PROVIDER="gce". |
| 290 | +Project: ... |
| 291 | +Network Project: ... |
| 292 | +Zone: ... |
| 293 | +Trying to find master named '...' |
| 294 | +Looking for address '...' |
| 295 | +Using master: ... (external IP: XX.XXX.XXX.XX; internal IP: (not set)) |
| 296 | +Type 'help' for list of commands. |
| 297 | +(dlv) |
| 298 | +``` |
| 299 | + |
| 300 | +Use the commands described in the [delve command lists](https://github.com/go-delve/delve/blob/master/Documentation/cli/README.md), for our example we'll set a breakpoint at the start of the method |
| 301 | + |
| 302 | +```sh |
| 303 | +(dlv) break test/e2e/storage/testsuites/provisioning.go:201 |
| 304 | +Breakpoint 1 set at 0x72856f2 for k8s.io/kubernetes/test/e2e/storage/testsuites.(*provisioningTestSuite).DefineTests.func4() _output/local/go/src/k8s.io/kubernetes/test/e2e/storage/testsuites/provisioning.go:201 |
| 305 | +``` |
| 306 | + |
| 307 | +When you're done setting breakpoints execute `continue` to continue the test, once the breakpoint hits you have the chance to explore variables in the test |
| 308 | + |
| 309 | +```sh |
| 310 | +(dlv) continue |
| 311 | +Apr 16 20:29:18.724: INFO: Fetching cloud provider for "gce" |
| 312 | +I0416 20:29:18.725327 3669683 gce.go:909] Using DefaultTokenSource &oauth2.reuseTokenSource{new:(*oauth2.tokenRefresher)(0xc002b65d10), mu:sync.Mutex{state:0, sema:0x0}, t:(*oauth2.Token)(0xc0028e43c0)} |
| 313 | +W0416 20:29:18.891866 3669683 gce.go:477] No network name or URL specified. |
| 314 | +I0416 20:29:18.892058 3669683 e2e.go:129] Starting e2e run "ae1b58af-9e9e-4745-b1f4-27d763451f8e" on Ginkgo node 1 |
| 315 | +{"msg":"Test Suite starting","total":1,"completed":0,"skipped":0,"failed":0} |
| 316 | +Running Suite: Kubernetes e2e suite |
| 317 | +=================================== |
| 318 | +Random Seed: 1618604956 - Will randomize all specs |
| 319 | +Will run 1 of 5745 specs |
| 320 | +... |
| 321 | +------------------------------ |
| 322 | +[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] provisioning |
| 323 | + should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource] |
| 324 | + _output/local/go/src/k8s.io/kubernetes/test/e2e/storage/testsuites/provisioning.go:200 |
| 325 | +[BeforeEach] [Testpattern: Dynamic PV (default fs)] provisioning |
| 326 | + _output/local/go/src/k8s.io/kubernetes/test/e2e/storage/framework/testsuite.go:51 |
| 327 | +[BeforeEach] [Testpattern: Dynamic PV (default fs)] provisioning |
| 328 | + _output/local/go/src/k8s.io/kubernetes/test/e2e/framework/framework.go:185 |
| 329 | +STEP: Creating a kubernetes client |
| 330 | +Apr 16 20:29:24.747: INFO: >>> kubeConfig: ... |
| 331 | +STEP: Building a namespace api object, basename provisioning |
| 332 | +W0416 20:29:24.901750 3669683 warnings.go:70] policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+ |
| 333 | +Apr 16 20:29:24.901: INFO: No PodSecurityPolicies found; assuming PodSecurityPolicy is disabled. |
| 334 | +STEP: Waiting for a default service account to be provisioned in namespace |
| 335 | +[It] should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource] |
| 336 | + _output/local/go/src/k8s.io/kubernetes/test/e2e/storage/testsuites/provisioning.go:200 |
| 337 | +> k8s.io/kubernetes/test/e2e/storage/testsuites.(*provisioningTestSuite).DefineTests.func4() _output/local/go/src/k8s.io/kubernetes/test/e2e/storage/testsuites/provisioning.go:201 (hits goroutine(165):1 total:1) (PC: 0x72856f2) |
| 338 | +Warning: listing may not match stale executable |
| 339 | + 196: |
| 340 | + 197: l.testCase.TestDynamicProvisioning() |
| 341 | + 198: }) |
| 342 | + 199: |
| 343 | + 200: ginkgo.It("should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]", func() { |
| 344 | +=> 201: if !dInfo.Capabilities[storageframework.CapSnapshotDataSource] { |
| 345 | + 202: e2eskipper.Skipf("Driver %q does not support populate data from snapshot - skipping", dInfo.Name) |
| 346 | + 203: } |
| 347 | + 204: if !dInfo.SupportedFsType.Has(pattern.FsType) { |
| 348 | + 205: e2eskipper.Skipf("Driver %q does not support %q fs type - skipping", dInfo.Name, pattern.FsType) |
| 349 | + 206: } |
| 350 | +(dlv) print dInfo |
| 351 | +*k8s.io/kubernetes/test/e2e/storage/framework.DriverInfo { |
| 352 | + Name: "csi-hostpath", |
| 353 | + InTreePluginName: "", |
| 354 | + FeatureTag: "", |
| 355 | + MaxFileSize: 104857600, |
| 356 | + SupportedSizeRange: k8s.io/kubernetes/test/e2e/framework/volume.SizeRange {Max: "", Min: "1Mi"}, |
| 357 | + SupportedFsType: k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/util/sets.String [ |
| 358 | + "": {}, |
| 359 | + ], |
| 360 | + SupportedMountOption: k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/util/sets.String nil, |
| 361 | + RequiredMountOption: k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/util/sets.String nil, |
| 362 | + Capabilities: map[k8s.io/kubernetes/test/e2e/storage/framework.Capability]bool [ |
| 363 | + "persistence": true, |
| 364 | + "snapshotDataSource": true, |
| 365 | + "multipods": true, |
| 366 | + "block": true, |
| 367 | + "pvcDataSource": true, |
| 368 | + "controllerExpansion": true, |
| 369 | + "singleNodeVolume": true, |
| 370 | + "volumeLimits": true, |
| 371 | + ], |
| 372 | + RequiredAccessModes: []k8s.io/kubernetes/vendor/k8s.io/api/core/v1.PersistentVolumeAccessMode len: 0, cap: 0, nil, |
| 373 | + TopologyKeys: []string len: 0, cap: 0, nil, |
| 374 | + NumAllowedTopologies: 0, |
| 375 | + StressTestOptions: *k8s.io/kubernetes/test/e2e/storage/framework.StressTestOptions {NumPods: 10, NumRestarts: 10}, |
| 376 | + VolumeSnapshotStressTestOptions: *k8s.io/kubernetes/test/e2e/storage/framework.VolumeSnapshotStressTestOptions {NumPods: 10, NumSnapshots: 10},} |
| 377 | +``` |
| 378 | +
|
262 | 379 | ### Local clusters
|
263 | 380 |
|
264 | 381 | It can be much faster to iterate on a local cluster instead of a cloud-based
|
|
0 commit comments