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

package tspi

// #include <trousers/tss.h>
import "C"
import "unsafe"

// ModulusFromBlob provides the modulus of a provided TSS key blob
func ModulusFromBlob(blob []byte) []byte {
	return blob[28:]
}

// Key is a TSS key
type Key struct {
	handle  C.TSS_HKEY
	context C.TSS_HCONTEXT
}

// GetPolicy returns the policy associated with the key
func (key *Key) GetPolicy(poltype int) (*Policy, error) {
	var policyHandle C.TSS_HPOLICY
	err := tspiError(C.Tspi_GetPolicyObject((C.TSS_HOBJECT)(key.handle), (C.TSS_FLAG)(poltype), &policyHandle))
	return &Policy{handle: policyHandle, context: key.context}, err
}

// SetModulus sets the modulus of a public key to the provided value
func (key *Key) SetModulus(n []byte) error {
	err := tspiError(C.Tspi_SetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_RSAKEY_INFO, C.TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, (C.UINT32)(len(n)), (*C.BYTE)(unsafe.Pointer(&n[0]))))
	return err
}

// GetModulus returns the modulus of the public key
func (key *Key) GetModulus() (modulus []byte, err error) {
	var dataLen C.UINT32
	var cData *C.BYTE
	err = tspiError(C.Tspi_GetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_RSAKEY_INFO, C.TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &dataLen, &cData))
	data := C.GoBytes(unsafe.Pointer(cData), (C.int)(dataLen))
	C.Tspi_Context_FreeMemory(key.context, cData)
	return data, err
}

// GetPubKeyBlob returns the public half of the key in TPM blob format
func (key *Key) GetPubKeyBlob() (pubkey []byte, err error) {
	var dataLen C.UINT32
	var cData *C.BYTE
	err = tspiError(C.Tspi_GetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_KEY_BLOB, C.TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &dataLen, &cData))
	data := C.GoBytes(unsafe.Pointer(cData), (C.int)(dataLen))
	C.Tspi_Context_FreeMemory(key.context, cData)
	return data, err
}

// GetKeyBlob returns an encrypted blob containing the public and private
// halves of the key
func (key *Key) GetKeyBlob() ([]byte, error) {
	var dataLen C.UINT32
	var cData *C.BYTE
	err := tspiError(C.Tspi_GetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_KEY_BLOB, C.TSS_TSPATTRIB_KEYBLOB_BLOB, &dataLen, &cData))
	data := C.GoBytes(unsafe.Pointer(cData), (C.int)(dataLen))
	C.Tspi_Context_FreeMemory(key.context, cData)
	return data, err
}

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

package tspi

// #include <trousers/tss.h>
import "C"
import "unsafe"

// ModulusFromBlob provides the modulus of a provided TSS key blob
func ModulusFromBlob(blob []byte) []byte {
	return blob[28:]
}

// Key is a TSS key
type Key struct {
	handle  C.TSS_HKEY
	context C.TSS_HCONTEXT
}

// GetPolicy returns the policy associated with the key
func (key *Key) GetPolicy(poltype int) (*Policy, error) {
	var policyHandle C.TSS_HPOLICY
	err := tspiError(C.Tspi_GetPolicyObject((C.TSS_HOBJECT)(key.handle), (C.TSS_FLAG)(poltype), &policyHandle))
	return &Policy{handle: policyHandle, context: key.context}, err
}

// SetModulus sets the modulus of a public key to the provided value
func (key *Key) SetModulus(n []byte) error {
	err := tspiError(C.Tspi_SetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_RSAKEY_INFO, C.TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, (C.UINT32)(len(n)), (*C.BYTE)(unsafe.Pointer(&n[0]))))
	return err
}

// GetModulus returns the modulus of the public key
func (key *Key) GetModulus() (modulus []byte, err error) {
	var dataLen C.UINT32
	var cData *C.BYTE
	err = tspiError(C.Tspi_GetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_RSAKEY_INFO, C.TSS_TSPATTRIB_KEYINFO_RSA_MODULUS, &dataLen, &cData))
	data := C.GoBytes(unsafe.Pointer(cData), (C.int)(dataLen))
	C.Tspi_Context_FreeMemory(key.context, cData)
	return data, err
}

// GetPubKeyBlob returns the public half of the key in TPM blob format
func (key *Key) GetPubKeyBlob() (pubkey []byte, err error) {
	var dataLen C.UINT32
	var cData *C.BYTE
	err = tspiError(C.Tspi_GetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_KEY_BLOB, C.TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, &dataLen, &cData))
	data := C.GoBytes(unsafe.Pointer(cData), (C.int)(dataLen))
	C.Tspi_Context_FreeMemory(key.context, cData)
	return data, err
}

// GetKeyBlob returns an encrypted blob containing the public and private
// halves of the key
func (key *Key) GetKeyBlob() ([]byte, error) {
	var dataLen C.UINT32
	var cData *C.BYTE
	err := tspiError(C.Tspi_GetAttribData((C.TSS_HOBJECT)(key.handle), C.TSS_TSPATTRIB_KEY_BLOB, C.TSS_TSPATTRIB_KEYBLOB_BLOB, &dataLen, &cData))
	data := C.GoBytes(unsafe.Pointer(cData), (C.int)(dataLen))
	C.Tspi_Context_FreeMemory(key.context, cData)
	return data, err
}

// GenerateKey generates a key pair on the TPM, wrapping it with the provided
// key
func (key *Key) GenerateKey(wrapkey *Key) (err error) {
	err = tspiError(C.Tspi_Key_CreateKey((C.TSS_HKEY)(key.handle), (C.TSS_HKEY)(wrapkey.handle), 0))
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/msbranco/goconfig"
	"github.com/vaughan0/go-zmq"
	"log"
	"log/syslog"
	"os"
	"strings"
)

func main() {

	// Syslog
		syslogLog, err :=syslog.New(syslog.LOG_INFO, "turtledq/server")
		if nil != err {
			log.Fatal("Big problem, could not open up syslog!")
/////////// RETURN
			return
		}

	//DEBUG
	syslogLog.Notice("=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=")
	syslogLog.Notice("TurtleDQ Server BEGIN.")

	// Config
		//DEBUG
		syslogLog.Notice("    Settings BEGIN.")

		cmdPath := os.Args[0]
		cmdPathLastSlash := strings.LastIndexFunc(cmdPath, func(c rune) bool {
			return '/' == c
		})

		cmdDirPath := cmdPath[0:cmdPathLastSlash]

		//DEBUG
		syslogLog.Notice( fmt.Sprintf("    command path: [%v]", cmdPath)  )
		syslogLog.Notice( fmt.Sprintf("    command path last slash: [%v]", cmdPathLastSlash) )
		syslogLog.Notice( fmt.Sprintf("    command dir path: [%v]", cmdDirPath) )

		confRelativePath := "turtledq.ini"
		confPath := cmdDirPath + "/" + confRelativePath

		//DEBUG
		syslogLog.Notice( fmt.Sprintf("    settings file relative path: [%v]", confRelativePath) )
		syslogLog.Notice( fmt.Sprintf("    settings file absolute path: [%v]", confPath) )

		//c, err := configfile.ReadConfigFile(confPath);
		c, err := goconfig.ReadConfigFile(confPath);
		if nil != err {
			errMsg := fmt.Sprintf("Error when trying to read config file: err = [%v]", err)
			syslogLog.Err(errMsg)
			log.Fatal(errMsg)
/////////// RETURN
			return
		}

		//DEBUG
		syslogLog.Notice( fmt.Sprintf("config file: [%v]", c) )

		//DEBUG
		syslogLog.Notice("    Settings END.")

	// Go!
		go dequeue(syslogLog)
		go enqueue(syslogLog)

	// Create ZeroMQ context.
		ctx, err := zmq.NewContext()
		if err != nil {
			panic(err)
		}
		defer ctx.Close()

	// Create ZeroMQ socket (from ZeroMQ context).
		sock, err := ctx.Socket(zmq.Router)
		if err != nil {
			panic(err)
		}
		defer sock.Close()

		if err = sock.Bind("tcp://*:5555"); err != nil {
			panic(err)
		}

	// Handle input from ZeroMQ (via channels).
		chans := sock.Channels()
		defer chans.Close()

		for {
			select {

				case msg := <-chans.In():
					go func() {
						resp := handleRequest(syslogLog, msg)
						chans.Out() <- resp
					}()

				case err := <-chans.Errors():
					panic(err)

			} // select
		}

	//DEBUG
	syslogLog.Notice("TurtleDQ Server END.")
}

func handleRequest(syslogLog *syslog.Writer, msg [][]byte) [][]byte {

//@TODO
	syslogLog.Notice( fmt.Sprintf("[handleRequest] msg = [%v]", msg) )

	// Return
//@TODO
		return [][]byte{
			[]byte("apple banana cherry"),
		}
}
<commit_msg>commented out ZeroMQ stuff for now<commit_after>package main

import (
	"fmt"
	"github.com/msbranco/goconfig"
//	"github.com/vaughan0/go-zmq"
	"log"
	"log/syslog"
	"os"
	"strings"
)

func main() {

	// Syslog
		syslogLog, err :=syslog.New(syslog.LOG_INFO, "turtledq/server")
		if nil != err {
			log.Fatal("Big problem, could not open up syslog!")
/////////// RETURN
			return
		}

	//DEBUG
	syslogLog.Notice("=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=-<>-=")
	syslogLog.Notice("TurtleDQ Server BEGIN.")

	// Config
		//DEBUG
		syslogLog.Notice("    Settings BEGIN.")

		cmdPath := os.Args[0]
		cmdPathLastSlash := strings.LastIndexFunc(cmdPath, func(c rune) bool {
			return '/' == c
		})

		cmdDirPath := cmdPath[0:cmdPathLastSlash]

		//DEBUG
		syslogLog.Notice( fmt.Sprintf("    command path: [%v]", cmdPath)  )
		syslogLog.Notice( fmt.Sprintf("    command path last slash: [%v]", cmdPathLastSlash) )
		syslogLog.Notice( fmt.Sprintf("    command dir path: [%v]", cmdDirPath) )

		confRelativePath := "turtledq.ini"
		confPath := cmdDirPath + "/" + confRelativePath

		//DEBUG
		syslogLog.Notice( fmt.Sprintf("    settings file relative path: [%v]", confRelativePath) )
		syslogLog.Notice( fmt.Sprintf("    settings file absolute path: [%v]", confPath) )

		//c, err := configfile.ReadConfigFile(confPath);
		c, err := goconfig.ReadConfigFile(confPath);
		if nil != err {
			errMsg := fmt.Sprintf("Error when trying to read config file: err = [%v]", err)
			syslogLog.Err(errMsg)
			log.Fatal(errMsg)
/////////// RETURN
			return
		}

		//DEBUG
		syslogLog.Notice( fmt.Sprintf("config file: [%v]", c) )

		//DEBUG
		syslogLog.Notice("    Settings END.")

	// Go!
		go dequeue(syslogLog)
		go enqueue(syslogLog)

//	// Create ZeroMQ context.
//		ctx, err := zmq.NewContext()
//		if err != nil {
//			panic(err)
//		}
//		defer ctx.Close()
//
//
//	// Create ZeroMQ socket (from ZeroMQ context).
//		sock, err := ctx.Socket(zmq.Router)
//		if err != nil {
//			panic(err)
//		}
//		defer sock.Close()
//
//		if err = sock.Bind("tcp://*:5555"); err != nil {
//			panic(err)
//		}
//
//
//	// Handle input from ZeroMQ (via channels).
//		chans := sock.Channels()
//		defer chans.Close()
//
//
//
//		for {
//			select {
//
//				case msg := <-chans.In():
//					go func() {
//						resp := handleRequest(syslogLog, msg)
//						chans.Out() <- resp
//					}()
//
//				case err := <-chans.Errors():
//					panic(err)
//
//			} // select
//		}

		select{}

	//DEBUG
	syslogLog.Notice("TurtleDQ Server END.")
}

func handleRequest(syslogLog *syslog.Writer, msg [][]byte) [][]byte {

//@TODO
	syslogLog.Notice( fmt.Sprintf("[handleRequest] msg = [%v]", msg) )

	// Return
//@TODO
		return [][]byte{
			[]byte("apple banana cherry"),
		}
}
<|endoftext|>


<commit_before>package msgpack

import (
	"io/ioutil"
	"reflect"
	"sync"
)

var (
	marshalerType   = reflect.TypeOf(new(Marshaler)).Elem()
	unmarshalerType = reflect.TypeOf(new(Unmarshaler)).Elem()
	stringsType     = reflect.TypeOf(([]string)(nil))
)

var structs = newStructCache()

var valueEncoders []encoderFunc
var valueDecoders []decoderFunc

