<commit_before>package core

import (
	"os"

	"github.com/hraberg/cljs.go/js"
)

import "fmt"

// This file will eventually be generated from cljs.core.

var STAR_print_fn_STAR_ = func(_ interface{}) interface{} {
	panic(js.Error{"No *print-fn* fn set for evaluation environment"})
}

var STAR_print_newline_STAR_ = true

func Enable_console_print_BANG_() interface{} {
	STAR_print_newline_STAR_ = false
	STAR_print_fn_STAR_ = func(x interface{}) interface{} {
		js.Console.Log(x)
		return nil
	}
	return nil
}

var STAR_main_cli_fn_STAR_ interface{}

func pr_opts() interface{} {
	return nil
}

func Newline(opts interface{}) interface{} {
	if STAR_print_newline_STAR_ {
		STAR_print_fn_STAR_("\n")
	}
	return nil
}

func Println(objs ...interface{}) interface{} {
	STAR_print_fn_STAR_(fmt.Sprint(objs...))
	Newline(pr_opts())
	return nil
}

// Main preamble

func Main() {
	Enable_console_print_BANG_()
	var args = make([]interface{}, len(os.Args[1:]))
	for i, a := range os.Args[1:] {
		args[i] = a
	}
	STAR_main_cli_fn_STAR_.(func(...interface{}) interface{})(args...)
}

// IFn

type CljsCoreIFn_InvokeArityVariadic func(...interface{}) interface{}
type CljsCoreIFn_InvokeArity0 func() interface{}
type CljsCoreIFn_InvokeArity1 func(interface{}) interface{}
type CljsCoreIFn_InvokeArity2 func(_, _ interface{}) interface{}
type CljsCoreIFn_InvokeArity3 func(_, _, _ interface{}) interface{}
type CljsCoreIFn_InvokeArity4 func(_, _, _, _ interface{}) interface{}

// There's a protocol called cljs.core.IFn we need to cooperate with, so we use AFn for now.
// So we might need to complicate this for various reasons, Keywords for example are IFns by protocol.
// That is, they implement CljsCoreIFn_InvokeArity1 (and 2), so we might need to re-add the interfaces.
// The easiest way to acheive this is renaming (and hide) the fields, and make CljsCoreIFn_InvokeArity1 an interface method.
// Then there's the issue of other protocols and how to represent them, as we prefer to keep them as Go interfaces.
// As can be seen above regarding IFn, it would be nice to ensure that IFn is just a special case that emit* :invoke knows about.
// My impression is that this is how CLJS does it. To reiterate - the reason this becomes extra messy in Go is lack of overloading.
// The main issue of making all invocations methods is that there's no way to create an anonymous type.
// The anonymous function bodies need to stay in the context where they're defined for closures to work.
// Interfaces might solve this though, as per earlier spikes.
// Another reason a function cannot (only) be an empty struct, is that in a protocol it's an interface method in Go.
// Most of this should be solvable with some indirection and interfaces.

// We also have the issue of functions that refer to themselves and how to ensure the var exists.
// This is extra interesting for anonymous "named" functions, ie. (fn foo [] (foo))

type AFn struct {
	CljsLangMaxFixedArity int
	CljsCoreIFn_InvokeArityVariadic
	CljsCoreIFn_InvokeArity0
	CljsCoreIFn_InvokeArity1
	CljsCoreIFn_InvokeArity2
	CljsCoreIFn_InvokeArity3
	CljsCoreIFn_InvokeArity4
}

func throwArity(arity int) interface{} {
	panic(js.Error{fmt.Sprint("Invalid arity: ", arity)})
}

func (this AFn) CljsCoreIFn_Invoke(args ...interface{}) interface{} {
	var argc = len(args)
	switch {
	case argc == 0 && this.CljsCoreIFn_InvokeArity0 != nil:
		return this.CljsCoreIFn_InvokeArity0()
	case argc == 1 && this.CljsCoreIFn_InvokeArity1 != nil:
		return this.CljsCoreIFn_InvokeArity1(args[0])
	case argc == 2 && this.CljsCoreIFn_InvokeArity2 != nil:
		return this.CljsCoreIFn_InvokeArity2(args[0], args[1])
	case argc == 3 && this.CljsCoreIFn_InvokeArity3 != nil:
		return this.CljsCoreIFn_InvokeArity3(args[0], args[1], args[3])
	case argc == 4 && this.CljsCoreIFn_InvokeArity4 != nil:
		return this.CljsCoreIFn_InvokeArity4(args[0], args[1], args[3], args[4])
	case argc > this.CljsLangMaxFixedArity && this.CljsCoreIFn_InvokeArityVariadic != nil:
		return this.CljsCoreIFn_InvokeArityVariadic(args...)
	}
	return throwArity(argc)
}

func (this AFn) CljsLangApplyTo(args ...interface{}) interface{} {
	var argc = len(args)
	if argc < 1 {
		throwArity(argc)
	}
	var spread = args[argc-1].([]interface{})
	return this.CljsCoreIFn_Invoke(append(args[:argc-1], spread...)...)
}

/*

There's a cljs.core, clj macro that eagerly turns things into strings in cljs.core.clj, but when not:
(str x) compiles to cljs.core.str.cljs$core$IFn$_invoke$arity$1(x)
cljs.core.str is the fn var
cljs$core$IFn is the protocol
$_invoke is the protocol fn
$arity$1 is the overload, ie [this a] in IFn, [x] in str. (How does the variadic [x & ys] map to the IFn arities?)

;; in cljs.core, cljs
(defn str
  "With no args, returns the empty string. With one arg x, returns
  x.toString().  (str nil) returns the empty string. With more than
  one arg, returns the concatenation of the str values of the args."
  ([] "")
  ([x] (if (nil? x)
         ""
         (.toString x)))
  ([x & ys]
    (loop [sb (StringBuffer. (str x)) more ys]
      (if more
        (recur (. sb  (append (str (first more)))) (next more))
        (.toString sb)))))

(defprotocol IFn
  (-invoke
    [this]
    [this a]
    [this a b]
    [this a b c]
    [this a b c d]
    [this a b c d e]
    [this a b c d e f]
    [this a b c d e f g]
    [this a b c d e f g h]
    [this a b c d e f g h i]
    [this a b c d e f g h i j]
    [this a b c d e f g h i j k]
    [this a b c d e f g h i j k l]
    [this a b c d e f g h i j k l m]
    [this a b c d e f g h i j k l m n]
    [this a b c d e f g h i j k l m n o]
    [this a b c d e f g h i j k l m n o p]
    [this a b c d e f g h i j k l m n o p q]
    [this a b c d e f g h i j k l m n o p q s]
    [this a b c d e f g h i j k l m n o p q s t]
    [this a b c d e f g h i j k l m n o p q s t rest]))
*/
<commit_msg>Some notes about seqs vs arrays<commit_after>package core

import (
	"os"

	"github.com/hraberg/cljs.go/js"
)

import "fmt"

// This file will eventually be generated from cljs.core.

var STAR_print_fn_STAR_ = func(_ interface{}) interface{} {
	panic(js.Error{"No *print-fn* fn set for evaluation environment"})
}

var STAR_print_newline_STAR_ = true

func Enable_console_print_BANG_() interface{} {
	STAR_print_newline_STAR_ = false
	STAR_print_fn_STAR_ = func(x interface{}) interface{} {
		js.Console.Log(x)
		return nil
	}
	return nil
}

var STAR_main_cli_fn_STAR_ interface{}

func pr_opts() interface{} {
	return nil
}

func Newline(opts interface{}) interface{} {
	if STAR_print_newline_STAR_ {
		STAR_print_fn_STAR_("\n")
	}
	return nil
}

func Println(objs ...interface{}) interface{} {
	STAR_print_fn_STAR_(fmt.Sprint(objs...))
	Newline(pr_opts())
	return nil
}

// Main preamble

func Main() {
	Enable_console_print_BANG_()
	var args = make([]interface{}, len(os.Args[1:]))
	for i, a := range os.Args[1:] {
		args[i] = a
	}
	STAR_main_cli_fn_STAR_.(func(...interface{}) interface{})(args...)
}

// IFn

// Implementations need to set up actual named locals as argument, and create an array-seq from the varargs.
type CljsCoreIFn_InvokeArityVariadic func(...interface{}) interface{}
type CljsCoreIFn_InvokeArity0 func() interface{}
type CljsCoreIFn_InvokeArity1 func(interface{}) interface{}
type CljsCoreIFn_InvokeArity2 func(_, _ interface{}) interface{}
type CljsCoreIFn_InvokeArity3 func(_, _, _ interface{}) interface{}
type CljsCoreIFn_InvokeArity4 func(_, _, _, _ interface{}) interface{}

// There's a protocol called cljs.core.IFn we need to cooperate with, so we use AFn for now.
// So we might need to complicate this for various reasons, Keywords for example are IFns by protocol.
// That is, they implement CljsCoreIFn_InvokeArity1 (and 2), so we might need to re-add the interfaces.
// The easiest way to acheive this is renaming (and hide) the fields, and make CljsCoreIFn_InvokeArity1 an interface method.
// Then there's the issue of other protocols and how to represent them, as we prefer to keep them as Go interfaces.
// As can be seen above regarding IFn, it would be nice to ensure that IFn is just a special case that emit* :invoke knows about.
// My impression is that this is how CLJS does it. To reiterate - the reason this becomes extra messy in Go is lack of overloading.
// The main issue of making all invocations methods is that there's no way to create an anonymous type.
// The anonymous function bodies need to stay in the context where they're defined for closures to work.
// Interfaces might solve this though, as per earlier spikes.
// Another reason a function cannot (only) be an empty struct, is that in a protocol it's an interface method in Go.
// Most of this should be solvable with some indirection and interfaces.

// We also have the issue of functions that refer to themselves and how to ensure the var exists.
// This is extra interesting for anonymous "named" functions, ie. (fn foo [] (foo))

type AFn struct {
	CljsLangMaxFixedArity int
	CljsCoreIFn_InvokeArityVariadic
	CljsCoreIFn_InvokeArity0
	CljsCoreIFn_InvokeArity1
	CljsCoreIFn_InvokeArity2
	CljsCoreIFn_InvokeArity3
	CljsCoreIFn_InvokeArity4
}

func throwArity(arity int) interface{} {
	panic(js.Error{fmt.Sprint("Invalid arity: ", arity)})
}

func (this AFn) CljsCoreIFn_Invoke(args ...interface{}) interface{} {
	var argc = len(args)
	switch {
	case argc == 0 && this.CljsCoreIFn_InvokeArity0 != nil:
		return this.CljsCoreIFn_InvokeArity0()
	case argc == 1 && this.CljsCoreIFn_InvokeArity1 != nil:
		return this.CljsCoreIFn_InvokeArity1(args[0])
	case argc == 2 && this.CljsCoreIFn_InvokeArity2 != nil:
		return this.CljsCoreIFn_InvokeArity2(args[0], args[1])
	case argc == 3 && this.CljsCoreIFn_InvokeArity3 != nil:
		return this.CljsCoreIFn_InvokeArity3(args[0], args[1], args[3])
	case argc == 4 && this.CljsCoreIFn_InvokeArity4 != nil:
		return this.CljsCoreIFn_InvokeArity4(args[0], args[1], args[3], args[4])
	case argc > this.CljsLangMaxFixedArity && this.CljsCoreIFn_InvokeArityVariadic != nil:
		return this.CljsCoreIFn_InvokeArityVariadic(args...)
	}
	return throwArity(argc)
}

func (this AFn) CljsLangApplyTo(args ...interface{}) interface{} {
	var argc = len(args)
	if argc < 1 {
		throwArity(argc)
	}
	var spread = args[argc-1].([]interface{}) // This will be a seq in real life.
	return this.CljsCoreIFn_Invoke(append(args[:argc-1], spread...)...)
}

/*

There's a cljs.core, clj macro that eagerly turns things into strings in cljs.core.clj, but when not:
(str x) compiles to cljs.core.str.cljs$core$IFn$_invoke$arity$1(x)
cljs.core.str is the fn var
cljs$core$IFn is the protocol
$_invoke is the protocol fn
$arity$1 is the overload, ie [this a] in IFn, [x] in str. (How does the variadic [x & ys] map to the IFn arities?)

;; in cljs.core, cljs
(defn str
  "With no args, returns the empty string. With one arg x, returns
  x.toString().  (str nil) returns the empty string. With more than
  one arg, returns the concatenation of the str values of the args."
  ([] "")
  ([x] (if (nil? x)
         ""
         (.toString x)))
  ([x & ys]
    (loop [sb (StringBuffer. (str x)) more ys]
      (if more
        (recur (. sb  (append (str (first more)))) (next more))
        (.toString sb)))))

(defprotocol IFn
  (-invoke
    [this]
    [this a]
    [this a b]
    [this a b c]
    [this a b c d]
    [this a b c d e]
    [this a b c d e f]
    [this a b c d e f g]
    [this a b c d e f g h]
    [this a b c d e f g h i]
    [this a b c d e f g h i j]
    [this a b c d e f g h i j k]
    [this a b c d e f g h i j k l]
    [this a b c d e f g h i j k l m]
    [this a b c d e f g h i j k l m n]
    [this a b c d e f g h i j k l m n o]
    [this a b c d e f g h i j k l m n o p]
    [this a b c d e f g h i j k l m n o p q]
    [this a b c d e f g h i j k l m n o p q s]
    [this a b c d e f g h i j k l m n o p q s t]
    [this a b c d e f g h i j k l m n o p q s t rest]))
*/
<|endoftext|>


<commit_before>// Copyright 2020 Sven Rebhan.
// Licensed under the MIT license which can be found in the LICENSE file.

package dpt

import (
	"reflect"
	"sync"
)

