aboutsummaryrefslogtreecommitdiff
path: root/lib/ssh
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ssh')
-rw-r--r--lib/ssh/client_test.go2
-rw-r--r--lib/ssh/config/config.go47
-rw-r--r--lib/ssh/config/config_test.go13
-rw-r--r--lib/ssh/config/parser.go15
-rw-r--r--lib/ssh/config/parser_test.go2
-rw-r--r--lib/ssh/config/section.go35
-rw-r--r--lib/ssh/config/section_match.go5
-rw-r--r--lib/ssh/config/section_match_test.go16
-rw-r--r--lib/ssh/config/section_test.go9
9 files changed, 88 insertions, 56 deletions
diff --git a/lib/ssh/client_test.go b/lib/ssh/client_test.go
index 062a32cc..feead9cc 100644
--- a/lib/ssh/client_test.go
+++ b/lib/ssh/client_test.go
@@ -20,7 +20,7 @@ func TestNewClient_KeyError_notExist(t *testing.T) {
t.Skip(`Require active SSH server`)
var (
- section = config.NewSection(`localhost`)
+ section = config.NewSection(nil, `localhost`)
wd string
err error
diff --git a/lib/ssh/config/config.go b/lib/ssh/config/config.go
index 21116d44..1c156da5 100644
--- a/lib/ssh/config/config.go
+++ b/lib/ssh/config/config.go
@@ -30,12 +30,31 @@ var (
type Config struct {
envs map[string]string
+ // workDir store the current working directory.
workDir string
+
homeDir string
sections []*Section
}
+// newConfig create new SSH Config instance from file.
+func newConfig(file string) (cfg *Config, err error) {
+ cfg = &Config{}
+
+ cfg.workDir, err = os.Getwd()
+ if err != nil {
+ return nil, err
+ }
+
+ cfg.homeDir, err = os.UserHomeDir()
+ if err != nil {
+ return nil, err
+ }
+
+ return cfg, nil
+}
+
// Load SSH configuration from file.
func Load(file string) (cfg *Config, err error) {
if len(file) == 0 {
@@ -47,26 +66,32 @@ func Load(file string) (cfg *Config, err error) {
section *Section
)
- cfg = &Config{
- sections: make([]*Section, 0),
+ cfg, err = newConfig(file)
+ if err != nil {
+ return nil, fmt.Errorf("%s %s: %w", logp, file, err)
}
cfg.loadEnvironments()
- p, err := newParser()
+ var p *parser
+
+ p, err = newParser(cfg)
if err != nil {
return nil, fmt.Errorf("%s %s: %w", logp, file, err)
}
- cfg.workDir = p.workDir
- cfg.homeDir = p.homeDir
+ var lines []string
- lines, err := p.load("", file)
+ lines, err = p.load("", file)
if err != nil {
return nil, fmt.Errorf("%s %s: %w", logp, file, err)
}
- for x, line := range lines {
+ var (
+ line string
+ x int
+ )
+ for x, line = range lines {
if line[0] == '#' {
continue
}
@@ -81,13 +106,13 @@ func Load(file string) (cfg *Config, err error) {
cfg.sections = append(cfg.sections, section)
section = nil
}
- section = newSectionHost(value)
+ section = newSectionHost(cfg, value)
case keyMatch:
if section != nil {
cfg.sections = append(cfg.sections, section)
section = nil
}
- section, err = newSectionMatch(value)
+ section, err = newSectionMatch(cfg, value)
if err != nil {
return nil, fmt.Errorf("%s %s line %d: %w", logp, file, x+1, err)
}
@@ -114,13 +139,13 @@ func Load(file string) (cfg *Config, err error) {
// If no Host or Match found, it still return non-nil Section but with empty
// fields.
func (cfg *Config) Get(s string) (section *Section) {
- section = NewSection(s)
+ section = NewSection(cfg, s)
for _, hostMatch := range cfg.sections {
if hostMatch.isMatch(s) {
section.mergeField(hostMatch)
}
}
- section.setDefaults(cfg.workDir, cfg.homeDir)
+ section.setDefaults()
if s != `` && section.Field[KeyHostname] == `` {
section.Set(KeyHostname, s)
diff --git a/lib/ssh/config/config_test.go b/lib/ssh/config/config_test.go
index f31e5050..bf9aed9b 100644
--- a/lib/ssh/config/config_test.go
+++ b/lib/ssh/config/config_test.go
@@ -14,19 +14,26 @@ import (
)
var (
- testDefaultSection = NewSection(``)
+ dummyConfig *Config
+ testDefaultSection *Section
testParser *parser
)
func TestMain(m *testing.M) {
var err error
- testParser, err = newParser()
+ dummyConfig, err = newConfig(``)
if err != nil {
log.Fatal(err)
}
- testDefaultSection.setDefaults(testParser.workDir, testParser.homeDir)
+ testParser, err = newParser(dummyConfig)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ testDefaultSection = NewSection(dummyConfig, ``)
+ testDefaultSection.setDefaults()
os.Exit(m.Run())
}
diff --git a/lib/ssh/config/parser.go b/lib/ssh/config/parser.go
index 260f0b46..3ffef0a7 100644
--- a/lib/ssh/config/parser.go
+++ b/lib/ssh/config/parser.go
@@ -21,18 +21,11 @@ type parser struct {
homeDir string
}
-func newParser() (p *parser, err error) {
+func newParser(cfg *Config) (p *parser, err error) {
p = &parser{
- files: make(map[string]struct{}),
- }
-
- p.workDir, err = os.Getwd()
- if err != nil {
- return nil, err
- }
- p.homeDir, err = os.UserHomeDir()
- if err != nil {
- return nil, err
+ files: make(map[string]struct{}),
+ workDir: cfg.workDir,
+ homeDir: cfg.homeDir,
}
return p, nil
diff --git a/lib/ssh/config/parser_test.go b/lib/ssh/config/parser_test.go
index dea0db82..21bef8cd 100644
--- a/lib/ssh/config/parser_test.go
+++ b/lib/ssh/config/parser_test.go
@@ -134,7 +134,7 @@ func TestConfigParser_load(t *testing.T) {
}}
for _, c := range cases {
- p, err := newParser()
+ p, err := newParser(dummyConfig)
if err != nil {
t.Fatal(err)
}
diff --git a/lib/ssh/config/section.go b/lib/ssh/config/section.go
index dc0b9654..6b359bf5 100644
--- a/lib/ssh/config/section.go
+++ b/lib/ssh/config/section.go
@@ -232,27 +232,39 @@ type Section struct {
}
// NewSection create an empty Host or Match section.
-func NewSection(name string) *Section {
+//
+// The Config parameter is optional, if not set the section will assume that
+// any path is relative to current working directory or using absolute path.
+func NewSection(cfg *Config, name string) (section *Section) {
name = strings.TrimSpace(name)
if len(name) == 0 {
name = `*`
}
- return &Section{
+ section = &Section{
Field: map[string]string{},
env: map[string]string{},
name: name,
}
-}
-func newSectionHost(rawPattern string) (host *Section) {
- patterns := strings.Fields(rawPattern)
+ if cfg != nil {
+ section.homeDir = cfg.homeDir
+ section.WorkingDir = cfg.workDir
+ }
+
+ return section
+}
- host = NewSection(rawPattern)
- host.patterns = make([]*pattern, 0, len(patterns))
+func newSectionHost(cfg *Config, rawPattern string) (host *Section) {
+ host = NewSection(cfg, rawPattern)
- for _, pattern := range patterns {
- pat := newPattern(pattern)
+ var (
+ patterns = strings.Fields(rawPattern)
+ s string
+ pat *pattern
+ )
+ for _, s = range patterns {
+ pat = newPattern(s)
host.patterns = append(host.patterns, pat)
}
return host
@@ -465,10 +477,7 @@ func (section *Section) isMatch(s string) bool {
}
// setDefaults set and expand all of the fields values if its not set.
-func (section *Section) setDefaults(workDir, homeDir string) {
- section.homeDir = homeDir
- section.WorkingDir = workDir
-
+func (section *Section) setDefaults() {
if len(section.IdentityFile) == 0 {
section.IdentityFile = defaultIdentityFile()
}
diff --git a/lib/ssh/config/section_match.go b/lib/ssh/config/section_match.go
index 7c28188d..9626e20c 100644
--- a/lib/ssh/config/section_match.go
+++ b/lib/ssh/config/section_match.go
@@ -22,14 +22,13 @@ var (
// Other criteria may be combined arbitrarily.
// All criteria but "all", "canonical", and "final" require an argument.
// Criteria may be negated by prepending an exclamation mark (`!').
-func newSectionMatch(rawPattern string) (match *Section, err error) {
+func newSectionMatch(cfg *Config, rawPattern string) (match *Section, err error) {
var (
prevCriteria *matchCriteria
criteria *matchCriteria
)
- match = NewSection(rawPattern)
- match.criteria = make([]*matchCriteria, 0)
+ match = NewSection(cfg, rawPattern)
match.useCriteria = true
args := parseArgs(rawPattern, ' ')
diff --git a/lib/ssh/config/section_match_test.go b/lib/ssh/config/section_match_test.go
index d2742698..b1df06d9 100644
--- a/lib/ssh/config/section_match_test.go
+++ b/lib/ssh/config/section_match_test.go
@@ -21,7 +21,7 @@ func TestNewSectionMatch(t *testing.T) {
}}
for _, c := range cases {
- got, err := newSectionMatch(c.raw)
+ got, err := newSectionMatch(dummyConfig, c.raw)
if err != nil {
if c.expError != err.Error() {
t.Fatalf("parseCriteriaWithArg: expecting error %s, got %s",
@@ -29,7 +29,7 @@ func TestNewSectionMatch(t *testing.T) {
}
continue
}
- got.setDefaults(testParser.workDir, testParser.homeDir)
+ got.setDefaults()
test.Assert(t, c.raw, *c.exp, *got)
}
@@ -84,7 +84,7 @@ func TestParseCriteriaAll(t *testing.T) {
}}
for _, c := range cases {
- got, err := newSectionMatch(c.raw)
+ got, err := newSectionMatch(dummyConfig, c.raw)
if err != nil {
if c.expError != err.Error() {
t.Fatalf("parseCriteriaWithArg: expecting error %s, got %s",
@@ -92,7 +92,7 @@ func TestParseCriteriaAll(t *testing.T) {
}
continue
}
- got.setDefaults(testParser.workDir, testParser.homeDir)
+ got.setDefaults()
exp := c.exp(*testDefaultSection)
test.Assert(t, c.raw, *exp, *got)
@@ -129,7 +129,7 @@ func TestNewSectionMatch_ParseCriteriaExec(t *testing.T) {
}}
for _, c := range cases {
- got, err := newSectionMatch(c.raw)
+ got, err := newSectionMatch(dummyConfig, c.raw)
if err != nil {
if c.expError != err.Error() {
t.Fatalf("parseCriteriaWithArg: expecting error %s, got %s",
@@ -137,7 +137,7 @@ func TestNewSectionMatch_ParseCriteriaExec(t *testing.T) {
}
continue
}
- got.setDefaults(testParser.workDir, testParser.homeDir)
+ got.setDefaults()
exp := c.exp(*testDefaultSection)
test.Assert(t, c.raw, *exp, *got)
@@ -198,7 +198,7 @@ func TestParseCriteriaWithArg(t *testing.T) {
}}
for _, c := range cases {
- got, err := newSectionMatch(c.raw)
+ got, err := newSectionMatch(dummyConfig, c.raw)
if err != nil {
if c.expError != err.Error() {
t.Fatalf("parseCriteriaWithArg: expecting error %s, got %s",
@@ -206,7 +206,7 @@ func TestParseCriteriaWithArg(t *testing.T) {
}
continue
}
- got.setDefaults(testParser.workDir, testParser.homeDir)
+ got.setDefaults()
exp := c.exp(*testDefaultSection)
test.Assert(t, c.raw, *exp, *got)
diff --git a/lib/ssh/config/section_test.go b/lib/ssh/config/section_test.go
index 760d93d6..e89cc7b5 100644
--- a/lib/ssh/config/section_test.go
+++ b/lib/ssh/config/section_test.go
@@ -17,7 +17,6 @@ func TestNewSectionHost(t *testing.T) {
}{{
rawPattern: "",
exp: func(exp Section) *Section {
- exp.patterns = make([]*pattern, 0)
return &exp
},
}, {
@@ -53,8 +52,8 @@ func TestNewSectionHost(t *testing.T) {
}}
for _, c := range cases {
- got := newSectionHost(c.rawPattern)
- got.setDefaults(testParser.workDir, testParser.homeDir)
+ got := newSectionHost(dummyConfig, c.rawPattern)
+ got.setDefaults()
exp := c.exp(*testDefaultSection)
test.Assert(t, c.rawPattern, *exp, *got)
@@ -81,7 +80,7 @@ func TestSectionSetDefaults(t *testing.T) {
}}
for _, c := range cases {
got := c.section(*testDefaultSection)
- got.setDefaults(testParser.workDir, testParser.homeDir)
+ got.setDefaults()
exp := c.exp(*testDefaultSection)
test.Assert(t, `setDefaults`, exp.IdentityFile, got.IdentityFile)
@@ -167,7 +166,7 @@ func TestSection_UserKnownHostsFile(t *testing.T) {
}}
var (
- section = NewSection(`test`)
+ section = NewSection(dummyConfig, `test`)
c testCase
err error