Skip to content

Commit

Permalink
🚧 indices browsing - getting there
Browse files Browse the repository at this point in the history
  • Loading branch information
acidjazz committed Mar 15, 2024
1 parent 030df51 commit 51e5d50
Show file tree
Hide file tree
Showing 14 changed files with 396 additions and 136 deletions.
17 changes: 13 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,42 @@ module github.com/vulncheck-oss/cli

go 1.21.5


replace github.com/vulncheck-oss/sdk => /Users/k/vc/oss/sdk

require (
github.com/MakeNowJust/heredoc/v2 v2.0.1
github.com/charmbracelet/bubbles v0.18.0
github.com/charmbracelet/bubbletea v0.25.0
github.com/charmbracelet/lipgloss v0.10.0
github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.18.2
github.com/vulncheck-oss/sdk v1.2.0
github.com/vulncheck-oss/sdk v1.2.1
)

require (
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/catppuccin/go v0.2.0 // indirect
github.com/charmbracelet/huh v0.3.0 // indirect
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gomarkdown/markdown v0.0.0-20210208175418-bda154fe17d8 // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/octoper/go-ray v0.1.5 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
Expand All @@ -43,7 +52,7 @@ require (
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.6.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
22 changes: 22 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/bradleyjkemp/cupaloy/v2 v2.6.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA=
github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc=
github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0=
github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw=
github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt5dywy4TcM=
github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg=
github.com/charmbracelet/huh v0.3.0 h1:CxPplWkgW2yUTDDG0Z4S5HH8SJOosWHd4LxCvi0XsKE=
github.com/charmbracelet/huh v0.3.0/go.mod h1:fujUdKX8tC45CCSaRQdw789O6uaCRwx8l2NDyKfC4jA=
github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s=
github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE=
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY=
Expand All @@ -21,8 +26,13 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gomarkdown/markdown v0.0.0-20210208175418-bda154fe17d8 h1:nWU6p08f1VgIalT6iZyqXi4o5cZsz4X6qa87nusfcsc=
github.com/gomarkdown/markdown v0.0.0-20210208175418-bda154fe17d8/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
Expand All @@ -37,6 +47,8 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
Expand All @@ -46,12 +58,16 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b h1:1XF24mVaiu7u+CFywTdcDo2ie1pzzhwjt6RHqzpMU34=
github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
github.com/octoper/go-ray v0.1.5 h1:tTN+4HptuzSnw60E0wM71wegKsy8wYhnQ2THjMvXBGQ=
github.com/octoper/go-ray v0.1.5/go.mod h1:Y1I9cUEZ4oD94H0/M+xwHhvGVbFu1o/dW3fDrknELk8=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand Down Expand Up @@ -81,9 +97,12 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
Expand All @@ -96,6 +115,7 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
Expand All @@ -106,6 +126,8 @@ golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
4 changes: 3 additions & 1 deletion pkg/cmd/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package auth
import (
"github.com/spf13/cobra"
"github.com/vulncheck-oss/cli/pkg/cmd/auth/login"
"github.com/vulncheck-oss/cli/pkg/cmd/auth/logout"
"github.com/vulncheck-oss/cli/pkg/cmd/auth/status"
"github.com/vulncheck-oss/cli/pkg/session"
)

func Command() *cobra.Command {
cmd := &cobra.Command{
Use: "auth <command",
Use: "auth <command>",
Short: "Authenticate vc with the VulnCheck portal",
GroupID: "core",
}
Expand All @@ -18,6 +19,7 @@ func Command() *cobra.Command {

cmd.AddCommand(login.Command())
cmd.AddCommand(status.Command())
cmd.AddCommand(logout.Command())

return cmd
}
132 changes: 95 additions & 37 deletions pkg/cmd/auth/login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ package login
import (
"fmt"
"github.com/MakeNowJust/heredoc/v2"
"github.com/charmbracelet/huh"
"github.com/spf13/cobra"
"github.com/vulncheck-oss/cli/pkg/config"
"github.com/vulncheck-oss/cli/pkg/session"
"github.com/vulncheck-oss/cli/pkg/ui"
"github.com/vulncheck-oss/cli/pkg/util"
"strings"
)

type CmdCopy struct {
Short string
Long string
}

func Command() *cobra.Command {

cmd := &cobra.Command{
Expand All @@ -34,44 +39,72 @@ func Command() *cobra.Command {
# Authenticate with vulncheck.com by passing in a token
$ vc auth login token vulncheck_******************
`),
}

web := &cobra.Command{
Use: "web",
Short: "Log in with a VulnCheck account using a web browser",
RunE: func(cmd *cobra.Command, args []string) error {
return util.FlagErrorf("web login is not yet implemented")
},
}

token := &cobra.Command{
Use: "token",
Short: "Connect a VulnCheck account using a token",
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
token, err := ui.TokenPrompt()

if err != nil {
return util.FlagErrorf("Failed to read token: %v", err)
if config.HasConfig() && config.HasToken() {
logoutChoice := true
confirm := huh.NewConfirm().
Title("You currently have a token saved. Do you want to invalidate it first?").
Affirmative("Yes").
Negative("No").
Value(&logoutChoice)
confirm.Run()

if logoutChoice {
if _, err := session.InvalidateToken(config.Token()); err != nil {
if err := config.RemoveToken(); err != nil {
return ui.Danger("Failed to remove token from config")
}
return ui.Info("Token was not valid, removing from config")
} else {
if err := config.RemoveToken(); err != nil {
return ui.Danger("Failed to remove token from config")
}
ui.Success("Token invalidated successfully")
}
} else {
return nil
}
args = []string{token}
}
if !ValidToken(args[0]) {
return util.FlagErrorf("Invalid token specified")

}

spinner := ui.Spinner("Verifying Token...")
res, err := session.CheckToken(args[0])
var choice string
form := huh.NewForm(
huh.NewGroup(
huh.NewSelect[string]().
Title("Select an authentication method").
Options(
huh.NewOption("Login with a web browser", "web"),
huh.NewOption("Paste an authentication token", "token"),
).Value(&choice),
),
)

err := form.Run()
if err != nil {
return util.FlagErrorf("Token verification failed: %v", err)
return util.FlagErrorf("Failed to select authentication method: %v", err)
}
spinner.Quit()
ui.Success(fmt.Sprintf("Authenticated as %s (%s)", res.Data.Name, res.Data.Email))
_, err = config.SaveToken(args[0])
if err != nil {
return util.FlagErrorf("Failed to save config: %v", err)

switch choice {
case "token":
return cmdToken(cmd, args)
default:
return util.FlagErrorf("Invalid choice")
}
return nil
},
}

token := &cobra.Command{
Use: "token",
Short: "Connect a VulnCheck account using an authentication token",
RunE: cmdToken,
}

web := &cobra.Command{
Use: "web",
Short: "Log in with a VulnCheck account using a web browser",
RunE: func(cmd *cobra.Command, args []string) error {
return util.FlagErrorf("web login is not yet implemented")
},
}

Expand All @@ -81,13 +114,38 @@ func Command() *cobra.Command {
return cmd
}

func ValidToken(token string) bool {
if !strings.HasPrefix(token, "vulncheck_") {
return false
func cmdToken(cmd *cobra.Command, args []string) error {

var token string

input := huh.
NewInput().
Title("Enter your authentication token").
Password(true).
Placeholder("vulncheck_******************").
Value(&token)

if err := input.Run(); err != nil {
return ui.Danger(fmt.Sprintf("Token verification failed: %v", err))
}

if !config.ValidToken(token) {
return util.FlagErrorf("Invalid token specified")
}

if len(token) != 74 {
return false
return SaveToken(token)
}

func SaveToken(token string) error {

spinner := ui.Spinner("Verifying Token...")
res, err := session.CheckToken(token)
if err != nil {
return ui.Danger(fmt.Sprintf("Token verification failed: %v", err))
}
spinner.Quit()
if err := config.SaveToken(token); err != nil {
return util.FlagErrorf("Failed to save token: %v", err)
}
return true
return ui.Success(fmt.Sprintf("Authenticated as %s (%s)", res.Data.Name, res.Data.Email))
}
42 changes: 42 additions & 0 deletions pkg/cmd/auth/logout/logout.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package logout

import (
"github.com/spf13/cobra"
"github.com/vulncheck-oss/cli/pkg/config"
"github.com/vulncheck-oss/cli/pkg/session"
"github.com/vulncheck-oss/cli/pkg/ui"
)

func Command() *cobra.Command {
cmd := &cobra.Command{
Use: "logout",
Short: "Invalidate and remove your current authentication token",
RunE: func(cmd *cobra.Command, args []string) error {

if !config.HasConfig() {
return ui.Danger("No configuration file found")
}

if !config.HasToken() {
return ui.Danger("No valid token was found")
}

_, err := session.InvalidateToken(config.Token())
if err == nil {
if err := config.RemoveToken(); err != nil {
return ui.Danger("Failed to remove token")
}
return ui.Success("Token successfully invalidated")
}
if err.Error() == session.ErrorUnauthorized {
if err := config.RemoveToken(); err != nil {
return ui.Danger("Token was invalid, removing from config")
}
}

return err
},
}

return cmd
}
Loading

0 comments on commit 51e5d50

Please sign in to comment.