var (
	types = [...]DatapointValue{
		// 1.xxx
		new(DPT_1001),
		new(DPT_1002),
		new(DPT_1003),
		new(DPT_1009),
		new(DPT_1010),

		// 5.xxx
		new(DPT_5001),
		new(DPT_5003),
		new(DPT_5004),

		// 7.xxx
		new(DPT_7001),
		new(DPT_7002),
		new(DPT_7003),
		new(DPT_7004),
		new(DPT_7005),
		new(DPT_7006),
		new(DPT_7007),
		new(DPT_7010),
		new(DPT_7011),
		new(DPT_7012),
		new(DPT_7013),

		// 9.xxx
		new(DPT_9001),
		new(DPT_9002),
		new(DPT_9003),
		new(DPT_9004),
		new(DPT_9005),
		new(DPT_9006),
		new(DPT_9007),
		new(DPT_9008),
		new(DPT_9010),
		new(DPT_9011),
		new(DPT_9020),
		new(DPT_9021),
		new(DPT_9022),
		new(DPT_9023),
		new(DPT_9024),
		new(DPT_9025),
		new(DPT_9026),
		new(DPT_9027),
		new(DPT_9028),

		// 12.xxx
		new(DPT_12001),

		// 13.xxx
		new(DPT_13001),
		new(DPT_13002),
		new(DPT_13010),
		new(DPT_13011),
		new(DPT_13012),
		new(DPT_13013),
		new(DPT_13014),
		new(DPT_13015),
		new(DPT_13016),
		new(DPT_13100),

		// 14.xxx
		new(DPT_14000),
		new(DPT_14001),
		new(DPT_14002),
		new(DPT_14010),
		new(DPT_14011),
		new(DPT_14012),
		new(DPT_14013),
		new(DPT_14014),
		new(DPT_14015),
		new(DPT_14016),
		new(DPT_14017),
		new(DPT_14018),
		new(DPT_14019),
		new(DPT_14020),
		new(DPT_14021),
		new(DPT_14022),
		new(DPT_14023),
		new(DPT_14024),
		new(DPT_14025),
		new(DPT_14026),
		new(DPT_14027),
		new(DPT_14028),
		new(DPT_14029),
		new(DPT_14030),
		new(DPT_14031),
		new(DPT_14032),
		new(DPT_14033),
		new(DPT_14034),
		new(DPT_14035),
		new(DPT_14036),
		new(DPT_14037),
		new(DPT_14038),
		new(DPT_14039),
		new(DPT_14040),
		new(DPT_14041),
		new(DPT_14042),
		new(DPT_14043),
		new(DPT_14044),
		new(DPT_14045),
		new(DPT_14046),
		new(DPT_14047),
		new(DPT_14048),
		new(DPT_14049),
		new(DPT_14050),
		new(DPT_14051),
		new(DPT_14052),
		new(DPT_14053),
		new(DPT_14054),
		new(DPT_14055),
		new(DPT_14056),
		new(DPT_14057),
		new(DPT_14058),
		new(DPT_14059),
		new(DPT_14060),
		new(DPT_14061),
		new(DPT_14062),
		new(DPT_14063),
		new(DPT_14064),
		new(DPT_14065),
		new(DPT_14066),
		new(DPT_14067),
		new(DPT_14068),
		new(DPT_14069),
		new(DPT_14070),
		new(DPT_14071),
		new(DPT_14072),
		new(DPT_14073),
		new(DPT_14074),
		new(DPT_14075),
		new(DPT_14076),
		new(DPT_14077),
		new(DPT_14078),
		new(DPT_14079),

		// 17.xxx
		new(DPT_17001),
		// 18.xxx
		new(DPT_18001),
		// 251.xxx
		new(DPT_251600),
	}
	once     sync.Once
	registry map[string]reflect.Type
)

// Init function used to add all types
func setup() {
	// Singleton, can only run once
	once.Do(func() {
		// Register the types
		registry = make(map[string]reflect.Type)
		for _, d := range types {
			// Determine the name of the datatype
			d_type := reflect.TypeOf(d).Elem()
			name := d_type.Name()

			// Convert the name into KNX yy.xxx (e.g. DPT_1001 --> 1.001) format
			name = name[4:len(name)-3] + "." + name[len(name)-3:]

			// Register the type
			registry[name] = d_type
		}
	})
}

// ListSupportedTypes returns the name all known datapoint-types (DPTs).
func ListSupportedTypes() []string {
	// Setup the registry
	setup()

	// Initialize the key-list
	keys := make([]string, len(registry))

	// Fill the key-list
	i := 0
	for k := range registry {
		keys[i] = k
		i++
	}

	return keys
}

// Produce creates a new instance of the given datapoint-type name e.g. "1.001".
func Produce(name string) (d DatapointValue, ok bool) {
	// Setup the registry
	setup()

	// Lookup the given type and create a new instance of that type
	x, ok := registry[name]
	if ok {
		d = reflect.New(x).Interface().(DatapointValue)
	}
	return d, ok
}
<commit_msg>Add DPT 1.008 to registry<commit_after>// Copyright 2020 Sven Rebhan.
// Licensed under the MIT license which can be found in the LICENSE file.

package dpt

import (
	"reflect"
	"sync"
)

var (
	types = [...]DatapointValue{
		// 1.xxx
		new(DPT_1001),
		new(DPT_1002),
		new(DPT_1003),
		new(DPT_1008),
		new(DPT_1009),
		new(DPT_1010),

		// 5.xxx
		new(DPT_5001),
		new(DPT_5003),
		new(DPT_5004),

		// 7.xxx
		new(DPT_7001),
		new(DPT_7002),
		new(DPT_7003),
		new(DPT_7004),
		new(DPT_7005),
		new(DPT_7006),
		new(DPT_7007),
		new(DPT_7010),
		new(DPT_7011),
		new(DPT_7012),
		new(DPT_7013),

		// 9.xxx
		new(DPT_9001),
		new(DPT_9002),
		new(DPT_9003),
		new(DPT_9004),
		new(DPT_9005),
		new(DPT_9006),
		new(DPT_9007),
		new(DPT_9008),
		new(DPT_9010),
		new(DPT_9011),
		new(DPT_9020),
		new(DPT_9021),
		new(DPT_9022),
		new(DPT_9023),
		new(DPT_9024),
		new(DPT_9025),
		new(DPT_9026),
		new(DPT_9027),
		new(DPT_9028),

		// 12.xxx
		new(DPT_12001),

		// 13.xxx
		new(DPT_13001),
		new(DPT_13002),
		new(DPT_13010),
		new(DPT_13011),
		new(DPT_13012),
		new(DPT_13013),
		new(DPT_13014),
		new(DPT_13015),
		new(DPT_13016),
		new(DPT_13100),

		// 14.xxx
		new(DPT_14000),
		new(DPT_14001),
		new(DPT_14002),
		new(DPT_14010),
		new(DPT_14011),
		new(DPT_14012),
		new(DPT_14013),
		new(DPT_14014),
		new(DPT_14015),
		new(DPT_14016),
		new(DPT_14017),
		new(DPT_14018),
		new(DPT_14019),
		new(DPT_14020),
		new(DPT_14021),
		new(DPT_14022),
		new(DPT_14023),
		new(DPT_14024),
		new(DPT_14025),
		new(DPT_14026),
		new(DPT_14027),
		new(DPT_14028),
		new(DPT_14029),
		new(DPT_14030),
		new(DPT_14031),
		new(DPT_14032),
		new(DPT_14033),
		new(DPT_14034),
		new(DPT_14035),
		new(DPT_14036),
		new(DPT_14037),
		new(DPT_14038),
		new(DPT_14039),
		new(DPT_14040),
		new(DPT_14041),
		new(DPT_14042),
		new(DPT_14043),
		new(DPT_14044),
		new(DPT_14045),
		new(DPT_14046),
		new(DPT_14047),
		new(DPT_14048),
		new(DPT_14049),
		new(DPT_14050),
		new(DPT_14051),
		new(DPT_14052),
		new(DPT_14053),
		new(DPT_14054),
		new(DPT_14055),
		new(DPT_14056),
		new(DPT_14057),
		new(DPT_14058),
		new(DPT_14059),
		new(DPT_14060),
		new(DPT_14061),
		new(DPT_14062),
		new(DPT_14063),
		new(DPT_14064),
		new(DPT_14065),
		new(DPT_14066),
		new(DPT_14067),
		new(DPT_14068),
		new(DPT_14069),
		new(DPT_14070),
		new(DPT_14071),
		new(DPT_14072),
		new(DPT_14073),
		new(DPT_14074),
		new(DPT_14075),
		new(DPT_14076),
		new(DPT_14077),
		new(DPT_14078),
		new(DPT_14079),

		// 17.xxx
		new(DPT_17001),
		// 18.xxx
		new(DPT_18001),
		// 251.xxx
		new(DPT_251600),
	}
	once     sync.Once
	registry map[string]reflect.Type
)

// Init function used to add all types
func setup() {
	// Singleton, can only run once
	once.Do(func() {
		// Register the types
		registry = make(map[string]reflect.Type)
		for _, d := range types {
			// Determine the name of the datatype
			d_type := reflect.TypeOf(d).Elem()
			name := d_type.Name()

			// Convert the name into KNX yy.xxx (e.g. DPT_1001 --> 1.001) format
			name = name[4:len(name)-3] + "." + name[len(name)-3:]

			// Register the type
			registry[name] = d_type
		}
	})
}

// ListSupportedTypes returns the name all known datapoint-types (DPTs).
func ListSupportedTypes() []string {
	// Setup the registry
	setup()

	// Initialize the key-list
	keys := make([]string, len(registry))

	// Fill the key-list
	i := 0
	for k := range registry {
		keys[i] = k
		i++
	}

	return keys
}

// Produce creates a new instance of the given datapoint-type name e.g. "1.001".
func Produce(name string) (d DatapointValue, ok bool) {
	// Setup the registry
	setup()

	// Lookup the given type and create a new instance of that type
	x, ok := registry[name]
	if ok {
		d = reflect.New(x).Interface().(DatapointValue)
	}
	return d, ok
}
<|endoftext|>


<commit_before>// Copyright 2016 Andrew O'Neill, Nordstrom

// 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 (
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"net/http/pprof"
	"os"
	"os/signal"
	"syscall"
	"time"

	"golang.org/x/net/context"

	"github.com/Nordstrom/choices"
	"github.com/foolusion/elwinprotos/elwin"
	"github.com/pkg/errors"
	"github.com/prometheus/client_golang/prometheus"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
)

var config = struct {
	ec              *choices.Config
	grpcAddr        string
	jsonAddr        string
	mongoAddr       string
	mongoDB         string
	mongoCollection string
	readTimeout     string
	writeTimeout    string
	idleTimeout     string
	readiness       struct {
		storage      bool
		grpcServer   bool
		errorHandler bool
		httpServer   bool
	}
}{
	jsonAddr:        ":8081",
	grpcAddr:        ":8080",
	mongoAddr:       "elwin-storage:80",
	mongoDB:         "elwin",
	mongoCollection: "test",
	readTimeout:     "5s",
	writeTimeout:    "5s",
	idleTimeout:     "30s",
}

var (
	jsonRequests = prometheus.NewCounter(prometheus.CounterOpts{
		Namespace: "nordstrom",
		Subsystem: "elwin",
		Name:      "json_requests",
		Help:      "The number of json requests recieved.",
	})
	jsonDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
		Namespace: "nordstrom",
		Subsystem: "elwin",
		Name:      "json_durations_nanoseconds",
		Help:      "json latency distributions.",
		Buckets:   prometheus.ExponentialBuckets(1, 10, 10),
	})
	updateErrors = prometheus.NewCounter(prometheus.CounterOpts{
		Namespace: "nordstrom",
		Subsystem: "elwin",
		Name:      "update_errors",
		Help:      "The number of errors while updating storage.",
	})
)

const (
	envJSONAddr     = "JSON_ADDRESS"
	envGRPCAddr     = "GRPC_ADDRESS"
	envMongoAddr    = "MONGO_ADDRESS"
	envMongoDB      = "MONGO_DATABASE"
	envMongoColl    = "MONGO_COLLECTION"
	envReadTimeout  = "READ_TIMEOUT"
	envWriteTimeout = "WRITE_TIMEOUT"
	envIdleTimeout  = "IDLE_TIMEOUT"
	envProfiler     = "PROFILER"
)

func env(dst *string, src string) {
	if os.Getenv(src) != "" {
		*dst = os.Getenv(src)
		log.Printf("Set %s to %s", src, *dst)
	}
}

func main() {
	log.Println("Starting elwin...")

	env(&config.jsonAddr, envJSONAddr)
	env(&config.grpcAddr, envGRPCAddr)
	env(&config.mongoAddr, envMongoAddr)
	env(&config.mongoDB, envMongoDB)
	env(&config.mongoCollection, envMongoColl)
	env(&config.readTimeout, envReadTimeout)
	env(&config.writeTimeout, envWriteTimeout)
	env(&config.idleTimeout, envIdleTimeout)

	var storageEnv int
	switch config.mongoCollection {
	case "staging", "dev", "test":
		storageEnv = choices.StorageEnvironmentDev
	case "production", "prod":
		storageEnv = choices.StorageEnvironmentProd
	default:
		log.Fatal("bad storage environment")
	}
	log.Println(config.mongoCollection, storageEnv)

	// create elwin config
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	ec, err := choices.NewChoices(
		ctx,
		choices.WithGlobalSalt("choices"),
		choices.WithStorageConfig(config.mongoAddr, storageEnv),
		choices.WithUpdateInterval(10*time.Second),
	)
	if err != nil {
		log.Fatal(err)
	}
	config.ec = ec
	config.readiness.storage = true

	// register prometheus metrics
	prometheus.MustRegister(jsonRequests)
	prometheus.MustRegister(jsonDurations)
	prometheus.MustRegister(updateErrors)

	ljson, err := net.Listen("tcp", config.jsonAddr)
	if err != nil {
		log.Fatalf("could not listen on %s: %v", config.jsonAddr, err)
	}
	defer ljson.Close()

	mux := http.NewServeMux()
	mux.HandleFunc("/", rootHandler)
	mux.HandleFunc("/healthz", healthzHandler)
	mux.HandleFunc("/readiness", readinessHandler)
	mux.Handle("/metrics", prometheus.Handler())
	if len(os.Getenv(envProfiler)) > 0 {
		mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
	}
	srv := http.Server{
		Handler: mux,
	}
	if rt, err := time.ParseDuration(config.readTimeout); err != nil {
		log.Fatal(err)
	} else if wt, err := time.ParseDuration(config.writeTimeout); err != nil {
		log.Fatal(err)
	} else if it, err := time.ParseDuration(config.idleTimeout); err != nil {
		log.Fatal(err)
	} else {
		srv.ReadTimeout = rt
		srv.WriteTimeout = wt
		srv.IdleTimeout = it
	}

	go func() {
		config.readiness.httpServer = true
		config.ec.ErrChan <- srv.Serve(ljson)
	}()

	go func() {
		lgrpc, err := net.Listen("tcp", config.grpcAddr)
		if err != nil {
			config.ec.ErrChan <- fmt.Errorf("main: failed to listen: %v", err)
		}
		defer lgrpc.Close()

		grpcServer := grpc.NewServer()
		elwin.RegisterElwinServer(grpcServer, &elwinServer{})
		config.readiness.grpcServer = true
		config.ec.ErrChan <- grpcServer.Serve(lgrpc)
	}()

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

	config.readiness.errorHandler = true
	for {
		select {
		case err := <-config.ec.ErrChan:
			if err != nil {
				switch err := errors.Cause(err).(type) {
				case choices.ErrUpdateStorage:
					updateErrors.Inc()
					log.Println(err)
					continue
				default:
					log.Fatal(err)
				}
			}
		case s := <-signalChan:
			log.Printf("Captured %v. Exitting...", s)
			// send StatusServiceUnavailable to new requestors
			// block server from accepting new requests
			os.Exit(0)
		}
	}
}