func init() {
	valueEncoders = []encoderFunc{
		reflect.Bool:          encodeBoolValue,
		reflect.Int:           encodeInt64Value,
		reflect.Int8:          encodeInt64Value,
		reflect.Int16:         encodeInt64Value,
		reflect.Int32:         encodeInt64Value,
		reflect.Int64:         encodeInt64Value,
		reflect.Uint:          encodeUint64Value,
		reflect.Uint8:         encodeUint64Value,
		reflect.Uint16:        encodeUint64Value,
		reflect.Uint32:        encodeUint64Value,
		reflect.Uint64:        encodeUint64Value,
		reflect.Float32:       encodeFloat64Value,
		reflect.Float64:       encodeFloat64Value,
		reflect.Array:         encodeArrayValue,
		reflect.Interface:     encodeInterfaceValue,
		reflect.Map:           encodeMapValue,
		reflect.Ptr:           encodePtrValue,
		reflect.Slice:         encodeSliceValue,
		reflect.String:        encodeStringValue,
		reflect.Struct:        encodeStructValue,
		reflect.UnsafePointer: nil,
	}
	valueDecoders = []decoderFunc{
		reflect.Bool:          decodeBoolValue,
		reflect.Int:           decodeInt64Value,
		reflect.Int8:          decodeInt64Value,
		reflect.Int16:         decodeInt64Value,
		reflect.Int32:         decodeInt64Value,
		reflect.Int64:         decodeInt64Value,
		reflect.Uint:          decodeUint64Value,
		reflect.Uint8:         decodeUint64Value,
		reflect.Uint16:        decodeUint64Value,
		reflect.Uint32:        decodeUint64Value,
		reflect.Uint64:        decodeUint64Value,
		reflect.Float32:       decodeFloat64Value,
		reflect.Float64:       decodeFloat64Value,
		reflect.Array:         decodeArrayValue,
		reflect.Interface:     decodeInterfaceValue,
		reflect.Map:           decodeMapValue,
		reflect.Ptr:           decodePtrValue,
		reflect.Slice:         decodeSliceValue,
		reflect.String:        decodeStringValue,
		reflect.Struct:        decodeStructValue,
		reflect.UnsafePointer: nil,
	}
}

//------------------------------------------------------------------------------

type field struct {
	index     []int
	omitEmpty bool

	encoder encoderFunc
	decoder decoderFunc
}

func (f *field) value(strct reflect.Value) reflect.Value {
	return strct.FieldByIndex(f.index)
}

func (f *field) Omit(strct reflect.Value) bool {
	return f.omitEmpty && isEmptyValue(f.value(strct))
}

func (f *field) EncodeValue(e *Encoder, strct reflect.Value) error {
	return f.encoder(e, f.value(strct))
}

func (f *field) DecodeValue(d *Decoder, strct reflect.Value) error {
	return f.decoder(d, f.value(strct))
}

//------------------------------------------------------------------------------

type fields map[string]*field

//------------------------------------------------------------------------------

func encodeBoolValue(e *Encoder, v reflect.Value) error {
	return e.EncodeBool(v.Bool())
}

func decodeBoolValue(d *Decoder, v reflect.Value) error {
	return d.boolValue(v)
}

//------------------------------------------------------------------------------

func encodeFloat64Value(e *Encoder, v reflect.Value) error {
	return e.EncodeFloat64(v.Float())
}

func decodeFloat64Value(d *Decoder, v reflect.Value) error {
	return d.float64Value(v)
}

//------------------------------------------------------------------------------

func encodeStringValue(e *Encoder, v reflect.Value) error {
	return e.EncodeString(v.String())
}

func decodeStringValue(d *Decoder, v reflect.Value) error {
	return d.stringValue(v)
}

//------------------------------------------------------------------------------

func encodeBytesValue(e *Encoder, v reflect.Value) error {
	return e.EncodeBytes(v.Bytes())
}

func decodeBytesValue(d *Decoder, v reflect.Value) error {
	return d.bytesValue(v)
}

//------------------------------------------------------------------------------

func encodeInt64Value(e *Encoder, v reflect.Value) error {
	return e.EncodeInt64(v.Int())
}

func decodeInt64Value(d *Decoder, v reflect.Value) error {
	return d.int64Value(v)
}

//------------------------------------------------------------------------------

func encodeUint64Value(e *Encoder, v reflect.Value) error {
	return e.EncodeUint64(v.Uint())
}

func decodeUint64Value(d *Decoder, v reflect.Value) error {
	return d.uint64Value(v)
}

//------------------------------------------------------------------------------

func encodeSliceValue(e *Encoder, v reflect.Value) error {
	return e.encodeSlice(v)
}

func decodeSliceValue(d *Decoder, v reflect.Value) error {
	return d.sliceValue(v)
}

//------------------------------------------------------------------------------

func encodeArrayValue(e *Encoder, v reflect.Value) error {
	return e.encodeArray(v)
}

func decodeArrayValue(d *Decoder, v reflect.Value) error {
	return d.sliceValue(v)
}

//------------------------------------------------------------------------------

func encodeInterfaceValue(e *Encoder, v reflect.Value) error {
	if v.IsNil() {
		return e.EncodeNil()
	}
	return e.EncodeValue(v.Elem())
}

func decodeInterfaceValue(d *Decoder, v reflect.Value) error {
	if v.IsNil() {
		return d.interfaceValue(v)
	}
	return d.DecodeValue(v.Elem())
}

//------------------------------------------------------------------------------

func encodeMapValue(e *Encoder, v reflect.Value) error {
	return e.encodeMap(v)
}

func decodeMapValue(d *Decoder, v reflect.Value) error {
	return d.mapValue(v)
}

//------------------------------------------------------------------------------

func encodePtrValue(e *Encoder, v reflect.Value) error {
	if v.IsNil() {
		return e.EncodeNil()
	}
	return e.EncodeValue(v.Elem())
}

func decodePtrValue(d *Decoder, v reflect.Value) error {
	if v.IsNil() {
		v.Set(reflect.New(v.Type().Elem()))
	}
	return d.DecodeValue(v.Elem())
}

//------------------------------------------------------------------------------

func encodeStructValue(e *Encoder, v reflect.Value) error {
	return e.encodeStruct(v)
}

func decodeStructValue(d *Decoder, v reflect.Value) error {
	return d.structValue(v)
}

//------------------------------------------------------------------------------

func marshalValue(e *Encoder, v reflect.Value) error {
	marshaler := v.Interface().(Marshaler)
	b, err := marshaler.MarshalMsgpack()
	if err != nil {
		return err
	}
	_, err = e.w.Write(b)
	return err
}

func unmarshalValue(d *Decoder, v reflect.Value) error {
	if v.IsNil() {
		v.Set(reflect.New(v.Type().Elem()))
	}

	b, err := ioutil.ReadAll(d.r)
	if err != nil {
		return err
	}
	unmarshaler := v.Interface().(Unmarshaler)
	return unmarshaler.UnmarshalMsgpack(b)
}

//------------------------------------------------------------------------------

type structCache struct {
	l sync.RWMutex
	m map[reflect.Type]fields
}

func newStructCache() *structCache {
	return &structCache{
		m: make(map[reflect.Type]fields),
	}
}

func (m *structCache) Fields(typ reflect.Type) fields {
	m.l.RLock()
	fs, ok := m.m[typ]
	m.l.RUnlock()
	if !ok {
		m.l.Lock()
		fs, ok = m.m[typ]
		if !ok {
			fs = getFields(typ)
			m.m[typ] = fs
		}
		m.l.Unlock()
	}

	return fs
}

func getFields(typ reflect.Type) fields {
	numField := typ.NumField()
	fs := make(fields, numField)
	for i := 0; i < numField; i++ {
		f := typ.Field(i)

		if f.PkgPath != "" {
			continue
		}

		name, opts := parseTag(f.Tag.Get("msgpack"))
		if name == "-" {
			continue
		}
		if name == "" {
			name = f.Name
		}

		fieldTyp := typ.FieldByIndex(f.Index).Type
		fs[name] = &field{
			index:     f.Index,
			omitEmpty: opts.Contains("omitempty"),

			encoder: getEncoder(fieldTyp),
			decoder: getDecoder(fieldTyp),
		}
	}
	return fs
}

func getEncoder(typ reflect.Type) encoderFunc {
	if encoder, ok := typEncMap[typ]; ok {
		return encoder
	}

	if typ.Implements(marshalerType) {
		return marshalValue
	}

	kind := typ.Kind()
	if kind == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
		return encodeBytesValue
	}

	return valueEncoders[kind]
}

func getDecoder(typ reflect.Type) decoderFunc {
	if decoder, ok := typDecMap[typ]; ok {
		return decoder
	}

	if typ.Implements(unmarshalerType) {
		return unmarshalValue
	}

	kind := typ.Kind()
	if kind == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
		return decodeBytesValue
	}

	return valueDecoders[kind]
}

func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return false
}
<commit_msg>Remove unused var.<commit_after>package msgpack

import (
	"io/ioutil"
	"reflect"
	"sync"
)

var (
	marshalerType   = reflect.TypeOf(new(Marshaler)).Elem()
	unmarshalerType = reflect.TypeOf(new(Unmarshaler)).Elem()
)

var structs = newStructCache()

var valueEncoders []encoderFunc
var valueDecoders []decoderFunc

func init() {
	valueEncoders = []encoderFunc{
		reflect.Bool:          encodeBoolValue,
		reflect.Int:           encodeInt64Value,
		reflect.Int8:          encodeInt64Value,
		reflect.Int16:         encodeInt64Value,
		reflect.Int32:         encodeInt64Value,
		reflect.Int64:         encodeInt64Value,
		reflect.Uint:          encodeUint64Value,
		reflect.Uint8:         encodeUint64Value,
		reflect.Uint16:        encodeUint64Value,
		reflect.Uint32:        encodeUint64Value,
		reflect.Uint64:        encodeUint64Value,
		reflect.Float32:       encodeFloat64Value,
		reflect.Float64:       encodeFloat64Value,
		reflect.Array:         encodeArrayValue,
		reflect.Interface:     encodeInterfaceValue,
		reflect.Map:           encodeMapValue,
		reflect.Ptr:           encodePtrValue,
		reflect.Slice:         encodeSliceValue,
		reflect.String:        encodeStringValue,
		reflect.Struct:        encodeStructValue,
		reflect.UnsafePointer: nil,
	}
	valueDecoders = []decoderFunc{
		reflect.Bool:          decodeBoolValue,
		reflect.Int:           decodeInt64Value,
		reflect.Int8:          decodeInt64Value,
		reflect.Int16:         decodeInt64Value,
		reflect.Int32:         decodeInt64Value,
		reflect.Int64:         decodeInt64Value,
		reflect.Uint:          decodeUint64Value,
		reflect.Uint8:         decodeUint64Value,
		reflect.Uint16:        decodeUint64Value,
		reflect.Uint32:        decodeUint64Value,
		reflect.Uint64:        decodeUint64Value,
		reflect.Float32:       decodeFloat64Value,
		reflect.Float64:       decodeFloat64Value,
		reflect.Array:         decodeArrayValue,
		reflect.Interface:     decodeInterfaceValue,
		reflect.Map:           decodeMapValue,
		reflect.Ptr:           decodePtrValue,
		reflect.Slice:         decodeSliceValue,
		reflect.String:        decodeStringValue,
		reflect.Struct:        decodeStructValue,
		reflect.UnsafePointer: nil,
	}
}

//------------------------------------------------------------------------------

type field struct {
	index     []int
	omitEmpty bool

	encoder encoderFunc
	decoder decoderFunc
}

func (f *field) value(strct reflect.Value) reflect.Value {
	return strct.FieldByIndex(f.index)
}

func (f *field) Omit(strct reflect.Value) bool {
	return f.omitEmpty && isEmptyValue(f.value(strct))
}

func (f *field) EncodeValue(e *Encoder, strct reflect.Value) error {
	return f.encoder(e, f.value(strct))
}

func (f *field) DecodeValue(d *Decoder, strct reflect.Value) error {
	return f.decoder(d, f.value(strct))
}

//------------------------------------------------------------------------------

type fields map[string]*field

//------------------------------------------------------------------------------

func encodeBoolValue(e *Encoder, v reflect.Value) error {
	return e.EncodeBool(v.Bool())
}

func decodeBoolValue(d *Decoder, v reflect.Value) error {
	return d.boolValue(v)
}

//------------------------------------------------------------------------------

func encodeFloat64Value(e *Encoder, v reflect.Value) error {
	return e.EncodeFloat64(v.Float())
}

func decodeFloat64Value(d *Decoder, v reflect.Value) error {
	return d.float64Value(v)
}

//------------------------------------------------------------------------------

func encodeStringValue(e *Encoder, v reflect.Value) error {
	return e.EncodeString(v.String())
}

func decodeStringValue(d *Decoder, v reflect.Value) error {
	return d.stringValue(v)
}

//------------------------------------------------------------------------------

func encodeBytesValue(e *Encoder, v reflect.Value) error {
	return e.EncodeBytes(v.Bytes())
}

func decodeBytesValue(d *Decoder, v reflect.Value) error {
	return d.bytesValue(v)
}

//------------------------------------------------------------------------------

func encodeInt64Value(e *Encoder, v reflect.Value) error {
	return e.EncodeInt64(v.Int())
}

func decodeInt64Value(d *Decoder, v reflect.Value) error {
	return d.int64Value(v)
}

//------------------------------------------------------------------------------

func encodeUint64Value(e *Encoder, v reflect.Value) error {
	return e.EncodeUint64(v.Uint())
}

