github.com/polvi/nsproxy@v0.0.0-20140119202807-96ac732fa7f3/nsproxy.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "log" 7 "net" 8 "os" 9 10 "github.com/codegangsta/cli" 11 "github.com/coreos/go-etcd/etcd" 12 nameNet "github.com/coreos/go-namespaces/net" 13 "github.com/coreos/go-namespaces/namespace" 14 ) 15 16 func proxyConn(conn *net.Conn, addr string) { 17 rConn, err := net.Dial("tcp", addr) 18 if err != nil { 19 log.Printf(err.Error()) 20 (*conn).Close() 21 return 22 } 23 24 go io.Copy(rConn, *conn) 25 go io.Copy(*conn, rConn) 26 } 27 28 func proxy(c *cli.Context) { 29 addr := c.String("addr") 30 namespacePid := c.Int("namespace-pid") 31 namespacePath := c.String("namespace-path") 32 if namespacePid == 0 && namespacePath == "" { 33 fmt.Fprintln(os.Stderr, "error: a namespace pid or path is required") 34 return 35 } 36 37 path := c.String("path") 38 if path == "" { 39 fmt.Fprintln(os.Stderr, "error: an etcd path is required") 40 return 41 } 42 43 if namespacePid != 0 { 44 p, err := namespace.ProcessPath(namespacePid, namespace.CLONE_NEWNET) 45 if err != nil { 46 panic(err) 47 } 48 namespacePath = p 49 } 50 51 peers := trimsplit(c.String("peers"), ",") 52 client := etcd.NewClient(peers) 53 54 log.Printf("Proxying for keys in %s on host %s", path, addr) 55 56 // Keep an eye on the backend path 57 b := backends{path: path} 58 err := b.Sync(client) 59 if err != nil { 60 log.Fatal(err) 61 } 62 63 go b.Watch(client) 64 65 log.Printf("Proxying for keys in %s on host %s in namespace %d", path, addr, namespacePath) 66 listener, err := nameNet.ListenNamespace(namespacePath, "tcp", addr) 67 68 if err != nil { 69 panic(err) 70 } 71 72 for { 73 // Wait for a connection. 74 conn, err := listener.Accept() 75 if err != nil { 76 log.Fatal(err) 77 } 78 79 next := b.Next() 80 if next == "" { 81 conn.Close() 82 log.Printf("No backends! Closing the connection") 83 continue 84 } 85 86 log.Printf("PROXY: targetAddr:%v addr:%v\n", addr, next) 87 go proxyConn(&conn, next) 88 } 89 } 90 91 func main() { 92 app := cli.NewApp() 93 app.Name = "nsproxy" 94 app.Usage = "Proxy into a network namespace" 95 app.Flags = []cli.Flag{ 96 cli.IntFlag{"namespace-pid, ns-pid", 0, "target namespace pid", false}, 97 cli.StringFlag{"namespace-path, ns-path", "", "target namespace path", false}, 98 cli.StringFlag{"path, p", "", "path to a etcd dir", false}, 99 cli.StringFlag{"addr, a", "127.0.0.1:8080", "target address inside the namespace", false}, 100 cli.StringFlag{"peers, C", "http://127.0.0.1:4001", "a comma seperated list of machine addresses in the etcd cluster", false}, 101 } 102 app.Action = proxy 103 app.Run(os.Args) 104 }