package sshconf import ( "os" "path/filepath" "testing" ) func TestParseWithIncludeAndTags(t *testing.T) { dir := t.TempDir() incDir := filepath.Join(dir, "conf.d") if err := os.MkdirAll(incDir, 0o755); err != nil { t.Fatal(err) } main := `# global defaults Host * ServerAliveInterval 60 # tag: prod, riedel Host web1 web2 HostName 10.0.0.5 User deploy Port 2222 ProxyJump bastion Include conf.d/*.conf Host bastion HostName bastion.example.com User admin ` inc := `# tag: staging Host stage HostName stage.example.com User dev = ignored Host = eqform HostName eq.example.com ` if err := os.WriteFile(filepath.Join(dir, "config"), []byte(main), 0o644); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(incDir, "a.conf"), []byte(inc), 0o644); err != nil { t.Fatal(err) } hosts, err := Parse(filepath.Join(dir, "config")) if err != nil { t.Fatal(err) } byAlias := map[string]Host{} for _, h := range hosts { byAlias[h.Alias] = h } // Wildcard "Host *" must not appear as a connectable target. if _, ok := byAlias["*"]; ok { t.Error("wildcard host * should be skipped") } // Multiple aliases in one block share settings and tags. for _, a := range []string{"web1", "web2"} { h, ok := byAlias[a] if !ok { t.Fatalf("missing host %s", a) } if h.HostName != "10.0.0.5" || h.User != "deploy" || h.Port != "2222" || h.ProxyJump != "bastion" { t.Errorf("%s wrong fields: %+v", a, h) } if len(h.Tags) != 2 || h.Tags[0] != "prod" || h.Tags[1] != "riedel" { t.Errorf("%s wrong tags: %v", a, h.Tags) } } // Included file's host and its tag. stage, ok := byAlias["stage"] if !ok { t.Fatal("included host 'stage' missing") } if len(stage.Tags) != 1 || stage.Tags[0] != "staging" { t.Errorf("stage tags wrong: %v", stage.Tags) } // "Host = eqform" equals-form should parse the alias. if _, ok := byAlias["eqform"]; !ok { t.Error("equals-form Host 'eqform' missing") } // Ordering: web1 before included stage before bastion. order := []string{} for _, h := range hosts { order = append(order, h.Alias) } t.Logf("order: %v", order) } func TestParseMissingConfig(t *testing.T) { hosts, err := Parse(filepath.Join(t.TempDir(), "does-not-exist")) if err != nil { t.Fatalf("missing config should not error: %v", err) } if hosts != nil { t.Errorf("expected nil hosts, got %v", hosts) } }