44 "fmt"
55 "os"
66 "path/filepath"
7- "regexp "
7+ "slices "
88 "strconv"
99 "strings"
1010
@@ -72,34 +72,6 @@ func NewHost(username, hostname string, port uint16, proxyJump string, identityF
7272 host .HostName = parts [0 ]
7373 }
7474
75- // port
76- if host .Port == 0 {
77- portInt , err := strconv .Atoi (ssh_config .Get (host .HostName , "Port" ))
78- if err != nil {
79- return nil , fmt .Errorf ("invalid port format: %v" , host .HostName )
80- } else if portInt <= 0 || portInt >= 65536 {
81- return nil , fmt .Errorf ("invalid port format: %v" , host .HostName )
82- } else {
83- host .Port = uint16 (portInt )
84- }
85-
86- // default port
87- if host .Port == 0 {
88- host .Port = 22
89- }
90- }
91-
92- // username
93- if host .Username == "" {
94- host .Username = ssh_config .Get (host .HostName , "User" )
95- if host .Username == "" {
96- host .Username = os .Getenv ("USER" )
97- }
98- if host .Username == "" {
99- host .Username = "root"
100- }
101- }
102-
10375 // identity files
10476 for _ , identityFile := range identityFiles {
10577 if _ , err := os .Stat (identityFile ); err != nil {
@@ -108,42 +80,7 @@ func NewHost(username, hostname string, port uint16, proxyJump string, identityF
10880 host .IdentityFiles = append (host .IdentityFiles , identityFile )
10981 }
11082
111- if len (host .IdentityFiles ) == 0 {
112- identityFiles := ssh_config .GetAll (host .HostName , "IdentityFile" )
113- for _ , identityFile := range identityFiles {
114- if _ , err := os .Stat (identityFile ); err != nil {
115- continue
116- }
117- host .IdentityFiles = append (host .IdentityFiles , identityFile )
118- }
119-
120- // default identity file
121- if len (host .IdentityFiles ) == 0 {
122- host .IdentityFiles = []string {filepath .Join (os .Getenv ("HOME" ), ".ssh" , "id_rsa" )}
123- }
124- }
125-
126- // proxy jump
127- if host .ProxyJump == "" {
128- host .ProxyJump = ssh_config .Get (host .HostName , "ProxyJump" )
129- }
130-
131- // jump list
132- for _ , jump := range strings .Split (host .ProxyJump , "," ) {
133- if jump == "" {
134- continue
135- }
136- jumpHost , err := NewHost ("" , jump , 0 , "" , host .IdentityFiles )
137- if err != nil {
138- return nil , err
139- }
140- host .JumpList = append (host .JumpList , jumpHost )
141- }
142-
143- rawHostname := ssh_config .Get (host .HostName , "HostName" )
144- if rawHostname != "" {
145- host .HostName = rawHostname
146- }
83+ host .FillAttrsWithSSHConfig ()
14784
14885 logger .Debugf ("host: %+#v" , host )
14986 return host , nil
@@ -171,27 +108,164 @@ func (host *Host) JumpString() string {
171108 return strings .Join (hosts , "," )
172109}
173110
174- func CheckTags (tags string ) error {
175- if matched , err := regexp .MatchString (`[0-9a-zA-z_\-,]*` , tags ); err != nil {
176- return err
177- } else if ! matched {
178- return fmt .Errorf ("Invalid tags!" )
111+ func (host * Host ) MatchTags (tags []string ) bool {
112+ if len (tags ) == 0 {
113+ return false
114+ }
115+ for _ , tag := range tags {
116+ if slices .Contains (host .TagList , tag ) {
117+ return true
118+ }
119+ }
120+ return false
121+ }
122+
123+ func (host * Host ) fillUsername () {
124+ if host .Username != "" {
125+ return
126+ }
127+
128+ // fill username with patterns
129+ for _ , pattern := range host .Patterns {
130+ if strings .ContainsAny (pattern , "*!?" ) {
131+ continue
132+ }
133+ host .Username = ssh_config .Get (pattern , "User" )
134+ if host .Username != "" {
135+ break
136+ }
137+ }
138+
139+ // fill username with host name
140+ if host .Username == "" {
141+ host .Username = ssh_config .Get (host .HostName , "User" )
142+ }
143+
144+ // fill username with environment variable
145+ if host .Username == "" {
146+ host .Username = os .Getenv ("USER" )
147+ }
148+
149+ // default username
150+ if host .Username == "" {
151+ host .Username = "root"
152+ }
153+ }
154+
155+ func (host * Host ) fillPort () {
156+ if host .Port != 0 {
157+ return
158+ }
159+
160+ // fill port with patterns
161+ for _ , pattern := range host .Patterns {
162+ if strings .ContainsAny (pattern , "*!?" ) {
163+ continue
164+ }
165+ portInt , err := strconv .Atoi (ssh_config .Get (pattern , "Port" ))
166+ if err != nil {
167+ continue
168+ }
169+ if portInt <= 0 || portInt >= 65536 {
170+ continue
171+ }
172+ host .Port = uint16 (portInt )
173+ return
174+ }
175+
176+ // fill port with host name
177+ if host .Port == 0 {
178+ portInt , err := strconv .Atoi (ssh_config .Get (host .HostName , "Port" ))
179+ if err != nil {
180+ return
181+ }
182+ host .Port = uint16 (portInt )
183+ }
184+
185+ // fill port with host name
186+ if host .Port == 0 {
187+ host .Port = 22
179188 }
180- return nil
181189}
182190
183- func GetHostNames () (names []string ) {
184- hosts , err := GetHostsFromSSHConfig ()
185- if err != nil {
186- return nil
191+ func (host * Host ) fillProxyJump () {
192+ if host .ProxyJump != "" {
193+ return
187194 }
188- for _ , host := range hosts {
189- for _ , pattern := range host .Patterns {
190- if strings .ContainsAny (pattern , "*!?" ) {
195+
196+ // fill proxy jump with patterns
197+ for _ , pattern := range host .Patterns {
198+ if strings .ContainsAny (pattern , "*!?" ) {
199+ continue
200+ }
201+ host .ProxyJump = ssh_config .Get (pattern , "ProxyJump" )
202+ }
203+
204+ // fill proxy jump with host name
205+ if host .ProxyJump == "" {
206+ host .ProxyJump = ssh_config .Get (host .HostName , "ProxyJump" )
207+ }
208+
209+ // jump list
210+ if host .ProxyJump != "" {
211+ for _ , jump := range strings .Split (host .ProxyJump , "," ) {
212+ if jump == "" {
213+ continue
214+ }
215+ jumpHost , err := NewHost ("" , jump , 0 , "" , host .IdentityFiles )
216+ if err != nil {
191217 continue
192218 }
193- names = append (names , pattern )
219+ host .JumpList = append (host .JumpList , jumpHost )
220+ }
221+ }
222+ }
223+
224+ func (host * Host ) fillIdentityFiles () {
225+ if len (host .IdentityFiles ) > 0 {
226+ return
227+ }
228+
229+ // fill identity files with patterns
230+ for _ , pattern := range host .Patterns {
231+ if strings .ContainsAny (pattern , "*!?" ) {
232+ continue
233+ }
234+ identityFiles := ssh_config .GetAll (pattern , "IdentityFile" )
235+ for _ , identityFile := range identityFiles {
236+ if _ , err := os .Stat (identityFile ); err == nil {
237+ host .IdentityFiles = append (host .IdentityFiles , identityFile )
238+ }
194239 }
195240 }
196- return names
241+
242+ // fill identity files with host name
243+ if len (host .IdentityFiles ) == 0 {
244+ identityFiles := ssh_config .GetAll (host .HostName , "IdentityFile" )
245+ for _ , identityFile := range identityFiles {
246+ if _ , err := os .Stat (identityFile ); err == nil {
247+ host .IdentityFiles = append (host .IdentityFiles , identityFile )
248+ }
249+ }
250+ }
251+
252+ // default identity file
253+ if len (host .IdentityFiles ) == 0 {
254+ defaultIdentityFile := filepath .Join (os .Getenv ("HOME" ), ".ssh" , "id_rsa" )
255+ if _ , err := os .Stat (defaultIdentityFile ); err == nil {
256+ host .IdentityFiles = []string {defaultIdentityFile }
257+ }
258+ }
259+ }
260+
261+ func (host * Host ) FillAttrsWithSSHConfig () {
262+ host .fillUsername ()
263+ host .fillPort ()
264+ host .fillIdentityFiles ()
265+ host .fillProxyJump () // must after identity files
266+
267+ rawHostname := ssh_config .Get (host .HostName , "HostName" )
268+ if rawHostname != "" {
269+ host .HostName = rawHostname
270+ }
197271}
0 commit comments