type elwinServer struct{}

func (e *elwinServer) GetNamespaces(ctx context.Context, id *elwin.Identifier) (*elwin.Experiments, error) {
	log.Printf("GetNamespaces: %v", id)
	if id == nil {
		return nil, grpc.Errorf(codes.InvalidArgument, "GetNamespaces: no Identifier recieved")
	}

	resp, err := config.ec.Namespaces(id.TeamID, id.UserID)
	if err != nil {
		return nil, fmt.Errorf("error resolving namespaces for %s, %s: %v", id.TeamID, id.UserID, err)
	}

	exp := &elwin.Experiments{
		Experiments: make(map[string]*elwin.Experiment, len(resp)),
	}

	for _, v := range resp {
		exp.Experiments[v.Name] = &elwin.Experiment{
			Namespace: v.Namespace,
			Params:    make([]*elwin.Param, len(v.Params)),
		}

		for i, p := range v.Params {
			exp.Experiments[v.Name].Params[i] = &elwin.Param{
				Name:  p.Name,
				Value: p.Value,
			}
		}
	}
	return exp, nil
}

func logCloseErr(c io.Closer) {
	if err := c.Close(); err != nil {
		log.Printf("could not close response body: %s", err)
	}
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	start := time.Now()
	defer jsonRequests.Inc()
	defer func() {
		jsonDurations.Observe(float64(time.Since(start)))
	}()
	if err := r.ParseForm(); err != nil {
		log.Printf("could not parse form: %s", err)
		w.WriteHeader(http.StatusBadRequest)
		w.Header().Set("Content-type", "text/plain")
		if _, err := w.Write([]byte("invalid form data")); err != nil {
			log.Printf("could not write to root connection: %s", err)
		}
		return
	}
	if r.Body != nil {
		defer logCloseErr(r.Body)
	}

	var label string
	switch {
	case r.Form.Get("label") != "":
		label = r.Form.Get("label")
	case r.Form.Get("teamid") != "":
		label = r.Form.Get("teamid")
	case r.Form.Get("group-id") != "":
		label = r.Form.Get("group-id")
	default:
		label = ""
	}

	resp, err := config.ec.Namespaces(label, r.Form.Get("userid"))
	if err != nil {
		config.ec.ErrChan <- fmt.Errorf("rootHandler: couldn't get Namespaces: %v", err)
		return
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	if err := elwinJSON(resp, w); err != nil {
		config.ec.ErrChan <- err
		return
	}
}

type errWriter struct {
	w   io.Writer
	err error
}

func (ew *errWriter) write(buf []byte) {
	if ew.err != nil {
		return
	}
	_, ew.err = ew.w.Write(buf)
}

func (ew *errWriter) writeKey(buf []byte) {
	ew.write(jsonQuote)
	ew.write(buf)
	ew.write(jsonQuote)
	ew.write(jsonKeyEnd)
}

func (ew *errWriter) writeString(buf []byte) {
	ew.write(jsonQuote)
	ew.write(buf)
	ew.write(jsonQuote)
}

var (
	jsonQuote    = []byte{'"'}
	jsonKeyEnd   = []byte{':', ' '}
	jsonComma    = []byte{',', ' '}
	jsonOpenObj  = []byte{'{'}
	jsonCloseObj = []byte{'}'}
)

func elwinJSON(er []choices.ExperimentResponse, w io.Writer) error {
	ew := &errWriter{w: w}
	ew.write(jsonOpenObj)
	ew.writeKey([]byte("experiments"))
	ew.write(jsonOpenObj)
	for i, exp := range er {
		ew.writeKey([]byte(exp.Name))
		ew.write(jsonOpenObj)
		ew.writeKey([]byte("namespace"))
		ew.writeString([]byte(exp.Namespace))
		ew.write(jsonComma)
		ew.writeKey([]byte("params"))
		ew.write(jsonOpenObj)
		for j, param := range exp.Params {
			ew.writeKey([]byte(param.Name))
			ew.writeString([]byte(param.Value))
			if j < len(exp.Params)-1 {
				ew.write(jsonComma)
			}
		}
		ew.write(jsonCloseObj)
		ew.write(jsonCloseObj)
		if i < len(er)-1 {
			ew.write(jsonComma)
		}
	}
	ew.write(jsonCloseObj)
	ew.write(jsonCloseObj)
	ew.write([]byte{'\n'})
	if ew.err != nil {
		return ew.err
	}
	return nil
}

func healthzHandler(w http.ResponseWriter, _ *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Header().Set("Content-Type", "text/plain")
	if _, err := w.Write([]byte("OK")); err != nil {
		log.Printf("could not write to healthz connection: %s", err)
	}
}

func readinessHandler(w http.ResponseWriter, _ *http.Request) {
	if config.readiness.storage && config.readiness.httpServer && config.readiness.grpcServer && config.readiness.errorHandler {
		w.WriteHeader(http.StatusOK)
		return
	}
	w.WriteHeader(http.StatusServiceUnavailable)
}
<commit_msg>cmd/elwin: immediately fail on error<commit_after>// Copyright 2016 Andrew O'Neill, Nordstrom

// 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 (
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"net/http/pprof"
	"os"
	"os/signal"
	"syscall"
	"time"

	"golang.org/x/net/context"

	"github.com/Nordstrom/choices"
	"github.com/foolusion/elwinprotos/elwin"
	"github.com/prometheus/client_golang/prometheus"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
)

var config = struct {
	ec              *choices.Config
	grpcAddr        string
	jsonAddr        string
	mongoAddr       string
	mongoDB         string
	mongoCollection string
	readTimeout     string
	writeTimeout    string
	idleTimeout     string
	readiness       struct {
		storage      bool
		grpcServer   bool
		errorHandler bool
		httpServer   bool
	}
}{
	jsonAddr:        ":8081",
	grpcAddr:        ":8080",
	mongoAddr:       "elwin-storage:80",
	mongoDB:         "elwin",
	mongoCollection: "test",
	readTimeout:     "5s",
	writeTimeout:    "5s",
	idleTimeout:     "30s",
}

var (
	jsonRequests = prometheus.NewCounter(prometheus.CounterOpts{
		Namespace: "nordstrom",
		Subsystem: "elwin",
		Name:      "json_requests",
		Help:      "The number of json requests recieved.",
	})
	jsonDurations = prometheus.NewHistogram(prometheus.HistogramOpts{
		Namespace: "nordstrom",
		Subsystem: "elwin",
		Name:      "json_durations_nanoseconds",
		Help:      "json latency distributions.",
		Buckets:   prometheus.ExponentialBuckets(1, 10, 10),
	})
	updateErrors = prometheus.NewCounter(prometheus.CounterOpts{
		Namespace: "nordstrom",
		Subsystem: "elwin",
		Name:      "update_errors",
		Help:      "The number of errors while updating storage.",
	})
)

const (
	envJSONAddr     = "JSON_ADDRESS"
	envGRPCAddr     = "GRPC_ADDRESS"
	envMongoAddr    = "MONGO_ADDRESS"
	envMongoDB      = "MONGO_DATABASE"
	envMongoColl    = "MONGO_COLLECTION"
	envReadTimeout  = "READ_TIMEOUT"
	envWriteTimeout = "WRITE_TIMEOUT"
	envIdleTimeout  = "IDLE_TIMEOUT"
	envProfiler     = "PROFILER"
)

func env(dst *string, src string) {
	if os.Getenv(src) != "" {
		*dst = os.Getenv(src)
		log.Printf("Set %s to %s", src, *dst)
	}
}

func main() {
	log.Println("Starting elwin...")

	env(&config.jsonAddr, envJSONAddr)
	env(&config.grpcAddr, envGRPCAddr)
	env(&config.mongoAddr, envMongoAddr)
	env(&config.mongoDB, envMongoDB)
	env(&config.mongoCollection, envMongoColl)
	env(&config.readTimeout, envReadTimeout)
	env(&config.writeTimeout, envWriteTimeout)
	env(&config.idleTimeout, envIdleTimeout)

	var storageEnv int
	switch config.mongoCollection {
	case "staging", "dev", "test":
		storageEnv = choices.StorageEnvironmentDev
	case "production", "prod":
		storageEnv = choices.StorageEnvironmentProd
	default:
		log.Fatal("bad storage environment")
	}
	log.Println(config.mongoCollection, storageEnv)

	// create elwin config
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	ec, err := choices.NewChoices(
		ctx,
		choices.WithGlobalSalt("choices"),
		choices.WithStorageConfig(config.mongoAddr, storageEnv),
		choices.WithUpdateInterval(10*time.Second),
	)
	if err != nil {
		log.Fatal(err)
	}
	config.ec = ec
	config.readiness.storage = true

	// register prometheus metrics
	prometheus.MustRegister(jsonRequests)
	prometheus.MustRegister(jsonDurations)
	prometheus.MustRegister(updateErrors)

	ljson, err := net.Listen("tcp", config.jsonAddr)
	if err != nil {
		log.Fatalf("could not listen on %s: %v", config.jsonAddr, err)
	}
	defer ljson.Close()

	mux := http.NewServeMux()
	mux.HandleFunc("/", rootHandler)
	mux.HandleFunc("/healthz", healthzHandler)
	mux.HandleFunc("/readiness", readinessHandler)
	mux.Handle("/metrics", prometheus.Handler())
	if len(os.Getenv(envProfiler)) > 0 {
		mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
	}
	srv := http.Server{
		Handler: mux,
	}
	if rt, err := time.ParseDuration(config.readTimeout); err != nil {
		log.Fatal(err)
	} else if wt, err := time.ParseDuration(config.writeTimeout); err != nil {
		log.Fatal(err)
	} else if it, err := time.ParseDuration(config.idleTimeout); err != nil {
		log.Fatal(err)
	} else {
		srv.ReadTimeout = rt
		srv.WriteTimeout = wt
		srv.IdleTimeout = it
	}

	go func() {
		config.readiness.httpServer = true
		config.ec.ErrChan <- srv.Serve(ljson)
	}()

	go func() {
		lgrpc, err := net.Listen("tcp", config.grpcAddr)
		if err != nil {
			config.ec.ErrChan <- fmt.Errorf("main: failed to listen: %v", err)
		}
		defer lgrpc.Close()

		grpcServer := grpc.NewServer()
		elwin.RegisterElwinServer(grpcServer, &elwinServer{})
		config.readiness.grpcServer = true
		config.ec.ErrChan <- grpcServer.Serve(lgrpc)
	}()

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)

	config.readiness.errorHandler = true
	for {
		select {
		case err := <-config.ec.ErrChan:
			log.Fatal(err)
		case s := <-signalChan:
			cancel()
			log.Printf("Captured %v. Exitting...", s)
			// send StatusServiceUnavailable to new requestors
			// block server from accepting new requests
			os.Exit(0)
		}
	}
}

type elwinServer struct{}

func (e *elwinServer) GetNamespaces(ctx context.Context, id *elwin.Identifier) (*elwin.Experiments, error) {
	log.Printf("GetNamespaces: %v", id)
	if id == nil {
		return nil, grpc.Errorf(codes.InvalidArgument, "GetNamespaces: no Identifier recieved")
	}

	resp, err := config.ec.Namespaces(id.TeamID, id.UserID)
	if err != nil {
		return nil, fmt.Errorf("error resolving namespaces for %s, %s: %v", id.TeamID, id.UserID, err)
	}

	exp := &elwin.Experiments{
		Experiments: make(map[string]*elwin.Experiment, len(resp)),
	}

	for _, v := range resp {
		exp.Experiments[v.Name] = &elwin.Experiment{
			Namespace: v.Namespace,
			Params:    make([]*elwin.Param, len(v.Params)),
		}

		for i, p := range v.Params {
			exp.Experiments[v.Name].Params[i] = &elwin.Param{
				Name:  p.Name,
				Value: p.Value,
			}
		}
	}
	return exp, nil
}

