func (cdc *CassandraDockerConfig) renderFile(src, dest string) {
	in, err := os.Open(src)
	if err != nil {
		log.Fatalf("could not open '%s' for reading: %s\n", src, err)
	}
	defer in.Close()
	out, err := os.OpenFile(dest, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		log.Fatalf("could not open '%s' for write: %s\n", dest, err)
	}
	defer out.Close()
	cdc.render(in, out)
}
renderFile renders one file to another using text/template
package main
import (
	"bytes"
	"io"
	"io/ioutil"
	"log"
	"net"
	"os"
	"path"
	"path/filepath"
	"strings"
	"text/template"
	"github.com/tobert/sprok"
	"gopkg.in/yaml.v2"
)
const ugid = 1337
type CassandraDockerConfig struct {
	SrcConfDir     string    
	ConfDir        string    
	DataDir        string    
	CommitLogDir   string    
	LogDir         string    
	LibDir         string    
	SavedCachesDir string    
	CqlshDotDir    string    
	CqlshConf      string    
	CassandraYaml  string    
	SprokDir       string    
	ExtraArgs      []string  
	ClusterName      string  
	Seeds            string  
	CassandraLogfile string  
	DefaultIface     string  
	DefaultIP        string  
	JmxPort          string  
	HeapMB           int     
	NewMB            int     
	Snitch           string  
	DataCenter       string  
	Rack             string  
}
func main() {
	cdc := CassandraDockerConfig{
		SrcConfDir:       "/src/conf",
		ConfDir:          "/data/conf",
		DataDir:          "/data/data",
		CommitLogDir:     "/data/commitlog",
		LogDir:           "/data/log",
		LibDir:           "/data/lib",
		SavedCachesDir:   "/data/saved_caches",
		CqlshDotDir:      "/data/.cassandra",
		CqlshConf:        "/data/.cassandra/cqlshrc",
		CassandraYaml:    "/data/conf/cassandra.yaml",
		SprokDir:         "/data/conf/sproks",
		ClusterName:      "Docker Cluster",
		Seeds:            "127.0.0.1",
		CassandraLogfile: "/data/log/system.log",
		DefaultIface:     "eth0",
		DefaultIP:        "127.0.0.1",
		JmxPort:          "7199",
		HeapMB:           1024,
		NewMB:            256,
		Snitch:           "SimpleSnitch",
		DataCenter:       "DC1",
		Rack:             "RAC1",
	}
	var command, sprokFile string
	var args []string
	var dcOrRackSet bool
	if path.Base(os.Args[0]) != "cassandra-docker" {
		command = path.Base(os.Args[0])
		args = os.Args[1:]
	} else if len(os.Args) == 1 {
		command = "cassandra"
		args = []string{}
	} else if len(os.Args) > 1 {
		if strings.HasPrefix(os.Args[1], "-") {
			command = "cassandra"
			args = os.Args[1:]
		} else {
			command = os.Args[1]
			if len(os.Args) > 2 {
				args = os.Args[2:]
			} else {
				args = []string{}
			}
		}
	}
	switch command {
	case "cassandra":
		dcOrRackSet = topologySpecified(args)
		args, _, cdc.Seeds = extractArg(args, "seeds", "127.0.0.1")
		args, _, cdc.ClusterName = extractArg(args, "name", "Docker Cluster")
		args, _, cdc.HeapMB = extractIntArg(args, "heap", 1024)
		args, _, cdc.NewMB = extractIntArg(args, "new", 256)
		args, _, cdc.Snitch = extractArg(args, "snitch", "SimpleSnitch")
		args, _, cdc.DataCenter = extractArg(args, "dc", "DC1")
		args, _, cdc.Rack = extractArg(args, "rack", "RAC1")
		if cdc.HeapMB != 1024 && cdc.NewMB == 256 {
			cdc.NewMB = cdc.HeapMB / 4
		}
		if (dcOrRackSet) && cdc.Snitch == "SimpleSnitch" {
			cdc.Snitch = "GossipingPropertyFileSnitch"
		}
		sprokFile = path.Join(cdc.SprokDir, "cassandra.yaml")
	case "cqlsh":
		sprokFile = path.Join(cdc.SprokDir, "cqlsh.yaml")
	case "nodetool":
		args, _, cdc.JmxPort = extractArg(args, "p", "7199")
		sprokFile = path.Join(cdc.SprokDir, "nodetool.yaml")
	case "cassandra-stress":
		sprokFile = path.Join(cdc.SprokDir, "cassandra-stress.yaml")
	default:
		log.Fatalf("invalid command '%s'", command)
	}
	cdc.ExtraArgs = args
	cdc.guessDefaultIface()
	if strings.EqualFold(cdc.Seeds, "127.0.0.1") {
		cdc.Seeds = cdc.DefaultIP
	}
	cdc.mkdirs()
	cdc.tmplCopy()
	fd, err := os.Open(sprokFile)
	if err != nil {
		log.Fatalf("error opening '%s' for read: %s\n", sprokFile, err)
	}
	var data bytes.Buffer
	cdc.render(fd, &data)
	proc := sprok.NewProcess()
	err = yaml.Unmarshal(data.Bytes(), &proc)
	if err != nil {
		log.Fatalf("could not parse YAML in file '%s': %s\n", sprokFile, err)
	}
	proc.Exec()
}
func topologySpecified(args []string) bool {
	for _, arg := range args {
		if arg == "-dc" || arg == "-rack" {
			return true
		}
	}
	return false
}
func (cdc *CassandraDockerConfig) mkdirs() {
	mkdirAll(cdc.ConfDir)
	mkdirAll(cdc.DataDir)
	mkdirAll(cdc.CommitLogDir)
	mkdirAll(cdc.LogDir)
	mkdirAll(cdc.SavedCachesDir)
	mkdirAll(cdc.CqlshDotDir)
	mkdirAll(cdc.SprokDir)
	chownAll(cdc.DataDir)
	chownAll(cdc.CommitLogDir)
	chownAll(cdc.LogDir)
	chownAll(cdc.SavedCachesDir)
	chownAll(cdc.CqlshDotDir)
}
func (cdc *CassandraDockerConfig) tmplCopy() {
	walk := func(fromName string, fromFi os.FileInfo, err error) error {
		if err != nil {
			log.Fatalf("failed to find files in '%s': %s\n", cdc.SrcConfDir, err)
		}
		toName := strings.Replace(fromName, cdc.SrcConfDir, cdc.ConfDir, 1)
		if exists(toName) {
			return nil
		} else if strings.HasPrefix(path.Base(fromName), ".") {
			return nil
		} else if fromFi.IsDir() {
			if exists(toName) {
				return nil
			} else {
				mkdirAll(toName)
			}
		} else if fromFi.Mode().IsRegular() {
			if strings.HasSuffix(path.Dir(fromName), "sproks") {
				cp(fromName, toName)
			} else {
				cdc.renderFile(fromName, toName)
			}
		} else {
			log.Fatalf("unsupported file mode on file '%s'\n", fromName)
		}
		return nil
	}
	err := filepath.Walk(cdc.SrcConfDir, walk)
	if err != nil {
		log.Fatalf("tmplCopy() failed: %s\n", err)
	}
	if !exists(cdc.CqlshConf) {
		cdc.renderFile(path.Join(cdc.SrcConfDir, "cqlshrc"), cdc.CqlshConf)
	}
}