func decodeUint64Value(d *Decoder, v reflect.Value) error {
	return d.uint64Value(v)
}

//------------------------------------------------------------------------------

func encodeSliceValue(e *Encoder, v reflect.Value) error {
	return e.encodeSlice(v)
}

func decodeSliceValue(d *Decoder, v reflect.Value) error {
	return d.sliceValue(v)
}

//------------------------------------------------------------------------------

func encodeArrayValue(e *Encoder, v reflect.Value) error {
	return e.encodeArray(v)
}

func decodeArrayValue(d *Decoder, v reflect.Value) error {
	return d.sliceValue(v)
}

//------------------------------------------------------------------------------

func encodeInterfaceValue(e *Encoder, v reflect.Value) error {
	if v.IsNil() {
		return e.EncodeNil()
	}
	return e.EncodeValue(v.Elem())
}

func decodeInterfaceValue(d *Decoder, v reflect.Value) error {
	if v.IsNil() {
		return d.interfaceValue(v)
	}
	return d.DecodeValue(v.Elem())
}

//------------------------------------------------------------------------------

func encodeMapValue(e *Encoder, v reflect.Value) error {
	return e.encodeMap(v)
}

func decodeMapValue(d *Decoder, v reflect.Value) error {
	return d.mapValue(v)
}

//------------------------------------------------------------------------------

func encodePtrValue(e *Encoder, v reflect.Value) error {
	if v.IsNil() {
		return e.EncodeNil()
	}
	return e.EncodeValue(v.Elem())
}

func decodePtrValue(d *Decoder, v reflect.Value) error {
	if v.IsNil() {
		v.Set(reflect.New(v.Type().Elem()))
	}
	return d.DecodeValue(v.Elem())
}

//------------------------------------------------------------------------------

func encodeStructValue(e *Encoder, v reflect.Value) error {
	return e.encodeStruct(v)
}

func decodeStructValue(d *Decoder, v reflect.Value) error {
	return d.structValue(v)
}

//------------------------------------------------------------------------------

func marshalValue(e *Encoder, v reflect.Value) error {
	marshaler := v.Interface().(Marshaler)
	b, err := marshaler.MarshalMsgpack()
	if err != nil {
		return err
	}
	_, err = e.w.Write(b)
	return err
}

func unmarshalValue(d *Decoder, v reflect.Value) error {
	if v.IsNil() {
		v.Set(reflect.New(v.Type().Elem()))
	}

	b, err := ioutil.ReadAll(d.r)
	if err != nil {
		return err
	}
	unmarshaler := v.Interface().(Unmarshaler)
	return unmarshaler.UnmarshalMsgpack(b)
}

//------------------------------------------------------------------------------

type structCache struct {
	l sync.RWMutex
	m map[reflect.Type]fields
}

func newStructCache() *structCache {
	return &structCache{
		m: make(map[reflect.Type]fields),
	}
}

func (m *structCache) Fields(typ reflect.Type) fields {
	m.l.RLock()
	fs, ok := m.m[typ]
	m.l.RUnlock()
	if !ok {
		m.l.Lock()
		fs, ok = m.m[typ]
		if !ok {
			fs = getFields(typ)
			m.m[typ] = fs
		}
		m.l.Unlock()
	}

	return fs
}

func getFields(typ reflect.Type) fields {
	numField := typ.NumField()
	fs := make(fields, numField)
	for i := 0; i < numField; i++ {
		f := typ.Field(i)

		if f.PkgPath != "" {
			continue
		}

		name, opts := parseTag(f.Tag.Get("msgpack"))
		if name == "-" {
			continue
		}
		if name == "" {
			name = f.Name
		}

		fieldTyp := typ.FieldByIndex(f.Index).Type
		fs[name] = &field{
			index:     f.Index,
			omitEmpty: opts.Contains("omitempty"),

			encoder: getEncoder(fieldTyp),
			decoder: getDecoder(fieldTyp),
		}
	}
	return fs
}

func getEncoder(typ reflect.Type) encoderFunc {
	if encoder, ok := typEncMap[typ]; ok {
		return encoder
	}

	if typ.Implements(marshalerType) {
		return marshalValue
	}

	kind := typ.Kind()
	if kind == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
		return encodeBytesValue
	}

	return valueEncoders[kind]
}

func getDecoder(typ reflect.Type) decoderFunc {
	if decoder, ok := typDecMap[typ]; ok {
		return decoder
	}

	if typ.Implements(unmarshalerType) {
		return unmarshalValue
	}

	kind := typ.Kind()
	if kind == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
		return decodeBytesValue
	}

	return valueDecoders[kind]
}

func isEmptyValue(v reflect.Value) bool {
	switch v.Kind() {
	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
		return v.Len() == 0
	case reflect.Bool:
		return !v.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return v.Int() == 0
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return v.Uint() == 0
	case reflect.Float32, reflect.Float64:
		return v.Float() == 0
	case reflect.Interface, reflect.Ptr:
		return v.IsNil()
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/gokyle/sshkey"
	"github.com/jessevdk/go-flags"

	"github.com/tg123/sshpiper/sshpiperd/auditor"
	"github.com/tg123/sshpiper/sshpiperd/challenger"
	"github.com/tg123/sshpiper/sshpiperd/registry"
	"github.com/tg123/sshpiper/sshpiperd/upstream"
)

type subCommand struct{ callback func(args []string) error }

func (s *subCommand) Execute(args []string) error {
	return s.callback(args)
}

func addSubCommand(parser *flags.Parser, name, desc string, callback func(args []string) error) {
	_, err := parser.AddCommand(name, desc, "", &subCommand{callback})

	if err != nil {
		panic(err)
	}
}

func addOpt(parser *flags.Parser, name string, data interface{}) {
	_, err := parser.AddGroup(name, "", data)

	if err != nil {
		panic(err)
	}
}

func addPlugins(parser *flags.Parser, name string, pluginNames []string, getter func(n string) registry.Plugin) {
	for _, n := range pluginNames {

		p := getter(n)

		opt := p.GetOpts()

		if opt == nil {
			continue
		}

		_, err := parser.AddGroup(name+"."+p.GetName(), "", opt)

		if err != nil {
			panic(err)
		}
	}
}

func populateFromConfig(ini *flags.IniParser, data interface{}, longopt string) error {

	parser := flags.NewParser(data, flags.IgnoreUnknown)
	parser.Parse()

	o := parser.FindOptionByLongName(longopt)
	file := o.Value().(flags.Filename)
	err := ini.ParseFile(string(file))

	if err != nil {
		// set by user
		if !o.IsSetDefault() {
			return err
		}
	}

	return nil
}

func main() {

	parser := flags.NewNamedParser("sshpiperd", flags.Default)
	parser.SubcommandsOptional = true
	parser.LongDescription = "SSH Piper works as a proxy-like ware, and route connections by username, src ip , etc. Please see <https://github.com/tg123/sshpiper> for more information"

	// version
	addSubCommand(parser, "version", "show version", func(args []string) error {
		showVersion()
		return nil
	})

	dumpConfig := func() {
		ini := flags.NewIniParser(parser)
		ini.Write(os.Stdout, flags.IniIncludeDefaults)
	}

	// dumpini
	addSubCommand(parser, "dumpconfig", "dump current config ini to stdout", func(args []string) error {
		dumpConfig()
		return nil
	})

	// manpage
	addSubCommand(parser, "manpage", "write man page to stdout", func(args []string) error {
		parser.WriteManPage(os.Stdout)
		return nil
	})

	// plugins
	addSubCommand(parser, "plugins", "list support plugins, e.g. sshpiperd plugis upstream", func(args []string) error {

		output := func(all []string) {
			for _, p := range all {
				fmt.Println(p)
			}

		}

		if len(args) == 0 {
			args = []string{"upstream", "challenger", "auditor"}
		}

		for _, n := range args {
			switch n {
			case "upstream":
				output(upstream.All())
			case "challenger":
				output(challenger.All())
			case "auditor":
				output(auditor.All())
			}
		}

		return nil
	})

	// options, for snap only at the moment
	addSubCommand(parser, "options", "list all options", func(args []string) error {
		for _, g := range parser.Groups() {
			for _, o := range g.Options() {
				fmt.Println(o.LongName)
			}
		}

		return nil
	})

	// generate key tools
	addSubCommand(parser, "genkey", "generate a 2048 rsa key to stdout", func(args []string) error {
		key, err := sshkey.GenerateKey(sshkey.KEY_RSA, 2048)
		if err != nil {
			return err
		}

		out, err := sshkey.MarshalPrivate(key, "")
		if err != nil {
			return err
		}

		_, err = fmt.Fprint(os.Stdout, string(out))

		return err
	})

	config := &struct {
		piperdConfig

		loggerConfig

		// need to be shown in help, or will be moved to populate config
		ConfigFile flags.Filename `long:"config" description:"Config file path. Will be overwriten by arg options and environment variables" default:"/etc/sshpiperd.ini" env:"SSHPIPERD_CONFIG_FILE" no-ini:"true"`
	}{}

	addOpt(parser, "sshpiperd", config)

	addPlugins(parser, "upstream", upstream.All(), func(n string) registry.Plugin { return upstream.Get(n) })
	addPlugins(parser, "challenger", challenger.All(), func(n string) registry.Plugin { return challenger.Get(n) })
	addPlugins(parser, "auditor", auditor.All(), func(n string) registry.Plugin { return auditor.Get(n) })

	// populate by config
	ini := flags.NewIniParser(parser)
	err := populateFromConfig(ini, config, "config")
	if err != nil {
		fmt.Println(fmt.Sprintf("load config file failed %v", err))
		os.Exit(1)
	}

	parser.CommandHandler = func(command flags.Commander, args []string) error {

		// no subcommand called, start to serve
		if command == nil {

			if len(args) > 0 {
				return fmt.Errorf("unknown command %v", args)
			}

			showVersion()
			dumpConfig()

			return startPiper(&config.piperdConfig, config.createLogger())
		}

		return command.Execute(args)
	}

	parser.Parse()
}
<commit_msg>dump only used config when starting<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/gokyle/sshkey"
	"github.com/jessevdk/go-flags"

	"github.com/tg123/sshpiper/sshpiperd/auditor"
	"github.com/tg123/sshpiper/sshpiperd/challenger"
	"github.com/tg123/sshpiper/sshpiperd/registry"
	"github.com/tg123/sshpiper/sshpiperd/upstream"
)

type subCommand struct{ callback func(args []string) error }

func (s *subCommand) Execute(args []string) error {
	return s.callback(args)
}

func addSubCommand(parser *flags.Parser, name, desc string, callback func(args []string) error) {
	_, err := parser.AddCommand(name, desc, "", &subCommand{callback})

	if err != nil {
		panic(err)
	}
}

func addOpt(parser *flags.Parser, name string, data interface{}) {
	_, err := parser.AddGroup(name, "", data)

	if err != nil {
		panic(err)
	}
}

func addPlugins(parser *flags.Parser, name string, pluginNames []string, getter func(n string) registry.Plugin) {
	for _, n := range pluginNames {

		p := getter(n)

		opt := p.GetOpts()

		if opt == nil {
			continue
		}

		_, err := parser.AddGroup(name+"."+p.GetName(), "", opt)

		if err != nil {
			panic(err)
		}
	}
}

func populateFromConfig(ini *flags.IniParser, data interface{}, longopt string) error {

	parser := flags.NewParser(data, flags.IgnoreUnknown)
	parser.Parse()

	o := parser.FindOptionByLongName(longopt)
	file := o.Value().(flags.Filename)
	err := ini.ParseFile(string(file))

	if err != nil {
		// set by user
		if !o.IsSetDefault() {
			return err
		}
	}

	return nil
}