func logCloseErr(c io.Closer) {
	if err := c.Close(); err != nil {
		log.Printf("could not close response body: %s", err)
	}
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	start := time.Now()
	defer jsonRequests.Inc()
	defer func() {
		jsonDurations.Observe(float64(time.Since(start)))
	}()
	if err := r.ParseForm(); err != nil {
		log.Printf("could not parse form: %s", err)
		w.WriteHeader(http.StatusBadRequest)
		w.Header().Set("Content-type", "text/plain")
		if _, err := w.Write([]byte("invalid form data")); err != nil {
			log.Printf("could not write to root connection: %s", err)
		}
		return
	}
	if r.Body != nil {
		defer logCloseErr(r.Body)
	}

	var label string
	switch {
	case r.Form.Get("label") != "":
		label = r.Form.Get("label")
	case r.Form.Get("teamid") != "":
		label = r.Form.Get("teamid")
	case r.Form.Get("group-id") != "":
		label = r.Form.Get("group-id")
	default:
		label = ""
	}

	resp, err := config.ec.Namespaces(label, r.Form.Get("userid"))
	if err != nil {
		config.ec.ErrChan <- fmt.Errorf("rootHandler: couldn't get Namespaces: %v", err)
		return
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	if err := elwinJSON(resp, w); err != nil {
		config.ec.ErrChan <- err
		return
	}
}

type errWriter struct {
	w   io.Writer
	err error
}

func (ew *errWriter) write(buf []byte) {
	if ew.err != nil {
		return
	}
	_, ew.err = ew.w.Write(buf)
}

func (ew *errWriter) writeKey(buf []byte) {
	ew.write(jsonQuote)
	ew.write(buf)
	ew.write(jsonQuote)
	ew.write(jsonKeyEnd)
}

func (ew *errWriter) writeString(buf []byte) {
	ew.write(jsonQuote)
	ew.write(buf)
	ew.write(jsonQuote)
}

var (
	jsonQuote    = []byte{'"'}
	jsonKeyEnd   = []byte{':', ' '}
	jsonComma    = []byte{',', ' '}
	jsonOpenObj  = []byte{'{'}
	jsonCloseObj = []byte{'}'}
)

func elwinJSON(er []choices.ExperimentResponse, w io.Writer) error {
	ew := &errWriter{w: w}
	ew.write(jsonOpenObj)
	ew.writeKey([]byte("experiments"))
	ew.write(jsonOpenObj)
	for i, exp := range er {
		ew.writeKey([]byte(exp.Name))
		ew.write(jsonOpenObj)
		ew.writeKey([]byte("namespace"))
		ew.writeString([]byte(exp.Namespace))
		ew.write(jsonComma)
		ew.writeKey([]byte("params"))
		ew.write(jsonOpenObj)
		for j, param := range exp.Params {
			ew.writeKey([]byte(param.Name))
			ew.writeString([]byte(param.Value))
			if j < len(exp.Params)-1 {
				ew.write(jsonComma)
			}
		}
		ew.write(jsonCloseObj)
		ew.write(jsonCloseObj)
		if i < len(er)-1 {
			ew.write(jsonComma)
		}
	}
	ew.write(jsonCloseObj)
	ew.write(jsonCloseObj)
	ew.write([]byte{'\n'})
	if ew.err != nil {
		return ew.err
	}
	return nil
}

func healthzHandler(w http.ResponseWriter, _ *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Header().Set("Content-Type", "text/plain")
	if _, err := w.Write([]byte("OK")); err != nil {
		log.Printf("could not write to healthz connection: %s", err)
	}
}

func readinessHandler(w http.ResponseWriter, _ *http.Request) {
	if config.readiness.storage && config.readiness.httpServer && config.readiness.grpcServer && config.readiness.errorHandler {
		w.WriteHeader(http.StatusOK)
		return
	}
	w.WriteHeader(http.StatusServiceUnavailable)
}
<|endoftext|>


<commit_before>package main

import (
	"gnd.la/admin"
	"gnd.la/app"
	"gnd.la/log"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
)

func RmGen(ctx *app.Context) {
	var dir string
	ctx.ParseIndexValue(0, &dir)
	if dir == "" {
		dir = "."
	}
	re := regexp.MustCompile("(?i).+\\.gen\\..+")
	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if info != nil && !info.IsDir() && re.MatchString(path) {
			log.Infof("Removing %s", path)
			if err := os.Remove(path); err != nil {
				panic(err)
			}
			dir := filepath.Dir(path)
			if infos, err := ioutil.ReadDir(dir); err == nil && len(infos) == 0 {
				log.Infof("Removing empty dir %s", dir)
				if err := os.Remove(dir); err != nil {
					panic(err)
				}
			}
		}
		return nil
	})
	if err != nil {
		panic(err)
	}
}

func init() {
	admin.Register(RmGen, &admin.Options{
		Help: "Remove Gondola generated files (identifier by *.gen.*)",
	})
}
<commit_msg>Fix typo in help message<commit_after>package main

import (
	"gnd.la/admin"
	"gnd.la/app"
	"gnd.la/log"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
)

func RmGen(ctx *app.Context) {
	var dir string
	ctx.ParseIndexValue(0, &dir)
	if dir == "" {
		dir = "."
	}
	re := regexp.MustCompile("(?i).+\\.gen\\..+")
	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if info != nil && !info.IsDir() && re.MatchString(path) {
			log.Infof("Removing %s", path)
			if err := os.Remove(path); err != nil {
				panic(err)
			}
			dir := filepath.Dir(path)
			if infos, err := ioutil.ReadDir(dir); err == nil && len(infos) == 0 {
				log.Infof("Removing empty dir %s", dir)
				if err := os.Remove(dir); err != nil {
					panic(err)
				}
			}
		}
		return nil
	})
	if err != nil {
		panic(err)
	}
}

func init() {
	admin.Register(RmGen, &admin.Options{
		Help: "Remove Gondola generated files (identified by *.gen.*)",
	})
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"io"
	"os"
	"regexp"

	"github.com/Maki-Daisuke/go-kaito"
	"github.com/jessevdk/go-flags"
)

var opts struct {
	DisableGzip  bool `short:"G" long:"disable-gzip" description:"Disable Gzip decompression and pass through raw input."`
	DisableBzip2 bool `short:"B" long:"disable-bzip2" description:"Disable Bzip2 decompression and pass through raw input."`
	DisableXz    bool `short:"X" long:"disable-xz" description:"Disable Xz decompression and pass through raw input."`
	ForceNative  bool `short:"n" long:"force-native" description:"Force to use Go-native implentation of decompression algorithm (this makes xz decompression fail)."`
	ToStdout     bool `short:"c" long:"stdout" description:"Write the decompressed data to standard output instead of a file. This implies --keep."`
	Keep         bool `short:"k" long:"keep" description:"Don't delete the input files."`
	Decode       bool `short:"d" long:"decompress" description:"Nop. Just for tar command."`
}

