<commit_before>package terraform

import (
	"bytes"
	"encoding/json"
	"errors"
	"reflect"

	"github.com/EngineerBetter/concourse-up/util"
	"github.com/asaskevich/govalidator"
)

// InputVars holds all the parameters GCP IAAS needs
type GCPInputVars struct {
	AllowIPs           string
	ConfigBucket       string
	DBName             string
	DBPassword         string
	DBTier             string
	DBUsername         string
	Deployment         string
	DNSManagedZoneName string
	DNSRecordSetPrefix string
	ExternalIP         string
	GCPCredentialsJSON string
	Namespace          string
	Project            string
	Region             string
	Tags               string
	Zone               string
	PublicCIDR         string
	PrivateCIDR        string
}

// ConfigureTerraform interpolates terraform contents and returns terraform config
func (v *GCPInputVars) ConfigureTerraform(terraformContents string) (string, error) {
	terraformConfig, err := util.RenderTemplate("terraform", terraformContents, v)
	if terraformConfig == nil {
		return "", err
	}
	return string(terraformConfig), err
}

// Metadata represents output from terraform on GCP or GCP
type GCPOutputs struct {
	Network                    MetadataStringValue `json:"network" valid:"required"`
	PrivateSubnetworkName      MetadataStringValue `json:"private_subnetwork_name" valid:"required"`
	PublicSubnetworkName       MetadataStringValue `json:"public_subnetwork_name" valid:"required"`
	PublicSubnetworkCidr       MetadataStringValue `json:"public_subnetwork_cidr" valid:"required"`
	PrivateSubnetworkCidr      MetadataStringValue `json:"private_subnetwork_cidr" valid:"required"`
	PrivateSubnetworInternalGw MetadataStringValue `json:"private_subnetwor_internal_gw" valid:"required"`
	PublicSubnetworInternalGw  MetadataStringValue `json:"public_subnetwor_internal_gw" valid:"required"`
	ATCPublicIP                MetadataStringValue `json:"atc_public_ip" valid:"required"`
	DirectorAccountCreds       MetadataStringValue `json:"director_account_creds" valid:"required"`
	DirectorPublicIP           MetadataStringValue `json:"director_public_ip" valid:"required"`
	BoshDBAddress              MetadataStringValue `json:"bosh_db_address" valid:"required"`
	DBName                     MetadataStringValue `json:"db_name" valid:"required"`
	NatGatewayIP               MetadataStringValue `json:"nat_gateway_ip" valid:"required"`
	SQLServerCert              MetadataStringValue `json:"server_ca_cert" valid:"required"`
	DirectorSecurityGroupID    MetadataStringValue `json:"director_firewall_name" valid:"required"`
}

// AssertValid returns an error if the struct contains any missing fields
func (outputs *GCPOutputs) AssertValid() error {
	_, err := govalidator.ValidateStruct(outputs)
	return err
}

// Init populates outputs struct with values from the buffer
func (outputs *GCPOutputs) Init(buffer *bytes.Buffer) error {
	if err := json.NewDecoder(buffer).Decode(&outputs); err != nil {
		return err
	}

	return nil
}

// Get returns a the specified value from the outputs struct
func (outputs *GCPOutputs) Get(key string) (string, error) {
	reflectValue := reflect.ValueOf(outputs)
	reflectStruct := reflectValue.Elem()
	value := reflectStruct.FieldByName(key)
	if !value.IsValid() {
		return "", errors.New(key + " key not found")
	}

	return value.FieldByName("Value").String(), nil
}
<commit_msg>sort GCP TFOutputs for easier reading<commit_after>package terraform

import (
	"bytes"
	"encoding/json"
	"errors"
	"reflect"

	"github.com/EngineerBetter/concourse-up/util"
	"github.com/asaskevich/govalidator"
)

// InputVars holds all the parameters GCP IAAS needs
type GCPInputVars struct {
	AllowIPs           string
	ConfigBucket       string
	DBName             string
	DBPassword         string
	DBTier             string
	DBUsername         string
	Deployment         string
	DNSManagedZoneName string
	DNSRecordSetPrefix string
	ExternalIP         string
	GCPCredentialsJSON string
	Namespace          string
	Project            string
	Region             string
	Tags               string
	Zone               string
	PublicCIDR         string
	PrivateCIDR        string
}

// ConfigureTerraform interpolates terraform contents and returns terraform config
func (v *GCPInputVars) ConfigureTerraform(terraformContents string) (string, error) {
	terraformConfig, err := util.RenderTemplate("terraform", terraformContents, v)
	if terraformConfig == nil {
		return "", err
	}
	return string(terraformConfig), err
}

// Metadata represents output from terraform on GCP or GCP
type GCPOutputs struct {
	ATCPublicIP                MetadataStringValue `json:"atc_public_ip" valid:"required"`
	BoshDBAddress              MetadataStringValue `json:"bosh_db_address" valid:"required"`
	DBName                     MetadataStringValue `json:"db_name" valid:"required"`
	DirectorAccountCreds       MetadataStringValue `json:"director_account_creds" valid:"required"`
	DirectorPublicIP           MetadataStringValue `json:"director_public_ip" valid:"required"`
	DirectorSecurityGroupID    MetadataStringValue `json:"director_firewall_name" valid:"required"`
	NatGatewayIP               MetadataStringValue `json:"nat_gateway_ip" valid:"required"`
	Network                    MetadataStringValue `json:"network" valid:"required"`
	PrivateSubnetworInternalGw MetadataStringValue `json:"private_subnetwor_internal_gw" valid:"required"`
	PrivateSubnetworkCidr      MetadataStringValue `json:"private_subnetwork_cidr" valid:"required"`
	PrivateSubnetworkName      MetadataStringValue `json:"private_subnetwork_name" valid:"required"`
	PublicSubnetworInternalGw  MetadataStringValue `json:"public_subnetwor_internal_gw" valid:"required"`
	PublicSubnetworkCidr       MetadataStringValue `json:"public_subnetwork_cidr" valid:"required"`
	PublicSubnetworkName       MetadataStringValue `json:"public_subnetwork_name" valid:"required"`
	SQLServerCert              MetadataStringValue `json:"server_ca_cert" valid:"required"`
}

// AssertValid returns an error if the struct contains any missing fields
func (outputs *GCPOutputs) AssertValid() error {
	_, err := govalidator.ValidateStruct(outputs)
	return err
}

// Init populates outputs struct with values from the buffer
func (outputs *GCPOutputs) Init(buffer *bytes.Buffer) error {
	if err := json.NewDecoder(buffer).Decode(&outputs); err != nil {
		return err
	}

	return nil
}