func main() {

	parser := flags.NewNamedParser("sshpiperd", flags.Default)
	parser.SubcommandsOptional = true
	parser.LongDescription = "SSH Piper works as a proxy-like ware, and route connections by username, src ip , etc. Please see <https://github.com/tg123/sshpiper> for more information"

	// version
	addSubCommand(parser, "version", "show version", func(args []string) error {
		showVersion()
		return nil
	})

	dumpConfig := func() {
		ini := flags.NewIniParser(parser)
		ini.Write(os.Stdout, flags.IniIncludeDefaults)
	}

	// dumpini
	addSubCommand(parser, "dumpconfig", "dump current config ini to stdout", func(args []string) error {
		dumpConfig()
		return nil
	})

	// manpage
	addSubCommand(parser, "manpage", "write man page to stdout", func(args []string) error {
		parser.WriteManPage(os.Stdout)
		return nil
	})

	// plugins
	addSubCommand(parser, "plugins", "list support plugins, e.g. sshpiperd plugis upstream", func(args []string) error {

		output := func(all []string) {
			for _, p := range all {
				fmt.Println(p)
			}

		}

		if len(args) == 0 {
			args = []string{"upstream", "challenger", "auditor"}
		}

		for _, n := range args {
			switch n {
			case "upstream":
				output(upstream.All())
			case "challenger":
				output(challenger.All())
			case "auditor":
				output(auditor.All())
			}
		}

		return nil
	})

	// options, for snap only at the moment
	addSubCommand(parser, "options", "list all options", func(args []string) error {
		for _, g := range parser.Groups() {
			for _, o := range g.Options() {
				fmt.Println(o.LongName)
			}
		}

		return nil
	})

	// generate key tools
	addSubCommand(parser, "genkey", "generate a 2048 rsa key to stdout", func(args []string) error {
		key, err := sshkey.GenerateKey(sshkey.KEY_RSA, 2048)
		if err != nil {
			return err
		}

		out, err := sshkey.MarshalPrivate(key, "")
		if err != nil {
			return err
		}

		_, err = fmt.Fprint(os.Stdout, string(out))

		return err
	})

	config := &struct {
		piperdConfig

		loggerConfig

		// need to be shown in help, or will be moved to populate config
		ConfigFile flags.Filename `long:"config" description:"Config file path. Will be overwriten by arg options and environment variables" default:"/etc/sshpiperd.ini" env:"SSHPIPERD_CONFIG_FILE" no-ini:"true"`
	}{}

	addOpt(parser, "sshpiperd", config)

	addPlugins(parser, "upstream", upstream.All(), func(n string) registry.Plugin { return upstream.Get(n) })
	addPlugins(parser, "challenger", challenger.All(), func(n string) registry.Plugin { return challenger.Get(n) })
	addPlugins(parser, "auditor", auditor.All(), func(n string) registry.Plugin { return auditor.Get(n) })

	// populate by config
	ini := flags.NewIniParser(parser)
	err := populateFromConfig(ini, config, "config")
	if err != nil {
		fmt.Println(fmt.Sprintf("load config file failed %v", err))
		os.Exit(1)
	}

	parser.CommandHandler = func(command flags.Commander, args []string) error {

		// no subcommand called, start to serve
		if command == nil {

			if len(args) > 0 {
				return fmt.Errorf("unknown command %v", args)
			}

			showVersion()

			// dump used configure only
			{
				fmt.Println()
				for _, gk := range []string{"sshpiperd", "upstream." + config.UpstreamDriver, "challenger." + config.ChallengerDriver, "auditor." + config.AuditorDriver} {

					g := parser.Group.Find(gk)
					if g == nil {
						continue
					}

					fmt.Println("[" + g.ShortDescription + "]")
					for _, o := range g.Options() {
						fmt.Printf("%v = %v", o.LongName, o.Value())
						fmt.Println()
					}
					fmt.Println()
				}
			}

			return startPiper(&config.piperdConfig, config.createLogger())
		}

		return command.Execute(args)
	}

	parser.Parse()
}
<|endoftext|>


<commit_before>package kong

import (
	"fmt"
	"net/http"
)

type ConsumersPlugins struct {
	ACL *ConsumersACLService
	JWT *ConsumersJWTService
}

type ConsumersACLService service

type ConsumerACLConfigs struct {
	Data  []ConsumerACLConfig `json:"data,omitempty"`
	Total int                 `json:"total,omitempty"`
}

type ConsumerACLConfig struct {
	ConsumerID string `json:"consumer_id,omitempty"`
	CreatedAt  int    `json:"created_at,omitempty"`
	Group      string `json:"group,omitempty"`
	ID         string `json:"id,omitempty"`
}

func (s *ConsumersACLService) Post(consumer string, config *ConsumerACLConfig) (*http.Response, error) {
	u := fmt.Sprintf("consumers/%v/acls", consumer)

	req, err := s.client.NewRequest("POST", u, config)
	if err != nil {
		return nil, err
	}

	resp, err := s.client.Do(req, nil)

	return resp, err
}

func (s *ConsumersACLService) Get(consumer string) (*ConsumerACLConfigs, *http.Response, error) {
	u := fmt.Sprintf("consumers/%v/acls", consumer)

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	uResp := new(ConsumerACLConfigs)
	resp, err := s.client.Do(req, uResp)
	if err != nil {
		return nil, resp, err
	}

	return uResp, resp, err
}

func (s *ConsumersACLService) Delete(consumer, id string) (*http.Response, error) {
	u := fmt.Sprintf("consumers/%v/acls/%v", consumer, id)

	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return nil, err
	}

	resp, err := s.client.Do(req, nil)
	if err != nil {
		return resp, err
	}

	return resp, err
}

type ConsumersJWTService service

type ConsumerJWTConfigs struct {
	Data []ConsumerJWTConfig `json:"data,omitempty"`
	Total int `json:"total,omitemtpy"`
}

type ConsumerJWTConfig struct {
	Key string `json:"key,omitempty"`
	Algorithm string `json:"algorithm,omitempty"`
	RSAPublicKey string `json:"rsa_public_key,omitempty"`
	Secret string `json:"secret,omitempty"`
}

func (s *ConsumersJWTService) Post(consumer string, config *ConsumerJWTConfig) (*http.Response, error) {
	u := fmt.Sprintf("consumers/%v/jwt", consumer)

	req, err := s.client.NewRequest("POST", u, config)
	if err != nil {
		return nil, err
	}

	resp, err := s.client.Do(req, nil)

	return resp, err
}

func (s *ConsumersJWTService) Get(consumer string) (*ConsumerJWTConfigs, *http.Response, error) {
	u := fmt.Sprintf("consumers/%v/jwt", consumer)

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	uResp := new(ConsumerJWTConfigs)
	resp, err := s.client.Do(req, uResp)
	if err != nil {
		return nil, resp, err
	}

	return uResp, resp, err
}

func (s *ConsumersJWTService) Delete(consumer, id string) (*http.Response, error) {
	u := fmt.Sprintf("consumers/%v/jwt/%v", consumer, id)

	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return nil, err
	}

	resp, err := s.client.Do(req, nil)
	if err != nil {
		return resp, err
	}

	return resp, err
}<commit_msg>go fmt<commit_after>package kong

import (
	"fmt"
	"net/http"
)

type ConsumersPlugins struct {
	ACL *ConsumersACLService
	JWT *ConsumersJWTService
}

type ConsumersACLService service

type ConsumerACLConfigs struct {
	Data  []ConsumerACLConfig `json:"data,omitempty"`
	Total int                 `json:"total,omitempty"`
}

type ConsumerACLConfig struct {
	ConsumerID string `json:"consumer_id,omitempty"`
	CreatedAt  int    `json:"created_at,omitempty"`
	Group      string `json:"group,omitempty"`
	ID         string `json:"id,omitempty"`
}

func (s *ConsumersACLService) Post(consumer string, config *ConsumerACLConfig) (*http.Response, error) {
	u := fmt.Sprintf("consumers/%v/acls", consumer)

	req, err := s.client.NewRequest("POST", u, config)
	if err != nil {
		return nil, err
	}

	resp, err := s.client.Do(req, nil)

	return resp, err
}

func (s *ConsumersACLService) Get(consumer string) (*ConsumerACLConfigs, *http.Response, error) {
	u := fmt.Sprintf("consumers/%v/acls", consumer)

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	uResp := new(ConsumerACLConfigs)
	resp, err := s.client.Do(req, uResp)
	if err != nil {
		return nil, resp, err
	}

	return uResp, resp, err
}

func (s *ConsumersACLService) Delete(consumer, id string) (*http.Response, error) {
	u := fmt.Sprintf("consumers/%v/acls/%v", consumer, id)

	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return nil, err
	}

	resp, err := s.client.Do(req, nil)
	if err != nil {
		return resp, err
	}

	return resp, err
}

type ConsumersJWTService service

type ConsumerJWTConfigs struct {
	Data  []ConsumerJWTConfig `json:"data,omitempty"`
	Total int                 `json:"total,omitemtpy"`
}

type ConsumerJWTConfig struct {
	Key          string `json:"key,omitempty"`
	Algorithm    string `json:"algorithm,omitempty"`
	RSAPublicKey string `json:"rsa_public_key,omitempty"`
	Secret       string `json:"secret,omitempty"`
}

func (s *ConsumersJWTService) Post(consumer string, config *ConsumerJWTConfig) (*http.Response, error) {
	u := fmt.Sprintf("consumers/%v/jwt", consumer)

	req, err := s.client.NewRequest("POST", u, config)
	if err != nil {
		return nil, err
	}

	resp, err := s.client.Do(req, nil)

	return resp, err
}

func (s *ConsumersJWTService) Get(consumer string) (*ConsumerJWTConfigs, *http.Response, error) {
	u := fmt.Sprintf("consumers/%v/jwt", consumer)

	req, err := s.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	uResp := new(ConsumerJWTConfigs)
	resp, err := s.client.Do(req, uResp)
	if err != nil {
		return nil, resp, err
	}

	return uResp, resp, err
}

func (s *ConsumersJWTService) Delete(consumer, id string) (*http.Response, error) {
	u := fmt.Sprintf("consumers/%v/jwt/%v", consumer, id)

	req, err := s.client.NewRequest("DELETE", u, nil)
	if err != nil {
		return nil, err
	}

	resp, err := s.client.Do(req, nil)
	if err != nil {
		return resp, err
	}

	return resp, err
}
<|endoftext|>


<commit_before>package kontena

import (
	"fmt"
	"os"

	"github.com/jakubknejzlik/kontena-git-cli/model"
	"github.com/jakubknejzlik/kontena-git-cli/utils"
)

// StackList ...
func (c *Client) StackList() ([]string, error) {
	var list []string
	res, err := utils.Run("kontena stack ls -q")

	if err != nil {
		return list, err
	}

	return utils.SplitString(string(res), "\n"), nil
}

// StackListInGrid ...
func (c *Client) StackListInGrid(grid string) ([]string, error) {
	var list []string
	res, err := utils.Run(fmt.Sprintf("kontena stack ls --grid %s -q", grid))

	if err != nil {
		return list, err
	}

	return utils.SplitString(string(res), "\n"), nil
}

// StackExists ...
func (c *Client) StackExists(stack string) bool {
	stacks, err := c.StackList()
	if err != nil {
		return false
	}

	for _, _stack := range stacks {
		if _stack == stack {
			return true
		}
	}

	return false
}

// StackExistsInGrid ...
func (c *Client) StackExistsInGrid(grid, stack string) bool {
	stacks, err := c.StackListInGrid(grid)
	if err != nil {
		return false
	}

	for _, _stack := range stacks {
		if _stack == stack {
			return true
		}
	}

	return false
}

// StackInstallOrUpgrade ...
func (c *Client) StackInstallOrUpgrade(stack model.KontenaStack) error {
	if c.StackExists(stack.Name) {
		return c.StackUpgrade(stack)
	}
	return c.StackInstall(stack)
}

// StackInstallOrUpgradeInGrid ...
func (c *Client) StackInstallOrUpgradeInGrid(grid string, stack model.KontenaStack) error {
	if c.StackExistsInGrid(grid, stack.Name) {
		return c.StackUpgradeInGrid(grid, stack)
	}
	return c.StackInstallInGrid(grid, stack)
}

// StackDeploy ...
func (c *Client) StackDeploy(name string) error {
	return utils.RunInteractive(fmt.Sprintf("kontena stack deploy %s", name))
}

// StackDeployInGrid ...
func (c *Client) StackDeployInGrid(grid, name string) error {
	return utils.RunInteractive(fmt.Sprintf("kontena stack deploy --grid %s %s", grid, name))
}

// StackInstall ...
func (c *Client) StackInstall(stack model.KontenaStack) error {
	return c.stackAction("install", stack.Name, stack)
}

// StackInstallInGrid ...
func (c *Client) StackInstallInGrid(grid string, stack model.KontenaStack) error {
	return c.stackActionInGrid("install", grid, stack.Name, stack)
}

// StackUpgrade ...
func (c *Client) StackUpgrade(stack model.KontenaStack) error {
	return c.stackAction("upgrade", stack.Name, stack)
}

// StackUpgradeInGrid ...
func (c *Client) StackUpgradeInGrid(grid string, stack model.KontenaStack) error {
	return c.stackActionInGrid("upgrade", grid, stack.Name, stack)
}

// StackRemove ...
func (c *Client) StackRemove(name string) error {
	return utils.RunInteractive(fmt.Sprintf("kontena stack remove --force %s", name))
}

// StackRemoveFromGrid ...
func (c *Client) StackRemoveFromGrid(grid, name string) error {
	return utils.RunInteractive(fmt.Sprintf("kontena stack remove --grid %s --force %s", grid, name))
}

func (c *Client) stackAction(action, name string, stack model.KontenaStack) error {
	dsPath, err := stack.ExportTemporary(true)
	if err != nil {
		return err
	}

	defer os.Remove(dsPath)

	cmd := fmt.Sprintf("kontena stack upgrade --no-deploy %s %s", name, dsPath)
	if action == "install" {
		cmd = fmt.Sprintf("kontena stack install --name %s %s", name, dsPath)
	}
	return utils.RunInteractive(cmd)
}

func (c *Client) stackActionInGrid(grid, action, name string, stack model.KontenaStack) error {
	dsPath, err := stack.ExportTemporary(true)
	if err != nil {
		return err
	}

	defer os.Remove(dsPath)

	cmd := fmt.Sprintf("kontena stack upgrade --force --grid %s --no-deploy %s %s", grid, name, dsPath)
	if action == "install" {
		cmd = fmt.Sprintf("kontena stack install --grid %s --name %s %s", grid, name, dsPath)
	}
	return utils.RunInteractive(cmd)
}
<commit_msg>Add force upgrade to stack install<commit_after>package kontena