func main() {
	args, err := flags.Parse(&opts)
	if err != nil {
		if flags.WroteHelp(err) {
			os.Exit(0)
		}
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	if opts.ToStdout {
		opts.Keep = true
	}

	var kaitoOpts kaito.Options
	if opts.DisableGzip {
		kaitoOpts |= kaito.DisableGzip
	}
	if opts.DisableBzip2 {
		kaitoOpts |= kaito.DisableBzip2
	}
	if opts.DisableXz {
		kaitoOpts |= kaito.DisableXz
	}
	if opts.ForceNative {
		kaitoOpts |= kaito.ForceNative
	}

	if len(args) == 0 { // Filter mode
		args = append(args, "-")
	}

	for _, file := range args {
		if file == "-" {
			k := kaito.NewWithOptions(os.Stdin, kaitoOpts)
			_, err := io.Copy(os.Stdout, k)
			if err != nil {
				fmt.Fprintf(os.Stderr, "kaito: %s\n", err)
			}
		} else {
			var err error
			rd, err := os.Open(file)
			if err != nil {
				fmt.Fprintf(os.Stderr, "kaito: %s\n", err)
				continue
			}
			out := os.Stdout
			if !opts.ToStdout {
				outFile, err := outputFilename(file)
				if err != nil {
					fmt.Fprintf(os.Stderr, "kaito: %s: Filename has an unknown suffix, skipping\n", file)
					continue
				}
				if _, err := os.Open(outFile); err == nil {
					fmt.Fprintf(os.Stderr, "kaito: %s already exists, skipping\n", outFile)
					continue
				}
				out, err = os.Create(outFile)
				if err != nil {
					fmt.Fprintf(os.Stderr, "kaito: %s :%s\n", outFile, err)
					continue
				}
			}
			k := kaito.NewWithOptions(rd, kaitoOpts)
			_, err = io.Copy(out, k)
			if err != nil {
				fmt.Fprintf(os.Stderr, "kaito: %s: %s\n", file, err)
			}
			if !opts.Keep {
				err := os.Remove(file)
				if err != nil {
					fmt.Fprintf(os.Stderr, "kaito: %s: %s\n", file, err)
				}
			}
		}
	}
}

var reExt *regexp.Regexp = regexp.MustCompile(`(?i)\.(?:gz|bz2|xz)$`)

func outputFilename(s string) (string, error) {
	t := reExt.FindString(s)
	if t == "" {
		return "", errors.New("unknown suffix")
	}
	return s[0 : len(s)-len(t)], nil
}
<commit_msg>Update help message<commit_after>package main

import (
	"errors"
	"fmt"
	"io"
	"os"
	"regexp"

	"github.com/Maki-Daisuke/go-kaito"
	"github.com/jessevdk/go-flags"
)

var opts struct {
	DisableGzip  bool `short:"G" long:"disable-gzip" description:"Disable Gzip decompression and pass through raw input."`
	DisableBzip2 bool `short:"B" long:"disable-bzip2" description:"Disable Bzip2 decompression and pass through raw input."`
	DisableXz    bool `short:"X" long:"disable-xz" description:"Disable Xz decompression and pass through raw input."`
	ForceNative  bool `short:"n" long:"force-native" description:"Force to use Go-native implentation of decompression algorithm."`
	ToStdout     bool `short:"c" long:"stdout" description:"Write the decompressed data to standard output instead of a file. This implies --keep."`
	Keep         bool `short:"k" long:"keep" description:"Don't delete the input files."`
	Decode       bool `short:"d" long:"decompress" description:"Nop. Just for tar command."`
}

func main() {
	args, err := flags.Parse(&opts)
	if err != nil {
		if flags.WroteHelp(err) {
			os.Exit(0)
		}
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	if opts.ToStdout {
		opts.Keep = true
	}

	var kaitoOpts kaito.Options
	if opts.DisableGzip {
		kaitoOpts |= kaito.DisableGzip
	}
	if opts.DisableBzip2 {
		kaitoOpts |= kaito.DisableBzip2
	}
	if opts.DisableXz {
		kaitoOpts |= kaito.DisableXz
	}
	if opts.ForceNative {
		kaitoOpts |= kaito.ForceNative
	}

	if len(args) == 0 { // Filter mode
		args = append(args, "-")
	}

	for _, file := range args {
		if file == "-" {
			k := kaito.NewWithOptions(os.Stdin, kaitoOpts)
			_, err := io.Copy(os.Stdout, k)
			if err != nil {
				fmt.Fprintf(os.Stderr, "kaito: %s\n", err)
			}
		} else {
			var err error
			rd, err := os.Open(file)
			if err != nil {
				fmt.Fprintf(os.Stderr, "kaito: %s\n", err)
				continue
			}
			out := os.Stdout
			if !opts.ToStdout {
				outFile, err := outputFilename(file)
				if err != nil {
					fmt.Fprintf(os.Stderr, "kaito: %s: Filename has an unknown suffix, skipping\n", file)
					continue
				}
				if _, err := os.Open(outFile); err == nil {
					fmt.Fprintf(os.Stderr, "kaito: %s already exists, skipping\n", outFile)
					continue
				}
				out, err = os.Create(outFile)
				if err != nil {
					fmt.Fprintf(os.Stderr, "kaito: %s :%s\n", outFile, err)
					continue
				}
			}
			k := kaito.NewWithOptions(rd, kaitoOpts)
			_, err = io.Copy(out, k)
			if err != nil {
				fmt.Fprintf(os.Stderr, "kaito: %s: %s\n", file, err)
			}
			if !opts.Keep {
				err := os.Remove(file)
				if err != nil {
					fmt.Fprintf(os.Stderr, "kaito: %s: %s\n", file, err)
				}
			}
		}
	}
}

var reExt *regexp.Regexp = regexp.MustCompile(`(?i)\.(?:gz|bz2|xz)$`)

func outputFilename(s string) (string, error) {
	t := reExt.FindString(s)
	if t == "" {
		return "", errors.New("unknown suffix")
	}
	return s[0 : len(s)-len(t)], nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"os"
	"strings"
	"time"

	"github.com/serge-v/toolbox/acomplete"
)

func installChat(name string) {
	ip, _ := listDroplets(name)

	ssh(ip, "mkdir -p /home/freebsd/.config/departures")

	scp(ip, os.Getenv("HOME")+"/go/src/github.com/milla-v/chat/chat.tar.gz")
	ssh(ip, "sudo tar -C / -xzf chat.tar.gz")

	scp(ip, os.Getenv("HOME")+"/go/src/github.com/milla-v/chat/chatd-prod~.json")
	ssh(ip, "sudo mv chatd-prod~.json /usr/local/etc/chatd.json")
	scp(ip, os.Getenv("HOME")+"/.config/departures/smtp.txt")
	ssh(ip, "mv smtp.txt /home/freebsd/.config/departures/smtp.txt")

	ssh(ip, "sudo /usr/local/lib/chat.tar.gz-configure.sh")

	time.Sleep(time.Second * 3)
	ssh(ip, "tail -20 /var/log/chatd.log")
}

func installLetsencryptCert(name string) {
	ip, _ := listDroplets(name)
	ssh(ip, "sudo pkg install py27-certbot")
	ssh(ip, "sudo certbot certonly --standalone -d wet.voilokov.com -d voilokov.com")
	ssh(ip, "sudo cp /usr/local/etc/letsencrypt/live/wet.voilokov.com/privkey.pem /usr/local/www/wet/work/server.key")
	ssh(ip, "sudo cp /usr/local/etc/letsencrypt/live/wet.voilokov.com/fullchain.pem /usr/local/www/wet/work/server.pem")
	ssh(ip, "sudo cp /usr/local/etc/letsencrypt/live/wet.voilokov.com/privkey.pem /usr/local/www/homepage/work/server.key")
	ssh(ip, "sudo cp /usr/local/etc/letsencrypt/live/wet.voilokov.com/fullchain.pem /usr/local/www/homepage/work/server.pem")
}

func installWeather(name string) {
	ip, _ := listDroplets(name)

	ssh(ip, "sudo pkg install --yes git go")
	ssh(ip, "rm -rf ~/go/src/github.com/serge-v/toolbox")
	ssh(ip, "go get github.com/serge-v/toolbox/cmd/tb/...")

	scp(ip, os.Getenv("HOME")+"/go/src/github.com/serge-v/toolbox/cmd/tb/tbweather-freebsd.json")
	ssh(ip, "sudo cp tbweather-freebsd.json /usr/local/etc/tbweather.json")
	ssh(ip, "sudo chmod a+r /usr/local/etc/tbweather.json")
	ssh(ip, "mkdir -p .cache/weather; mkdir -p .config/departures")
	scp(ip, os.Getenv("HOME")+"/.config/departures/smtp.txt")
	ssh(ip, "mv smtp.txt /home/freebsd/.config/departures/smtp.txt")
	ssh(ip, "touch .bashrc")

	scp(ip, os.Getenv("HOME")+"/go/src/github.com/serge-v/toolbox/cmd/tb/weather-crontab.txt")
	ssh(ip, "cat *-crontab.txt > crontabs.txt; crontab crontabs.txt; crontab -l")

	ssh(ip, "go/bin/tb -weather 10974")
}

func installDepartures(name string) {
	ip, _ := listDroplets(name)
	ssh(ip, "sudo pkg install --yes git cmake libxml2")
	ssh(ip, "rm -rf w/common; mkdir w; cd w; git clone https://github.com/serge-v/common")
	ssh(ip, "rm -rf w/departures; mkdir w; cd w; git clone https://github.com/serge-v/departures")
	ssh(ip, "cd w/departures; mkdir build; cd build; cmake ..; make; sudo make install")

	scp(ip, os.Getenv("HOME")+"/.config/departures/smtp.txt")
	ssh(ip, "mkdir -p ~/.config/departures; mv smtp.txt ~/.config/departures/smtp.txt")

	ssh(ip, "echo '14 10 * * * /usr/local/bin/departures -f XG -t HB -m' > departures-crontab.txt")
	ssh(ip, "cat *-crontab.txt > crontabs.txt; crontab crontabs.txt; crontab -l")
	ssh(ip, "/usr/local/bin/departures -f XG -t HB -m")
}

func installHomepage(name string) {
	ip, _ := listDroplets(name)
	ssh(ip, "sudo pkg install --yes git go")
	ssh(ip, "sudo service homepaged stop")
	ssh(ip, "rm -rf ~/go/src/github.com/serge-v/homepage")
	ssh(ip, "go get github.com/serge-v/homepage/...")
	ssh(ip, "sudo cp -R go/src/github.com/serge-v/homepage/dist/usr/ /usr/")
	ssh(ip, "sudo cp go/bin/homepage /usr/local/www/homepage/homepaged")
	ssh(ip, "sudo /usr/local/lib/homepage-configure.sh")
	time.Sleep(time.Second * 3)
	ssh(ip, "tail -20 /var/log/homepaged.log")
}

func installCooking(name string) {
	ip, _ := listDroplets(name)
	ssh(ip, "sudo pkg install --yes git go")
	ssh(ip, "rm -rf cooking")
	ssh(ip, "git clone https://github.com/serge-v/cooking")
	ssh(ip, "cd cooking; make; go build server.go; mkdir -p build/bakery/pies; ./generator")
	ssh(ip, "sudo mkdir -p /usr/local/www/recbook; sudo cp -R cooking/build /usr/local/www/recbook/")
	ssh(ip, "sudo cp cooking/server /usr/local/www/recbook/server")
	ssh(ip, "sudo cp -R cooking/images /usr/local/www/recbook/build")
	ssh(ip, "go get github.com/serge-v/recbook/...")
	ssh(ip, "sudo cp go/bin/server /usr/local/www/recbook/server")
}

func installGiftsDB(name string) {
	ip, _ := listDroplets(name)
	ssh(ip, "sudo pkg install --yes mariadb101-server")
	//	scp(ip, os.Getenv("HOME")+"/gifts/bin/db_data.sql")
	//	ssh(ip, "sudo service mysql-server start")
	// ssh(ip, "mysql -u root -e 'create database gifts'")
	//	ssh(ip, "mysql -u root -D gifts < db_data.sql")
	ssh(ip, `mysql -u root -e "create user 'editor'@'localhost' identified by 'password'"`)
	ssh(ip, `mysql -u root -e "grant all privileges on gifts.* to 'editor'@'localhost'"`)
}

func installGifts(name string) {
	ip, _ := listDroplets(name)
	ssh(ip, "sudo pkg install --yes php56 php56-openssl php56-json php56-session php56-mysqli")
	ssh(ip, "rm -rf gifts")
	ssh(ip, "git clone https://github.com/serge-v/gifts; cd gifts; git submodule update --init")
	ssh(ip, "sudo mkdir -p /usr/local/www/gifts; sudo cp -R gifts/src/ /usr/local/www/gifts; sudo cp -R gifts/lib /usr/local/www/")
	//	scp(ip, os.Getenv("HOME")+"/config_dev.php")
	//	scp(ip, os.Getenv("HOME")+"/gifts/bin/pics.tgz")
	//	scp(ip, os.Getenv("HOME")+"/gifts/bin/photos.tgz")
	//	ssh(ip, "sudo cp config_dev.php /usr/local/www/gifts/")
	//	ssh(ip, "sudo tar -C /usr/local/www/gifts/ -vxzf pics.tgz")
	//	ssh(ip, "sudo tar -C /usr/local/www/gifts/ -vxzf photos.tgz")
}

func switchServerIP(rule string) {
	p := strings.Split(rule, ":")
	if len(p) != 2 {
		panic("invalid switch parameter")
	}
	switchFloatingIP(p[0], p[1])
}

var (
	autocomplete   = flag.Bool("c", false, "for bash autocomplete")
	showInfo       = flag.Bool("info", false, "show ocean info")
	serverToDelete = flag.String("server-delete", "", "delete server by `name`")
	serverToCreate = flag.String("server-create", "", "create server with `name`")
	serverSwitchIP = flag.String("server-switch-ip", "", "switch ip `from_server:to_server`")
	chatServer     = flag.String("deploy-chat", "", "deploy chat service to `name`")
	certServer     = flag.String("deploy-cert", "", "deploy certificate to `name`")
	weatherServer  = flag.String("deploy-weather", "", "deploy weather bot to `name`")
	departsServer  = flag.String("deploy-departs", "", "deploy departures bot to `name`")
	homepageServer = flag.String("deploy-homepage", "", "deploy homepage to `name`")
	cookingServer  = flag.String("deploy-cooking", "", "deploy cooking website to `name`")
	giftsServer    = flag.String("deploy-gifts", "", "deploy gifts website to `name`")
)

func main() {
	acomplete.Init("ocean", true, []string{})
	flag.Parse()
	if *autocomplete {
		acomplete.Complete()
		return
	}
	createOceanClient()

	if *showInfo {
		showAccountInfo()
		listImages("")
		listFloatingIPs()
		listDroplets("")
		return
	}

	if *serverToCreate != "" {
		createVirtualServer(*serverToCreate, "f6:08:5d:5a:75:0a:9d:f0:23:dc:63:a0:03:71:a7:98")
	}

	if *chatServer != "" {
		installChat(*chatServer)
	}

	if *certServer != "" {
		installLetsencryptCert(*certServer)
	}

	if *weatherServer != "" {
		installWeather(*weatherServer)
	}

	if *departsServer != "" {
		installDepartures(*departsServer)
	}

	if *homepageServer != "" {
		installHomepage(*homepageServer)
	}

	if *cookingServer != "" {
		installCooking(*cookingServer)
	}

	if *giftsServer != "" {
		// installGiftsDB(*giftsServer)
		installGifts(*giftsServer)
	}

	if *serverSwitchIP != "" {
		switchServerIP(*serverSwitchIP)
	}

	if *serverToDelete != "" {
		deleteVirtualServer(*serverToDelete)
	}
}
<commit_msg>Edit flag descriptions<commit_after>package main

import (
	"flag"
	"os"
	"strings"
	"time"

	"github.com/serge-v/toolbox/acomplete"
)

func installChat(name string) {
	ip, _ := listDroplets(name)

	ssh(ip, "mkdir -p /home/freebsd/.config/departures")

	scp(ip, os.Getenv("HOME")+"/go/src/github.com/milla-v/chat/chat.tar.gz")
	ssh(ip, "sudo tar -C / -xzf chat.tar.gz")

	scp(ip, os.Getenv("HOME")+"/go/src/github.com/milla-v/chat/chatd-prod~.json")
	ssh(ip, "sudo mv chatd-prod~.json /usr/local/etc/chatd.json")
	scp(ip, os.Getenv("HOME")+"/.config/departures/smtp.txt")
	ssh(ip, "mv smtp.txt /home/freebsd/.config/departures/smtp.txt")

	ssh(ip, "sudo /usr/local/lib/chat.tar.gz-configure.sh")

	time.Sleep(time.Second * 3)
	ssh(ip, "tail -20 /var/log/chatd.log")
}

func installLetsencryptCert(name string) {
	ip, _ := listDroplets(name)
	ssh(ip, "sudo pkg install py27-certbot")
	ssh(ip, "sudo certbot certonly --standalone -d wet.voilokov.com -d voilokov.com")
	ssh(ip, "sudo cp /usr/local/etc/letsencrypt/live/wet.voilokov.com/privkey.pem /usr/local/www/wet/work/server.key")
	ssh(ip, "sudo cp /usr/local/etc/letsencrypt/live/wet.voilokov.com/fullchain.pem /usr/local/www/wet/work/server.pem")
	ssh(ip, "sudo cp /usr/local/etc/letsencrypt/live/wet.voilokov.com/privkey.pem /usr/local/www/homepage/work/server.key")
	ssh(ip, "sudo cp /usr/local/etc/letsencrypt/live/wet.voilokov.com/fullchain.pem /usr/local/www/homepage/work/server.pem")
}

func installWeather(name string) {
	ip, _ := listDroplets(name)

	ssh(ip, "sudo pkg install --yes git go")
	ssh(ip, "rm -rf ~/go/src/github.com/serge-v/toolbox")
	ssh(ip, "go get github.com/serge-v/toolbox/cmd/tb/...")

	scp(ip, os.Getenv("HOME")+"/go/src/github.com/serge-v/toolbox/cmd/tb/tbweather-freebsd.json")
	ssh(ip, "sudo cp tbweather-freebsd.json /usr/local/etc/tbweather.json")
	ssh(ip, "sudo chmod a+r /usr/local/etc/tbweather.json")
	ssh(ip, "mkdir -p .cache/weather; mkdir -p .config/departures")
	scp(ip, os.Getenv("HOME")+"/.config/departures/smtp.txt")
	ssh(ip, "mv smtp.txt /home/freebsd/.config/departures/smtp.txt")
	ssh(ip, "touch .bashrc")

	scp(ip, os.Getenv("HOME")+"/go/src/github.com/serge-v/toolbox/cmd/tb/weather-crontab.txt")
	ssh(ip, "cat *-crontab.txt > crontabs.txt; crontab crontabs.txt; crontab -l")

	ssh(ip, "go/bin/tb -weather 10974")
}

func installDepartures(name string) {
	ip, _ := listDroplets(name)
	ssh(ip, "sudo pkg install --yes git cmake libxml2")
	ssh(ip, "rm -rf w/common; mkdir w; cd w; git clone https://github.com/serge-v/common")
	ssh(ip, "rm -rf w/departures; mkdir w; cd w; git clone https://github.com/serge-v/departures")
	ssh(ip, "cd w/departures; mkdir build; cd build; cmake ..; make; sudo make install")

	scp(ip, os.Getenv("HOME")+"/.config/departures/smtp.txt")
	ssh(ip, "mkdir -p ~/.config/departures; mv smtp.txt ~/.config/departures/smtp.txt")

	ssh(ip, "echo '14 10 * * * /usr/local/bin/departures -f XG -t HB -m' > departures-crontab.txt")
	ssh(ip, "cat *-crontab.txt > crontabs.txt; crontab crontabs.txt; crontab -l")
	ssh(ip, "/usr/local/bin/departures -f XG -t HB -m")
}

func installHomepage(name string) {
	ip, _ := listDroplets(name)
	ssh(ip, "sudo pkg install --yes git go")
	ssh(ip, "sudo service homepaged stop")
	ssh(ip, "rm -rf ~/go/src/github.com/serge-v/homepage")
	ssh(ip, "go get github.com/serge-v/homepage/...")
	ssh(ip, "sudo cp -R go/src/github.com/serge-v/homepage/dist/usr/ /usr/")
	ssh(ip, "sudo cp go/bin/homepage /usr/local/www/homepage/homepaged")
	ssh(ip, "sudo /usr/local/lib/homepage-configure.sh")
	time.Sleep(time.Second * 3)
	ssh(ip, "tail -20 /var/log/homepaged.log")
}

func installCooking(name string) {
	ip, _ := listDroplets(name)
	ssh(ip, "sudo pkg install --yes git go")
	ssh(ip, "rm -rf cooking")
	ssh(ip, "git clone https://github.com/serge-v/cooking")
	ssh(ip, "cd cooking; make; go build server.go; mkdir -p build/bakery/pies; ./generator")
	ssh(ip, "sudo mkdir -p /usr/local/www/recbook; sudo cp -R cooking/build /usr/local/www/recbook/")
	ssh(ip, "sudo cp cooking/server /usr/local/www/recbook/server")
	ssh(ip, "sudo cp -R cooking/images /usr/local/www/recbook/build")
	ssh(ip, "go get github.com/serge-v/recbook/...")
	ssh(ip, "sudo cp go/bin/server /usr/local/www/recbook/server")
}

func installGiftsDB(name string) {
	ip, _ := listDroplets(name)
	ssh(ip, "sudo pkg install --yes mariadb101-server")
	//	scp(ip, os.Getenv("HOME")+"/gifts/bin/db_data.sql")
	//	ssh(ip, "sudo service mysql-server start")
	// ssh(ip, "mysql -u root -e 'create database gifts'")
	//	ssh(ip, "mysql -u root -D gifts < db_data.sql")
	ssh(ip, `mysql -u root -e "create user 'editor'@'localhost' identified by 'password'"`)
	ssh(ip, `mysql -u root -e "grant all privileges on gifts.* to 'editor'@'localhost'"`)
}

func installGifts(name string) {
	ip, _ := listDroplets(name)
	ssh(ip, "sudo pkg install --yes php56 php56-openssl php56-json php56-session php56-mysqli")
	ssh(ip, "rm -rf gifts")
	ssh(ip, "git clone https://github.com/serge-v/gifts; cd gifts; git submodule update --init")
	ssh(ip, "sudo mkdir -p /usr/local/www/gifts; sudo cp -R gifts/src/ /usr/local/www/gifts; sudo cp -R gifts/lib /usr/local/www/")
	//	scp(ip, os.Getenv("HOME")+"/config_dev.php")
	//	scp(ip, os.Getenv("HOME")+"/gifts/bin/pics.tgz")
	//	scp(ip, os.Getenv("HOME")+"/gifts/bin/photos.tgz")
	//	ssh(ip, "sudo cp config_dev.php /usr/local/www/gifts/")
	//	ssh(ip, "sudo tar -C /usr/local/www/gifts/ -vxzf pics.tgz")
	//	ssh(ip, "sudo tar -C /usr/local/www/gifts/ -vxzf photos.tgz")
}

func switchServerIP(rule string) {
	p := strings.Split(rule, ":")
	if len(p) != 2 {
		panic("invalid switch parameter")
	}
	switchFloatingIP(p[0], p[1])
}

var (
	autocomplete   = flag.Bool("c", false, "for bash autocomplete")
	showInfo       = flag.Bool("info", false, "show ocean info")
	serverToDelete = flag.String("server-delete", "", "delete server by `SERVER`")
	serverToCreate = flag.String("server-create", "", "create server with `SERVER`")
	serverSwitchIP = flag.String("server-switch-ip", "", "switch ip `from_SERVER:to_SERVER`")
	chatServer     = flag.String("deploy-chat", "", "deploy chat service to `SERVER`")
	certServer     = flag.String("deploy-cert", "", "deploy certificate to `SERVER`")
	weatherServer  = flag.String("deploy-weather", "", "deploy weather bot to `SERVER`")
	departsServer  = flag.String("deploy-departs", "", "deploy departures bot to `SERVER`")
	homepageServer = flag.String("deploy-homepage", "", "deploy homepage to `SERVER`")
	cookingServer  = flag.String("deploy-cooking", "", "deploy cooking website to `SERVER`")
	giftsServer    = flag.String("deploy-gifts", "", "deploy gifts website to `SERVER`")
	slug           = flag.String("slug", "freebsd-11-0-x64-zfs", "image slug for server-create")
)

func main() {
	acomplete.Init("ocean", true, []string{})
	flag.Parse()
	if *autocomplete {
		acomplete.Complete()
		return
	}
	createOceanClient()

	if *showInfo {
		showAccountInfo()
		listImages("")
		listFloatingIPs()
		listDroplets("")
		return
	}

	if *serverToCreate != "" {
		createVirtualServer(*serverToCreate, "f6:08:5d:5a:75:0a:9d:f0:23:dc:63:a0:03:71:a7:98")
	}

	if *chatServer != "" {
		installChat(*chatServer)
	}

	if *certServer != "" {
		installLetsencryptCert(*certServer)
	}

	if *weatherServer != "" {
		installWeather(*weatherServer)
	}

	if *departsServer != "" {
		installDepartures(*departsServer)
	}

	if *homepageServer != "" {
		installHomepage(*homepageServer)
	}

	if *cookingServer != "" {
		installCooking(*cookingServer)
	}

	if *giftsServer != "" {
		// installGiftsDB(*giftsServer)
		installGifts(*giftsServer)
	}

	if *serverSwitchIP != "" {
		switchServerIP(*serverSwitchIP)
	}

	if *serverToDelete != "" {
		deleteVirtualServer(*serverToDelete)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"

	"github.com/ponzu-cms/ponzu/system/admin"
	"github.com/ponzu-cms/ponzu/system/api"
	"github.com/ponzu-cms/ponzu/system/api/analytics"
	"github.com/ponzu-cms/ponzu/system/db"
	"github.com/ponzu-cms/ponzu/system/tls"

	_ "github.com/ponzu-cms/ponzu/content"
)

var (
	usage     = usageHeader + usageNew + usageGenerate + usageBuild + usageRun
	port      int
	httpsport int
	https     bool
	devhttps  bool

	// for ponzu internal / core development
	dev   bool
	fork  string
	gocmd string
)

func main() {
	flag.Usage = func() {
		fmt.Println(usage)
	}

	flag.IntVar(&port, "port", 8080, "port for ponzu to bind its HTTP listener")
	flag.IntVar(&httpsport, "httpsport", 443, "port for ponzu to bind its HTTPS listener")
	flag.BoolVar(&https, "https", false, "enable automatic TLS/SSL certificate management")
	flag.BoolVar(&devhttps, "devhttps", false, "[dev environment] enable automatic TLS/SSL certificate management")
	flag.BoolVar(&dev, "dev", false, "modify environment for Ponzu core development")
	flag.StringVar(&fork, "fork", "", "modify repo source for Ponzu core development")
	flag.StringVar(&gocmd, "gocmd", "go", "custom go command if using beta or new release of Go")
	flag.Parse()

	args := flag.Args()

	if len(args) < 1 {
		fmt.Println(usage)
		os.Exit(0)
	}

	switch args[0] {
	case "help", "h":
		if len(args) < 2 {
			fmt.Println(usageHelp)
			fmt.Println(usage)
			os.Exit(0)
		}

		switch args[1] {
		case "new":
			fmt.Println(usageNew)
			os.Exit(0)

		case "generate", "gen", "g":
			fmt.Println(usageGenerate)
			os.Exit(0)

		case "build":
			fmt.Println(usageBuild)
			os.Exit(0)

		case "run":
			fmt.Println(usageRun)
			os.Exit(0)
		}

	case "new":
		if len(args) < 2 {
			fmt.Println(usageNew)
			os.Exit(0)
		}

		err := newProjectInDir(args[1])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "generate", "gen", "g":
		if len(args) < 3 {
			fmt.Println(usageGenerate)
			os.Exit(0)
		}

		// check what we are asked to generate
		switch args[2] {
		case "content", "c":
			fmt.Println(args, "|", args[2])
			err := generateContentType(args[2:])
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
		}

	case "build":
		err := buildPonzuServer(args)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "run":
		fmt.Println("Running..")
		var addTLS string
		if https {
			addTLS = "--https"
		} else {
			addTLS = "--https=false"
		}

		if devhttps {
			addTLS = "--devhttps"
		}

		var services string
		if len(args) > 1 {
			services = args[1]
		} else {
			services = "admin,api"
		}

		fmt.Println("services:", services)

		serve := exec.Command("./ponzu-server",
			fmt.Sprintf("--port=%d", port),
			fmt.Sprintf("--httpsport=%d", httpsport),
			addTLS,
			"serve",
			services,
		)
		serve.Stderr = os.Stderr
		serve.Stdout = os.Stdout

		err := serve.Start()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		err = serve.Wait()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		fmt.Println("serve command executed.")

	case "serve", "s":
		db.Init()
		defer db.Close()
		fmt.Println("called db.Init()")

		analytics.Init()
		defer analytics.Close()
		fmt.Println("called analytics.Init()")

		if len(args) > 1 {
			services := strings.Split(args[1], ",")
			fmt.Println("configured to start services:", services)

			for i := range services {
				if services[i] == "api" {
					api.Run()
					fmt.Println("called api.Run()")

				} else if services[i] == "admin" {
					admin.Run()
					fmt.Println("called admin.Run()")

				} else {
					fmt.Println("To execute 'ponzu serve', you must specify which service to run.")
					fmt.Println("$ ponzu --help")
					os.Exit(1)
				}
			}
		}

		// save the https port the system is listening on
		err := db.PutConfig("https_port", fmt.Sprintf("%d", httpsport))
		if err != nil {
			log.Fatalln("System failed to save config. Please try to run again.", err)
		}
		fmt.Println("called db.PutConfig('https_port')")

		// cannot run production HTTPS and development HTTPS together
		if devhttps {
			fmt.Println("Enabling self-signed HTTPS... [DEV]")

			go tls.EnableDev()
			fmt.Println("Server listening on https://localhost:10443 for requests... [DEV]")
			fmt.Println("----")
			fmt.Println("If your browser rejects HTTPS requests, try allowing insecure connections on localhost.")
			fmt.Println("on Chrome, visit chrome://flags/#allow-insecure-localhost")

		} else if https {
			fmt.Println("Enabling HTTPS...")

			go tls.Enable()
			fmt.Printf("Server listening on :%s for HTTPS requests...\n", db.ConfigCache("https_port").(string))
		}

		// save the https port the system is listening on so internal system can make
		// HTTP api calls while in dev or production w/o adding more cli flags
		err = db.PutConfig("http_port", fmt.Sprintf("%d", port))
		if err != nil {
			log.Fatalln("System failed to save config. Please try to run again.", err)
		}
		fmt.Println("called db.PutConfig('http_port')")

		log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
		fmt.Println("called http.ListenAndServe()")

	case "":
		fmt.Println(usage)
		fmt.Println(usageHelp)

	default:
		fmt.Println(usage)
		fmt.Println(usageHelp)
	}
}
<commit_msg>removing fmt debug and changing index of args to match generator<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"

	"github.com/ponzu-cms/ponzu/system/admin"
	"github.com/ponzu-cms/ponzu/system/api"
	"github.com/ponzu-cms/ponzu/system/api/analytics"
	"github.com/ponzu-cms/ponzu/system/db"
	"github.com/ponzu-cms/ponzu/system/tls"

	_ "github.com/ponzu-cms/ponzu/content"
)

var (
	usage     = usageHeader + usageNew + usageGenerate + usageBuild + usageRun
	port      int
	httpsport int
	https     bool
	devhttps  bool

	// for ponzu internal / core development
	dev   bool
	fork  string
	gocmd string
)

func main() {
	flag.Usage = func() {
		fmt.Println(usage)
	}

	flag.IntVar(&port, "port", 8080, "port for ponzu to bind its HTTP listener")
	flag.IntVar(&httpsport, "httpsport", 443, "port for ponzu to bind its HTTPS listener")
	flag.BoolVar(&https, "https", false, "enable automatic TLS/SSL certificate management")
	flag.BoolVar(&devhttps, "devhttps", false, "[dev environment] enable automatic TLS/SSL certificate management")
	flag.BoolVar(&dev, "dev", false, "modify environment for Ponzu core development")
	flag.StringVar(&fork, "fork", "", "modify repo source for Ponzu core development")
	flag.StringVar(&gocmd, "gocmd", "go", "custom go command if using beta or new release of Go")
	flag.Parse()

	args := flag.Args()

	if len(args) < 1 {
		fmt.Println(usage)
		os.Exit(0)
	}

	switch args[0] {
	case "help", "h":
		if len(args) < 2 {
			fmt.Println(usageHelp)
			fmt.Println(usage)
			os.Exit(0)
		}

		switch args[1] {
		case "new":
			fmt.Println(usageNew)
			os.Exit(0)

		case "generate", "gen", "g":
			fmt.Println(usageGenerate)
			os.Exit(0)

		case "build":
			fmt.Println(usageBuild)
			os.Exit(0)

		case "run":
			fmt.Println(usageRun)
			os.Exit(0)
		}

	case "new":
		if len(args) < 2 {
			fmt.Println(usageNew)
			os.Exit(0)
		}

		err := newProjectInDir(args[1])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "generate", "gen", "g":
		if len(args) < 3 {
			fmt.Println(usageGenerate)
			os.Exit(0)
		}

		// check what we are asked to generate
		switch args[1] {
		case "content", "c":
			err := generateContentType(args[2:])
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
		default:
			msg := fmt.Sprintf("Generator '%s' is not implemented.", args[1])
			fmt.Println(msg)
		}

	case "build":
		err := buildPonzuServer(args)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "run":
		fmt.Println("Running..")
		var addTLS string
		if https {
			addTLS = "--https"
		} else {
			addTLS = "--https=false"
		}

		if devhttps {
			addTLS = "--devhttps"
		}

		var services string
		if len(args) > 1 {
			services = args[1]
		} else {
			services = "admin,api"
		}

		fmt.Println("services:", services)

		serve := exec.Command("./ponzu-server",
			fmt.Sprintf("--port=%d", port),
			fmt.Sprintf("--httpsport=%d", httpsport),
			addTLS,
			"serve",
			services,
		)
		serve.Stderr = os.Stderr
		serve.Stdout = os.Stdout

		err := serve.Start()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		err = serve.Wait()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		fmt.Println("serve command executed.")

	case "serve", "s":
		db.Init()
		defer db.Close()
		fmt.Println("called db.Init()")

		analytics.Init()
		defer analytics.Close()
		fmt.Println("called analytics.Init()")

		if len(args) > 1 {
			services := strings.Split(args[1], ",")
			fmt.Println("configured to start services:", services)

			for i := range services {
				if services[i] == "api" {
					api.Run()
					fmt.Println("called api.Run()")

				} else if services[i] == "admin" {
					admin.Run()
					fmt.Println("called admin.Run()")

				} else {
					fmt.Println("To execute 'ponzu serve', you must specify which service to run.")
					fmt.Println("$ ponzu --help")
					os.Exit(1)
				}
			}
		}

		// save the https port the system is listening on
		err := db.PutConfig("https_port", fmt.Sprintf("%d", httpsport))
		if err != nil {
			log.Fatalln("System failed to save config. Please try to run again.", err)
		}
		fmt.Println("called db.PutConfig('https_port')")

		// cannot run production HTTPS and development HTTPS together
		if devhttps {
			fmt.Println("Enabling self-signed HTTPS... [DEV]")

			go tls.EnableDev()
			fmt.Println("Server listening on https://localhost:10443 for requests... [DEV]")
			fmt.Println("----")
			fmt.Println("If your browser rejects HTTPS requests, try allowing insecure connections on localhost.")
			fmt.Println("on Chrome, visit chrome://flags/#allow-insecure-localhost")

		} else if https {
			fmt.Println("Enabling HTTPS...")

			go tls.Enable()
			fmt.Printf("Server listening on :%s for HTTPS requests...\n", db.ConfigCache("https_port").(string))
		}

		// save the https port the system is listening on so internal system can make
		// HTTP api calls while in dev or production w/o adding more cli flags
		err = db.PutConfig("http_port", fmt.Sprintf("%d", port))
		if err != nil {
			log.Fatalln("System failed to save config. Please try to run again.", err)
		}
		fmt.Println("called db.PutConfig('http_port')")

		log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
		fmt.Println("called http.ListenAndServe()")

	case "":
		fmt.Println(usage)
		fmt.Println(usageHelp)

	default:
		fmt.Println(usage)
		fmt.Println(usageHelp)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"

	log "github.com/Sirupsen/logrus"
	"github.com/ralreegorganon/rudia"
)

var relayPort = flag.String("port", "32779", "TCP port to relay to")
var upstream = flag.String("upstream", "localhost:32778", "Upstream address to relay from in host:port format")

func init() {
	log.SetLevel(log.DebugLevel)
}

func main() {
	flag.Parse()

	r := rudia.NewRepeater()
	r.Proxy(*upstream)
	r.ListenAndAccept(":" + *relayPort)
}
<commit_msg>Add support for multiple upstreams<commit_after>package main

import (
	"flag"

	log "github.com/Sirupsen/logrus"
	"github.com/ralreegorganon/rudia"
)

var relayPort = flag.String("port", "32779", "TCP port to relay to")

func init() {
	log.SetLevel(log.DebugLevel)
}

func main() {
	flag.Parse()
	r := rudia.NewRepeater()

	for _, arg := range flag.Args() {
		r.Proxy(arg)
	}

	r.ListenAndAccept(":" + *relayPort)
}
<|endoftext|>


<commit_before>/*
seqls - list directory contents, rolled up into file sequences
*/
package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"text/tabwriter"
	"time"

	"github.com/MichaelTJones/walk"
	"github.com/jessevdk/go-flags"
	"github.com/justinfx/gofileseq"
)

var opts struct {
	Recurse   bool `short:"r" long:"recurse" description:"recursively scan all sub-directories"`
	AllFiles  bool `short:"a" long:"all" description:"list all files, including those without frame patterns"`
	LongList  bool `short:"l" long:"long" description:"long listing; include extra stat information"`
	AbsPath   bool `short:"f" long:"full" description:"show absolute paths"`
	HumanSize bool `short:"H" long:"human" description:"when using long listing, show human-readable file size units"`
	Quiet     bool `short:"q" long:"quiet" description:"Don't print errors encountered when reading the file system"`
}

const (
	Version   = "0.9.0"
	DateFmt   = `Jan _2 15:04`
	ErrorPath = `Error: Failed reading path`
)

var (
	// number of goroutines to spawn for processing directories
	// and building FileSequence results
	numWorkers = 50

	errOut io.Writer = os.Stderr
)

func init() {
	// If $GOMAXPROCS isn't set, use the full capacity of the machine.
	// For small machines, use at least 4 threads.
	if os.Getenv("GOMAXPROCS") == "" {
		n := runtime.NumCPU()
		if n < 4 {
			n = 4
		}
		runtime.GOMAXPROCS(n)
	}
}

var usage = fmt.Sprintf(`[options] [path [...]]

Version: %s

List directory contents, rolled up into file sequences.

One or more paths may be provided. If no path is provided, the current
working directory will be scanned.

Only files are shown in listing results.
`, Version)

func main() {
	parser := flags.NewParser(&opts, flags.HelpFlag|flags.PrintErrors)
	parser.Name = "seqls"
	parser.Usage = usage
	roots, err := parser.Parse()

	if err != nil {
		os.Exit(1)
	}

	if opts.Quiet {
		errOut = ioutil.Discard
	}

	if len(roots) == 0 {
		// Use the current directory if specific dirs were not passed
		roots = []string{"."}
	}

	var wg sync.WaitGroup

	pathChan := make(chan string)
	seqChan := make(chan fileseq.FileSequences)

	// fmt.Printf("launching %d workers\n", numWorkers)

	var listerFn func(string) (fileseq.FileSequences, error)
	if opts.AllFiles {
		listerFn = fileseq.ListFiles
	} else {
		listerFn = fileseq.FindSequencesOnDisk
	}

	// Start the workers to find sequences
	for i := 0; i < numWorkers; i++ {
		wg.Add(1)
		go func() {
			for path := range pathChan {
				seqs, err := listerFn(path)
				if err != nil {
					// Bail out of the app for any path error
					os.Exit(255)
					fmt.Fprintf(errOut, "%s %q: %s\n", ErrorPath, path, err)
				}
				seqChan <- seqs
			}
			wg.Done()
		}()
	}

	// Load the root paths into the source channel
	unique := cleanDirs(roots)
	go func() {
		if opts.Recurse {
			loadRecursive(unique, pathChan)
		} else {
			for r := range unique {
				pathChan <- r
			}
		}
		close(pathChan)
	}()

	// Will close the output channel when no more source
	// paths are being added
	go func() {
		wg.Wait()
		close(seqChan)
	}()

	// Pull out all processed sequences and print
	var w io.Writer
	if opts.LongList {
		w = tabwriter.NewWriter(os.Stdout, 5, 0, 2, ' ', 0)
	} else {
		w = os.Stdout
	}

	var printer func(io.Writer, *fileseq.FileSequence)
	if opts.LongList {
		printer = printLongListing
	} else {
		printer = printShortListing
	}

	// Start processing the results that are feeding in the channel
	for seqs := range seqChan {
		for _, s := range seqs {
			printer(w, s)
		}
	}

	if opts.LongList {
		// Flush the tabwriter buffer
		w.(*tabwriter.Writer).Flush()
	}

	os.Exit(0)
}

// Parallel walk the root paths and populate the path
// channel for the worker routines to consume.
func loadRecursive(roots uniquePaths, out chan string) {
	walkFn := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			out <- path

		} else if fi, err := os.Stat(path); err == nil && fi.IsDir() {
			out <- path
		}
		return nil
	}
	for r := range roots {
		r := r
		if err := walk.Walk(r, walkFn); err != nil {
			if err != filepath.SkipDir {
				fmt.Fprintf(errOut, "%s %q: %s\n", ErrorPath, r, err)
			}
		}
	}
}

