mirror of
https://github.com/kemko/xc.git
synced 2026-01-01 15:55:43 +03:00
hosts files
This commit is contained in:
@@ -176,6 +176,11 @@ func (x *completer) completeExec(line []rune) ([][]rune, int) {
|
|||||||
return x.completeTag(line[1:])
|
return x.completeTag(line[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(line) > 0 && line[0] == '&' {
|
||||||
|
comp, ll := completeFiles(line[1:])
|
||||||
|
return comp, ll + 1
|
||||||
|
}
|
||||||
|
|
||||||
return x.completeHost(line)
|
return x.completeHost(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ func (c *Cli) setupCmdHandlers() {
|
|||||||
c.handlers["version"] = c.doVersion
|
c.handlers["version"] = c.doVersion
|
||||||
c.handlers["goruntime"] = c.doGoruntime
|
c.handlers["goruntime"] = c.doGoruntime
|
||||||
c.handlers["natural_sort"] = c.doNaturalSort
|
c.handlers["natural_sort"] = c.doNaturalSort
|
||||||
|
c.handlers["_mem"] = c.doMemoryDump
|
||||||
|
|
||||||
commands := make([]string, len(c.handlers))
|
commands := make([]string, len(c.handlers))
|
||||||
i := 0
|
i := 0
|
||||||
@@ -74,6 +76,16 @@ func (c *Cli) doExit(name string, argsLine string, args ...string) {
|
|||||||
c.stopped = true
|
c.stopped = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cli) doMemoryDump(name string, argsLine string, args ...string) {
|
||||||
|
f, err := os.Create("/tmp/xcheap.dump")
|
||||||
|
if err != nil {
|
||||||
|
term.Errorf("Can't dump: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
debug.WriteHeapDump(f.Fd())
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Cli) doMode(name string, argsLine string, args ...string) {
|
func (c *Cli) doMode(name string, argsLine string, args ...string) {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
term.Errorf("Usage: mode <[serial,parallel,collapse]>\n")
|
term.Errorf("Usage: mode <[serial,parallel,collapse]>\n")
|
||||||
|
|||||||
@@ -252,7 +252,8 @@ with symlinks. It's more stable though.`,
|
|||||||
Every expression is a comma-separated list of tokens, where token may be
|
Every expression is a comma-separated list of tokens, where token may be
|
||||||
- a single host,
|
- a single host,
|
||||||
- a single group,
|
- a single group,
|
||||||
- a single workgroup,
|
- a single workgroup,
|
||||||
|
- a filename containing a list of hosts
|
||||||
and every item may optionally be limited to a particular datacenter, a given tag,
|
and every item may optionally be limited to a particular datacenter, a given tag,
|
||||||
or even be completely excluded from the list.
|
or even be completely excluded from the list.
|
||||||
|
|
||||||
@@ -263,8 +264,9 @@ Some self-explanatory examples:
|
|||||||
%group1,-host2 - all hosts from group1, excluding(!) host2
|
%group1,-host2 - all hosts from group1, excluding(!) host2
|
||||||
%group2@dc1 - all hosts from group2, located in datacenter dc1
|
%group2@dc1 - all hosts from group2, located in datacenter dc1
|
||||||
*myworkgroup@dc2,-%group3,host5 - all hosts from wg "myworkgroup" excluding hosts from group3, plus host5
|
*myworkgroup@dc2,-%group3,host5 - all hosts from wg "myworkgroup" excluding hosts from group3, plus host5
|
||||||
%group5#tag1 - all hosts from group5 tagged with tag1
|
%group5#tag1 - all hosts from group5 tagged with tag1
|
||||||
|
&hosts.txt - hosts from file hosts.txt
|
||||||
|
|
||||||
You may combine any number of tokens keeping in mind that they are resolved left to right, so exclusions
|
You may combine any number of tokens keeping in mind that they are resolved left to right, so exclusions
|
||||||
almost always should be on the righthand side. For example, "-host1,host1" will end up with host1 in list
|
almost always should be on the righthand side. For example, "-host1,host1" will end up with host1 in list
|
||||||
despite being excluded previously.`,
|
despite being excluded previously.`,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -9,12 +10,17 @@ import (
|
|||||||
"github.com/viert/xc/backend/inventoree"
|
"github.com/viert/xc/backend/inventoree"
|
||||||
"github.com/viert/xc/backend/localini"
|
"github.com/viert/xc/backend/localini"
|
||||||
|
|
||||||
|
_ "net/http/pprof"
|
||||||
|
|
||||||
"github.com/viert/xc/cli"
|
"github.com/viert/xc/cli"
|
||||||
"github.com/viert/xc/config"
|
"github.com/viert/xc/config"
|
||||||
"github.com/viert/xc/term"
|
"github.com/viert/xc/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
go http.ListenAndServe(":5001", nil)
|
||||||
|
|
||||||
var tool *cli.Cli
|
var tool *cli.Cli
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ const (
|
|||||||
tTypeGroup
|
tTypeGroup
|
||||||
tTypeWorkGroup
|
tTypeWorkGroup
|
||||||
tTypeHostRegexp
|
tTypeHostRegexp
|
||||||
|
tTypeHostListFile
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -25,6 +26,7 @@ const (
|
|||||||
stateReadTag
|
stateReadTag
|
||||||
stateReadHostBracePattern
|
stateReadHostBracePattern
|
||||||
stateReadRegexp
|
stateReadRegexp
|
||||||
|
stateReadHostListFile
|
||||||
)
|
)
|
||||||
|
|
||||||
type token struct {
|
type token struct {
|
||||||
@@ -83,6 +85,12 @@ func parseExpression(expr []rune) ([]*token, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sym == '&' {
|
||||||
|
ct.Type = tTypeHostListFile
|
||||||
|
state = stateReadHostListFile
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if sym == '/' || sym == '~' {
|
if sym == '/' || sym == '~' {
|
||||||
state = stateReadHost
|
state = stateReadHost
|
||||||
ct.Type = tTypeHostRegexp
|
ct.Type = tTypeHostRegexp
|
||||||
@@ -214,6 +222,19 @@ func parseExpression(expr []rune) ([]*token, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ct.Value += string(sym)
|
ct.Value += string(sym)
|
||||||
|
|
||||||
|
case stateReadHostListFile:
|
||||||
|
if sym == ',' || last {
|
||||||
|
if last && sym != ',' {
|
||||||
|
ct.Value += string(sym)
|
||||||
|
}
|
||||||
|
res = append(res, ct)
|
||||||
|
ct = newToken()
|
||||||
|
state = stateWait
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ct.Value += string(sym)
|
||||||
|
|
||||||
case stateReadHostBracePattern:
|
case stateReadHostBracePattern:
|
||||||
if sym == '{' {
|
if sym == '{' {
|
||||||
return nil, fmt.Errorf("nested patterns are not allowed (at %d)", i)
|
return nil, fmt.Errorf("nested patterns are not allowed (at %d)", i)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package store
|
package store
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -179,6 +181,22 @@ func (s *Store) HostList(expr []rune) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch token.Type {
|
switch token.Type {
|
||||||
|
case tTypeHostListFile:
|
||||||
|
filename := token.Value
|
||||||
|
f, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sc := bufio.NewScanner(f)
|
||||||
|
for sc.Scan() {
|
||||||
|
hostname := strings.Trim(sc.Text(), " \t\r\n")
|
||||||
|
if hostname == "" || strings.Contains(hostname, " ") || strings.HasPrefix(hostname, "#") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
etoken.hosts = append(etoken.hosts, hostname)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
|
||||||
case tTypeHostRegexp:
|
case tTypeHostRegexp:
|
||||||
for _, host := range s.matchHost(token.RegexpFilter) {
|
for _, host := range s.matchHost(token.RegexpFilter) {
|
||||||
etoken.hosts = append(etoken.hosts, host)
|
etoken.hosts = append(etoken.hosts, host)
|
||||||
|
|||||||
Reference in New Issue
Block a user