diff --git a/README.md b/README.md index d823355e281894dc39cab9d4dd3486e9dd89acb4..748f1a368eb46102c15d7990067a64f552f810f8 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Flags: -d, --debug print out request and response objects -h, --help help for nova-password -i, --private-key-path string a path to the RSA private key (PuTTY and OpenSSH formats) (default "~/.ssh/id_rsa") + -q, --quiet quiet (no extra output) --version version for nova-password -w, --wait uint wait for the password timeout in seconds ``` diff --git a/main.go b/main.go index 7c2bb6ef0a046ea3cd9f163231efc9ff06356588..f86589d79e37379a4dcc18d397b5c60383ba19b4 100644 --- a/main.go +++ b/main.go @@ -42,10 +42,14 @@ var RootCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { // get the wait timeout wait := viper.GetUint("wait") + // get the quiet flag + quiet := viper.GetBool("quiet") // Convert Unix path type to Windows path type, when necessary keyPath := filepath.FromSlash(viper.GetString("private-key-path")) - fmt.Printf("private-key-path: %s\n", keyPath) + if quiet == false { + log.Printf("private-key-path: %s\n", keyPath) + } // Read the key key, err := readKey(keyPath) @@ -63,9 +67,7 @@ var RootCmd = &cobra.Command{ // parse putty key if puttyKey.Encryption != "none" { // If the key is encrypted, decrypt it - log.Print("Private key is encrypted with the password") - fmt.Print("Enter the password: ") - pass, err := gopass.GetPasswd() + pass, err := getKeyPass(quiet) if err != nil { return err } @@ -85,9 +87,7 @@ var RootCmd = &cobra.Command{ if err != nil { if err.Error() != "ssh: no key found" { // If the key is encrypted, decrypt it - log.Print("Private key is encrypted with the password") - fmt.Print("Enter the password: ") - pass, err := gopass.GetPasswd() + pass, err := getKeyPass(quiet) if err != nil { return err } @@ -98,6 +98,7 @@ var RootCmd = &cobra.Command{ } } else { if pkerr != nil { + // if there was an error in putty format, print it as well log.Print(pkerr) } return err @@ -117,10 +118,10 @@ var RootCmd = &cobra.Command{ } for _, server := range args { - err = processServer(client, server, v, wait) + err = processServer(client, server, v, wait, quiet) if err != nil { - log.Printf("%s", err) - errors = append(errors, err) + log.Printf("Error getting the password for the %q server: %s", server, err) + errors = append(errors, fmt.Errorf("Error getting the password for the %q server: %s", server, err)) } } default: @@ -158,9 +159,12 @@ func initRootCmdFlags() { RootCmd.PersistentFlags().BoolP("debug", "d", false, "print out request and response objects") RootCmd.PersistentFlags().StringP("private-key-path", "i", defaultKeyPath, "a path to the RSA private key (PuTTY and OpenSSH formats)") RootCmd.PersistentFlags().UintP("wait", "w", 0, "wait for the password timeout in seconds") + RootCmd.PersistentFlags().BoolP("quiet", "q", false, "quiet (no extra output)") viper.BindPFlag("debug", RootCmd.PersistentFlags().Lookup("debug")) viper.BindPFlag("private-key-path", RootCmd.PersistentFlags().Lookup("private-key-path")) viper.BindPFlag("wait", RootCmd.PersistentFlags().Lookup("wait")) + viper.BindPFlag("quiet", RootCmd.PersistentFlags().Lookup("quiet")) + } // newComputeV2 creates a ServiceClient that may be used with the v2 compute @@ -194,24 +198,25 @@ func newComputeV2() (*gophercloud.ServiceClient, error) { }) } -func processServer(client *gophercloud.ServiceClient, server string, privateKey *rsa.PrivateKey, wait uint) error { +func processServer(client *gophercloud.ServiceClient, server string, privateKey *rsa.PrivateKey, wait uint, quiet bool) error { + tmp := server // Verify whether UUID was provided. If the name was provided, resolve the server name _, err := uuid.Parse(server) if err != nil { - fmt.Printf("server: %s", server) server, err = servers.IDFromName(client, server) if err != nil { - fmt.Println() return err } - fmt.Printf(" (%s)\n", server) - } else { - fmt.Printf("server: %s\n", server) + if quiet == false { + log.Printf("Resolved %q server name to the %q uuid", tmp, server) + } } var res servers.GetPasswordResult if wait > 0 { - log.Printf("Waiting for %d seconds to get the password", wait) + if quiet == false { + log.Printf("Waiting for %d seconds to get the password", wait) + } // Wait for the encrypted server password res, err = waitForPassword(client, server, wait) if err != nil { @@ -231,7 +236,12 @@ func processServer(client *gophercloud.ServiceClient, server string, privateKey if err != nil { return err } - fmt.Printf("Decrypted compute instance password: %s\n", pwd) + + if quiet == false { + fmt.Printf("%q instance password: %s\n", tmp, pwd) + } else { + fmt.Printf("%s\n", pwd) + } return nil } @@ -293,3 +303,19 @@ func readKey(path string) ([]byte, error) { return key, nil } + +func getKeyPass(quiet bool) ([]byte, error) { + pass := env.Get("NOVA_PASSWORD_KEY_PASSWORD") + + if pass == "" { + if quiet == true { + return nil, fmt.Errorf(`Private key is encrypted with the password, please set the "NOVA_PASSWORD_KEY_PASSWORD" environment variable`) + } + + log.Print("Private key is encrypted with the password") + fmt.Print("Enter the password: ") + return gopass.GetPasswd() + } + + return []byte(pass), nil +}