type uniquePaths map[string]struct{}

// Take a list of paths and reduce them to cleaned
// and unique paths.
func cleanDirs(paths []string) uniquePaths {
	u := make(uniquePaths)
	var (
		fi  os.FileInfo
		err error
	)
	for _, p := range paths {
		p := strings.TrimSpace(filepath.Clean(p))
		if p == "" {
			continue
		}
		if fi, err = os.Stat(p); err != nil {
			fmt.Fprintf(errOut, "%s %q: %s\n", ErrorPath, p, err)
			continue
		}
		if !fi.IsDir() {
			continue
		}
		u[p] = struct{}{}
	}
	return u
}

func printShortListing(w io.Writer, fs *fileseq.FileSequence) {
	str := fs.String()
	if opts.AbsPath {
		abs, err := filepath.Abs(str)
		if err == nil {
			str = abs
		}
	}
	fmt.Fprintln(w, str)
}

func printLongListing(w io.Writer, fs *fileseq.FileSequence) {
	var (
		err      error
		byteSize int64
		stat     os.FileInfo
		str      string
	)

	count := fs.Len()
	if count == 1 {
		// Only a single file
		str = fs.Index(0)
		stat, err = os.Stat(str)
		if err == nil {
			byteSize = stat.Size()
		}

	} else {
		str = fs.String()
		// For a sequence of files, we want to get the most
		// recent modtime, as well as the total size of the
		// combined files.
		mod := time.Unix(0, 0)
		var thisStat os.FileInfo
		var thisStr string
		for i := 0; i < count; i++ {
			thisStr = fs.Index(i)
			thisStat, err = os.Stat(thisStr)
			if err != nil {
				continue
			}
			byteSize += thisStat.Size()
			if thisStat.ModTime().After(mod) {
				stat = thisStat
				mod = thisStat.ModTime()
			}
		}
	}

	if opts.AbsPath {
		abs, err := filepath.Abs(str)
		if err == nil {
			str = abs
		}
	}

	if err != nil {
		fmt.Println(str)
		fmt.Fprintf(errOut, "%s: %s\n", ErrorPath, err.Error())
		return
	}

	var size interface{}
	if opts.HumanSize {
		size = ByteSize(byteSize)
	} else {
		size = byteSize
	}

	printDetails(w, str, stat, size)
}

