Skip to content

Commit 87d077a

Browse files
craig[bot]herkolategan
andcommitted
Merge #152008
152008: roachprod: add SSH config export r=golgeek a=herkolategan This change introduces a new option to `roachprod list` that exports an SSH configuration file for the listed clusters. This configuration enables direct SSH access to roachprod-created clusters using any SSH client, removing the need to run `roachprod ssh`. This feature is useful for tools, such as IDEs, that support remote SSH connections. Epic: None Release note: None Co-authored-by: Herko Lategan <herko@cockroachlabs.com>
2 parents 7e7425f + f0f3b27 commit 87d077a

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

pkg/cmd/roachprod/cli/commands.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"net/url"
1313
"os"
1414
"path"
15+
"path/filepath"
1516
"runtime"
1617
"sort"
1718
"strconv"
@@ -556,6 +557,44 @@ hosts file.
556557
}
557558
}
558559
}
560+
561+
// Optionally, export an SSH client config file for the clusters.
562+
// Only export if a pattern is specified or if the --mine flag is set.
563+
if exportSSHConfig != "" && (listPattern != "" || listMine) {
564+
hostTemplate := `Host %[1]s
565+
HostName %[2]s
566+
User %[3]s
567+
StrictHostKeyChecking no
568+
UserKnownHostsFile /dev/null
569+
%[4]s
570+
`
571+
var allKeys strings.Builder
572+
paths := make([]string, len(config.DefaultPubKeyNames))
573+
for idx, name := range config.DefaultPubKeyNames {
574+
paths[idx] = filepath.Join(config.SSHDirectory, name)
575+
}
576+
for _, p := range paths {
577+
if _, notFoundErr := os.Stat(p); notFoundErr == nil {
578+
allKeys.WriteString(fmt.Sprintf(" IdentityFile %s\n", p))
579+
}
580+
}
581+
582+
var configBuf strings.Builder
583+
for _, c := range filteredCloud.Clusters {
584+
for _, cVM := range c.VMs {
585+
if cVM.PublicIP == "" {
586+
continue
587+
}
588+
configBuf.WriteString(
589+
fmt.Sprintf(hostTemplate, cVM.Name, cVM.PublicIP, config.SharedUser, allKeys.String()),
590+
)
591+
}
592+
}
593+
err = os.WriteFile(filepath.Join(exportSSHConfig), []byte(configBuf.String()), 0600)
594+
if err != nil {
595+
return errors.Wrapf(err, "failed to write SSH config file to %s", exportSSHConfig)
596+
}
597+
}
559598
return nil
560599
}),
561600
}

pkg/cmd/roachprod/cli/flags.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ var (
5353
virtualClusterName string
5454
sqlInstance int
5555
extraSSHOptions = ""
56+
exportSSHConfig string
5657
nodeEnv []string
5758
tag string
5859
external = false
@@ -217,6 +218,8 @@ func initListCmdFlags(listCmd *cobra.Command) {
217218
"mine", "m", false, "Show only clusters belonging to the current user")
218219
listCmd.Flags().StringVar(&listPattern,
219220
"pattern", "", "Show only clusters matching the regex pattern. Empty string matches everything.")
221+
listCmd.Flags().StringVar(&exportSSHConfig,
222+
"export-ssh-config", os.Getenv("ROACHPROD_EXPORT_SSH_CONFIG"), "export the SSH config for listed clusters (only when pattern or mine is specified")
220223
}
221224

222225
func initAdminurlCmdFlags(adminurlCmd *cobra.Command) {
@@ -271,7 +274,6 @@ func initSyncCmdFlags(syncCmd *cobra.Command) {
271274
syncCmd.Flags().BoolVar(&listOpts.IncludeVolumes, "include-volumes", false, "Include volumes when syncing")
272275
syncCmd.Flags().StringArrayVarP(&listOpts.IncludeProviders, "clouds", "c",
273276
make([]string, 0), "Specify the cloud providers when syncing. Important: Use this flag only if you are certain that you want to sync with a specific cloud. All DNS host entries for other clouds will be erased from the DNS zone.")
274-
275277
}
276278

277279
func initStageCmdFlags(stageCmd *cobra.Command) {

0 commit comments

Comments
 (0)