Skip to content
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

Allow linking to artifact directly in prow logs #40493

Merged
merged 4 commits into from
Aug 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile.core.mk
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ ifeq ($(PULL_POLICY),)
$(error "PULL_POLICY cannot be empty")
endif

PROW_ARTIFACTS_BASE ?= https://gcsweb.istio.io/gcs/istio-prow

include tools/proto/proto.mk

.PHONY: default
Expand Down
4 changes: 3 additions & 1 deletion common/scripts/check_clean_repo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ function write_patch_file() {
echo "WARNING: patch file was too large to persist ($(du -h "${PATCH_OUT}"))"
return 0
fi
echo "You can also try applying the patch file from the build artifacts."
outName="artifacts/${PATCH_OUT#"${ARTIFACTS}"/}"
patchFile="${PROW_ARTIFACTS_BASE:-https://gcsweb.istio.io/gcs/istio-prow}/pr-logs/pull/${REPO_OWNER}_${REPO_NAME}/${PULL_NUMBER}/${JOB_NAME}/${BUILD_ID}/${outName}"
echo "You can also try applying the patch file from the build artifacts: 'git apply <(curl -sL \"${patchFile}\")'"
}

if [[ -n $(git status --porcelain) ]]; then
Expand Down
5 changes: 4 additions & 1 deletion pkg/test/framework/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
ferrors "istio.io/istio/pkg/test/framework/errors"
"istio.io/istio/pkg/test/framework/label"
"istio.io/istio/pkg/test/framework/resource"
"istio.io/istio/pkg/test/prow"
"istio.io/istio/pkg/test/scopes"
"istio.io/istio/pkg/test/util/file"
"istio.io/pkg/log"
Expand Down Expand Up @@ -455,7 +456,9 @@ func (s *suiteImpl) run() (errLevel int) {
ctx.RecordTraceEvent("suite-runtime", end.Sub(start).Seconds())
ctx.RecordTraceEvent("echo-calls", echo.GlobalEchoRequests.Load())
ctx.RecordTraceEvent("yaml-apply", GlobalYAMLWrites.Load())
_ = appendToFile(ctx.marshalTraceEvent(), filepath.Join(ctx.Settings().BaseDir, "trace.yaml"))
traceFile := filepath.Join(ctx.Settings().BaseDir, "trace.yaml")
scopes.Framework.Infof("Wrote trace to %v", prow.ArtifactsURL(traceFile))
_ = appendToFile(ctx.marshalTraceEvent(), traceFile)
}()

