<commit_before>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/flannel/Godeps/_workspace/src/github.com/coreos/go-systemd/daemon"
	log "github.com/coreos/flannel/Godeps/_workspace/src/github.com/golang/glog"

	"github.com/coreos/flannel/backend"
	"github.com/coreos/flannel/backend/alloc"
	"github.com/coreos/flannel/backend/hostgw"
	"github.com/coreos/flannel/backend/udp"
	"github.com/coreos/flannel/backend/vxlan"
	"github.com/coreos/flannel/pkg/ip"
	"github.com/coreos/flannel/pkg/task"
	"github.com/coreos/flannel/subnet"
)

type CmdLineOpts struct {
	etcdEndpoints string
	etcdPrefix    string
	etcdKeyfile   string
	etcdCertfile  string
	etcdCAFile    string
	help          bool
	version       bool
	ipMasq        bool
	subnetFile    string
	iface         string
}

var opts CmdLineOpts

func init() {
	flag.StringVar(&opts.etcdEndpoints, "etcd-endpoints", "http://127.0.0.1:4001", "a comma-delimited list of etcd endpoints")
	flag.StringVar(&opts.etcdPrefix, "etcd-prefix", "/coreos.com/network", "etcd prefix")
	flag.StringVar(&opts.etcdKeyfile, "etcd-keyfile", "", "SSL key file used to secure etcd communication")
	flag.StringVar(&opts.etcdCertfile, "etcd-certfile", "", "SSL certification file used to secure etcd communication")
	flag.StringVar(&opts.etcdCAFile, "etcd-cafile", "", "SSL Certificate Authority file used to secure etcd communication")
	flag.StringVar(&opts.subnetFile, "subnet-file", "/run/flannel/subnet.env", "filename where env variables (subnet and MTU values) will be written to")
	flag.StringVar(&opts.iface, "iface", "", "interface to use (IP or name) for inter-host communication")
	flag.BoolVar(&opts.ipMasq, "ip-masq", false, "setup IP masquerade rule for traffic destined outside of overlay network")
	flag.BoolVar(&opts.help, "help", false, "print this message")
	flag.BoolVar(&opts.version, "version", false, "print version and exit")
}

// TODO: This is yet another copy (others found in etcd, fleet) -- Pull it out!
// flagsFromEnv parses all registered flags in the given flagset,
// and if they are not already set it attempts to set their values from
// environment variables. Environment variables take the name of the flag but
// are UPPERCASE, have the given prefix, and any dashes are replaced by
// underscores - for example: some-flag => PREFIX_SOME_FLAG
func flagsFromEnv(prefix string, fs *flag.FlagSet) {
	alreadySet := make(map[string]bool)
	fs.Visit(func(f *flag.Flag) {
		alreadySet[f.Name] = true
	})
	fs.VisitAll(func(f *flag.Flag) {
		if !alreadySet[f.Name] {
			key := strings.ToUpper(prefix + "_" + strings.Replace(f.Name, "-", "_", -1))
			val := os.Getenv(key)
			if val != "" {
				fs.Set(f.Name, val)
			}
		}
	})
}

func writeSubnetFile(sn *backend.SubnetDef) error {
	// Write out the first usable IP by incrementing
	// sn.IP by one
	sn.Net.IP += 1

	dir, name := filepath.Split(opts.subnetFile)
	os.MkdirAll(dir, 0755)

	tempFile := filepath.Join(dir, "."+name)
	f, err := os.Create(tempFile)
	if err != nil {
		return err
	}

	fmt.Fprintf(f, "FLANNEL_SUBNET=%s\n", sn.Net)
	fmt.Fprintf(f, "FLANNEL_MTU=%d\n", sn.MTU)
	_, err = fmt.Fprintf(f, "FLANNEL_IPMASQ=%v\n", opts.ipMasq)
	f.Close()
	if err != nil {
		return err
	}

	// rename(2) the temporary file to the desired location so that it becomes
	// atomically visible with the contents
	return os.Rename(tempFile, opts.subnetFile)
}

func lookupIface() (*net.Interface, net.IP, error) {
	var iface *net.Interface
	var ipaddr net.IP
	var err error

	if len(opts.iface) > 0 {
		if ipaddr = net.ParseIP(opts.iface); ipaddr != nil {
			iface, err = ip.GetInterfaceByIP(ipaddr)
			if err != nil {
				return nil, nil, fmt.Errorf("Error looking up interface %s: %s", opts.iface, err)
			}
		} else {
			iface, err = net.InterfaceByName(opts.iface)
			if err != nil {
				return nil, nil, fmt.Errorf("Error looking up interface %s: %s", opts.iface, err)
			}
		}
	} else {
		log.Info("Determining IP address of default interface")
		if iface, err = ip.GetDefaultGatewayIface(); err != nil {
			return nil, nil, fmt.Errorf("Failed to get default interface: %s", err)
		}
	}

	if ipaddr == nil {
		ipaddr, err = ip.GetIfaceIP4Addr(iface)
		if err != nil {
			return nil, nil, fmt.Errorf("Failed to find IPv4 address for interface %s", iface.Name)
		}
	}

	return iface, ipaddr, nil
}

func newSubnetManager() *subnet.SubnetManager {
	peers := strings.Split(opts.etcdEndpoints, ",")

	cfg := &subnet.EtcdConfig{
		Endpoints: peers,
		Keyfile:   opts.etcdKeyfile,
		Certfile:  opts.etcdCertfile,
		CAFile:    opts.etcdCAFile,
		Prefix:    opts.etcdPrefix,
	}

	for {
		sm, err := subnet.NewSubnetManager(cfg)
		if err == nil {
			return sm
		}

		log.Error("Failed to create SubnetManager: ", err)
		time.Sleep(time.Second)
	}
}

func newBackend(sm *subnet.SubnetManager) (backend.Backend, error) {
	config := sm.GetConfig()

	var bt struct {
		Type string
	}

	if len(config.Backend) == 0 {
		bt.Type = "udp"
	} else {
		if err := json.Unmarshal(config.Backend, &bt); err != nil {
			return nil, fmt.Errorf("Error decoding Backend property of config: %v", err)
		}
	}

	switch strings.ToLower(bt.Type) {
	case "udp":
		return udp.New(sm, config.Backend), nil
	case "alloc":
		return alloc.New(sm), nil
	case "host-gw":
		return hostgw.New(sm), nil
	case "vxlan":
		return vxlan.New(sm, config.Backend), nil
	default:
		return nil, fmt.Errorf("'%v': unknown backend type", bt.Type)
	}
}

func run(sm *subnet.SubnetManager, be backend.Backend, exit chan int) {
	var err error
	defer func() {
		if err == nil || err == task.ErrCanceled {
			exit <- 0
		} else {
			log.Error(err)
			exit <- 1
		}
	}()

	iface, ipaddr, err := lookupIface()
	if err != nil {
		return
	}

	if iface.MTU == 0 {
		err = fmt.Errorf("Failed to determine MTU for %s interface", ipaddr)
		return
	}

	log.Infof("Using %s as external interface", ipaddr)

	sn, err := be.Init(iface, ipaddr)
	if err != nil {
		return
	}

	if opts.ipMasq {
		flannelNet := sm.GetConfig().Network
		if err = setupIPMasq(flannelNet); err != nil {
			return
		}
	}

	writeSubnetFile(sn)
	daemon.SdNotify("READY=1")

	log.Infof("%s mode initialized", be.Name())
	be.Run()
}

func main() {
	// glog will log to tmp files by default. override so all entries
	// can flow into journald (if running under systemd)
	flag.Set("logtostderr", "true")

	// now parse command line args
	flag.Parse()

	if opts.help {
		fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]...\n", os.Args[0])
		flag.PrintDefaults()
		os.Exit(0)
	}

	if opts.version {
		fmt.Fprintln(os.Stderr, Version)
		os.Exit(0)
	}

	flagsFromEnv("FLANNELD", flag.CommandLine)

	sm := newSubnetManager()
	be, err := newBackend(sm)
	if err != nil {
		log.Info(err)
		os.Exit(1)
	}

	// Register for SIGINT and SIGTERM and wait for one of them to arrive
	log.Info("Installing signal handlers")
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)

	exit := make(chan int)
	go run(sm, be, exit)

	for {
		select {
		case <-sigs:
			// unregister to get default OS nuke behaviour in case we don't exit cleanly
			signal.Stop(sigs)

			log.Info("Exiting...")
			be.Stop()

		case code := <-exit:
			log.Infof("%s mode exited", be.Name())
			os.Exit(code)
		}
	}
}
<commit_msg>updated to try both new and old etcd ports<commit_after>// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/flannel/Godeps/_workspace/src/github.com/coreos/go-systemd/daemon"
	log "github.com/coreos/flannel/Godeps/_workspace/src/github.com/golang/glog"

	"github.com/coreos/flannel/backend"
	"github.com/coreos/flannel/backend/alloc"
	"github.com/coreos/flannel/backend/hostgw"
	"github.com/coreos/flannel/backend/udp"
	"github.com/coreos/flannel/backend/vxlan"
	"github.com/coreos/flannel/pkg/ip"
	"github.com/coreos/flannel/pkg/task"
	"github.com/coreos/flannel/subnet"
)

type CmdLineOpts struct {
	etcdEndpoints string
	etcdPrefix    string
	etcdKeyfile   string
	etcdCertfile  string
	etcdCAFile    string
	help          bool
	version       bool
	ipMasq        bool
	subnetFile    string
	iface         string
}

var opts CmdLineOpts

func init() {
	flag.StringVar(&opts.etcdEndpoints, "etcd-endpoints", "http://127.0.0.1:4001,http://localhost:2379", "a comma-delimited list of etcd endpoints")
	flag.StringVar(&opts.etcdPrefix, "etcd-prefix", "/coreos.com/network", "etcd prefix")
	flag.StringVar(&opts.etcdKeyfile, "etcd-keyfile", "", "SSL key file used to secure etcd communication")
	flag.StringVar(&opts.etcdCertfile, "etcd-certfile", "", "SSL certification file used to secure etcd communication")
	flag.StringVar(&opts.etcdCAFile, "etcd-cafile", "", "SSL Certificate Authority file used to secure etcd communication")
	flag.StringVar(&opts.subnetFile, "subnet-file", "/run/flannel/subnet.env", "filename where env variables (subnet and MTU values) will be written to")
	flag.StringVar(&opts.iface, "iface", "", "interface to use (IP or name) for inter-host communication")
	flag.BoolVar(&opts.ipMasq, "ip-masq", false, "setup IP masquerade rule for traffic destined outside of overlay network")
	flag.BoolVar(&opts.help, "help", false, "print this message")
	flag.BoolVar(&opts.version, "version", false, "print version and exit")
}

// TODO: This is yet another copy (others found in etcd, fleet) -- Pull it out!
// flagsFromEnv parses all registered flags in the given flagset,
// and if they are not already set it attempts to set their values from
// environment variables. Environment variables take the name of the flag but
// are UPPERCASE, have the given prefix, and any dashes are replaced by
// underscores - for example: some-flag => PREFIX_SOME_FLAG
func flagsFromEnv(prefix string, fs *flag.FlagSet) {
	alreadySet := make(map[string]bool)
	fs.Visit(func(f *flag.Flag) {
		alreadySet[f.Name] = true
	})
	fs.VisitAll(func(f *flag.Flag) {
		if !alreadySet[f.Name] {
			key := strings.ToUpper(prefix + "_" + strings.Replace(f.Name, "-", "_", -1))
			val := os.Getenv(key)
			if val != "" {
				fs.Set(f.Name, val)
			}
		}
	})
}

func writeSubnetFile(sn *backend.SubnetDef) error {
	// Write out the first usable IP by incrementing
	// sn.IP by one
	sn.Net.IP += 1

	dir, name := filepath.Split(opts.subnetFile)
	os.MkdirAll(dir, 0755)

	tempFile := filepath.Join(dir, "."+name)
	f, err := os.Create(tempFile)
	if err != nil {
		return err
	}

	fmt.Fprintf(f, "FLANNEL_SUBNET=%s\n", sn.Net)
	fmt.Fprintf(f, "FLANNEL_MTU=%d\n", sn.MTU)
	_, err = fmt.Fprintf(f, "FLANNEL_IPMASQ=%v\n", opts.ipMasq)
	f.Close()
	if err != nil {
		return err
	}

	// rename(2) the temporary file to the desired location so that it becomes
	// atomically visible with the contents
	return os.Rename(tempFile, opts.subnetFile)
}

func lookupIface() (*net.Interface, net.IP, error) {
	var iface *net.Interface
	var ipaddr net.IP
	var err error

	if len(opts.iface) > 0 {
		if ipaddr = net.ParseIP(opts.iface); ipaddr != nil {
			iface, err = ip.GetInterfaceByIP(ipaddr)
			if err != nil {
				return nil, nil, fmt.Errorf("Error looking up interface %s: %s", opts.iface, err)
			}
		} else {
			iface, err = net.InterfaceByName(opts.iface)
			if err != nil {
				return nil, nil, fmt.Errorf("Error looking up interface %s: %s", opts.iface, err)
			}
		}
	} else {
		log.Info("Determining IP address of default interface")
		if iface, err = ip.GetDefaultGatewayIface(); err != nil {
			return nil, nil, fmt.Errorf("Failed to get default interface: %s", err)
		}
	}

	if ipaddr == nil {
		ipaddr, err = ip.GetIfaceIP4Addr(iface)
		if err != nil {
			return nil, nil, fmt.Errorf("Failed to find IPv4 address for interface %s", iface.Name)
		}
	}

	return iface, ipaddr, nil
}

