@@ -54,6 +54,7 @@ type sshConfigOptions struct {
54
54
disableAutostart bool
55
55
header []string
56
56
headerCommand string
57
+ removedKeys map [string ]bool
57
58
}
58
59
59
60
// addOptions expects options in the form of "option=value" or "option value".
@@ -74,30 +75,20 @@ func (o *sshConfigOptions) addOption(option string) error {
74
75
if err != nil {
75
76
return err
76
77
}
77
- for i , existing := range o .sshOptions {
78
- // Override existing option if they share the same key.
79
- // This is case-insensitive. Parsing each time might be a little slow,
80
- // but it is ok.
81
- existingKey , _ , err := codersdk .ParseSSHConfigOption (existing )
82
- if err != nil {
83
- // Don't mess with original values if there is an error.
84
- // This could have come from the user's manual edits.
85
- continue
86
- }
87
- if strings .EqualFold (existingKey , key ) {
88
- if value == "" {
89
- // Delete existing option.
90
- o .sshOptions = append (o .sshOptions [:i ], o .sshOptions [i + 1 :]... )
91
- } else {
92
- // Override existing option.
93
- o .sshOptions [i ] = option
94
- }
95
- return nil
96
- }
78
+ lowerKey := strings .ToLower (key )
79
+ if o .removedKeys != nil && o .removedKeys [lowerKey ] {
80
+ // Key marked as removed, skip.
81
+ return nil
97
82
}
98
- // Only append the option if it is not empty.
83
+ // Only append the option if it is not empty
84
+ // (we interpret empty as removal).
99
85
if value != "" {
100
86
o .sshOptions = append (o .sshOptions , option )
87
+ } else {
88
+ if o .removedKeys == nil {
89
+ o .removedKeys = make (map [string ]bool )
90
+ }
91
+ o .removedKeys [lowerKey ] = true
101
92
}
102
93
return nil
103
94
}
@@ -440,26 +431,29 @@ func (r *RootCmd) configSSH() *serpent.Command {
440
431
configOptions := sshConfigOpts
441
432
configOptions .sshOptions = nil
442
433
443
- // Add standard options.
444
- err := configOptions .addOptions (defaultOptions ... )
445
- if err != nil {
446
- return err
434
+ // User options first (SSH only uses the first
435
+ // option unless it can be given multiple times)
436
+ for _ , opt := range sshConfigOpts .sshOptions {
437
+ err := configOptions .addOptions (opt )
438
+ if err != nil {
439
+ return xerrors .Errorf ("add flag config option %q: %w" , opt , err )
440
+ }
447
441
}
448
442
449
- // Override with deployment options
443
+ // Deployment options second, allow them to
444
+ // override standard options.
450
445
for k , v := range coderdConfig .SSHConfigOptions {
451
446
opt := fmt .Sprintf ("%s %s" , k , v )
452
447
err := configOptions .addOptions (opt )
453
448
if err != nil {
454
449
return xerrors .Errorf ("add coderd config option %q: %w" , opt , err )
455
450
}
456
451
}
457
- // Override with flag options
458
- for _ , opt := range sshConfigOpts .sshOptions {
459
- err := configOptions .addOptions (opt )
460
- if err != nil {
461
- return xerrors .Errorf ("add flag config option %q: %w" , opt , err )
462
- }
452
+
453
+ // Finally, add the standard options.
454
+ err := configOptions .addOptions (defaultOptions ... )
455
+ if err != nil {
456
+ return err
463
457
}
464
458
465
459
hostBlock := []string {
0 commit comments