add an ark bug command

Signed-off-by: Dave Parfitt <diparfitt@gmail.com>
pull/774/head
Dave Parfitt 2018-07-27 14:15:54 -04:00
parent 652069b5e6
commit 342a1c6437
9 changed files with 366 additions and 1 deletions

View File

@ -27,7 +27,7 @@ about: Tell us about a problem you are experiencing
**Environment:** **Environment:**
- Ark version (use `ark version`): - Ark version (use `ark version`):
- Kubernetes version (use `kubectl version`): - Kubernetes version (use `kubectl version`):
- Kubernetes installer & version: - Kubernetes installer & version:
- Cloud provider or hardware configuration: - Cloud provider or hardware configuration:

View File

@ -31,6 +31,7 @@ operations can also be performed as 'ark backup get' and 'ark schedule create'.
### SEE ALSO ### SEE ALSO
* [ark backup](ark_backup.md) - Work with backups * [ark backup](ark_backup.md) - Work with backups
* [ark bug](ark_bug.md) - Report an Ark bug
* [ark client](ark_client.md) - Ark client related commands * [ark client](ark_client.md) - Ark client related commands
* [ark completion](ark_completion.md) - Output shell completion code for the specified shell (bash or zsh) * [ark completion](ark_completion.md) - Output shell completion code for the specified shell (bash or zsh)
* [ark create](ark_create.md) - Create ark resources * [ark create](ark_create.md) - Create ark resources

View File

@ -0,0 +1,37 @@
## ark bug
Report an Ark bug
### Synopsis
Open a browser window to report an Ark bug
```
ark bug [flags]
```
### Options
```
-h, --help help for bug
```
### Options inherited from parent commands
```
--alsologtostderr log to standard error as well as files
--kubeconfig string Path to the kubeconfig file to use to talk to the Kubernetes apiserver. If unset, try the environment variable KUBECONFIG, as well as in-cluster configuration
--kubecontext string The context to use to talk to the Kubernetes apiserver. If unset defaults to whatever your current-context is (kubectl config current-context)
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--logtostderr log to standard error instead of files
-n, --namespace string The namespace in which Ark should operate (default "heptio-ark")
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
-v, --v Level log level for V logs
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [ark](ark.md) - Back up and restore Kubernetes cluster resources.

View File

@ -0,0 +1,45 @@
/*
Copyright 2018 the Heptio Ark contributors.
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.
*/
// This code renders the IssueTemplate string in pkg/cmd/cli/bug/bug.go to
// .github/ISSUE_TEMPLATE/bug_report.md via the hack/update-generated-issue-template.sh script.
package main
import (
"log"
"os"
"text/template"
"github.com/heptio/ark/pkg/cmd/cli/bug"
)
func main() {
outTemplateFilename := os.Args[1]
outFile, err := os.OpenFile(outTemplateFilename, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer outFile.Close()
tmpl, err := template.New("ghissue").Parse(bug.IssueTemplate)
if err != nil {
log.Fatal(err)
}
err = tmpl.Execute(outFile, bug.ArkBugInfo{})
if err != nil {
log.Fatal(err)
}
}

View File

@ -2,6 +2,8 @@
These tips can help you troubleshoot known issues. If they don't help, you can [file an issue][4], or talk to us on the [#ark-dr channel][25] on the Kubernetes Slack server. These tips can help you troubleshoot known issues. If they don't help, you can [file an issue][4], or talk to us on the [#ark-dr channel][25] on the Kubernetes Slack server.
In `ark` version >= `0.1.0`, you can use the `ark bug` command to open a [Github issue][4] by launching a browser window with some prepopulated values. Values included are OS, CPU architecture, `kubectl` client and server versions (if available) and the `ark` client version. This information isn't submitted to Github until you click the `Submit new issue` button in the Github UI, so feel free to add, remove or update whatever information you like.
Some general commands for troubleshooting that may be helpful: Some general commands for troubleshooting that may be helpful:
* `ark backup describe <backupName>` - describe the details of a backup * `ark backup describe <backupName>` - describe the details of a backup

View File

@ -0,0 +1,36 @@
#!/bin/bash -e
#
# Copyright 2018 the Heptio Ark contributors.
#
# 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.
ARK_ROOT=$(dirname ${BASH_SOURCE})/..
BIN=${ARK_ROOT}/_output/bin
mkdir -p ${BIN}
echo "Updating generated Github issue template"
go build -o ${BIN}/issue-tmpl-gen ./docs/issue-template-gen/main.go
if [[ $# -gt 1 ]]; then
echo "usage: ${BASH_SOURCE} [OUTPUT_FILE]"
exit 1
fi
OUTPUT_ISSUE_FILE="$1"
if [[ -z "${OUTPUT_ISSUE_FILE}" ]]; then
OUTPUT_ISSUE_FILE=${ARK_ROOT}/.github/ISSUE_TEMPLATE/bug_report.md
fi
${BIN}/issue-tmpl-gen ${OUTPUT_ISSUE_FILE}
echo "Success!"

View File

@ -0,0 +1,39 @@
#!/bin/bash -e
#
# Copyright 2018 the Heptio Ark contributors.
#
# 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.
ARK_ROOT=$(dirname ${BASH_SOURCE})/..
HACK_DIR=$(dirname "${BASH_SOURCE}")
ISSUE_TEMPLATE_FILE=${ARK_ROOT}/.github/ISSUE_TEMPLATE/bug_report.md
OUT_TMP_FILE="$(mktemp -d)"/bug_report.md
trap cleanup INT TERM HUP EXIT
cleanup() {
rm -rf ${TMP_DIR}
}
echo "Verifying generated Github issue template"
${HACK_DIR}/update-generated-issue-template.sh ${OUT_TMP_FILE} > /dev/null
output=$(echo "`diff ${ISSUE_TEMPLATE_FILE} ${OUT_TMP_FILE}`")
if [[ -n "${output}" ]] ; then
echo "FAILURE: verification of generated template failed:"
echo "${output}"
exit 1
fi
echo "Success!"

View File

@ -23,6 +23,7 @@ import (
"github.com/heptio/ark/pkg/client" "github.com/heptio/ark/pkg/client"
"github.com/heptio/ark/pkg/cmd/cli/backup" "github.com/heptio/ark/pkg/cmd/cli/backup"
"github.com/heptio/ark/pkg/cmd/cli/bug"
cliclient "github.com/heptio/ark/pkg/cmd/cli/client" cliclient "github.com/heptio/ark/pkg/cmd/cli/client"
"github.com/heptio/ark/pkg/cmd/cli/completion" "github.com/heptio/ark/pkg/cmd/cli/completion"
"github.com/heptio/ark/pkg/cmd/cli/create" "github.com/heptio/ark/pkg/cmd/cli/create"
@ -69,6 +70,7 @@ operations can also be performed as 'ark backup get' and 'ark schedule create'.`
cliclient.NewCommand(), cliclient.NewCommand(),
completion.NewCommand(), completion.NewCommand(),
restic.NewCommand(f), restic.NewCommand(f),
bug.NewCommand(),
) )
// add the glog flags // add the glog flags