func newSubnetManager() *subnet.SubnetManager {
	peers := strings.Split(opts.etcdEndpoints, ",")

	cfg := &subnet.EtcdConfig{
		Endpoints: peers,
		Keyfile:   opts.etcdKeyfile,
		Certfile:  opts.etcdCertfile,
		CAFile:    opts.etcdCAFile,
		Prefix:    opts.etcdPrefix,
	}

	for {
		sm, err := subnet.NewSubnetManager(cfg)
		if err == nil {
			return sm
		}

		log.Error("Failed to create SubnetManager: ", err)
		time.Sleep(time.Second)
	}
}

func newBackend(sm *subnet.SubnetManager) (backend.Backend, error) {
	config := sm.GetConfig()

	var bt struct {
		Type string
	}

	if len(config.Backend) == 0 {
		bt.Type = "udp"
	} else {
		if err := json.Unmarshal(config.Backend, &bt); err != nil {
			return nil, fmt.Errorf("Error decoding Backend property of config: %v", err)
		}
	}

	switch strings.ToLower(bt.Type) {
	case "udp":
		return udp.New(sm, config.Backend), nil
	case "alloc":
		return alloc.New(sm), nil
	case "host-gw":
		return hostgw.New(sm), nil
	case "vxlan":
		return vxlan.New(sm, config.Backend), nil
	default:
		return nil, fmt.Errorf("'%v': unknown backend type", bt.Type)
	}
}

func run(sm *subnet.SubnetManager, be backend.Backend, exit chan int) {
	var err error
	defer func() {
		if err == nil || err == task.ErrCanceled {
			exit <- 0
		} else {
			log.Error(err)
			exit <- 1
		}
	}()

	iface, ipaddr, err := lookupIface()
	if err != nil {
		return
	}

	if iface.MTU == 0 {
		err = fmt.Errorf("Failed to determine MTU for %s interface", ipaddr)
		return
	}

	log.Infof("Using %s as external interface", ipaddr)

	sn, err := be.Init(iface, ipaddr)
	if err != nil {
		return
	}

	if opts.ipMasq {
		flannelNet := sm.GetConfig().Network
		if err = setupIPMasq(flannelNet); err != nil {
			return
		}
	}

	writeSubnetFile(sn)
	daemon.SdNotify("READY=1")

	log.Infof("%s mode initialized", be.Name())
	be.Run()
}

func main() {
	// glog will log to tmp files by default. override so all entries
	// can flow into journald (if running under systemd)
	flag.Set("logtostderr", "true")

	// now parse command line args
	flag.Parse()

	if opts.help {
		fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]...\n", os.Args[0])
		flag.PrintDefaults()
		os.Exit(0)
	}

	if opts.version {
		fmt.Fprintln(os.Stderr, Version)
		os.Exit(0)
	}

	flagsFromEnv("FLANNELD", flag.CommandLine)

	sm := newSubnetManager()
	be, err := newBackend(sm)
	if err != nil {
		log.Info(err)
		os.Exit(1)
	}

	// Register for SIGINT and SIGTERM and wait for one of them to arrive
	log.Info("Installing signal handlers")
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)

	exit := make(chan int)
	go run(sm, be, exit)

	for {
		select {
		case <-sigs:
			// unregister to get default OS nuke behaviour in case we don't exit cleanly
			signal.Stop(sigs)

			log.Info("Exiting...")
			be.Stop()

		case code := <-exit:
			log.Infof("%s mode exited", be.Name())
			os.Exit(code)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"

	"github.com/vbatts/tar-split/archive/tar"
)

func main() {
	flag.Parse()
	log.SetOutput(os.Stderr)
	for _, arg := range flag.Args() {
		func() {
			// Open the tar archive
			fh, err := os.Open(arg)
			if err != nil {
				log.Fatal(err, arg)
			}
			defer fh.Close()

			output, err := os.Create(fmt.Sprintf("%s.out", arg))
			if err != nil {
				log.Fatal(err)
			}
			defer output.Close()
			log.Printf("writing %q to %q", fh.Name(), output.Name())

			fi, err := fh.Stat()
			if err != nil {
				log.Fatal(err, fh.Name())
			}
			size := fi.Size()
			var sum int64
			tr := tar.NewReader(fh)
			tr.RawAccounting = true
			for {
				hdr, err := tr.Next()
				if err != nil {
					if err != io.EOF {
						log.Println(err)
					}
					// even when an EOF is reached, there is often 1024 null bytes on
					// the end of an archive. Collect them too.
					post := tr.RawBytes()
					output.Write(post)
					sum += int64(len(post))
					break
				}

				pre := tr.RawBytes()
				output.Write(pre)
				sum += int64(len(pre))

				var i int64
				if i, err = io.Copy(output, tr); err != nil {
					log.Println(err)
					break
				}
				sum += i

				post := tr.RawBytes()
				output.Write(post)
				sum += int64(len(post))

				fmt.Println(hdr.Name, "pre:", len(pre), "read:", i, "post:", len(post))
			}

			// it is allowable, and not uncommon that there is further padding on the
			// end of an archive, apart from the expected 1024 null bytes
			remainder, err := ioutil.ReadAll(fh)
			if err != nil && err != io.EOF {
				log.Fatal(err, fh.Name())
			}
			output.Write(remainder)
			sum += int64(len(remainder))

			if size != sum {
				fmt.Printf("Size: %d; Sum: %d; Diff: %d\n", size, sum, size-sum)
				fmt.Printf("Compare like `cmp -bl %s %s | less`\n", fh.Name(), output.Name())
			} else {
				fmt.Printf("Size: %d; Sum: %d\n", size, sum)
			}
		}()
	}
}
<commit_msg>main.go: explicit build of main.go<commit_after>// +build ignore

package main

import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"

	"github.com/vbatts/tar-split/archive/tar"
)