import (
	"fmt"
	"os"

	"github.com/jakubknejzlik/kontena-git-cli/model"
	"github.com/jakubknejzlik/kontena-git-cli/utils"
)

// StackList ...
func (c *Client) StackList() ([]string, error) {
	var list []string
	res, err := utils.Run("kontena stack ls -q")

	if err != nil {
		return list, err
	}

	return utils.SplitString(string(res), "\n"), nil
}

// StackListInGrid ...
func (c *Client) StackListInGrid(grid string) ([]string, error) {
	var list []string
	res, err := utils.Run(fmt.Sprintf("kontena stack ls --grid %s -q", grid))

	if err != nil {
		return list, err
	}

	return utils.SplitString(string(res), "\n"), nil
}

// StackExists ...
func (c *Client) StackExists(stack string) bool {
	stacks, err := c.StackList()
	if err != nil {
		return false
	}

	for _, _stack := range stacks {
		if _stack == stack {
			return true
		}
	}

	return false
}

// StackExistsInGrid ...
func (c *Client) StackExistsInGrid(grid, stack string) bool {
	stacks, err := c.StackListInGrid(grid)
	if err != nil {
		return false
	}

	for _, _stack := range stacks {
		if _stack == stack {
			return true
		}
	}

	return false
}

// StackInstallOrUpgrade ...
func (c *Client) StackInstallOrUpgrade(stack model.KontenaStack) error {
	if c.StackExists(stack.Name) {
		return c.StackUpgrade(stack)
	}
	return c.StackInstall(stack)
}

// StackInstallOrUpgradeInGrid ...
func (c *Client) StackInstallOrUpgradeInGrid(grid string, stack model.KontenaStack) error {
	if c.StackExistsInGrid(grid, stack.Name) {
		return c.StackUpgradeInGrid(grid, stack)
	}
	return c.StackInstallInGrid(grid, stack)
}

// StackDeploy ...
func (c *Client) StackDeploy(name string) error {
	return utils.RunInteractive(fmt.Sprintf("kontena stack deploy %s", name))
}

// StackDeployInGrid ...
func (c *Client) StackDeployInGrid(grid, name string) error {
	return utils.RunInteractive(fmt.Sprintf("kontena stack deploy --grid %s %s", grid, name))
}

// StackInstall ...
func (c *Client) StackInstall(stack model.KontenaStack) error {
	return c.stackAction("install", stack.Name, stack)
}

// StackInstallInGrid ...
func (c *Client) StackInstallInGrid(grid string, stack model.KontenaStack) error {
	return c.stackActionInGrid("install", grid, stack.Name, stack)
}

// StackUpgrade ...
func (c *Client) StackUpgrade(stack model.KontenaStack) error {
	return c.stackAction("upgrade", stack.Name, stack)
}

// StackUpgradeInGrid ...
func (c *Client) StackUpgradeInGrid(grid string, stack model.KontenaStack) error {
	return c.stackActionInGrid("upgrade", grid, stack.Name, stack)
}

// StackRemove ...
func (c *Client) StackRemove(name string) error {
	return utils.RunInteractive(fmt.Sprintf("kontena stack remove --force %s", name))
}

// StackRemoveFromGrid ...
func (c *Client) StackRemoveFromGrid(grid, name string) error {
	return utils.RunInteractive(fmt.Sprintf("kontena stack remove --grid %s --force %s", grid, name))
}

func (c *Client) stackAction(action, name string, stack model.KontenaStack) error {
	dsPath, err := stack.ExportTemporary(true)
	if err != nil {
		return err
	}

	defer os.Remove(dsPath)

	cmd := fmt.Sprintf("kontena stack upgrade --force --no-deploy %s %s", name, dsPath)
	if action == "install" {
		cmd = fmt.Sprintf("kontena stack install --name %s %s", name, dsPath)
	}
	return utils.RunInteractive(cmd)
}

func (c *Client) stackActionInGrid(grid, action, name string, stack model.KontenaStack) error {
	dsPath, err := stack.ExportTemporary(true)
	if err != nil {
		return err
	}

	defer os.Remove(dsPath)

	cmd := fmt.Sprintf("kontena stack upgrade --force --grid %s --no-deploy %s %s", grid, name, dsPath)
	if action == "install" {
		cmd = fmt.Sprintf("kontena stack install --grid %s --name %s %s", grid, name, dsPath)
	}
	return utils.RunInteractive(cmd)
}
<|endoftext|>


<commit_before>package static

import (
	"bytes"
	"compress/gzip"
	"encoding/base64"
	"errors"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"sort"
	"time"
)

// byName implements sort.Interface.
type byName []os.FileInfo

func (f byName) Len() int           { return len(f) }
func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }

// DirFile contains the static directory and file content info
type DirFile struct {
	Path       string
	Name       string
	Size       int64
	Mode       os.FileMode
	ModTime    int64
	IsDir      bool
	Compressed string
	Files      []*DirFile
}

// Files contains a full instance of a static file collection
type Files struct {
	absPkgPath string
	dir        Dir
}

// File contains the static FileInfo
type file struct {
	data         []byte
	path         string
	name         string
	size         int64
	mode         os.FileMode
	modTime      int64
	isDir        bool
	files        []*file
	lastDirIndex int
}

// Dir implements the FileSystem interface
type Dir struct {
	useStaticFiles bool
	files          map[string]*file
}

type httpFile struct {
	*bytes.Reader
	*file
}

// Config contains information about how extracting the data should behave
type Config struct {
	UseStaticFiles bool
	AbsPkgPath     string // the Absolute package path used for local file reading when UseStaticFiles is false
}

// Open returns the FileSystem DIR
func (dir Dir) Open(name string) (http.File, error) {

	if dir.useStaticFiles {
		f, found := dir.files[path.Clean(name)]
		if !found {
			return nil, os.ErrNotExist
		}

		return f.File()
	}

	return os.Open(name)
}

// File returns an http.File or error
func (f file) File() (http.File, error) {

	// if production read filesystem file
	return &httpFile{
		bytes.NewReader(f.data),
		&f,
	}, nil
}

// Close closes the File, rendering it unusable for I/O. It returns an error, if any.
func (f file) Close() error {
	return nil
}

// Readdir returns nil fileinfo and an error because the static FileSystem does not store directories
func (f file) Readdir(count int) ([]os.FileInfo, error) {

	if !f.IsDir() {
		return nil, errors.New("not a directory")
	}

	var files []os.FileInfo

	if count <= 0 {
		files = make([]os.FileInfo, len(f.files))
		count = len(f.files)
		f.lastDirIndex = 0
	} else {
		files = make([]os.FileInfo, count)
	}

	if f.lastDirIndex >= len(f.files) {
		return nil, io.EOF
	}

	if count+f.lastDirIndex >= len(f.files) {
		count = len(f.files)
	}

	for i := f.lastDirIndex; i < count; i++ {
		files = append(files, *f.files[i])
	}

	return files, nil
}

// Stat returns the FileInfo structure describing file. If there is an error, it will be of type *PathError.
func (f file) Stat() (os.FileInfo, error) {
	return f, nil
}

// Name returns the name of the file as presented to Open.
func (f file) Name() string {
	return f.name
}

// Size length in bytes for regular files; system-dependent for others
func (f file) Size() int64 {
	return f.size
}

// Mode returns file mode bits
func (f file) Mode() os.FileMode {
	mode := os.FileMode(0644)
	if f.IsDir() {
		return mode | os.ModeDir
	}
	return mode
}

// ModTime returns the files modification time
func (f file) ModTime() time.Time {
	return time.Unix(f.modTime, 0)
}

// IsDir reports whether f describes a directory.
func (f file) IsDir() bool {
	return f.isDir
}

// Sys returns the underlying data source (can return nil)
func (f file) Sys() interface{} {
	return f
}

// New create a new static file instance.
func New(config *Config, dirFile *DirFile) (*Files, error) {

	files := map[string]*file{}

	if config.UseStaticFiles {
		processFiles(files, dirFile)
	} else {
		if !filepath.IsAbs(config.AbsPkgPath) {
			return nil, errors.New("AbsPkgPath is required when not using static files otherwise the static package has no idea where to grab local files from when your package is used from within another package.")
		}
	}

	return &Files{
		absPkgPath: config.AbsPkgPath,
		dir: Dir{
			useStaticFiles: config.UseStaticFiles,
			files:          files,
		},
	}, nil
}

func processFiles(files map[string]*file, dirFile *DirFile) *file {

	f := &file{
		path:    dirFile.Path,
		name:    dirFile.Name,
		size:    dirFile.Size,
		mode:    dirFile.Mode,
		modTime: dirFile.ModTime,
		isDir:   dirFile.IsDir,
		files:   []*file{},
	}

	files[f.path] = f

	if dirFile.IsDir {
		for _, nestedFile := range dirFile.Files {
			resultFile := processFiles(files, nestedFile)
			f.files = append(f.files, resultFile)
		}

		return f
	}

	// decompress file contents
	b64 := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(dirFile.Compressed))
	reader, err := gzip.NewReader(b64)
	if err != nil {
		log.Fatal(err)
	}

	f.data, err = ioutil.ReadAll(reader)
	if err != nil {
		log.Fatal(err)
	}

	return f
}

// FS returns an http.FileSystem object for serving files over http
func (f *Files) FS() http.FileSystem {
	return f.dir
}

func (f *Files) determinePath(name string) string {
	if f.dir.useStaticFiles {
		return name
	}

	return f.absPkgPath + name
}

// GetHTTPFile returns an http.File object
func (f *Files) GetHTTPFile(filename string) (http.File, error) {
	return f.dir.Open(f.determinePath(filename))
}

// ReadFile returns a files contents as []byte from the filesystem, static or local
func (f *Files) ReadFile(filename string) ([]byte, error) {

	file, err := f.dir.Open(f.determinePath(filename))
	if err != nil {
		return nil, err
	}

	return ioutil.ReadAll(file)
}

// Readdir reads the directory named by dirname and returns
// a list of sorted directory entries.
func (f *Files) Readdir(dirname string) ([]os.FileInfo, error) {

	file, err := f.dir.Open(f.determinePath(dirname))
	if err != nil {
		return nil, err
	}

	results, err := file.Readdir(-1)
	if err != nil {
		return nil, err
	}

	sort.Sort(byName(results))

	return results, nil
}

// ReadFiles returns a directories file contents as a map[string][]byte from the filesystem, static or local
func (f *Files) ReadFiles(dirname string, recursive bool) (map[string][]byte, error) {

	dirname = f.determinePath(dirname)

	results := map[string][]byte{}

	file, err := f.dir.Open(dirname)
	if err != nil {
		return nil, err
	}

	if err = f.readFilesRecursive(dirname, file, results, recursive); err != nil {
		return nil, err
	}

	return results, nil
}

func (f *Files) readFilesRecursive(dirname string, file http.File, results map[string][]byte, recursive bool) error {

	files, err := file.Readdir(-1)
	if err != nil {
		return err
	}

	var fpath string

	for _, fi := range files {

		fpath = dirname + fi.Name()

		newFile, err := f.dir.Open(fpath)
		if err != nil {
			return err
		}

		if fi.IsDir() {

			if !recursive {
				continue
			}

			err := f.readFilesRecursive(fpath, newFile, results, recursive)
			if err != nil {
				return err
			}

			continue
		}

		results[fpath], err = ioutil.ReadAll(newFile)
		if err != nil {
			return err
		}
	}

	return nil
}
<commit_msg>change my mind about naming<commit_after>package static

import (
	"bytes"
	"compress/gzip"
	"encoding/base64"
	"errors"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"sort"
	"time"
)

// byName implements sort.Interface.
type byName []os.FileInfo

func (f byName) Len() int           { return len(f) }
func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }

// DirFile contains the static directory and file content info
type DirFile struct {
	Path       string
	Name       string
	Size       int64
	Mode       os.FileMode
	ModTime    int64
	IsDir      bool
	Compressed string
	Files      []*DirFile
}

// Files contains a full instance of a static file collection
type Files struct {
	absPkgPath string
	dir        Dir
}

// File contains the static FileInfo
type file struct {
	data         []byte
	path         string
	name         string
	size         int64
	mode         os.FileMode
	modTime      int64
	isDir        bool
	files        []*file
	lastDirIndex int
}

// Dir implements the FileSystem interface
type Dir struct {
	useStaticFiles bool
	files          map[string]*file
}

type httpFile struct {
	*bytes.Reader
	*file
}

// Config contains information about how extracting the data should behave
type Config struct {
	UseStaticFiles bool
	AbsPkgPath     string // the Absolute package path used for local file reading when UseStaticFiles is false
}

// Open returns the FileSystem DIR
func (dir Dir) Open(name string) (http.File, error) {

	if dir.useStaticFiles {
		f, found := dir.files[path.Clean(name)]
		if !found {
			return nil, os.ErrNotExist
		}

		return f.File()
	}

	return os.Open(name)
}