203
pkg/cmd/cli/bug/bug.go Normal file
View File

@ -0,0 +1,203 @@
/*
Copyright 2018 the Heptio Ark contributors.
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 bug
import (
"bytes"
"errors"
"fmt"
"net/url"
"os"
"os/exec"
"runtime"
"strings"
"text/template"
"time"
"github.com/heptio/ark/pkg/buildinfo"
"github.com/heptio/ark/pkg/cmd"
"github.com/spf13/cobra"
)
const (
// kubectlTimeout is how long we wait in seconds for `kubectl version`
// before killing the process
kubectlTimeout = 5 * time.Second
issueURL = "https://github.com/heptio/ark/issues/new"
// IssueTemplate is used to generate .github/ISSUE_TEMPLATE/bug_report.md
// as well as the initial text that's place in a new Github issue as
// the result of running `ark bug`.
IssueTemplate = `---
name: Bug report
about: Tell us about a problem you are experiencing
---
**What steps did you take and what happened:**
[A clear and concise description of what the bug is, and what commands you ran.)
**What did you expect to happen:**
**The output of the following commands will help us better understand what's going on**:
(Pasting long output into a [GitHub gist](https://gist.github.com) or other pastebin is fine.)
* ` + "`kubectl logs deployment/ark -n heptio-ark`" + `
* ` + "`ark backup describe <backupname>` or `kubectl get backup/<backupname> -n heptio-ark -o yaml`" + `
* ` + "`ark backup logs <backupname>`" + `
* ` + "`ark restore describe <restorename>` or `kubectl get restore/<restorename> -n heptio-ark -o yaml`" + `
* ` + "`ark restore logs <restorename>`" + `
**Anything else you would like to add:**
[Miscellaneous information that will assist in solving the issue.]
**Environment:**
- Ark version (use ` + "`ark version`" + `):{{.ArkVersion}} {{.GitCommit}} {{.GitTreeState}}
- Kubernetes version (use ` + "`kubectl version`" + `):
{{- if .KubectlVersion}}
` + "```" + `
{{.KubectlVersion}}
` + "```" + `
{{end}}
- Kubernetes installer & version:
- Cloud provider or hardware configuration:
- OS (e.g. from ` + "`/etc/os-release`" + `):
{{if .RuntimeOS}} - RuntimeOS: {{.RuntimeOS}}{{end -}}
{{if .RuntimeArch}} - RuntimeArch: {{.RuntimeArch}}{{end -}}
`
)
func NewCommand() *cobra.Command {
c := &cobra.Command{
Use: "bug",
Short: "Report an Ark bug",
Long: "Open a browser window to report an Ark bug",
Run: func(c *cobra.Command, args []string) {
kubectlVersion, err := getKubectlVersion()
if err != nil {
// we don't want to prevent the user from submitting a bug
// if we can't get the kubectl version, so just display a warning
fmt.Fprintf(os.Stderr, "WARNING: can't get kubectl version: %v\n", err)
}
body, err := renderToString(newBugInfo(kubectlVersion))
cmd.CheckError(err)
cmd.CheckError(showIssueInBrowser(body))
},
}
return c
}
type ArkBugInfo struct {
ArkVersion string
GitCommit string
GitTreeState string
RuntimeOS string
RuntimeArch string
KubectlVersion string
}
// cmdExistsOnPath checks to see if an executable is available on the current PATH
func cmdExistsOnPath(name string) bool {
if _, err := exec.LookPath(name); err != nil {
return false
}
return true
}
// getKubectlVersion makes a best-effort to run `kubectl version`
// and return it's output. This func will timeout and return an empty
// string after kubectlTimeout if we're not connected to a cluster.
func getKubectlVersion() (string, error) {
if !cmdExistsOnPath("kubectl") {
return "", errors.New("kubectl not found on PATH")
}
kubectlCmd := exec.Command("kubectl", "version")
var outbuf bytes.Buffer
kubectlCmd.Stdout = &outbuf
if err := kubectlCmd.Start(); err != nil {
return "", errors.New("can't start kubectl")
}
done := make(chan error, 1)
go func() {
done <- kubectlCmd.Wait()
}()
select {
case <-time.After(kubectlTimeout):
// we don't care about the possible error returned from Kill() here,
// just return an empty string
kubectlCmd.Process.Kill()
return "", errors.New("timeout waiting for kubectl version")
case err := <-done:
if err != nil {
return "", errors.New("error waiting for kubectl process")
}
}
versionOut := outbuf.String()
kubectlVersion := strings.TrimSpace(string(versionOut))
return kubectlVersion, nil
}
func newBugInfo(kubectlVersion string) *ArkBugInfo {
return &ArkBugInfo{
ArkVersion: buildinfo.Version,
GitCommit: buildinfo.GitSHA,
GitTreeState: buildinfo.GitTreeState,
RuntimeOS: runtime.GOOS,
RuntimeArch: runtime.GOARCH,
KubectlVersion: kubectlVersion}
}
// renderToString renders IssueTemplate to a string using the
// supplied *ArkBugInfo
func renderToString(bugInfo *ArkBugInfo) (string, error) {
outputTemplate, err := template.New("ghissue").Parse(IssueTemplate)
if err != nil {
return "", err
}
var buf bytes.Buffer
err = outputTemplate.Execute(&buf, bugInfo)
if err != nil {
return "", err
}
return buf.String(), nil
}
// showIssueInBrowser opens a browser window to submit a Github issue using
// a platform specific binary.
func showIssueInBrowser(body string) error {
url := issueURL + "?body=" + url.QueryEscape(body)
switch runtime.GOOS {
case "darwin":
return exec.Command("open", url).Start()
case "linux":
if cmdExistsOnPath("xdg-open") {
return exec.Command("xdg-open", url).Start()
}
return fmt.Errorf("ark can't open a browser window using the command '%s'", "xdg-open")
case "windows":
return exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
default:
return fmt.Errorf("ark can't open a browser window on platform %s", runtime.GOOS)
}
}