func main() {
	flag.Parse()
	log.SetOutput(os.Stderr)
	for _, arg := range flag.Args() {
		func() {
			// Open the tar archive
			fh, err := os.Open(arg)
			if err != nil {
				log.Fatal(err, arg)
			}
			defer fh.Close()

			output, err := os.Create(fmt.Sprintf("%s.out", arg))
			if err != nil {
				log.Fatal(err)
			}
			defer output.Close()
			log.Printf("writing %q to %q", fh.Name(), output.Name())

			fi, err := fh.Stat()
			if err != nil {
				log.Fatal(err, fh.Name())
			}
			size := fi.Size()
			var sum int64
			tr := tar.NewReader(fh)
			tr.RawAccounting = true
			for {
				hdr, err := tr.Next()
				if err != nil {
					if err != io.EOF {
						log.Println(err)
					}
					// even when an EOF is reached, there is often 1024 null bytes on
					// the end of an archive. Collect them too.
					post := tr.RawBytes()
					output.Write(post)
					sum += int64(len(post))
					break
				}

				pre := tr.RawBytes()
				output.Write(pre)
				sum += int64(len(pre))

				var i int64
				if i, err = io.Copy(output, tr); err != nil {
					log.Println(err)
					break
				}
				sum += i

				post := tr.RawBytes()
				output.Write(post)
				sum += int64(len(post))

				fmt.Println(hdr.Name, "pre:", len(pre), "read:", i, "post:", len(post))
			}

			// it is allowable, and not uncommon that there is further padding on the
			// end of an archive, apart from the expected 1024 null bytes
			remainder, err := ioutil.ReadAll(fh)
			if err != nil && err != io.EOF {
				log.Fatal(err, fh.Name())
			}
			output.Write(remainder)
			sum += int64(len(remainder))

			if size != sum {
				fmt.Printf("Size: %d; Sum: %d; Diff: %d\n", size, sum, size-sum)
				fmt.Printf("Compare like `cmp -bl %s %s | less`\n", fh.Name(), output.Name())
			} else {
				fmt.Printf("Size: %d; Sum: %d\n", size, sum)
			}
		}()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"flag"
	"fmt"
	"log"
	"os"
	"sync"

	_ "github.com/go-sql-driver/mysql"
)

const (
	// Timeout for DNS queries
	timeout = 3 * 1e9

	// maximum number of attempts for a query
	maxAttempts = 3
)

var (
	pending         = make(chan *job, 100)
	finished        = make(chan *job, 100)
	pendingWg       sync.WaitGroup
	finishedWg      sync.WaitGroup
	workersCount    = 32
	referenceServer = "8.8.8.8"
	connection      string
	domainArg       string
)

func main() {
	databaseArg := flag.String("database", "database.yml", "Path to file containing the database configuration")
	flag.StringVar(&domainArg, "domains", "domains.txt", "Path to file containing the domain list")
	flag.StringVar(&geoDbPath, "geodb", "GeoLite2-City.mmdb", "Path to GeoDB database")
	flag.StringVar(&referenceServer, "reference", referenceServer, "The nameserver that every other is compared with")
	flag.IntVar(&workersCount, "workers", workersCount, "Number of worker routines")
	flag.Parse()

	dnsClient.ReadTimeout = timeout

	environment := os.Getenv("RAILS_ENV")
	if environment == "" {
		environment = "development"
	}

	// read domain list
	if err := readDomains(domainArg); err != nil {
		fmt.Println("unable to read domain list")
		panic(err)
	}

	// load database configuration
	connection = databasePath(*databaseArg, environment)

	// check the GeoDB
	location(referenceServer)

	// Get results from the reference nameserver
	res, _, err := resolveDomains(referenceServer)
	if err != nil {
		panic(err)
	}
	expectedResults = res

	// Start result writer
	finishedWg.Add(1)
	go resultWriter()

	// Start workers
	pendingWg.Add(workersCount)
	for i := 0; i < workersCount; i++ {
		go worker()
	}

	createJobs()

	// wait for workers to finish
	pendingWg.Wait()

	close(finished)
	finishedWg.Wait()
}

func createJobs() {
	currentID := 0
	batchSize := 1000
	found := batchSize

	// Open SQL connection
	db, err := sql.Open("mysql", connection)
	if err != nil {
		panic(err)
	}
	defer db.Close()

	for batchSize == found {
		// Read the next batch
		rows, err := db.Query("SELECT id, ip FROM nameservers WHERE id > ? LIMIT ?", currentID, batchSize)
		if err != nil {
			panic(err)
		}

		found = 0
		for rows.Next() {
			j := new(job)

			// get RawBytes from data
			err = rows.Scan(&j.id, &j.address)
			if err != nil {
				panic(err)
			}
			pending <- j
			currentID = j.id
			found++
		}
		rows.Close()
	}
	close(pending)
}

func worker() {
	for job := range pending {
		executeJob(job)
		finished <- job
	}
	pendingWg.Done()
}

func resultWriter() {
	// Open SQL connection
	db, err := sql.Open("mysql", connection)
	if err != nil {
		panic(err)
	}
	defer db.Close()

	stm, err := db.Prepare("UPDATE nameservers SET name=?, state=?, error=?, version=?, dnssec=?, checked_at=NOW(), country_id=?, city=? WHERE id=?")
	defer stm.Close()

	for res := range finished {
		log.Println(res)
		stm.Exec(res.name, res.state, res.err, res.version, res.dnssec, res.country, res.city, res.id)
	}

	finishedWg.Done()
}

// consumes a job and writes the result in the given job
func executeJob(job *job) {
	// GeoDB lookup
	job.country, job.city = location(job.address)

	// Run the check
	dnssec, err := check(job)
	job.name = ptrName(job.address)

	// query the bind version
	if err == nil || err.Error() != "i/o timeout" {
		job.version = version(job.address)
	}

	if err == nil {
		job.state = "valid"
		job.err = ""
		job.dnssec = &dnssec
	} else {
		job.state = "invalid"
		job.err = err.Error()
	}
}
<commit_msg>Improve logging (a bit)<commit_after>package main

import (
	"database/sql"
	"flag"
	"fmt"
	"log"
	"os"
	"sync"

	_ "github.com/go-sql-driver/mysql"
)

const (
	// Timeout for DNS queries
	timeout = 3 * 1e9

	// maximum number of attempts for a query
	maxAttempts = 3
)

var (
	pending         = make(chan *job, 100)
	finished        = make(chan *job, 100)
	pendingWg       sync.WaitGroup
	finishedWg      sync.WaitGroup
	workersCount    = 32
	referenceServer = "8.8.8.8"
	connection      string
	domainArg       string
	verbose         bool
	syslog          bool
)

func main() {
	databaseArg := flag.String("database", "database.yml", "Path to file containing the database configuration")
	flag.StringVar(&domainArg, "domains", "domains.txt", "Path to file containing the domain list")
	flag.StringVar(&geoDbPath, "geodb", "GeoLite2-City.mmdb", "Path to GeoDB database")
	flag.StringVar(&referenceServer, "reference", referenceServer, "The nameserver that every other is compared with")
	flag.IntVar(&workersCount, "workers", workersCount, "Number of worker routines")
	flag.BoolVar(&verbose, "verbose", verbose, "Increase logging output")
	flag.BoolVar(&syslog, "syslog", syslog, "Prepare logging for syslog (print to stdout, no timestamps)")
	flag.Parse()

	if syslog {
		log.SetOutput(os.Stdout)
		log.SetFlags(0)
	}

	dnsClient.ReadTimeout = timeout

	environment := os.Getenv("RAILS_ENV")
	if environment == "" {
		environment = "development"
	}

	// read domain list
	if err := readDomains(domainArg); err != nil {
		fmt.Println("unable to read domain list")
		panic(err)
	}

	// load database configuration
	connection = databasePath(*databaseArg, environment)

	// check the GeoDB
	location(referenceServer)

	// Get results from the reference nameserver
	res, _, err := resolveDomains(referenceServer)
	if err != nil {
		panic(err)
	}
	expectedResults = res

	// Start result writer
	finishedWg.Add(1)
	go resultWriter()

	// Start workers
	pendingWg.Add(workersCount)
	for i := 0; i < workersCount; i++ {
		go worker()
	}

	createJobs()

	// wait for workers to finish
	pendingWg.Wait()

	close(finished)
	finishedWg.Wait()
}

func createJobs() {
	currentID := 0
	batchSize := 1000
	found := batchSize

	// Open SQL connection
	db, err := sql.Open("mysql", connection)
	if err != nil {
		panic(err)
	}
	defer db.Close()

	for batchSize == found {
		// Read the next batch
		rows, err := db.Query("SELECT id, ip FROM nameservers WHERE id > ? LIMIT ?", currentID, batchSize)
		if err != nil {
			panic(err)
		}

		found = 0
		for rows.Next() {
			j := new(job)

			// get RawBytes from data
			err = rows.Scan(&j.id, &j.address)
			if err != nil {
				panic(err)
			}
			pending <- j
			currentID = j.id
			found++
		}
		rows.Close()
	}
	close(pending)
}

func worker() {
	for job := range pending {
		executeJob(job)
		finished <- job
	}
	pendingWg.Done()
}

func resultWriter() {
	// Open SQL connection
	db, err := sql.Open("mysql", connection)
	if err != nil {
		panic(err)
	}
	defer db.Close()

	stm, err := db.Prepare("UPDATE nameservers SET name=?, state=?, error=?, version=?, dnssec=?, checked_at=NOW(), country_id=?, city=? WHERE id=?")
	defer stm.Close()

	for res := range finished {
		if verbose {
			log.Println(res)
		}
		stm.Exec(res.name, res.state, res.err, res.version, res.dnssec, res.country, res.city, res.id)
	}

	finishedWg.Done()
}

// consumes a job and writes the result in the given job
func executeJob(job *job) {
	// GeoDB lookup
	job.country, job.city = location(job.address)

	// Run the check
	dnssec, err := check(job)
	job.name = ptrName(job.address)

	// query the bind version
	if err == nil || err.Error() != "i/o timeout" {
		job.version = version(job.address)
	}

	if err == nil {
		job.state = "valid"
		job.err = ""
		job.dnssec = &dnssec
	} else {
		job.state = "invalid"
		job.err = err.Error()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"golang.org/x/build/kubernetes/api"
	"log"
	"net/http"
	"os"
	"time"
)

type Stream struct {
	Type  string    `json:"type,omitempty"`
	Event api.Event `json:"object"`
}

func main() {
	apiAddr := os.Getenv("OPENSHIFT_API_URL")
	apiToken := os.Getenv("OPENSHIFT_TOKEN")

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest("GET", apiAddr+"/api/v1/events?watch=true", nil)
	if err != nil {
		log.Fatal("## Error while opening connection to openshift api", err)
	}
	req.Header.Add("Authorization", "Bearer "+apiToken)

	for {
		resp, err := client.Do(req)

		if err != nil {
			log.Println("## Error while connecting to:", apiAddr, err)
			time.Sleep(5 * time.Second)
			break
		}

		reader := bufio.NewReader(resp.Body)

		for {
			line, err := reader.ReadBytes('\n')
			if err != nil {
				log.Println("## Error reading from response stream.", err)
				break
			}

			event := Stream{}
			decErr := json.Unmarshal(line, &event)
			if decErr != nil {
				log.Println("## Error decoding json", err)
				break
			}

			fmt.Printf("%v | Project: %v | Name: %v | Kind: %v | Reason: %v | Message: %v\n",
				event.Event.LastTimestamp,
				event.Event.Namespace, event.Event.Name,
				event.Event.Kind, event.Event.Reason, event.Event.Message)
		}
	}
}

<commit_msg>Fixed break > continue<commit_after>package main

import (
	"bufio"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"golang.org/x/build/kubernetes/api"
	"log"
	"net/http"
	"os"
	"time"
)

type Stream struct {
	Type  string    `json:"type,omitempty"`
	Event api.Event `json:"object"`
}

func main() {
	apiAddr := os.Getenv("OPENSHIFT_API_URL")
	apiToken := os.Getenv("OPENSHIFT_TOKEN")

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest("GET", apiAddr+"/api/v1/events?watch=true", nil)
	if err != nil {
		log.Fatal("## Error while opening connection to openshift api", err)
	}
	req.Header.Add("Authorization", "Bearer "+apiToken)

	for {
		resp, err := client.Do(req)

		if err != nil {
			log.Println("## Error while connecting to:", apiAddr, err)
			time.Sleep(5 * time.Second)
			continue
		}

		reader := bufio.NewReader(resp.Body)

		for {
			line, err := reader.ReadBytes('\n')
			if err != nil {
				log.Println("## Error reading from response stream.", err)
				continue
			}

			event := Stream{}
			decErr := json.Unmarshal(line, &event)
			if decErr != nil {
				log.Println("## Error decoding json", err)
				continue
			}

			fmt.Printf("%v | Project: %v | Name: %v | Kind: %v | Reason: %v | Message: %v\n",
				event.Event.LastTimestamp,
				event.Event.Namespace, event.Event.Name,
				event.Event.Kind, event.Event.Reason, event.Event.Message)
		}
	}
}

<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"github.com/aduermael/crypto/ssh"
	"github.com/spf13/cobra"
)

var (
	// path to private key or empty to use default
	sshIdentityFile = ""
	// open a bash session by default, but different option can be used
	shell = "bash"
	// proxy mode (don't start shell session)
	proxyMode = false
)

func main() {

	rootCmd := &cobra.Command{
		Use:   "docker-tunnel [user@]host",
		Short: "Docker-tunnel connects you to remote Docker hosts using SSH tunnels",
		Run: func(cmd *cobra.Command, args []string) {
			if len(args) != 1 {
				cmd.Usage()
				return
			}

			sshClient, err := sshConnect(args[0], sshIdentityFile)
			if err != nil {
				log.Fatalln(err)
			}
			defer sshClient.Close()

			if proxyMode {
				ln, err := net.Listen("tcp", ":2375")
				if err != nil {
					log.Fatalln(err)
				}
				fmt.Println("listening on port 2375...")
				for {
					conn, err := ln.Accept()
					if err != nil {
						log.Fatalln(err)
					}
					go handleProxyConnection(conn, sshClient)
				}
				return
			}

			// proxyMode == false
			// open shell session, connected to remote Docker host

			socketPath := tmpSocketPath()

			ln, err := net.Listen("unix", socketPath)
			if err != nil {
				log.Fatalln(err)
			}
			defer os.RemoveAll(socketPath)

			// listen in background
			go func() {
				for {
					conn, err := ln.Accept()
					if err != nil {
						log.Fatalln(err)
					}
					go handleProxyConnection(conn, sshClient)
				}
			}()

			os.Setenv("PS1", "🐳  $ ")
			os.Setenv("DOCKER_HOST", "unix://"+socketPath)

			sh := exec.Command(shell)
			sh.Stdout = os.Stdout
			sh.Stderr = os.Stderr
			sh.Stdin = os.Stdin

			err = sh.Run()
			if err != nil {
				log.Fatalln(err.Error())
			}
		},
	}

	rootCmd.Flags().StringVarP(&sshIdentityFile, "sshid", "i", "", "path to private key")
	rootCmd.Flags().StringVarP(&shell, "shell", "s", "bash", "shell to open session")
	rootCmd.Flags().BoolVarP(&proxyMode, "proxy", "p", false, "proxy mode (don't start shell session)")

	if err := rootCmd.Execute(); err != nil {
		log.Fatalln(err.Error())
	}
}

func createTunnel(userAtHost string) (process *os.Process, socketPath string) {
	socketPath = tmpSocketPath()

	args := []string{
		"-nNT",
		"-o", "UserKnownHostsFile=/dev/null",
		"-o", "StrictHostKeyChecking=no",
		"-L", socketPath + ":/var/run/docker.sock",
	}

	// check if custom ssh id path should be used
	if sshIdentityFile != "" {
		args = append(args, "-i", sshIdentityFile)
	}

	args = append(args, userAtHost)

	cmd := exec.Command("ssh", args...)
	err := cmd.Start()
	if err != nil {
		log.Fatalln(err.Error())
	}

	// TODO: it fails sometimes...
	// Maybe we could wait for socket to be created
	// and eventually retry

	process = cmd.Process
	return
}

func tmpSocketPath() string {
	randBytes := make([]byte, 16)
	rand.Read(randBytes)
	return filepath.Join(os.TempDir(), "docker-"+hex.EncodeToString(randBytes)+".sock")
}

// func proxy(socketPath string) *httputil.ReverseProxy {
// 	u, err := url.Parse("http://unix.sock")
// 	if err != nil {
// 		log.Fatalln(err)
// 	}

// 	proxy := httputil.NewSingleHostReverseProxy(u)

// 	tr := &http.Transport{
// 		Dial: func(proto, addr string) (conn net.Conn, err error) {
// 			return net.Dial("unix", socketPath)
// 		},
// 	}
// 	proxy.Transport = tr

// 	return proxy
// }

func sshConnect(userAtHost string, privateKeyPath string) (*ssh.Client, error) {
	// root user by default
	user := "root"
	host := ""
	userAndHost := strings.SplitN(userAtHost, "@", 2)
	if len(userAndHost) == 1 {
		host = userAndHost[0]
	} else {
		user = userAndHost[0]
		host = userAndHost[1]
	}

	u, err := url.Parse(host)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("ssh connection can't be established: %s", err))
	}
	if u.Scheme == "" {
		u.Scheme = "tcp"
	}

	authMethod, err := authMethodPublicKeys(privateKeyPath)
	if err != nil {
		log.Fatalln(err)
	}
	config := &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{authMethod},
	}

	addr := u.Host + u.Path
	parts := strings.Split(addr, ":")
	lastPart := parts[len(parts)-1]
	_, err = strconv.Atoi(lastPart)
	// port is required, used 22 by default
	if err != nil {
		addr += ":22"
	}

	sshClientConn, err := ssh.Dial(u.Scheme, addr, config)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("ssh connection can't be established: %s", err))
	}
	return sshClientConn, nil
}

func handleProxyConnection(conn net.Conn, sshClient *ssh.Client) {
	err := forward(conn, sshClient, "unix:///var/run/docker.sock")
	if err != nil {
		fmt.Fprintf(os.Stderr, "can't forward connection: %s\n", err.Error())
	}
}

func forward(conn net.Conn, sshClient *ssh.Client, remoteAddr string) error {

	// parse OpenSSH version, 6.7 is the minimum required
	reOpenSSH := regexp.MustCompile("OpenSSH_[.0-9]+")
	reOpenSSHVersion := regexp.MustCompile("[.0-9]+")
	match := reOpenSSH.Find(sshClient.ServerVersion())
	openSSHVersionStr := string(reOpenSSHVersion.Find(match))
	openSSHVersion, err := strconv.ParseFloat(openSSHVersionStr, 64)
	if err != nil {
		return errors.New("can't parse server OpenSSH version")
	}
	if openSSHVersion < 6.7 {
		return errors.New("OpenSSH 6.7 minimum required on server side")
	}

	// remote addr
	u, err := url.Parse(remoteAddr)
	if err != nil {
		return errors.New(fmt.Sprintf("can't parse remote address: %s\n", remoteAddr))
	}

	addr := filepath.Join(u.Host, u.Path)

	sshConn, err := sshClient.Dial(u.Scheme, addr)
	if err != nil {
		return errors.New(fmt.Sprintf("can't connect to %s (from remote)", remoteAddr))
	}

	// Copy conn.Reader to sshConn.Writer
	go func() {
		_, err = io.Copy(sshConn, conn)
		if err != nil {
			if err != io.EOF {
				log.Fatalln(err)
			}
		}
	}()

	// Copy sshConn.Reader to localConn.Writer
	go func() {
		_, err = io.Copy(conn, sshConn)
		if err != nil {
			if err != io.EOF {
				log.Fatalln(err)
			}
		}
	}()

	return nil
}
<commit_msg>removed dead code<commit_after>package main

import (
	"crypto/rand"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"github.com/aduermael/crypto/ssh"
	"github.com/spf13/cobra"
)

var (
	// path to private key or empty to use default
	sshIdentityFile = ""
	// open a bash session by default, but different option can be used
	shell = "bash"
	// proxy mode (don't start shell session)
	proxyMode = false
)