type ByteSize float64

const (
	_           = iota // ignore first value by assigning to blank identifier
	KB ByteSize = 1 << (10 * iota)
	MB
	GB
	TB
)

func (b ByteSize) String() string {
	switch {
	case b >= TB:
		return fmt.Sprintf("%.1fT", b/TB)
	case b >= GB:
		return fmt.Sprintf("%.1fG", b/GB)
	case b >= MB:
		return fmt.Sprintf("%.1fM", b/MB)
	case b >= KB:
		return fmt.Sprintf("%.1fK", b/KB)
	case b == 0:
		return strconv.Itoa(0)
	}
	return fmt.Sprintf("%.0f", b)
}
<commit_msg>Don't bail out early on errors reading filesystem. Keep processing.<commit_after>/*
seqls - list directory contents, rolled up into file sequences
*/
package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"sync"
	"text/tabwriter"
	"time"

	"github.com/MichaelTJones/walk"
	"github.com/jessevdk/go-flags"
	"github.com/justinfx/gofileseq"
)

var opts struct {
	Recurse   bool `short:"r" long:"recurse" description:"recursively scan all sub-directories"`
	AllFiles  bool `short:"a" long:"all" description:"list all files, including those without frame patterns"`
	LongList  bool `short:"l" long:"long" description:"long listing; include extra stat information"`
	AbsPath   bool `short:"f" long:"full" description:"show absolute paths"`
	HumanSize bool `short:"H" long:"human" description:"when using long listing, show human-readable file size units"`
	Quiet     bool `short:"q" long:"quiet" description:"Don't print errors encountered when reading the file system"`
}

const (
	Version   = "0.9.0"
	DateFmt   = `Jan _2 15:04`
	ErrorPath = `Error: Failed reading path`
)

var (
	// number of goroutines to spawn for processing directories
	// and building FileSequence results
	numWorkers = 50

	errOut io.Writer = os.Stderr
)

func init() {
	// If $GOMAXPROCS isn't set, use the full capacity of the machine.
	// For small machines, use at least 4 threads.
	if os.Getenv("GOMAXPROCS") == "" {
		n := runtime.NumCPU()
		if n < 4 {
			n = 4
		}
		runtime.GOMAXPROCS(n)
	}
}

var usage = fmt.Sprintf(`[options] [path [...]]

Version: %s

List directory contents, rolled up into file sequences.

One or more paths may be provided. If no path is provided, the current
working directory will be scanned.

Only files are shown in listing results.
`, Version)

func main() {
	parser := flags.NewParser(&opts, flags.HelpFlag|flags.PrintErrors)
	parser.Name = "seqls"
	parser.Usage = usage
	roots, err := parser.Parse()

	if err != nil {
		os.Exit(1)
	}

	if opts.Quiet {
		errOut = ioutil.Discard
	}

	if len(roots) == 0 {
		// Use the current directory if specific dirs were not passed
		roots = []string{"."}
	}

	var wg sync.WaitGroup

	pathChan := make(chan string)
	seqChan := make(chan fileseq.FileSequences)

	// fmt.Printf("launching %d workers\n", numWorkers)

	var listerFn func(string) (fileseq.FileSequences, error)
	if opts.AllFiles {
		listerFn = fileseq.ListFiles
	} else {
		listerFn = fileseq.FindSequencesOnDisk
	}

	// Start the workers to find sequences
	for i := 0; i < numWorkers; i++ {
		wg.Add(1)
		go func() {
			for path := range pathChan {
				seqs, err := listerFn(path)
				if err != nil {
					// Bail out of the app for any path error
					fmt.Fprintf(errOut, "%s %q: %s\n", ErrorPath, path, err)
					continue
				}
				seqChan <- seqs
			}
			wg.Done()
		}()
	}

	// Load the root paths into the source channel
	unique := cleanDirs(roots)
	go func() {
		if opts.Recurse {
			loadRecursive(unique, pathChan)
		} else {
			for r := range unique {
				pathChan <- r
			}
		}
		close(pathChan)
	}()

	// Will close the output channel when no more source
	// paths are being added
	go func() {
		wg.Wait()
		close(seqChan)
	}()

	// Pull out all processed sequences and print
	var w io.Writer
	if opts.LongList {
		w = tabwriter.NewWriter(os.Stdout, 5, 0, 2, ' ', 0)
	} else {
		w = os.Stdout
	}

	var printer func(io.Writer, *fileseq.FileSequence)
	if opts.LongList {
		printer = printLongListing
	} else {
		printer = printShortListing
	}

	// Start processing the results that are feeding in the channel
	for seqs := range seqChan {
		for _, s := range seqs {
			printer(w, s)
		}
	}

	if opts.LongList {
		// Flush the tabwriter buffer
		w.(*tabwriter.Writer).Flush()
	}

	os.Exit(0)
}

// Parallel walk the root paths and populate the path
// channel for the worker routines to consume.
func loadRecursive(roots uniquePaths, out chan string) {
	walkFn := func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return nil
		}

		if info.IsDir() {
			out <- path

		} else if info, err = os.Stat(path); err == nil && info.IsDir() {
			out <- path
		}

		return nil
	}
	for r := range roots {
		r := r
		if err := walk.Walk(r, walkFn); err != nil {
			if err != filepath.SkipDir {
				fmt.Fprintf(errOut, "%s %q: %s\n", ErrorPath, r, err)
			}
		}
	}
}

type uniquePaths map[string]struct{}

// Take a list of paths and reduce them to cleaned
// and unique paths.
func cleanDirs(paths []string) uniquePaths {
	u := make(uniquePaths)
	var (
		fi  os.FileInfo
		err error
	)
	for _, p := range paths {
		p := strings.TrimSpace(filepath.Clean(p))
		if p == "" {
			continue
		}
		if fi, err = os.Stat(p); err != nil {
			fmt.Fprintf(errOut, "%s %q: %s\n", ErrorPath, p, err)
			continue
		}
		if !fi.IsDir() {
			continue
		}
		u[p] = struct{}{}
	}
	return u
}

func printShortListing(w io.Writer, fs *fileseq.FileSequence) {
	str := fs.String()
	if opts.AbsPath {
		abs, err := filepath.Abs(str)
		if err == nil {
			str = abs
		}
	}
	fmt.Fprintln(w, str)
}

func printLongListing(w io.Writer, fs *fileseq.FileSequence) {
	var (
		err      error
		byteSize int64
		stat     os.FileInfo
		str      string
	)

	count := fs.Len()
	if count == 1 {
		// Only a single file
		str = fs.Index(0)
		stat, err = os.Stat(str)
		if err == nil {
			byteSize = stat.Size()
		}

	} else {
		str = fs.String()
		// For a sequence of files, we want to get the most
		// recent modtime, as well as the total size of the
		// combined files.
		mod := time.Unix(0, 0)
		var thisStat os.FileInfo
		var thisStr string
		for i := 0; i < count; i++ {
			thisStr = fs.Index(i)
			thisStat, err = os.Stat(thisStr)
			if err != nil {
				continue
			}
			byteSize += thisStat.Size()
			if thisStat.ModTime().After(mod) {
				stat = thisStat
				mod = thisStat.ModTime()
			}
		}
	}

	if opts.AbsPath {
		abs, err := filepath.Abs(str)
		if err == nil {
			str = abs
		}
	}

	if err != nil {
		fmt.Println(str)
		fmt.Fprintf(errOut, "%s: %s\n", ErrorPath, err.Error())
		return
	}

	var size interface{}
	if opts.HumanSize {
		size = ByteSize(byteSize)
	} else {
		size = byteSize
	}

	printDetails(w, str, stat, size)
}

type ByteSize float64

const (
	_           = iota // ignore first value by assigning to blank identifier
	KB ByteSize = 1 << (10 * iota)
	MB
	GB
	TB
)