// File returns an http.File or error
func (f file) File() (http.File, error) {

	// if production read filesystem file
	return &httpFile{
		bytes.NewReader(f.data),
		&f,
	}, nil
}

// Close closes the File, rendering it unusable for I/O. It returns an error, if any.
func (f file) Close() error {
	return nil
}

// Readdir returns nil fileinfo and an error because the static FileSystem does not store directories
func (f file) Readdir(count int) ([]os.FileInfo, error) {

	if !f.IsDir() {
		return nil, errors.New("not a directory")
	}

	var files []os.FileInfo

	if count <= 0 {
		files = make([]os.FileInfo, len(f.files))
		count = len(f.files)
		f.lastDirIndex = 0
	} else {
		files = make([]os.FileInfo, count)
	}

	if f.lastDirIndex >= len(f.files) {
		return nil, io.EOF
	}

	if count+f.lastDirIndex >= len(f.files) {
		count = len(f.files)
	}

	for i := f.lastDirIndex; i < count; i++ {
		files = append(files, *f.files[i])
	}

	return files, nil
}

// Stat returns the FileInfo structure describing file. If there is an error, it will be of type *PathError.
func (f file) Stat() (os.FileInfo, error) {
	return f, nil
}

// Name returns the name of the file as presented to Open.
func (f file) Name() string {
	return f.name
}

// Size length in bytes for regular files; system-dependent for others
func (f file) Size() int64 {
	return f.size
}

// Mode returns file mode bits
func (f file) Mode() os.FileMode {
	mode := os.FileMode(0644)
	if f.IsDir() {
		return mode | os.ModeDir
	}
	return mode
}

// ModTime returns the files modification time
func (f file) ModTime() time.Time {
	return time.Unix(f.modTime, 0)
}

// IsDir reports whether f describes a directory.
func (f file) IsDir() bool {
	return f.isDir
}

// Sys returns the underlying data source (can return nil)
func (f file) Sys() interface{} {
	return f
}

// New create a new static file instance.
func New(config *Config, dirFile *DirFile) (*Files, error) {

	files := map[string]*file{}

	if config.UseStaticFiles {
		processFiles(files, dirFile)
	} else {
		if !filepath.IsAbs(config.AbsPkgPath) {
			return nil, errors.New("AbsPkgPath is required when not using static files otherwise the static package has no idea where to grab local files from when your package is used from within another package.")
		}
	}

	return &Files{
		absPkgPath: config.AbsPkgPath,
		dir: Dir{
			useStaticFiles: config.UseStaticFiles,
			files:          files,
		},
	}, nil
}

func processFiles(files map[string]*file, dirFile *DirFile) *file {

	f := &file{
		path:    dirFile.Path,
		name:    dirFile.Name,
		size:    dirFile.Size,
		mode:    dirFile.Mode,
		modTime: dirFile.ModTime,
		isDir:   dirFile.IsDir,
		files:   []*file{},
	}

	files[f.path] = f

	if dirFile.IsDir {
		for _, nestedFile := range dirFile.Files {
			resultFile := processFiles(files, nestedFile)
			f.files = append(f.files, resultFile)
		}

		return f
	}

	// decompress file contents
	b64 := base64.NewDecoder(base64.StdEncoding, bytes.NewBufferString(dirFile.Compressed))
	reader, err := gzip.NewReader(b64)
	if err != nil {
		log.Fatal(err)
	}

	f.data, err = ioutil.ReadAll(reader)
	if err != nil {
		log.Fatal(err)
	}

	return f
}

// FS returns an http.FileSystem object for serving files over http
func (f *Files) FS() http.FileSystem {
	return f.dir
}

func (f *Files) determinePath(name string) string {
	if f.dir.useStaticFiles {
		return name
	}

	return f.absPkgPath + name
}

// GetHTTPFile returns an http.File object
func (f *Files) GetHTTPFile(filename string) (http.File, error) {
	return f.dir.Open(f.determinePath(filename))
}

// ReadFile returns a files contents as []byte from the filesystem, static or local
func (f *Files) ReadFile(filename string) ([]byte, error) {

	file, err := f.dir.Open(f.determinePath(filename))
	if err != nil {
		return nil, err
	}

	return ioutil.ReadAll(file)
}

// ReadDir reads the directory named by dirname and returns
// a list of sorted directory entries.
func (f *Files) ReadDir(dirname string) ([]os.FileInfo, error) {

	file, err := f.dir.Open(f.determinePath(dirname))
	if err != nil {
		return nil, err
	}

	results, err := file.Readdir(-1)
	if err != nil {
		return nil, err
	}

	sort.Sort(byName(results))

	return results, nil
}

// ReadFiles returns a directories file contents as a map[string][]byte from the filesystem, static or local
func (f *Files) ReadFiles(dirname string, recursive bool) (map[string][]byte, error) {

	dirname = f.determinePath(dirname)

	results := map[string][]byte{}

	file, err := f.dir.Open(dirname)
	if err != nil {
		return nil, err
	}

	if err = f.readFilesRecursive(dirname, file, results, recursive); err != nil {
		return nil, err
	}

	return results, nil
}

