mirror of
https://github.com/kemko/xc.git
synced 2026-01-01 15:55:43 +03:00
@@ -135,6 +135,7 @@ func New(cfg *config.XCConfig, backend store.Backend) (*Cli, error) {
|
||||
remote.SetDebug(cli.debug)
|
||||
remote.SetUsePasswordManager(cli.usePasswordMgr)
|
||||
remote.SetNumThreads(cli.sshThreads)
|
||||
remote.SetRemoteEnvironment(cfg.RemoteEnvironment)
|
||||
|
||||
// interpreter
|
||||
cli.setInterpreter("none", cfg.Interpreter)
|
||||
@@ -232,6 +233,9 @@ func (c *Cli) OneCmd(line string) {
|
||||
var argsLine string
|
||||
|
||||
line = strings.Trim(line, " \n\t")
|
||||
if strings.HasPrefix(line, "#") {
|
||||
return
|
||||
}
|
||||
|
||||
cmdRunes, rest := split([]rune(line))
|
||||
cmd := string(cmdRunes)
|
||||
|
||||
@@ -90,6 +90,7 @@ type XCConfig struct {
|
||||
PasswordManagerPath string
|
||||
PasswordManagerOptions map[string]string
|
||||
LocalEnvironment map[string]string
|
||||
RemoteEnvironment map[string]string
|
||||
Distribute string
|
||||
}
|
||||
|
||||
@@ -163,6 +164,7 @@ func read(filename string, secondPass bool) (*XCConfig, error) {
|
||||
cfg.Readline = defaultReadlineConfig
|
||||
cfg.BackendCfg = &BackendConfig{Type: BTIni, Options: make(map[string]string)}
|
||||
cfg.LocalEnvironment = make(map[string]string)
|
||||
cfg.RemoteEnvironment = make(map[string]string)
|
||||
|
||||
hf, err := props.GetString("main.history_file")
|
||||
if err != nil {
|
||||
@@ -351,5 +353,13 @@ func read(filename string, secondPass bool) (*XCConfig, error) {
|
||||
}
|
||||
}
|
||||
|
||||
envkeys, err = props.Subkeys("remote_environ")
|
||||
if err == nil {
|
||||
for _, key := range envkeys {
|
||||
value, _ := props.GetString(fmt.Sprintf("remote_environ.%s", key))
|
||||
cfg.RemoteEnvironment[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ var (
|
||||
outputFile *os.File
|
||||
poolLock *sync.Mutex
|
||||
poolSize int
|
||||
remoteEnvironment map[string]string
|
||||
|
||||
noneInterpreter string
|
||||
suInterpreter string
|
||||
@@ -114,6 +115,11 @@ func SetNumThreads(numThreads int) {
|
||||
poolSize = numThreads
|
||||
}
|
||||
|
||||
// SetRemoteEnvironment sets remote environ variables
|
||||
func SetRemoteEnvironment(environ map[string]string) {
|
||||
remoteEnvironment = environ
|
||||
}
|
||||
|
||||
func prepareTempFiles(cmd string) (string, string, error) {
|
||||
f, err := ioutil.TempFile("", "xc.")
|
||||
if err != nil {
|
||||
@@ -123,6 +129,10 @@ func prepareTempFiles(cmd string) (string, string, error) {
|
||||
|
||||
remoteFilename := filepath.Join(currentRemoteTmpdir, filepath.Base(f.Name()))
|
||||
io.WriteString(f, "#!/bin/bash\n\n")
|
||||
for varName, value := range remoteEnvironment {
|
||||
io.WriteString(f, fmt.Sprintf("%s=%s\n", varName, value))
|
||||
}
|
||||
io.WriteString(f, "\n")
|
||||
io.WriteString(f, fmt.Sprintf("nohup bash -c \"sleep 1; rm -f $0\" >/dev/null 2>&1 </dev/null &\n")) // self-destroy
|
||||
io.WriteString(f, cmd+"\n") // run command
|
||||
f.Chmod(0755)
|
||||
|
||||
@@ -246,6 +246,12 @@ execLoop:
|
||||
r.Codes[host] = ErrCopyFailed
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
for varName, value := range remoteEnvironment {
|
||||
remoteCmd += fmt.Sprintf("%s=%s ", varName, value)
|
||||
}
|
||||
remoteCmd += "$SHELL"
|
||||
remoteCmd = "'" + remoteCmd + "'"
|
||||
}
|
||||
|
||||
cmd = createSSHCmd(host, remoteCmd)
|
||||
|
||||
@@ -176,7 +176,7 @@ func (s *Store) HostList(expr []rune) ([]string, error) {
|
||||
continue
|
||||
}
|
||||
for _, tag := range token.TagsFilter {
|
||||
if !stringslice.Contains(invhost.Tags, tag) {
|
||||
if !stringslice.Contains(invhost.AllTags, tag) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -201,7 +201,7 @@ func (s *Store) HostList(expr []rune) ([]string, error) {
|
||||
}
|
||||
|
||||
for _, tag := range token.TagsFilter {
|
||||
if !stringslice.Contains(host.Tags, tag) {
|
||||
if !stringslice.Contains(host.AllTags, tag) {
|
||||
continue hostLoop1
|
||||
}
|
||||
}
|
||||
@@ -250,7 +250,7 @@ func (s *Store) HostList(expr []rune) ([]string, error) {
|
||||
}
|
||||
|
||||
for _, tag := range token.TagsFilter {
|
||||
if !stringslice.Contains(host.Tags, tag) {
|
||||
if !stringslice.Contains(host.AllTags, tag) {
|
||||
continue hostLoop2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,16 @@ func (fb *FakeBackend) Load() error {
|
||||
ParentID: "g1",
|
||||
Tags: []string{"tag3", "tag4"},
|
||||
}
|
||||
fb.groups = append(fb.groups, group1, group2)
|
||||
|
||||
group3 := &Group{
|
||||
ID: "g3",
|
||||
Name: "group3",
|
||||
WorkGroupID: "wg1",
|
||||
ParentID: "g1",
|
||||
Tags: []string{"special"},
|
||||
}
|
||||
|
||||
fb.groups = append(fb.groups, group1, group2, group3)
|
||||
|
||||
dc1 := &Datacenter{
|
||||
ID: "dc1",
|
||||
@@ -74,7 +83,17 @@ func (fb *FakeBackend) Load() error {
|
||||
GroupID: "g2",
|
||||
DatacenterID: "dc2",
|
||||
}
|
||||
fb.hosts = append(fb.hosts, host)
|
||||
|
||||
host2 := &Host{
|
||||
ID: "h2",
|
||||
FQDN: "host2.example.com",
|
||||
Aliases: []string{"host2", "host2.i"},
|
||||
Tags: []string{},
|
||||
GroupID: "g3",
|
||||
DatacenterID: "dc2",
|
||||
}
|
||||
|
||||
fb.hosts = append(fb.hosts, host, host2)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -177,3 +196,51 @@ func TestStoreRelations(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestHostlist1(t *testing.T) {
|
||||
fb := newFB()
|
||||
fb.Load()
|
||||
|
||||
s, err := CreateStore(fb)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
hostlist, err := s.HostList([]rune("%group1#special"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(hostlist) != 1 {
|
||||
t.Errorf("hostlist %%group1#special is expected to contain exactly 1 element")
|
||||
return
|
||||
}
|
||||
|
||||
if hostlist[0] != "host2.example.com" {
|
||||
t.Errorf("host is expected to be host2.example.gom, got %s instead", hostlist[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostlist2(t *testing.T) {
|
||||
fb := newFB()
|
||||
fb.Load()
|
||||
|
||||
s, err := CreateStore(fb)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
hostlist, err := s.HostList([]rune("%group1#tag1"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(hostlist) != 2 {
|
||||
t.Errorf("hostlist %%group1#tag1 is expected to contain exactly 2 elements")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user