func main() {

	rootCmd := &cobra.Command{
		Use:   "docker-tunnel [user@]host",
		Short: "Docker-tunnel connects you to remote Docker hosts using SSH tunnels",
		Run: func(cmd *cobra.Command, args []string) {
			if len(args) != 1 {
				cmd.Usage()
				return
			}

			sshClient, err := sshConnect(args[0], sshIdentityFile)
			if err != nil {
				log.Fatalln(err)
			}
			defer sshClient.Close()

			if proxyMode {
				ln, err := net.Listen("tcp", ":2375")
				if err != nil {
					log.Fatalln(err)
				}
				fmt.Println("listening on port 2375...")
				for {
					conn, err := ln.Accept()
					if err != nil {
						log.Fatalln(err)
					}
					go handleProxyConnection(conn, sshClient)
				}
				return
			}

			// proxyMode == false
			// open shell session, connected to remote Docker host

			socketPath := tmpSocketPath()

			ln, err := net.Listen("unix", socketPath)
			if err != nil {
				log.Fatalln(err)
			}
			defer os.RemoveAll(socketPath)

			// listen in background
			go func() {
				for {
					conn, err := ln.Accept()
					if err != nil {
						log.Fatalln(err)
					}
					go handleProxyConnection(conn, sshClient)
				}
			}()

			os.Setenv("PS1", "🐳  $ ")
			os.Setenv("DOCKER_HOST", "unix://"+socketPath)

			sh := exec.Command(shell)
			sh.Stdout = os.Stdout
			sh.Stderr = os.Stderr
			sh.Stdin = os.Stdin

			err = sh.Run()
			if err != nil {
				log.Fatalln(err.Error())
			}
		},
	}

	rootCmd.Flags().StringVarP(&sshIdentityFile, "sshid", "i", "", "path to private key")
	rootCmd.Flags().StringVarP(&shell, "shell", "s", "bash", "shell to open session")
	rootCmd.Flags().BoolVarP(&proxyMode, "proxy", "p", false, "proxy mode (don't start shell session)")

	if err := rootCmd.Execute(); err != nil {
		log.Fatalln(err.Error())
	}
}

func tmpSocketPath() string {
	randBytes := make([]byte, 16)
	rand.Read(randBytes)
	return filepath.Join(os.TempDir(), "docker-"+hex.EncodeToString(randBytes)+".sock")
}

func sshConnect(userAtHost string, privateKeyPath string) (*ssh.Client, error) {
	// root user by default
	user := "root"
	host := ""
	userAndHost := strings.SplitN(userAtHost, "@", 2)
	if len(userAndHost) == 1 {
		host = userAndHost[0]
	} else {
		user = userAndHost[0]
		host = userAndHost[1]
	}

	u, err := url.Parse(host)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("ssh connection can't be established: %s", err))
	}
	if u.Scheme == "" {
		u.Scheme = "tcp"
	}

	authMethod, err := authMethodPublicKeys(privateKeyPath)
	if err != nil {
		log.Fatalln(err)
	}
	config := &ssh.ClientConfig{
		User: user,
		Auth: []ssh.AuthMethod{authMethod},
	}

	addr := u.Host + u.Path
	parts := strings.Split(addr, ":")
	lastPart := parts[len(parts)-1]
	_, err = strconv.Atoi(lastPart)
	// port is required, used 22 by default
	if err != nil {
		addr += ":22"
	}

	sshClientConn, err := ssh.Dial(u.Scheme, addr, config)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("ssh connection can't be established: %s", err))
	}
	return sshClientConn, nil
}

func handleProxyConnection(conn net.Conn, sshClient *ssh.Client) {
	err := forward(conn, sshClient, "unix:///var/run/docker.sock")
	if err != nil {
		fmt.Fprintf(os.Stderr, "can't forward connection: %s\n", err.Error())
	}
}

func forward(conn net.Conn, sshClient *ssh.Client, remoteAddr string) error {

	// parse OpenSSH version, 6.7 is the minimum required
	reOpenSSH := regexp.MustCompile("OpenSSH_[.0-9]+")
	reOpenSSHVersion := regexp.MustCompile("[.0-9]+")
	match := reOpenSSH.Find(sshClient.ServerVersion())
	openSSHVersionStr := string(reOpenSSHVersion.Find(match))
	openSSHVersion, err := strconv.ParseFloat(openSSHVersionStr, 64)
	if err != nil {
		return errors.New("can't parse server OpenSSH version")
	}
	if openSSHVersion < 6.7 {
		return errors.New("OpenSSH 6.7 minimum required on server side")
	}

	// remote addr
	u, err := url.Parse(remoteAddr)
	if err != nil {
		return errors.New(fmt.Sprintf("can't parse remote address: %s\n", remoteAddr))
	}

	addr := filepath.Join(u.Host, u.Path)

	sshConn, err := sshClient.Dial(u.Scheme, addr)
	if err != nil {
		return errors.New(fmt.Sprintf("can't connect to %s (from remote)", remoteAddr))
	}

	// Copy conn.Reader to sshConn.Writer
	go func() {
		_, err = io.Copy(sshConn, conn)
		if err != nil {
			if err != io.EOF {
				log.Fatalln(err)
			}
		}
	}()

	// Copy sshConn.Reader to localConn.Writer
	go func() {
		_, err = io.Copy(conn, sshConn)
		if err != nil {
			if err != io.EOF {
				log.Fatalln(err)
			}
		}
	}()

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"encoding/json"
	"io/ioutil"
	"strings"
	"net/http"
	"gopkg.in/alecthomas/kingpin.v2"
	"github.com/dghubble/sling"
)

var (
	modeCommand = kingpin.Command("mode", "Get Hoverfly's current mode")
	simulateCommand = kingpin.Command("simulate", "Set Hoverfly to simulate mode")
	captureCommand = kingpin.Command("capture", "Set Hoverfly to capture mode")
	modifyCommand = kingpin.Command("modify", "Set Hoverfly to modify mode")
	synthesizeCommand = kingpin.Command("synthesize", "Set Hoverfly to synthesize mode")
)

type ApiStateResponse struct {
	Mode string        `json:"mode"`
	Destination string `json"destination"`
}

func main() {
	switch kingpin.Parse() {
		case modeCommand.FullCommand():
			modeHandler()
		case simulateCommand.FullCommand():
			simulateHandler()
		case captureCommand.FullCommand():
			captureHandler()
		case modifyCommand.FullCommand():
			modifyHandler()
		case synthesizeCommand.FullCommand():
			synthesizeHandler()

	}
}

func modeHandler() {
	response := getHoverflyMode()
	fmt.Println("Hoverfly is currently set to " + response.Mode + " mode")
}

func simulateHandler() {
	response := setHoverflyMode("simulate")
	defer response.Body.Close()
	fmt.Println("Hoverfly set to simulate mode")
}

func captureHandler() {
	response := setHoverflyMode("capture")
	defer response.Body.Close()
	fmt.Println("Hoverfly set to capture mode")
}

func modifyHandler() {
	response := setHoverflyMode("modify")
	defer response.Body.Close()
	fmt.Println("Hoverfly set to modify mode")
}

func synthesizeHandler() {
	response := setHoverflyMode("synthesize")
	defer response.Body.Close()
	fmt.Println("Hoverfly set to synthesize mode")
}

func getHoverflyMode() (ApiStateResponse) {
	request, _ := sling.New().Get("http://localhost:8888/api/state").Request()
	response, _ := http.DefaultClient.Do(request)
	defer response.Body.Close()

	body, _ := ioutil.ReadAll(response.Body)
	var jsonResponse ApiStateResponse
	json.Unmarshal(body, &jsonResponse)
	return jsonResponse
}

func setHoverflyMode(mode string) (*http.Response) {
	request, _ := sling.New().Post("http://localhost:8888/api/state").Body(strings.NewReader(`{"mode":"` + mode + `"}`)).Request()
	response, _ := http.DefaultClient.Do(request)
	return response
}
<commit_msg>Moved all the mode commands to under mode.<commit_after>package main

import (
	"fmt"
	"encoding/json"
	"io/ioutil"
	"strings"
	"net/http"
	"gopkg.in/alecthomas/kingpin.v2"
	"github.com/dghubble/sling"
)

var (
	modeCategory = kingpin.Command("mode", "Get Hoverfly's current mode")
	modeCommand = modeCategory.Command("status", "Get Hoverfly's current mode").Default()
	simulateCommand = modeCategory.Command("simulate", "Set Hoverfly to simulate mode")
	captureCommand = modeCategory.Command("capture", "Set Hoverfly to capture mode")
	modifyCommand = modeCategory.Command("modify", "Set Hoverfly to modify mode")
	synthesizeCommand = modeCategory.Command("synthesize", "Set Hoverfly to synthesize mode")
)

type ApiStateResponse struct {
	Mode string        `json:"mode"`
	Destination string `json"destination"`
}

func main() {
	fmt.Println(modeCommand.FullCommand())
	switch kingpin.Parse() {
		case modeCommand.FullCommand():
			modeHandler()
		case simulateCommand.FullCommand():
			simulateHandler()
		case captureCommand.FullCommand():
			captureHandler()
		case modifyCommand.FullCommand():
			modifyHandler()
		case synthesizeCommand.FullCommand():
			synthesizeHandler()

	}
}

func modeHandler() {
	response := getHoverflyMode()
	fmt.Println("Hoverfly is currently set to " + response.Mode + " mode")
}

func simulateHandler() {
	response := setHoverflyMode("simulate")
	defer response.Body.Close()
	fmt.Println("Hoverfly set to simulate mode")
}

func captureHandler() {
	response := setHoverflyMode("capture")
	defer response.Body.Close()
	fmt.Println("Hoverfly set to capture mode")
}

func modifyHandler() {
	response := setHoverflyMode("modify")
	defer response.Body.Close()
	fmt.Println("Hoverfly set to modify mode")
}

func synthesizeHandler() {
	response := setHoverflyMode("synthesize")
	defer response.Body.Close()
	fmt.Println("Hoverfly set to synthesize mode")
}

func getHoverflyMode() (ApiStateResponse) {
	request, _ := sling.New().Get("http://localhost:8888/api/state").Request()
	response, _ := http.DefaultClient.Do(request)
	defer response.Body.Close()

	body, _ := ioutil.ReadAll(response.Body)
	var jsonResponse ApiStateResponse
	json.Unmarshal(body, &jsonResponse)
	return jsonResponse
}

func setHoverflyMode(mode string) (*http.Response) {
	request, _ := sling.New().Post("http://localhost:8888/api/state").Body(strings.NewReader(`{"mode":"` + mode + `"}`)).Request()
	response, _ := http.DefaultClient.Do(request)
	return response
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
)

func main() {
	var client SlackAPI

	flag.Usage = func() {
		fmt.Println("Slack API Client")
		fmt.Println("  http://cixtor.com/")
		fmt.Println("  https://api.slack.com/")
		fmt.Println("  https://github.com/cixtor/slackapi")
		fmt.Println()
		fmt.Println("Low level Slack API client with custom commands. Slack, the 'messaging app for")
		fmt.Println("teams' offers an API that has been used to build multiple projects around it,")
		fmt.Println("from bots to independent clients as well as integrations with other external")
		fmt.Println("services. This project aims to offer a low level experience for advanced users")
		fmt.Println("that want to either drop the web client or interact with the API for testing")
		fmt.Println("purpose.")
		fmt.Println()
		fmt.Println("Usage:")
		fmt.Println("  slackapi api.test                                  Checks API calling code.")
		fmt.Println("  slackapi auth.test                                 Checks authentication & identity.")
		fmt.Println("  slackapi channels.history [channel] [time]         Fetches history of messages and events from a channel.")
		fmt.Println("  slackapi channels.info [channel]                   Gets information about a channel.")
		fmt.Println("  slackapi channels.list                             Lists all channels in a Slack team.")
		fmt.Println("  slackapi channels.mark [channel] [time]            Sets the read cursor in a channel.")
		fmt.Println("  slackapi channels.setPurpose [channel] [purpose]   Sets the purpose for a channel.")
		fmt.Println("  slackapi channels.setTopic [channel] [topic]       Sets the topic for a channel.")
		fmt.Println("  slackapi chat.delete [channel] [time]              Deletes a message.")
		fmt.Println("  slackapi chat.postMessage [channel] [text]         Sends a message to a channel.")
		fmt.Println("  slackapi chat.session                              Starts a new chat session.")
		fmt.Println("  slackapi chat.update [channel] [time] [text]       Updates a message.")
		fmt.Println("  slackapi emoji.list                                Lists custom emoji for a team.")
		fmt.Println("  slackapi groups.close [channel]                    Closes a private channel.")
		fmt.Println("  slackapi groups.history [channel] [time]           Fetches history of messages and events from a private channel.")
		fmt.Println("  slackapi groups.info [channel]                     Gets information about a private channel.")
		fmt.Println("  slackapi groups.list                               Lists private channels that the calling user has access to.")
		fmt.Println("  slackapi groups.mark [channel] [time]              Sets the read cursor in a private channel.")
		fmt.Println("  slackapi groups.open [group]                       Opens a private channel.")
		fmt.Println("  slackapi groups.setPurpose [channel] [purpose]     Sets the purpose for a private channel.")
		fmt.Println("  slackapi groups.setTopic [channel] [topic]         Sets the topic for a private channel.")
		fmt.Println("  slackapi im.close [channel]                        Close a direct message channel.")
		fmt.Println("  slackapi im.history [channel] [time]               Fetches history of messages and events from direct message channel.")
		fmt.Println("  slackapi im.list                                   Lists direct message channels for the calling user.")
		fmt.Println("  slackapi im.mark [channel] [time]                  Sets the read cursor in a direct message channel.")
		fmt.Println("  slackapi im.open [user]                            Opens a direct message channel.")
		fmt.Println("  slackapi mpim.list                                 Lists multiparty direct message channels for the calling user.")
		fmt.Println("  slackapi reactions.add [name] [channel] [time]     Adds a reaction to an item.")
		fmt.Println("  slackapi reactions.get [channel] [time]            Gets reactions for an item.")
		fmt.Println("  slackapi reactions.list [user]                     Lists reactions made by a user.")
		fmt.Println("  slackapi reactions.remove [name] [channel] [time]  Removes a reaction from an item.")
		fmt.Println("  slackapi team.info                                 Gets information about the current team.")
		fmt.Println("  slackapi users.getPresence [user]                  Gets user presence information.")
		fmt.Println("  slackapi users.info [user]                         Gets information about a user.")
		fmt.Println("  slackapi users.list                                Lists all users in a Slack team.")
		fmt.Println("  slackapi users.search [user]                       Search users by name or email address.")
		fmt.Println("  slackapi users.setActive                           Marks a user as active.")
		fmt.Println("  slackapi users.setPresence [presence]              Manually sets user presence.")
		fmt.Println("  slackapi -help")
		fmt.Println()
		fmt.Println("Usage (chat.session):")
		fmt.Println("  :history     Displays the messages in the current session")
		fmt.Println("  :open        Opens a new session with a user, channel, or group")
		fmt.Println("  :delete      Deletes the latest message in the session history")
		fmt.Println("  :flush       Deletes all the messages in the session history")
		fmt.Println("  :exec        Executes and sends the output of a local command")
		fmt.Println("  :execv       Same as :exec but includes the executed command")
		fmt.Println("  :boton       Activates the robot to send 3rd-party messages")
		fmt.Println("  :botoff      Deactivates the robot to send normal messages")
		fmt.Println("  :botinfo     Displays the configuration of the robot")
		fmt.Println("  :botname     Sets the user name of the robot")
		fmt.Println("  :botimage    Sets the avatar for the robot")
		fmt.Println("  :userid      Displays the unique identifier of an user")
		fmt.Println("  :userlist    Displays the information of all the users")
		fmt.Println("  :usersearch  Searches the information of a specific user")
		flag.PrintDefaults()
	}

	flag.Parse()
	client.AutoConfigure()

	switch flag.Arg(0) {
	case "api.test":
		client.ApiTest()
	case "auth.test":
		client.AuthTest()
	case "channels.history":
		client.ChannelsHistory(flag.Arg(1), flag.Arg(2))
	case "channels.info":
		client.ChannelsInfo(flag.Arg(1))
	case "channels.list":
		client.ChannelsListVerbose()
	case "channels.mark":
		client.ChannelsMark(flag.Arg(1), flag.Arg(2))
	case "channels.setPurpose":
		client.ChannelsSetPurpose(flag.Arg(1), flag.Arg(2))
	case "channels.setTopic":
		client.ChannelsSetTopic(flag.Arg(1), flag.Arg(2))
	case "chat.delete":
		client.ChatDeleteVerbose(flag.Arg(1), flag.Arg(2))
	case "chat.postMessage":
		client.ChatPostMessageVerbose(flag.Arg(1), flag.Arg(2))
	case "chat.session":
		client.ChatSession()
	case "chat.update":
		client.ChatUpdateVerbose(flag.Arg(1), flag.Arg(2), flag.Arg(3))
	case "emoji.list":
		client.EmojiList()
	case "groups.close":
		client.GroupsClose(flag.Arg(1))
	case "groups.history":
		client.GroupsHistory(flag.Arg(1), flag.Arg(2))
	case "groups.info":
		client.GroupsInfo(flag.Arg(1))
	case "groups.list":
		client.GroupsListVerbose()
	case "groups.mark":
		client.GroupsMark(flag.Arg(1), flag.Arg(2))
	case "groups.open":
		client.GroupsOpenVerbose(flag.Arg(1))
	case "groups.setPurpose":
		client.GroupsSetPurpose(flag.Arg(1), flag.Arg(2))
	case "groups.setTopic":
		client.GroupsSetTopic(flag.Arg(1), flag.Arg(2))
	case "im.close":
		client.InstantMessagingCloseVerbose(flag.Arg(1))
	case "im.history":
		client.InstantMessagingHistory(flag.Arg(1), flag.Arg(2))
	case "im.list":
		client.InstantMessagingList()
	case "im.mark":
		client.InstantMessagingMark(flag.Arg(1), flag.Arg(2))
	case "im.open":
		client.InstantMessagingOpenVerbose(flag.Arg(1))
	case "mpim.list":
		client.MultiPartyInstantMessagingList()
	case "reactions.add":
		client.ReactionsAdd(flag.Arg(1), flag.Arg(2), flag.Arg(3))
	case "reactions.get":
		client.ReactionsGet(flag.Arg(1), flag.Arg(2))
	case "reactions.list":
		client.ReactionsList(flag.Arg(1))
	case "reactions.remove":
		client.ReactionsRemove(flag.Arg(1), flag.Arg(2), flag.Arg(3))
	case "team.info":
		client.TeamInfo()
	case "users.getPresence":
		client.UsersGetPresence(flag.Arg(1))
	case "users.info":
		client.UsersInfo(flag.Arg(1))
	case "users.list":
		client.UsersListVerbose()
	case "users.search":
		client.UsersSearchVerbose(flag.Arg(1))
	case "users.setActive":
		client.UsersSetActive()
	case "users.setPresence":
		client.UsersSetPresence(flag.Arg(1))
	case "-help":
		flag.Usage()
	}

	os.Exit(0)
}
<commit_msg>Added short description of the program<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
)

func main() {
	var client SlackAPI

	flag.Usage = func() {
		fmt.Println("Slack API Client")
		fmt.Println("  http://cixtor.com/")
		fmt.Println("  https://api.slack.com/")
		fmt.Println("  https://github.com/cixtor/slackapi")
		fmt.Println()
		fmt.Println("Description:")
		fmt.Println("  Low level Slack API client with custom commands. Slack, the 'messaging app for")
		fmt.Println("  teams' offers an API that has been used to build multiple projects around it,")
		fmt.Println("  from bots to independent clients as well as integrations with other external")
		fmt.Println("  services. This project aims to offer a low level experience for advanced users")
		fmt.Println("  that want to either drop the web client or interact with the API for testing")
		fmt.Println("  purpose.")
		fmt.Println()
		fmt.Println("Usage:")
		fmt.Println("  slackapi api.test                                  Checks API calling code.")
		fmt.Println("  slackapi auth.test                                 Checks authentication & identity.")
		fmt.Println("  slackapi channels.history [channel] [time]         Fetches history of messages and events from a channel.")
		fmt.Println("  slackapi channels.info [channel]                   Gets information about a channel.")
		fmt.Println("  slackapi channels.list                             Lists all channels in a Slack team.")
		fmt.Println("  slackapi channels.mark [channel] [time]            Sets the read cursor in a channel.")
		fmt.Println("  slackapi channels.setPurpose [channel] [purpose]   Sets the purpose for a channel.")
		fmt.Println("  slackapi channels.setTopic [channel] [topic]       Sets the topic for a channel.")
		fmt.Println("  slackapi chat.delete [channel] [time]              Deletes a message.")
		fmt.Println("  slackapi chat.postMessage [channel] [text]         Sends a message to a channel.")
		fmt.Println("  slackapi chat.session                              Starts a new chat session.")
		fmt.Println("  slackapi chat.update [channel] [time] [text]       Updates a message.")
		fmt.Println("  slackapi emoji.list                                Lists custom emoji for a team.")
		fmt.Println("  slackapi groups.close [channel]                    Closes a private channel.")
		fmt.Println("  slackapi groups.history [channel] [time]           Fetches history of messages and events from a private channel.")
		fmt.Println("  slackapi groups.info [channel]                     Gets information about a private channel.")
		fmt.Println("  slackapi groups.list                               Lists private channels that the calling user has access to.")
		fmt.Println("  slackapi groups.mark [channel] [time]              Sets the read cursor in a private channel.")
		fmt.Println("  slackapi groups.open [group]                       Opens a private channel.")
		fmt.Println("  slackapi groups.setPurpose [channel] [purpose]     Sets the purpose for a private channel.")
		fmt.Println("  slackapi groups.setTopic [channel] [topic]         Sets the topic for a private channel.")
		fmt.Println("  slackapi im.close [channel]                        Close a direct message channel.")
		fmt.Println("  slackapi im.history [channel] [time]               Fetches history of messages and events from direct message channel.")
		fmt.Println("  slackapi im.list                                   Lists direct message channels for the calling user.")
		fmt.Println("  slackapi im.mark [channel] [time]                  Sets the read cursor in a direct message channel.")
		fmt.Println("  slackapi im.open [user]                            Opens a direct message channel.")
		fmt.Println("  slackapi mpim.list                                 Lists multiparty direct message channels for the calling user.")
		fmt.Println("  slackapi reactions.add [name] [channel] [time]     Adds a reaction to an item.")
		fmt.Println("  slackapi reactions.get [channel] [time]            Gets reactions for an item.")
		fmt.Println("  slackapi reactions.list [user]                     Lists reactions made by a user.")
		fmt.Println("  slackapi reactions.remove [name] [channel] [time]  Removes a reaction from an item.")
		fmt.Println("  slackapi team.info                                 Gets information about the current team.")
		fmt.Println("  slackapi users.getPresence [user]                  Gets user presence information.")
		fmt.Println("  slackapi users.info [user]                         Gets information about a user.")
		fmt.Println("  slackapi users.list                                Lists all users in a Slack team.")
		fmt.Println("  slackapi users.search [user]                       Search users by name or email address.")
		fmt.Println("  slackapi users.setActive                           Marks a user as active.")
		fmt.Println("  slackapi users.setPresence [presence]              Manually sets user presence.")
		fmt.Println("  slackapi -help")
		fmt.Println()
		fmt.Println("Usage (chat.session):")
		fmt.Println("  :history     Displays the messages in the current session")
		fmt.Println("  :open        Opens a new session with a user, channel, or group")
		fmt.Println("  :delete      Deletes the latest message in the session history")
		fmt.Println("  :flush       Deletes all the messages in the session history")
		fmt.Println("  :exec        Executes and sends the output of a local command")
		fmt.Println("  :execv       Same as :exec but includes the executed command")
		fmt.Println("  :boton       Activates the robot to send 3rd-party messages")
		fmt.Println("  :botoff      Deactivates the robot to send normal messages")
		fmt.Println("  :botinfo     Displays the configuration of the robot")
		fmt.Println("  :botname     Sets the user name of the robot")
		fmt.Println("  :botimage    Sets the avatar for the robot")
		fmt.Println("  :userid      Displays the unique identifier of an user")
		fmt.Println("  :userlist    Displays the information of all the users")
		fmt.Println("  :usersearch  Searches the information of a specific user")
		flag.PrintDefaults()
	}

	flag.Parse()
	client.AutoConfigure()

	switch flag.Arg(0) {
	case "api.test":
		client.ApiTest()
	case "auth.test":
		client.AuthTest()
	case "channels.history":
		client.ChannelsHistory(flag.Arg(1), flag.Arg(2))
	case "channels.info":
		client.ChannelsInfo(flag.Arg(1))
	case "channels.list":
		client.ChannelsListVerbose()
	case "channels.mark":
		client.ChannelsMark(flag.Arg(1), flag.Arg(2))
	case "channels.setPurpose":
		client.ChannelsSetPurpose(flag.Arg(1), flag.Arg(2))
	case "channels.setTopic":
		client.ChannelsSetTopic(flag.Arg(1), flag.Arg(2))
	case "chat.delete":
		client.ChatDeleteVerbose(flag.Arg(1), flag.Arg(2))
	case "chat.postMessage":
		client.ChatPostMessageVerbose(flag.Arg(1), flag.Arg(2))
	case "chat.session":
		client.ChatSession()
	case "chat.update":
		client.ChatUpdateVerbose(flag.Arg(1), flag.Arg(2), flag.Arg(3))
	case "emoji.list":
		client.EmojiList()
	case "groups.close":
		client.GroupsClose(flag.Arg(1))
	case "groups.history":
		client.GroupsHistory(flag.Arg(1), flag.Arg(2))
	case "groups.info":
		client.GroupsInfo(flag.Arg(1))
	case "groups.list":
		client.GroupsListVerbose()
	case "groups.mark":
		client.GroupsMark(flag.Arg(1), flag.Arg(2))
	case "groups.open":
		client.GroupsOpenVerbose(flag.Arg(1))
	case "groups.setPurpose":
		client.GroupsSetPurpose(flag.Arg(1), flag.Arg(2))
	case "groups.setTopic":
		client.GroupsSetTopic(flag.Arg(1), flag.Arg(2))
	case "im.close":
		client.InstantMessagingCloseVerbose(flag.Arg(1))
	case "im.history":
		client.InstantMessagingHistory(flag.Arg(1), flag.Arg(2))
	case "im.list":
		client.InstantMessagingList()
	case "im.mark":
		client.InstantMessagingMark(flag.Arg(1), flag.Arg(2))
	case "im.open":
		client.InstantMessagingOpenVerbose(flag.Arg(1))
	case "mpim.list":
		client.MultiPartyInstantMessagingList()
	case "reactions.add":
		client.ReactionsAdd(flag.Arg(1), flag.Arg(2), flag.Arg(3))
	case "reactions.get":
		client.ReactionsGet(flag.Arg(1), flag.Arg(2))
	case "reactions.list":
		client.ReactionsList(flag.Arg(1))
	case "reactions.remove":
		client.ReactionsRemove(flag.Arg(1), flag.Arg(2), flag.Arg(3))
	case "team.info":
		client.TeamInfo()
	case "users.getPresence":
		client.UsersGetPresence(flag.Arg(1))
	case "users.info":
		client.UsersInfo(flag.Arg(1))
	case "users.list":
		client.UsersListVerbose()
	case "users.search":
		client.UsersSearchVerbose(flag.Arg(1))
	case "users.setActive":
		client.UsersSetActive()
	case "users.setPresence":
		client.UsersSetPresence(flag.Arg(1))
	case "-help":
		flag.Usage()
	}

	os.Exit(0)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"net/http"
	"os"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ecs"
)

