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  }