diff --git a/cmd/root.go b/cmd/root.go index 441b0fb..c162221 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,26 +1,42 @@ package cmd import ( + "bytes" "context" + yamlConfig "docker-netns/config" "fmt" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/client" "github.com/kardianos/service" + "github.com/kballard/go-shellquote" "github.com/spf13/cobra" + "github.com/vishvananda/netns" "log" "os" + "os/exec" + "path" + "runtime" + "syscall" ) +func init() { + rootCmd.Flags().StringVar(&configPath, "config", path.Join("/opt", appName, "config.yaml"), "YAML configuration file") +} + +const appName = "docker-netns" + var ( - logger service.Logger - rootCmd = &cobra.Command{ - Use: "docker-netns", - Short: "Docker network namespace manager", + configPath string + logger service.Logger + rootCmd = &cobra.Command{ + Use: appName, + Short: "Docker network namespace manager", Version: "1.0.0", Run: func(cmd *cobra.Command, args []string) { - prg := &program{} + prg := NewProgram() s, err := service.New(prg, svcConfig) + prg.service = s if err != nil { fmt.Fprintf(os.Stderr, "[service.New] %v\n", err) os.Exit(1) @@ -33,13 +49,14 @@ var ( err = s.Run() if err != nil { logger.Error(err) + os.Exit(1) } }, } svcConfig = &service.Config{ - Name: "docker-netns", + Name: "docker-netns", DisplayName: "Docker network namespace service", - UserName: "root", + UserName: "root", Dependencies: []string{ "After=network.target syslog.target docker.service", }, @@ -49,29 +66,131 @@ var ( } ) -type program struct {} +func nsContext(containerID string, callback func() (interface{}, error)) (interface{}, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + originNamespace, err := netns.Get() + if err != nil { + return nil, err + } + defer originNamespace.Close() + cli, err := client.NewClientWithOpts(client.WithVersion("1.40")) + if err != nil { + return nil, err + } + container, err := cli.ContainerInspect(context.Background(), containerID) + if err != nil { + return nil, err + } + ContainerNamespace, err := netns.GetFromPid(container.State.Pid) + if err != nil { + return nil, err + } + defer ContainerNamespace.Close() + err = netns.Set(ContainerNamespace) + if err != nil { + return nil, err + } + res, err := callback() + if err != nil { + return res, err + } + err = netns.Set(originNamespace) + if err != nil { + return nil, err + } + return res, nil +} + +func execCommands(containerID string, commands []string) error { + _, err := nsContext(containerID, func() (interface{}, error) { + for _, command := range commands { + command, err := shellquote.Split(command) + if err != nil { + return nil, err + } + execCmd := exec.Command(command[0], command[1:]...) + var stderr bytes.Buffer + execCmd.Stderr = &stderr + err = execCmd.Run() + if err != nil { + return nil, fmt.Errorf("%v: %v", err, stderr.String()) + } + } + return nil, nil + }) + return err +} + +type program struct { + service service.Service + ctx context.Context + cancel context.CancelFunc + exited chan error +} + +func NewProgram() *program { + ctx, cancel := context.WithCancel(context.Background()) + exited := make(chan error) + return &program{ctx: ctx, cancel: cancel, exited: exited} +} func (p *program) Start(s service.Service) error { // Start should not block. Do the actual work async. + config, err := yamlConfig.NewConfig(configPath) + if err != nil { + return err + } cli, err := client.NewClientWithOpts(client.WithVersion("1.40")) if err != nil { return err } - go p.run(cli) + go p.run(config, cli) return nil } -func (p *program) run(cli *client.Client) { - ctx := context.Background() +func (p *program) run(config *yamlConfig.Config, cli *client.Client) { + defer close(p.exited) + process, _ := os.FindProcess(os.Getpid()) + containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{}) + if err != nil { + process.Signal(syscall.SIGTERM) + p.exited <- err + return + } + for containerID := range *config { + for _, container := range containers { + if containerID == container.ID[:len(containerID)] { + err := execCommands(containerID, (*config)[containerID]) + if err != nil { + process.Signal(syscall.SIGTERM) + p.exited <- err + return + } + break + } + } + } + f := filters.NewArgs() f.Add("event", "start") - msgs, errs := cli.Events(ctx, types.EventsOptions{Filters: f}) + msgs, errs := cli.Events(p.ctx, types.EventsOptions{Filters: f}) for { select { - case msg := <-msgs: - _ = msg + case <-p.ctx.Done(): + return + case <-msgs: + for containerID := range *config { + err := execCommands(containerID, (*config)[containerID]) + if err != nil { + process.Signal(syscall.SIGTERM) + p.exited <- err + return + } + } case err := <-errs: - _ = err + process.Signal(syscall.SIGTERM) + p.exited <- err return } } @@ -79,7 +198,8 @@ func (p *program) run(cli *client.Client) { func (p *program) Stop(s service.Service) error { // Stop should not block. Return with a few seconds. - return nil + p.cancel() + return <-p.exited } func Execute() { diff --git a/cmd/service.go b/cmd/service.go index b67a5ad..085672c 100644 --- a/cmd/service.go +++ b/cmd/service.go @@ -4,30 +4,88 @@ import ( "fmt" "github.com/kardianos/service" "github.com/spf13/cobra" + "io/ioutil" "os" - "strings" + "path" ) func init() { - serviceCmd.Flags().StringP("action", "a", "", strings.Join(service.ControlAction[:], "|")) - serviceCmd.MarkFlagRequired("action") + installCmd.Flags().String("config", "./config.yaml", "YAML configuration file") + serviceCmd.AddCommand(startCmd, stopCmd, restartCmd, installCmd, uninstallCmd) rootCmd.AddCommand(serviceCmd) } -var serviceCmd = &cobra.Command{ - Use: "service", - Short: "Service management", - Run: func(cmd *cobra.Command, args []string) { - prg := &program{} +func serviceControl(action string) func(*cobra.Command, []string) { + return func(cmd *cobra.Command, args []string) { + prg := NewProgram() s, err := service.New(prg, svcConfig) + prg.service = s if err != nil { fmt.Fprintf(os.Stderr, "[service.New] %v\n", err) os.Exit(1) } - err = service.Control(s, cmd.Flag("action").Value.String()) + err = service.Control(s, action) if err != nil { fmt.Fprintf(os.Stderr, "[service.Control] %v\n", err) os.Exit(1) } - }, + } } + +var ( + serviceCmd = &cobra.Command{ + Use: "service", + Short: "Service management", + } + startCmd = &cobra.Command{ + Use: "start", + Short: "Start service", + Run: serviceControl("start"), + } + stopCmd = &cobra.Command{ + Use: "stop", + Short: "Stop service", + Run: serviceControl("stop"), + } + restartCmd = &cobra.Command{ + Use: "restart", + Short: "Restart service", + Run: serviceControl("restart"), + } + installCmd = &cobra.Command{ + Use: "install", + Short: "Install service", + Run: func(cmd *cobra.Command, args []string) { + // TODO: transaction + err := os.Mkdir(path.Join("/opt", appName), 0755) + if err != nil { + fmt.Fprintf(os.Stderr, "[os.Mkdir] %v\n", err) + os.Exit(1) + } + bytes, err := ioutil.ReadFile(cmd.Flag("config").Value.String()) + if err != nil { + fmt.Fprintf(os.Stderr, "[ioutil.ReadFile] %v\n", err) + os.Exit(1) + } + err = ioutil.WriteFile(path.Join("/opt", appName, "config.yaml"), bytes, 0644) + if err != nil { + fmt.Fprintf(os.Stderr, "[ioutil.WriteFile] %v\n", err) + os.Exit(1) + } + serviceControl("install")(cmd, args) + }, + } + uninstallCmd = &cobra.Command{ + Use: "uninstall", + Short: "Uninstall service", + Run: func(cmd *cobra.Command, args []string) { + // TODO: transaction + err := os.RemoveAll(path.Join("/opt", appName)) + if err != nil { + fmt.Fprintf(os.Stderr, "[ioutil.RemoveAll] %v\n", err) + os.Exit(1) + } + serviceControl("uninstall")(cmd, args) + }, + } +) diff --git a/cmd/shell.go b/cmd/shell.go index f949ccd..d896a1c 100644 --- a/cmd/shell.go +++ b/cmd/shell.go @@ -1,14 +1,10 @@ package cmd import ( - "context" "fmt" - "github.com/docker/docker/client" "github.com/spf13/cobra" - "github.com/vishvananda/netns" "os" "os/exec" - "runtime" ) func init() { @@ -21,49 +17,20 @@ var shellCmd = &cobra.Command{ Use: "shell", Short: "Start a shell in a specific network namespace", Run: func(cmd *cobra.Command, args []string) { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - originNamespace, err := netns.Get() - if err != nil { - fmt.Fprintf(os.Stderr, "[netns.Get] %v\n", err) - os.Exit(1) - } - defer originNamespace.Close() - cli, err := client.NewClientWithOpts(client.WithVersion("1.40")) - if err != nil { - fmt.Fprintf(os.Stderr, "[client.NewClientWithOpts] %v\n", err) - os.Exit(1) - } - container, err := cli.ContainerInspect(context.Background(), cmd.Flag("container").Value.String()) - if err != nil { - fmt.Fprintf(os.Stderr, "[cli.ContainerInspect] %v\n", err) - os.Exit(1) - } - println(container.State.Pid) - ContainerNamespace, err := netns.GetFromPid(container.State.Pid) - if err != nil { - fmt.Fprintf(os.Stderr, "[netns.GetFromPid] %v\n", err) - os.Exit(1) - } - defer ContainerNamespace.Close() - err = netns.Set(ContainerNamespace) - if err != nil { - fmt.Fprintf(os.Stderr, "[netns.Set] %v\n", err) - os.Exit(1) - } - shell := exec.Command(os.Getenv("SHELL")) - shell.Stdin = os.Stdin - shell.Stdout = os.Stdout - shell.Stderr = os.Stderr - err = shell.Run() + _, err := nsContext(cmd.Flag("container").Value.String(), func() (interface{}, error) { + shell := exec.Command(os.Getenv("SHELL")) + shell.Stdin = os.Stdin + shell.Stdout = os.Stdout + shell.Stderr = os.Stderr + err := shell.Run() + if err != nil { + return nil, err + } + return nil, nil + }) if err != nil { fmt.Fprintf(os.Stderr, "[shell.Run] %v\n", err) os.Exit(1) } - err = netns.Set(originNamespace) - if err != nil { - fmt.Fprintf(os.Stderr, "[netns.Set] %v\n", err) - os.Exit(1) - } }, } diff --git a/config.yaml b/config.yaml index a22885e..2688547 100644 --- a/config.yaml +++ b/config.yaml @@ -1,3 +1,2 @@ -d8b71122deaa: - - ip route add default via 192.168.1.254 dev eth0 - +360f9c13f2ab9: + - iptables -P OUTPUT DROP diff --git a/go.mod b/go.mod index b3cc1e9..f5f022d 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/docker/go-units v0.4.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/kardianos/service v1.2.0 + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect diff --git a/go.sum b/go.sum index 987ee92..d2c9028 100644 --- a/go.sum +++ b/go.sum @@ -27,15 +27,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/c-bata/go-prompt v0.2.6 h1:POP+nrHE+DfLYx370bedwNhsqmpCUynWPxuHi0C5vZI= -github.com/c-bata/go-prompt v0.2.6/go.mod h1:/LMAke8wD2FsNu9EXNdHxNLbd9MedkPnCdfpU9wwHfY= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/containerd/containerd v1.4.4 h1:rtRG4N6Ct7GNssATwgpvMGfnjnwfjnu/Zs9W3Ikzq+M= github.com/containerd/containerd v1.4.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= @@ -124,11 +116,11 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kardianos/service v1.2.0 h1:bGuZ/epo3vrt8IPC7mnKQolqFeYJb7Cs8Rk4PSOBB/g= github.com/kardianos/service v1.2.0/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= @@ -139,26 +131,9 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo= -github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= -github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -187,8 +162,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/term v1.2.0-beta.2 h1:L3y/h2jkuBVFdWiJvNfYfKmzcCnILw7mJWm2JQuMppw= -github.com/pkg/term v1.2.0-beta.2/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -285,16 +258,13 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -302,14 +272,8 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88= golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=