func (f *Files) readFilesRecursive(dirname string, file http.File, results map[string][]byte, recursive bool) error {

	files, err := file.Readdir(-1)
	if err != nil {
		return err
	}

	var fpath string

	for _, fi := range files {

		fpath = dirname + fi.Name()

		newFile, err := f.dir.Open(fpath)
		if err != nil {
			return err
		}

		if fi.IsDir() {

			if !recursive {
				continue
			}

			err := f.readFilesRecursive(fpath, newFile, results, recursive)
			if err != nil {
				return err
			}

			continue
		}

		results[fpath], err = ioutil.ReadAll(newFile)
		if err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package amazonebsmock_test

import (
	"fmt"
	"github.com/Horgix/packer-builder-amazon-ebs-mock/amazon-ebs-mock"
	"github.com/Horgix/packer-builder-amazon-ebs-mock/packer-lib-mock"
	"log"
	"testing"
)

// LoadDefaultConfig : 'Generate' parameter
func TestLoadDefaultConfig_DefaultGenerate(t *testing.T) {
	const expectedGenerate = true

	builder := new(amazonebsmock.Builder)
	builder.LoadDefaultConfig()

	if builder.Config.Generate != expectedGenerate {
		t.Error(fmt.Sprintf("LoadDefaultConfig() should return a default config with Generate to '%v' but it reported '%v'", expectedGenerate, builder.Config.Generate))
	}
}

// LoadDefaultConfig : 'Amount' parameter
func TestLoadDefaultConfig_DefaultAmount(t *testing.T) {
	const expectedAmount = 1

	builder := new(amazonebsmock.Builder)
	builder.LoadDefaultConfig()

	if builder.Config.Amount != expectedAmount {
		t.Error("LoadDefaultConfig() should return a default config with Amount to '%v' but it reported '%v'", expectedAmount, builder.Config.Amount)
	}
}

// LoadDefaultConfig : 'Region' parameter
func TestLoadDefaultConfig_DefaultRegion(t *testing.T) {
	const expectedRegion = ""

	builder := new(amazonebsmock.Builder)
	builder.LoadDefaultConfig()

	if builder.Config.Region != expectedRegion {
		t.Error("LoadDefaultConfig() should return a default config with Region to '%v' but it reported '%v'", expectedRegion, builder.Config.Region)
	}
}

// TODO : Test config parsing

func TestPrepare_Rand(t *testing.T) {
	builder := new(amazonebsmock.Builder)
	builder.Prepare()

	if builder.TestMsg != "Rand seeded" {
		t.Errorf("Prepare() should initialize rand but didn't report it")
	}
}

// func TestPrepare(t *testing.T) {
// 	builder := new(amazonebsmock.Builder)
// 	builder.Prepare()
//
// 	if builder.TestMsg != "Rand seeded" {
// 		t.Errorf("Prepare() should initialize rand but didn't report it")
// 	}
// }

// Dumb test, but you know, coverage.
func TestCancel(t *testing.T) {
	builder := new(amazonebsmock.Builder)
	builder.Cancel()
	if builder.TestMsg != "This method is doing nothing" {
		t.Errorf("Cancel() should be doing nothing but it didn't report it")
	}
}

// Check that Run() method notify the user as expected
func TestRun_UiCalls(t *testing.T) {
	// Initialize and Prepare Builder
	builder := new(amazonebsmock.Builder)
	builder.Prepare()

	// Mock the "ui" part so we can count calls to ui.Say()
	ui := &packermock.MockUi{}

	log.Printf("ui.Say call SayCounter pre Run: %v", ui.SayCount)
	builder.Run(ui, nil, nil)
	log.Printf("ui.Say call SayCounter post Run: %v", ui.SayCount)

	// We should have 4 calls to ui.Say()
	const expectedSayCount = 2
	if ui.SayCount != expectedSayCount {
		t.Errorf("Number of calls to ui.Say() was incorrect, "+
			"got %d but expected %d", ui.SayCount,
			expectedSayCount)
	}
}
<commit_msg>tests: refactor builder tests using subtests and common setup step<commit_after>package amazonebsmock_test

import (
	"github.com/Horgix/packer-builder-amazon-ebs-mock/amazon-ebs-mock"
	"github.com/Horgix/packer-builder-amazon-ebs-mock/packer-lib-mock"
	"log"
	"testing"
)

// LoadDefaultConfig
func TestLoadDefaultConfig(t *testing.T) {
	// Expected default values for parameters
	const expectedGenerate = true
	const expectedAmount = 1
	const expectedRegion = ""

	// Initialize the Builder and its config
	builder := new(amazonebsmock.Builder)
	builder.LoadDefaultConfig()

	// Check 'Generate' parameter
	t.Run("Generate", func(t *testing.T) {
		if builder.Config.Generate != expectedGenerate {
			t.Error(
				"LoadDefaultConfig() should return a default "+
					"config with Generate to '%v' but it reported '%v'",
				expectedGenerate,
				builder.Config.Generate,
			)
		}
	})

	// Check 'Amount' parameter
	t.Run("Amount", func(t *testing.T) {
		if builder.Config.Amount != expectedAmount {
			t.Error(
				"LoadDefaultConfig() should return a default "+
					"config with Amount to '%v' but it reported '%v'",
				expectedAmount,
				builder.Config.Amount,
			)
		}
	})

	// Check 'Region' parameter
	t.Run("Region", func(t *testing.T) {
		if builder.Config.Region != expectedRegion {
			t.Error(
				"LoadDefaultConfig() should return a default "+
					"config with Region to '%v' but it reported '%v'",
				expectedRegion,
				builder.Config.Region,
			)
		}
	})
}

// TODO : Test config parsing

func TestPrepare_Rand(t *testing.T) {
	builder := new(amazonebsmock.Builder)
	builder.Prepare()

	if builder.TestMsg != "Rand seeded" {
		t.Errorf("Prepare() should initialize rand but didn't report it")
	}
}

// func TestPrepare(t *testing.T) {
// 	builder := new(amazonebsmock.Builder)
// 	builder.Prepare()
//
// 	if builder.TestMsg != "Rand seeded" {
// 		t.Errorf("Prepare() should initialize rand but didn't report it")
// 	}
// }

// Dumb test, but you know, coverage.
func TestCancel(t *testing.T) {
	builder := new(amazonebsmock.Builder)
	builder.Cancel()
	if builder.TestMsg != "This method is doing nothing" {
		t.Errorf("Cancel() should be doing nothing but it didn't report it")
	}
}

// Check that Run() method notify the user as expected
func TestRun_UiCalls(t *testing.T) {
	// Initialize and Prepare Builder
	builder := new(amazonebsmock.Builder)
	builder.Prepare()

	// Mock the "ui" part so we can count calls to ui.Say()
	ui := &packermock.MockUi{}

	log.Printf("ui.Say call SayCounter pre Run: %v", ui.SayCount)
	builder.Run(ui, nil, nil)
	log.Printf("ui.Say call SayCounter post Run: %v", ui.SayCount)

	// We should have 4 calls to ui.Say()
	const expectedSayCount = 2
	if ui.SayCount != expectedSayCount {
		t.Errorf("Number of calls to ui.Say() was incorrect, "+
			"got %d but expected %d", ui.SayCount,
			expectedSayCount)
	}
}
<|endoftext|>


<commit_before>package metric_test

import (
	"os"
	"time"

	"code.cloudfoundry.org/lager"
	"github.com/concourse/concourse/atc/db"
	"github.com/concourse/concourse/atc/db/dbfakes"
	"github.com/concourse/concourse/atc/metric"
	"github.com/concourse/concourse/atc/metric/metricfakes"
	"github.com/tedsuo/ifrit"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gstruct"
)

var _ = Describe("Periodic emission of metrics", func() {
	var (
		emitter *metricfakes.FakeEmitter
		monitor *metric.Monitor

		process ifrit.Process
	)

	BeforeEach(func() {
		emitter = &metricfakes.FakeEmitter{}
		monitor = metric.NewMonitor()

		emitterFactory := &metricfakes.FakeEmitterFactory{}
		emitterFactory.IsConfiguredReturns(true)
		emitterFactory.NewEmitterReturns(emitter, nil)

		monitor.RegisterEmitter(emitterFactory)
		monitor.Initialize(testLogger, "test", map[string]string{}, 1000)

	})

	JustBeforeEach(func() {
		runner := metric.PeriodicallyEmit(
			lager.NewLogger("dont care"),
			monitor,
			250*time.Millisecond,
		)

		process = ifrit.Invoke(runner)
	})

	AfterEach(func() {
		process.Signal(os.Interrupt)
		<-process.Wait()
	})

	Context("database-related metrics", func() {
		BeforeEach(func() {
			a := &dbfakes.FakeConn{}
			a.NameReturns("A")
			b := &dbfakes.FakeConn{}
			b.NameReturns("B")
			monitor.Databases = []db.Conn{a, b}
		})

		It("emits database queries", func() {
			Eventually(func() [][]interface{} { return emitter.Invocations()["Emit"] }).Should(
				ContainElement(
					ConsistOf(
						Not(BeNil()),
						MatchFields(IgnoreExtras, Fields{
							"Name": Equal("database queries"),
						}),
					),
				),
			)

			By("emits database connections for each pool")
			Eventually(func() [][]interface{} { return emitter.Invocations()["Emit"] }).Should(
				ContainElement(
					ConsistOf(
						Not(BeNil()),
						MatchFields(IgnoreExtras, Fields{
							"Name":       Equal("database connections"),
							"Attributes": Equal(map[string]string{"ConnectionName": "A"}),
						}),
					),
				),
			)
			Eventually(func() [][]interface{} { return emitter.Invocations()["Emit"] }).Should(
				ContainElement(
					ConsistOf(
						Not(BeNil()),
						MatchFields(IgnoreExtras, Fields{
							"Name":       Equal("database connections"),
							"Attributes": Equal(map[string]string{"ConnectionName": "B"}),
						}),
					),
				),
			)
		})
	})

	Context("concurrent requests", func() {
		const action = "ListAllSomething"

		BeforeEach(func() {
			gauge := &metric.Gauge{}
			gauge.Set(123)

			counter := &metric.Counter{}
			counter.IncDelta(10)

			monitor.ConcurrentRequests[action] = gauge
			monitor.ConcurrentRequestsLimitHit[action] = counter
		})

		It("emits", func() {
			Eventually(func() [][]interface{} { return emitter.Invocations()["Emit"] }).Should(
				ContainElement(
					ConsistOf(
						Not(BeNil()),
						MatchFields(IgnoreExtras, Fields{
							"Name":  Equal("concurrent requests"),
							"Value": Equal(float64(123)),
							"Attributes": Equal(map[string]string{
								"action": action,
							}),
						}),
					),
				),
			)

			Eventually(func() [][]interface{} { return emitter.Invocations()["Emit"] }).Should(
				ContainElement(
					ConsistOf(
						Not(BeNil()),
						MatchFields(IgnoreExtras, Fields{
							"Name":  Equal("concurrent requests limit hit"),
							"Value": Equal(float64(10)),
							"Attributes": Equal(map[string]string{
								"action": action,
							}),
						}),
					),
				),
			)
		})
	})

	Context("limit-active-tasks metrics", func() {
		BeforeEach(func() {
			gauge := &metric.Gauge{}
			gauge.Set(123)
			monitor.TasksWaiting = *gauge
		})
		It("emits", func() {
			Eventually(func() [][]interface{} { return emitter.Invocations()["Emit"] }).Should(
				ContainElement(
					ConsistOf(
						Not(BeNil()),
						MatchFields(IgnoreExtras, Fields{
							"Name":  Equal("tasks waiting"),
							"Value": Equal(float64(123)),
						}),
					),
				),
			)
		})
	})
})
<commit_msg>atc/metric: structure: add events test helper<commit_after>package metric_test

import (
	"os"
	"time"

	"code.cloudfoundry.org/lager"
	"github.com/concourse/concourse/atc/db"
	"github.com/concourse/concourse/atc/db/dbfakes"
	"github.com/concourse/concourse/atc/metric"
	"github.com/concourse/concourse/atc/metric/metricfakes"
	"github.com/tedsuo/ifrit"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gstruct"
)

var _ = Describe("Periodic emission of metrics", func() {
	var (
		emitter *metricfakes.FakeEmitter
		monitor *metric.Monitor

		process ifrit.Process
	)

	BeforeEach(func() {
		emitter = &metricfakes.FakeEmitter{}
		monitor = metric.NewMonitor()

		emitterFactory := &metricfakes.FakeEmitterFactory{}
		emitterFactory.IsConfiguredReturns(true)
		emitterFactory.NewEmitterReturns(emitter, nil)

		monitor.RegisterEmitter(emitterFactory)
		monitor.Initialize(testLogger, "test", map[string]string{}, 1000)

	})

	JustBeforeEach(func() {
		runner := metric.PeriodicallyEmit(
			lager.NewLogger("dont care"),
			monitor,
			250*time.Millisecond,
		)

		process = ifrit.Invoke(runner)
	})

	AfterEach(func() {
		process.Signal(os.Interrupt)
		<-process.Wait()
	})

	events := func() []metric.Event {
		var events []metric.Event
		for i := 0; i < emitter.EmitCallCount(); i++ {
			_, event := emitter.EmitArgsForCall(i)
			events = append(events, event)
		}
		return events
	}

	Context("database-related metrics", func() {
		BeforeEach(func() {
			a := &dbfakes.FakeConn{}
			a.NameReturns("A")
			b := &dbfakes.FakeConn{}
			b.NameReturns("B")
			monitor.Databases = []db.Conn{a, b}
		})

		It("emits database queries", func() {
			Eventually(events).Should(
				ContainElement(
					MatchFields(IgnoreExtras, Fields{
						"Name": Equal("database queries"),
					}),
				),
			)

			By("emits database connections for each pool")
			Eventually(events).Should(
				ContainElement(
					MatchFields(IgnoreExtras, Fields{
						"Name":       Equal("database connections"),
						"Attributes": Equal(map[string]string{"ConnectionName": "A"}),
					}),
				),
			)
			Eventually(events).Should(
				ContainElement(
					MatchFields(IgnoreExtras, Fields{
						"Name":       Equal("database connections"),
						"Attributes": Equal(map[string]string{"ConnectionName": "B"}),
					}),
				),
			)
		})
	})

	Context("concurrent requests", func() {
		const action = "ListAllSomething"

		BeforeEach(func() {
			gauge := &metric.Gauge{}
			gauge.Set(123)

			counter := &metric.Counter{}
			counter.IncDelta(10)

			monitor.ConcurrentRequests[action] = gauge
			monitor.ConcurrentRequestsLimitHit[action] = counter
		})

		It("emits", func() {
			Eventually(events).Should(
				ContainElement(
					MatchFields(IgnoreExtras, Fields{
						"Name":  Equal("concurrent requests"),
						"Value": Equal(float64(123)),
						"Attributes": Equal(map[string]string{
							"action": action,
						}),
					}),
				),
			)

			Eventually(events).Should(
				ContainElement(
					MatchFields(IgnoreExtras, Fields{
						"Name":  Equal("concurrent requests limit hit"),
						"Value": Equal(float64(10)),
						"Attributes": Equal(map[string]string{
							"action": action,
						}),
					}),
				),
			)
		})
	})

	Context("limit-active-tasks metrics", func() {
		BeforeEach(func() {
			gauge := &metric.Gauge{}
			gauge.Set(123)
			monitor.TasksWaiting = *gauge
		})
		It("emits", func() {
			Eventually(events).Should(
				ContainElement(
					MatchFields(IgnoreExtras, Fields{
						"Name":  Equal("tasks waiting"),
						"Value": Equal(float64(123)),
					}),
				),
			)
		})
	})
})
<|endoftext|>


<commit_before>package base

import (
	"archive/tar"
	"compress/gzip"
	"fmt"
	. "github.com/smartystreets/goconvey/convey"
	"io"
	"io/ioutil"
	"testing"
)

func TestSerializeToCSV(t *testing.T) {
	Convey("Reading some instances...", t, func() {
		inst, err := ParseCSVToInstances("../examples/datasets/iris_headers.csv", true)
		So(err, ShouldBeNil)

		Convey("Saving the instances to CSV...", func() {
			f, err := ioutil.TempFile("", "instTmp")
			So(err, ShouldBeNil)
			err = SerializeInstancesToCSV(inst, f.Name())
			So(err, ShouldBeNil)
			Convey("What's written out should match what's read in", func() {
				dinst, err := ParseCSVToInstances(f.Name(), true)
				So(err, ShouldBeNil)
				So(inst.String(), ShouldEqual, dinst.String())
			})
		})
	})
}

func TestSerializeToFile(t *testing.T) {
	Convey("Reading some instances...", t, func() {
		inst, err := ParseCSVToInstances("../examples/datasets/iris_headers.csv", true)
		So(err, ShouldBeNil)

		Convey("Dumping to file...", func() {
			f, err := ioutil.TempFile("", "instTmp")
			So(err, ShouldBeNil)
			err = SerializeInstances(inst, f)
			So(err, ShouldBeNil)
			f.Seek(0, 0)
			Convey("Contents of the archive should be right...", func() {
				gzr, err := gzip.NewReader(f)
				So(err, ShouldBeNil)
				tr := tar.NewReader(gzr)
				classAttrsPresent := false
				manifestPresent := false
				regularAttrsPresent := false
				dataPresent := false
				dimsPresent := false
				readBytes := make([]byte, len([]byte(SerializationFormatVersion)))
				for {
					hdr, err := tr.Next()
					if err == io.EOF {
						break
					}
					So(err, ShouldBeNil)
					switch hdr.Name {
					case "MANIFEST":
						tr.Read(readBytes)
						manifestPresent = true
						break
					case "CATTRS":
						classAttrsPresent = true
						break
					case "ATTRS":
						regularAttrsPresent = true
						break
					case "DATA":
						dataPresent = true
						break
					case "DIMS":
						dimsPresent = true
						break
					default:
						fmt.Printf("Unknown file: %s\n", hdr.Name)
					}
				}
				Convey("MANIFEST should be present", func() {
					So(manifestPresent, ShouldBeTrue)
					Convey("MANIFEST should be right...", func() {
						So(readBytes, ShouldResemble, []byte(SerializationFormatVersion))
					})
				})
				Convey("DATA should be present", func() {
					So(dataPresent, ShouldBeTrue)
				})
				Convey("ATTRS should be present", func() {
					So(regularAttrsPresent, ShouldBeTrue)
				})
				Convey("CATTRS should be present", func() {
					So(classAttrsPresent, ShouldBeTrue)
				})
				Convey("DIMS should be present", func() {
					So(dimsPresent, ShouldBeTrue)
				})
			})
			Convey("Should be able to reconstruct...", func() {
				f.Seek(0, 0)
				dinst, err := DeserializeInstances(f)
				So(err, ShouldBeNil)
				So(InstancesAreEqual(inst, dinst), ShouldBeTrue)
			})
		})
	})
}
<commit_msg>base: correct some non-deterministic serialisation test behaviour<commit_after>package base

import (
	"archive/tar"
	"compress/gzip"
	"fmt"
	. "github.com/smartystreets/goconvey/convey"
	"io"
	"io/ioutil"
	"testing"
)

func TestSerializeToCSV(t *testing.T) {
	Convey("Reading some instances...", t, func() {
		inst, err := ParseCSVToInstances("../examples/datasets/iris_headers.csv", true)
		So(err, ShouldBeNil)

		Convey("Saving the instances to CSV...", func() {
			f, err := ioutil.TempFile("", "instTmpCSV")
			So(err, ShouldBeNil)
			err = SerializeInstancesToCSV(inst, f.Name())
			So(err, ShouldBeNil)
			Convey("What's written out should match what's read in", func() {
				dinst, err := ParseCSVToInstances(f.Name(), true)
				So(err, ShouldBeNil)
				So(inst.String(), ShouldEqual, dinst.String())
			})
		})
	})
}

func TestSerializeToFile(t *testing.T) {
	Convey("Reading some instances...", t, func() {
		inst, err := ParseCSVToInstances("../examples/datasets/iris_headers.csv", true)
		So(err, ShouldBeNil)

		Convey("Dumping to file...", func() {
			f, err := ioutil.TempFile("", "instTmpF")
			So(err, ShouldBeNil)
			err = SerializeInstances(inst, f)
			So(err, ShouldBeNil)
			f.Seek(0, 0)
			Convey("Contents of the archive should be right...", func() {
				gzr, err := gzip.NewReader(f)
				So(err, ShouldBeNil)
				tr := tar.NewReader(gzr)
				classAttrsPresent := false
				manifestPresent := false
				regularAttrsPresent := false
				dataPresent := false
				dimsPresent := false
				readBytes := make([]byte, len([]byte(SerializationFormatVersion)))
				for {
					hdr, err := tr.Next()
					if err == io.EOF {
						break
					}
					So(err, ShouldBeNil)
					switch hdr.Name {
					case "MANIFEST":
						tr.Read(readBytes)
						manifestPresent = true
						break
					case "CATTRS":
						classAttrsPresent = true
						break
					case "ATTRS":
						regularAttrsPresent = true
						break
					case "DATA":
						dataPresent = true
						break
					case "DIMS":
						dimsPresent = true
						break
					default:
						fmt.Printf("Unknown file: %s\n", hdr.Name)
					}
				}
				Convey("MANIFEST should be present", func() {
					So(manifestPresent, ShouldBeTrue)
					Convey("MANIFEST should be right...", func() {
						So(readBytes, ShouldResemble, []byte(SerializationFormatVersion))
					})
				})
				Convey("DATA should be present", func() {
					So(dataPresent, ShouldBeTrue)
				})
				Convey("ATTRS should be present", func() {
					So(regularAttrsPresent, ShouldBeTrue)
				})
				Convey("CATTRS should be present", func() {
					So(classAttrsPresent, ShouldBeTrue)
				})
				Convey("DIMS should be present", func() {
					So(dimsPresent, ShouldBeTrue)
				})
			})
			Convey("Should be able to reconstruct...", func() {
				f.Seek(0, 0)
				dinst, err := DeserializeInstances(f)
				So(err, ShouldBeNil)
				So(InstancesAreEqual(inst, dinst), ShouldBeTrue)
			})
		})
	})
}
<|endoftext|>


<commit_before>/*
   Copyright 2020 Docker Compose CLI authors

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package e2e

import (
	"encoding/json"
	"fmt"
	"os"
	"strings"
	"testing"
	"time"

	"gotest.tools/v3/assert"
	"gotest.tools/v3/icmd"
	"gotest.tools/v3/poll"

	"github.com/docker/compose-cli/cli/cmd"
	. "github.com/docker/compose-cli/utils/e2e"
)

var binDir string

func TestMain(m *testing.M) {
	p, cleanup, err := SetupExistingCLI()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	binDir = p
	exitCode := m.Run()
	cleanup()
	os.Exit(exitCode)
}

func TestLocalBackendRun(t *testing.T) {
	c := NewParallelE2eCLI(t, binDir)
	c.RunDockerCmd("context", "create", "local", "test-context").Assert(t, icmd.Success)
	c.RunDockerCmd("context", "use", "test-context").Assert(t, icmd.Success)

	t.Run("run", func(t *testing.T) {
		t.Parallel()
		res := c.RunDockerCmd("run", "-d", "nginx:alpine")
		containerName := strings.TrimSpace(res.Combined())
		t.Cleanup(func() {
			_ = c.RunDockerOrExitError("rm", "-f", containerName)
		})
		res = c.RunDockerCmd("inspect", containerName)
		res.Assert(t, icmd.Expected{Out: `"Status": "running"`})
	})

	t.Run("run rm", func(t *testing.T) {
		t.Parallel()
		res := c.RunDockerCmd("run", "--rm", "-d", "nginx:alpine")
		containerName := strings.TrimSpace(res.Combined())
		t.Cleanup(func() {
			_ = c.RunDockerOrExitError("rm", "-f", containerName)
		})
		_ = c.RunDockerCmd("stop", containerName)
		checkRemoved := func(t poll.LogT) poll.Result {
			res = c.RunDockerOrExitError("inspect", containerName)
			if res.ExitCode == 1 && strings.Contains(res.Stderr(), "No such container") {
				return poll.Success()
			}
			return poll.Continue("waiting for container to be removed")
		}
		poll.WaitOn(t, checkRemoved, poll.WithDelay(1*time.Second), poll.WithTimeout(10*time.Second))
	})

	t.Run("run with ports", func(t *testing.T) {
		res := c.RunDockerCmd("run", "-d", "-p", "85:80", "nginx:alpine")
		containerName := strings.TrimSpace(res.Combined())
		t.Cleanup(func() {
			_ = c.RunDockerOrExitError("rm", "-f", containerName)
		})
		res = c.RunDockerCmd("inspect", containerName)

		inspect := &cmd.ContainerInspectView{}
		err := json.Unmarshal([]byte(res.Stdout()), inspect)
		assert.NilError(t, err)
		assert.Equal(t, inspect.Status, "running")
		nginxID := inspect.ID

		res = c.RunDockerCmd("ps")
		nginxFound := false
		lines := Lines(res.Stdout())
		for _, line := range lines {
			fields := strings.Fields(line)
			if fields[0] == nginxID {
				nginxFound = true
				assert.Equal(t, fields[1], "nginx:alpine", res.Combined())
				assert.Equal(t, fields[2], "/docker-entrypoint.sh", res.Combined())
				assert.Equal(t, fields[len(fields)-1], "0.0.0.0:85->80/tcp", res.Combined())
			}
		}
		assert.Assert(t, nginxFound, res.Stdout())

		res = c.RunDockerCmd("ps", "--format", "json")
		res.Assert(t, icmd.Expected{Out: `"Image":"nginx:alpine","Status":"Up Less than a second","Command":"/docker-entrypoint.sh nginx -g 'daemon off;'","Ports":["0.0.0.0:85->80/tcp"`})

		res = c.RunDockerCmd("ps", "--quiet")
		res.Assert(t, icmd.Expected{Out: nginxID + "\n"})
	})

	t.Run("run with volume", func(t *testing.T) {
		t.Parallel()
		t.Cleanup(func() {
			_ = c.RunDockerOrExitError("volume", "rm", "local-test")
		})
		c.RunDockerCmd("volume", "create", "local-test")
		c.RunDockerCmd("run", "--rm", "-d", "--volume", "local-test:/data", "alpine", "sh", "-c", `echo "testdata" > /data/test`)
		// FIXME: Remove sleep when race to attach to dead container is fixed
		res := c.RunDockerOrExitError("run", "--rm", "--volume", "local-test:/data", "alpine", "sh", "-c", "cat /data/test && sleep 1")
		res.Assert(t, icmd.Expected{Out: "testdata"})
	})

	t.Run("inspect not found", func(t *testing.T) {
		t.Parallel()
		res := c.RunDockerOrExitError("inspect", "nonexistentcontainer")
		res.Assert(t, icmd.Expected{
			ExitCode: 1,
			Err:      "Error: No such container: nonexistentcontainer",
		})
	})
}

func TestLocalBackendVolumes(t *testing.T) {
	c := NewParallelE2eCLI(t, binDir)
	c.RunDockerCmd("context", "create", "local", "test-context").Assert(t, icmd.Success)
	c.RunDockerCmd("context", "use", "test-context").Assert(t, icmd.Success)

	t.Run("volume crud", func(t *testing.T) {
		t.Parallel()
		name := "crud"
		t.Cleanup(func() {
			_ = c.RunDockerOrExitError("volume", "rm", name)
		})
		res := c.RunDockerCmd("volume", "create", name)
		res.Assert(t, icmd.Expected{Out: name})
		res = c.RunDockerCmd("volume", "ls")
		res.Assert(t, icmd.Expected{Out: name})
		res = c.RunDockerCmd("volume", "inspect", name)
		res.Assert(t, icmd.Expected{Out: fmt.Sprintf(`"ID": "%s"`, name)})
		res = c.RunDockerCmd("volume", "rm", name)
		res.Assert(t, icmd.Expected{Out: name})
		res = c.RunDockerOrExitError("volume", "inspect", name)
		res.Assert(t, icmd.Expected{ExitCode: 1})
	})
}
<commit_msg>Fir port display assertion, Docker engine returns 2 entries in container inspect<commit_after>/*
   Copyright 2020 Docker Compose CLI authors

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package e2e

import (
	"encoding/json"
	"fmt"
	"os"
	"strings"
	"testing"
	"time"

	"gotest.tools/v3/assert"
	"gotest.tools/v3/icmd"
	"gotest.tools/v3/poll"

	"github.com/docker/compose-cli/cli/cmd"
	. "github.com/docker/compose-cli/utils/e2e"
)

var binDir string

func TestMain(m *testing.M) {
	p, cleanup, err := SetupExistingCLI()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	binDir = p
	exitCode := m.Run()
	cleanup()
	os.Exit(exitCode)
}

func TestLocalBackendRun(t *testing.T) {
	c := NewParallelE2eCLI(t, binDir)
	c.RunDockerCmd("context", "create", "local", "test-context").Assert(t, icmd.Success)
	c.RunDockerCmd("context", "use", "test-context").Assert(t, icmd.Success)

	t.Run("run", func(t *testing.T) {
		t.Parallel()
		res := c.RunDockerCmd("run", "-d", "nginx:alpine")
		containerName := strings.TrimSpace(res.Combined())
		t.Cleanup(func() {
			_ = c.RunDockerOrExitError("rm", "-f", containerName)
		})
		res = c.RunDockerCmd("inspect", containerName)
		res.Assert(t, icmd.Expected{Out: `"Status": "running"`})
	})

	t.Run("run rm", func(t *testing.T) {
		t.Parallel()
		res := c.RunDockerCmd("run", "--rm", "-d", "nginx:alpine")
		containerName := strings.TrimSpace(res.Combined())
		t.Cleanup(func() {
			_ = c.RunDockerOrExitError("rm", "-f", containerName)
		})
		_ = c.RunDockerCmd("stop", containerName)
		checkRemoved := func(t poll.LogT) poll.Result {
			res = c.RunDockerOrExitError("inspect", containerName)
			if res.ExitCode == 1 && strings.Contains(res.Stderr(), "No such container") {
				return poll.Success()
			}
			return poll.Continue("waiting for container to be removed")
		}
		poll.WaitOn(t, checkRemoved, poll.WithDelay(1*time.Second), poll.WithTimeout(10*time.Second))
	})

	t.Run("run with ports", func(t *testing.T) {
		res := c.RunDockerCmd("run", "-d", "-p", "85:80", "nginx:alpine")
		containerName := strings.TrimSpace(res.Combined())
		t.Cleanup(func() {
			_ = c.RunDockerOrExitError("rm", "-f", containerName)
		})
		res = c.RunDockerCmd("inspect", containerName)

		inspect := &cmd.ContainerInspectView{}
		err := json.Unmarshal([]byte(res.Stdout()), inspect)
		assert.NilError(t, err)
		assert.Equal(t, inspect.Status, "running")
		nginxID := inspect.ID

		res = c.RunDockerCmd("ps")
		nginxFound := false
		lines := Lines(res.Stdout())
		for _, line := range lines {
			fields := strings.Fields(line)
			if fields[0] == nginxID {
				nginxFound = true
				assert.Equal(t, fields[1], "nginx:alpine", res.Combined())
				assert.Equal(t, fields[2], "/docker-entrypoint.sh", res.Combined())
				assert.Assert(t, strings.Contains(fields[len(fields)-1], ":85->80/tcp"), res.Combined())
			}
		}
		assert.Assert(t, nginxFound, res.Stdout())

		res = c.RunDockerCmd("ps", "--format", "json")
		res.Assert(t, icmd.Expected{Out: `"Image":"nginx:alpine","Status":"Up Less than a second","Command":"/docker-entrypoint.sh nginx -g 'daemon off;'","Ports":["0.0.0.0:85->80/tcp"`})

		res = c.RunDockerCmd("ps", "--quiet")
		res.Assert(t, icmd.Expected{Out: nginxID + "\n"})
	})

	t.Run("run with volume", func(t *testing.T) {
		t.Parallel()
		t.Cleanup(func() {
			_ = c.RunDockerOrExitError("volume", "rm", "local-test")
		})
		c.RunDockerCmd("volume", "create", "local-test")
		c.RunDockerCmd("run", "--rm", "-d", "--volume", "local-test:/data", "alpine", "sh", "-c", `echo "testdata" > /data/test`)
		// FIXME: Remove sleep when race to attach to dead container is fixed
		res := c.RunDockerOrExitError("run", "--rm", "--volume", "local-test:/data", "alpine", "sh", "-c", "cat /data/test && sleep 1")
		res.Assert(t, icmd.Expected{Out: "testdata"})
	})

	t.Run("inspect not found", func(t *testing.T) {
		t.Parallel()
		res := c.RunDockerOrExitError("inspect", "nonexistentcontainer")
		res.Assert(t, icmd.Expected{
			ExitCode: 1,
			Err:      "Error: No such container: nonexistentcontainer",
		})
	})
}

func TestLocalBackendVolumes(t *testing.T) {
	c := NewParallelE2eCLI(t, binDir)
	c.RunDockerCmd("context", "create", "local", "test-context").Assert(t, icmd.Success)
	c.RunDockerCmd("context", "use", "test-context").Assert(t, icmd.Success)

	t.Run("volume crud", func(t *testing.T) {
		t.Parallel()
		name := "crud"
		t.Cleanup(func() {
			_ = c.RunDockerOrExitError("volume", "rm", name)
		})
		res := c.RunDockerCmd("volume", "create", name)
		res.Assert(t, icmd.Expected{Out: name})
		res = c.RunDockerCmd("volume", "ls")
		res.Assert(t, icmd.Expected{Out: name})
		res = c.RunDockerCmd("volume", "inspect", name)
		res.Assert(t, icmd.Expected{Out: fmt.Sprintf(`"ID": "%s"`, name)})
		res = c.RunDockerCmd("volume", "rm", name)
		res.Assert(t, icmd.Expected{Out: name})
		res = c.RunDockerOrExitError("volume", "inspect", name)
		res.Assert(t, icmd.Expected{ExitCode: 1})
	})
}
<|endoftext|>