attempt := 0
Expand Down
17 changes: 9 additions & 8 deletions pkg/test/kube/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
"istio.io/istio/pkg/test/framework/components/cluster"
"istio.io/istio/pkg/test/framework/components/istioctl"
"istio.io/istio/pkg/test/framework/resource"
"istio.io/istio/pkg/test/prow"
"istio.io/istio/pkg/test/scopes"
"istio.io/istio/pkg/test/util/retry"
)
Expand Down Expand Up @@ -340,31 +341,31 @@ func DumpPodLogs(_ resource.Context, c cluster.Cluster, workDir, namespace strin

// Get previous container logs, if applicable
if restarts := containerRestarts(pod, container.Name); restarts > 0 {
fname := podOutputPath(workDir, c, pod, fmt.Sprintf("%s.previous.log", container.Name))
// only care about istio components restart
if proxyContainer.IsContainer(container) || discoveryContainer.IsContainer(container) || initContainer.IsContainer(container) ||
validationContainer.IsContainer(container) || strings.HasPrefix(pod.Name, "istio-cni-node") {
// This is only called if the test failed, so we cannot mark it as "failed" again. Instead, output
// a log which will get highlighted in the test logs
// TODO proper analysis of restarts to ensure we do not miss crashes when tests still pass.
scopes.Framework.Errorf("FAIL: cluster/pod/container %s/%s/%s/%s restarted %d times",
c.Name(), pod.Namespace, pod.Name, container.Name, restarts)
scopes.Framework.Errorf("FAIL: cluster/pod/container %s/%s/%s/%s restarted %d times. Logs: %v",
c.Name(), pod.Namespace, pod.Name, container.Name, restarts, prow.ArtifactsURL(fname))
}
l, err := c.PodLogs(context.TODO(), pod.Name, pod.Namespace, container.Name, true /* previousLog */)
if err != nil {
scopes.Framework.Warnf("Unable to get previous logs for cluster/pod/container: %s/%s/%s/%s: %v",
c.Name(), pod.Namespace, pod.Name, container.Name, err)
}

fname := podOutputPath(workDir, c, pod, fmt.Sprintf("%s.previous.log", container.Name))
if err = os.WriteFile(fname, []byte(l), os.ModePerm); err != nil {
scopes.Framework.Warnf("Unable to write previous logs for cluster/pod/container: %s/%s/%s/%s: %v",
c.Name(), pod.Namespace, pod.Name, container.Name, err)
}
}

if crashed, terminateState := containerCrashed(pod, container.Name); crashed {
scopes.Framework.Errorf("FAIL: cluster/pod/container: %s/%s/%s/%s crashed with status: %+v",
c.Name(), pod.Namespace, pod.Name, container.Name, terminateState)
scopes.Framework.Errorf("FAIL: cluster/pod/container: %s/%s/%s/%s crashed with status: %+v. Logs: %v",
c.Name(), pod.Namespace, pod.Name, container.Name, terminateState, prow.ArtifactsURL(fname))
}

// Get envoy logs if the pod is a VM, since kubectl logs only shows the logs from iptables for VMs
Expand All @@ -378,7 +379,7 @@ func DumpPodLogs(_ resource.Context, c cluster.Cluster, workDir, namespace strin
}
if strings.Contains(stdout, "envoy backtrace") {
scopes.Framework.Errorf("FAIL: VM envoy crashed in cluster/pod/container: %s/%s/%s/%s. See log: %s",
c.Name(), pod.Namespace, pod.Name, container.Name, fname)
c.Name(), pod.Namespace, pod.Name, container.Name, prow.ArtifactsURL(fname))

if strings.Contains(stdAll, "Too many open files") {
// Run netstat on the container with the crashed proxy to debug socket creation issues.
Expand Down Expand Up @@ -511,8 +512,8 @@ func dumpProxyCommand(c cluster.Cluster, fw kube.PortForwarder, pod corev1.Pod,
break
}
if attempts > 3 {
scopes.Framework.Warnf("FAIL: cluster/pod %s/%s/%s found warming resources (%v) on final attempt",
c.Name(), pod.Namespace, pod.Name, warming)
scopes.Framework.Warnf("FAIL: cluster/pod %s/%s/%s found warming resources (%v) on final attempt. Logs: %v",
c.Name(), pod.Namespace, pod.Name, warming, prow.ArtifactsURL(fname))
break
}
scopes.Framework.Warnf("cluster/pod %s/%s/%s found warming resources (%v) on attempt %d",
Expand Down
52 changes: 52 additions & 0 deletions pkg/test/prow/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright Istio 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 prow

import (
"fmt"
"net/url"
"strings"

"istio.io/pkg/env"
)

var (
runningInCI = env.RegisterBoolVar("CI", false, "If true, indicates we are running in CI").Get()
artifactsBase = env.RegisterStringVar("PROW_ARTIFACTS_BASE", "https://gcsweb.istio.io/gcs/istio-prow", "the base url for prow artifacts").Get()
// https://github.com/kubernetes/test-infra/blob/master/prow/jobs.md#job-environment-variables
jobType = env.RegisterStringVar("JOB_TYPE", "presubmit", "type of job").Get()
jobName = env.RegisterStringVar("JOB_NAME", "", "name of job").Get()
pullNumber = env.RegisterStringVar("PULL_NUMBER", "", "PR of job").Get()
repoName = env.RegisterStringVar("REPO_NAME", "istio", "repo name").Get()
repoOwner = env.RegisterStringVar("REPO_OWNER", "istio", "repo owner").Get()
buildID = env.RegisterStringVar("BUILD_ID", "", "build id").Get()
artifacts = env.RegisterStringVar("ARTIFACTS", "", "artifacts base").Get()
)

func ArtifactsURL(filename string) string {
if !runningInCI {
return filename
}
name := "artifacts/" + strings.TrimPrefix(filename, artifacts+"/")
if jobType == "presubmit" {
return join(artifactsBase, "pr-logs/pull", fmt.Sprintf("%s_%s", repoOwner, repoName), pullNumber, jobName, buildID, name)
}
return join(artifactsBase, "logs", jobName, buildID, name)
}

func join(base string, elem ...string) string {
res, _ := url.JoinPath(base, elem...)
return res
}