-
Notifications
You must be signed in to change notification settings - Fork 551
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce a mechanism for gathering test artifacts during individual test failures #2442
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#! /bin/bash | ||
|
||
set -o pipefail | ||
set -o nounset | ||
set -o errexit | ||
|
||
: "${KUBECONFIG:?}" | ||
: "${TEST_NAMESPACE:?}" | ||
: "${TEST_ARTIFACTS_DIR:?}" | ||
|
||
mkdir -p "${TEST_ARTIFACTS_DIR}" | ||
|
||
commands=() | ||
commands+=("get subscriptions -o yaml") | ||
commands+=("get operatorgroups -o yaml") | ||
commands+=("get clusterserviceversions -o yaml") | ||
commands+=("get installplans -o yaml") | ||
commands+=("get pods -o wide") | ||
commands+=("get events --sort-by .lastTimestamp") | ||
|
||
echo "Storing the test artifact output in the ${TEST_ARTIFACTS_DIR} directory" | ||
for command in "${commands[@]}"; do | ||
echo "Collecting ${command} output..." | ||
COMMAND_OUTPUT_FILE=${TEST_ARTIFACTS_DIR}/${command// /_} | ||
kubectl -n ${TEST_NAMESPACE} ${command} >> "${COMMAND_OUTPUT_FILE}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: this script would also neglect deleting any "empty" files here - any file that contains an empty List will still be created and housed in this directory:
|
||
done |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,9 @@ package ctx | |
|
||
import ( | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
"strings" | ||
|
||
. "github.com/onsi/ginkgo" | ||
|
@@ -32,6 +35,7 @@ type TestContext struct { | |
dynamicClient dynamic.Interface | ||
packageClient pversioned.Interface | ||
ssaClient *controllerclient.ServerSideApplier | ||
artifactsDir string | ||
|
||
scheme *runtime.Scheme | ||
|
||
|
@@ -86,6 +90,35 @@ func (ctx TestContext) SSAClient() *controllerclient.ServerSideApplier { | |
return ctx.ssaClient | ||
} | ||
|
||
func (ctx TestContext) DumpNamespaceArtifacts(namespace string) error { | ||
if ctx.artifactsDir == "" { | ||
ctx.Logf("$ARTIFACTS_DIR is unset -- not collecting failed test case logs") | ||
return nil | ||
} | ||
ctx.Logf("collecting logs in the %s artifacts directory", ctx.artifactsDir) | ||
|
||
logDir := filepath.Join(ctx.artifactsDir, namespace) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm open to suggestions on how to best dump individual test failure artifacts. In the current implementation, this creates a directory named after whatever namespace was generated for that test. It wouldn't be immediately clear how to map this to an individual test failure, outside of looking at the overall CI logs that are produced during a run (as the namespace generated is logged). |
||
if err := os.MkdirAll(logDir, os.ModePerm); err != nil { | ||
return err | ||
} | ||
envvars := []string{ | ||
"TEST_NAMESPACE=" + namespace, | ||
"TEST_ARTIFACTS_DIR=" + logDir, | ||
"KUBECONFIG=" + os.Getenv("KUBECONFIG"), | ||
} | ||
|
||
// compiled test binary running e2e tests is run from the root ./bin directory | ||
cmd := exec.Command("../test/e2e/collect-ci-artifacts.sh") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: likely need to stat this file vs. relying on a local file reference. |
||
cmd.Env = append(cmd.Env, envvars...) | ||
cmd.Stdout = os.Stdout | ||
cmd.Stderr = os.Stderr | ||
if err := cmd.Run(); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func setDerivedFields(ctx *TestContext) error { | ||
if ctx == nil { | ||
return fmt.Errorf("nil test context") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -946,3 +946,20 @@ func SetupGeneratedTestNamespace(name string) corev1.Namespace { | |
|
||
return ns | ||
} | ||
|
||
func TeardownNamespace(ns string) { | ||
log := ctx.Ctx().Logf | ||
|
||
currentTest := CurrentGinkgoTestDescription() | ||
if currentTest.Failed { | ||
log("collecting the %s namespace artifacts as the '%s' test case failed", ns, currentTest.TestText) | ||
if err := ctx.Ctx().DumpNamespaceArtifacts(ns); err != nil { | ||
log("failed to collect namespace artifacts: %v", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We avoid performing operations like |
||
} | ||
} | ||
|
||
log("tearing down the %s namespace", ns) | ||
Eventually(func() error { | ||
return ctx.Ctx().KubeClient().KubernetesInterface().CoreV1().Namespaces().Delete(context.Background(), ns, metav1.DeleteOptions{}) | ||
}).Should(Succeed()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This output file likely needs some work - here's an example of an e2e run locally: