<commit_before>package main

import (
	"pcap";
	"fmt";
	"flag";
	"time";
	"os";
)

const (
	TYPE_IP = 0x0800;
	TYPE_ARP = 0x0806;
	TYPE_IP6 = 0x86DD;

	IP_ICMP = 1;
	IP_INIP = 4;
	IP_TCP = 6;
	IP_UDP = 17;

)

func main() {
	var device *string = flag.String("i", "", "interface");
	var snaplen *int = flag.Int("s", 65535, "snaplen");
	expr := "";

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [ -i interface ] [ -s snaplen ] [ expression ]\n", os.Args[0]);
		os.Exit(1);
	};

	flag.Parse();

	if (len(flag.Args()) > 0) {
		expr = flag.Arg(0);
	}

	if *device == "" {
		flag.Usage();
	}

	h, err := pcap.Openlive(*device, int32(*snaplen), true, 0);
	if h == nil {
		fmt.Fprintf(os.Stderr, "tcpdump: %s\n", err);
		return
	}

	if expr != "" {
		ferr := h.Setfilter(expr);
		if ferr != "" {
			fmt.Printf("tcpdump: %s\n", ferr);
		}
	}

	for pkt := h.Next() ; pkt != nil ; pkt = h.Next() {
		Printpacket(pkt);
	}

}

func Printpacket(pkt *pcap.Packet) {
	//destmac := Decodemac(pkt.Data[0:6]);
	//srcmac := Decodemac(pkt.Data[6:12]);
	pkttype := Decodeuint16(pkt.Data[12:14]);

	t := time.SecondsToLocalTime(int64(pkt.Time.Sec));
	fmt.Printf("%02d:%02d:%02d.%06d ", t.Hour, t.Minute, t.Second, pkt.Time.Usec);

	//fmt.Printf("%012x -> %012x ", srcmac, destmac);

	switch pkttype {
		case TYPE_IP: Decodeip(pkt.Data[14:])
		case TYPE_ARP: Decodearp(pkt.Data[14:])
		case TYPE_IP6: Decodeip6(pkt.Data[14:]);
		default: Unsupported(pkttype)
	}

	fmt.Printf("\n");
}

func Decodemac(pkt []byte) uint64 {
	mac := uint64(0);
	for i:= uint(0) ; i < 6 ; i++ {
		mac = (mac << 8) + uint64(pkt[i]);
	}
	return mac
}

func Decodeuint16(pkt []byte) uint16 {
	return uint16(pkt[0]) << 8 + uint16(pkt[1])
}

func Decodeuint32(pkt []byte) uint32 {
	return uint32(pkt[0]) << 24 + uint32(pkt[1]) << 16 + uint32(pkt[2]) << 8 + uint32(pkt[3])
}

func Unsupported(pkttype uint16) {
	fmt.Printf("unsupported protocol %d", int(pkttype));
}

type Arphdr struct {
	Addrtype uint16;
	Protocol uint16;
	HwAddressSize uint8;
	ProtAddressSize uint8;
	Operation uint16;
	SourceHwAddress []byte;
	SourceProtAddress []byte;
	DestHwAddress []byte;
	DestProtAddress []byte;
}

func Arpop(op uint16) string {
	switch op {
		case 1: return "Request"
		case 2: return "Reply"
	}
	return ""
}

func Decodearp(pkt []byte) {
	arp := new(Arphdr);
	arp.Addrtype = Decodeuint16(pkt[0:2]);
	arp.Protocol = Decodeuint16(pkt[2:4]);
	arp.HwAddressSize = pkt[4];
	arp.ProtAddressSize = pkt[5];
	arp.Operation = Decodeuint16(pkt[6:8]);
	arp.SourceHwAddress = pkt[8:8+arp.HwAddressSize];
	arp.SourceProtAddress = pkt[8+arp.HwAddressSize:8+arp.HwAddressSize+arp.ProtAddressSize];
	arp.DestHwAddress = pkt[8+arp.HwAddressSize+arp.ProtAddressSize:8+2*arp.HwAddressSize+arp.ProtAddressSize];
	arp.DestProtAddress = pkt[8+2*arp.HwAddressSize+arp.ProtAddressSize:8+2*arp.HwAddressSize+2*arp.ProtAddressSize];

	fmt.Printf("ARP %s ", Arpop(arp.Operation));

	if arp.Addrtype == pcap.LINKTYPE_ETHERNET && arp.Protocol == TYPE_IP {
		fmt.Printf("%012x (", Decodemac(arp.SourceHwAddress));
		Printip(arp.SourceProtAddress);
		fmt.Printf(") > %012x (", Decodemac(arp.DestHwAddress));
		Printip(arp.DestProtAddress);
		fmt.Printf(")")
	} else {
		fmt.Printf("addrtype = %d protocol = %d", arp.Addrtype, arp.Protocol)
	}
}

type Iphdr struct {
	Version uint8;
	Ihl uint8;
	Tos uint8;
	Length uint16;
	Id uint16;
	Flags uint8;
	FragOffset uint16;
	Ttl uint8;
	Protocol uint8;
	Checksum uint16;
	SrcIp []byte;
	DestIp []byte;
}

func Decodeip(pkt []byte) {
	ip := new(Iphdr);

	ip.Version = uint8(pkt[0]) >> 4;
	ip.Ihl = uint8(pkt[0]) & 0x0F;;
	ip.Tos = pkt[1];
	ip.Length = Decodeuint16(pkt[2:4]);
	ip.Id = Decodeuint16(pkt[4:6]);
	flagsfrags := Decodeuint16(pkt[6:8]);
	ip.Flags = uint8(flagsfrags >> 13);
	ip.FragOffset = flagsfrags & 0x1FFF;
	ip.Ttl = pkt[8];
	ip.Protocol = pkt[9];
	ip.Checksum = Decodeuint16(pkt[10:12]);
	ip.SrcIp = pkt[12:16];
	ip.DestIp = pkt[16:20];

	switch ip.Protocol {
		case IP_TCP: Decodetcp(ip, pkt[ip.Ihl*4:])
		case IP_UDP: Decodeudp(ip, pkt[ip.Ihl*4:])
		case IP_ICMP: Decodeicmp(ip, pkt[ip.Ihl*4:])
		case IP_INIP:
			Printip(ip.SrcIp);
			fmt.Printf(" > ");
			Printip(ip.DestIp);
			fmt.Printf(" IP in IP: ");
			Decodeip(pkt[ip.Ihl*4:]);
		default:
			Printip(ip.SrcIp);
			fmt.Printf(" > ");
			Printip(ip.DestIp);
			fmt.Printf(" unsupported protocol %d", int(ip.Protocol));
	}
}

type Tcphdr struct {
	SrcPort uint16;
	DestPort uint16;
	Seq uint32;
	Ack uint32;
	DataOffset uint8;
	Flags uint8;
	Window uint16;
	Checksum uint16;
	Urgent uint16;
	Data []byte;
}

const (
	TCP_FIN = 1 << iota;
	TCP_SYN;
	TCP_RST;
	TCP_PSH;
	TCP_ACK;
	TCP_URG;
)

func Decodetcp(ip *Iphdr, pkt []byte) {
	tcp := new(Tcphdr);
	tcp.SrcPort = Decodeuint16(pkt[0:2]);
	tcp.DestPort = Decodeuint16(pkt[2:4]);
	tcp.Seq = Decodeuint32(pkt[4:8]);
	tcp.Ack = Decodeuint32(pkt[8:12]);
	tcp.DataOffset = pkt[12] & 0x0F;
	tcp.Flags = uint8(Decodeuint16(pkt[12:14]) & 0x3F);
	tcp.Window = Decodeuint16(pkt[14:16]);
	tcp.Checksum = Decodeuint16(pkt[16:18]);
	tcp.Urgent = Decodeuint16(pkt[18:20]);
	tcp.Data = pkt[tcp.DataOffset*4:];

	Printtcp(ip, tcp);
}

func Printtcp(ip *Iphdr, tcp *Tcphdr) {
	fmt.Printf("TCP ");
	Printip(ip.SrcIp);
	fmt.Printf(":%d > ", int(tcp.SrcPort));
	Printip(ip.DestIp);
	fmt.Printf(":%d ", int(tcp.DestPort));
	Printflags(tcp.Flags);
	fmt.Printf(" SEQ=%d ACK=%d", int64(tcp.Seq), int64(tcp.Ack))
}

func Printflags(flags uint8) {
	fmt.Printf("[ ");
	if 0 != (flags & TCP_SYN) {
		fmt.Printf("syn ")
	}
	if 0 != (flags & TCP_FIN) {
		fmt.Printf("fin ")
	}
	if 0 != (flags & TCP_ACK) {
		fmt.Printf("ack ")
	}
	if 0 != (flags & TCP_PSH) {
		fmt.Printf("psh ")
	}
	if 0 != (flags & TCP_RST) {
		fmt.Printf("rst ")
	}
	if 0 != (flags & TCP_URG) {
		fmt.Printf("urg ")
	}
	fmt.Printf("]")
}

func Printip(ip []byte) {
	for i:=0;i<4;i++ {
		fmt.Printf("%d", int(ip[i]));
		if i < 3 {
			fmt.Printf(".");
		}
	}
}

type Udphdr struct {
	SrcPort uint16;
	DestPort uint16;
	Length uint16;
	Checksum uint16;
}

func Decodeudp(ip *Iphdr, pkt []byte) {
	udp := new(Udphdr);
	udp.SrcPort = Decodeuint16(pkt[0:2]);
	udp.DestPort = Decodeuint16(pkt[2:4]);
	udp.Length = Decodeuint16(pkt[4:6]);
	udp.Checksum = Decodeuint16(pkt[6:8]);

	fmt.Printf("UDP ");
	Printip(ip.SrcIp);
	fmt.Printf(":%d > ", udp.SrcPort);
	Printip(ip.DestIp);
	fmt.Printf(":%d LEN=%d CHKSUM=%d", int(udp.DestPort), int(udp.Length), int(udp.Checksum));
}

type Icmphdr struct {
	Type uint8;
	Code uint8;
	Checksum uint16;
	Id uint16;
	Seq uint16;
	Data []byte;
}

func Decodeicmp(ip *Iphdr, pkt []byte) {
	icmp := new(Icmphdr);
	icmp.Type = pkt[0];
	icmp.Code = pkt[1];
	icmp.Checksum = Decodeuint16(pkt[2:4]);
	icmp.Id = Decodeuint16(pkt[4:6]);
	icmp.Seq = Decodeuint16(pkt[6:8]);
	icmp.Data = pkt[8:];

	Printicmp(ip, icmp);
}

func Printicmp(ip *Iphdr, icmp *Icmphdr) {
	fmt.Printf("ICMP ");
	Printip(ip.SrcIp);
	fmt.Printf(" > ");
	Printip(ip.DestIp);
	fmt.Printf(" Type = %d Code = %d ", icmp.Type, icmp.Code);
	switch icmp.Type {
		case 0: fmt.Printf("Echo reply ttl=%d seq=%d", ip.Ttl, icmp.Seq)
		case 3:
			switch icmp.Code {
				case 0: fmt.Printf("Network unreachable")
				case 1: fmt.Printf("Host unreachable")
				case 2: fmt.Printf("Protocol unreachable")
				case 3: fmt.Printf("Port unreachable")
				default: fmt.Printf("Destination unreachable")
			}
		case 8: fmt.Printf("Echo request ttl=%d seq=%d", ip.Ttl, icmp.Seq)
		case 30: fmt.Printf("Traceroute")
	}
}

func Decodeip6(pkt []byte) {
	fmt.Printf("TODO: IPv6")
}
<commit_msg>implemented -X flag to print packet hex dumps.<commit_after>package main

import (
	"pcap";
	"fmt";
	"flag";
	"time";
	"os";
)

const (
	TYPE_IP = 0x0800;
	TYPE_ARP = 0x0806;
	TYPE_IP6 = 0x86DD;

	IP_ICMP = 1;
	IP_INIP = 4;
	IP_TCP = 6;
	IP_UDP = 17;

)

func main() {
	var device *string = flag.String("i", "", "interface");
	var snaplen *int = flag.Int("s", 65535, "snaplen");
	var hexdump *bool = flag.Bool("X", false, "hexdump");
	expr := "";

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [ -i interface ] [ -s snaplen ] [ -X ] [ expression ]\n", os.Args[0]);
		os.Exit(1);
	};

	flag.Parse();

	if (len(flag.Args()) > 0) {
		expr = flag.Arg(0);
	}

	if *device == "" {
		devs, err := pcap.Findalldevs();
		if err != "" {
			fmt.Fprintf(os.Stderr, "tcpdump: couldn't find any devices: %s\n", err);
		}
		if 0 == len(devs) {
			flag.Usage();
		}
		*device = devs[0].Name;
	}

	h, err := pcap.Openlive(*device, int32(*snaplen), true, 0);
	if h == nil {
		fmt.Fprintf(os.Stderr, "tcpdump: %s\n", err);
		return
	}

	if expr != "" {
		ferr := h.Setfilter(expr);
		if ferr != "" {
			fmt.Printf("tcpdump: %s\n", ferr);
		}
	}

	for pkt := h.Next() ; pkt != nil ; pkt = h.Next() {
		Printpacket(pkt);
		if *hexdump {
			Hexdump(pkt);
		}
	}

}

func Printpacket(pkt *pcap.Packet) {
	//destmac := Decodemac(pkt.Data[0:6]);
	//srcmac := Decodemac(pkt.Data[6:12]);
	pkttype := Decodeuint16(pkt.Data[12:14]);

	t := time.SecondsToLocalTime(int64(pkt.Time.Sec));
	fmt.Printf("%02d:%02d:%02d.%06d ", t.Hour, t.Minute, t.Second, pkt.Time.Usec);

	//fmt.Printf("%012x -> %012x ", srcmac, destmac);

	switch pkttype {
		case TYPE_IP: Decodeip(pkt.Data[14:])
		case TYPE_ARP: Decodearp(pkt.Data[14:])
		case TYPE_IP6: Decodeip6(pkt.Data[14:]);
		default: Unsupported(pkttype)
	}

	fmt.Printf("\n");
}

func Decodemac(pkt []byte) uint64 {
	mac := uint64(0);
	for i:= uint(0) ; i < 6 ; i++ {
		mac = (mac << 8) + uint64(pkt[i]);
	}
	return mac
}

func Decodeuint16(pkt []byte) uint16 {
	return uint16(pkt[0]) << 8 + uint16(pkt[1])
}

func Decodeuint32(pkt []byte) uint32 {
	return uint32(pkt[0]) << 24 + uint32(pkt[1]) << 16 + uint32(pkt[2]) << 8 + uint32(pkt[3])
}

func Unsupported(pkttype uint16) {
	fmt.Printf("unsupported protocol %d", int(pkttype));
}

type Arphdr struct {
	Addrtype uint16;
	Protocol uint16;
	HwAddressSize uint8;
	ProtAddressSize uint8;
	Operation uint16;
	SourceHwAddress []byte;
	SourceProtAddress []byte;
	DestHwAddress []byte;
	DestProtAddress []byte;
}

func Arpop(op uint16) string {
	switch op {
		case 1: return "Request"
		case 2: return "Reply"
	}
	return ""
}

func Decodearp(pkt []byte) {
	arp := new(Arphdr);
	arp.Addrtype = Decodeuint16(pkt[0:2]);
	arp.Protocol = Decodeuint16(pkt[2:4]);
	arp.HwAddressSize = pkt[4];
	arp.ProtAddressSize = pkt[5];
	arp.Operation = Decodeuint16(pkt[6:8]);
	arp.SourceHwAddress = pkt[8:8+arp.HwAddressSize];
	arp.SourceProtAddress = pkt[8+arp.HwAddressSize:8+arp.HwAddressSize+arp.ProtAddressSize];
	arp.DestHwAddress = pkt[8+arp.HwAddressSize+arp.ProtAddressSize:8+2*arp.HwAddressSize+arp.ProtAddressSize];
	arp.DestProtAddress = pkt[8+2*arp.HwAddressSize+arp.ProtAddressSize:8+2*arp.HwAddressSize+2*arp.ProtAddressSize];

	fmt.Printf("ARP %s ", Arpop(arp.Operation));

	if arp.Addrtype == pcap.LINKTYPE_ETHERNET && arp.Protocol == TYPE_IP {
		fmt.Printf("%012x (", Decodemac(arp.SourceHwAddress));
		Printip(arp.SourceProtAddress);
		fmt.Printf(") > %012x (", Decodemac(arp.DestHwAddress));
		Printip(arp.DestProtAddress);
		fmt.Printf(")")
	} else {
		fmt.Printf("addrtype = %d protocol = %d", arp.Addrtype, arp.Protocol)
	}
}

type Iphdr struct {
	Version uint8;
	Ihl uint8;
	Tos uint8;
	Length uint16;
	Id uint16;
	Flags uint8;
	FragOffset uint16;
	Ttl uint8;
	Protocol uint8;
	Checksum uint16;
	SrcIp []byte;
	DestIp []byte;
}

func Decodeip(pkt []byte) {
	ip := new(Iphdr);

	ip.Version = uint8(pkt[0]) >> 4;
	ip.Ihl = uint8(pkt[0]) & 0x0F;;
	ip.Tos = pkt[1];
	ip.Length = Decodeuint16(pkt[2:4]);
	ip.Id = Decodeuint16(pkt[4:6]);
	flagsfrags := Decodeuint16(pkt[6:8]);
	ip.Flags = uint8(flagsfrags >> 13);
	ip.FragOffset = flagsfrags & 0x1FFF;
	ip.Ttl = pkt[8];
	ip.Protocol = pkt[9];
	ip.Checksum = Decodeuint16(pkt[10:12]);
	ip.SrcIp = pkt[12:16];
	ip.DestIp = pkt[16:20];

	switch ip.Protocol {
		case IP_TCP: Decodetcp(ip, pkt[ip.Ihl*4:])
		case IP_UDP: Decodeudp(ip, pkt[ip.Ihl*4:])
		case IP_ICMP: Decodeicmp(ip, pkt[ip.Ihl*4:])
		case IP_INIP:
			Printip(ip.SrcIp);
			fmt.Printf(" > ");
			Printip(ip.DestIp);
			fmt.Printf(" IP in IP: ");
			Decodeip(pkt[ip.Ihl*4:]);
		default:
			Printip(ip.SrcIp);
			fmt.Printf(" > ");
			Printip(ip.DestIp);
			fmt.Printf(" unsupported protocol %d", int(ip.Protocol));
	}
}

type Tcphdr struct {
	SrcPort uint16;
	DestPort uint16;
	Seq uint32;
	Ack uint32;
	DataOffset uint8;
	Flags uint8;
	Window uint16;
	Checksum uint16;
	Urgent uint16;
	Data []byte;
}

const (
	TCP_FIN = 1 << iota;
	TCP_SYN;
	TCP_RST;
	TCP_PSH;
	TCP_ACK;
	TCP_URG;
)

func Decodetcp(ip *Iphdr, pkt []byte) {
	tcp := new(Tcphdr);
	tcp.SrcPort = Decodeuint16(pkt[0:2]);
	tcp.DestPort = Decodeuint16(pkt[2:4]);
	tcp.Seq = Decodeuint32(pkt[4:8]);
	tcp.Ack = Decodeuint32(pkt[8:12]);
	tcp.DataOffset = pkt[12] & 0x0F;
	tcp.Flags = uint8(Decodeuint16(pkt[12:14]) & 0x3F);
	tcp.Window = Decodeuint16(pkt[14:16]);
	tcp.Checksum = Decodeuint16(pkt[16:18]);
	tcp.Urgent = Decodeuint16(pkt[18:20]);
	tcp.Data = pkt[tcp.DataOffset*4:];

	Printtcp(ip, tcp);
}

func Printtcp(ip *Iphdr, tcp *Tcphdr) {
	fmt.Printf("TCP ");
	Printip(ip.SrcIp);
	fmt.Printf(":%d > ", int(tcp.SrcPort));
	Printip(ip.DestIp);
	fmt.Printf(":%d ", int(tcp.DestPort));
	Printflags(tcp.Flags);
	fmt.Printf(" SEQ=%d ACK=%d", int64(tcp.Seq), int64(tcp.Ack))
}

func Printflags(flags uint8) {
	fmt.Printf("[ ");
	if 0 != (flags & TCP_SYN) {
		fmt.Printf("syn ")
	}
	if 0 != (flags & TCP_FIN) {
		fmt.Printf("fin ")
	}
	if 0 != (flags & TCP_ACK) {
		fmt.Printf("ack ")
	}
	if 0 != (flags & TCP_PSH) {
		fmt.Printf("psh ")
	}
	if 0 != (flags & TCP_RST) {
		fmt.Printf("rst ")
	}
	if 0 != (flags & TCP_URG) {
		fmt.Printf("urg ")
	}
	fmt.Printf("]")
}

func Printip(ip []byte) {
	for i:=0;i<4;i++ {
		fmt.Printf("%d", int(ip[i]));
		if i < 3 {
			fmt.Printf(".");
		}
	}
}

type Udphdr struct {
	SrcPort uint16;
	DestPort uint16;
	Length uint16;
	Checksum uint16;
}

func Decodeudp(ip *Iphdr, pkt []byte) {
	udp := new(Udphdr);
	udp.SrcPort = Decodeuint16(pkt[0:2]);
	udp.DestPort = Decodeuint16(pkt[2:4]);
	udp.Length = Decodeuint16(pkt[4:6]);
	udp.Checksum = Decodeuint16(pkt[6:8]);

	fmt.Printf("UDP ");
	Printip(ip.SrcIp);
	fmt.Printf(":%d > ", udp.SrcPort);
	Printip(ip.DestIp);
	fmt.Printf(":%d LEN=%d CHKSUM=%d", int(udp.DestPort), int(udp.Length), int(udp.Checksum));
}

type Icmphdr struct {
	Type uint8;
	Code uint8;
	Checksum uint16;
	Id uint16;
	Seq uint16;
	Data []byte;
}

func Decodeicmp(ip *Iphdr, pkt []byte) {
	icmp := new(Icmphdr);
	icmp.Type = pkt[0];
	icmp.Code = pkt[1];
	icmp.Checksum = Decodeuint16(pkt[2:4]);
	icmp.Id = Decodeuint16(pkt[4:6]);
	icmp.Seq = Decodeuint16(pkt[6:8]);
	icmp.Data = pkt[8:];

	Printicmp(ip, icmp);
}

func Printicmp(ip *Iphdr, icmp *Icmphdr) {
	fmt.Printf("ICMP ");
	Printip(ip.SrcIp);
	fmt.Printf(" > ");
	Printip(ip.DestIp);
	fmt.Printf(" Type = %d Code = %d ", icmp.Type, icmp.Code);
	switch icmp.Type {
		case 0: fmt.Printf("Echo reply ttl=%d seq=%d", ip.Ttl, icmp.Seq)
		case 3:
			switch icmp.Code {
				case 0: fmt.Printf("Network unreachable")
				case 1: fmt.Printf("Host unreachable")
				case 2: fmt.Printf("Protocol unreachable")
				case 3: fmt.Printf("Port unreachable")
				default: fmt.Printf("Destination unreachable")
			}
		case 8: fmt.Printf("Echo request ttl=%d seq=%d", ip.Ttl, icmp.Seq)
		case 30: fmt.Printf("Traceroute")
	}
}

func Decodeip6(pkt []byte) {
	fmt.Printf("TODO: IPv6")
}

func min(a, b int) int {
	if a < b {
		return a;
	}
	return b;
}

func Hexdump(pkt *pcap.Packet) {
	for i := 0 ; i < len(pkt.Data) ; i += 16 {
		Dumpline(uint32(i), pkt.Data[i:min(i+16,len(pkt.Data))]);
	}
}

func Dumpline(addr uint32, line []byte) {
	fmt.Printf("\t0x%04x: ", int32(addr));
	var i uint16;
	for i = 0 ; i < 16 && i < uint16(len(line)) ; i++ {
		if i % 2 == 0 {
			fmt.Printf(" ");
		}
		fmt.Printf("%02x", line[i]);
	}
	for j := i ; j <= 16 ; j++ {
		if j % 2 == 0 {
			fmt.Printf(" ");
		}
		fmt.Printf("  ");
	}
	fmt.Printf("  ");
	for i = 0 ; i < 16 && i < uint16(len(line)) ; i++ {
		if (line[i] >= 32 && line[i] <= 126) {
			fmt.Printf("%c", line[i]);
		} else {
			fmt.Printf(".");
		}
	}
	fmt.Printf("\n");
}
<|endoftext|>


<commit_before>// Copyright 2013 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Tee transcribes the standard input to the standard output and makes copies in the files.

The options are:
      –a    Append the output to the files rather than rewriting them.
*/

package main

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

var append = flag.Bool("a", false, "append the output to the files rather than rewriting them")

func main() {
	var buf [8192]byte

	flag.Parse()

	oflags := os.O_WRONLY | os.O_CREATE
	if *append {
		oflags |= os.O_APPEND
	}

	files := make([]*os.File, flag.NArg())
	for i, v := range flag.Args() {
		f, err := os.OpenFile(v, oflags, 0666)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error opening %s: %v", v, err)
			os.Exit(1)
		}
		files[i] = f
	}

	for {
		n, err := os.Stdin.Read(buf[:])
		if err != nil {
			if err != io.EOF {
				fmt.Fprintf(os.Stderr, "error reading stdin: %v\n", err)
			}
			os.Exit(1)
		}

		os.Stdout.Write(buf[:n])
		for _, v := range files {
			v.Write(buf[:n])
		}
	}
}
<commit_msg>Tee: don't exit with status 1 on EOF.<commit_after>// Copyright 2013 the u-root Authors. All rights reserved
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Tee transcribes the standard input to the standard output and makes copies in the files.

The options are:
      –a    Append the output to the files rather than rewriting them.
*/

package main

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

var append = flag.Bool("a", false, "append the output to the files rather than rewriting them")

func main() {
	var buf [8192]byte

	flag.Parse()

	oflags := os.O_WRONLY | os.O_CREATE
	if *append {
		oflags |= os.O_APPEND
	}

	files := make([]*os.File, flag.NArg())
	for i, v := range flag.Args() {
		f, err := os.OpenFile(v, oflags, 0666)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error opening %s: %v", v, err)
			os.Exit(1)
		}
		files[i] = f
	}

	for {
		n, err := os.Stdin.Read(buf[:])
		if err != nil {
			if err != io.EOF {
				fmt.Fprintf(os.Stderr, "error reading stdin: %v\n", err)
				os.Exit(1)
			}
			break
		}

		os.Stdout.Write(buf[:n])
		for _, v := range files {
			v.Write(buf[:n])
		}
	}
}
<|endoftext|>


<commit_before>package tenordb

import (
	"encoding/json"
	"fmt"
	"github.com/zephyyrr/goda"
	"io/ioutil"
	"log"
)

var dba *goda.DatabaseAdministrator
var storerMap map[string]goda.Storer

var debugging = true

func init() {
	if debugging {
		log.Println("Connecting to Database...")
	}
	//Setup Database Connection
	var err error
	dba, err = goda.NewDatabaseAdministrator(goda.LoadPGEnv())
	if err != nil {
		log.Fatalln("TenorDB: Database Connection Error: ", err)
	}
	storerMap = make(map[string]goda.Storer)
	storerMap["AbsNote"], err = dba.Storer("absnote", AbsNote{})
	if err != nil {
		panic(err)
	}
	storerMap["RelNote"], _ = dba.Storer("relnote", RelNote{})
	if err != nil {
		panic(err)
	}
	storerMap["Chord"], _ = dba.Storer("chord", Chord{})
	if err != nil {
		panic(err)
	}
	storerMap["Scale"], _ = dba.Storer("scale", Scale{})
	if err != nil {
		panic(err)
	}
	storerMap["ChordPattern"], _ = dba.Storer("chordpattern", ChordPattern{})
	if err != nil {
		panic(err)
	}
	storerMap["ScalePattern"], _ = dba.Storer("scalepattern", ScalePattern{})
	if err != nil {
		panic(err)
	}
	storerMap["ChordNote"], _ = dba.Storer("chordnote", ChordNote{})
	if err != nil {
		panic(err)
	}
	storerMap["ScaleNote"], _ = dba.Storer("scalenote", ScaleNote{})
	if err != nil {
		panic(err)
	}
	storerMap["ChordPatternNote"], _ = dba.Storer("chordpatternnote", ChordPatternNote{})
	if err != nil {
		panic(err)
	}
	storerMap["ScalePatternNote"], _ = dba.Storer("scalepatternnote", ScalePatternNote{})
	if err != nil {
		panic(err)
	}

	if debugging {
		log.Println("Initialize Finished!")
	}
}

func deleteTables() error {
	var err error
	tables := []string{
		"chordnote",
		"scalenote",
		"chord",
		"scale",
		"chordpatternnote",
		"scalepatternnote",
		"chordpattern",
		"scalepattern",
		"absnote",
		"relnote",
	}

	for _, table := range tables {
		_, err = dba.Query(fmt.Sprintf("DELETE FROM %s;", table))
		if err != nil {
			return err
		}
	}
	return nil
}

func insertNotes() error {
	// Gen Notes
	var err error
	chrom := []string{"C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B"}
	for i, name := range chrom {
		err = storerMap["AbsNote"].Store(AbsNote{Id: i, Name: name})
		if err != nil {
			log.Println(err)
			return err
		}
		// TODO Find some relevant name for relative notes, like "major third"...
		err = storerMap["RelNote"].Store(RelNote{Id: i, Name: ""})
		if err != nil {
			return err
		}
	}
	return nil
}

func fetchPatternMapFromDB(filename string)(map[int][]int, error){
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	query := string(data)
	rows, err := dba.Query(query)
	if err != nil {
		return nil, err
	}
	patternMap := make(map[int][]int)
	for rows.Next() {
		var cp_id, rn_id int
		var cp_name string
		rows.Scan(&cp_id, &cp_name, &rn_id)
		if _, ok := patternMap[cp_id]; !ok {
			patternMap[cp_id] = make([]int, 0)
		}
		patternMap[cp_id] = append(patternMap[cp_id], rn_id)
	}

	return patternMap, nil
}

func loadJSON(filename string) (map[string]interface{}, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	jsonMap := make(map[string]interface{})
	err = json.Unmarshal(data, &jsonMap)
	if err != nil {
		return nil, err
	}

	return jsonMap, nil
}

func extractMap(jsonMap map[string]interface{}) (map[string][]int, error) {
	resultMap := make(map[string][]int)
	for _, jmValue := range jsonMap {
		valueSlice := jmValue.([]interface{})
		for _, patternMap := range valueSlice {

			mapv := patternMap.(map[string]interface{})

			patternName := mapv["name"].(string)
			notes := make([]int, 0)
			for _, mv := range mapv["notes"].([]interface{}) {
				notes = append(notes, int(mv.(float64)))
			}
			resultMap[patternName] = notes

		}
	}

	return resultMap, nil
}

func loadPatternMap(filename string) (map[string][]int, error) {
	var err error

	jsonMap, err := loadJSON(filename)

	if err != nil {
		return nil, err
	}

	chordPatternMap, err := extractMap(jsonMap)

	if err != nil {
		return nil, err
	}
	return chordPatternMap, nil
}

func Setup() error {
	var err error

	// Delete old data
	err = deleteTables()
	if err != nil {
		log.Println(err)
		return err
	}

	// Insert absolute and relative notes
	err = insertNotes()
	if err != nil {
		log.Println(err)
		return err
	}

	// Insert chord patterns into the database
	err = insertChordPatterns()
	if err != nil {
		log.Println(err)
		return err
	}

	// Insert chords into the database
	err = insertChords()
	if err != nil {
		log.Println(err)
		return err
	}

	// Insert scale patterns into the database

	err = insertScalePatterns()
	if err != nil {
		log.Println(err)
		return err
	}
	// Insert scales into the database
	err = insertScales()
	if err != nil {
		log.Println(err)
		return err
	}

	return nil
}
<commit_msg>New assemble chord function, the initial design<commit_after>package tenordb

import (
	"encoding/json"
	"fmt"
	"github.com/zephyyrr/goda"
	"io/ioutil"
	"log"
)

var dba *goda.DatabaseAdministrator
var storerMap map[string]goda.Storer

var debugging = true

func init() {
	if debugging {
		log.Println("Connecting to Database...")
	}
	//Setup Database Connection
	var err error
	dba, err = goda.NewDatabaseAdministrator(goda.LoadPGEnv())
	if err != nil {
		log.Fatalln("TenorDB: Database Connection Error: ", err)
	}
	storerMap = make(map[string]goda.Storer)
	storerMap["AbsNote"], err = dba.Storer("absnote", AbsNote{})
	if err != nil {
		panic(err)
	}
	storerMap["RelNote"], _ = dba.Storer("relnote", RelNote{})
	if err != nil {
		panic(err)
	}
	storerMap["Chord"], _ = dba.Storer("chord", Chord{})
	if err != nil {
		panic(err)
	}
	storerMap["Scale"], _ = dba.Storer("scale", Scale{})
	if err != nil {
		panic(err)
	}
	storerMap["ChordPattern"], _ = dba.Storer("chordpattern", ChordPattern{})
	if err != nil {
		panic(err)
	}
	storerMap["ScalePattern"], _ = dba.Storer("scalepattern", ScalePattern{})
	if err != nil {
		panic(err)
	}
	storerMap["ChordNote"], _ = dba.Storer("chordnote", ChordNote{})
	if err != nil {
		panic(err)
	}
	storerMap["ScaleNote"], _ = dba.Storer("scalenote", ScaleNote{})
	if err != nil {
		panic(err)
	}
	storerMap["ChordPatternNote"], _ = dba.Storer("chordpatternnote", ChordPatternNote{})
	if err != nil {
		panic(err)
	}
	storerMap["ScalePatternNote"], _ = dba.Storer("scalepatternnote", ScalePatternNote{})
	if err != nil {
		panic(err)
	}

	if debugging {
		log.Println("Initialize Finished!")
	}
}

func deleteTables() error {
	var err error
	tables := []string{
		"chordnote",
		"scalenote",
		"chord",
		"scale",
		"chordpatternnote",
		"scalepatternnote",
		"chordpattern",
		"scalepattern",
		"absnote",
		"relnote",
	}

	for _, table := range tables {
		_, err = dba.Query(fmt.Sprintf("DELETE FROM %s;", table))
		if err != nil {
			return err
		}
	}
	return nil
}

func insertNotes() error {
	// Gen Notes
	var err error
	chrom := []string{"C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B"}
	for i, name := range chrom {
		err = storerMap["AbsNote"].Store(AbsNote{Id: i, Name: name})
		if err != nil {
			log.Println(err)
			return err
		}
		// TODO Find some relevant name for relative notes, like "major third"...
		err = storerMap["RelNote"].Store(RelNote{Id: i, Name: ""})
		if err != nil {
			return err
		}
	}
	return nil
}

func fetchPatternMapFromDB(filename string)(map[int][]int, error){
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	query := string(data)
	rows, err := dba.Query(query)
	if err != nil {
		return nil, err
	}
	patternMap := make(map[int][]int)
	for rows.Next() {
		var cp_id, rn_id int
		var cp_name string
		rows.Scan(&cp_id, &cp_name, &rn_id)
		if _, ok := patternMap[cp_id]; !ok {
			patternMap[cp_id] = make([]int, 0)
		}
		patternMap[cp_id] = append(patternMap[cp_id], rn_id)
	}

	return patternMap, nil
}

func loadJSON(filename string) (map[string]interface{}, error) {
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}

	jsonMap := make(map[string]interface{})
	err = json.Unmarshal(data, &jsonMap)
	if err != nil {
		return nil, err
	}

	return jsonMap, nil
}

func extractMap(jsonMap map[string]interface{}) (map[string][]int, error) {
	resultMap := make(map[string][]int)
	for _, jmValue := range jsonMap {
		valueSlice := jmValue.([]interface{})
		for _, patternMap := range valueSlice {

			mapv := patternMap.(map[string]interface{})

			patternName := mapv["name"].(string)
			notes := make([]int, 0)
			for _, mv := range mapv["notes"].([]interface{}) {
				notes = append(notes, int(mv.(float64)))
			}
			resultMap[patternName] = notes

		}
	}

	return resultMap, nil
}

func loadPatternMap(filename string) (map[string][]int, error) {
	var err error

	jsonMap, err := loadJSON(filename)

	if err != nil {
		return nil, err
	}

	chordPatternMap, err := extractMap(jsonMap)

	if err != nil {
		return nil, err
	}
	return chordPatternMap, nil
}

func Setup() error {
	var err error

	// Delete old data
	err = deleteTables()
	if err != nil {
		log.Println(err)
		return err
	}

	// Insert absolute and relative notes
	err = insertNotes()
	if err != nil {
		log.Println(err)
		return err
	}

	// Insert chord patterns into the database
	err = insertChordPatterns()
	if err != nil {
		log.Println(err)
		return err
	}

	// Insert chords into the database
	err = insertChords()
	if err != nil {
		log.Println(err)
		return err
	}

	// Insert scale patterns into the database

	err = insertScalePatterns()
	if err != nil {
		log.Println(err)
		return err
	}
	// Insert scales into the database
	err = insertScales()
	if err != nil {
		log.Println(err)
		return err
	}

	return nil
}

func AssembleChord(notes []string) ([]string, error){
	if len(notes) == 0 {
		return nil, nil
	}

	data, err := ioutil.ReadFile("tmpl/assembleChords.sql.tmpl")
	if err != nil {
		return nil, err
	}

	tmpl := string(data)

	s := ""
	for _, note := range(notes[:(len(notes)-1)]){
		s += fmt.Sprintf("absnote.name = '%s' OR ", note)
	}
	s += fmt.Sprintf("absnote.name = '%s'\n", notes[len(notes)-1])

	result := make([]string, 0)

	query := fmt.Sprintf(tmpl, s)
	rows, err := dba.Query(query)
	if err != nil {
		return nil, err
	}

	for rows.Next(){
		var root, pattern string
		var size int
		var precision float64
		rows.Scan(&root, &pattern, &size, &precision)
		result = append(result, fmt.Sprintf("%s %s", root, pattern))
	}

	return result, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/json"
	"io/ioutil"
	"os"
	"path"
	"strings"
	"time"

	"github.com/codegangsta/cli"
	"github.com/xenolf/lego/acme"
)

func checkFolder(path string) error {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return os.MkdirAll(path, 0700)
	}
	return nil
}

func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
	err := checkFolder(c.GlobalString("path"))
	if err != nil {
		logger().Fatalf("Cound not check/create path: %s", err.Error())
	}

	conf := NewConfiguration(c)
	if len(c.GlobalString(email)) == 0 {
		logger().Fatal("You have to pass an account (email address) to the program using --email or -m")
	}

	//TODO: move to account struct? Currently MUST pass email.
	acc := NewAccount(c.GlobalString("email"), conf)

	client, err := acme.NewClient(c.GlobalString("server"), acc, conf.RsaBits(), conf.OptPort())
	if err != nil {
		logger().Fatalf("Could not create client: %s", err.Error())
	}

	return conf, acc, client
}

func saveCertRes(certRes acme.CertificateResource, conf *Configuration) {
	// We store the certificate, private key and metadata in different files
	// as web servers would not be able to work with a combined file.
	certOut := path.Join(conf.CertPath(), certRes.Domain+".crt")
	privOut := path.Join(conf.CertPath(), certRes.Domain+".key")
	metaOut := path.Join(conf.CertPath(), certRes.Domain+".json")

	err := ioutil.WriteFile(certOut, certRes.Certificate, 0600)
	if err != nil {
		logger().Fatalf("Unable to save Certificate for domain %s\n\t%s", certRes.Domain, err.Error())
	}

	err = ioutil.WriteFile(privOut, certRes.PrivateKey, 0600)
	if err != nil {
		logger().Fatalf("Unable to save PrivateKey for domain %s\n\t%s", certRes.Domain, err.Error())
	}

	jsonBytes, err := json.MarshalIndent(certRes, "", "\t")
	if err != nil {
		logger().Fatalf("Unable to marshal CertResource for domain %s\n\t%s", certRes.Domain, err.Error())
	}

	err = ioutil.WriteFile(metaOut, jsonBytes, 0600)
	if err != nil {
		logger().Fatalf("Unable to save CertResource for domain %s\n\t%s", certRes.Domain, err.Error())
	}
}

func run(c *cli.Context) {
	conf, acc, client := setup(c)
	if acc.Registration == nil {
		reg, err := client.Register()
		if err != nil {
			logger().Fatalf("Could not complete registration\n\t%s", err.Error())
		}

		acc.Registration = reg
		acc.Save()

		logger().Print("!!!! HEADS UP !!!!")
		logger().Printf(`
		Your account credentials have been saved in your Let's Encrypt
		configuration directory at "%s".
		You should make a secure backup	of this folder now. This
		configuration directory will also contain certificates and
		private keys obtained from Let's Encrypt so making regular
		backups of this folder is ideal.`, conf.AccountPath(c.GlobalString("email")))

	}

	if acc.Registration.Body.Agreement == "" {
		reader := bufio.NewReader(os.Stdin)
		logger().Printf("Please review the TOS at %s", acc.Registration.TosURL)

		for {
			logger().Println("Do you accept the TOS? Y/n")
			text, err := reader.ReadString('\n')
			if err != nil {
				logger().Fatalf("Could not read from console -> %s", err.Error())
			}

			text = strings.Trim(text, "\r\n")

			if text == "n" {
				logger().Fatal("You did not accept the TOS. Unable to proceed.")
			}

			if text == "Y" || text == "y" || text == "" {
				err = client.AgreeToTOS()
				if err != nil {
					logger().Fatalf("Could not agree to tos -> %s", err)
				}
				acc.Save()
				break
			}

			logger().Println("Your input was invalid. Please answer with one of Y/y, n or by pressing enter.")
		}
	}

	if len(c.GlobalStringSlice(domains)) == 0 {
		logger().Fatal("Please specify --domains or -d")
	}

	cert, failures := client.ObtainSANCertificate(c.GlobalStringSlice("domains"), true)
	if len(failures) > 0 {
		for k, v := range failures {
			logger().Printf("[%s] Could not obtain certificates\n\t%s", k, v.Error())
		}

		// Make sure to return a non-zero exit code if ObtainSANCertificate
		// returned at least one error. Due to us not returning partial
		// certificate we can just exit here instead of at the end.
		os.Exit(1)
	}

	err := checkFolder(conf.CertPath())
	if err != nil {
		logger().Fatalf("Cound not check/create path: %s", err.Error())
	}

	saveCertRes(cert, conf)
}

func revoke(c *cli.Context) {

	conf, _, client := setup(c)

	err := checkFolder(conf.CertPath())
	if err != nil {
		logger().Fatalf("Cound not check/create path: %s", err.Error())
	}

	for _, domain := range c.GlobalStringSlice("domains") {
		logger().Printf("Trying to revoke certificate for domain %s", domain)

		certPath := path.Join(conf.CertPath(), domain+".crt")
		certBytes, err := ioutil.ReadFile(certPath)

		err = client.RevokeCertificate(certBytes)
		if err != nil {
			logger().Fatalf("Error while revoking the certificate for domain %s\n\t%s", domain, err.Error())
		} else {
			logger().Print("Certificate was revoked.")
		}
	}
}

func renew(c *cli.Context) {
	conf, _, client := setup(c)

	for _, domain := range c.GlobalStringSlice("domains") {
		// load the cert resource from files.
		// We store the certificate, private key and metadata in different files
		// as web servers would not be able to work with a combined file.
		certPath := path.Join(conf.CertPath(), domain+".crt")
		privPath := path.Join(conf.CertPath(), domain+".key")
		metaPath := path.Join(conf.CertPath(), domain+".json")

		certBytes, err := ioutil.ReadFile(certPath)
		if err != nil {
			logger().Fatalf("Error while loading the certificate for domain %s\n\t%s", domain, err.Error())
		}

		if c.IsSet("days") {
			expTime, err := acme.GetPEMCertExpiration(certBytes)
			if err != nil {
				logger().Printf("Could not get Certification expiration for domain %s", domain)
			}

			if int(expTime.Sub(time.Now()).Hours()/24.0) <= c.Int("days") {
				continue
			}
		}

		keyBytes, err := ioutil.ReadFile(privPath)
		if err != nil {
			logger().Fatalf("Error while loading the private key for domain %s\n\t%s", domain, err.Error())
		}

		metaBytes, err := ioutil.ReadFile(metaPath)
		if err != nil {
			logger().Fatalf("Error while loading the meta data for domain %s\n\t%s", domain, err.Error())
		}

		var certRes acme.CertificateResource
		err = json.Unmarshal(metaBytes, &certRes)
		if err != nil {
			logger().Fatalf("Error while marshalling the meta data for domain %s\n\t%s", domain, err.Error())
		}

		certRes.PrivateKey = keyBytes
		certRes.Certificate = certBytes

		newCert, err := client.RenewCertificate(certRes, true, true)
		if err != nil {
			logger().Fatalf("%s", err.Error())
		}

		saveCertRes(newCert, conf)
	}
}
<commit_msg>typo fix<commit_after>package main

import (
	"bufio"
	"encoding/json"
	"io/ioutil"
	"os"
	"path"
	"strings"
	"time"

	"github.com/codegangsta/cli"
	"github.com/xenolf/lego/acme"
)

func checkFolder(path string) error {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return os.MkdirAll(path, 0700)
	}
	return nil
}

func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) {
	err := checkFolder(c.GlobalString("path"))
	if err != nil {
		logger().Fatalf("Cound not check/create path: %s", err.Error())
	}

	conf := NewConfiguration(c)
	if len(c.GlobalString("email")) == 0 {
		logger().Fatal("You have to pass an account (email address) to the program using --email or -m")
	}

	//TODO: move to account struct? Currently MUST pass email.
	acc := NewAccount(c.GlobalString("email"), conf)

	client, err := acme.NewClient(c.GlobalString("server"), acc, conf.RsaBits(), conf.OptPort())
	if err != nil {
		logger().Fatalf("Could not create client: %s", err.Error())
	}

	return conf, acc, client
}

func saveCertRes(certRes acme.CertificateResource, conf *Configuration) {
	// We store the certificate, private key and metadata in different files
	// as web servers would not be able to work with a combined file.
	certOut := path.Join(conf.CertPath(), certRes.Domain+".crt")
	privOut := path.Join(conf.CertPath(), certRes.Domain+".key")
	metaOut := path.Join(conf.CertPath(), certRes.Domain+".json")

	err := ioutil.WriteFile(certOut, certRes.Certificate, 0600)
	if err != nil {
		logger().Fatalf("Unable to save Certificate for domain %s\n\t%s", certRes.Domain, err.Error())
	}

	err = ioutil.WriteFile(privOut, certRes.PrivateKey, 0600)
	if err != nil {
		logger().Fatalf("Unable to save PrivateKey for domain %s\n\t%s", certRes.Domain, err.Error())
	}

	jsonBytes, err := json.MarshalIndent(certRes, "", "\t")
	if err != nil {
		logger().Fatalf("Unable to marshal CertResource for domain %s\n\t%s", certRes.Domain, err.Error())
	}

	err = ioutil.WriteFile(metaOut, jsonBytes, 0600)
	if err != nil {
		logger().Fatalf("Unable to save CertResource for domain %s\n\t%s", certRes.Domain, err.Error())
	}
}

func run(c *cli.Context) {
	conf, acc, client := setup(c)
	if acc.Registration == nil {
		reg, err := client.Register()
		if err != nil {
			logger().Fatalf("Could not complete registration\n\t%s", err.Error())
		}

		acc.Registration = reg
		acc.Save()

		logger().Print("!!!! HEADS UP !!!!")
		logger().Printf(`
		Your account credentials have been saved in your Let's Encrypt
		configuration directory at "%s".
		You should make a secure backup	of this folder now. This
		configuration directory will also contain certificates and
		private keys obtained from Let's Encrypt so making regular
		backups of this folder is ideal.`, conf.AccountPath(c.GlobalString("email")))

	}

	if acc.Registration.Body.Agreement == "" {
		reader := bufio.NewReader(os.Stdin)
		logger().Printf("Please review the TOS at %s", acc.Registration.TosURL)

		for {
			logger().Println("Do you accept the TOS? Y/n")
			text, err := reader.ReadString('\n')
			if err != nil {
				logger().Fatalf("Could not read from console -> %s", err.Error())
			}

			text = strings.Trim(text, "\r\n")

			if text == "n" {
				logger().Fatal("You did not accept the TOS. Unable to proceed.")
			}

			if text == "Y" || text == "y" || text == "" {
				err = client.AgreeToTOS()
				if err != nil {
					logger().Fatalf("Could not agree to tos -> %s", err)
				}
				acc.Save()
				break
			}

			logger().Println("Your input was invalid. Please answer with one of Y/y, n or by pressing enter.")
		}
	}

	if len(c.GlobalStringSlice("domains")) == 0 {
		logger().Fatal("Please specify --domains or -d")
	}

	cert, failures := client.ObtainSANCertificate(c.GlobalStringSlice("domains"), true)
	if len(failures) > 0 {
		for k, v := range failures {
			logger().Printf("[%s] Could not obtain certificates\n\t%s", k, v.Error())
		}

		// Make sure to return a non-zero exit code if ObtainSANCertificate
		// returned at least one error. Due to us not returning partial
		// certificate we can just exit here instead of at the end.
		os.Exit(1)
	}

	err := checkFolder(conf.CertPath())
	if err != nil {
		logger().Fatalf("Cound not check/create path: %s", err.Error())
	}

	saveCertRes(cert, conf)
}

func revoke(c *cli.Context) {

	conf, _, client := setup(c)

	err := checkFolder(conf.CertPath())
	if err != nil {
		logger().Fatalf("Cound not check/create path: %s", err.Error())
	}

	for _, domain := range c.GlobalStringSlice("domains") {
		logger().Printf("Trying to revoke certificate for domain %s", domain)

		certPath := path.Join(conf.CertPath(), domain+".crt")
		certBytes, err := ioutil.ReadFile(certPath)

		err = client.RevokeCertificate(certBytes)
		if err != nil {
			logger().Fatalf("Error while revoking the certificate for domain %s\n\t%s", domain, err.Error())
		} else {
			logger().Print("Certificate was revoked.")
		}
	}
}

func renew(c *cli.Context) {
	conf, _, client := setup(c)

	for _, domain := range c.GlobalStringSlice("domains") {
		// load the cert resource from files.
		// We store the certificate, private key and metadata in different files
		// as web servers would not be able to work with a combined file.
		certPath := path.Join(conf.CertPath(), domain+".crt")
		privPath := path.Join(conf.CertPath(), domain+".key")
		metaPath := path.Join(conf.CertPath(), domain+".json")

		certBytes, err := ioutil.ReadFile(certPath)
		if err != nil {
			logger().Fatalf("Error while loading the certificate for domain %s\n\t%s", domain, err.Error())
		}

		if c.IsSet("days") {
			expTime, err := acme.GetPEMCertExpiration(certBytes)
			if err != nil {
				logger().Printf("Could not get Certification expiration for domain %s", domain)
			}

			if int(expTime.Sub(time.Now()).Hours()/24.0) <= c.Int("days") {
				continue
			}
		}

		keyBytes, err := ioutil.ReadFile(privPath)
		if err != nil {
			logger().Fatalf("Error while loading the private key for domain %s\n\t%s", domain, err.Error())
		}

		metaBytes, err := ioutil.ReadFile(metaPath)
		if err != nil {
			logger().Fatalf("Error while loading the meta data for domain %s\n\t%s", domain, err.Error())
		}

		var certRes acme.CertificateResource
		err = json.Unmarshal(metaBytes, &certRes)
		if err != nil {
			logger().Fatalf("Error while marshalling the meta data for domain %s\n\t%s", domain, err.Error())
		}

		certRes.PrivateKey = keyBytes
		certRes.Certificate = certBytes

		newCert, err := client.RenewCertificate(certRes, true, true)
		if err != nil {
			logger().Fatalf("%s", err.Error())
		}

		saveCertRes(newCert, conf)
	}
}
<|endoftext|>


<commit_before>package client

import (
	"fmt"
	"io"
	"net"
	"os"
	"os/user"
	"path/filepath"

	"github.com/chzyer/flagly"
	"github.com/chzyer/flow"
	"github.com/chzyer/readline"
	"github.com/google/shlex"

	"gopkg.in/logex.v1"
)

type Shell struct {
	flow   *flow.Flow
	Sock   string
	ln     net.Listener
	client *Client
}

func NewShell(f *flow.Flow, cli *Client, sock string) (*Shell, error) {
	ln, err := net.Listen("unix", sock)
	if err != nil {
		return nil, logex.Trace(err)
	}
	os.Chmod(sock, 0777)
	sh := &Shell{
		Sock:   sock,
		client: cli,
		ln:     ln,
	}
	f.ForkTo(&sh.flow, sh.Close)
	return sh, nil
}

func (s *Shell) Close() {
	s.ln.Close()
	s.flow.Close()
	os.Remove(s.Sock)
}

func (s *Shell) handleConn(conn net.Conn) {
	defer conn.Close()

	homeDir := os.Getenv("HOME")
	userAcct, _ := user.Current()
	if userAcct != nil {
		homeDir = userAcct.HomeDir
	}

	hf := filepath.Join(homeDir, ".nextcli_history")
	cfg := readline.Config{
		HistoryFile: hf,
		Prompt:      " -> ",
	}
	rl, err := readline.HandleConn(cfg, conn)
	if err != nil {
		return
	}
	defer rl.Close()

	sh := &ShellCLI{}
	fset, err := flagly.Compile("", sh)
	if err != nil {
		logex.Info(err)
		return
	}
	fset.Context(rl, s.client)

	io.WriteString(rl, "Next Client CLI\n")
	for {
		command, err := rl.Readline()
		if err == readline.ErrInterrupt {
			if len(command) == 0 {
				break
			} else {
				continue
			}
		} else if err != nil {
			break
		}

		args, err := shlex.Split(command)
		if err != nil {
			continue
		}

		if err := fset.Run(args); err != nil {
			fmt.Fprintln(rl.Stderr(), err)
			continue
		}
	}
}

func (s *Shell) loop() {
	for {
		conn, err := s.ln.Accept()
		if err != nil {
			break
		}
		go s.handleConn(conn)
	}
}

type ShellCLI struct {
	Help      *flagly.CmdHelp `flagly:"handler"`
	Ping      *ShellPing      `flagly:"handler"`
	HeartBeat *ShellHeartBeat `flagly:"handler"`
	Route     *ShellRoute     `flagly:"handler"`
}

type ShellHeartBeat struct{}

func (*ShellHeartBeat) FlaglyHandle(c *Client, rl *readline.Instance) error {
	stat := c.dcs.GetStats()
	fmt.Fprintln(rl, stat)
	return nil
}

type ShellPing struct{}

func (*ShellPing) FlaglyHandle(c *Client) error {
	logex.Info(c)
	return nil
}
<commit_msg>[client] only print slogan in tty<commit_after>package client

import (
	"fmt"
	"net"
	"os"
	"os/user"
	"path/filepath"

	"github.com/chzyer/flagly"
	"github.com/chzyer/flow"
	"github.com/chzyer/readline"
	"github.com/google/shlex"

	"gopkg.in/logex.v1"
)

type Shell struct {
	flow   *flow.Flow
	Sock   string
	ln     net.Listener
	client *Client
}

func NewShell(f *flow.Flow, cli *Client, sock string) (*Shell, error) {
	ln, err := net.Listen("unix", sock)
	if err != nil {
		return nil, logex.Trace(err)
	}
	os.Chmod(sock, 0777)
	sh := &Shell{
		Sock:   sock,
		client: cli,
		ln:     ln,
	}
	f.ForkTo(&sh.flow, sh.Close)
	return sh, nil
}

func (s *Shell) Close() {
	s.ln.Close()
	s.flow.Close()
	os.Remove(s.Sock)
}

func (s *Shell) handleConn(conn net.Conn) {
	defer conn.Close()

	homeDir := os.Getenv("HOME")
	userAcct, _ := user.Current()
	if userAcct != nil {
		homeDir = userAcct.HomeDir
	}

	hf := filepath.Join(homeDir, ".nextcli_history")
	cfg := readline.Config{
		HistoryFile: hf,
		Prompt:      " -> ",
	}
	rl, err := readline.HandleConn(cfg, conn)
	if err != nil {
		return
	}
	defer rl.Close()

	sh := &ShellCLI{}
	fset, err := flagly.Compile("", sh)
	if err != nil {
		logex.Info(err)
		return
	}
	fset.Context(rl, s.client)

	if readline.IsTerminal(0) {
		fmt.Fprintln(rl, "Next Client CLI")
	}
	for {
		command, err := rl.Readline()
		if err == readline.ErrInterrupt {
			if len(command) == 0 {
				break
			} else {
				continue
			}
		} else if err != nil {
			break
		}

		args, err := shlex.Split(command)
		if err != nil {
			continue
		}

		if err := fset.Run(args); err != nil {
			fmt.Fprintln(rl.Stderr(), err)
			continue
		}
	}
}

func (s *Shell) loop() {
	for {
		conn, err := s.ln.Accept()
		if err != nil {
			break
		}
		go s.handleConn(conn)
	}
}

type ShellCLI struct {
	Help      *flagly.CmdHelp `flagly:"handler"`
	Ping      *ShellPing      `flagly:"handler"`
	HeartBeat *ShellHeartBeat `flagly:"handler"`
	Route     *ShellRoute     `flagly:"handler"`
}

type ShellHeartBeat struct{}

func (*ShellHeartBeat) FlaglyHandle(c *Client, rl *readline.Instance) error {
	stat := c.dcs.GetStats()
	fmt.Fprintln(rl, stat)
	return nil
}

type ShellPing struct{}

func (*ShellPing) FlaglyHandle(c *Client) error {
	logex.Info(c)
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2014 Volker Dobler.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"log"
	"time"

	"github.com/vdobler/ht/hist"
	"github.com/vdobler/ht/ht"
)

var cmdBench = &Command{
	Run:         runBench,
	Usage:       "bench [flags] <suite>...",
	Description: "benchmark requests",
	Help: `
Benchmark the tests by running count many requests seperated by pause
after doing warmup many requests which are not measured.
`,
}

func init() {
	cmdBench.Flag.IntVar(&bcountFlag, "count", 17,
		"measure `n` requests")
	cmdBench.Flag.IntVar(&concurrentFlag, "concurrent", 1,
		"run `conc` many request in parallel")
	cmdBench.Flag.IntVar(&warmupFlag, "warmup", 3,
		"warmup system with `n` unmeasured requests")
	cmdBench.Flag.DurationVar(&pauseFlag, "pause", 10*time.Millisecond,
		"sleep `duration` between requests")
	addVariablesFlag(&cmdBench.Flag)
	addOnlyFlag(&cmdBench.Flag)
	addSkipFlag(&cmdBench.Flag)
	addVerbosityFlag(&cmdBench.Flag)

}

var (
	bcountFlag     int
	warmupFlag     int
	pauseFlag      time.Duration
	concurrentFlag int
)

func runBench(cmd *Command, suites []*ht.Suite) {
	println(warmupFlag, bcountFlag, concurrentFlag)
	for s, suite := range suites {
		suite.ExecuteSetup()
		if suite.Status != ht.Pass {
			log.Printf("Suite %d %q: Setup failure %q", s, suite.Name,
				suite.Error.Error())
			continue
		}
		for _, test := range suite.Tests {
			if test.Poll.Max < 0 {
				continue
			}
			results := test.Benchmark(suite.Variables,
				warmupFlag, bcountFlag, pauseFlag, concurrentFlag)
			fmt.Printf("Suite: %s; Test: %s\n", suite.Name, test.Name)
			printBenchmarkSummary(results)
		}
		suite.ExecuteTeardown()
	}
}

func printBenchmarkSummary(results []ht.Test) {
	max := 0
	for _, r := range results {
		if d := int(r.Duration / 1e6); d > max {
			max = d
		}
	}
	h := hist.NewLogHist(7, max)
	for _, r := range results {
		h.Add(int(r.Duration / 1e6))
	}

	ps := []float64{0, 0.25, 0.50, 0.75, 0.80, 0.85, 0.90, 0.95, 0.97, 0.98, 0.99, 1}
	cps := make([]int, len(ps))
	for i, p := range ps {
		cps[i] = int(100*p + 0.2)
	}

	fmt.Printf("Percentil %4d \n", cps)
	fmt.Printf("Resp.Time %4d  [ms]\n", h.Percentils(ps))
}
<commit_msg>cmd/ht: fix nil panic while skipping test during bench<commit_after>// Copyright 2014 Volker Dobler.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"log"
	"time"

	"github.com/vdobler/ht/hist"
	"github.com/vdobler/ht/ht"
)

var cmdBench = &Command{
	Run:         runBench,
	Usage:       "bench [flags] <suite>...",
	Description: "benchmark requests",
	Help: `
Benchmark the tests by running count many requests seperated by pause
after doing warmup many requests which are not measured.
`,
}

func init() {
	cmdBench.Flag.IntVar(&bcountFlag, "count", 17,
		"measure `n` requests")
	cmdBench.Flag.IntVar(&concurrentFlag, "concurrent", 1,
		"run `conc` many request in parallel")
	cmdBench.Flag.IntVar(&warmupFlag, "warmup", 3,
		"warmup system with `n` unmeasured requests")
	cmdBench.Flag.DurationVar(&pauseFlag, "pause", 10*time.Millisecond,
		"sleep `duration` between requests")
	addVariablesFlag(&cmdBench.Flag)
	addOnlyFlag(&cmdBench.Flag)
	addSkipFlag(&cmdBench.Flag)
	addVerbosityFlag(&cmdBench.Flag)

}

var (
	bcountFlag     int
	warmupFlag     int
	pauseFlag      time.Duration
	concurrentFlag int
)

func runBench(cmd *Command, suites []*ht.Suite) {
	println(warmupFlag, bcountFlag, concurrentFlag)
	for s, suite := range suites {
		suite.ExecuteSetup()
		if suite.Status != ht.Pass && suite.Status != ht.Skipped {
			log.Printf("Suite %d %q: Setup failure %q", s, suite.Name,
				suite.Error.Error())
			continue
		}
		for _, test := range suite.Tests {
			if test.Poll.Max < 0 {
				continue
			}
			results := test.Benchmark(suite.Variables,
				warmupFlag, bcountFlag, pauseFlag, concurrentFlag)
			fmt.Printf("Suite: %s; Test: %s\n", suite.Name, test.Name)
			printBenchmarkSummary(results)
		}
		suite.ExecuteTeardown()
	}
}

func printBenchmarkSummary(results []ht.Test) {
	max := 0
	for _, r := range results {
		if d := int(r.Duration / 1e6); d > max {
			max = d
		}
	}
	h := hist.NewLogHist(7, max)
	for _, r := range results {
		h.Add(int(r.Duration / 1e6))
	}

	ps := []float64{0, 0.25, 0.50, 0.75, 0.80, 0.85, 0.90, 0.95, 0.97, 0.98, 0.99, 1}
	cps := make([]int, len(ps))
	for i, p := range ps {
		cps[i] = int(100*p + 0.2)
	}

	fmt.Printf("Percentil %4d \n", cps)
	fmt.Printf("Resp.Time %4d  [ms]\n", h.Percentils(ps))
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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"
	"fmt"
	"os"

	"github.com/rlmcpherson/kops/upup/pkg/api"
	"github.com/spf13/cobra"
)

// GetCmd represents the get command
type GetCmd struct {
	output string

	cobraCommand *cobra.Command
}

var getCmd = GetCmd{
	cobraCommand: &cobra.Command{
		Use:        "get",
		SuggestFor: []string{"list"},
		Short:      "list or get objects",
		Long:       `list or get objects`,
	},
}

const (
	OutputYaml  = "yaml"
	OutputTable = "table"
	OutputJSON  = "json"
)

func init() {
	cmd := getCmd.cobraCommand

	rootCommand.AddCommand(cmd)

	cmd.PersistentFlags().StringVarP(&getCmd.output, "output", "o", OutputTable, "output format.  One of: table, yaml, json")
}

type marshalFunc func(v interface{}) ([]byte, error)

func marshalToStdout(item interface{}, marshal marshalFunc) error {
	b, err := marshal(item)
	if err != nil {
		return err
	}
	_, err = os.Stdout.Write(b)
	if err != nil {
		return fmt.Errorf("error writing to stdout: %v", err)
	}
	return nil
}

// v must be a pointer to a marshalable object
func marshalYaml(v interface{}) ([]byte, error) {
	y, err := api.ToYaml(v)
	if err != nil {
		return nil, fmt.Errorf("error marshaling yaml: %v", err)
	}
	return y, nil
}

// v must be a pointer to a marshalable object
func marshalJSON(v interface{}) ([]byte, error) {
	j, err := json.Marshal(v)
	if err != nil {
		return nil, fmt.Errorf("error marshaling json: %v", err)
	}
	return j, nil
}
<commit_msg>use ToVersionedYaml<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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"
	"fmt"
	"os"

	"github.com/spf13/cobra"
	api "k8s.io/kops/pkg/apis/kops"
	"k8s.io/kubernetes/pkg/runtime"
)

// GetCmd represents the get command
type GetCmd struct {
	output string

	cobraCommand *cobra.Command
}

var getCmd = GetCmd{
	cobraCommand: &cobra.Command{
		Use:        "get",
		SuggestFor: []string{"list"},
		Short:      "list or get objects",
		Long:       `list or get objects`,
	},
}

const (
	OutputYaml  = "yaml"
	OutputTable = "table"
	OutputJSON  = "json"
)

func init() {
	cmd := getCmd.cobraCommand

	rootCommand.AddCommand(cmd)

	cmd.PersistentFlags().StringVarP(&getCmd.output, "output", "o", OutputTable, "output format.  One of: table, yaml, json")
}

type marshalFunc func(obj runtime.Object) ([]byte, error)

func marshalToStdout(obj runtime.Object, marshal marshalFunc) error {
	b, err := marshal(obj)
	if err != nil {
		return err
	}
	_, err = os.Stdout.Write(b)
	if err != nil {
		return fmt.Errorf("error writing to stdout: %v", err)
	}
	return nil
}

// v must be a pointer to a marshalable object
func marshalYaml(obj runtime.Object) ([]byte, error) {
	y, err := api.ToVersionedYaml(obj)
	if err != nil {
		return nil, fmt.Errorf("error marshaling yaml: %v", err)
	}
	return y, nil
}

// v must be a pointer to a marshalable object
func marshalJSON(obj runtime.Object) ([]byte, error) {
	j, err := json.MarshalIndent(obj, "", "  ")
	if err != nil {
		return nil, fmt.Errorf("error marshaling json: %v", err)
	}
	return j, nil
}
<|endoftext|>


<commit_before>package cmd

import (
	"bytes"
	"fmt"
	"html/template"
	"log"
	"time"
)

func Ruminate(c Config, burp bool) []Point {
	l.Infow("Going to create InfluxDB client")
	i, err := NewInflux(c.Gulp.Host, c.Gulp.Proto, c.Gulp.Db, c.Gulp.User, c.Gulp.Pass, c.Gulp.Series, c.Gulp.Indicator, c.Gulp.Port)
	if err != nil {
		l.Fatal("Could net create InfluxDB client", "error", err.Error())
	}

	l.Infow("Getting latest timestamp from InfluxDB")
	latest, err := i.GetLatestMarker()
	if err != nil {
		l.Fatalw("Could not get latest timestamp in series. How you already prepared the database with 'init'?", "error", err.Error())
	}
	l.Infof("Latest entry at %s", latest.Format("2006-01-02 15:04:05"))

	es := NewElasticSearch(c.Regurgitate.Proto, c.Regurgitate.Host, c.Regurgitate.Port)

	sampledQueries := make(map[time.Time][]string)
	interv := c.Regurgitate.Sampler.Interval
	if interv != "" {
		l.Infow("Sampler found, building queries")
		s, err := NewSampler(c.Regurgitate.Sampler)
		if err != nil {
			l.Fatalw("Error occured", "error", err.Error())
		}
		sampledQueries = s.BuildQueries(c.Regurgitate.Query, latest)
		l.Infof("A total of %d queries are built", len(sampledQueries)*c.Regurgitate.Sampler.Samples)
	} else {
		l.Infow("No sampler config found, building simple query")
		t := template.Must(template.New("t1").Parse(c.Regurgitate.Query))
		var query bytes.Buffer
		t.Execute(&query, ToEsTimestamp(latest))
		sampledQueries[latest] = []string{query.String()}
	}

	var points []Point
	processed := 0
	for ts, queries := range sampledQueries {
		var samples []Point
		l.Infof("Sampling @ %s", ts.Format("2006-01-02 15:04:05"))
		for i, query := range queries {
			l.Infof("-- Query ElasticSearch for sample %d", i)
			result, err := es.Query(c.Regurgitate.Index, c.Regurgitate.Type, query)
			if err != nil {
				l.Fatalw("-- Query failed", "error", err.Error())
			}
			j, err := result.AggsAsJson()
			if err != nil {
				log.Fatal(err)
			}
			p := Point{
				Timestamp: ts,
				Tags:      make(map[string]string),
				Values:    make(map[string]interface{}),
			}
			l.Infow("-- Processing results")
			var sample []Point
			var jsonFragment string
			if burp {
				l.Infow("Printing latest processed json fragment")
				sample, jsonFragment, err = Burp(j, c.Ruminate.Iterator, p)
				fmt.Printf("\n%s\n\n", jsonFragment)
			} else {
				sample, err = Chew(j, c.Ruminate.Iterator, p)
			}
			if err != nil {
				l.Fatalw("Could not process data", "error", err.Error())
			}
			samples = append(samples, sample...)
			processed += 1
		}

		if c.Regurgitate.Sampler.Samples > 1 {
			l.Infow("-- Calculating average of samples")
			samples = Avg(samples, c.Regurgitate.Sampler.Samples)
		}
		points = append(points, samples...)
		l.Infof("%d of %d queries run and processed", processed, len(sampledQueries)*c.Regurgitate.Sampler.Samples)
	}

	return points
}
<commit_msg>improved burp when using a sampler<commit_after>package cmd

import (
	"bytes"
	"fmt"
	"html/template"
	"log"
	"time"
)

func Ruminate(c Config, burp bool) []Point {
	l.Infow("Going to create InfluxDB client")
	i, err := NewInflux(c.Gulp.Host, c.Gulp.Proto, c.Gulp.Db, c.Gulp.User, c.Gulp.Pass, c.Gulp.Series, c.Gulp.Indicator, c.Gulp.Port)
	if err != nil {
		l.Fatal("Could net create InfluxDB client", "error", err.Error())
	}

	l.Infow("Getting latest timestamp from InfluxDB")
	latest, err := i.GetLatestMarker()
	if err != nil {
		l.Fatalw("Could not get latest timestamp in series. How you already prepared the database with 'init'?", "error", err.Error())
	}
	l.Infof("Latest entry at %s", latest.Format("2006-01-02 15:04:05"))

	es := NewElasticSearch(c.Regurgitate.Proto, c.Regurgitate.Host, c.Regurgitate.Port)

	sampledQueries := make(map[time.Time][]string)
	interv := c.Regurgitate.Sampler.Interval
	if interv != "" {
		l.Infow("Sampler found, building queries")
		s, err := NewSampler(c.Regurgitate.Sampler)
		if err != nil {
			l.Fatalw("Error occured", "error", err.Error())
		}
		sampledQueries = s.BuildQueries(c.Regurgitate.Query, latest)
		l.Infof("A total of %d queries are built", len(sampledQueries)*c.Regurgitate.Sampler.Samples)
	} else {
		l.Infow("No sampler config found, building simple query")
		t := template.Must(template.New("t1").Parse(c.Regurgitate.Query))
		var query bytes.Buffer
		t.Execute(&query, ToEsTimestamp(latest))
		sampledQueries[latest] = []string{query.String()}
	}

	var points []Point
	processed := 0
	for ts, queries := range sampledQueries {
		if burp && len(points) > 0 {
			break
		}
		var samples []Point
		l.Infof("Sampling @ %s", ts.Format("2006-01-02 15:04:05"))
		for i, query := range queries {
			l.Infof("-- Query ElasticSearch for sample %d", i)
			result, err := es.Query(c.Regurgitate.Index, c.Regurgitate.Type, query)
			if err != nil {
				l.Fatalw("-- Query failed", "error", err.Error())
			}
			j, err := result.AggsAsJson()
			if err != nil {
				log.Fatal(err)
			}
			p := Point{
				Timestamp: ts,
				Tags:      make(map[string]string),
				Values:    make(map[string]interface{}),
			}
			l.Infow("-- Processing results")
			var sample []Point
			var jsonFragment string
			if burp {
				l.Infow("Printing latest processed json fragment")
				sample, jsonFragment, err = Burp(j, c.Ruminate.Iterator, p)
				if jsonFragment != "" {
					fmt.Printf("\n%s\n\n", jsonFragment)
				}
			} else {
				sample, err = Chew(j, c.Ruminate.Iterator, p)
			}
			if err != nil {
				l.Fatalw("Could not process data", "error", err.Error())
			}
			samples = append(samples, sample...)
			processed += 1
		}

		if c.Regurgitate.Sampler.Samples > 1 {
			l.Infow("-- Calculating average of samples")
			samples = Avg(samples, c.Regurgitate.Sampler.Samples)
		}
		points = append(points, samples...)
		l.Infof("%d of %d queries run and processed", processed, len(sampledQueries)*c.Regurgitate.Sampler.Samples)
	}

	return points
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/gonuts/commander"
	"github.com/gonuts/flag"
)

func lbpkr_make_cmd_repo_add() *commander.Command {
	cmd := &commander.Command{
		Run:       lbpkr_run_cmd_repo_add,
		UsageLine: "repo-add [options] <repo-name> <repo-url>",
		Short:     "add a repository",
		Long: `repo-add adds a repository source named <repo-name> and located at <repo-url>.

ex:
 $ lbpkr repo-add my-test /some/where
 $ lbpkr repo-add extra http://example.com/rpm
`,
		Flag: *flag.NewFlagSet("lbpkr-repo-add", flag.ExitOnError),
	}
	add_default_options(cmd)
	cmd.Flag.Int("maxdepth", -1, "maximum depth level of dependency graph (-1: all)")
	return cmd
}

func lbpkr_run_cmd_repo_add(cmd *commander.Command, args []string) error {
	var err error

	debug := cmd.Flag.Lookup("v").Value.Get().(bool)
	siteroot := cmd.Flag.Lookup("siteroot").Value.Get().(string)
	//dmax := cmd.Flag.Lookup("maxdepth").Value.Get().(int)

	reponame := ""
	repourl := ""

	switch len(args) {
	case 2:
		reponame = args[0]
		repourl = args[1]
	default:
		cmd.Usage()
		return fmt.Errorf("lbpkr: invalid number of arguments. expected n=2. got=%d (%v)",
			len(args),
			args,
		)
	}

	cfg := NewConfig(siteroot)
	ctx, err := New(cfg, Debug(debug))
	if err != nil {
		return err
	}
	defer ctx.Close()

	err = ctx.AddRepository(reponame, repourl)
	return err
}
<commit_msg>repo-add: add shortcuts for nightlies+releases<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/gonuts/commander"
	"github.com/gonuts/flag"
)

func lbpkr_make_cmd_repo_add() *commander.Command {
	cmd := &commander.Command{
		Run:       lbpkr_run_cmd_repo_add,
		UsageLine: "repo-add [options] <repo-name> <repo-url>",
		Short:     "add a repository",
		Long: `repo-add adds a repository source named <repo-name> and located at <repo-url>.

ex:
 $ lbpkr repo-add my-test /some/where
 $ lbpkr repo-add extra http://example.com/rpm

 # add lhcb-release/Fri (2015-01-20, DaVinci-v36r4p1)
 $ lbpkr repo-add lhcb-release/Fri

 # add a nightly lhcb-gaudi-head/Fri
 $ lbpkr repo-add lhcb-gaudi-head/Fri
`,
		Flag: *flag.NewFlagSet("lbpkr-repo-add", flag.ExitOnError),
	}
	add_default_options(cmd)
	cmd.Flag.Int("maxdepth", -1, "maximum depth level of dependency graph (-1: all)")
	return cmd
}

func lbpkr_run_cmd_repo_add(cmd *commander.Command, args []string) error {
	var err error

	debug := cmd.Flag.Lookup("v").Value.Get().(bool)
	siteroot := cmd.Flag.Lookup("siteroot").Value.Get().(string)
	//dmax := cmd.Flag.Lookup("maxdepth").Value.Get().(int)

	cfg := NewConfig(siteroot)
	ctx, err := New(cfg, Debug(debug))
	if err != nil {
		return err
	}
	defer ctx.Close()

	reponame := ""
	repourl := ""

	switch len(args) {
	case 1:
		reponame = strings.Replace(args[0], "/", "-", -1)
		// https://buildlhcb.cern.ch/artifacts/lhcb-gaudi-head/Fri/slot-config.json
		// https://buildlhcb.cern.ch/artifacts/release/lhcb-release/375/slot-config.json
		url := "https://buildlhcb.cern.ch/artifacts/"
		if strings.HasPrefix(args[0], "lhcb-release/") {
			url += "release/"
		}
		if !strings.HasSuffix(url, "/") {
			url += "/"
		}
		url += args[0]
		if strings.HasSuffix(url, "/") {
			url = url[:len(url)-2]
		}

		repourl = url + "/rpm"
		url += "/slot-config.json"
		f, err := getRemoteData(url)
		if err != nil {
			ctx.msg.Errorf("could not download [%s]: %v\n", url, err)
			return err
		}
		defer f.Close()

		data := struct {
			Slot    string `json:"slot"`
			BuildID int    `json:"build_id"`
			Date    string `json:"date"`
		}{}

		err = json.NewDecoder(f).Decode(&data)
		if err != nil {
			ctx.msg.Errorf("could not decode slot-config.json: %v\n", err)
			return err
		}

		ctx.msg.Infof("slot: %q\n", data.Slot)
		ctx.msg.Infof("date: %q (build-id: %v)\n", data.Date, data.BuildID)
		ctx.msg.Infof("url:  %q\n", repourl)

	case 2:
		reponame = args[0]
		repourl = args[1]
	default:
		cmd.Usage()
		return fmt.Errorf("lbpkr: invalid number of arguments. expected n=1|2. got=%d (%v)",
			len(args),
			args,
		)
	}

	err = ctx.AddRepository(reponame, repourl)
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"

	"github.com/golang/example/stringutil"
)

type Message struct {
	Name string
	Body string
	Time int64
}

func homePage(w http.ResponseWriter, r *http.Request) {
	m := Message{"Alice", "Hello", 1294706395881547000}
	b, _ := json.Marshal(m)

	fmt.Fprintf(w, string(b))
	fmt.Println("get request at root endpoint")
}

func handleRequests() {
	http.HandleFunc("/", homePage)
	log.Fatal(http.ListenAndServe(":8081", nil))
}

func main() {
	fmt.Println(stringutil.Reverse("HI"))
	handleRequests()
}
<commit_msg>set response header to jsonw<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"

	"github.com/golang/example/stringutil"
)

type Message struct {
	Name string
	Body string
	Time int64
}

func homePage(w http.ResponseWriter, r *http.Request) {
	m := Message{"Alice", "Hello", 1294706395881547000}
	b, _ := json.Marshal(m)

	w.Header().Set("Content-Type", "application/json")

	fmt.Fprintf(w, string(b))
	fmt.Println("get request at root endpoint")
}

func handleRequests() {
	http.HandleFunc("/", homePage)
	log.Fatal(http.ListenAndServe(":8081", nil))
}

func main() {
	fmt.Println(stringutil.Reverse("HI"))
	handleRequests()
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/Terry-Mao/goim/define"
	"sync"
)

// Bucket is a channel holder.
type Bucket struct {
	cLock       sync.RWMutex                    // protect the channels for chs
	chs         map[string]*Channel             // map sub key to a channel
	rooms       map[int32]map[*Channel]struct{} // map room id with channels
	roomChannel int
}

// NewBucket new a bucket struct. store the subkey with im channel.
func NewBucket(channel, room, roomChannel, cliProto, svrProto int) *Bucket {
	b := new(Bucket)
	b.chs = make(map[string]*Channel, channel)
	b.rooms = make(map[int32]map[*Channel]struct{}, room)
	b.roomChannel = roomChannel
	return b
}

// Put put a channel according with sub key.
func (b *Bucket) Put(subKey string, ch *Channel) {
	var (
		room map[*Channel]struct{}
		ok   bool
	)
	b.cLock.Lock()
	b.chs[subKey] = ch
	if ch.RoomId != define.NoRoom {
		if room, ok = b.rooms[ch.RoomId]; !ok {
			room = make(map[*Channel]struct{}, b.roomChannel)
			b.rooms[ch.RoomId] = room
		}
		room[ch] = struct{}{}
	}
	b.cLock.Unlock()
}

// Get get a channel by sub key.
func (b *Bucket) Get(subKey string) *Channel {
	var ch *Channel
	b.cLock.RLock()
	ch = b.chs[subKey]
	b.cLock.RUnlock()
	return ch
}

// Del delete the channel by sub key.
func (b *Bucket) Del(subKey string) {
	var (
		ok   bool
		ch   *Channel
		room map[*Channel]struct{}
	)
	b.cLock.Lock()
	if ch, ok = b.chs[subKey]; ok {
		delete(b.chs, subKey)
		if ch.RoomId != define.NoRoom {
			if room, ok = b.rooms[ch.RoomId]; ok {
				delete(room, ch)
			}
		}
	}
	b.cLock.Unlock()
}

// Broadcast push msgs to all channels in the bucket.
func (b *Bucket) Broadcast(ver int16, operation int32, msg []byte) {
	var ch *Channel
	b.cLock.RLock()
	for _, ch = range b.chs {
		// ignore error
		ch.PushMsg(ver, operation, msg)
	}
	b.cLock.RUnlock()
}

// Broadcast push msgs to all channels in the bucket's room.
func (b *Bucket) BroadcastRoom(rid int32, ver int16, operation int32, msg []byte) {
	var (
		ok   bool
		ch   *Channel
		room map[*Channel]struct{}
	)
	b.cLock.RLock()
	if room, ok = b.rooms[rid]; ok && len(room) > 0 {
		for ch, _ = range room {
			// ignore error
			ch.PushMsg(ver, operation, msg)
		}
	}
	b.cLock.RUnlock()
}

// Rooms get all room id where online number > 0.
func (b *Bucket) Rooms() (res map[int32]struct{}) {
	var (
		roomId int32
		room   map[*Channel]struct{}
	)
	b.cLock.RLock()
	res = make(map[int32]struct{}, len(b.rooms))
	for roomId, room = range b.rooms {
		if len(room) > 0 {
			res[roomId] = struct{}{}
		}
	}
	b.cLock.RUnlock()
	return
}
<commit_msg>fix empty room free<commit_after>package main

import (
	"github.com/Terry-Mao/goim/define"
	"sync"
)

// Bucket is a channel holder.
type Bucket struct {
	cLock       sync.RWMutex                    // protect the channels for chs
	chs         map[string]*Channel             // map sub key to a channel
	rooms       map[int32]map[*Channel]struct{} // map room id with channels
	roomChannel int
}

// NewBucket new a bucket struct. store the subkey with im channel.
func NewBucket(channel, room, roomChannel, cliProto, svrProto int) *Bucket {
	b := new(Bucket)
	b.chs = make(map[string]*Channel, channel)
	b.rooms = make(map[int32]map[*Channel]struct{}, room)
	b.roomChannel = roomChannel
	return b
}

// Put put a channel according with sub key.
func (b *Bucket) Put(subKey string, ch *Channel) {
	var (
		room map[*Channel]struct{}
		ok   bool
	)
	b.cLock.Lock()
	b.chs[subKey] = ch
	if ch.RoomId != define.NoRoom {
		if room, ok = b.rooms[ch.RoomId]; !ok {
			room = make(map[*Channel]struct{}, b.roomChannel)
			b.rooms[ch.RoomId] = room
		}
		room[ch] = struct{}{}
	}
	b.cLock.Unlock()
}

// Get get a channel by sub key.
func (b *Bucket) Get(subKey string) *Channel {
	var ch *Channel
	b.cLock.RLock()
	ch = b.chs[subKey]
	b.cLock.RUnlock()
	return ch
}

// Del delete the channel by sub key.
func (b *Bucket) Del(subKey string) {
	var (
		ok   bool
		ch   *Channel
		room map[*Channel]struct{}
	)
	b.cLock.Lock()
	if ch, ok = b.chs[subKey]; ok {
		delete(b.chs, subKey)
		if ch.RoomId != define.NoRoom {
			if room, ok = b.rooms[ch.RoomId]; ok {
				// clean the room's channel
				// when room empty
				// clean the room space for free large room memory
				// WARN: if room flip between empty and someone let GC busy
				// this scene is rare
				delete(room, ch)
				if len(room) == 0 {
					delete(b.rooms, ch.RoomId)
				}
			}
		}
	}
	b.cLock.Unlock()
}

// Broadcast push msgs to all channels in the bucket.
func (b *Bucket) Broadcast(ver int16, operation int32, msg []byte) {
	var ch *Channel
	b.cLock.RLock()
	for _, ch = range b.chs {
		// ignore error
		ch.PushMsg(ver, operation, msg)
	}
	b.cLock.RUnlock()
}

// Broadcast push msgs to all channels in the bucket's room.
func (b *Bucket) BroadcastRoom(rid int32, ver int16, operation int32, msg []byte) {
	var (
		ok   bool
		ch   *Channel
		room map[*Channel]struct{}
	)
	b.cLock.RLock()
	if room, ok = b.rooms[rid]; ok && len(room) > 0 {
		for ch, _ = range room {
			// ignore error
			ch.PushMsg(ver, operation, msg)
		}
	}
	b.cLock.RUnlock()
}

// Rooms get all room id where online number > 0.
func (b *Bucket) Rooms() (res map[int32]struct{}) {
	var (
		roomId int32
		room   map[*Channel]struct{}
	)
	b.cLock.RLock()
	res = make(map[int32]struct{}, len(b.rooms))
	for roomId, room = range b.rooms {
		if len(room) > 0 {
			res[roomId] = struct{}{}
		}
	}
	b.cLock.RUnlock()
	return
}
<|endoftext|>


<commit_before>package command

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strconv"

	"github.com/hashicorp/terraform/config/module"
	"github.com/hashicorp/terraform/state"
	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/cli"
	"github.com/mitchellh/colorstring"
)

// Meta are the meta-options that are available on all or most commands.
type Meta struct {
	Color       bool
	ContextOpts *terraform.ContextOpts
	Ui          cli.Ui

	// State read when calling `Context`. This is available after calling
	// `Context`.
	state       state.State
	stateResult *StateResult

	// This can be set by the command itself to provide extra hooks.
	extraHooks []terraform.Hook

	// This can be set by tests to change some directories
	dataDir string

	// Variables for the context (private)
	autoKey       string
	autoVariables map[string]string
	input         bool
	variables     map[string]string

	// Targets for this context (private)
	targets []string

	color bool
	oldUi cli.Ui

	// The fields below are expected to be set by the command via
	// command line flags. See the Apply command for an example.
	//
	// statePath is the path to the state file. If this is empty, then
	// no state will be loaded. It is also okay for this to be a path to
	// a file that doesn't exist; it is assumed that this means that there
	// is simply no state.
	//
	// stateOutPath is used to override the output path for the state.
	// If not provided, the StatePath is used causing the old state to
	// be overriden.
	//
	// backupPath is used to backup the state file before writing a modified
	// version. It defaults to stateOutPath + DefaultBackupExtention
	statePath    string
	stateOutPath string
	backupPath   string
}

// initStatePaths is used to initialize the default values for
// statePath, stateOutPath, and backupPath
func (m *Meta) initStatePaths() {
	if m.statePath == "" {
		m.statePath = DefaultStateFilename
	}
	if m.stateOutPath == "" {
		m.stateOutPath = m.statePath
	}
	if m.backupPath == "" {
		m.backupPath = m.stateOutPath + DefaultBackupExtention
	}
}

// StateOutPath returns the true output path for the state file
func (m *Meta) StateOutPath() string {
	return m.stateOutPath
}

// Colorize returns the colorization structure for a command.
func (m *Meta) Colorize() *colorstring.Colorize {
	return &colorstring.Colorize{
		Colors:  colorstring.DefaultColors,
		Disable: !m.color,
		Reset:   true,
	}
}

// Context returns a Terraform Context taking into account the context
// options used to initialize this meta configuration.
func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
	opts := m.contextOpts()

	// First try to just read the plan directly from the path given.
	f, err := os.Open(copts.Path)
	if err == nil {
		plan, err := terraform.ReadPlan(f)
		f.Close()
		if err == nil {
			// Setup our state
			state, statePath, err := StateFromPlan(m.statePath, plan)
			if err != nil {
				return nil, false, fmt.Errorf("Error loading plan: %s", err)
			}

			// Set our state
			m.state = state
			m.stateOutPath = statePath

			if len(m.variables) > 0 {
				return nil, false, fmt.Errorf(
					"You can't set variables with the '-var' or '-var-file' flag\n" +
						"when you're applying a plan file. The variables used when\n" +
						"the plan was created will be used. If you wish to use different\n" +
						"variable values, create a new plan file.")
			}

			return plan.Context(opts), true, nil
		}
	}

	// Load the statePath if not given
	if copts.StatePath != "" {
		m.statePath = copts.StatePath
	}

	// Tell the context if we're in a destroy plan / apply
	opts.Destroy = copts.Destroy

	// Store the loaded state
	state, err := m.State()
	if err != nil {
		return nil, false, err
	}

	// Load the root module
	mod, err := module.NewTreeModule("", copts.Path)
	if err != nil {
		return nil, false, fmt.Errorf("Error loading config: %s", err)
	}

	err = mod.Load(m.moduleStorage(m.DataDir()), copts.GetMode)
	if err != nil {
		return nil, false, fmt.Errorf("Error downloading modules: %s", err)
	}

	opts.Module = mod
	opts.State = state.State()
	ctx := terraform.NewContext(opts)
	return ctx, false, nil
}

// DataDir returns the directory where local data will be stored.
func (m *Meta) DataDir() string {
	dataDir := DefaultDataDirectory
	if m.dataDir != "" {
		dataDir = m.dataDir
	}

	return dataDir
}

const (
	// InputModeEnvVar is the environment variable that, if set to "false" or
	// "0", causes terraform commands to behave as if the `-input=false` flag was
	// specified.
	InputModeEnvVar = "TF_INPUT"
)

// InputMode returns the type of input we should ask for in the form of
// terraform.InputMode which is passed directly to Context.Input.
func (m *Meta) InputMode() terraform.InputMode {
	if test || !m.input {
		return 0
	}

	if envVar := os.Getenv(InputModeEnvVar); envVar != "" {
		if v, err := strconv.ParseBool(envVar); err == nil {
			if !v {
				return 0
			}
		}
	}

	var mode terraform.InputMode
	mode |= terraform.InputModeProvider
	if len(m.variables) == 0 && m.autoKey == "" {
		mode |= terraform.InputModeVar
		mode |= terraform.InputModeVarUnset
	}

	return mode
}

// State returns the state for this meta.
func (m *Meta) State() (state.State, error) {
	if m.state != nil {
		return m.state, nil
	}

	result, err := State(m.StateOpts())
	if err != nil {
		return nil, err
	}

	m.state = result.State
	m.stateOutPath = result.StatePath
	m.stateResult = result
	return m.state, nil
}

// StateRaw is used to setup the state manually.
func (m *Meta) StateRaw(opts *StateOpts) (*StateResult, error) {
	result, err := State(opts)
	if err != nil {
		return nil, err
	}

	m.state = result.State
	m.stateOutPath = result.StatePath
	m.stateResult = result
	return result, nil
}

// StateOpts returns the default state options
func (m *Meta) StateOpts() *StateOpts {
	localPath := m.statePath
	if localPath == "" {
		localPath = DefaultStateFilename
	}
	remotePath := filepath.Join(m.DataDir(), DefaultStateFilename)

	return &StateOpts{
		LocalPath:     localPath,
		LocalPathOut:  m.stateOutPath,
		RemotePath:    remotePath,
		RemoteRefresh: true,
		BackupPath:    m.backupPath,
	}
}

// UIInput returns a UIInput object to be used for asking for input.
func (m *Meta) UIInput() terraform.UIInput {
	return &UIInput{
		Colorize: m.Colorize(),
	}
}

// PersistState is used to write out the state, handling backup of
// the existing state file and respecting path configurations.
func (m *Meta) PersistState(s *terraform.State) error {
	if err := m.state.WriteState(s); err != nil {
		return err
	}

	return m.state.PersistState()
}

// Input returns true if we should ask for input for context.
func (m *Meta) Input() bool {
	return !test && m.input && len(m.variables) == 0
}

// contextOpts returns the options to use to initialize a Terraform
// context with the settings from this Meta.
func (m *Meta) contextOpts() *terraform.ContextOpts {
	var opts terraform.ContextOpts = *m.ContextOpts
	opts.Hooks = make(
		[]terraform.Hook,
		len(m.ContextOpts.Hooks)+len(m.extraHooks)+1)
	opts.Hooks[0] = m.uiHook()
	copy(opts.Hooks[1:], m.ContextOpts.Hooks)
	copy(opts.Hooks[len(m.ContextOpts.Hooks)+1:], m.extraHooks)

	vs := make(map[string]string)
	for k, v := range opts.Variables {
		vs[k] = v
	}
	for k, v := range m.autoVariables {
		vs[k] = v
	}
	for k, v := range m.variables {
		vs[k] = v
	}
	opts.Variables = vs
	opts.Targets = m.targets
	opts.UIInput = m.UIInput()

	return &opts
}

// flags adds the meta flags to the given FlagSet.
func (m *Meta) flagSet(n string) *flag.FlagSet {
	f := flag.NewFlagSet(n, flag.ContinueOnError)
	f.BoolVar(&m.input, "input", true, "input")
	f.Var((*FlagKV)(&m.variables), "var", "variables")
	f.Var((*FlagKVFile)(&m.variables), "var-file", "variable file")
	f.Var((*FlagStringSlice)(&m.targets), "target", "resource to target")

	if m.autoKey != "" {
		f.Var((*FlagKVFile)(&m.autoVariables), m.autoKey, "variable file")
	}

	// Create an io.Writer that writes to our Ui properly for errors.
	// This is kind of a hack, but it does the job. Basically: create
	// a pipe, use a scanner to break it into lines, and output each line
	// to the UI. Do this forever.
	errR, errW := io.Pipe()
	errScanner := bufio.NewScanner(errR)
	go func() {
		for errScanner.Scan() {
			m.Ui.Error(errScanner.Text())
		}
	}()
	f.SetOutput(errW)

	return f
}

// moduleStorage returns the module.Storage implementation used to store
// modules for commands.
func (m *Meta) moduleStorage(root string) module.Storage {
	return &uiModuleStorage{
		Storage: &module.FolderStorage{
			StorageDir: filepath.Join(root, "modules"),
		},
		Ui: m.Ui,
	}
}

// process will process the meta-parameters out of the arguments. This
// will potentially modify the args in-place. It will return the resulting
// slice.
//
// vars says whether or not we support variables.
func (m *Meta) process(args []string, vars bool) []string {
	// We do this so that we retain the ability to technically call
	// process multiple times, even if we have no plans to do so
	if m.oldUi != nil {
		m.Ui = m.oldUi
	}

	// Set colorization
	m.color = m.Color
	for i, v := range args {
		if v == "-no-color" {
			m.color = false
			args = append(args[:i], args[i+1:]...)
			break
		}
	}

	// Set the UI
	m.oldUi = m.Ui
	m.Ui = &cli.ConcurrentUi{
		Ui: &ColorizeUi{
			Colorize:   m.Colorize(),
			ErrorColor: "[red]",
			WarnColor:  "[yellow]",
			Ui:         m.oldUi,
		},
	}

	// If we support vars and the default var file exists, add it to
	// the args...
	m.autoKey = ""
	if vars {
		if _, err := os.Stat(DefaultVarsFilename); err == nil {
			m.autoKey = "var-file-default"
			args = append(args, "", "")
			copy(args[2:], args[0:])
			args[0] = "-" + m.autoKey
			args[1] = DefaultVarsFilename
		}

		if _, err := os.Stat(DefaultVarsFilename + ".json"); err == nil {
			m.autoKey = "var-file-default"
			args = append(args, "", "")
			copy(args[2:], args[0:])
			args[0] = "-" + m.autoKey
			args[1] = DefaultVarsFilename + ".json"
		}
	}

	return args
}

// uiHook returns the UiHook to use with the context.
func (m *Meta) uiHook() *UiHook {
	return &UiHook{
		Colorize: m.Colorize(),
		Ui:       m.Ui,
	}
}

const (
	// The name of the environment variable that can be used to set module depth.
	ModuleDepthEnvVar = "TF_MODULE_DEPTH"
)

func (m *Meta) addModuleDepthFlag(flags *flag.FlagSet, moduleDepth *int) {
	flags.IntVar(moduleDepth, "module-depth", 0, "module-depth")
	if envVar := os.Getenv(ModuleDepthEnvVar); envVar != "" {
		if md, err := strconv.Atoi(envVar); err == nil {
			*moduleDepth = md
		}
	}
}

// contextOpts are the options used to load a context from a command.
type contextOpts struct {
	// Path to the directory where the root module is.
	Path string

	// StatePath is the path to the state file. If this is empty, then
	// no state will be loaded. It is also okay for this to be a path to
	// a file that doesn't exist; it is assumed that this means that there
	// is simply no state.
	StatePath string

	// GetMode is the module.GetMode to use when loading the module tree.
	GetMode module.GetMode

	// Set to true when running a destroy plan/apply.
	Destroy bool
}
<commit_msg>Add -no-color option for subcommands<commit_after>package command

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strconv"

	"github.com/hashicorp/terraform/config/module"
	"github.com/hashicorp/terraform/state"
	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/cli"
	"github.com/mitchellh/colorstring"
)

// Meta are the meta-options that are available on all or most commands.
type Meta struct {
	Color       bool
	ContextOpts *terraform.ContextOpts
	Ui          cli.Ui

	// State read when calling `Context`. This is available after calling
	// `Context`.
	state       state.State
	stateResult *StateResult

	// This can be set by the command itself to provide extra hooks.
	extraHooks []terraform.Hook

	// This can be set by tests to change some directories
	dataDir string

	// Variables for the context (private)
	autoKey       string
	autoVariables map[string]string
	input         bool
	variables     map[string]string

	// Targets for this context (private)
	targets []string

	color bool
	oldUi cli.Ui

	// The fields below are expected to be set by the command via
	// command line flags. See the Apply command for an example.
	//
	// statePath is the path to the state file. If this is empty, then
	// no state will be loaded. It is also okay for this to be a path to
	// a file that doesn't exist; it is assumed that this means that there
	// is simply no state.
	//
	// stateOutPath is used to override the output path for the state.
	// If not provided, the StatePath is used causing the old state to
	// be overriden.
	//
	// backupPath is used to backup the state file before writing a modified
	// version. It defaults to stateOutPath + DefaultBackupExtention
	statePath    string
	stateOutPath string
	backupPath   string
}

// initStatePaths is used to initialize the default values for
// statePath, stateOutPath, and backupPath
func (m *Meta) initStatePaths() {
	if m.statePath == "" {
		m.statePath = DefaultStateFilename
	}
	if m.stateOutPath == "" {
		m.stateOutPath = m.statePath
	}
	if m.backupPath == "" {
		m.backupPath = m.stateOutPath + DefaultBackupExtention
	}
}

// StateOutPath returns the true output path for the state file
func (m *Meta) StateOutPath() string {
	return m.stateOutPath
}

// Colorize returns the colorization structure for a command.
func (m *Meta) Colorize() *colorstring.Colorize {
	return &colorstring.Colorize{
		Colors:  colorstring.DefaultColors,
		Disable: !m.color,
		Reset:   true,
	}
}

// Context returns a Terraform Context taking into account the context
// options used to initialize this meta configuration.
func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
	opts := m.contextOpts()

	// First try to just read the plan directly from the path given.
	f, err := os.Open(copts.Path)
	if err == nil {
		plan, err := terraform.ReadPlan(f)
		f.Close()
		if err == nil {
			// Setup our state
			state, statePath, err := StateFromPlan(m.statePath, plan)
			if err != nil {
				return nil, false, fmt.Errorf("Error loading plan: %s", err)
			}

			// Set our state
			m.state = state
			m.stateOutPath = statePath

			if len(m.variables) > 0 {
				return nil, false, fmt.Errorf(
					"You can't set variables with the '-var' or '-var-file' flag\n" +
						"when you're applying a plan file. The variables used when\n" +
						"the plan was created will be used. If you wish to use different\n" +
						"variable values, create a new plan file.")
			}

			return plan.Context(opts), true, nil
		}
	}

	// Load the statePath if not given
	if copts.StatePath != "" {
		m.statePath = copts.StatePath
	}

	// Tell the context if we're in a destroy plan / apply
	opts.Destroy = copts.Destroy

	// Store the loaded state
	state, err := m.State()
	if err != nil {
		return nil, false, err
	}

	// Load the root module
	mod, err := module.NewTreeModule("", copts.Path)
	if err != nil {
		return nil, false, fmt.Errorf("Error loading config: %s", err)
	}

	err = mod.Load(m.moduleStorage(m.DataDir()), copts.GetMode)
	if err != nil {
		return nil, false, fmt.Errorf("Error downloading modules: %s", err)
	}

	opts.Module = mod
	opts.State = state.State()
	ctx := terraform.NewContext(opts)
	return ctx, false, nil
}

// DataDir returns the directory where local data will be stored.
func (m *Meta) DataDir() string {
	dataDir := DefaultDataDirectory
	if m.dataDir != "" {
		dataDir = m.dataDir
	}

	return dataDir
}

const (
	// InputModeEnvVar is the environment variable that, if set to "false" or
	// "0", causes terraform commands to behave as if the `-input=false` flag was
	// specified.
	InputModeEnvVar = "TF_INPUT"
)

// InputMode returns the type of input we should ask for in the form of
// terraform.InputMode which is passed directly to Context.Input.
func (m *Meta) InputMode() terraform.InputMode {
	if test || !m.input {
		return 0
	}

	if envVar := os.Getenv(InputModeEnvVar); envVar != "" {
		if v, err := strconv.ParseBool(envVar); err == nil {
			if !v {
				return 0
			}
		}
	}

	var mode terraform.InputMode
	mode |= terraform.InputModeProvider
	if len(m.variables) == 0 && m.autoKey == "" {
		mode |= terraform.InputModeVar
		mode |= terraform.InputModeVarUnset
	}

	return mode
}

// State returns the state for this meta.
func (m *Meta) State() (state.State, error) {
	if m.state != nil {
		return m.state, nil
	}

	result, err := State(m.StateOpts())
	if err != nil {
		return nil, err
	}

	m.state = result.State
	m.stateOutPath = result.StatePath
	m.stateResult = result
	return m.state, nil
}

// StateRaw is used to setup the state manually.
func (m *Meta) StateRaw(opts *StateOpts) (*StateResult, error) {
	result, err := State(opts)
	if err != nil {
		return nil, err
	}

	m.state = result.State
	m.stateOutPath = result.StatePath
	m.stateResult = result
	return result, nil
}

// StateOpts returns the default state options
func (m *Meta) StateOpts() *StateOpts {
	localPath := m.statePath
	if localPath == "" {
		localPath = DefaultStateFilename
	}
	remotePath := filepath.Join(m.DataDir(), DefaultStateFilename)

	return &StateOpts{
		LocalPath:     localPath,
		LocalPathOut:  m.stateOutPath,
		RemotePath:    remotePath,
		RemoteRefresh: true,
		BackupPath:    m.backupPath,
	}
}

// UIInput returns a UIInput object to be used for asking for input.
func (m *Meta) UIInput() terraform.UIInput {
	return &UIInput{
		Colorize: m.Colorize(),
	}
}

// PersistState is used to write out the state, handling backup of
// the existing state file and respecting path configurations.
func (m *Meta) PersistState(s *terraform.State) error {
	if err := m.state.WriteState(s); err != nil {
		return err
	}

	return m.state.PersistState()
}

// Input returns true if we should ask for input for context.
func (m *Meta) Input() bool {
	return !test && m.input && len(m.variables) == 0
}

// contextOpts returns the options to use to initialize a Terraform
// context with the settings from this Meta.
func (m *Meta) contextOpts() *terraform.ContextOpts {
	var opts terraform.ContextOpts = *m.ContextOpts
	opts.Hooks = make(
		[]terraform.Hook,
		len(m.ContextOpts.Hooks)+len(m.extraHooks)+1)
	opts.Hooks[0] = m.uiHook()
	copy(opts.Hooks[1:], m.ContextOpts.Hooks)
	copy(opts.Hooks[len(m.ContextOpts.Hooks)+1:], m.extraHooks)

	vs := make(map[string]string)
	for k, v := range opts.Variables {
		vs[k] = v
	}
	for k, v := range m.autoVariables {
		vs[k] = v
	}
	for k, v := range m.variables {
		vs[k] = v
	}
	opts.Variables = vs
	opts.Targets = m.targets
	opts.UIInput = m.UIInput()

	return &opts
}

// flags adds the meta flags to the given FlagSet.
func (m *Meta) flagSet(n string) *flag.FlagSet {
	f := flag.NewFlagSet(n, flag.ContinueOnError)
	f.BoolVar(&m.input, "input", true, "input")
	f.Var((*FlagKV)(&m.variables), "var", "variables")
	f.Var((*FlagKVFile)(&m.variables), "var-file", "variable file")
	f.Var((*FlagStringSlice)(&m.targets), "target", "resource to target")

	if m.autoKey != "" {
		f.Var((*FlagKVFile)(&m.autoVariables), m.autoKey, "variable file")
	}

	// Create an io.Writer that writes to our Ui properly for errors.
	// This is kind of a hack, but it does the job. Basically: create
	// a pipe, use a scanner to break it into lines, and output each line
	// to the UI. Do this forever.
	errR, errW := io.Pipe()
	errScanner := bufio.NewScanner(errR)
	go func() {
		for errScanner.Scan() {
			m.Ui.Error(errScanner.Text())
		}
	}()
	f.SetOutput(errW)

	return f
}

// moduleStorage returns the module.Storage implementation used to store
// modules for commands.
func (m *Meta) moduleStorage(root string) module.Storage {
	return &uiModuleStorage{
		Storage: &module.FolderStorage{
			StorageDir: filepath.Join(root, "modules"),
		},
		Ui: m.Ui,
	}
}

// process will process the meta-parameters out of the arguments. This
// will potentially modify the args in-place. It will return the resulting
// slice.
//
// vars says whether or not we support variables.
func (m *Meta) process(args []string, vars bool) []string {
	// We do this so that we retain the ability to technically call
	// process multiple times, even if we have no plans to do so
	if m.oldUi != nil {
		m.Ui = m.oldUi
	}

	// Set colorization
	m.color = m.Color
	for i, v := range args {
		if v == "-no-color" {
			m.color = false
			m.Color = false
			args = append(args[:i], args[i+1:]...)
			break
		}
	}

	// Set the UI
	m.oldUi = m.Ui
	m.Ui = &cli.ConcurrentUi{
		Ui: &ColorizeUi{
			Colorize:   m.Colorize(),
			ErrorColor: "[red]",
			WarnColor:  "[yellow]",
			Ui:         m.oldUi,
		},
	}

	// If we support vars and the default var file exists, add it to
	// the args...
	m.autoKey = ""
	if vars {
		if _, err := os.Stat(DefaultVarsFilename); err == nil {
			m.autoKey = "var-file-default"
			args = append(args, "", "")
			copy(args[2:], args[0:])
			args[0] = "-" + m.autoKey
			args[1] = DefaultVarsFilename
		}

		if _, err := os.Stat(DefaultVarsFilename + ".json"); err == nil {
			m.autoKey = "var-file-default"
			args = append(args, "", "")
			copy(args[2:], args[0:])
			args[0] = "-" + m.autoKey
			args[1] = DefaultVarsFilename + ".json"
		}
	}

	return args
}

// uiHook returns the UiHook to use with the context.
func (m *Meta) uiHook() *UiHook {
	return &UiHook{
		Colorize: m.Colorize(),
		Ui:       m.Ui,
	}
}

const (
	// The name of the environment variable that can be used to set module depth.
	ModuleDepthEnvVar = "TF_MODULE_DEPTH"
)

func (m *Meta) addModuleDepthFlag(flags *flag.FlagSet, moduleDepth *int) {
	flags.IntVar(moduleDepth, "module-depth", 0, "module-depth")
	if envVar := os.Getenv(ModuleDepthEnvVar); envVar != "" {
		if md, err := strconv.Atoi(envVar); err == nil {
			*moduleDepth = md
		}
	}
}

// contextOpts are the options used to load a context from a command.
type contextOpts struct {
	// Path to the directory where the root module is.
	Path string

	// StatePath is the path to the state file. If this is empty, then
	// no state will be loaded. It is also okay for this to be a path to
	// a file that doesn't exist; it is assumed that this means that there
	// is simply no state.
	StatePath string

	// GetMode is the module.GetMode to use when loading the module tree.
	GetMode module.GetMode

	// Set to true when running a destroy plan/apply.
	Destroy bool
}
<|endoftext|>