var (
	clusterName = flag.String("c", "", "Cluster name to deploy to")
	repoName    = flag.String("i", "", "Container repo to pull from e.g. quay.io/username/reponame")
	appName     = flag.String("a", "", "Application name")
	environment = flag.String("e", "", "Application environment, e.g. production")
	sha         = flag.String("s", "", "Tag, usually short git SHA to deploy")
	region      = flag.String("r", "", "AWS region")
	webhook     = flag.String("w", "", "Webhook (slack) URL to post to")
	targetImage = flag.String("t", "", "Target image (overrides -s and -i)")
	debug       = flag.Bool("d", false, "enable Debug output")
)

func fail(s string) {
	fmt.Printf(s)
	webhookFunc(s)
	os.Exit(2)
}

func webhookFunc(s string) {
	if *webhook == "" {
		return
	}

	json, _ := json.Marshal(
		struct {
			Text     string `json:"text"`
			Username string `json:"username"`
		}{
			s,
			"GO ECS Deploy",
		},
	)

	reader := bytes.NewReader(json)
	http.Post(*webhook, "application/json", reader)
}

func main() {
	flag.Parse()

	if *clusterName == "" || *appName == "" || *environment == "" || *region == "" {
		flag.Usage()
		fail(fmt.Sprintf("Failed deployment %s \n`bad parameters`", *appName))
	}

	if *repoName == "" || *sha == "" {
		if *targetImage == "" {
			flag.Usage()
			fail(fmt.Sprintf("Failed deployment %s \n`no repo name, sha or target image specified`", *appName))
		} else {
			x := fmt.Sprintf("%s", *targetImage)
		}
	} else {
		x := fmt.Sprintf("%s:%s", *repoName, *sha)
	}

	serviceName := *appName + "-" + *environment

	svc := ecs.New(session.New(), &aws.Config{Region: aws.String(*region)})

	fmt.Printf("Request to deploy sha: %s to %s at %s \n", *sha, *environment, *region)
	fmt.Printf("Describing services for cluster %s and service %s \n", *clusterName, serviceName)
	fail("DEBUG EXIT NOW")
	serviceDesc, err :=
		svc.DescribeServices(
			&ecs.DescribeServicesInput{
				Cluster:  clusterName,
				Services: []*string{&serviceName},
			})
	if err != nil {
		fail(fmt.Sprintf("Failed: deployment %s \n`%s`", *appName, err.Error()))
	}

	if len(serviceDesc.Services) < 1 {
		msg := fmt.Sprintf("No service %s found on cluster %s", serviceName, *clusterName)
		fail("Failed: " + msg)
	}

	service := serviceDesc.Services[0]
	if serviceName != *service.ServiceName {
		msg := fmt.Sprintf("Found the wrong service when looking for %s found %s \n", serviceName, *service.ServiceName)
		fail("Failed: " + msg)
	}

	fmt.Printf("Found existing ARN %s for service %s \n", *service.ClusterArn, *service.ServiceName)

	taskDesc, err :=
		svc.DescribeTaskDefinition(
			&ecs.DescribeTaskDefinitionInput{
				TaskDefinition: service.TaskDefinition})
	if err != nil {
		fail(fmt.Sprintf("Failed: deployment %s \n`%s`", *appName, err.Error()))
	}

	if *debug {
		fmt.Printf("Current task description: \n%+v \n", taskDesc)
	}

	containerDef := taskDesc.TaskDefinition.ContainerDefinitions[0]
	oldImage := containerDef.Image
	containerImage := &x

	futureDef := &ecs.RegisterTaskDefinitionInput{
		ContainerDefinitions: taskDesc.TaskDefinition.ContainerDefinitions,
		Family:               taskDesc.TaskDefinition.Family,
		Volumes:              taskDesc.TaskDefinition.Volumes,
		NetworkMode:          taskDesc.TaskDefinition.NetworkMode,
		TaskRoleArn:          taskDesc.TaskDefinition.TaskRoleArn,
	}

	if *debug {
		fmt.Printf("Future task description: \n%+v \n", futureDef)
	}

	registerRes, err :=
		svc.RegisterTaskDefinition(futureDef)
	if err != nil {
		fail(fmt.Sprintf("Failed: deployment %s for %s to %s \n`%s`", *containerImage, *appName, *clusterName, err.Error()))
	}

	newArn := registerRes.TaskDefinition.TaskDefinitionArn

	fmt.Printf("Registered new task for %s:%s \n", *sha, *newArn)

	// update service to use new definition
	_, err = svc.UpdateService(
		&ecs.UpdateServiceInput{
			Cluster:        clusterName,
			Service:        &serviceName,
			DesiredCount:   service.DesiredCount,
			TaskDefinition: newArn,
		})
	if err != nil {
		fail(fmt.Sprintf("Failed: deployment %s for %s to %s as %s \n`%s`", *containerImage, *appName, *clusterName, *newArn, err.Error()))
	}

	slackMsg := fmt.Sprintf("Deployed %s for *%s* to *%s* as `%s`", *containerImage, *appName, *clusterName, *newArn)

	// extract old image sha, and use it to generate a git compare URL
	if *oldImage != "" && *sha != "" {
		parts := strings.Split(*oldImage, ":")
		if len(parts) == 2 {
			// possibly a tagged image "def15c31-php5.5"
			parts = strings.Split(parts[1], "-")
			if gitURL, err := gitURL(parts[0], *sha); err == nil {
				slackMsg += " (<" + gitURL + "|diff>)"
			}
		}
	}
	webhookFunc(slackMsg)

	fmt.Printf("Updated %s service to use new ARN: %s \n", serviceName, *newArn)

}

// gitURL uses git since the program runs in many CI environments
func gitURL(startSHA string, endSHA string) (string, error) {
	var project string

	if travisSlug, ok := os.LookupEnv("TRAVIS_REPO_SLUG"); ok {
		project = travisSlug
	}

	if werckerOwner, ok := os.LookupEnv("WERCKER_GIT_OWNER"); ok {
		if werckerRepo, ok := os.LookupEnv("WERCKER_GIT_REPOSITORY"); ok {
			project = werckerOwner + "/" + werckerRepo
		}
	}

	if project == "" {
		return "", errors.New("nope")
	}

	url := "https://github.com/" + project + "/compare/" + startSHA + "..." + endSHA
	return url, nil
}
<commit_msg>minor fixes<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"net/http"
	"os"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ecs"
)

var (
	clusterName = flag.String("c", "", "Cluster name to deploy to")
	repoName    = flag.String("i", "", "Container repo to pull from e.g. quay.io/username/reponame")
	appName     = flag.String("a", "", "Application name")
	environment = flag.String("e", "", "Application environment, e.g. production")
	sha         = flag.String("s", "", "Tag, usually short git SHA to deploy")
	region      = flag.String("r", "", "AWS region")
	webhook     = flag.String("w", "", "Webhook (slack) URL to post to")
	targetImage = flag.String("t", "", "Target image (overrides -s and -i)")
	debug       = flag.Bool("d", false, "enable Debug output")
)

func fail(s string) {
	fmt.Printf(s)
	webhookFunc(s)
	os.Exit(2)
}

func webhookFunc(s string) {
	if *webhook == "" {
		return
	}

	json, _ := json.Marshal(
		struct {
			Text     string `json:"text"`
			Username string `json:"username"`
		}{
			s,
			"GO ECS Deploy",
		},
	)

	reader := bytes.NewReader(json)
	http.Post(*webhook, "application/json", reader)
}

func main() {
	flag.Parse()

	if *clusterName == "" || *appName == "" || *environment == "" || *region == "" {
		flag.Usage()
		fail(fmt.Sprintf("Failed deployment %s : missing parameters\n", *appName))
	}

	if (*repoName == "" && *sha == "") && *targetImage == "" {
		flag.Usage()
		fail(fmt.Sprintf("Failed deployment %s : no repo name, sha or target image specified\n", *appName))
	}

	serviceName := *appName + "-" + *environment

	svc := ecs.New(session.New(), &aws.Config{Region: aws.String(*region)})

	fmt.Printf("Request to deploy sha: %s to %s at %s \n", *sha, *environment, *region)
	fmt.Printf("Describing services for cluster %s and service %s \n", *clusterName, serviceName)
	fail("DEBUG EXIT NOW")
	serviceDesc, err :=
		svc.DescribeServices(
			&ecs.DescribeServicesInput{
				Cluster:  clusterName,
				Services: []*string{&serviceName},
			})
	if err != nil {
		fail(fmt.Sprintf("Failed: deployment %s \n`%s`", *appName, err.Error()))
	}

	if len(serviceDesc.Services) < 1 {
		msg := fmt.Sprintf("No service %s found on cluster %s", serviceName, *clusterName)
		fail("Failed: " + msg)
	}

	service := serviceDesc.Services[0]
	if serviceName != *service.ServiceName {
		msg := fmt.Sprintf("Found the wrong service when looking for %s found %s \n", serviceName, *service.ServiceName)
		fail("Failed: " + msg)
	}

	fmt.Printf("Found existing ARN %s for service %s \n", *service.ClusterArn, *service.ServiceName)

	taskDesc, err :=
		svc.DescribeTaskDefinition(
			&ecs.DescribeTaskDefinitionInput{
				TaskDefinition: service.TaskDefinition})
	if err != nil {
		fail(fmt.Sprintf("Failed: deployment %s \n`%s`", *appName, err.Error()))
	}

	if *debug {
		fmt.Printf("Current task description: \n%+v \n", taskDesc)
	}

	containerDef := taskDesc.TaskDefinition.ContainerDefinitions[0]
	oldImage := containerDef.Image
	{
		x := *targetImage
		if *targetImage == "" {
			x = fmt.Sprintf("%s:%s", *repoName, *sha)
		}
		containerDef.Image = &x
	}

	futureDef := &ecs.RegisterTaskDefinitionInput{
		ContainerDefinitions: taskDesc.TaskDefinition.ContainerDefinitions,
		Family:               taskDesc.TaskDefinition.Family,
		Volumes:              taskDesc.TaskDefinition.Volumes,
		NetworkMode:          taskDesc.TaskDefinition.NetworkMode,
		TaskRoleArn:          taskDesc.TaskDefinition.TaskRoleArn,
	}

	if *debug {
		fmt.Printf("Future task description: \n%+v \n", futureDef)
	}

	registerRes, err :=
		svc.RegisterTaskDefinition(futureDef)
	if err != nil {
		fail(fmt.Sprintf("Failed: deployment %s for %s to %s \n`%s`", *containerDef.Image, *appName, *clusterName, err.Error()))
	}

	newArn := registerRes.TaskDefinition.TaskDefinitionArn

	fmt.Printf("Registered new task for %s:%s \n", *sha, *newArn)

	// update service to use new definition
	_, err = svc.UpdateService(
		&ecs.UpdateServiceInput{
			Cluster:        clusterName,
			Service:        &serviceName,
			DesiredCount:   service.DesiredCount,
			TaskDefinition: newArn,
		})
	if err != nil {
		fail(fmt.Sprintf("Failed: deployment %s for %s to %s as %s \n`%s`", *containerDef.Image, *appName, *clusterName, *newArn, err.Error()))
	}

	slackMsg := fmt.Sprintf("Deployed %s for *%s* to *%s* as `%s`", *containerDef.Image, *appName, *clusterName, *newArn)

	// extract old image sha, and use it to generate a git compare URL
	if *oldImage != "" && *sha != "" {
		parts := strings.Split(*oldImage, ":")
		if len(parts) == 2 {
			// possibly a tagged image "def15c31-php5.5"
			parts = strings.Split(parts[1], "-")
			if gitURL, err := gitURL(parts[0], *sha); err == nil {
				slackMsg += " (<" + gitURL + "|diff>)"
			}
		}
	}
	webhookFunc(slackMsg)

	fmt.Printf("Updated %s service to use new ARN: %s \n", serviceName, *newArn)

}

// gitURL uses git since the program runs in many CI environments
func gitURL(startSHA string, endSHA string) (string, error) {
	var project string

	if travisSlug, ok := os.LookupEnv("TRAVIS_REPO_SLUG"); ok {
		project = travisSlug
	}

	if werckerOwner, ok := os.LookupEnv("WERCKER_GIT_OWNER"); ok {
		if werckerRepo, ok := os.LookupEnv("WERCKER_GIT_REPOSITORY"); ok {
			project = werckerOwner + "/" + werckerRepo
		}
	}

	if project == "" {
		return "", errors.New("nope")
	}

	url := "https://github.com/" + project + "/compare/" + startSHA + "..." + endSHA
	return url, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/kch42/gomcmap/mcmap"
	"github.com/mattn/go-gtk/gdk"
	"github.com/mattn/go-gtk/glib"
	"github.com/mattn/go-gtk/gtk"
	"os"
)

