Skip to content

Commit

Permalink
Initial implementation of bug-report command (istio#26045)
Browse files Browse the repository at this point in the history
* Initial implementation of kube-capture command

* Add unmarshaling and some tests

* Add filter test

* Add test coverage, rename to bug-report

* Add time range filterning

* Implement building cluster resource tree

* Add input flag processing, handle slices and overlay

* Add kubectlcmd

* Refactor, fetch logs

* Add log processing, importance ranking

* Add zip package

* Previous log handling, cleanup

* Get coredumps, cleanup

* Cleanup

* Get k8s resources, cleanup

* Get various cluster resources

* Get istiod resources

* Bug fixes

* Fixes, implement other resource fetches

* Comments

* Cleanup

* Lint

* Restructure file paths, comments

* Comments

* Add bug-report binary target

* Add other debug endpoints

* Fix dir path

* Lint

* Fix import format

* Try again to work around linter

* Another workaround attempt

* Comments

* Timeout

* Lint

* Release notes, cleanup

* Fix release note yaml

* Lint

* Fix release notes
  • Loading branch information
ostromart authored Sep 1, 2020
1 parent 9f3f254 commit a025011
Show file tree
Hide file tree
Showing 23 changed files with 2,748 additions and 2 deletions.
5 changes: 3 additions & 2 deletions Makefile.core.mk
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,11 @@ BINARIES:=./istioctl/cmd/istioctl \
./cni/cmd/istio-cni-repair \
./cni/cmd/istio-cni-taint \
./cni/cmd/install-cni \
./tools/istio-iptables
./tools/istio-iptables \
./tools/bug-report

# List of binaries included in releases
RELEASE_BINARIES:=pilot-discovery pilot-agent istioctl
RELEASE_BINARIES:=pilot-discovery pilot-agent istioctl bug-report

.PHONY: build
build: depend ## Builds all go binaries.
Expand Down
5 changes: 5 additions & 0 deletions istioctl/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"istio.io/istio/operator/cmd/mesh"
"istio.io/istio/pilot/pkg/serviceregistry/kube/controller"
"istio.io/istio/pkg/cmd"
"istio.io/istio/tools/bug-report/pkg/bugreport"
"istio.io/pkg/collateral"
"istio.io/pkg/env"
"istio.io/pkg/log"
Expand Down Expand Up @@ -255,6 +256,10 @@ debug and diagnose their Istio mesh.
hideInheritedFlags(upgradeCmd, "namespace", "istioNamespace")
rootCmd.AddCommand(upgradeCmd)

bugReportCmd := bugreport.Cmd()
hideInheritedFlags(bugReportCmd, "namespace", "istioNamespace")
rootCmd.AddCommand(bugReportCmd)

experimentalCmd.AddCommand(multicluster.NewCreateRemoteSecretCommand())
experimentalCmd.AddCommand(multicluster.NewMulticlusterCommand())

Expand Down
8 changes: 8 additions & 0 deletions releasenotes/notes/bug-report.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: release-notes/v2
kind: feature
area: istioctl
issue:
- 26045
releaseNotes:
- |
**Added** istioctl bug-report generates an archive of Istio and cluster information to assist with debugging.
29 changes: 29 additions & 0 deletions tools/bug-report/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 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 main

import (
"fmt"
"os"

"istio.io/istio/tools/bug-report/pkg/bugreport"
)

func main() {
if err := bugreport.Cmd().Execute(); err != nil {
fmt.Println(err)
os.Exit(-1)
}
}
110 changes: 110 additions & 0 deletions tools/bug-report/pkg/archive/archive.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// 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 archive

import (
"archive/tar"
"compress/gzip"
"io"
"os"
"path/filepath"
"strings"
"sync"
)

const (
bugReportSubdir = "bug-report"
proxyLogsPathSubdir = "proxies"
istioLogsPathSubdir = "istio"
clusterInfoSubdir = "cluster"
)

var (
tmpDir string
initDir sync.Once
)

func ProxyLogPath(rootDir, namespace, pod string) string {
dir := filepath.Join(getRootDir(rootDir), proxyLogsPathSubdir, namespace)
return filepath.Join(dir, pod+".log")
}

func ProxyCoredumpPath(rootDir, namespace, pod string) string {
dir := filepath.Join(getRootDir(rootDir), proxyLogsPathSubdir, namespace)
return filepath.Join(dir, pod+".core")
}

func IstiodPath(rootDir, namespace, pod string) string {
dir := filepath.Join(getRootDir(rootDir), istioLogsPathSubdir, namespace)
return filepath.Join(dir, pod)
}

func ClusterInfoPath(rootDir string) string {
dir := filepath.Join(getRootDir(rootDir), clusterInfoSubdir)
return dir
}

// Create creates a gzipped tar file from srcDir and writes it to outPath.
func Create(srcDir, outPath string) error {
mw, err := os.Create(outPath)
if err != nil {
return err
}

gzw := gzip.NewWriter(mw)
defer gzw.Close()

tw := tar.NewWriter(gzw)
defer tw.Close()

return filepath.Walk(srcDir, func(file string, fi os.FileInfo, err error) error {
if err != nil {
return err
}
if !fi.Mode().IsRegular() {
return nil
}
header, err := tar.FileInfoHeader(fi, fi.Name())
if err != nil {
return err
}
header.Name = strings.TrimPrefix(strings.Replace(file, srcDir, "", -1), string(filepath.Separator))
if err := tw.WriteHeader(header); err != nil {
return err
}

f, err := os.Open(file)
if err != nil {
return err
}
if _, err := io.Copy(tw, f); err != nil {
return err
}

f.Close()

return nil
})
}

func getRootDir(rootDir string) string {
if rootDir != "" {
return rootDir
}
initDir.Do(func() {
tmpDir = filepath.Join(os.TempDir(), bugReportSubdir)
})
return tmpDir
}
Loading

0 comments on commit a025011

Please sign in to comment.