Skip to content

Commit

Permalink
Interactive login (#5)
Browse files Browse the repository at this point in the history
* config file creation implemented

* generate new key function added

* login command implemented partially

* help text modified

* regex fix

* login authentication via PagerDuty API implemented

* main, root files moved

* connection pkg implemented for pdcli client connection

* client object added to login

* makefile changes, lint WIP

* constants package created, made config pkg changes

* sample test created

Co-authored-by: Supreeth Basabattini <[email protected]>
  • Loading branch information
Supreeth Basabattini and Supreeth Basabattini authored Sep 3, 2021
1 parent e5866da commit 6dc238f
Show file tree
Hide file tree
Showing 11 changed files with 399 additions and 80 deletions.
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,3 @@
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# PDCLI binary
pdcli
36 changes: 7 additions & 29 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,45 +21,23 @@ export GOPROXY=https://proxy.golang.org
# Disable CGO so that we always generate static binaries:
export CGO_ENABLED=0

# Constants
GOPATH := $(shell go env GOPATH)

# Allow overriding: `make lint container_runner=docker`.
container_runner:=podman

.PHONY: all
all: cmds

.PHONY: tools
tools:
which go-bindata || go get github.com/go-bindata/go-bindata/go-bindata

.PHONY: generate
generate: tools
go generate -x ./cmd/...

.PHONY: cmds
cmds: generate
for cmd in $$(ls cmd); do \
go build -o "$${cmd}" "./cmd/$${cmd}" || exit 1; \
done

.PHONY: build
build:
go build -o pdcli
go build -o pdcli ./cmd/pdcli

.PHONY: install
install:
go install ./pdcli
go build -o ${GOPATH}/bin/pdcli ./cmd/pdcli

.PHONY: test
test: cmds
ginkgo -r cmd tests

.PHONY: test $(FILE)
test $(FILE):
@go test $@

.PHONY: fmt
fmt:
gofmt -s -l -w cmd tests
test:
ginkgo -v -r tests

.PHONY: lint
lint:
Expand Down
155 changes: 141 additions & 14 deletions cmd/pdcli/login/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,158 @@ 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 login

import (
"bufio"
"errors"
"fmt"
"os"

"github.com/PagerDuty/go-pagerduty"
"github.com/openshift/pagerduty-short-circuiter/pkg/config"
"github.com/openshift/pagerduty-short-circuiter/pkg/constants"
"github.com/openshift/pagerduty-short-circuiter/pkg/pdcli"
"github.com/spf13/cobra"
)

// pdcli/login/cmdCmd represents the pdcli/login/cmd command
var loginArgs struct {
apiKey string
}

var Cmd = &cobra.Command{
Use: "login",
Short: "A brief description of your command",
Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:
`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("logged in")
},
Short: "Login to the PagerDuty CLI",
Long: `The pdcli login command logs a user into PagerDuty CLI given a valid API key is provided.
You will have to login only once, all the pdcli commands are then available even if the terminal restarts.`,
Args: cobra.NoArgs,
RunE: loginHandler,
}

func init() {
//cobra.OnInitialize(initConfig)
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
//flags
Cmd.Flags().StringVar(
&loginArgs.apiKey,
"api-key",
"",
"Access API key/token generated from "+constants.APIKeyURL+"\nUse this option to overwrite the existing API key.",
)
}

// loginHandler handles the login flow into pdcli.
func loginHandler(cmd *cobra.Command, args []string) error {

// load the configuration info
cfg, err := config.Load()

// If no config file can be located
// Or if the config file has errors
// Or if this is the first time a user is trying to login
// A new configuration struct is initialized on login
if err != nil {
cfg = new(config.Config)
}

// if the key arg is not-empty
if loginArgs.apiKey != "" {
cfg.ApiKey = loginArgs.apiKey

// Save the key in the config file
err = config.Save(cfg)

if err != nil {
return err
}

err = login(cfg.ApiKey)

if err != nil {
return err
}

return nil
}

// API key is not found in the config file
if len(cfg.ApiKey) == 0 {

// Create a new API key and store it in the config file
err = generateNewKey(cfg)

if err != nil {
return err
}

// Login using the newly generated API Key
err = login(cfg.ApiKey)

if err != nil {
return err
}

} else {

// Login using the existing API key in the configuration file
err = login(cfg.ApiKey)

if err != nil {
return err
}
}

return nil
}

// generateNewKey prompts the user to create a new API key and saves it to the config file.
func generateNewKey(cfg *config.Config) (err error) {
//prompts the user to generate an API Key
fmt.Println("In order to login it is mandatory to provide an API key.\nThe recommended way is to generate an API key via: " + constants.APIKeyURL)

//Takes standard input from the user and stores it in a variable
reader := bufio.NewReader(os.Stdin)
fmt.Print("API Key: ")
cfg.ApiKey, err = reader.ReadString('\n')

if err != nil {
return err
}

err = config.Save(cfg)

if err != nil {
return err
}

return nil
}

// login handles PagerDuty REST API authentication via an user API token.
// Requests that cannot be authenticated will return a `401 Unauthorized` error response.
func login(apiKey string) error {

// PagerDuty client object is created
client, err := pdcli.NewConnection().Build()

if err != nil {
return err
}

user, err := client.GetCurrentUser(pagerduty.GetCurrentUserOptions{})

if err != nil {
var apiError pagerduty.APIError

//`401 Unauthorized` error response
if errors.As(err, &apiError) {
err = fmt.Errorf("login failed\n%v Unauthorized", apiError.StatusCode)
return err
}

return err
} else {
fmt.Printf("Successfully logged in as user: %s\n", user.Name)
}

// Cobra also supports local flags, which will only run
// when this action is called directly.
return nil
}
4 changes: 1 addition & 3 deletions main.go → cmd/pdcli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ limitations under the License.
*/
package main

import "github.com/openshift/pagerduty-short-circuiter/cmd"

func main() {
cmd.Execute()
Execute()
}
31 changes: 10 additions & 21 deletions cmd/root.go → cmd/pdcli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,19 @@ 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 cmd
package main

import (
"github.com/openshift/pagerduty-short-circuiter/cmd/pdcli/login"
"github.com/spf13/cobra"
"github.com/openshift/pagerduty-short-circuiter/cmd/pdcli/login"
)


// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "pdcli",
Short: "A CLI application called pdcli short for pagerDuty CLI.",
Long: `It can be used reduce the time taken, from the time, SRE receives a PD alert to the time where troubleshooting on the cluster actually begins.
`,
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
Use: "pdcli",
Short: "A CLI application called pdcli short for PagerDuty CLI.",
Long: `It can be used reduce the time taken, from the time, SRE receives a PD alert to the time where troubleshooting on the cluster actually begins. `,
SilenceErrors: true,
}

// Execute adds all child commands to the root command and sets flags appropriately.
Expand All @@ -40,15 +35,9 @@ func Execute() {
}

func init() {
//cobra.OnInitialize(initConfig)
rootCmd.AddCommand(login.Cmd)
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.

// Cobra also supports local flags, which will only run
// when this action is called directly.
}
rootCmd.AddCommand(login.Cmd)

// initConfig reads in config file and ENV variables if set.
//Do not provide the default completion command
rootCmd.CompletionOptions.DisableDefaultCmd = true

}
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ module github.com/openshift/pagerduty-short-circuiter

go 1.15

require github.com/spf13/cobra v1.2.1
require (
github.com/PagerDuty/go-pagerduty v1.4.1
github.com/spf13/cobra v1.2.1
)
9 changes: 9 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/PagerDuty/go-pagerduty v1.4.1 h1:Mid8VpTj6eoECwuJ5xMcnVPxMxYGhZtMkENxYBOnbyk=
github.com/PagerDuty/go-pagerduty v1.4.1/go.mod h1:W5hSIIPrzSgAkNBDiuymWN5g9yQVzimL7BUBL44f3RY=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
Expand Down Expand Up @@ -115,6 +117,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
Expand Down Expand Up @@ -166,6 +170,7 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
Expand All @@ -176,6 +181,7 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
Expand All @@ -198,6 +204,7 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
Expand All @@ -209,6 +216,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
Expand Down Expand Up @@ -341,6 +349,7 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
Loading

0 comments on commit 6dc238f

Please sign in to comment.