type GUI struct {
	window    *gtk.Window
	statusbar *gtk.Statusbar

	showbiomes *gtk.CheckButton
	fixSnowIce *gtk.CheckButton

	menuitemSave *gtk.MenuItem

	statusContext uint
	lastStatus    string

	mapw *MapWidget
}

func (g *GUI) openWorldDlg() {
	dlg := gtk.NewFileChooserDialog("Open World (region directory)", g.window, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, "Open Region dir", gtk.RESPONSE_OK, "Cancel", gtk.RESPONSE_CANCEL)
	if dlg.Run() == gtk.RESPONSE_OK {
		g.openWorld(dlg.GetFilename())
	}
	dlg.Destroy()
}

func (g *GUI) openWorld(path string) {
	region, err := mcmap.OpenRegion(path, false)
	if err != nil {
		dlg := gtk.NewMessageDialog(g.window, gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Could not load world %s:\n%s", path, err.Error())
		dlg.Run()
		dlg.Destroy()
	}

	g.menuitemSave.SetSensitive(true)

	g.mapw.SetRegion(region)
}

func (g *GUI) aboutDlg() {
	dlg := gtk.NewAboutDialog()
	dlg.SetName("biome-editor")
	dlg.SetVersion("β")
	dlg.SetCopyright("© 2013 by Kevin Chabowski")
	dlg.SetAuthors([]string{"Kevin Chabowski <kevin@kch42.de>"})
	dlg.SetLicense(`Copyright (c) 2013 Kevin Chabowski

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
`)
	dlg.Run()
	dlg.Destroy()
}

func (g *GUI) mkMenuBar() *gtk.MenuBar {
	menubar := gtk.NewMenuBar()

	fileMenu := gtk.NewMenu()

	open := gtk.NewMenuItemWithLabel("Open")
	open.Connect("activate", g.openWorldDlg)
	fileMenu.Append(open)

	if quickopen, ok := g.mkQuickOpen(); ok {
		quickopenItem := gtk.NewMenuItemWithLabel("Open Map")
		quickopenItem.SetSubmenu(quickopen)
		fileMenu.Append(quickopenItem)
	}

	g.menuitemSave = gtk.NewMenuItemWithLabel("Save")
	g.menuitemSave.Connect("activate", g.save)
	g.menuitemSave.SetSensitive(false)
	fileMenu.Append(g.menuitemSave)

	quit := gtk.NewMenuItemWithLabel("Quit")
	quit.Connect("activate", g.exitApp)
	fileMenu.Append(quit)

	fileMenuItem := gtk.NewMenuItemWithLabel("File")
	fileMenuItem.SetSubmenu(fileMenu)
	menubar.Append(fileMenuItem)

	/*editMenu := gtk.NewMenu()

	undo := gtk.NewMenuItemWithLabel("Undo")
	undo.Connect("activate", g.undo)
	editMenu.Append(undo)

	editMenuItem := gtk.NewMenuItemWithLabel("Edit")
	editMenuItem.SetSubmenu(editMenu)
	menubar.Append(editMenuItem)*/

	helpMenu := gtk.NewMenu()

	about := gtk.NewMenuItemWithLabel("About")
	about.Connect("activate", g.aboutDlg)
	helpMenu.Append(about)

	helpMenuItem := gtk.NewMenuItemWithLabel("Help")
	helpMenuItem.SetSubmenu(helpMenu)
	menubar.Append(helpMenuItem)

	return menubar
}

func (g *GUI) betaWarning() {
	dlg := gtk.NewMessageDialog(g.window, gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "This software is currently in beta.\nAlthough everythung seems to work, you should make a backup of your maps, just in case!")
	dlg.Run()
	dlg.Destroy()
}

func (g *GUI) save() {
	g.setBusy(true)
	g.mapw.Save()
	g.setBusy(false)

	dlg := gtk.NewMessageDialog(g.window, gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Map saved!")
	dlg.Run()
	dlg.Destroy()
}

func (g *GUI) mkQuickOpen() (*gtk.Menu, bool) {
	maps := allMaps()
	if (maps == nil) || (len(maps) == 0) {
		return nil, false
	}

	menu := gtk.NewMenu()
	for name, p := range maps {
		mitem := gtk.NewMenuItemWithLabel(name)
		p2 := p
		mitem.Connect("activate", func() { g.openWorld(p2) })
		menu.Append(mitem)
	}

	return menu, true
}

func labelCustomFont(text, font string) *gtk.Label {
	label := gtk.NewLabel(text)
	label.ModifyFontEasy(font)
	return label
}

func (g *GUI) mkSidebar() *gtk.ScrolledWindow {
	vbox := gtk.NewVBox(false, 0)

	vbox.PackStart(labelCustomFont("Tools", "Sans Bold 14"), false, false, 3)

	g.showbiomes = gtk.NewCheckButtonWithLabel("Show Biomes")
	g.showbiomes.SetActive(true)
	g.showbiomes.Connect("toggled", g.showbiomesToggled)
	vbox.PackStart(g.showbiomes, false, false, 3)

	g.fixSnowIce = gtk.NewCheckButtonWithLabel("Fix Snow/Ice")
	g.fixSnowIce.SetTooltipText("Add Snow/Ice for Taiga/Ice Plains. Remove Snow/Ice for other biomes.")
	g.fixSnowIce.Connect("toggled", g.fixSnowIceToggled)
	vbox.PackStart(g.fixSnowIce, false, false, 3)

	fill := gtk.NewRadioButtonWithLabel(nil, "Fill")
	fill.SetActive(true)
	fill.Connect("toggled", g.mkUpdateToolFx(fill, NewFillTool()))

	draw := gtk.NewRadioButtonWithLabel(fill.GetGroup(), "Draw")
	drawRadius := gtk.NewSpinButtonWithRange(1, 20, 1)
	drawHBox := gtk.NewHBox(false, 0)
	drawHBox.PackStart(draw, true, true, 0)
	drawHBox.PackStart(gtk.NewLabel("Radius:"), false, false, 3)
	drawHBox.PackEnd(drawRadius, false, false, 3)
	draw.Connect("toggled", g.mkUpdateToolFx(draw, NewDrawTool(func() int { return int(drawRadius.GetValue()) })))

	vbox.PackStart(fill, false, false, 3)
	vbox.PackStart(drawHBox, false, false, 3)

	vbox.PackStart(gtk.NewHSeparator(), false, false, 3)
	vbox.PackStart(labelCustomFont("Biomes", "Sans Bold 14"), false, false, 3)

	var grp *glib.SList
	for _, bio := range bioList {
		biohbox := gtk.NewHBox(false, 0)
		cbox := colorBox(bioColors[bio])
		cbox.SetSizeRequest(20, 20)
		biohbox.PackStart(cbox, false, false, 3)
		rbutton := gtk.NewRadioButtonWithLabel(grp, bio.String())
		grp = rbutton.GetGroup()
		rbutton.Connect("toggled", g.mkUpdateBiomeFx(rbutton, bio))
		biohbox.PackEnd(rbutton, true, true, 3)
		vbox.PackStart(biohbox, false, false, 3)
	}

	scrolled := gtk.NewScrolledWindow(nil, nil)
	scrolled.SetPolicy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
	scrolled.AddWithViewPort(vbox)
	return scrolled
}

func (g *GUI) Init() {
	g.window = gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
	g.window.SetTitle("Biome Editor")

	menubar := g.mkMenuBar()
	vbox := gtk.NewVBox(false, 0)
	vbox.PackStart(menubar, false, false, 0)

	hbox := gtk.NewHBox(false, 0)

	g.mapw = NewMapWidget(GUICallbacks{g.reportError, g.updateInfo, g.setBusy})
	hbox.PackStart(g.mapw.DArea(), true, true, 3)

	sidebar := g.mkSidebar()
	hbox.PackEnd(sidebar, false, false, 3)

	vbox.PackStart(hbox, true, true, 0)

	g.statusbar = gtk.NewStatusbar()
	g.statusContext = g.statusbar.GetContextId("mapinfo")
	vbox.PackEnd(g.statusbar, false, false, 0)

	g.window.Add(vbox)
	g.window.SetDefaultSize(800, 600)

	g.window.Connect("destroy", g.exitApp)

	g.setTool(NewFillTool())
}

func (g *GUI) setBusy(b bool) {
	g.window.SetSensitive(!b)
	g.statusbar.Pop(g.statusContext)
	if b {
		g.statusbar.Push(g.statusContext, "!!! PLEASE WAIT !!!")

	} else {
		g.statusbar.Push(g.statusContext, g.lastStatus)
	}
}

func (g *GUI) reportError(msg string) {
	dlg := gtk.NewMessageDialog(g.window, gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, msg)
	dlg.Run()
	dlg.Destroy()
	os.Exit(1)
}

func (g *GUI) updateInfo(x, z int, bio mcmap.Biome) {
	g.lastStatus = fmt.Sprintf("X:%d, Z:%d, Biome:%s", x, z, bio)
	g.statusbar.Pop(g.statusContext)
	g.statusbar.Push(g.statusContext, g.lastStatus)
}

func (g *GUI) mkUpdateToolFx(rb *gtk.RadioButton, t Tool) func() {
	return func() {
		if rb.GetActive() {
			g.setTool(t)
		}
	}
}

func (g *GUI) mkUpdateBiomeFx(rb *gtk.RadioButton, bio mcmap.Biome) func() {
	return func() {
		if rb.GetActive() {
			g.setBiome(bio)
		}
	}
}

func (g *GUI) setTool(t Tool) {
	g.mapw.SetTool(t)
}

func (g *GUI) setBiome(bio mcmap.Biome) {
	g.mapw.SetBiome(bio)
}

func (g *GUI) showbiomesToggled() {
	g.mapw.SetShowBiomes(g.showbiomes.GetActive())
}

func (g *GUI) fixSnowIceToggled() {
	g.mapw.SetFixSnowIce(g.fixSnowIce.GetActive())
}

/*func (g *GUI) undo() {
	fmt.Println("Undo")
}*/

func (g *GUI) Show() {
	g.window.ShowAll()
	g.betaWarning()
}

func (g *GUI) exitApp() {
	gtk.MainQuit()
}

func main() {
	glib.ThreadInit(nil)
	gdk.ThreadsInit()
	gdk.ThreadsEnter()
	gtk.Init(nil)

	gui := new(GUI)
	gui.Init()
	gui.Show()

	gtk.Main()
	gdk.ThreadsLeave()
}
<commit_msg>A small help dialog.<commit_after>package main

import (
	"fmt"
	"github.com/kch42/gomcmap/mcmap"
	"github.com/mattn/go-gtk/gdk"
	"github.com/mattn/go-gtk/glib"
	"github.com/mattn/go-gtk/gtk"
	"os"
)

type GUI struct {
	window    *gtk.Window
	statusbar *gtk.Statusbar

	showbiomes *gtk.CheckButton
	fixSnowIce *gtk.CheckButton

	menuitemSave *gtk.MenuItem

	statusContext uint
	lastStatus    string

	mapw *MapWidget
}

func (g *GUI) openWorldDlg() {
	dlg := gtk.NewFileChooserDialog("Open World (region directory)", g.window, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, "Open Region dir", gtk.RESPONSE_OK, "Cancel", gtk.RESPONSE_CANCEL)
	if dlg.Run() == gtk.RESPONSE_OK {
		g.openWorld(dlg.GetFilename())
	}
	dlg.Destroy()
}

func (g *GUI) openWorld(path string) {
	region, err := mcmap.OpenRegion(path, false)
	if err != nil {
		dlg := gtk.NewMessageDialog(g.window, gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Could not load world %s:\n%s", path, err.Error())
		dlg.Run()
		dlg.Destroy()
	}

	g.menuitemSave.SetSensitive(true)

	g.mapw.SetRegion(region)
}

func (g *GUI) aboutDlg() {
	dlg := gtk.NewAboutDialog()
	dlg.SetName("biome-editor")
	dlg.SetVersion("β")
	dlg.SetCopyright("© 2013 by Kevin Chabowski")
	dlg.SetAuthors([]string{"Kevin Chabowski <kevin@kch42.de>"})
	dlg.SetLicense(`Copyright (c) 2013 Kevin Chabowski

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
`)
	dlg.Run()
	dlg.Destroy()
}

func (g *GUI) mkMenuBar() *gtk.MenuBar {
	menubar := gtk.NewMenuBar()

	fileMenu := gtk.NewMenu()

	open := gtk.NewMenuItemWithLabel("Open")
	open.Connect("activate", g.openWorldDlg)
	fileMenu.Append(open)

	if quickopen, ok := g.mkQuickOpen(); ok {
		quickopenItem := gtk.NewMenuItemWithLabel("Open Map")
		quickopenItem.SetSubmenu(quickopen)
		fileMenu.Append(quickopenItem)
	}

	g.menuitemSave = gtk.NewMenuItemWithLabel("Save")
	g.menuitemSave.Connect("activate", g.save)
	g.menuitemSave.SetSensitive(false)
	fileMenu.Append(g.menuitemSave)

	quit := gtk.NewMenuItemWithLabel("Quit")
	quit.Connect("activate", g.exitApp)
	fileMenu.Append(quit)

	fileMenuItem := gtk.NewMenuItemWithLabel("File")
	fileMenuItem.SetSubmenu(fileMenu)
	menubar.Append(fileMenuItem)

	/*editMenu := gtk.NewMenu()

	undo := gtk.NewMenuItemWithLabel("Undo")
	undo.Connect("activate", g.undo)
	editMenu.Append(undo)

	editMenuItem := gtk.NewMenuItemWithLabel("Edit")
	editMenuItem.SetSubmenu(editMenu)
	menubar.Append(editMenuItem)*/

	helpMenu := gtk.NewMenu()

	controls := gtk.NewMenuItemWithLabel("Controls")
	controls.Connect("activate", func() {
		dlg := gtk.NewMessageDialog(g.window, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Click to use selected tool.\nMiddle mouse button to move around.")
		dlg.Run()
		dlg.Destroy()
	})
	helpMenu.Append(controls)

	about := gtk.NewMenuItemWithLabel("About")
	about.Connect("activate", g.aboutDlg)
	helpMenu.Append(about)

	helpMenuItem := gtk.NewMenuItemWithLabel("Help")
	helpMenuItem.SetSubmenu(helpMenu)
	menubar.Append(helpMenuItem)

	return menubar
}

func (g *GUI) betaWarning() {
	dlg := gtk.NewMessageDialog(g.window, gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "This software is currently in beta.\nAlthough everythung seems to work, you should make a backup of your maps, just in case!")
	dlg.Run()
	dlg.Destroy()
}

func (g *GUI) save() {
	g.setBusy(true)
	g.mapw.Save()
	g.setBusy(false)

	dlg := gtk.NewMessageDialog(g.window, gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Map saved!")
	dlg.Run()
	dlg.Destroy()
}

func (g *GUI) mkQuickOpen() (*gtk.Menu, bool) {
	maps := allMaps()
	if (maps == nil) || (len(maps) == 0) {
		return nil, false
	}

	menu := gtk.NewMenu()
	for name, p := range maps {
		mitem := gtk.NewMenuItemWithLabel(name)
		p2 := p
		mitem.Connect("activate", func() { g.openWorld(p2) })
		menu.Append(mitem)
	}

	return menu, true
}

func labelCustomFont(text, font string) *gtk.Label {
	label := gtk.NewLabel(text)
	label.ModifyFontEasy(font)
	return label
}

func (g *GUI) mkSidebar() *gtk.ScrolledWindow {
	vbox := gtk.NewVBox(false, 0)

	vbox.PackStart(labelCustomFont("Tools", "Sans Bold 14"), false, false, 3)

	g.showbiomes = gtk.NewCheckButtonWithLabel("Show Biomes")
	g.showbiomes.SetActive(true)
	g.showbiomes.Connect("toggled", g.showbiomesToggled)
	vbox.PackStart(g.showbiomes, false, false, 3)

	g.fixSnowIce = gtk.NewCheckButtonWithLabel("Fix Snow/Ice")
	g.fixSnowIce.SetTooltipText("Add Snow/Ice for Taiga/Ice Plains. Remove Snow/Ice for other biomes.")
	g.fixSnowIce.Connect("toggled", g.fixSnowIceToggled)
	vbox.PackStart(g.fixSnowIce, false, false, 3)

	fill := gtk.NewRadioButtonWithLabel(nil, "Fill")
	fill.SetActive(true)
	fill.Connect("toggled", g.mkUpdateToolFx(fill, NewFillTool()))

	draw := gtk.NewRadioButtonWithLabel(fill.GetGroup(), "Draw")
	drawRadius := gtk.NewSpinButtonWithRange(1, 20, 1)
	drawHBox := gtk.NewHBox(false, 0)
	drawHBox.PackStart(draw, true, true, 0)
	drawHBox.PackStart(gtk.NewLabel("Radius:"), false, false, 3)
	drawHBox.PackEnd(drawRadius, false, false, 3)
	draw.Connect("toggled", g.mkUpdateToolFx(draw, NewDrawTool(func() int { return int(drawRadius.GetValue()) })))

	vbox.PackStart(fill, false, false, 3)
	vbox.PackStart(drawHBox, false, false, 3)

	vbox.PackStart(gtk.NewHSeparator(), false, false, 3)
	vbox.PackStart(labelCustomFont("Biomes", "Sans Bold 14"), false, false, 3)

	var grp *glib.SList
	for _, bio := range bioList {
		biohbox := gtk.NewHBox(false, 0)
		cbox := colorBox(bioColors[bio])
		cbox.SetSizeRequest(20, 20)
		biohbox.PackStart(cbox, false, false, 3)
		rbutton := gtk.NewRadioButtonWithLabel(grp, bio.String())
		grp = rbutton.GetGroup()
		rbutton.Connect("toggled", g.mkUpdateBiomeFx(rbutton, bio))
		biohbox.PackEnd(rbutton, true, true, 3)
		vbox.PackStart(biohbox, false, false, 3)
	}

	scrolled := gtk.NewScrolledWindow(nil, nil)
	scrolled.SetPolicy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
	scrolled.AddWithViewPort(vbox)
	return scrolled
}

func (g *GUI) Init() {
	g.window = gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
	g.window.SetTitle("Biome Editor")

	menubar := g.mkMenuBar()
	vbox := gtk.NewVBox(false, 0)
	vbox.PackStart(menubar, false, false, 0)

	hbox := gtk.NewHBox(false, 0)

	g.mapw = NewMapWidget(GUICallbacks{g.reportError, g.updateInfo, g.setBusy})
	hbox.PackStart(g.mapw.DArea(), true, true, 3)

	sidebar := g.mkSidebar()
	hbox.PackEnd(sidebar, false, false, 3)

	vbox.PackStart(hbox, true, true, 0)

	g.statusbar = gtk.NewStatusbar()
	g.statusContext = g.statusbar.GetContextId("mapinfo")
	vbox.PackEnd(g.statusbar, false, false, 0)

	g.window.Add(vbox)
	g.window.SetDefaultSize(800, 600)

	g.window.Connect("destroy", g.exitApp)

	g.setTool(NewFillTool())
}

func (g *GUI) setBusy(b bool) {
	g.window.SetSensitive(!b)
	g.statusbar.Pop(g.statusContext)
	if b {
		g.statusbar.Push(g.statusContext, "!!! PLEASE WAIT !!!")

	} else {
		g.statusbar.Push(g.statusContext, g.lastStatus)
	}
}

func (g *GUI) reportError(msg string) {
	dlg := gtk.NewMessageDialog(g.window, gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, msg)
	dlg.Run()
	dlg.Destroy()
	os.Exit(1)
}

func (g *GUI) updateInfo(x, z int, bio mcmap.Biome) {
	g.lastStatus = fmt.Sprintf("X:%d, Z:%d, Biome:%s", x, z, bio)
	g.statusbar.Pop(g.statusContext)
	g.statusbar.Push(g.statusContext, g.lastStatus)
}

func (g *GUI) mkUpdateToolFx(rb *gtk.RadioButton, t Tool) func() {
	return func() {
		if rb.GetActive() {
			g.setTool(t)
		}
	}
}

func (g *GUI) mkUpdateBiomeFx(rb *gtk.RadioButton, bio mcmap.Biome) func() {
	return func() {
		if rb.GetActive() {
			g.setBiome(bio)
		}
	}
}

func (g *GUI) setTool(t Tool) {
	g.mapw.SetTool(t)
}

func (g *GUI) setBiome(bio mcmap.Biome) {
	g.mapw.SetBiome(bio)
}

func (g *GUI) showbiomesToggled() {
	g.mapw.SetShowBiomes(g.showbiomes.GetActive())
}

func (g *GUI) fixSnowIceToggled() {
	g.mapw.SetFixSnowIce(g.fixSnowIce.GetActive())
}

/*func (g *GUI) undo() {
	fmt.Println("Undo")
}*/

func (g *GUI) Show() {
	g.window.ShowAll()
	g.betaWarning()
}

func (g *GUI) exitApp() {
	gtk.MainQuit()
}

func main() {
	glib.ThreadInit(nil)
	gdk.ThreadsInit()
	gdk.ThreadsEnter()
	gtk.Init(nil)

	gui := new(GUI)
	gui.Init()
	gui.Show()

	gtk.Main()
	gdk.ThreadsLeave()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/iamthemuffinman/logsip"
)

var log = logsip.New(os.Stdout)

func main() {
	// Set config options.
	awsProfile := ""
	sourceElb := ""
	destElb := ""

	// Set AWS_PROFILE env variable on OS.
	err := os.Setenv("AWS_PROFILE", awsProfile)
	if err != nil {
		log.Fatal("Failed to set AWS_PROFILE environment variable", err)
	}
	// Open a new elb session with the aws-sdk.
	svc := elb.New(session.New())

	// Define parameters to pass to DescribeInstanceHealth
	params := &elb.DescribeInstanceHealthInput{LoadBalancerName: aws.String(sourceElb), Instances: []*elb.Instance{}}

	result, err := svc.DescribeInstanceHealth(params)
	if err != nil {
		log.Fatal("Failed to describe ELBs", err)
	}
	// See instances currently registered with sourceElb.
	fmt.Println(result)

	// Loop through registered instances to get instance ids and register them with the destElb.
	for _, instances := range result.InstanceStates {

		id := aws.StringValue(instances.InstanceId)
		resp, err := svc.RegisterInstancesWithLoadBalancer(&elb.RegisterInstancesWithLoadBalancerInput{Instances: []*elb.Instance{{InstanceId: aws.String(id)}}, LoadBalancerName: aws.String(destElb)})
		if err != nil {
			log.Fatal("Failed to register instance", err.Error())
		}
		fmt.Println(resp)
	}

	time.Sleep(20 * time.Second)

	// Define parameters to pass to DescribeInstanceHealth for destElb
	paramsDest := &elb.DescribeInstanceHealthInput{LoadBalancerName: aws.String(destElb), Instances: []*elb.Instance{}}

	resultDest, err := svc.DescribeInstanceHealth(paramsDest)
	if err != nil {
		log.Fatal("Failed to describe ELBs", err.Error())
	}
	// Loop through Instance states for destELB and check if state is InService.
	for _, instances := range resultDest.InstanceStates {
		id := aws.StringValue(instances.InstanceId)
		state := aws.StringValue(instances.State)
		if state != "InService" {
			log.Fatalf("%s is not registered successfully with the load balancer", id)
		} else {
			fmt.Printf("%s registered successfully with the load balancer.\n", id)
		}
	}

}
<commit_msg>Update main.go and remove custom strings<commit_after>package main

import (
	"fmt"
	"os"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/iamthemuffinman/logsip"
)

var log = logsip.New(os.Stdout)

func main() {
	// Set config options.
	sourceElb := "<sourceELB_name_here>"
	destElb := "<destELB_name_here>"

	// Create a new aws session.
	stsSvc := session.New()

	// Get new temporary STS credentials for assumed role.
	getCreds := stscreds.NewCredentials(stsSvc, "<roleARNhere>")

	// Open a new elb session with the aws-sdk and pass in temporary sts credentials.
	svc := elb.New(session.New(&aws.Config{Region: aws.String("us-east-1"), Credentials: getCreds}))

	// Define parameters to pass to DescribeInstanceHealth
	params := &elb.DescribeInstanceHealthInput{LoadBalancerName: aws.String(sourceElb), Instances: []*elb.Instance{}}

	result, err := svc.DescribeInstanceHealth(params)
	if err != nil {
		log.Fatal("Failed to describe ELB: \n", err.Error())
	}

	// See instances currently registered with sourceElb.
	fmt.Printf("Currently registered instances with %s: \n", sourceElb)
	fmt.Println(result)

	// Loop through registered instances to get instance ids and register them with the destElb.
	for _, instances := range result.InstanceStates {

		id := aws.StringValue(instances.InstanceId)
		_, err := svc.RegisterInstancesWithLoadBalancer(&elb.RegisterInstancesWithLoadBalancerInput{Instances: []*elb.Instance{{InstanceId: aws.String(id)}}, LoadBalancerName: aws.String(destElb)})
		if err != nil {
			log.Fatal("Failed to register instance", err.Error())
		}

	}
	// Sleep for 20 seconds to allow instance registration in the destElb.
	fmt.Println("Going to sleep for 20 seconds before checking instance registration status ... ")
	time.Sleep(20 * time.Second)

	// Define parameters to pass to DescribeInstanceHealth for destElb
	paramsDest := &elb.DescribeInstanceHealthInput{LoadBalancerName: aws.String(destElb), Instances: []*elb.Instance{}}

	resultDest, err := svc.DescribeInstanceHealth(paramsDest)
	if err != nil {
		log.Fatal("Failed to describe ELBs", err.Error())
	}
	// Loop through Instance states for destELB and check if state is InService.
	for _, instances := range resultDest.InstanceStates {
		id := aws.StringValue(instances.InstanceId)
		state := aws.StringValue(instances.State)
		if state != "InService" {
			log.Fatalf("%s is not registered successfully with the load balancer", id)
		} else {
			fmt.Printf("%s registered successfully with the load balancer.\n", id)
		}
	}

}

<|endoftext|>