func (b ByteSize) String() string {
	switch {
	case b >= TB:
		return fmt.Sprintf("%.1fT", b/TB)
	case b >= GB:
		return fmt.Sprintf("%.1fG", b/GB)
	case b >= MB:
		return fmt.Sprintf("%.1fM", b/MB)
	case b >= KB:
		return fmt.Sprintf("%.1fK", b/KB)
	case b == 0:
		return strconv.Itoa(0)
	}
	return fmt.Sprintf("%.0f", b)
}
<|endoftext|>


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

package cmd

import (
	"bytes"
	"errors"
	"io/ioutil"
	. "launchpad.net/gocheck"
	"net/http"
	"os"
	"testing"
)

func Test(t *testing.T) { TestingT(t) }

type S struct {
	stdin *os.File
}

type transport struct {
	msg    string
	status int
}

type conditionalTransport struct {
	transport
	condFunc func(*http.Request) bool
}

var _ = Suite(&S{})
var manager *Manager

func (t *transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
	resp = &http.Response{
		Body:       ioutil.NopCloser(bytes.NewBufferString(t.msg)),
		StatusCode: t.status,
	}
	return resp, nil
}

func (t *conditionalTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	if !t.condFunc(req) {
		return &http.Response{Body: nil, StatusCode: 500}, errors.New("condition failed")
	}
	return t.transport.RoundTrip(req)
}

func (s *S) SetUpTest(c *C) {
	var stdout, stderr bytes.Buffer
	manager = NewManager("glb", "1.0", "", &stdout, &stderr, os.Stdin)
	var exiter recordingExiter
	manager.e = &exiter
}
<commit_msg>cmd/tests: add support for headers in fake transport<commit_after>// Copyright 2012 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cmd

import (
	"bytes"
	"errors"
	"io/ioutil"
	. "launchpad.net/gocheck"
	"net/http"
	"os"
	"testing"
)

func Test(t *testing.T) { TestingT(t) }

type S struct {
	stdin *os.File
}

type transport struct {
	msg     string
	status  int
	headers map[string][]string
}

type conditionalTransport struct {
	transport
	condFunc func(*http.Request) bool
}

var _ = Suite(&S{})
var manager *Manager

func (t *transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
	resp = &http.Response{
		Body:       ioutil.NopCloser(bytes.NewBufferString(t.msg)),
		StatusCode: t.status,
		Header:     http.Header(t.headers),
	}
	return resp, nil
}

func (t *conditionalTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	if !t.condFunc(req) {
		return &http.Response{Body: nil, StatusCode: 500}, errors.New("condition failed")
	}
	return t.transport.RoundTrip(req)
}

func (s *S) SetUpTest(c *C) {
	var stdout, stderr bytes.Buffer
	manager = NewManager("glb", "1.0", "", &stdout, &stderr, os.Stdin)
	var exiter recordingExiter
	manager.e = &exiter
}
<|endoftext|>


<commit_before>package main

var UsageConnect = `'alias' or 'transport://[addr][/path]/targetcall[?params...]'

transport:
  winmor:     WINMOR TNC
  ardop:      ARDOP TNC
  ax25:       AX.25 (Linux only)
  telnet:     TCP/IP
  serial-tnc: Serial AX.25 TNC

addr:
  Used to address the transport device, _not_ to be confused with the connection
   PATH. Format: [user[:pass]@]host[:port]

  telnet:       [user:pass]@host:port
  ax25:         (optional) host=axport

path:
  The last element of the path is the target station's callsign. If the path has
   multiple hops (e.g. AX.25), they are separated by '/'.

params:
  ?freq=        Sets QSY frequency (winmor and ardop only)
`
var ExampleConnect = `
  connect telnet                     (alias) Connect to one of the Winlink Common Message Servers via tcp.
  connect ax25:///LA1B-10            Connect to the RMS Gateway LA1B-10 using Linux AX.25 on the default axport.
  connect ax25://tmd710/LA1B-10      Connect to the RMS Gateway LA1B-10 using Linux AX.25 on axport 'tmd710'.
  connect ax25:///LA1B/LA5NTA        Peer-to-peer connection with LA5NTA via LA1B digipeater.
  connect winmor:///LA3F             Connect to the RMS HF Gateway LA3F using WINMOR TNC on default tcp address and port.
  connect winmor:///LA3F?freq=5350   Same as above, but set dial frequency of the radio using rigcontrol.
  connect ardop:///LA3F              Connect to the RMS HF Gateway LA3F using ARDOP on the default tcp address and port.
  connect ardop:///LA3F?freq=5350    Same as above, but set dial frequency of the radio using rigcontrol.
  connect serial-tnc:///LA1B-10      Connect to the RMS Gateway LA1B-10 over a AX.25 serial TNC on the default serial port.
`
<commit_msg>cmd/wl2k: Update usage<commit_after>package main

var UsageConnect = `'alias' or 'transport://[addr][/path]/targetcall[?params...]'

transport:
  winmor:     WINMOR TNC
  ardop:      ARDOP TNC
  ax25:       AX.25 (Linux only)
  telnet:     TCP/IP
  serial-tnc: Serial AX.25 TNC

addr:
  Used to address the transport device, _not_ to be confused with the connection
   PATH. Format: [user[:pass]@]host[:port]

  telnet:       [user:pass]@host:port
  ax25:         (optional) host=axport

path:
  The last element of the path is the target station's callsign. If the path has
   multiple hops (e.g. AX.25), they are separated by '/'.

params:
  ?freq=        Sets QSY frequency (winmor, ardop and ax25 only)
`
var ExampleConnect = `
  connect telnet                     (alias) Connect to one of the Winlink Common Message Servers via tcp.
  connect ax25:///LA1B-10            Connect to the RMS Gateway LA1B-10 using Linux AX.25 on the default axport.
  connect ax25://tmd710/LA1B-10      Connect to the RMS Gateway LA1B-10 using Linux AX.25 on axport 'tmd710'.
  connect ax25:///LA1B/LA5NTA        Peer-to-peer connection with LA5NTA via LA1B digipeater.
  connect winmor:///LA3F             Connect to the RMS HF Gateway LA3F using WINMOR TNC on default tcp address and port.
  connect winmor:///LA3F?freq=5350   Same as above, but set dial frequency of the radio using rigcontrol.
  connect ardop:///LA3F              Connect to the RMS HF Gateway LA3F using ARDOP on the default tcp address and port.
  connect ardop:///LA3F?freq=5350    Same as above, but set dial frequency of the radio using rigcontrol.
  connect serial-tnc:///LA1B-10      Connect to the RMS Gateway LA1B-10 over a AX.25 serial TNC on the default serial port.
`
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/spf13/cobra"
	"github.com/spf13/cobra/cobra/cmd"
)

var rootCmd = &cobra.Command{Use: "yangc"}

func main() {
	if err := cmd.RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}
<commit_msg>Update main.go<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"sort"

	"github.com/openconfig/goyang/pkg/yang"
	"github.com/spf13/cobra"
)

var mainCmd = &cobra.Command{
	Use:   os.Args[0],
	Short: "Tool to translate Yang Models to Unit Data API",
}

var yangFileName string

func init() {
	mainCmd.PersistentFlags().StringVarP(&yangFileName, "file", "f", "test.yang", "yang file name")
}

func main() {
	if _, err := mainCmd.ExecuteC(); err != nil {
		os.Exit(-1)
	}
}

func doCompile(fileName string) []*yang.Entry {
	var entries []*yang.Entry

	ms := yang.NewModules()
	files := make([]string, 0, 10)
	files = append(files, fileName)

	if len(files) == 0 {
		data, err := ioutil.ReadAll(os.Stdin)
		if err == nil {
			err = ms.Parse(string(data), "<STDIN>")
		}
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			os.Exit(1)
		}
	}

	for _, name := range files {
		if err := ms.Read(name); err != nil {
			fmt.Fprintln(os.Stderr, err)
			continue
		}
	}

	// Process the read files, exiting if any errors were found.
	exitIfError(ms.Process())

	// Keep track of the top level modules we read in.
	// Those are the only modules we want to print below.
	mods := map[string]*yang.Module{}
	var names []string

	for _, m := range ms.Modules {
		if mods[m.Name] == nil {
			mods[m.Name] = m
			names = append(names, m.Name)
		}
	}
	sort.Strings(names)
	entries = make([]*yang.Entry, len(names))
	for x, n := range names {
		fmt.Printf("- module[%s] ...\n", n)
		entries[x] = yang.ToEntry(mods[n])
		// copy Typedef dictionary & return?
	}
	return entries
}

// exitIfError writes errs to standard error and exits with an exit status of 1.
// If errs is empty then exitIfError does nothing and simply returns.
func exitIfError(errs []error) {
	if len(errs) > 0 {
		for _, err := range errs {
			fmt.Fprintln(os.Stderr, err)
		}
		os.Exit(1)
	}
}

<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"encoding/pem"
	"flag"
	"io/ioutil"
	"os"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/zmap/zcrypto/x509"
	"github.com/zmap/zlint"
)

var ( //flags
	listLintsJSON bool
	prettyprint   bool
	format        string
)

func init() {
	flag.BoolVar(&listLintsJSON, "list-lints-json", false, "Use this flag to print supported lints in JSON format, one per line")
	flag.StringVar(&format, "format", "pem", "One of {pem, der, base64}")
	flag.BoolVar(&prettyprint, "pretty", false, "Pretty-print output")
	flag.Parse()

	log.SetLevel(log.InfoLevel)
}

func main() {

	if listLintsJSON {
		zlint.EncodeLintDescriptionsToJSON(os.Stdout)
		return
	}

	var inputFile *os.File
	if flag.NArg() < 1 || flag.Arg(0) == "-" {
		inputFile = os.Stdin
	} else {
		filePath := flag.Arg(0)
		var err error
		inputFile, err = os.Open(filePath)
		if err != nil {
			log.Fatalf("unable to open file %s: %s", filePath, err)
		}
	}

	fileBytes, err := ioutil.ReadAll(inputFile)
	if err != nil {
		log.Fatalf("unable to read file %s: %s", inputFile.Name(), err)
	}

	var asn1Data []byte
	switch inform := strings.ToLower(format); inform {
	case "pem":
		p, _ := pem.Decode(fileBytes)
		if p == nil || p.Type != "CERTIFICATE" {
			log.Fatal("unable to parse PEM")
		}
		asn1Data = p.Bytes
	case "der":
		asn1Data = fileBytes
	case "base64":
		asn1Data, err = base64.StdEncoding.DecodeString(string(fileBytes))
		if err != nil {
			log.Fatalf("unable to parse base64: %s", err)
		}
	default:
		log.Fatalf("unknown input format %s", format)
	}

	c, err := x509.ParseCertificate(asn1Data)
	if err != nil {
		log.Fatalf("unable to parse certificate: %s", err)
	}

	zlintResult := zlint.LintCertificate(c)
	jsonBytes, err := json.Marshal(zlintResult.ZLint)
	if err != nil {
		log.Fatalf("unable to encode lints JSON: %s", err)
	}
	if prettyprint {
		var out bytes.Buffer
		if err := json.Indent(&out, jsonBytes, "", " "); err != nil {
			log.Fatalf("can't format output: %s", err)
		}
		os.Stdout.Write(out.Bytes())
	} else {
		os.Stdout.Write(jsonBytes)
	}
	os.Stdout.Write([]byte{'\n'})
	os.Stdout.Sync()
}
<commit_msg>Take multiple input files; intuit filetype (#132)<commit_after>package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"encoding/pem"
	"flag"
	"io/ioutil"
	"os"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/zmap/zcrypto/x509"
	"github.com/zmap/zlint"
)

var ( //flags
	listLintsJSON bool
	prettyprint   bool
	format        string
)

func init() {
	flag.BoolVar(&listLintsJSON, "list-lints-json", false, "Use this flag to print supported lints in JSON format, one per line")
	flag.StringVar(&format, "format", "pem", "One of {pem, der, base64}")
	flag.BoolVar(&prettyprint, "pretty", false, "Pretty-print output")
	flag.Parse()

	log.SetLevel(log.InfoLevel)
}

func main() {

	if listLintsJSON {
		zlint.EncodeLintDescriptionsToJSON(os.Stdout)
		return
	}

	var inform = strings.ToLower(format)
	if flag.NArg() < 1 || flag.Arg(0) == "-" {
		lint(os.Stdin, inform)
	} else {
		for _, filePath := range flag.Args() {
			var inputFile *os.File
			var err error
			inputFile, err = os.Open(filePath)
			if err != nil {
				log.Fatalf("unable to open file %s: %s", filePath, err)
			}
			var fmt = inform
			switch {
			case strings.HasSuffix(filePath, ".der"):
				fmt = "der"
			case strings.HasSuffix(filePath, ".pem"):
				fmt = "pem"
			}
			lint(inputFile, fmt)
			inputFile.Close()
		}
	}
}

func lint(inputFile *os.File, inform string) {
	fileBytes, err := ioutil.ReadAll(inputFile)
	if err != nil {
		log.Fatalf("unable to read file %s: %s", inputFile.Name(), err)
	}

	var asn1Data []byte
	switch inform {
	case "pem":
		p, _ := pem.Decode(fileBytes)
		if p == nil || p.Type != "CERTIFICATE" {
			log.Fatal("unable to parse PEM")
		}
		asn1Data = p.Bytes
	case "der":
		asn1Data = fileBytes
	case "base64":
		asn1Data, err = base64.StdEncoding.DecodeString(string(fileBytes))
		if err != nil {
			log.Fatalf("unable to parse base64: %s", err)
		}
	default:
		log.Fatalf("unknown input format %s", format)
	}

	c, err := x509.ParseCertificate(asn1Data)
	if err != nil {
		log.Fatalf("unable to parse certificate: %s", err)
	}

	zlintResult := zlint.LintCertificate(c)
	jsonBytes, err := json.Marshal(zlintResult.ZLint)
	if err != nil {
		log.Fatalf("unable to encode lints JSON: %s", err)
	}
	if prettyprint {
		var out bytes.Buffer
		if err := json.Indent(&out, jsonBytes, "", " "); err != nil {
			log.Fatalf("can't format output: %s", err)
		}
		os.Stdout.Write(out.Bytes())
	} else {
		os.Stdout.Write(jsonBytes)
	}
	os.Stdout.Write([]byte{'\n'})
	os.Stdout.Sync()
}
<|endoftext|>