// Get returns a the specified value from the outputs struct
func (outputs *GCPOutputs) Get(key string) (string, error) {
	reflectValue := reflect.ValueOf(outputs)
	reflectStruct := reflectValue.Elem()
	value := reflectStruct.FieldByName(key)
	if !value.IsValid() {
		return "", errors.New(key + " key not found")
	}

	return value.FieldByName("Value").String(), nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package fs

import (
	"bytes"
	"fmt"
	"io"

	"github.com/m3db/m3/src/dbnode/digest"
	"github.com/m3db/m3/src/dbnode/persist/fs/msgpack"
)

type dataFileSetReaderDecoderStream interface {
	msgpack.ByteDecoderStream

	// reader returns the underlying reader with access to the
	// incremental computed digest
	reader() digest.ReaderWithDigest
}

type readerDecoderStream struct {
	bytesReader      *bytes.Reader
	readerWithDigest digest.ReaderWithDigest
	backingBytes     []byte
	buf              [8]byte
	lastReadByte     int
	unreadByte       int
}

func newReaderDecoderStream() dataFileSetReaderDecoderStream {
	return &readerDecoderStream{
		readerWithDigest: digest.NewReaderWithDigest(nil),
		bytesReader:      bytes.NewReader(nil),
	}
}

func (s *readerDecoderStream) reader() digest.ReaderWithDigest {
	return s.readerWithDigest
}

func (s *readerDecoderStream) Reset(d []byte) {
	s.bytesReader.Reset(d)
	s.readerWithDigest.Reset(s.bytesReader)
	s.backingBytes = d
	s.lastReadByte = -1
	s.unreadByte = -1
}

func (s *readerDecoderStream) Read(p []byte) (int, error) {
	if len(p) == 0 {
		return 0, nil
	}

	ref := p

	var numUnreadByte int
	if s.unreadByte >= 0 {
		p[0] = byte(s.unreadByte)
		p = p[1:]
		s.unreadByte = -1
		numUnreadByte = 1
	}
	n, err := s.readerWithDigest.Read(p)
	n += numUnreadByte
	if n > 0 {
		s.lastReadByte = int(ref[n-1])
	}
	if err == io.EOF && n > 0 {
		return n, nil // return EOF next time, might be returning last byte still
	}
	return n, err
}

func (s *readerDecoderStream) ReadByte() (byte, error) {
	if s.unreadByte >= 0 {
		r := byte(s.unreadByte)
		s.unreadByte = -1
		return r, nil
	}
	n, err := s.readerWithDigest.Read(s.buf[:1])
	if n > 0 {
		s.lastReadByte = int(s.buf[0])
	}
	return s.buf[0], err
}

func (s *readerDecoderStream) UnreadByte() error {
	if s.lastReadByte < 0 {
		return fmt.Errorf("no previous read byte or already unread byte")
	}
	s.unreadByte = s.lastReadByte
	s.lastReadByte = -1
	return nil
}

func (s *readerDecoderStream) Bytes() []byte {
	return s.backingBytes
}

func (s *readerDecoderStream) Skip(length int64) error {
	// NB(r): This ensures the reader with digest is always read
	// from start to end, i.e. to calculate digest properly.
	remaining := length
	for {
		readEnd := int64(len(s.buf))
		if remaining < readEnd {
			readEnd = remaining
		}
		n, err := s.Read(s.buf[:readEnd])
		if err != nil {
			return err
		}
		remaining -= int64(n)
		if remaining < 0 {
			return fmt.Errorf("skipped too far, remaining is: %d", remaining)
		}
		if remaining == 0 {
			return nil
		}
	}
}

func (s *readerDecoderStream) Remaining() int64 {
	var unreadBytes int64
	if s.unreadByte != -1 {
		unreadBytes = 1
	}
	return int64(s.bytesReader.Len()) + unreadBytes
}

func (s *readerDecoderStream) Offset() int {
	return len(s.backingBytes) - int(s.Remaining())
}
<commit_msg>[dbnode] Increase readerDecoderStream.buf length to 64 (#3652)<commit_after>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package fs

import (
	"bytes"
	"fmt"
	"io"

	"github.com/m3db/m3/src/dbnode/digest"
	"github.com/m3db/m3/src/dbnode/persist/fs/msgpack"
)

type dataFileSetReaderDecoderStream interface {
	msgpack.ByteDecoderStream

	// reader returns the underlying reader with access to the
	// incremental computed digest
	reader() digest.ReaderWithDigest
}

type readerDecoderStream struct {
	bytesReader      *bytes.Reader
	readerWithDigest digest.ReaderWithDigest
	backingBytes     []byte
	buf              [64]byte
	lastReadByte     int
	unreadByte       int
}

func newReaderDecoderStream() dataFileSetReaderDecoderStream {
	return &readerDecoderStream{
		readerWithDigest: digest.NewReaderWithDigest(nil),
		bytesReader:      bytes.NewReader(nil),
	}
}

func (s *readerDecoderStream) reader() digest.ReaderWithDigest {
	return s.readerWithDigest
}

func (s *readerDecoderStream) Reset(d []byte) {
	s.bytesReader.Reset(d)
	s.readerWithDigest.Reset(s.bytesReader)
	s.backingBytes = d
	s.lastReadByte = -1
	s.unreadByte = -1
}

func (s *readerDecoderStream) Read(p []byte) (int, error) {
	if len(p) == 0 {
		return 0, nil
	}

	ref := p

	var numUnreadByte int
	if s.unreadByte >= 0 {
		p[0] = byte(s.unreadByte)
		p = p[1:]
		s.unreadByte = -1
		numUnreadByte = 1
	}
	n, err := s.readerWithDigest.Read(p)
	n += numUnreadByte
	if n > 0 {
		s.lastReadByte = int(ref[n-1])
	}
	if err == io.EOF && n > 0 {
		return n, nil // return EOF next time, might be returning last byte still
	}
	return n, err
}

func (s *readerDecoderStream) ReadByte() (byte, error) {
	if s.unreadByte >= 0 {
		r := byte(s.unreadByte)
		s.unreadByte = -1
		return r, nil
	}
	n, err := s.readerWithDigest.Read(s.buf[:1])
	if n > 0 {
		s.lastReadByte = int(s.buf[0])
	}
	return s.buf[0], err
}

func (s *readerDecoderStream) UnreadByte() error {
	if s.lastReadByte < 0 {
		return fmt.Errorf("no previous read byte or already unread byte")
	}
	s.unreadByte = s.lastReadByte
	s.lastReadByte = -1
	return nil
}

func (s *readerDecoderStream) Bytes() []byte {
	return s.backingBytes
}

func (s *readerDecoderStream) Skip(length int64) error {
	// NB(r): This ensures the reader with digest is always read
	// from start to end, i.e. to calculate digest properly.
	remaining := length
	for {
		readEnd := int64(len(s.buf))
		if remaining < readEnd {
			readEnd = remaining
		}
		n, err := s.Read(s.buf[:readEnd])
		if err != nil {
			return err
		}
		remaining -= int64(n)
		if remaining < 0 {
			return fmt.Errorf("skipped too far, remaining is: %d", remaining)
		}
		if remaining == 0 {
			return nil
		}
	}
}

func (s *readerDecoderStream) Remaining() int64 {
	var unreadBytes int64
	if s.unreadByte != -1 {
		unreadBytes = 1
	}
	return int64(s.bytesReader.Len()) + unreadBytes
}

func (s *readerDecoderStream) Offset() int {
	return len(s.backingBytes) - int(s.Remaining())
}
<|endoftext|>


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

// +build android

package sensor

/*
#cgo LDFLAGS: -landroid

#include <stdlib.h>
#include <android/sensor.h>

void GoAndroid_createManager();
void GoAndroid_destroyManager();
int  GoAndroid_enableSensor(int, int32_t);
void GoAndroid_disableSensor(int);
int  GoAndroid_readQueue(int n, int32_t* types, int64_t* timestamps, float* vectors);
*/
import "C"
import (
	"fmt"
	"runtime"
	"sync"
	"time"
	"unsafe"
)

var (
	collectingMu sync.Mutex // guards collecting

	// collecting is true if sensor event collecting background
	// job has already started.
	collecting bool
)

// closeSignal destroys the underlying looper and event queue.
type closeSignal struct{}

// readSignal reads up to len(dst) events and mutates n with
// the number of returned events. If error occurs during the read,
// it mutates err.
type readSignal struct {
	dst []Event
	n   *int
	err *error
}

// enableSignal enables the sensors events on the underlying
// event queue for the specified sensor type with the specified
// latency criterion.
type enableSignal struct {
	t     Type
	delay time.Duration
	err   *error
}

// disableSignal disables the events on the underlying event queue
// from the sensor specified.
type disableSignal struct {
	t Type
}

type inOut struct {
	in  interface{}
	out chan struct{}
}

var inout = make(chan inOut)

// init inits the manager and creates a goroutine to proxy the CGO calls.
// All actions related to an ALooper needs to be performed from the same
// OS thread. The goroutine proxy locks itself to an OS thread and handles the
// CGO traffic on the same thread.
func init() {
	go func() {
		runtime.LockOSThread()
		C.GoAndroid_createManager()

		for {
			v := <-inout
			switch s := v.in.(type) {

			case enableSignal:
				usecsDelay := s.delay.Nanoseconds() / 1000
				code := int(C.GoAndroid_enableSensor(typeToInt(s.t), C.int32_t(usecsDelay)))
				if code != 0 {
					*s.err = fmt.Errorf("sensor: no default %v sensor on the device", s.t)
				}
			case disableSignal:
				C.GoAndroid_disableSensor(typeToInt(s.t))
			case readSignal:
				n, err := readEvents(s.dst)
				*s.n = n
				*s.err = err
			case closeSignal:
				C.GoAndroid_destroyManager()
				close(v.out)
				return // we don't need this goroutine anymore
			}
			close(v.out)
		}
	}()
}

func enable(s Sender, t Type, delay time.Duration) error {
	startCollecting(s)

	var err error
	done := make(chan struct{})
	inout <- inOut{
		in:  enableSignal{t: t, delay: delay, err: &err},
		out: done,
	}
	<-done
	return err
}

func startCollecting(s Sender) {
	collectingMu.Lock()
	defer collectingMu.Unlock()

	if collecting {
		// already collecting.
		return
	}
	collecting = true

	go func() {
		ev := make([]Event, 8)
		var n int
		var err error // TODO(jbd): How to handle the errors? error channel?
		for {
			done := make(chan struct{})
			inout <- inOut{
				in:  readSignal{dst: ev, n: &n, err: &err},
				out: done,
			}
			<-done
			for i := 0; i < n; i++ {
				s.Send(ev[i])
			}
		}
	}()
}

func disable(t Type) error {
	done := make(chan struct{})
	inout <- inOut{
		in:  disableSignal{t: t},
		out: done,
	}
	<-done
	return nil
}

func readEvents(e []Event) (n int, err error) {
	num := len(e)
	types := make([]C.int32_t, num)
	timestamps := make([]C.int64_t, num)
	vectors := make([]C.float, 3*num)

	n = int(C.GoAndroid_readQueue(
		C.int(num),
		(*C.int32_t)(unsafe.Pointer(&types[0])),
		(*C.int64_t)(unsafe.Pointer(&timestamps[0])),
		(*C.float)(unsafe.Pointer(&vectors[0]))),
	)
	for i := 0; i < n; i++ {
		e[i] = Event{
			Sensor:    intToType[int(types[i])],
			Timestamp: int64(timestamps[i]),
			Data: []float64{
				float64(vectors[i*3]),
				float64(vectors[i*3+1]),
				float64(vectors[i*3+2]),
			},
		}
	}
	return
}

// TODO(jbd): Remove destroy?
func destroy() error {
	done := make(chan struct{})
	inout <- inOut{
		in:  closeSignal{},
		out: done,
	}
	<-done
	return nil
}

var intToType = map[int]Type{
	C.ASENSOR_TYPE_ACCELEROMETER:  Accelerometer,
	C.ASENSOR_TYPE_GYROSCOPE:      Gyroscope,
	C.ASENSOR_TYPE_MAGNETIC_FIELD: Magnetometer,
}

func typeToInt(t Type) C.int {
	for k, v := range intToType {
		if v == t {
			return C.int(k)
		}
	}
	return C.int(-1)
}
<commit_msg>exp/sensor: remove the unpopulated error from the readSignal<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build android

package sensor

/*
#cgo LDFLAGS: -landroid

#include <stdlib.h>
#include <android/sensor.h>

void GoAndroid_createManager();
void GoAndroid_destroyManager();
int  GoAndroid_enableSensor(int, int32_t);
void GoAndroid_disableSensor(int);
int  GoAndroid_readQueue(int n, int32_t* types, int64_t* timestamps, float* vectors);
*/
import "C"
import (
	"fmt"
	"runtime"
	"sync"
	"time"
	"unsafe"
)

var (
	collectingMu sync.Mutex // guards collecting

	// collecting is true if sensor event collecting background
	// job has already started.
	collecting bool
)

// closeSignal destroys the underlying looper and event queue.
type closeSignal struct{}

// readSignal reads up to len(dst) events and mutates n with
// the number of returned events.
type readSignal struct {
	dst []Event
	n   *int
}

// enableSignal enables the sensors events on the underlying
// event queue for the specified sensor type with the specified
// latency criterion.
type enableSignal struct {
	t     Type
	delay time.Duration
	err   *error
}

// disableSignal disables the events on the underlying event queue
// from the sensor specified.
type disableSignal struct {
	t Type
}

type inOut struct {
	in  interface{}
	out chan struct{}
}

var inout = make(chan inOut)

// init inits the manager and creates a goroutine to proxy the CGO calls.
// All actions related to an ALooper needs to be performed from the same
// OS thread. The goroutine proxy locks itself to an OS thread and handles the
// CGO traffic on the same thread.
func init() {
	go func() {
		runtime.LockOSThread()
		C.GoAndroid_createManager()

		for {
			v := <-inout
			switch s := v.in.(type) {

			case enableSignal:
				usecsDelay := s.delay.Nanoseconds() / 1000
				code := int(C.GoAndroid_enableSensor(typeToInt(s.t), C.int32_t(usecsDelay)))
				if code != 0 {
					*s.err = fmt.Errorf("sensor: no default %v sensor on the device", s.t)
				}
			case disableSignal:
				C.GoAndroid_disableSensor(typeToInt(s.t))
			case readSignal:
				n := readEvents(s.dst)
				*s.n = n
			case closeSignal:
				C.GoAndroid_destroyManager()
				close(v.out)
				return // we don't need this goroutine anymore
			}
			close(v.out)
		}
	}()
}

func enable(s Sender, t Type, delay time.Duration) error {
	startCollecting(s)

	var err error
	done := make(chan struct{})
	inout <- inOut{
		in:  enableSignal{t: t, delay: delay, err: &err},
		out: done,
	}
	<-done
	return err
}

func startCollecting(s Sender) {
	collectingMu.Lock()
	defer collectingMu.Unlock()

	if collecting {
		// already collecting.
		return
	}
	collecting = true

	go func() {
		ev := make([]Event, 8)
		var n int
		for {
			done := make(chan struct{})
			inout <- inOut{
				in:  readSignal{dst: ev, n: &n},
				out: done,
			}
			<-done
			for i := 0; i < n; i++ {
				s.Send(ev[i])
			}
		}
	}()
}

func disable(t Type) error {
	done := make(chan struct{})
	inout <- inOut{
		in:  disableSignal{t: t},
		out: done,
	}
	<-done
	return nil
}

func readEvents(e []Event) (n int) {
	num := len(e)
	types := make([]C.int32_t, num)
	timestamps := make([]C.int64_t, num)
	vectors := make([]C.float, 3*num)

	n = int(C.GoAndroid_readQueue(
		C.int(num),
		(*C.int32_t)(unsafe.Pointer(&types[0])),
		(*C.int64_t)(unsafe.Pointer(&timestamps[0])),
		(*C.float)(unsafe.Pointer(&vectors[0]))),
	)
	for i := 0; i < n; i++ {
		e[i] = Event{
			Sensor:    intToType[int(types[i])],
			Timestamp: int64(timestamps[i]),
			Data: []float64{
				float64(vectors[i*3]),
				float64(vectors[i*3+1]),
				float64(vectors[i*3+2]),
			},
		}
	}
	return
}

// TODO(jbd): Remove destroy?
func destroy() error {
	done := make(chan struct{})
	inout <- inOut{
		in:  closeSignal{},
		out: done,
	}
	<-done
	return nil
}

var intToType = map[int]Type{
	C.ASENSOR_TYPE_ACCELEROMETER:  Accelerometer,
	C.ASENSOR_TYPE_GYROSCOPE:      Gyroscope,
	C.ASENSOR_TYPE_MAGNETIC_FIELD: Magnetometer,
}

func typeToInt(t Type) C.int {
	for k, v := range intToType {
		if v == t {
			return C.int(k)
		}
	}
	return C.int(-1)
}
<|endoftext|>


<commit_before>package shp

import (
	"bytes"
	"fmt"
	"reflect"
	"strconv"
	"strings"

	"github.com/ctessum/geom"
	"github.com/jonas-p/go-shp"
)

// Tag to use for matching struct fields with shapefile attributes.
// Case insensitive.
const tag = "shp"

const (
	// intLength is the integer length to use when creating shapefiles
	intLength = 10

	// floatLength is the float length to use when creating shapefiles
	floatLength = 10

	// floatPrecision is the float precision to use when creating shapefiles
	floatPrecision = 10

	// stringLength is the length of the string to use when creating shapefiles
	stringLength = 50
)

// Decoder is a wrapper around the github.com/jonas-p/go-shp shapefile
// reader.
type Decoder struct {
	shp.Reader
	row          int
	fieldIndices map[string]int
	err          error
}

func NewDecoder(filename string) (*Decoder, error) {
	fname := strings.TrimSuffix(filename, ".shp")
	r := new(Decoder)
	rr, err := shp.Open(fname + ".shp")
	if err != nil {
		return nil, err
	}
	r.Reader = *rr
	return r, err
}

func (r *Decoder) Close() {
	r.Reader.Close()
}

// getFieldIndices figures out the indices of the attribute fields
func (r *Decoder) getFieldIndices() {
	if r.fieldIndices == nil {
		r.fieldIndices = make(map[string]int)
		for i, f := range r.Fields() {
			name := strings.ToLower(shpFieldName2String(f.Name))
			r.fieldIndices[name] = i
		}
	}
}

// DecodeRow decodes a shapefile row into a struct. The input
// value rec must be a pointer to a struct. The function will
// attempt to match the struct fields to shapefile data.
// It will read the shape data into any struct fields that
// implement the geom.T interface. It will read attribute
// data into any struct fields whose `shp` tag or field names
// that match an attribute name in the shapefile (case insensitive).
// Only exported fields will be matched, and all matched fields
// must be of either string, int, or float64 types.
// The return value is true if there are still more records
// to be read from the shapefile.
// Be sure to call r.Error() after reading is finished
// to check for any errors that may have occured.
func (r *Decoder) DecodeRow(rec interface{}) bool {
	run := r.Next()
	if !run || r.err != nil {
		return false
	}
	r.getFieldIndices()
	v, t := getRecInfo(rec)
	_, shape := r.Shape()

	gI := reflect.TypeOf((*geom.T)(nil)).Elem()
	for i := 0; i < v.NumField(); i++ {
		fType := t.Field(i)
		fValue := v.Field(i)
		fName := strings.ToLower(fType.Name)
		tagName := strings.ToLower(fType.Tag.Get(tag))

		// First, check if this is a geometry field
		if fType.Type.Implements(gI) {
			_, g, err := shp2Geom(0, shape)
			if err != nil {
				r.err = err
				return false
			}
			fValue.Set(reflect.ValueOf(g))

			// Then, check the tag name
		} else if j, ok := r.fieldIndices[tagName]; ok {
			r.setFieldToAttribute(fValue, fType.Type, j)

			// Finally, check the struct field name
		} else if j, ok := r.fieldIndices[fName]; ok {
			r.setFieldToAttribute(fValue, fType.Type, j)
		}
	}
	r.row++
	return run
}

// DecodeRowFields decodes a shapefile row, returning the row
// geometry (g), the values of the specified fields (fields),
// and whether there are still more records to be read from the
// shapefile (more).
func (r *Decoder) DecodeRowFields(fieldNames ...string) (
	g geom.T, fields map[string]interface{}, more bool) {

	fields = make(map[string]interface{})
	var err error

	more = r.Next()
	if !more || r.err != nil {
		return
	}

	r.getFieldIndices()

	// Get geometry
	_, shape := r.Shape()
	_, g, err = shp2Geom(0, shape)
	if err != nil {
		r.err = err
		return
	}

	// Get fields
	for _, name := range fieldNames {
		if i, ok := r.fieldIndices[strings.ToLower(name)]; ok {
			fields[name] = r.getField(i)
		} else {
			r.err = fmt.Errorf("Shapefile does not contain field `%s`", name)
			return
		}
	}
	r.row++
	return

}

// Error returns any errors that have been encountered while decoding
// a shapfile.
func (r Decoder) Error() error {
	return r.err
}

func getRecInfo(rec interface{}) (reflect.Value, reflect.Type) {
	t := reflect.TypeOf(rec)
	if t.Kind() != reflect.Ptr {
		panic(fmt.Sprintf("rec must be a pointer to a "+
			"struct, not a %v.", t.Kind()))
	}
	v := reflect.Indirect(reflect.ValueOf(rec))
	if tt := v.Type().Kind(); tt != reflect.Struct {
		panic(fmt.Sprintf("rec must be a struct, not a %v.", tt))
	}
	return v, v.Type()
}

// ShpFieldName2String converts the shapefile field name into a
// string that can be more easily dealt with.
func shpFieldName2String(name [11]byte) string {
	b := bytes.Trim(name[:], "\x00")
	n := bytes.Index(b, []byte{0})
	if n == -1 {
		n = len(b)
	}
	return strings.TrimSpace(string(b[0:n]))
}

// ShpAttrbute2Float converts a shapefile attribute (which may contain
// "\x00" characters to a float.
func shpAttributeToFloat(attr string) (float64, error) {
	f, err := strconv.ParseFloat(strings.Trim(attr, "\x00"), 64)
	return f, err
}

// ShpAttrbute2Int converts a shapefile attribute (which may contain
// "\x00" characters to an int.
func shpAttributeToInt(attr string) (int64, error) {
	i, err := strconv.ParseInt(strings.Trim(attr, "\x00"), 10, 64)
	return i, err
}

func (r Decoder) setFieldToAttribute(fValue reflect.Value,
	fType reflect.Type, index int) {
	dataStr := r.ReadAttribute(r.row, index)
	switch fType.Kind() {
	case reflect.Float64:
		d, err := shpAttributeToFloat(dataStr)
		if err != nil {
			r.err = err
			return
		}
		fValue.SetFloat(d)
	case reflect.Int:
		d, err := shpAttributeToInt(dataStr)
		if err != nil {
			r.err = err
			return
		}
		fValue.SetInt(d)
	case reflect.String:
		fValue.SetString(dataStr)
	default:
		panic("Struct field type can only be float64, int, or string.")
	}
}

func (r Decoder) getField(index int) (out interface{}) {
	dataStr := r.ReadAttribute(r.row, index)
	var err error
	switch r.Fields()[index].Fieldtype {
	case 'F':
		out, err = shpAttributeToFloat(dataStr)
		if err != nil {
			r.err = err
			return
		}
	case 'N':
		out, err = shpAttributeToInt(dataStr)
		if err != nil {
			r.err = err
			return
		}
	case 'C', 'D': // Date fields not yet implemented
		out = dataStr
	default:
		panic("Field type can only be float64, int, or string.")
	}
	return
}

// Encode is a wrapper around the github.com/jonas-p/go-shp shapefile
// reader.
type Encoder struct {
	shp.Writer
	fieldIndices      []int
	geomIndex         int
	row               int
	createdFromStruct bool
}

// NewEncoder creates a new encoder using the path to the output shapefile
// and a data archetype which is a struct whose fields will become the
// fields in the output shapefile. The archetype struct must also contain
// a field that holds a concrete geometry type by which to set the shape type
// in the output shapefile.
func NewEncoder(filename string, archetype interface{}) (*Encoder, error) {
	var err error
	e := new(Encoder)
	e.createdFromStruct = true

	t := reflect.TypeOf(archetype)
	if t.Kind() != reflect.Struct {
		panic("Archetype must be a struct")
	}

	var shpType shp.ShapeType
	var shpFields []shp.Field
	for i := 0; i < t.NumField(); i++ {
		sField := t.Field(i)
		switch sField.Type.Kind() {
		case reflect.Int:
			shpFields = append(shpFields, shp.NumberField(sField.Name, intLength))
			e.fieldIndices = append(e.fieldIndices, i)
		case reflect.Float64:
			shpFields = append(shpFields,
				shp.FloatField(sField.Name, floatLength, floatPrecision))
			e.fieldIndices = append(e.fieldIndices, i)
		case reflect.String:
			shpFields = append(shpFields,
				shp.StringField(sField.Name, stringLength))
			e.fieldIndices = append(e.fieldIndices, i)
		case reflect.Struct, reflect.Slice:
			switch sField.Name {
			case "Point":
				shpType = shp.POINT
				e.geomIndex = i
			case "LineString":
				shpType = shp.POLYLINE
				e.geomIndex = i
			case "Polygon":
				shpType = shp.POLYGON
				e.geomIndex = i
			case "MultiPoint":
				shpType = shp.MULTIPOINT
				e.geomIndex = i
			case "PointZ":
				shpType = shp.POINTZ
				e.geomIndex = i
			case "LineStringZ":
				shpType = shp.POLYLINEZ
				e.geomIndex = i
			case "PolygonZ":
				shpType = shp.POLYGONZ
				e.geomIndex = i
			case "MultiPolygonZ":
				shpType = shp.MULTIPOINTZ
				e.geomIndex = i
			case "PointM":
				shpType = shp.POINTM
				e.geomIndex = i
			case "LineStringM":
				shpType = shp.POLYLINEM
				e.geomIndex = i
			case "PolygonM":
				shpType = shp.POLYGONM
				e.geomIndex = i
			case "MultiPointM":
				shpType = shp.MULTIPOINTM
				e.geomIndex = i
				//shpType = shp.MULTIPATCH
			}
		default:
			panic(fmt.Sprintf("Invalid type `%v` for field `%v`.",
				sField.Type.Kind(), sField.Name))
		}
	}
	if shpType == shp.NULL {
		panic("Did not find a shape field in the archetype struct")
	}

	w, err := shp.Create(filename, shpType)
	if err != nil {
		return nil, err
	}
	e.Writer = *w
	e.Writer.SetFields(shpFields)
	return e, nil
}

func NewEncoderFromFields(filename string, t shp.ShapeType,
	fields ...shp.Field) (*Encoder, error) {

	var err error
	e := new(Encoder)

	w, err := shp.Create(filename, t)
	if err != nil {
		return nil, err
	}
	e.Writer = *w
	e.Writer.SetFields(fields)

	return e, nil
}

func (e *Encoder) Close() {
	e.Writer.Close()
}

// Encode encodes the data in a struct as a shapefile record.
// d must be of the same type as the archetype struct that was used to
// initialize the encoder.
func (e *Encoder) Encode(d interface{}) error {
	if !e.createdFromStruct {
		panic("Encode can only be used for encoders created with " +
			"NewEncoder. Try EncodeFields instead.")
	}
	v := reflect.ValueOf(d)
	for i, j := range e.fieldIndices {
		e.Writer.WriteAttribute(e.row, i, v.Field(j).Interface())
	}

	shape, err := geom2Shp(v.Field(e.geomIndex).Interface().(geom.T))
	if err != nil {
		return err
	}
	e.Writer.Write(shape)
	e.row++
	return nil
}

// EncodeFields encodes the geometry 'g' and 'vals' values as a
// shapefile record. The number of values should be the same as
// the number of fields the shapefile was created with.
func (e *Encoder) EncodeFields(g geom.T, vals ...interface{}) error {
	shape, err := geom2Shp(g)
	if err != nil {
		return err
	}
	e.Writer.Write(shape)
	for i, v := range vals {
		e.Writer.WriteAttribute(e.row, i, v)
	}
	e.row++
	return nil
}
<commit_msg>changed dbf value return to all strings<commit_after>package shp

import (
	"bytes"
	"fmt"
	"reflect"
	"strconv"
	"strings"

	"github.com/ctessum/geom"
	"github.com/jonas-p/go-shp"
)

// Tag to use for matching struct fields with shapefile attributes.
// Case insensitive.
const tag = "shp"

const (
	// intLength is the integer length to use when creating shapefiles
	intLength = 10

	// floatLength is the float length to use when creating shapefiles
	floatLength = 10

	// floatPrecision is the float precision to use when creating shapefiles
	floatPrecision = 10

	// stringLength is the length of the string to use when creating shapefiles
	stringLength = 50
)

// Decoder is a wrapper around the github.com/jonas-p/go-shp shapefile
// reader.
type Decoder struct {
	shp.Reader
	row          int
	fieldIndices map[string]int
	err          error
}

func NewDecoder(filename string) (*Decoder, error) {
	fname := strings.TrimSuffix(filename, ".shp")
	r := new(Decoder)
	rr, err := shp.Open(fname + ".shp")
	if err != nil {
		return nil, err
	}
	r.Reader = *rr
	return r, err
}

func (r *Decoder) Close() {
	r.Reader.Close()
}

// getFieldIndices figures out the indices of the attribute fields
func (r *Decoder) getFieldIndices() {
	if r.fieldIndices == nil {
		r.fieldIndices = make(map[string]int)
		for i, f := range r.Fields() {
			name := strings.ToLower(shpFieldName2String(f.Name))
			r.fieldIndices[name] = i
		}
	}
}

// DecodeRow decodes a shapefile row into a struct. The input
// value rec must be a pointer to a struct. The function will
// attempt to match the struct fields to shapefile data.
// It will read the shape data into any struct fields that
// implement the geom.T interface. It will read attribute
// data into any struct fields whose `shp` tag or field names
// that match an attribute name in the shapefile (case insensitive).
// Only exported fields will be matched, and all matched fields
// must be of either string, int, or float64 types.
// The return value is true if there are still more records
// to be read from the shapefile.
// Be sure to call r.Error() after reading is finished
// to check for any errors that may have occured.
func (r *Decoder) DecodeRow(rec interface{}) bool {
	run := r.Next()
	if !run || r.err != nil {
		return false
	}
	r.getFieldIndices()
	v, t := getRecInfo(rec)
	_, shape := r.Shape()

	gI := reflect.TypeOf((*geom.T)(nil)).Elem()
	for i := 0; i < v.NumField(); i++ {
		fType := t.Field(i)
		fValue := v.Field(i)
		fName := strings.ToLower(fType.Name)
		tagName := strings.ToLower(fType.Tag.Get(tag))

		// First, check if this is a geometry field
		if fType.Type.Implements(gI) {
			_, g, err := shp2Geom(0, shape)
			if err != nil {
				r.err = err
				return false
			}
			fValue.Set(reflect.ValueOf(g))

			// Then, check the tag name
		} else if j, ok := r.fieldIndices[tagName]; ok {
			r.setFieldToAttribute(fValue, fType.Type, j)

			// Finally, check the struct field name
		} else if j, ok := r.fieldIndices[fName]; ok {
			r.setFieldToAttribute(fValue, fType.Type, j)
		}
	}
	r.row++
	return run
}

// DecodeRowFields decodes a shapefile row, returning the row
// geometry (g), the values of the specified fields (fields),
// and whether there are still more records to be read from the
// shapefile (more).
func (r *Decoder) DecodeRowFields(fieldNames ...string) (
	g geom.T, fields map[string]string, more bool) {

	fields = make(map[string]string)
	var err error

	more = r.Next()
	if !more || r.err != nil {
		return
	}

	r.getFieldIndices()

	// Get geometry
	_, shape := r.Shape()
	_, g, err = shp2Geom(0, shape)
	if err != nil {
		r.err = err
		return
	}

	// Get fields
	for _, name := range fieldNames {
		if i, ok := r.fieldIndices[strings.ToLower(name)]; ok {
			fields[name] = r.ReadAttribute(r.row, i)
			if r.err != nil {
				return
			}
		} else {
			r.err = fmt.Errorf("Shapefile does not contain field `%s`", name)
			return
		}
	}
	r.row++
	return

}

// Error returns any errors that have been encountered while decoding
// a shapfile.
func (r Decoder) Error() error {
	return r.err
}

func getRecInfo(rec interface{}) (reflect.Value, reflect.Type) {
	t := reflect.TypeOf(rec)
	if t.Kind() != reflect.Ptr {
		panic(fmt.Sprintf("rec must be a pointer to a "+
			"struct, not a %v.", t.Kind()))
	}
	v := reflect.Indirect(reflect.ValueOf(rec))
	if tt := v.Type().Kind(); tt != reflect.Struct {
		panic(fmt.Sprintf("rec must be a struct, not a %v.", tt))
	}
	return v, v.Type()
}

// ShpFieldName2String converts the shapefile field name into a
// string that can be more easily dealt with.
func shpFieldName2String(name [11]byte) string {
	b := bytes.Trim(name[:], "\x00")
	n := bytes.Index(b, []byte{0})
	if n == -1 {
		n = len(b)
	}
	return strings.TrimSpace(string(b[0:n]))
}

// shpAttrbuteToFloat converts a shapefile attribute (which may contain
// "\x00" characters to a float.
func shpAttributeToFloat(attr string) (float64, error) {
	f, err := strconv.ParseFloat(strings.Trim(attr, "\x00"), 64)
	return f, err
}

// shpAttrbuteToInt converts a shapefile attribute (which may contain
// "\x00" characters to an int.
func shpAttributeToInt(attr string) (int64, error) {
	i, err := strconv.ParseInt(strings.Trim(attr, "\x00"), 10, 64)
	return i, err
}

func (r Decoder) setFieldToAttribute(fValue reflect.Value,
	fType reflect.Type, index int) {
	dataStr := r.ReadAttribute(r.row, index)
	switch fType.Kind() {
	case reflect.Float64:
		d, err := shpAttributeToFloat(dataStr)
		if err != nil {
			r.err = err
			return
		}
		fValue.SetFloat(d)
	case reflect.Int:
		d, err := shpAttributeToInt(dataStr)
		if err != nil {
			r.err = err
			return
		}
		fValue.SetInt(d)
	case reflect.String:
		fValue.SetString(dataStr)
	default:
		panic("Struct field type can only be float64, int, or string.")
	}
}

// Encode is a wrapper around the github.com/jonas-p/go-shp shapefile
// reader.
type Encoder struct {
	shp.Writer
	fieldIndices      []int
	geomIndex         int
	row               int
	createdFromStruct bool
}

// NewEncoder creates a new encoder using the path to the output shapefile
// and a data archetype which is a struct whose fields will become the
// fields in the output shapefile. The archetype struct must also contain
// a field that holds a concrete geometry type by which to set the shape type
// in the output shapefile.
func NewEncoder(filename string, archetype interface{}) (*Encoder, error) {
	var err error
	e := new(Encoder)
	e.createdFromStruct = true

	t := reflect.TypeOf(archetype)
	if t.Kind() != reflect.Struct {
		panic("Archetype must be a struct")
	}

	var shpType shp.ShapeType
	var shpFields []shp.Field
	for i := 0; i < t.NumField(); i++ {
		sField := t.Field(i)
		switch sField.Type.Kind() {
		case reflect.Int:
			shpFields = append(shpFields, shp.NumberField(sField.Name, intLength))
			e.fieldIndices = append(e.fieldIndices, i)
		case reflect.Float64:
			shpFields = append(shpFields,
				shp.FloatField(sField.Name, floatLength, floatPrecision))
			e.fieldIndices = append(e.fieldIndices, i)
		case reflect.String:
			shpFields = append(shpFields,
				shp.StringField(sField.Name, stringLength))
			e.fieldIndices = append(e.fieldIndices, i)
		case reflect.Struct, reflect.Slice:
			switch sField.Name {
			case "Point":
				shpType = shp.POINT
				e.geomIndex = i
			case "LineString":
				shpType = shp.POLYLINE
				e.geomIndex = i
			case "Polygon":
				shpType = shp.POLYGON
				e.geomIndex = i
			case "MultiPoint":
				shpType = shp.MULTIPOINT
				e.geomIndex = i
			case "PointZ":
				shpType = shp.POINTZ
				e.geomIndex = i
			case "LineStringZ":
				shpType = shp.POLYLINEZ
				e.geomIndex = i
			case "PolygonZ":
				shpType = shp.POLYGONZ
				e.geomIndex = i
			case "MultiPolygonZ":
				shpType = shp.MULTIPOINTZ
				e.geomIndex = i
			case "PointM":
				shpType = shp.POINTM
				e.geomIndex = i
			case "LineStringM":
				shpType = shp.POLYLINEM
				e.geomIndex = i
			case "PolygonM":
				shpType = shp.POLYGONM
				e.geomIndex = i
			case "MultiPointM":
				shpType = shp.MULTIPOINTM
				e.geomIndex = i
				//shpType = shp.MULTIPATCH
			}
		default:
			panic(fmt.Sprintf("Invalid type `%v` for field `%v`.",
				sField.Type.Kind(), sField.Name))
		}
	}
	if shpType == shp.NULL {
		panic("Did not find a shape field in the archetype struct")
	}

	w, err := shp.Create(filename, shpType)
	if err != nil {
		return nil, err
	}
	e.Writer = *w
	e.Writer.SetFields(shpFields)
	return e, nil
}

func NewEncoderFromFields(filename string, t shp.ShapeType,
	fields ...shp.Field) (*Encoder, error) {

	var err error
	e := new(Encoder)

	w, err := shp.Create(filename, t)
	if err != nil {
		return nil, err
	}
	e.Writer = *w
	e.Writer.SetFields(fields)

	return e, nil
}

func (e *Encoder) Close() {
	e.Writer.Close()
}

// Encode encodes the data in a struct as a shapefile record.
// d must be of the same type as the archetype struct that was used to
// initialize the encoder.
func (e *Encoder) Encode(d interface{}) error {
	if !e.createdFromStruct {
		panic("Encode can only be used for encoders created with " +
			"NewEncoder. Try EncodeFields instead.")
	}
	v := reflect.ValueOf(d)
	for i, j := range e.fieldIndices {
		e.Writer.WriteAttribute(e.row, i, v.Field(j).Interface())
	}

	shape, err := geom2Shp(v.Field(e.geomIndex).Interface().(geom.T))
	if err != nil {
		return err
	}
	e.Writer.Write(shape)
	e.row++
	return nil
}

// EncodeFields encodes the geometry 'g' and 'vals' values as a
// shapefile record. The number of values should be the same as
// the number of fields the shapefile was created with.
func (e *Encoder) EncodeFields(g geom.T, vals ...interface{}) error {
	shape, err := geom2Shp(g)
	if err != nil {
		return err
	}
	e.Writer.Write(shape)
	for i, v := range vals {
		e.Writer.WriteAttribute(e.row, i, v)
	}
	e.row++
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Matthew Collins
//
// 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 entitysys provides a simple entity component system
// for handling entities.
package entitysys

import (
	"reflect"
)

// Stage is used to specify when a system is called.
type Stage int

const (
	// Add marks the system for being called when a entity is
	// added to a container.
	Add Stage = iota
	// Tick marks the system for being called when a entity is
	// ticked.
	Tick
	// Remove marks the system for being called when a entity is
	// removed from a container.
	Remove
)

// Container stores multiple systems and their entities.
type Container struct {
	systems     []*system
	preSystems  []*system
	postSystems []*system
}

// NewContainer creates a new Container.
func NewContainer() *Container {
	return &Container{}
}

// AddEntity adds the entity to all systems that are compatible
// with the entity.
func (c *Container) AddEntity(entity interface{}) {
	re := reflect.ValueOf(entity)
	for _, sys := range c.systems {
		if !sys.Matches(entity) {
			continue
		}
		se := &systemEntity{
			v:      re,
			params: make([]reflect.Value, len(sys.params)),
		}
		for i := range sys.params {
			se.params[i] = re
		}

		sys.entities = append(sys.entities, se)
	}
	for _, sys := range c.preSystems {
		if !sys.Matches(entity) {
			continue
		}
		params := make([]reflect.Value, len(sys.params))
		for i := range sys.params {
			params[i] = re
		}
		sys.f.Call(params)
	}
}

// RemoveEntity removes the entity from all systems it is
// attached too.
func (c *Container) RemoveEntity(e interface{}) {
	re := reflect.ValueOf(e)
	for _, sys := range c.systems {
		if !sys.Matches(e) {
			continue
		}
	seLoop:
		for i, se := range sys.entities {
			if se.v == re {
				sys.entities = append(sys.entities[:i], sys.entities[i+1:]...)
				break seLoop
			}
		}
	}
	for _, sys := range c.postSystems {
		if !sys.Matches(e) {
			continue
		}
		params := make([]reflect.Value, len(sys.params))
		for i := range sys.params {
			params[i] = re
		}
		sys.f.Call(params)
	}
}

// AddSystem adds the system to the container, the passed desc
// values will be used to match when an entity is added. f will
// called for all matching entities each 'tick'. All parameters
// to f are automatically added to matchers.
func (c *Container) AddSystem(stage Stage, f interface{}, matchers ...Matcher) {
	s := &system{
		f:        reflect.ValueOf(f),
		matchers: matchers,
	}
	t := s.f.Type()
	for i := 0; i < t.NumIn(); i++ {
		s.params = append(s.params, t.In(i))
		s.matchers = append(s.matchers, typeMatcher{Type: t.In(i)})
	}
	switch stage {
	case Add:
		c.preSystems = append(c.preSystems, s)
	case Tick:
		c.systems = append(c.systems, s)
	case Remove:
		c.postSystems = append(c.postSystems, s)
	}
}

// Tick ticks all systems and their entities.
func (c *Container) Tick() {
	for _, sys := range c.systems {
		for _, e := range sys.entities {
			sys.f.Call(e.params)
		}
	}
}

type system struct {
	f        reflect.Value
	params   []reflect.Type
	matchers []Matcher

	entities []*systemEntity
}

func (s *system) Matches(e interface{}) bool {
	for _, matcher := range s.matchers {
		if !matcher.Match(e) {
			return false
		}
	}
	return true
}

type systemEntity struct {
	v reflect.Value

	params []reflect.Value
}
<commit_msg>entitysys: update documentation<commit_after>// Copyright 2015 Matthew Collins
//
// 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 entitysys provides a simple entity component system
// for handling entities.
package entitysys

import (
	"reflect"
)

// Stage is used to specify when a system is called.
type Stage int

const (
	// Add marks the system for being called when a entity is
	// added to a container.
	Add Stage = iota
	// Tick marks the system for being called when a entity is
	// ticked.
	Tick
	// Remove marks the system for being called when a entity is
	// removed from a container.
	Remove
)

// Container stores multiple systems and their entities.
type Container struct {
	systems     []*system
	preSystems  []*system
	postSystems []*system
}

// NewContainer creates a new Container.
func NewContainer() *Container {
	return &Container{}
}

// AddEntity adds the entity to all systems that are compatible
// with the entity.
func (c *Container) AddEntity(entity interface{}) {
	re := reflect.ValueOf(entity)
	for _, sys := range c.systems {
		if !sys.Matches(entity) {
			continue
		}
		se := &systemEntity{
			v:      re,
			params: make([]reflect.Value, len(sys.params)),
		}
		for i := range sys.params {
			se.params[i] = re
		}

		sys.entities = append(sys.entities, se)
	}
	for _, sys := range c.preSystems {
		if !sys.Matches(entity) {
			continue
		}
		params := make([]reflect.Value, len(sys.params))
		for i := range sys.params {
			params[i] = re
		}
		sys.f.Call(params)
	}
}

// RemoveEntity removes the entity from all systems it is
// attached too.
func (c *Container) RemoveEntity(e interface{}) {
	re := reflect.ValueOf(e)
	for _, sys := range c.systems {
		if !sys.Matches(e) {
			continue
		}
	seLoop:
		for i, se := range sys.entities {
			if se.v == re {
				sys.entities = append(sys.entities[:i], sys.entities[i+1:]...)
				break seLoop
			}
		}
	}
	for _, sys := range c.postSystems {
		if !sys.Matches(e) {
			continue
		}
		params := make([]reflect.Value, len(sys.params))
		for i := range sys.params {
			params[i] = re
		}
		sys.f.Call(params)
	}
}

// AddSystem adds the system to the container, the passed desc
// values will be used to match when an entity is added. f will
// called for all matching entities depending on the stage. All
// parameters to f are automatically added to matchers.
func (c *Container) AddSystem(stage Stage, f interface{}, matchers ...Matcher) {
	s := &system{
		f:        reflect.ValueOf(f),
		matchers: matchers,
	}
	t := s.f.Type()
	for i := 0; i < t.NumIn(); i++ {
		s.params = append(s.params, t.In(i))
		s.matchers = append(s.matchers, typeMatcher{Type: t.In(i)})
	}
	switch stage {
	case Add:
		c.preSystems = append(c.preSystems, s)
	case Tick:
		c.systems = append(c.systems, s)
	case Remove:
		c.postSystems = append(c.postSystems, s)
	}
}

// Tick ticks all systems and their entities.
func (c *Container) Tick() {
	for _, sys := range c.systems {
		for _, e := range sys.entities {
			sys.f.Call(e.params)
		}
	}
}

type system struct {
	f        reflect.Value
	params   []reflect.Type
	matchers []Matcher

	entities []*systemEntity
}

func (s *system) Matches(e interface{}) bool {
	for _, matcher := range s.matchers {
		if !matcher.Match(e) {
			return false
		}
	}
	return true
}

type systemEntity struct {
	v reflect.Value

	params []reflect.Value
}
<|endoftext|>


<commit_before>package memory

import (
	"github.com/AutogrowSystems/faye-go/protocol"
	"github.com/AutogrowSystems/faye-go/utils"
	creg "github.com/roncohen/cleaningRegister"
	"time"
)

type ClientRegister struct {
	clients              *creg.CleaningRegister
	subscriptionRegister *SubscriptionRegister
	logger               utils.Logger
}

func NewClientRegister(logger utils.Logger) *ClientRegister {
	subReg := NewSubscriptionRegister()

	shouldRemove := func(key interface{}, item interface{}) bool {
		client := item.(*protocol.Client)
		return client.IsExpired()
	}

	removed := func(key interface{}, item interface{}) {
		client := item.(*protocol.Client)
		logger.Infof("Removing client %s due to inactivity", client.Id())
		subReg.RemoveClient(client.Id())
	}

	clientreg := ClientRegister{
		clients:              creg.New(1*time.Minute, shouldRemove, removed),
		subscriptionRegister: subReg,
		logger:               logger,
	}

	return &clientreg
}

func (cr ClientRegister) AddClient(client *protocol.Client) {
	cr.clients.Put(client.Id(), client)
}

func (cr ClientRegister) removeClient(clientId string) {
	// TODO: More cleanups
	cr.subscriptionRegister.RemoveClient(clientId)
}

func (cr ClientRegister) GetClient(clientId string) *protocol.Client {
	client, ok := cr.clients.Get(clientId)
	if ok {
		return client.(*protocol.Client)
	} else {
		return nil
	}
}

/* Front for SubscriptionRegister */

func (cr ClientRegister) AddSubscription(clientId string, patterns []string) {
	cr.subscriptionRegister.AddSubscription(clientId, patterns)
}

func (cr ClientRegister) RemoveSubscription(clientId string, patterns []string) {
	cr.subscriptionRegister.RemoveSubscription(clientId, patterns)
}

func (cr ClientRegister) GetClients(patterns []string) []string {
	return cr.subscriptionRegister.GetClients(patterns)
}
<commit_msg>mutexed the client register<commit_after>package memory

import (
	"github.com/AutogrowSystems/faye-go/protocol"
	"github.com/AutogrowSystems/faye-go/utils"
	creg "github.com/roncohen/cleaningRegister"
	"sync"
	"time"
)

type ClientRegister struct {
	clients              *creg.CleaningRegister
	subscriptionRegister *SubscriptionRegister
	logger               utils.Logger
	lock                 *sync.RWMutex
}

func NewClientRegister(logger utils.Logger) *ClientRegister {
	subReg := NewSubscriptionRegister()

	shouldRemove := func(key interface{}, item interface{}) bool {
		client := item.(*protocol.Client)
		return client.IsExpired()
	}

	removed := func(key interface{}, item interface{}) {
		client := item.(*protocol.Client)
		logger.Infof("Removing client %s due to inactivity", client.Id())
		subReg.RemoveClient(client.Id())
	}

	clientreg := ClientRegister{
		clients:              creg.New(1*time.Minute, shouldRemove, removed),
		subscriptionRegister: subReg,
		logger:               logger,
		lock:                 &sync.RWMutex{},
	}

	return &clientreg
}

func (cr ClientRegister) AddClient(client *protocol.Client) {
	cr.lock.Lock()
	defer cr.lock.Unlock()
	cr.clients.Put(client.Id(), client)
}

func (cr ClientRegister) removeClient(clientId string) {
	// TODO: More cleanups
	cr.lock.Lock()
	defer cr.lock.Unlock()
	cr.subscriptionRegister.RemoveClient(clientId)
}

func (cr ClientRegister) GetClient(clientId string) *protocol.Client {
	cr.lock.Lock()
	defer cr.lock.Unlock()
	client, ok := cr.clients.Get(clientId)
	if ok {
		return client.(*protocol.Client)
	} else {
		return nil
	}
}

/* Front for SubscriptionRegister */

func (cr ClientRegister) AddSubscription(clientId string, patterns []string) {
	cr.lock.Lock()
	defer cr.lock.Unlock()
	cr.subscriptionRegister.AddSubscription(clientId, patterns)
}

func (cr ClientRegister) RemoveSubscription(clientId string, patterns []string) {
	cr.lock.Lock()
	defer cr.lock.Unlock()
	cr.subscriptionRegister.RemoveSubscription(clientId, patterns)
}

func (cr ClientRegister) GetClients(patterns []string) []string {
	return cr.subscriptionRegister.GetClients(patterns)
}
<|endoftext|>


<commit_before>// Copyright 2016 Stratumn SAS. All rights reserved.
// Use of this source code is governed by the license
// that can be found in the LICENSE file.

package merkle_test

import (
	"flag"
	"os"
	"testing"

	"github.com/stratumn/goprivate/merkle"
	"github.com/stratumn/goprivate/merkle/treetestcases"
)

func TestMain(m *testing.M) {
	treetestcases.LoadFixtures("treetestcases/testdata")
	flag.Parse()
	os.Exit(m.Run())
}

func TestNewStaticTree(t *testing.T) {
	tree, err := merkle.NewStaticTree([]merkle.Hash{treetestcases.RandomHash()})
	if err != nil {
		t.Fatal(err)
	}
	if tree == nil {
		t.Fatal("expected tree not to be nil")
	}

	// Compiling will fail if interface is not implemented.
	_ = merkle.Tree(tree)
}

func TestNewStaticTreeNoLeaves(t *testing.T) {
	_, err := merkle.NewStaticTree(nil)
	if err == nil {
		t.Fatal("expected error not to be nil")
	}
	if err.Error() != "tree should have at least one leaf" {
		t.Log(err)
		t.Fatal("unexpected error message")
	}
}

func TestStaticTree(t *testing.T) {
	treetestcases.Factory{
		New: func(leaves []merkle.Hash) (merkle.Tree, error) {
			return merkle.NewStaticTree(leaves)
		},
	}.RunTests(t)
}

func BenchmarkStaticTree(b *testing.B) {
	treetestcases.Factory{
		New: func(leaves []merkle.Hash) (merkle.Tree, error) {
			return merkle.NewStaticTree(leaves)
		},
	}.RunBenchmarks(b)
}
<commit_msg>merkle: Remove useless test<commit_after>// Copyright 2016 Stratumn SAS. All rights reserved.
// Use of this source code is governed by the license
// that can be found in the LICENSE file.

package merkle_test

import (
	"flag"
	"os"
	"testing"

	"github.com/stratumn/goprivate/merkle"
	"github.com/stratumn/goprivate/merkle/treetestcases"
)

func TestMain(m *testing.M) {
	treetestcases.LoadFixtures("treetestcases/testdata")
	flag.Parse()
	os.Exit(m.Run())
}

func TestNewStaticTree(t *testing.T) {
	tree, err := merkle.NewStaticTree([]merkle.Hash{treetestcases.RandomHash()})
	if err != nil {
		t.Fatal(err)
	}
	if tree == nil {
		t.Fatal("expected tree not to be nil")
	}
}

func TestNewStaticTreeNoLeaves(t *testing.T) {
	_, err := merkle.NewStaticTree(nil)
	if err == nil {
		t.Fatal("expected error not to be nil")
	}
	if err.Error() != "tree should have at least one leaf" {
		t.Log(err)
		t.Fatal("unexpected error message")
	}
}

func TestStaticTree(t *testing.T) {
	treetestcases.Factory{
		New: func(leaves []merkle.Hash) (merkle.Tree, error) {
			return merkle.NewStaticTree(leaves)
		},
	}.RunTests(t)
}

func BenchmarkStaticTree(b *testing.B) {
	treetestcases.Factory{
		New: func(leaves []merkle.Hash) (merkle.Tree, error) {
			return merkle.NewStaticTree(leaves)
		},
	}.RunBenchmarks(b)
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package main

import (
	"flag"
	"regexp"

	"github.com/uber-common/bark"
	"github.com/uber/ringpop-go"
	"github.com/uber/ringpop-go/swim"

	log "github.com/Sirupsen/logrus"
	"github.com/uber/tchannel-go"
)

var (
	hostport        = flag.String("listen", "127.0.0.1:3000", "hostport to start ringpop on")
	hostfile        = flag.String("hosts", "./hosts.json", "path to hosts file")
	hostportPattern = regexp.MustCompile(`^(\d+.\d+.\d+.\d+):\d+$`)
)

func main() {
	verbose := flag.Bool("verbose", false, "enable debug level logging")
	flag.Parse()

	if !hostportPattern.MatchString(*hostport) {
		log.Fatalf("bad hostport: %s", *hostport)
	}

	ch, err := tchannel.NewChannel("ringpop", nil)
	if err != nil {
		log.Fatalf("could not create channel: %v", err)
	}

	logger := log.StandardLogger()
	if *verbose {
		logger.Level = log.DebugLevel
	}
	rp, _ := ringpop.New("ringpop",
		ringpop.Channel(ch),
		ringpop.Identity(*hostport),
		ringpop.Logger(bark.NewLoggerFromLogrus(logger)),
	)

	if err := ch.ListenAndServe(rp.WhoAmI()); err != nil {
		log.Fatalf("could not listen on %s: %v", rp.WhoAmI(), err)
	}

	opts := &swim.BootstrapOptions{}
	opts.File = *hostfile

	_, err = rp.Bootstrap(opts)
	if err != nil {
		log.Fatalf("bootstrap failed: %v", err)
	}

	// block
	select {}
}
<commit_msg>Fix testpop<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package main

import (
	"flag"
	"regexp"

	"github.com/uber-common/bark"
	"github.com/uber/ringpop-go"
	"github.com/uber/ringpop-go/swim"

	log "github.com/Sirupsen/logrus"
	"github.com/uber/tchannel-go"
)

var (
	hostport        = flag.String("listen", "127.0.0.1:3000", "hostport to start ringpop on")
	hostfile        = flag.String("hosts", "./hosts.json", "path to hosts file")
	hostportPattern = regexp.MustCompile(`^(\d+.\d+.\d+.\d+):\d+$`)
)

func main() {
	verbose := flag.Bool("verbose", false, "enable debug level logging")
	flag.Parse()

	if !hostportPattern.MatchString(*hostport) {
		log.Fatalf("bad hostport: %s", *hostport)
	}

	ch, err := tchannel.NewChannel("ringpop", nil)
	if err != nil {
		log.Fatalf("could not create channel: %v", err)
	}

	logger := log.StandardLogger()
	if *verbose {
		logger.Level = log.DebugLevel
	}
	rp, _ := ringpop.New("ringpop",
		ringpop.Channel(ch),
		ringpop.Identity(*hostport),
		ringpop.Logger(bark.NewLoggerFromLogrus(logger)),
	)

	if err := ch.ListenAndServe(*hostport); err != nil {
		log.Fatalf("could not listen on %s: %v", *hostport, err)
	}

	opts := &swim.BootstrapOptions{}
	opts.File = *hostfile

	_, err = rp.Bootstrap(opts)
	if err != nil {
		log.Fatalf("bootstrap failed: %v", err)
	}

	// block
	select {}
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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 testapi provides a helper for retrieving the KUBE_TEST_API environment variable.
package testapi

import (
	"fmt"
	"os"
	"strings"

	"k8s.io/kubernetes/pkg/api"
	_ "k8s.io/kubernetes/pkg/api/install"
	_ "k8s.io/kubernetes/pkg/apis/extensions/install"

	"k8s.io/kubernetes/pkg/api/latest"
	"k8s.io/kubernetes/pkg/api/meta"
	apiutil "k8s.io/kubernetes/pkg/api/util"
	"k8s.io/kubernetes/pkg/runtime"
)

var (
	Groups       = make(map[string]TestGroup)
	Default      TestGroup
	Experimental TestGroup
)

type TestGroup struct {
	// Name of the group
	Group string
	// Version of the group Group under test
	VersionUnderTest string
	// Group and Version. In most cases equals to Group + "/" + VersionUnverTest
	GroupVersionUnderTest string
}

func init() {
	kubeTestAPI := os.Getenv("KUBE_TEST_API")
	if kubeTestAPI != "" {
		testGroupVersions := strings.Split(kubeTestAPI, ",")
		for _, groupVersion := range testGroupVersions {
			// TODO: caesarxuchao: the apiutil package is hacky, it will be replaced
			// by a following PR.
			Groups[apiutil.GetGroup(groupVersion)] =
				TestGroup{apiutil.GetGroup(groupVersion), apiutil.GetVersion(groupVersion), groupVersion}
		}
	}

	// TODO: caesarxuchao: we need a central place to store all available API
	// groups and their metadata.
	if _, ok := Groups[""]; !ok {
		// TODO: The second latest.GroupOrDie("").Version will be latest.GroupVersion after we
		// have multiple group support
		Groups[""] = TestGroup{"", latest.GroupOrDie("").Version, latest.GroupOrDie("").GroupVersion}
	}
	if _, ok := Groups["extensions"]; !ok {
		Groups["extensions"] = TestGroup{"extensions", latest.GroupOrDie("extensions").Version, latest.GroupOrDie("extensions").GroupVersion}
	}

	Default = Groups[""]
	Experimental = Groups["extensions"]
}

// Version returns the API version to test against, as set by the KUBE_TEST_API env var.
func (g TestGroup) Version() string {
	return g.VersionUnderTest
}

// GroupAndVersion returns the API version to test against for a group, as set
// by the KUBE_TEST_API env var.
// Return value is in the form of "group/version".
func (g TestGroup) GroupAndVersion() string {
	return g.GroupVersionUnderTest
}

// Codec returns the codec for the API version to test against, as set by the
// KUBE_TEST_API env var.
func (g TestGroup) Codec() runtime.Codec {
	// TODO: caesarxuchao: Restructure the body once we have a central `latest`.
	if g.Group == "" {
		interfaces, err := latest.GroupOrDie("").InterfacesFor(g.GroupVersionUnderTest)
		if err != nil {
			panic(err)
		}
		return interfaces.Codec
	}
	if g.Group == "extensions" {
		interfaces, err := latest.GroupOrDie("extensions").InterfacesFor(g.GroupVersionUnderTest)
		if err != nil {
			panic(err)
		}
		return interfaces.Codec
	}
	panic(fmt.Errorf("cannot test group %s", g.Group))
}

// Converter returns the api.Scheme for the API version to test against, as set by the
// KUBE_TEST_API env var.
func (g TestGroup) Converter() runtime.ObjectConvertor {
	// TODO: caesarxuchao: Restructure the body once we have a central `latest`.
	if g.Group == "" {
		interfaces, err := latest.GroupOrDie("").InterfacesFor(g.VersionUnderTest)
		if err != nil {
			panic(err)
		}
		return interfaces.ObjectConvertor
	}
	if g.Group == "extensions" {
		interfaces, err := latest.GroupOrDie("extensions").InterfacesFor(g.VersionUnderTest)
		if err != nil {
			panic(err)
		}
		return interfaces.ObjectConvertor
	}
	panic(fmt.Errorf("cannot test group %s", g.Group))

}

// MetadataAccessor returns the MetadataAccessor for the API version to test against,
// as set by the KUBE_TEST_API env var.
func (g TestGroup) MetadataAccessor() meta.MetadataAccessor {
	// TODO: caesarxuchao: Restructure the body once we have a central `latest`.
	if g.Group == "" {
		interfaces, err := latest.GroupOrDie("").InterfacesFor(g.VersionUnderTest)
		if err != nil {
			panic(err)
		}
		return interfaces.MetadataAccessor
	}
	if g.Group == "extensions" {
		interfaces, err := latest.GroupOrDie("extensions").InterfacesFor(g.VersionUnderTest)
		if err != nil {
			panic(err)
		}
		return interfaces.MetadataAccessor
	}
	panic(fmt.Errorf("cannot test group %s", g.Group))
}

// SelfLink returns a self link that will appear to be for the version Version().
// 'resource' should be the resource path, e.g. "pods" for the Pod type. 'name' should be
// empty for lists.
func (g TestGroup) SelfLink(resource, name string) string {
	if g.Group == "" {
		if name == "" {
			return fmt.Sprintf("/api/%s/%s", g.Version(), resource)
		}
		return fmt.Sprintf("/api/%s/%s/%s", g.Version(), resource, name)
	} else {
		// TODO: will need a /apis prefix once we have proper multi-group
		// support
		if name == "" {
			return fmt.Sprintf("/apis/%s/%s/%s", g.Group, g.Version(), resource)
		}
		return fmt.Sprintf("/apis/%s/%s/%s/%s", g.Group, g.Version(), resource, name)
	}
}

// Returns the appropriate path for the given prefix (watch, proxy, redirect, etc), resource, namespace and name.
// For ex, this is of the form:
// /api/v1/watch/namespaces/foo/pods/pod0 for v1.
func (g TestGroup) ResourcePathWithPrefix(prefix, resource, namespace, name string) string {
	var path string
	if len(g.Group) == 0 {
		path = "/api/" + g.Version()
	} else {
		// TODO: switch back once we have proper multiple group support
		// path = "/apis/" + g.Group + "/" + Version(group...)
		path = "/apis/" + g.Group + "/" + g.Version()
	}

	if prefix != "" {
		path = path + "/" + prefix
	}
	if namespace != "" {
		path = path + "/namespaces/" + namespace
	}
	// Resource names are lower case.
	resource = strings.ToLower(resource)
	if resource != "" {
		path = path + "/" + resource
	}
	if name != "" {
		path = path + "/" + name
	}
	return path
}

// Returns the appropriate path for the given resource, namespace and name.
// For example, this is of the form:
// /api/v1/namespaces/foo/pods/pod0 for v1.
func (g TestGroup) ResourcePath(resource, namespace, name string) string {
	return g.ResourcePathWithPrefix("", resource, namespace, name)
}

func (g TestGroup) RESTMapper() meta.RESTMapper {
	return latest.GroupOrDie(g.Group).RESTMapper
}

// Get codec based on runtime.Object
func GetCodecForObject(obj runtime.Object) (runtime.Codec, error) {
	_, kind, err := api.Scheme.ObjectVersionAndKind(obj)
	if err != nil {
		return nil, fmt.Errorf("unexpected encoding error: %v", err)
	}
	// TODO: caesarxuchao: we should detect which group an object belongs to
	// by using the version returned by Schem.ObjectVersionAndKind() once we
	// split the schemes for internal objects.
	// TODO: caesarxuchao: we should add a map from kind to group in Scheme.
	for _, group := range Groups {
		if api.Scheme.Recognizes(group.GroupAndVersion(), kind) {
			return group.Codec(), nil
		}
	}
	return nil, fmt.Errorf("unexpected kind: %v", kind)
}
<commit_msg>manual fix testapi<commit_after>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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 testapi provides a helper for retrieving the KUBE_TEST_API environment variable.
package testapi

import (
	"fmt"
	"os"
	"strings"

	"k8s.io/kubernetes/pkg/api"
	_ "k8s.io/kubernetes/pkg/api/install"
	_ "k8s.io/kubernetes/pkg/apis/extensions/install"

	"k8s.io/kubernetes/pkg/api/latest"
	"k8s.io/kubernetes/pkg/api/meta"
	apiutil "k8s.io/kubernetes/pkg/api/util"
	"k8s.io/kubernetes/pkg/runtime"
)

var (
	Groups     = make(map[string]TestGroup)
	Default    TestGroup
	Extensions TestGroup
)

type TestGroup struct {
	// Name of the group
	Group string
	// Version of the group Group under test
	VersionUnderTest string
	// Group and Version. In most cases equals to Group + "/" + VersionUnverTest
	GroupVersionUnderTest string
}

func init() {
	kubeTestAPI := os.Getenv("KUBE_TEST_API")
	if kubeTestAPI != "" {
		testGroupVersions := strings.Split(kubeTestAPI, ",")
		for _, groupVersion := range testGroupVersions {
			// TODO: caesarxuchao: the apiutil package is hacky, it will be replaced
			// by a following PR.
			Groups[apiutil.GetGroup(groupVersion)] =
				TestGroup{apiutil.GetGroup(groupVersion), apiutil.GetVersion(groupVersion), groupVersion}
		}
	}

	// TODO: caesarxuchao: we need a central place to store all available API
	// groups and their metadata.
	if _, ok := Groups[""]; !ok {
		// TODO: The second latest.GroupOrDie("").Version will be latest.GroupVersion after we
		// have multiple group support
		Groups[""] = TestGroup{"", latest.GroupOrDie("").Version, latest.GroupOrDie("").GroupVersion}
	}
	if _, ok := Groups["extensions"]; !ok {
		Groups["extensions"] = TestGroup{"extensions", latest.GroupOrDie("extensions").Version, latest.GroupOrDie("extensions").GroupVersion}
	}

	Default = Groups[""]
	Extensions = Groups["extensions"]
}

// Version returns the API version to test against, as set by the KUBE_TEST_API env var.
func (g TestGroup) Version() string {
	return g.VersionUnderTest
}

// GroupAndVersion returns the API version to test against for a group, as set
// by the KUBE_TEST_API env var.
// Return value is in the form of "group/version".
func (g TestGroup) GroupAndVersion() string {
	return g.GroupVersionUnderTest
}

// Codec returns the codec for the API version to test against, as set by the
// KUBE_TEST_API env var.
func (g TestGroup) Codec() runtime.Codec {
	// TODO: caesarxuchao: Restructure the body once we have a central `latest`.
	if g.Group == "" {
		interfaces, err := latest.GroupOrDie("").InterfacesFor(g.GroupVersionUnderTest)
		if err != nil {
			panic(err)
		}
		return interfaces.Codec
	}
	if g.Group == "extensions" {
		interfaces, err := latest.GroupOrDie("extensions").InterfacesFor(g.GroupVersionUnderTest)
		if err != nil {
			panic(err)
		}
		return interfaces.Codec
	}
	panic(fmt.Errorf("cannot test group %s", g.Group))
}

// Converter returns the api.Scheme for the API version to test against, as set by the
// KUBE_TEST_API env var.
func (g TestGroup) Converter() runtime.ObjectConvertor {
	// TODO: caesarxuchao: Restructure the body once we have a central `latest`.
	if g.Group == "" {
		interfaces, err := latest.GroupOrDie("").InterfacesFor(g.VersionUnderTest)
		if err != nil {
			panic(err)
		}
		return interfaces.ObjectConvertor
	}
	if g.Group == "extensions" {
		interfaces, err := latest.GroupOrDie("extensions").InterfacesFor(g.VersionUnderTest)
		if err != nil {
			panic(err)
		}
		return interfaces.ObjectConvertor
	}
	panic(fmt.Errorf("cannot test group %s", g.Group))

}

// MetadataAccessor returns the MetadataAccessor for the API version to test against,
// as set by the KUBE_TEST_API env var.
func (g TestGroup) MetadataAccessor() meta.MetadataAccessor {
	// TODO: caesarxuchao: Restructure the body once we have a central `latest`.
	if g.Group == "" {
		interfaces, err := latest.GroupOrDie("").InterfacesFor(g.VersionUnderTest)
		if err != nil {
			panic(err)
		}
		return interfaces.MetadataAccessor
	}
	if g.Group == "extensions" {
		interfaces, err := latest.GroupOrDie("extensions").InterfacesFor(g.VersionUnderTest)
		if err != nil {
			panic(err)
		}
		return interfaces.MetadataAccessor
	}
	panic(fmt.Errorf("cannot test group %s", g.Group))
}

// SelfLink returns a self link that will appear to be for the version Version().
// 'resource' should be the resource path, e.g. "pods" for the Pod type. 'name' should be
// empty for lists.
func (g TestGroup) SelfLink(resource, name string) string {
	if g.Group == "" {
		if name == "" {
			return fmt.Sprintf("/api/%s/%s", g.Version(), resource)
		}
		return fmt.Sprintf("/api/%s/%s/%s", g.Version(), resource, name)
	} else {
		// TODO: will need a /apis prefix once we have proper multi-group
		// support
		if name == "" {
			return fmt.Sprintf("/apis/%s/%s/%s", g.Group, g.Version(), resource)
		}
		return fmt.Sprintf("/apis/%s/%s/%s/%s", g.Group, g.Version(), resource, name)
	}
}

// Returns the appropriate path for the given prefix (watch, proxy, redirect, etc), resource, namespace and name.
// For ex, this is of the form:
// /api/v1/watch/namespaces/foo/pods/pod0 for v1.
func (g TestGroup) ResourcePathWithPrefix(prefix, resource, namespace, name string) string {
	var path string
	if len(g.Group) == 0 {
		path = "/api/" + g.Version()
	} else {
		// TODO: switch back once we have proper multiple group support
		// path = "/apis/" + g.Group + "/" + Version(group...)
		path = "/apis/" + g.Group + "/" + g.Version()
	}

	if prefix != "" {
		path = path + "/" + prefix
	}
	if namespace != "" {
		path = path + "/namespaces/" + namespace
	}
	// Resource names are lower case.
	resource = strings.ToLower(resource)
	if resource != "" {
		path = path + "/" + resource
	}
	if name != "" {
		path = path + "/" + name
	}
	return path
}

// Returns the appropriate path for the given resource, namespace and name.
// For example, this is of the form:
// /api/v1/namespaces/foo/pods/pod0 for v1.
func (g TestGroup) ResourcePath(resource, namespace, name string) string {
	return g.ResourcePathWithPrefix("", resource, namespace, name)
}

func (g TestGroup) RESTMapper() meta.RESTMapper {
	return latest.GroupOrDie(g.Group).RESTMapper
}

// Get codec based on runtime.Object
func GetCodecForObject(obj runtime.Object) (runtime.Codec, error) {
	_, kind, err := api.Scheme.ObjectVersionAndKind(obj)
	if err != nil {
		return nil, fmt.Errorf("unexpected encoding error: %v", err)
	}
	// TODO: caesarxuchao: we should detect which group an object belongs to
	// by using the version returned by Schem.ObjectVersionAndKind() once we
	// split the schemes for internal objects.
	// TODO: caesarxuchao: we should add a map from kind to group in Scheme.
	for _, group := range Groups {
		if api.Scheme.Recognizes(group.GroupAndVersion(), kind) {
			return group.Codec(), nil
		}
	}
	return nil, fmt.Errorf("unexpected kind: %v", kind)
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Google Inc. All rights reserved.

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 client

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strconv"
	"strings"
	"testing"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)

func TestHTTPKubeletClient(t *testing.T) {
	expectObj := api.PodInfo{
		"myID": api.ContainerStatus{},
	}
	body, err := json.Marshal(expectObj)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	fakeHandler := util.FakeHandler{
		StatusCode:   200,
		ResponseBody: string(body),
	}
	testServer := httptest.NewServer(&fakeHandler)
	defer testServer.Close()

	hostURL, err := url.Parse(testServer.URL)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	parts := strings.Split(hostURL.Host, ":")

	port, err := strconv.Atoi(parts[1])
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	podInfoGetter := &HTTPKubeletClient{
		Client: http.DefaultClient,
		Port:   uint(port),
	}
	gotObj, err := podInfoGetter.GetPodInfo(parts[0], api.NamespaceDefault, "foo")
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	// reflect.DeepEqual(expectObj, gotObj) doesn't handle blank times well
	if len(gotObj) != len(expectObj) {
		t.Errorf("Unexpected response.  Expected: %#v, received %#v", expectObj, gotObj)
	}
}

func TestHTTPKubeletClientNotFound(t *testing.T) {
	expectObj := api.PodInfo{
		"myID": api.ContainerStatus{},
	}
	_, err := json.Marshal(expectObj)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	fakeHandler := util.FakeHandler{
		StatusCode:   404,
		ResponseBody: "Pod not found",
	}
	testServer := httptest.NewServer(&fakeHandler)
	defer testServer.Close()

	hostURL, err := url.Parse(testServer.URL)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	parts := strings.Split(hostURL.Host, ":")

	port, err := strconv.Atoi(parts[1])
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	podInfoGetter := &HTTPKubeletClient{
		Client: http.DefaultClient,
		Port:   uint(port),
	}
	_, err = podInfoGetter.GetPodInfo(parts[0], api.NamespaceDefault, "foo")
	if err != ErrPodInfoNotAvailable {
		t.Errorf("Expected %#v, Got %#v", ErrPodInfoNotAvailable, err)
	}
}

func TestNewKubeletClient(t *testing.T) {
	config := &KubeletConfig{
		Port:        9000,
		EnableHttps: false,
	}
	client, err := NewKubeletClient(config)
	if err != nil {
		t.Errorf("Error %#v while trying to create a client.", err)
	}

	if client == nil {
		t.Errorf("%#v client is nil.", client)
	}
	host := "127.0.0.1"
	healthStatus, err := client.HealthCheck(host)
	if !(fmt.Sprintf("%v", healthStatus) == "unknown") {
		t.Errorf("Expected %v and got %v.", "unknown", healthStatus)
	}
	if err == nil {
		t.Errorf("%#v", "Expected a non nil error")
	}

}
<commit_msg>simplified TestNewKubeletClient in kubelet_test<commit_after>/*
Copyright 2014 Google Inc. All rights reserved.

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 client

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strconv"
	"strings"
	"testing"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/health"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)

func TestHTTPKubeletClient(t *testing.T) {
	expectObj := api.PodInfo{
		"myID": api.ContainerStatus{},
	}
	body, err := json.Marshal(expectObj)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	fakeHandler := util.FakeHandler{
		StatusCode:   200,
		ResponseBody: string(body),
	}
	testServer := httptest.NewServer(&fakeHandler)
	defer testServer.Close()

	hostURL, err := url.Parse(testServer.URL)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	parts := strings.Split(hostURL.Host, ":")

	port, err := strconv.Atoi(parts[1])
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	podInfoGetter := &HTTPKubeletClient{
		Client: http.DefaultClient,
		Port:   uint(port),
	}
	gotObj, err := podInfoGetter.GetPodInfo(parts[0], api.NamespaceDefault, "foo")
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	// reflect.DeepEqual(expectObj, gotObj) doesn't handle blank times well
	if len(gotObj) != len(expectObj) {
		t.Errorf("Unexpected response.  Expected: %#v, received %#v", expectObj, gotObj)
	}
}

func TestHTTPKubeletClientNotFound(t *testing.T) {
	expectObj := api.PodInfo{
		"myID": api.ContainerStatus{},
	}
	_, err := json.Marshal(expectObj)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	fakeHandler := util.FakeHandler{
		StatusCode:   404,
		ResponseBody: "Pod not found",
	}
	testServer := httptest.NewServer(&fakeHandler)
	defer testServer.Close()

	hostURL, err := url.Parse(testServer.URL)
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	parts := strings.Split(hostURL.Host, ":")

	port, err := strconv.Atoi(parts[1])
	if err != nil {
		t.Errorf("unexpected error: %v", err)
	}

	podInfoGetter := &HTTPKubeletClient{
		Client: http.DefaultClient,
		Port:   uint(port),
	}
	_, err = podInfoGetter.GetPodInfo(parts[0], api.NamespaceDefault, "foo")
	if err != ErrPodInfoNotAvailable {
		t.Errorf("Expected %#v, Got %#v", ErrPodInfoNotAvailable, err)
	}
}

func TestNewKubeletClient(t *testing.T) {
	config := &KubeletConfig{
		Port:        9000,
		EnableHttps: false,
	}

	client, err := NewKubeletClient(config)
	if err != nil {
		t.Errorf("Error while trying to create a client: %v", err)
	}
	if client == nil {
		t.Error("client is nil.")
	}

	host := "127.0.0.1"
	healthStatus, err := client.HealthCheck(host)
	if healthStatus != health.Unknown {
		t.Errorf("Expected %v and got %v.", health.Unknown, healthStatus)
	}
	if err == nil {
		t.Error("Expected a non nil error")
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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 cloudprovider

import (
	"errors"
	"fmt"
	"net"
	"strings"

	"k8s.io/kubernetes/pkg/api"
)

// Interface is an abstract, pluggable interface for cloud providers.
type Interface interface {
	// TCPLoadBalancer returns a balancer interface. Also returns true if the interface is supported, false otherwise.
	TCPLoadBalancer() (TCPLoadBalancer, bool)
	// Instances returns an instances interface. Also returns true if the interface is supported, false otherwise.
	Instances() (Instances, bool)
	// Zones returns a zones interface. Also returns true if the interface is supported, false otherwise.
	Zones() (Zones, bool)
	// Clusters returns a clusters interface.  Also returns true if the interface is supported, false otherwise.
	Clusters() (Clusters, bool)
	// Routes returns a routes interface along with whether the interface is supported.
	Routes() (Routes, bool)
	// ProviderName returns the cloud provider ID.
	ProviderName() string
}

// Clusters is an abstract, pluggable interface for clusters of containers.
type Clusters interface {
	// List lists the names of the available clusters.
	ListClusters() ([]string, error)
	// Master gets back the address (either DNS name or IP address) of the master node for the cluster.
	Master(clusterName string) (string, error)
}

// TODO(#6812): Use a shorter name that's less likely to be longer than cloud
// providers' name length limits.
func GetLoadBalancerName(service *api.Service) string {
	//GCE requires that the name of a load balancer starts with a lower case letter.
	ret := "a" + string(service.UID)
	ret = strings.Replace(ret, "-", "", -1)
	//AWS requires that the name of a load balancer is shorter than 32 bytes.
	if len(ret) > 32 {
		ret = ret[:32]
	}
	return ret
}

func GetInstanceProviderID(cloud Interface, nodeName string) (string, error) {
	instances, ok := cloud.Instances()
	if !ok {
		return "", fmt.Errorf("failed to get instances from cloud provider")
	}
	instanceID, err := instances.InstanceID(nodeName)
	if err != nil {
		return "", fmt.Errorf("failed to get instance ID from cloud provider: %v", err)
	}
	return cloud.ProviderName() + "://" + instanceID, nil
}

// TCPLoadBalancer is an abstract, pluggable interface for TCP load balancers.
type TCPLoadBalancer interface {
	// TODO: Break this up into different interfaces (LB, etc) when we have more than one type of service
	// GetTCPLoadBalancer returns whether the specified load balancer exists, and
	// if so, what its status is.
	GetTCPLoadBalancer(name, region string) (status *api.LoadBalancerStatus, exists bool, err error)
	// EnsureTCPLoadBalancer creates a new tcp load balancer, or updates an existing one. Returns the status of the balancer
	EnsureTCPLoadBalancer(name, region string, loadBalancerIP net.IP, ports []*api.ServicePort, hosts []string, affinityType api.ServiceAffinity) (*api.LoadBalancerStatus, error)
	// UpdateTCPLoadBalancer updates hosts under the specified load balancer.
	UpdateTCPLoadBalancer(name, region string, hosts []string) error
	// EnsureTCPLoadBalancerDeleted deletes the specified load balancer if it
	// exists, returning nil if the load balancer specified either didn't exist or
	// was successfully deleted.
	// This construction is useful because many cloud providers' load balancers
	// have multiple underlying components, meaning a Get could say that the LB
	// doesn't exist even if some part of it is still laying around.
	EnsureTCPLoadBalancerDeleted(name, region string) error
}

// Instances is an abstract, pluggable interface for sets of instances.
type Instances interface {
	// NodeAddresses returns the addresses of the specified instance.
	// TODO(roberthbailey): This currently is only used in such a way that it
	// returns the address of the calling instance. We should do a rename to
	// make this clearer.
	NodeAddresses(name string) ([]api.NodeAddress, error)
	// ExternalID returns the cloud provider ID of the specified instance (deprecated).
	ExternalID(name string) (string, error)
	// InstanceID returns the cloud provider ID of the specified instance.
	// Note that if the instance does not exist or is no longer running, we must return ("", cloudprovider.InstanceNotFound)
	InstanceID(name string) (string, error)
	// List lists instances that match 'filter' which is a regular expression which must match the entire instance name (fqdn)
	List(filter string) ([]string, error)
	// AddSSHKeyToAllInstances adds an SSH public key as a legal identity for all instances
	// expected format for the key is standard ssh-keygen format: <protocol> <blob>
	AddSSHKeyToAllInstances(user string, keyData []byte) error
	// Returns the name of the node we are currently running on
	// On most clouds (e.g. GCE) this is the hostname, so we provide the hostname
	CurrentNodeName(hostname string) (string, error)
}

// Route is a representation of an advanced routing rule.
type Route struct {
	// Name is the name of the routing rule in the cloud-provider.
	// It will be ignored in a Create (although nameHint may influence it)
	Name string
	// TargetInstance is the name of the instance as specified in routing rules
	// for the cloud-provider (in gce: the Instance Name).
	TargetInstance string
	// Destination CIDR is the CIDR format IP range that this routing rule
	// applies to.
	DestinationCIDR string
}

// Routes is an abstract, pluggable interface for advanced routing rules.
type Routes interface {
	// List all managed routes that belong to the specified clusterName
	ListRoutes(clusterName string) ([]*Route, error)
	// Create the described managed route
	// route.Name will be ignored, although the cloud-provider may use nameHint
	// to create a more user-meaningful name.
	CreateRoute(clusterName string, nameHint string, route *Route) error
	// Delete the specified managed route
	// Route should be as returned by ListRoutes
	DeleteRoute(clusterName string, route *Route) error
}

var InstanceNotFound = errors.New("instance not found")

// Zone represents the location of a particular machine.
type Zone struct {
	FailureDomain string
	Region        string
}

// Zones is an abstract, pluggable interface for zone enumeration.
type Zones interface {
	// GetZone returns the Zone containing the current failure zone and locality region that the program is running in
	GetZone() (Zone, error)
}
<commit_msg>Fixed some typos and improved comments<commit_after>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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 cloudprovider

import (
	"errors"
	"fmt"
	"net"
	"strings"

	"k8s.io/kubernetes/pkg/api"
)

// Interface is an abstract, pluggable interface for cloud providers.
type Interface interface {
	// TCPLoadBalancer returns a balancer interface. Also returns true if the interface is supported, false otherwise.
	TCPLoadBalancer() (TCPLoadBalancer, bool)
	// Instances returns an instances interface. Also returns true if the interface is supported, false otherwise.
	Instances() (Instances, bool)
	// Zones returns a zones interface. Also returns true if the interface is supported, false otherwise.
	Zones() (Zones, bool)
	// Clusters returns a clusters interface.  Also returns true if the interface is supported, false otherwise.
	Clusters() (Clusters, bool)
	// Routes returns a routes interface along with whether the interface is supported.
	Routes() (Routes, bool)
	// ProviderName returns the cloud provider ID.
	ProviderName() string
}

// Clusters is an abstract, pluggable interface for clusters of containers.
type Clusters interface {
	// ListClusters lists the names of the available clusters.
	ListClusters() ([]string, error)
	// Master gets back the address (either DNS name or IP address) of the master node for the cluster.
	Master(clusterName string) (string, error)
}

// TODO(#6812): Use a shorter name that's less likely to be longer than cloud
// providers' name length limits.
func GetLoadBalancerName(service *api.Service) string {
	//GCE requires that the name of a load balancer starts with a lower case letter.
	ret := "a" + string(service.UID)
	ret = strings.Replace(ret, "-", "", -1)
	//AWS requires that the name of a load balancer is shorter than 32 bytes.
	if len(ret) > 32 {
		ret = ret[:32]
	}
	return ret
}

func GetInstanceProviderID(cloud Interface, nodeName string) (string, error) {
	instances, ok := cloud.Instances()
	if !ok {
		return "", fmt.Errorf("failed to get instances from cloud provider")
	}
	instanceID, err := instances.InstanceID(nodeName)
	if err != nil {
		return "", fmt.Errorf("failed to get instance ID from cloud provider: %v", err)
	}
	return cloud.ProviderName() + "://" + instanceID, nil
}

// TCPLoadBalancer is an abstract, pluggable interface for TCP load balancers.
type TCPLoadBalancer interface {
	// TODO: Break this up into different interfaces (LB, etc) when we have more than one type of service
	// GetTCPLoadBalancer returns whether the specified load balancer exists, and
	// if so, what its status is.
	GetTCPLoadBalancer(name, region string) (status *api.LoadBalancerStatus, exists bool, err error)
	// EnsureTCPLoadBalancer creates a new tcp load balancer, or updates an existing one. Returns the status of the balancer
	EnsureTCPLoadBalancer(name, region string, loadBalancerIP net.IP, ports []*api.ServicePort, hosts []string, affinityType api.ServiceAffinity) (*api.LoadBalancerStatus, error)
	// UpdateTCPLoadBalancer updates hosts under the specified load balancer.
	UpdateTCPLoadBalancer(name, region string, hosts []string) error
	// EnsureTCPLoadBalancerDeleted deletes the specified load balancer if it
	// exists, returning nil if the load balancer specified either didn't exist or
	// was successfully deleted.
	// This construction is useful because many cloud providers' load balancers
	// have multiple underlying components, meaning a Get could say that the LB
	// doesn't exist even if some part of it is still laying around.
	EnsureTCPLoadBalancerDeleted(name, region string) error
}

// Instances is an abstract, pluggable interface for sets of instances.
type Instances interface {
	// NodeAddresses returns the addresses of the specified instance.
	// TODO(roberthbailey): This currently is only used in such a way that it
	// returns the address of the calling instance. We should do a rename to
	// make this clearer.
	NodeAddresses(name string) ([]api.NodeAddress, error)
	// ExternalID returns the cloud provider ID of the specified instance (deprecated).
	ExternalID(name string) (string, error)
	// InstanceID returns the cloud provider ID of the specified instance.
	// Note that if the instance does not exist or is no longer running, we must return ("", cloudprovider.InstanceNotFound)
	InstanceID(name string) (string, error)
	// List lists instances that match 'filter' which is a regular expression which must match the entire instance name (fqdn)
	List(filter string) ([]string, error)
	// AddSSHKeyToAllInstances adds an SSH public key as a legal identity for all instances
	// expected format for the key is standard ssh-keygen format: <protocol> <blob>
	AddSSHKeyToAllInstances(user string, keyData []byte) error
	// CurrentNodeName returns the name of the node we are currently running on
	// On most clouds (e.g. GCE) this is the hostname, so we provide the hostname
	CurrentNodeName(hostname string) (string, error)
}

// Route is a representation of an advanced routing rule.
type Route struct {
	// Name is the name of the routing rule in the cloud-provider.
	// It will be ignored in a Create (although nameHint may influence it)
	Name string
	// TargetInstance is the name of the instance as specified in routing rules
	// for the cloud-provider (in gce: the Instance Name).
	TargetInstance string
	// DestinationCIDR is the CIDR format IP range that this routing rule
	// applies to.
	DestinationCIDR string
}

// Routes is an abstract, pluggable interface for advanced routing rules.
type Routes interface {
	// ListRoutes lists all managed routes that belong to the specified clusterName
	ListRoutes(clusterName string) ([]*Route, error)
	// CreateRoute creates the described managed route
	// route.Name will be ignored, although the cloud-provider may use nameHint
	// to create a more user-meaningful name.
	CreateRoute(clusterName string, nameHint string, route *Route) error
	// DeleteRoute deletes the specified managed route
	// Route should be as returned by ListRoutes
	DeleteRoute(clusterName string, route *Route) error
}

var InstanceNotFound = errors.New("instance not found")

// Zone represents the location of a particular machine.
type Zone struct {
	FailureDomain string
	Region        string
}

// Zones is an abstract, pluggable interface for zone enumeration.
type Zones interface {
	// GetZone returns the Zone containing the current failure zone and locality region that the program is running in
	GetZone() (Zone, error)
}
<|endoftext|>