<commit_before>package tusd

import (
	"io"
)

type MetaData map[string]string

type FileInfo struct {
	ID string
	// Total file size in bytes specified in the NewUpload call
	Size int64
	// Offset in bytes (zero-based)
	Offset   int64
	MetaData MetaData
	// Indicates that this is a partial upload which will later be used to form
	// a final upload by concatenation. Partial uploads should not be processed
	// when they are finished since they are only incomplete chunks of files.
	IsPartial bool
	// Indicates that this is a final upload
	IsFinal bool
	// If the upload is a final one (see IsFinal) this will be a non-empty
	// ordered slice containing the ids of the uploads of which the final upload
	// will consist after concatenation.
	PartialUploads []string
}

type DataStore interface {
	// Create a new upload using the size as the file's length. The method must
	// return an unique id which is used to identify the upload. If no backend
	// (e.g. Riak) specifes the id you may want to use the uid package to
	// generate one. The properties Size and MetaData will be filled.
	NewUpload(info FileInfo) (id string, err error)
	// Write the chunk read from src into the file specified by the id at the
	// given offset. The handler will take care of validating the offset and
	// limiting the size of the src to not overflow the file's size. It may
	// return an os.ErrNotExist which will be interpreted as a 404 Not Found.
	// It will also lock resources while they are written to ensure only one
	// write happens per time.
	// The function call must return the number of bytes written.
	WriteChunk(id string, offset int64, src io.Reader) (int64, error)
	// Read the fileinformation used to validate the offset and respond to HEAD
	// requests. It may return an os.ErrNotExist which will be interpreted as a
	// 404 Not Found.
	GetInfo(id string) (FileInfo, error)
}

// TerminaterDataStore is the interface which must be implemented by DataStores
// if they want to receive DELETE requests using the Handler. If this interface
// is not implemented, no request handler for this method is attached.
type TerminaterDataStore interface {
	// Terminate an upload so any further requests to the resource, both reading
	// and writing, must return os.ErrNotExist or similar.
	Terminate(id string) error
}

// FinisherDataStore is the interface which can be implemented by DataStores
// which need to do additional operations once an entire upload has been
// completed. These tasks may include but are not limited to freeing unused
// resources or notifying other services. For example, S3Store uses this
// interface for removing a temporary object.
type FinisherDataStore interface {
	// FinishUpload executes additional operations for the finished upload which
	// is specified by its ID.
	FinishUpload(id string) error
}

// LockerDataStore is the interface required for custom lock persisting mechanisms.
// Common ways to store this information is in memory, on disk or using an
// external service, such as ZooKeeper.
// When multiple processes are attempting to access an upload, whether it be
// by reading or writing, a synchronization mechanism is required to prevent
// data corruption, especially to ensure correct offset values and the proper
// order of chunks inside a single upload.
type LockerDataStore interface {
	// LockUpload attempts to obtain an exclusive lock for the upload specified
	// by its id.
	// If this operation fails because the resource is already locked, the
	// tusd.ErrFileLocked must be returned. If no error is returned, the attempt
	// is consider to be successful and the upload to be locked until UnlockUpload
	// is invoked for the same upload.
	LockUpload(id string) error
	// UnlockUpload releases an existing lock for the given upload.
	UnlockUpload(id string) error
}

// GetReaderDataStore is the interface which must be implemented if handler should
// expose and support the GET route. It will allow clients to download the
// content of an upload regardless whether it's finished or not.
// Please, be aware that this feature is not part of the official tus
// specification. Instead it's a custom mechanism by tusd.
type GetReaderDataStore interface {
	// GetReader returns a reader which allows iterating of the content of an
	// upload specified by its ID. It should attempt to provide a reader even if
	// the upload has not been finished yet but it's not required.
	// If the returned reader also implements the io.Closer interface, the
	// Close() method will be invoked once everything has been read.
	// If the given upload could not be found, the error tusd.ErrNotFound should
	// be returned.
	GetReader(id string) (io.Reader, error)
}

// ConcaterDataStore is the interface required to be implemented if the
// Concatenation extension should be enabled. Only in this case, the handler
// will parse and respect the Upload-Concat header.
type ConcaterDataStore interface {
	// ConcatUploads concatenations the content from the provided partial uploads
	// and write the result in the destination upload which is specified by its
	// ID. The caller (usually the handler) must and will ensure that this
	// destination upload has been created before with enough space to hold all
	// partial uploads. The order, in which the partial uploads are supplied,
	// must be respected during concatenation.
	ConcatUploads(destination string, partialUploads []string) error
}
<commit_msg>Add SizeIsDeferred to FileInfo<commit_after>package tusd

import (
	"io"
)

type MetaData map[string]string

type FileInfo struct {
	ID string
	// Total file size in bytes specified in the NewUpload call
	Size int64
	// Indicates whether the total file size is deferred until later
	SizeIsDeferred bool
	// Offset in bytes (zero-based)
	Offset   int64
	MetaData MetaData
	// Indicates that this is a partial upload which will later be used to form
	// a final upload by concatenation. Partial uploads should not be processed
	// when they are finished since they are only incomplete chunks of files.
	IsPartial bool
	// Indicates that this is a final upload
	IsFinal bool
	// If the upload is a final one (see IsFinal) this will be a non-empty
	// ordered slice containing the ids of the uploads of which the final upload
	// will consist after concatenation.
	PartialUploads []string
}

type DataStore interface {
	// Create a new upload using the size as the file's length. The method must
	// return an unique id which is used to identify the upload. If no backend
	// (e.g. Riak) specifes the id you may want to use the uid package to
	// generate one. The properties Size and MetaData will be filled.
	NewUpload(info FileInfo) (id string, err error)
	// Write the chunk read from src into the file specified by the id at the
	// given offset. The handler will take care of validating the offset and
	// limiting the size of the src to not overflow the file's size. It may
	// return an os.ErrNotExist which will be interpreted as a 404 Not Found.
	// It will also lock resources while they are written to ensure only one
	// write happens per time.
	// The function call must return the number of bytes written.
	WriteChunk(id string, offset int64, src io.Reader) (int64, error)
	// Read the fileinformation used to validate the offset and respond to HEAD
	// requests. It may return an os.ErrNotExist which will be interpreted as a
	// 404 Not Found.
	GetInfo(id string) (FileInfo, error)
}

// TerminaterDataStore is the interface which must be implemented by DataStores
// if they want to receive DELETE requests using the Handler. If this interface
// is not implemented, no request handler for this method is attached.
type TerminaterDataStore interface {
	// Terminate an upload so any further requests to the resource, both reading
	// and writing, must return os.ErrNotExist or similar.
	Terminate(id string) error
}

// FinisherDataStore is the interface which can be implemented by DataStores
// which need to do additional operations once an entire upload has been
// completed. These tasks may include but are not limited to freeing unused
// resources or notifying other services. For example, S3Store uses this
// interface for removing a temporary object.
type FinisherDataStore interface {
	// FinishUpload executes additional operations for the finished upload which
	// is specified by its ID.
	FinishUpload(id string) error
}

// LockerDataStore is the interface required for custom lock persisting mechanisms.
// Common ways to store this information is in memory, on disk or using an
// external service, such as ZooKeeper.
// When multiple processes are attempting to access an upload, whether it be
// by reading or writing, a synchronization mechanism is required to prevent
// data corruption, especially to ensure correct offset values and the proper
// order of chunks inside a single upload.
type LockerDataStore interface {
	// LockUpload attempts to obtain an exclusive lock for the upload specified
	// by its id.
	// If this operation fails because the resource is already locked, the
	// tusd.ErrFileLocked must be returned. If no error is returned, the attempt
	// is consider to be successful and the upload to be locked until UnlockUpload
	// is invoked for the same upload.
	LockUpload(id string) error
	// UnlockUpload releases an existing lock for the given upload.
	UnlockUpload(id string) error
}

// GetReaderDataStore is the interface which must be implemented if handler should
// expose and support the GET route. It will allow clients to download the
// content of an upload regardless whether it's finished or not.
// Please, be aware that this feature is not part of the official tus
// specification. Instead it's a custom mechanism by tusd.
type GetReaderDataStore interface {
	// GetReader returns a reader which allows iterating of the content of an
	// upload specified by its ID. It should attempt to provide a reader even if
	// the upload has not been finished yet but it's not required.
	// If the returned reader also implements the io.Closer interface, the
	// Close() method will be invoked once everything has been read.
	// If the given upload could not be found, the error tusd.ErrNotFound should
	// be returned.
	GetReader(id string) (io.Reader, error)
}

// ConcaterDataStore is the interface required to be implemented if the
// Concatenation extension should be enabled. Only in this case, the handler
// will parse and respect the Upload-Concat header.
type ConcaterDataStore interface {
	// ConcatUploads concatenations the content from the provided partial uploads
	// and write the result in the destination upload which is specified by its
	// ID. The caller (usually the handler) must and will ensure that this
	// destination upload has been created before with enough space to hold all
	// partial uploads. The order, in which the partial uploads are supplied,
	// must be respected during concatenation.
	ConcatUploads(destination string, partialUploads []string) error
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 cmd

import (
	"fmt"
	"os"
	"os/signal"

	"k8s.io/kubernetes/pkg/capabilities"
	"k8s.io/kubernetes/pkg/kubelet/types"
	"k8s.io/minikube/pkg/localkube"
	"k8s.io/minikube/pkg/version"
)

// The main instance of the current localkube server that is started
var Server *localkube.LocalkubeServer

func StartLocalkube(){

	if Server.ShowVersion {
		fmt.Println("localkube version:", version.GetVersion())
		os.Exit(0)
	}

	// TODO: Require root

	SetupServer(Server)
	Server.StartAll()

	defer Server.StopAll()

	interruptChan := make(chan os.Signal, 1)
	signal.Notify(interruptChan, os.Interrupt)

	<-interruptChan
	fmt.Println("Shutting down...")
}

func SetupServer(s *localkube.LocalkubeServer) {
	if s.ShouldGenerateCerts {
		if err := s.GenerateCerts(); err != nil {
			fmt.Println("Failed to create certificates!")
			panic(err)
		}
	}

	// Setup capabilities. This can only be done once per binary.
	allSources, _ := types.GetValidatedSources([]string{types.AllSource})
	c := capabilities.Capabilities{
		AllowPrivileged: true,
		PrivilegedSources: capabilities.PrivilegedSources{
			HostNetworkSources: allSources,
			HostIPCSources:     allSources,
			HostPIDSources:     allSources,
		},
	}
	capabilities.Initialize(c)

	// setup etcd
	etcd, err := s.NewEtcd(localkube.KubeEtcdClientURLs, localkube.KubeEtcdPeerURLs, "kubeetcd", s.GetEtcdDataDirectory())
	if err != nil {
		panic(err)
	}
	s.AddServer(etcd)

	// setup apiserver
	apiserver := s.NewAPIServer()
	s.AddServer(apiserver)

	// setup controller-manager
	controllerManager := s.NewControllerManagerServer()
	s.AddServer(controllerManager)

	// setup scheduler
	scheduler := s.NewSchedulerServer()
	s.AddServer(scheduler)

	// setup kubelet
	kubelet := s.NewKubeletServer()
	s.AddServer(kubelet)

	// setup proxy
	proxy := s.NewProxyServer()
	s.AddServer(proxy)

	// setup dns if we should
	if s.EnableDNS {

		dns, err := s.NewDNSServer(s.DNSDomain, s.DNSIP.String(), s.GetAPIServerInsecureURL())
		if err != nil {
			panic(err)
		}
		s.AddServer(dns)
	}
}
<commit_msg>Run gofmt<commit_after>/*
Copyright 2016 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 cmd

import (
	"fmt"
	"os"
	"os/signal"

	"k8s.io/kubernetes/pkg/capabilities"
	"k8s.io/kubernetes/pkg/kubelet/types"
	"k8s.io/minikube/pkg/localkube"
	"k8s.io/minikube/pkg/version"
)

// The main instance of the current localkube server that is started
var Server *localkube.LocalkubeServer

func StartLocalkube() {

	if Server.ShowVersion {
		fmt.Println("localkube version:", version.GetVersion())
		os.Exit(0)
	}

	// TODO: Require root

	SetupServer(Server)
	Server.StartAll()

	defer Server.StopAll()

	interruptChan := make(chan os.Signal, 1)
	signal.Notify(interruptChan, os.Interrupt)

	<-interruptChan
	fmt.Println("Shutting down...")
}

func SetupServer(s *localkube.LocalkubeServer) {
	if s.ShouldGenerateCerts {
		if err := s.GenerateCerts(); err != nil {
			fmt.Println("Failed to create certificates!")
			panic(err)
		}
	}

	// Setup capabilities. This can only be done once per binary.
	allSources, _ := types.GetValidatedSources([]string{types.AllSource})
	c := capabilities.Capabilities{
		AllowPrivileged: true,
		PrivilegedSources: capabilities.PrivilegedSources{
			HostNetworkSources: allSources,
			HostIPCSources:     allSources,
			HostPIDSources:     allSources,
		},
	}
	capabilities.Initialize(c)

	// setup etcd
	etcd, err := s.NewEtcd(localkube.KubeEtcdClientURLs, localkube.KubeEtcdPeerURLs, "kubeetcd", s.GetEtcdDataDirectory())
	if err != nil {
		panic(err)
	}
	s.AddServer(etcd)

	// setup apiserver
	apiserver := s.NewAPIServer()
	s.AddServer(apiserver)

	// setup controller-manager
	controllerManager := s.NewControllerManagerServer()
	s.AddServer(controllerManager)

	// setup scheduler
	scheduler := s.NewSchedulerServer()
	s.AddServer(scheduler)

	// setup kubelet
	kubelet := s.NewKubeletServer()
	s.AddServer(kubelet)

	// setup proxy
	proxy := s.NewProxyServer()
	s.AddServer(proxy)

	// setup dns if we should
	if s.EnableDNS {

		dns, err := s.NewDNSServer(s.DNSDomain, s.DNSIP.String(), s.GetAPIServerInsecureURL())
		if err != nil {
			panic(err)
		}
		s.AddServer(dns)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Marcus Fritzsch
//
// 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 davr implements channel-centric communication with a Denon AVR
package davr

import (
	"bytes"
	"fmt"
	"io"
	"net"
	"strings"
)

// eventReader reads from r and assembles messages
func eventReader(r io.Reader, out chan<- []byte) {
	buf := make([]byte, 1024)
	assy := new(bytes.Buffer)

	for {
		n, err := r.Read(buf)

		if err != nil {
			close(out)
			return
		}

		assy.Write(buf[:n])

		for { // assmble commands that are spread over mutliple reads
			ev, e := assy.ReadBytes(0xd)
			if e != nil || len(ev) == 0 {
				break
			}
			out <- ev
		}
	}
}

// commandWriter writes commands to w
func commandWriter(commandIn <-chan []byte, w io.Writer) {
	for {
		select {
		case cmd, ok := <-commandIn:
			if !ok {
				return
			}

			if len(cmd) == 0 {
				continue
			}

			// Allow commands that do not have a trailing \r
			if cmd[len(cmd)-1] != 0xd {
				cmd = append(cmd, 0xd)
			}

			w.Write(cmd)
		}
	}
}

// DAVR represents a Denon AVR connection
type DAVR struct {
	conn      net.Conn
	eventIn   chan []byte /// events from avr can be read from here
	commandIn chan []byte /// commands to the avr can be written here
}

// New creates a Denon AVR connection, or returns an error value
// hostPort is of the form "host[:port]" if :port is omitted, the
// default port 23 is used.
func New(hostPort string) (*DAVR, error) {
	var conn string

	if strings.Contains(hostPort, ":") {
		conn = hostPort
	} else {
		conn = fmt.Sprintf("%s:23", hostPort)
	}

	c, e := net.Dial("tcp", conn)
	if e != nil {
		return nil, e
	}

	davr := &DAVR{c, make(chan []byte), make(chan []byte)}

	go eventReader(c, davr.eventIn)
	go commandWriter(davr.commandIn, c)

	return davr, nil
}

// GetCommandChan returns the write only command-channel to the AVR
func (avr *DAVR) GetCommandChan() chan<- []byte {
	return avr.commandIn
}

// GetEventChan seturns the read-only event channel from the AVR
// Events returned through this channel are already assembled
// and guarantieed to be bounded and complete
// When reading from this channel, check the ok-flag in
// in order to determine if the connection is still alive.
func (avr *DAVR) GetEventChan() <-chan []byte {
	return avr.eventIn
}

// Close a Denon AVR connection
func (avr *DAVR) Close() {
	avr.conn.Close()
	close(avr.commandIn)
}
<commit_msg>davr: assembling events manually, again<commit_after>// Copyright (c) 2015 Marcus Fritzsch
//
// 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 davr implements channel-centric communication with a Denon AVR
package davr

import (
	"bytes"
	"fmt"
	"io"
	"net"
	"strings"
)

// eventReader reads from r and assembles messages
func eventReader(r io.Reader, out chan<- []byte) {
	assy := make([]byte, 202) // assembly buffer
	buf := make([]byte, 101)

	for {
		n, err := r.Read(buf)

		if err != nil {
			close(out)
			return
		}

		if n == 0 {
			continue
		}

		assy = append(assy, buf[:n]...)

		for { // assemble commands that are spread over mutliple reads
			evTrail := bytes.SplitN(assy, []byte{0xd}, 2)
			if len(evTrail) != 2 {
				break
			}
			ev := evTrail[0]
			if len(ev) != 0 {
				out <- ev
			}
			assy = evTrail[1]
		}
	}
}

// commandWriter writes commands to w
func commandWriter(commandIn <-chan []byte, w io.Writer) {
	for {
		select {
		case cmd, ok := <-commandIn:
			if !ok {
				return
			}

			if len(cmd) == 0 {
				continue
			}

			// Allow commands that do not have a trailing \r
			if cmd[len(cmd)-1] != 0xd {
				cmd = append(cmd, 0xd)
			}

			w.Write(cmd)
		}
	}
}

// DAVR represents a Denon AVR connection
type DAVR struct {
	conn      net.Conn
	eventIn   chan []byte /// events from avr can be read from here
	commandIn chan []byte /// commands to the avr can be written here
}

// New creates a Denon AVR connection, or returns an error value
// hostPort is of the form "host[:port]" if :port is omitted, the
// default port 23 is used.
func New(hostPort string) (*DAVR, error) {
	var conn string

	if strings.Contains(hostPort, ":") {
		conn = hostPort
	} else {
		conn = fmt.Sprintf("%s:23", hostPort)
	}

	c, e := net.Dial("tcp", conn)
	if e != nil {
		return nil, e
	}

	davr := &DAVR{c, make(chan []byte), make(chan []byte)}

	go eventReader(c, davr.eventIn)
	go commandWriter(davr.commandIn, c)

	return davr, nil
}

// GetCommandChan returns the write only command-channel to the AVR
func (avr *DAVR) GetCommandChan() chan<- []byte {
	return avr.commandIn
}

// GetEventChan seturns the read-only event channel from the AVR
// Events returned through this channel are already assembled
// and guarantieed to be bounded and complete
// When reading from this channel, check the ok-flag in
// in order to determine if the connection is still alive.
func (avr *DAVR) GetEventChan() <-chan []byte {
	return avr.eventIn
}

// Close a Denon AVR connection
func (avr *DAVR) Close() {
	avr.conn.Close()
	close(avr.commandIn)
}
<|endoftext|>


<commit_before><commit_msg>Updated assets<commit_after><|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
)

func getHouses(s string) (houses int, err error) {
	var pos [2]int

	h := make(map[[2]int]bool)

	h[pos] = true

	for _, c := range s {
		switch c {
		case '<':
			pos[0]--
		case '>':
			pos[0]++
		case '^':
			pos[1]++
		case 'v':
			pos[1]--
		default:
			err = fmt.Errorf("invalid character %q", c)
			return
		}
		h[pos] = true
	}

	for k := range h {
		if h[k] {
			houses++
		}
	}
	return
}

func run() int {
	s := ">"
	h, err := getHouses(s)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}

	fmt.Printf("houses: %d\n", h)
	return 0
}

func main() {
	os.Exit(run())
}
<commit_msg>day3 part 1 complete<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

func getHouses(s string) (houses int, err error) {
	var pos [2]int

	h := make(map[[2]int]bool)

	h[pos] = true

	for _, c := range s {
		switch c {
		case '<':
			pos[0]--
		case '>':
			pos[0]++
		case '^':
			pos[1]++
		case 'v':
			pos[1]--
		default:
			err = fmt.Errorf("invalid character %q", c)
			return
		}
		h[pos] = true
	}

	for k := range h {
		if h[k] {
			houses++
		}
	}
	return
}

func run() int {
	if len(os.Args) != 2 {
		fmt.Fprintf(os.Stderr, "%s filename\n", os.Args[0])
		return 1
	}

	b, err := ioutil.ReadFile(os.Args[1])
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}
	s := strings.TrimSpace(string(b))

	h, err := getHouses(s)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}

	fmt.Printf("houses: %d\n", h)
	return 0
}

func main() {
	os.Exit(run())
}
<|endoftext|>


<commit_before>package main

import (
	"log"

	"github.com/streadway/amqp"
)

const (
	qDial = "amqp://guest:guest@192.168.59.103:5672"
)

func setup() *amqp.Channel {
	conn, err := amqp.Dial(qDial)
	if err != nil {
		panic(err)
	}

	ch, err := conn.Channel()
	if err != nil {
		panic(err)
	}

	err = ch.ExchangeDeclare(
		"logs",   // name
		"fanout", // type
		true,     // durable
		false,    // auto-deleted
		false,    // internal
		false,    // no-wait
		nil,      // arguments
	)
	if err != nil {
		panic(err)
	}

	return ch
}

func send() {
	ch := setup()

	msg := amqp.Publishing{
		ContentType: "text/plain",
		Body:        []byte("hello"),
	}

	err := ch.Publish(
		"logs", // exchange
		"",     // routing key
		false,  // mandatory
		false,  // immediate
		msg,    //
	)

	if err != nil {
		panic(err)
	}

	log.Println("sent it")
}

func receive() {
	ch := setup()

	q, err := ch.QueueDeclare(
		"",    // name
		false, // durable
		false, // delete when used
		true,  // exclusive
		false, // no-wait
		nil,   // arguments
	)
	if err != nil {
		panic(err)
	}

	err = ch.QueueBind(
		q.Name, // queue name
		"",     // routing key
		"logs", // exchange
		false,
		nil,
	)
	if err != nil {
		panic(err)
	}

	msgs, err := ch.Consume(
		q.Name, //queue name
		"",     // consumer
		true,   // auto-ack FIXME
		false,  // exclusive
		false,  // no-local
		false,  // no-wait
		nil,    // args
	)
	if err != nil {
		panic(err)
	}

	go func() {
		for d := range msgs {
			log.Printf("Received %s\n", d.Body)
			log.Printf("%+v\n", d)
		}
	}()

}

func main() {
	receive()
	send()
	log.Println("after send")

	forever := make(chan bool)
	<-forever
}
<commit_msg>basic working with rabbit and s3<commit_after>package main

import (
	"bytes"
	"encoding/gob"
	"log"
	"os"
	"time"

	"launchpad.net/goamz/aws"
	"launchpad.net/goamz/s3"

	"github.com/brnstz/ohmy"
	"github.com/streadway/amqp"
)

const (
	exchangeName = "listen"
	bucket       = "brnstz"
	path         = "/listen/shows"
)

// Declare our exchange
func ensureExchange(ch *amqp.Channel) error {
	return ch.ExchangeDeclare(
		// Fanout queue called listen
		exchangeName, "fanout",

		// yes durable
		true,

		// no auto-delete, no internal, no noWait
		false, false, false,

		// no extra arguments
		nil,
	)
}

// Bind to an exchange and get a Go channel of messages
func receiveFromQueue(ch *amqp.Channel, name string) (msgs <-chan amqp.Delivery, err error) {

	// Create the queue
	q, err := ch.QueueDeclare(
		name,

		// false to durable, delete when used
		false, false,

		// true to exclusive
		true,

		// no no wait and nil arguments
		false, nil,
	)
	if err != nil {
		log.Println(err)
		return
	}

	// Bind queue to our exchange
	err = ch.QueueBind(
		q.Name,

		// blank routing key
		"",

		exchangeName,

		// FIXME: what are these?
		false,
		nil,
	)
	if err != nil {
		log.Println(err)
		return
	}

	// Start receiving messages
	msgs, err = ch.Consume(
		q.Name,

		// consumer
		"",

		// auto-ack
		true,

		//  false to exclusive, no local, no wait
		false, false, false,

		nil, // args
	)
	if err != nil {
		log.Println(err)
	}

	return
}

func publishAsGob(value interface{}, ch *amqp.Channel) (err error) {

	// Setup stuff for gob
	var buff bytes.Buffer
	enc := gob.NewEncoder(&buff)

	// Encode into a gob
	err = enc.Encode(value)
	if err != nil {
		log.Println("Error encoding value %#v %v", value, err)
		return
	}

	// Create a message with the gob
	msg := amqp.Publishing{
		ContentType: "application/octet-stream",
		Body:        buff.Bytes(),
	}

	// Publish our gob
	err = ch.Publish(
		// Send to our exchange
		exchangeName,

		// routing key, not mandatory, not immediate
		"", false, false,

		msg,
	)
	if err != nil {
		log.Printf("Error publishing message: %+v %v\n", msg, err)
		return
	}

	// Success!
	return
}

func oneReader() {
	// Get connection to rabbit
	// FIXME: does it make sense to reconnect here?
	url := os.Getenv("AMQP_URL")
	conn, err := amqp.Dial(url)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()

	// Get a channel
	ch, err := conn.Channel()
	if err != nil {
		log.Println(err)
		return
	}
	defer ch.Close()

	err = ensureExchange(ch)
	if err != nil {
		return
	}

	// Get current shows
	shows, err := ohmy.GetShows(ohmy.RegionNYC, 100)
	if err != nil {
		// Skip when there's an err, will be logged by the ohmy lib
		return
	}

	// Look at each show
	for _, show := range shows {
		log.Printf("%+v\n", show)
		publishAsGob(show, ch)
	}
}

// Periodically pull updates from ohmy and publish it to our exchange
func reader() {
	for {
		oneReader()
		time.Sleep(time.Minute * 5)
	}
}

func s3Writer() {
	// Get connection to rabbit
	// FIXME: does it make sense to reconnect here?
	url := os.Getenv("AMQP_URL")
	conn, err := amqp.Dial(url)
	if err != nil {
		log.Println(err)
		return
	}
	defer conn.Close()

	// Get a channel
	ch, err := conn.Channel()
	if err != nil {
		log.Println(err)
		return
	}
	defer ch.Close()

	err = ensureExchange(ch)
	if err != nil {
		return
	}

	s3auth := aws.Auth{
		AccessKey: os.Getenv("AWS_ACCESS_KEY_ID"),
		SecretKey: os.Getenv("AWS_SECRET_ACCESS_KEY"),
	}
	s3conn := s3.New(s3auth, aws.Regions[os.Getenv("AWS_DEFAULT_REGION")])
	s3Bucket := s3conn.Bucket(bucket)
	log.Println(s3Bucket)

	msgs, err := receiveFromQueue(ch, "s3")
	for d := range msgs {
		log.Printf("Received %s\n", d.Body)
		log.Printf("%+v\n", d)
	}

}

func main() {
	go s3Writer()
	go reader()

	forever := make(chan bool)
	<-forever
}
<|endoftext|>


<commit_before>package query

import (
	"fmt"
	"sort"
	"strings"

	"github.com/jacksontj/dataman/src/router_node/sharding"
)

// Encapsulate a result from the datastore
type Result struct {
	Return []map[string]interface{} `json:"return"`
	// TODO: make a list of errors!
	Errors []string `json:"errors,omitempty"`
	// TODO: pointer to the right thing
	ValidationError interface{}            `json:"validation_error,omitempty"`
	Meta            map[string]interface{} `json:"meta,omitempty"`
}

func (r *Result) Err() error {
	if r.Errors == nil {
		return nil
	} else {
		return fmt.Errorf(strings.Join(r.Errors, "\n"))
	}
}

func (r *Result) Sort(keys []string, reverseList []bool) {
	if r.Return != nil {
		Sort(keys, reverseList, r.Return)
	}
}

// TODO: decide if we want to support globs, right now we give the entire sub-record
// if the parent is projected. Globs would only be useful if we want to do something
// like `a.b.*.c.d` where it would give you some subfields of a variety of fields--
// which seems not terribly helpful for structured data
func (r *Result) Project(fields []string) {
	// TODO: do this in the underlying datasource so we can get a partial select
	projectionFields := make([][]string, len(fields))
	for i, fieldName := range fields {
		projectionFields[i] = strings.Split(fieldName, ".")
	}

	for i, returnRow := range r.Return {
		projectedResult := make(map[string]interface{})
		for _, fieldNameParts := range projectionFields {
			if len(fieldNameParts) == 1 {
				tmpVal, ok := returnRow[fieldNameParts[0]]
				if ok {
					projectedResult[fieldNameParts[0]] = tmpVal
				}
			} else {
				dstTmp := projectedResult
				srcTmp := returnRow
				for _, fieldNamePart := range fieldNameParts[:len(fieldNameParts)-1] {
					_, ok := dstTmp[fieldNamePart]
					if !ok {
						dstTmp[fieldNamePart] = make(map[string]interface{})
					}
					dstTmp = dstTmp[fieldNamePart].(map[string]interface{})
					srcTmp = srcTmp[fieldNamePart].(map[string]interface{})
				}
				// Now we are on the last hop-- just copy the value over
				tmpVal, ok := srcTmp[fieldNameParts[len(fieldNameParts)-1]]
				if ok {
					dstTmp[fieldNameParts[len(fieldNameParts)-1]] = tmpVal
				}
			}
		}
		r.Return[i] = projectedResult
	}
}

// Merge multiple results together
func MergeResult(pkeyFields []string, numResults int, results chan *Result) *Result {
	// Fast-path single results
	if numResults == 1 {
		r := <-results
		return r
	}

	pkeyFieldParts := make([][]string, len(pkeyFields))
	for i, pkeyField := range pkeyFields {
		pkeyFieldParts[i] = strings.Split(pkeyField, ".")
	}

	// We want to make sure we don't duplicate return entries
	ids := make(map[uint64]struct{})

	combinedResult := &Result{
		Return: make([]map[string]interface{}, 0),
		Meta:   make(map[string]interface{}),
	}

	recievedResults := 0
	for result := range results {
		if result.Errors != nil {
			if combinedResult.Errors == nil {
				combinedResult.Errors = result.Errors
			} else {
				combinedResult.Errors = append(combinedResult.Errors, result.Errors...)
			}
		}
		// TODO: merge meta
		if len(combinedResult.Meta) == 0 {
			combinedResult.Meta = result.Meta
		}

		for _, resultReturn := range result.Return {

			pkeyFields := make([]interface{}, len(pkeyFieldParts))
			var ok bool
			for i, pkeyField := range pkeyFieldParts {
				pkeyFields[i], ok = GetValue(resultReturn, pkeyField)
				if !ok {
					// TODO: something else?
					panic("Missing pkey in response!!!")
				}
			}
			pkey, err := (sharding.HashMethod(sharding.SHA256).Get())(sharding.CombineKeys(pkeyFields))
			if err != nil {
				panic(fmt.Sprintf("MergeResult doesn't know how to hash pkey: %v", err))
			}
			if _, ok := ids[pkey]; !ok {
				ids[pkey] = struct{}{}
				combinedResult.Return = append(combinedResult.Return, resultReturn)
			}
		}
		recievedResults++
		if recievedResults == numResults {
			break
		}
	}

	return combinedResult
}

func GetValue(value map[string]interface{}, nameParts []string) (interface{}, bool) {
	val, ok := value[nameParts[0]]
	if !ok {
		return nil, ok
	}

	for _, namePart := range nameParts[1:] {
		typedVal, ok := val.(map[string]interface{})
		if !ok {
			return nil, ok
		}
		val, ok = typedVal[namePart]
		if !ok {
			return nil, ok
		}
	}
	return val, true
}

func SetValue(value map[string]interface{}, newValue interface{}, nameParts []string) interface{} {
	var val interface{}
	if len(nameParts) > 1 {
		val = value[nameParts[0]]
		for _, namePart := range nameParts[1 : len(nameParts)-1] {
			val = val.(map[string]interface{})[namePart]
		}

	} else {
		val = value
	}

	val.(map[string]interface{})[nameParts[len(nameParts)-1]] = newValue

	return val
}

func DelValue(value map[string]interface{}, nameParts []string) bool {
	var val interface{}
	if len(nameParts) > 1 {
		val = value[nameParts[0]]
		for _, namePart := range nameParts[1 : len(nameParts)-1] {
			val = val.(map[string]interface{})[namePart]
		}

	} else {
		val = value
	}

	_, ok := val.(map[string]interface{})[nameParts[len(nameParts)-1]]
	if ok {
		delete(val.(map[string]interface{}), nameParts[len(nameParts)-1])
	}
	return ok
}

func PopValue(value map[string]interface{}, nameParts []string) (interface{}, bool) {
	var val interface{}
	if len(nameParts) > 1 {
		val = value[nameParts[0]]
		for _, namePart := range nameParts[1 : len(nameParts)-1] {
			val = val.(map[string]interface{})[namePart]
		}

	} else {
		val = value
	}

	tmp, ok := val.(map[string]interface{})[nameParts[len(nameParts)-1]]
	if ok {
		delete(val.(map[string]interface{}), nameParts[len(nameParts)-1])
	}
	return tmp, ok
}

func FlattenResult(m map[string]interface{}) map[string]interface{} {
	result := make(map[string]interface{})
	for k, v := range m {
		switch typedV := v.(type) {
		case map[string]interface{}:
			// get the submap as a flattened thing
			subMap := FlattenResult(typedV)
			for subK, subV := range subMap {
				result[k+"."+subK] = subV
			}
		default:
			result[k] = v
		}
	}
	return result
}

// TODO: change map[string]interface to a `Record` struct type
// sort the given data by the given keys
func Sort(sortKeys []string, reverseList []bool, data []map[string]interface{}) {
	splitSortKeys := make([][]string, len(sortKeys))
	for i, sortKey := range sortKeys {
		splitSortKeys[i] = strings.Split(sortKey, ".")
	}

	less := func(i, j int) (l bool) {
		var reverse bool
		defer func() {
			if reverse {
				l = !l
			}
		}()
		for sortKeyIdx, keyParts := range splitSortKeys {
			reverse = reverseList[sortKeyIdx]
			// TODO: record could (and should) point at the CollectionFields which will tell us types
			iVal, _ := GetValue(data[i], keyParts)
			jVal, _ := GetValue(data[j], keyParts)
			switch iValTyped := iVal.(type) {
			case string:
				jValTyped := jVal.(string)
				if iValTyped != jValTyped {
					l = iValTyped < jValTyped
					return
				}
			case int:
				jValTyped := jVal.(int)
				if iValTyped != jValTyped {
					l = iValTyped < jValTyped
					return
				}
			case int64:
				jValTyped := jVal.(int64)
				if iValTyped != jValTyped {
					l = iValTyped < jValTyped
					return
				}
			case float64:
				jValTyped := jVal.(float64)
				if iValTyped != jValTyped {
					l = iValTyped < jValTyped
					return
				}
			case bool:
				jValTyped := jVal.(bool)
				if iValTyped != jValTyped {
					l = !iValTyped && jValTyped
					return
				}
			// TODO: return error? At this point if all return false, I'm not sure what happens
			default:
				panic("Unknown type")
				l = false
				return

			}
		}
		l = false
		return
	}
	sort.Slice(data, less)
}
<commit_msg>Remove old comment<commit_after>package query

import (
	"fmt"
	"sort"
	"strings"

	"github.com/jacksontj/dataman/src/router_node/sharding"
)

// Encapsulate a result from the datastore
type Result struct {
	Return []map[string]interface{} `json:"return"`
	Errors []string `json:"errors,omitempty"`
	// TODO: pointer to the right thing
	ValidationError interface{}            `json:"validation_error,omitempty"`
	Meta            map[string]interface{} `json:"meta,omitempty"`
}

func (r *Result) Err() error {
	if r.Errors == nil {
		return nil
	} else {
		return fmt.Errorf(strings.Join(r.Errors, "\n"))
	}
}

func (r *Result) Sort(keys []string, reverseList []bool) {
	if r.Return != nil {
		Sort(keys, reverseList, r.Return)
	}
}

// TODO: decide if we want to support globs, right now we give the entire sub-record
// if the parent is projected. Globs would only be useful if we want to do something
// like `a.b.*.c.d` where it would give you some subfields of a variety of fields--
// which seems not terribly helpful for structured data
func (r *Result) Project(fields []string) {
	// TODO: do this in the underlying datasource so we can get a partial select
	projectionFields := make([][]string, len(fields))
	for i, fieldName := range fields {
		projectionFields[i] = strings.Split(fieldName, ".")
	}

	for i, returnRow := range r.Return {
		projectedResult := make(map[string]interface{})
		for _, fieldNameParts := range projectionFields {
			if len(fieldNameParts) == 1 {
				tmpVal, ok := returnRow[fieldNameParts[0]]
				if ok {
					projectedResult[fieldNameParts[0]] = tmpVal
				}
			} else {
				dstTmp := projectedResult
				srcTmp := returnRow
				for _, fieldNamePart := range fieldNameParts[:len(fieldNameParts)-1] {
					_, ok := dstTmp[fieldNamePart]
					if !ok {
						dstTmp[fieldNamePart] = make(map[string]interface{})
					}
					dstTmp = dstTmp[fieldNamePart].(map[string]interface{})
					srcTmp = srcTmp[fieldNamePart].(map[string]interface{})
				}
				// Now we are on the last hop-- just copy the value over
				tmpVal, ok := srcTmp[fieldNameParts[len(fieldNameParts)-1]]
				if ok {
					dstTmp[fieldNameParts[len(fieldNameParts)-1]] = tmpVal
				}
			}
		}
		r.Return[i] = projectedResult
	}
}

// Merge multiple results together
func MergeResult(pkeyFields []string, numResults int, results chan *Result) *Result {
	// Fast-path single results
	if numResults == 1 {
		r := <-results
		return r
	}

	pkeyFieldParts := make([][]string, len(pkeyFields))
	for i, pkeyField := range pkeyFields {
		pkeyFieldParts[i] = strings.Split(pkeyField, ".")
	}

	// We want to make sure we don't duplicate return entries
	ids := make(map[uint64]struct{})

	combinedResult := &Result{
		Return: make([]map[string]interface{}, 0),
		Meta:   make(map[string]interface{}),
	}

	recievedResults := 0
	for result := range results {
		if result.Errors != nil {
			if combinedResult.Errors == nil {
				combinedResult.Errors = result.Errors
			} else {
				combinedResult.Errors = append(combinedResult.Errors, result.Errors...)
			}
		}
		// TODO: merge meta
		if len(combinedResult.Meta) == 0 {
			combinedResult.Meta = result.Meta
		}

		for _, resultReturn := range result.Return {

			pkeyFields := make([]interface{}, len(pkeyFieldParts))
			var ok bool
			for i, pkeyField := range pkeyFieldParts {
				pkeyFields[i], ok = GetValue(resultReturn, pkeyField)
				if !ok {
					// TODO: something else?
					panic("Missing pkey in response!!!")
				}
			}
			pkey, err := (sharding.HashMethod(sharding.SHA256).Get())(sharding.CombineKeys(pkeyFields))
			if err != nil {
				panic(fmt.Sprintf("MergeResult doesn't know how to hash pkey: %v", err))
			}
			if _, ok := ids[pkey]; !ok {
				ids[pkey] = struct{}{}
				combinedResult.Return = append(combinedResult.Return, resultReturn)
			}
		}
		recievedResults++
		if recievedResults == numResults {
			break
		}
	}

	return combinedResult
}

func GetValue(value map[string]interface{}, nameParts []string) (interface{}, bool) {
	val, ok := value[nameParts[0]]
	if !ok {
		return nil, ok
	}

	for _, namePart := range nameParts[1:] {
		typedVal, ok := val.(map[string]interface{})
		if !ok {
			return nil, ok
		}
		val, ok = typedVal[namePart]
		if !ok {
			return nil, ok
		}
	}
	return val, true
}

func SetValue(value map[string]interface{}, newValue interface{}, nameParts []string) interface{} {
	var val interface{}
	if len(nameParts) > 1 {
		val = value[nameParts[0]]
		for _, namePart := range nameParts[1 : len(nameParts)-1] {
			val = val.(map[string]interface{})[namePart]
		}

	} else {
		val = value
	}

	val.(map[string]interface{})[nameParts[len(nameParts)-1]] = newValue

	return val
}

func DelValue(value map[string]interface{}, nameParts []string) bool {
	var val interface{}
	if len(nameParts) > 1 {
		val = value[nameParts[0]]
		for _, namePart := range nameParts[1 : len(nameParts)-1] {
			val = val.(map[string]interface{})[namePart]
		}

	} else {
		val = value
	}

	_, ok := val.(map[string]interface{})[nameParts[len(nameParts)-1]]
	if ok {
		delete(val.(map[string]interface{}), nameParts[len(nameParts)-1])
	}
	return ok
}

func PopValue(value map[string]interface{}, nameParts []string) (interface{}, bool) {
	var val interface{}
	if len(nameParts) > 1 {
		val = value[nameParts[0]]
		for _, namePart := range nameParts[1 : len(nameParts)-1] {
			val = val.(map[string]interface{})[namePart]
		}

	} else {
		val = value
	}

	tmp, ok := val.(map[string]interface{})[nameParts[len(nameParts)-1]]
	if ok {
		delete(val.(map[string]interface{}), nameParts[len(nameParts)-1])
	}
	return tmp, ok
}

func FlattenResult(m map[string]interface{}) map[string]interface{} {
	result := make(map[string]interface{})
	for k, v := range m {
		switch typedV := v.(type) {
		case map[string]interface{}:
			// get the submap as a flattened thing
			subMap := FlattenResult(typedV)
			for subK, subV := range subMap {
				result[k+"."+subK] = subV
			}
		default:
			result[k] = v
		}
	}
	return result
}

// TODO: change map[string]interface to a `Record` struct type
// sort the given data by the given keys
func Sort(sortKeys []string, reverseList []bool, data []map[string]interface{}) {
	splitSortKeys := make([][]string, len(sortKeys))
	for i, sortKey := range sortKeys {
		splitSortKeys[i] = strings.Split(sortKey, ".")
	}

	less := func(i, j int) (l bool) {
		var reverse bool
		defer func() {
			if reverse {
				l = !l
			}
		}()
		for sortKeyIdx, keyParts := range splitSortKeys {
			reverse = reverseList[sortKeyIdx]
			// TODO: record could (and should) point at the CollectionFields which will tell us types
			iVal, _ := GetValue(data[i], keyParts)
			jVal, _ := GetValue(data[j], keyParts)
			switch iValTyped := iVal.(type) {
			case string:
				jValTyped := jVal.(string)
				if iValTyped != jValTyped {
					l = iValTyped < jValTyped
					return
				}
			case int:
				jValTyped := jVal.(int)
				if iValTyped != jValTyped {
					l = iValTyped < jValTyped
					return
				}
			case int64:
				jValTyped := jVal.(int64)
				if iValTyped != jValTyped {
					l = iValTyped < jValTyped
					return
				}
			case float64:
				jValTyped := jVal.(float64)
				if iValTyped != jValTyped {
					l = iValTyped < jValTyped
					return
				}
			case bool:
				jValTyped := jVal.(bool)
				if iValTyped != jValTyped {
					l = !iValTyped && jValTyped
					return
				}
			// TODO: return error? At this point if all return false, I'm not sure what happens
			default:
				panic("Unknown type")
				l = false
				return

			}
		}
		l = false
		return
	}
	sort.Slice(data, less)
}
<|endoftext|>


<commit_before>package handlers

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

	"github.com/go-chi/chi"
	"github.com/jrzimmerman/bestrida-server-go/models"
	log "github.com/sirupsen/logrus"
)

func TestGetUserByIDSuccess(t *testing.T) {
	r := chi.NewRouter()
	r.Get("/{id}", GetUserByID)
	server := httptest.NewServer(r)

	id := 17198619

	// Create the http request
	req, err := http.NewRequest("GET", fmt.Sprintf("%s/"+strconv.Itoa(id), server.URL), nil)
	if err != nil {
		t.Error("unable to generate request", err)
	}

	// Send the request to the API
	resp, err := http.DefaultClient.Do(req)

	// Check the status code
	if exp := http.StatusOK; resp.StatusCode != exp {
		t.Errorf("expected status code %v, got: %v", exp, resp.StatusCode)
	}

	// Unmarshal and check the response body
	var u models.User
	if err := json.NewDecoder(resp.Body).Decode(&u); err != nil {
		t.Errorf("unable to decode response: %s", err)
	}

	log.WithField("User ID", u.ID).Info("User returned from database")

	if u.ID != int64(id) {
		t.Errorf("unexpected user")
	}
}

func TestGetUserByIDFailureID(t *testing.T) {
	r := chi.NewRouter()
	r.Get("/{id}", GetUserByID)
	server := httptest.NewServer(r)

	id := 0

	// Create the http request
	req, err := http.NewRequest("GET", fmt.Sprintf("%s/"+strconv.Itoa(id), server.URL), nil)
	if err != nil {
		t.Error("unable to generate request", err)
	}

	// Send the request to the API
	resp, err := http.DefaultClient.Do(req)

	// Check the status code
	if exp := http.StatusInternalServerError; resp.StatusCode != exp {
		t.Errorf("expected status code %v, got: %v", exp, resp.StatusCode)
	}
}

func TestGetUserByIDFailureName(t *testing.T) {
	r := chi.NewRouter()
	r.Get("/{id}", GetUserByID)
	server := httptest.NewServer(r)

	id := "fred"

	// Create the http request
	req, err := http.NewRequest("GET", fmt.Sprintf("%s/"+id, server.URL), nil)
	if err != nil {
		t.Error("unable to generate request", err)
	}

	// Send the request to the API
	resp, err := http.DefaultClient.Do(req)

	// Check the status code
	if exp := http.StatusInternalServerError; resp.StatusCode != exp {
		t.Errorf("expected status code %v, got: %v", exp, resp.StatusCode)
	}
}
<commit_msg>add user handler tests<commit_after>package handlers

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

	"github.com/go-chi/chi"
	"github.com/jrzimmerman/bestrida-server-go/models"
	log "github.com/sirupsen/logrus"
)

func TestGetUserByIDSuccess(t *testing.T) {
	r := chi.NewRouter()
	r.Get("/{id}", GetUserByID)
	server := httptest.NewServer(r)

	id := 17198619

	// Create the http request
	req, err := http.NewRequest("GET", fmt.Sprintf("%s/"+strconv.Itoa(id), server.URL), nil)
	if err != nil {
		t.Error("unable to generate request", err)
	}

	// Send the request to the API
	resp, err := http.DefaultClient.Do(req)

	// Check the status code
	if exp := http.StatusOK; resp.StatusCode != exp {
		t.Errorf("expected status code %v, got: %v", exp, resp.StatusCode)
	}

	// Unmarshal and check the response body
	var u models.User
	if err := json.NewDecoder(resp.Body).Decode(&u); err != nil {
		t.Errorf("unable to decode response: %s", err)
	}

	log.WithField("User ID", u.ID).Info("User returned from database")

	if u.ID != int64(id) {
		t.Errorf("unexpected user")
	}
}

func TestGetUserByIDFailureID(t *testing.T) {
	r := chi.NewRouter()
	r.Get("/{id}", GetUserByID)
	server := httptest.NewServer(r)

	id := 0

	// Create the http request
	req, err := http.NewRequest("GET", fmt.Sprintf("%s/"+strconv.Itoa(id), server.URL), nil)
	if err != nil {
		t.Error("unable to generate request", err)
	}

	// Send the request to the API
	resp, err := http.DefaultClient.Do(req)

	// Check the status code
	if exp := http.StatusInternalServerError; resp.StatusCode != exp {
		t.Errorf("expected status code %v, got: %v", exp, resp.StatusCode)
	}
}

func TestGetUserByIDFailureName(t *testing.T) {
	r := chi.NewRouter()
	r.Get("/{id}", GetUserByID)
	server := httptest.NewServer(r)

	id := "fred"

	// Create the http request
	req, err := http.NewRequest("GET", fmt.Sprintf("%s/"+id, server.URL), nil)
	if err != nil {
		t.Error("unable to generate request", err)
	}

	// Send the request to the API
	resp, err := http.DefaultClient.Do(req)

	// Check the status code
	if exp := http.StatusInternalServerError; resp.StatusCode != exp {
		t.Errorf("expected status code %v, got: %v", exp, resp.StatusCode)
	}
}

func TestGetSegmentsByUserIDSuccess(t *testing.T) {
	r := chi.NewRouter()
	r.Get("/{id}", GetSegmentsByUserID)
	server := httptest.NewServer(r)

	id := 17198619

	// Create the http request
	req, err := http.NewRequest("GET", fmt.Sprintf("%s/"+strconv.Itoa(id), server.URL), nil)
	if err != nil {
		t.Error("unable to generate request", err)
	}

	// Send the request to the API
	resp, err := http.DefaultClient.Do(req)

	// Check the status code
	if exp := http.StatusOK; resp.StatusCode != exp {
		t.Errorf("expected status code %v, got: %v", exp, resp.StatusCode)
	}

	// Unmarshal and check the response body
	var s []models.UserSegment
	if err := json.NewDecoder(resp.Body).Decode(&s); err != nil {
		t.Errorf("unable to decode response: %s", err)
	}
	log.Infof("Returned %d segments from database for user %d", len(s), id)

	if len(s) <= 0 {
		t.Errorf("no segments returned from database for user %d", id)
	}
}

func TestGetFriendsByUserIDSuccess(t *testing.T) {
	r := chi.NewRouter()
	r.Get("/{id}", GetFriendsByUserID)
	server := httptest.NewServer(r)

	id := 17198619

	// Create the http request
	req, err := http.NewRequest("GET", fmt.Sprintf("%s/"+strconv.Itoa(id), server.URL), nil)
	if err != nil {
		t.Error("unable to generate request", err)
	}

	// Send the request to the API
	resp, err := http.DefaultClient.Do(req)

	// Check the status code
	if exp := http.StatusOK; resp.StatusCode != exp {
		t.Errorf("expected status code %v, got: %v", exp, resp.StatusCode)
	}

	// Unmarshal and check the response body
	var f []models.Friend
	if err := json.NewDecoder(resp.Body).Decode(&f); err != nil {
		t.Errorf("unable to decode response: %s", err)
	}
	log.Infof("Returned %d friends from database for user %d", len(f), id)

	if len(f) <= 0 {
		t.Errorf("no segments returned from database for user %d", id)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	exec "os/exec"
	"strconv"
	dstrings "strings"

	"github.com/golang/glog"
	"github.com/kubernetes-incubator/external-storage/lib/controller"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	//storage "k8s.io/client-go/pkg/apis/storage/v1beta1"
)

const (
	provisionerName = "gluster.org/glusterblock"
	defaultExecPath = "./createiscsi"
	secretKeyName   = "key"
)

type glusterBlockProvisioner struct {
	// Kubernetes Client. Use to retrieve Gluster admin secret
	client kubernetes.Interface

	// Identity of this glusterBlockProvisioner, generated. Used to identify "this"
	// provisioner's PVs.
	identity string

	// Configuration of gluster block provisioner
	provConfig provisionerConfig
}

type provisionerConfig struct {
	// Required:  this is the Rest Service Url ( ex: Heketi) for Gluster Block
	url string

	// Optional: Rest user who is capable of creating gluster block volumes.
	user string

	// Optional: Rest user key for above RestUser.
	userKey string

	// Optional:  secret name, namespace.
	secretNamespace string
	secretName      string
	secretValue     string

	// Optinal:  clusterID from which the provisioner create the block volume
	clusterID string

	// Optional: high availability count in case of multipathing
	haCount int

	// Optional: Operation mode  (rest, executable)
	opMode string

	// Optional: Executable path if we are operating in executable mode.
	execPath string
}

func NewglusterBlockProvisioner(client kubernetes.Interface, id string) controller.Provisioner {
	return &glusterBlockProvisioner{
		client:   client,
		identity: id,
	}
}

var _ controller.Provisioner = &glusterBlockProvisioner{}

// Provision creates a storage asset and returns a PV object representing it.
func (p *glusterBlockProvisioner) Provision(options controller.VolumeOptions) (*v1.PersistentVolume, error) {

	var err error
	if options.PVC.Spec.Selector != nil {
		return nil, fmt.Errorf("claim Selector is not supported")
	}

	glog.V(4).Infof("glusterblock: VolumeOptions %v", options)

	// If we want to retrieve storage class name.
	// scName := storageutil.GetClaimStorageClass(r.options.PVC)

	cfg, err := parseClassParameters(options.Parameters, p.client)
	if err != nil {
		return nil, err
	}
	p.provConfig = *cfg

	glog.V(4).Infof("glusterfs: creating volume with configuration %+v", p.provConfig)

	target, iqn, err := p.createVolume(options.PVName)
	if err != nil {
		return nil, err
	}
	glog.V(1).Infof("Target Portal and IQN returned :%v %v", target, iqn)

	pv := &v1.PersistentVolume{
		ObjectMeta: metav1.ObjectMeta{
			Name: options.PVName,
			Annotations: map[string]string{
				"glusterBlockProvisionerIdentity": p.identity,
			},
		},
		Spec: v1.PersistentVolumeSpec{
			PersistentVolumeReclaimPolicy: options.PersistentVolumeReclaimPolicy,
			AccessModes:                   options.PVC.Spec.AccessModes,
			Capacity: v1.ResourceList{
				v1.ResourceName(v1.ResourceStorage): options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)],
			},
			PersistentVolumeSource: v1.PersistentVolumeSource{
				ISCSI: &v1.ISCSIVolumeSource{
					TargetPortal: target,
					IQN:          iqn,
					Lun:          0,
					FSType:       "ext4",
					ReadOnly:     false,
				},
			},
		},
	}
	glog.Infof("successfully created Gluster Block volume %+v", pv.Spec.PersistentVolumeSource.ISCSI)
	return pv, nil
}

// createVolume creates a gluster block volume i.e. the storage asset.

func (p *glusterBlockProvisioner) createVolume(PVName string) (string, string, error) {
	var dtarget, diqn string
	if p.provConfig.opMode == "executable" {
		cmd := exec.Command("sh", p.provConfig.execPath)
		err := cmd.Run()
		if err != nil {
			glog.Errorf("%v", err)
		}
		dtarget = os.Getenv("TARGET")
		diqn = os.Getenv("IQN")
	}
	return dtarget, diqn, nil
}

// Delete removes the storage asset that was created by Provision represented
// by the given PV.
func (p *glusterBlockProvisioner) Delete(volume *v1.PersistentVolume) error {
	ann, ok := volume.Annotations["glusterBlockProvisionerIdentity"]
	if !ok {
		return errors.New("identity annotation not found on PV")
	}
	if ann != p.identity {
		return &controller.IgnoredError{"identity annotation on PV does not match ours"}
	}
	// Unset the variables.
	os.Setenv("TARGET", "")
	os.Setenv("IQN", "")

	return nil
}

func parseClassParameters(params map[string]string, kubeclient kubernetes.Interface) (*provisionerConfig, error) {
	var cfg provisionerConfig
	var err error

	authEnabled := true

	// Default multipath count has been set to 3
	haCount := 3

	for k, v := range params {
		switch dstrings.ToLower(k) {
		case "resturl":
			cfg.url = v
		case "restuser":
			cfg.user = v
		case "restuserkey":
			cfg.userKey = v
		case "secretname":
			cfg.secretName = v
		case "secretnamespace":
			cfg.secretNamespace = v
		case "clusterID":
			if len(v) != 0 {
				cfg.clusterID = v
			}
		case "restauthenabled":
			authEnabled = dstrings.ToLower(v) == "true"
		case "hacount":
			haCount, err = strconv.Atoi(v)
			if err != nil {
				return nil, fmt.Errorf("glusterblock: failed to parse hacount %v ", k)
			}
		case "opmode":
			cfg.opMode = v
		case "execpath":
			cfg.execPath = v
		default:
			return nil, fmt.Errorf("glusterblock: invalid option %q for volume plugin %s", k, "glusterblock")
		}
	}

	if len(cfg.url) == 0 {
		return nil, fmt.Errorf("StorageClass for provisioner %s must contain 'resturl' parameter", "glusterblock")
	}

	if haCount == 0 {
		cfg.haCount = haCount
	}

	if len(cfg.opMode) == 0 {
		cfg.opMode = "executable"
	}

	if len(cfg.execPath) == 0 {
		cfg.execPath = defaultExecPath
	}
	if !authEnabled {
		cfg.user = ""
		cfg.secretName = ""
		cfg.secretNamespace = ""
		cfg.userKey = ""
		cfg.secretValue = ""
	}

	if len(cfg.secretName) != 0 || len(cfg.secretNamespace) != 0 {
		// secretName + Namespace has precedence over userKey
		if len(cfg.secretName) != 0 && len(cfg.secretNamespace) != 0 {
			cfg.secretValue, err = parseSecret(cfg.secretNamespace, cfg.secretName, kubeclient)
			if err != nil {
				return nil, err
			}
		} else {
			return nil, fmt.Errorf("StorageClass for provisioner %q must have secretNamespace and secretName either both set or both empty", "glusterblock")
		}
	} else {
		cfg.secretValue = cfg.userKey
	}

	return &cfg, nil
}

// parseSecret finds a given Secret instance and reads user password from it.
func parseSecret(namespace, secretName string, kubeClient kubernetes.Interface) (string, error) {

	secretMap, err := GetSecretForPV(namespace, secretName, "glusterblock", kubeClient)
	if err != nil {
		glog.Errorf("failed to get secret %s/%s: %v", namespace, secretName, err)
		return "", fmt.Errorf("failed to get secret %s/%s: %v", namespace, secretName, err)
	}
	if len(secretMap) == 0 {
		return "", fmt.Errorf("empty secret map")
	}
	secret := ""
	for k, v := range secretMap {
		if k == secretKeyName {
			return v, nil
		}
		secret = v
	}
	// If not found, the last secret in the map wins as done before
	return secret, nil
}

// GetSecretForPV locates secret by name and namespace, verifies the secret type, and returns secret map

func GetSecretForPV(secretNamespace, secretName, volumePluginName string, kubeClient kubernetes.Interface) (map[string]string, error) {
	secret := make(map[string]string)
	if kubeClient == nil {
		return secret, fmt.Errorf("Cannot get kube client")
	}
	secrets, err := kubeClient.Core().Secrets(secretNamespace).Get(secretName, metav1.GetOptions{})
	if err != nil {
		return secret, err
	}
	if secrets.Type != v1.SecretType(volumePluginName) {
		return secret, fmt.Errorf("Cannot get secret of type %s", volumePluginName)
	}
	for name, data := range secrets.Data {
		secret[name] = string(data)
	}
	return secret, nil
}

var (
	master     = flag.String("master", "", "Master URL")
	kubeconfig = flag.String("kubeconfig", "", "Absolute path to the kubeconfig")
	id         = flag.String("id", "", "Unique provisioner identity")
)

func main() {
	flag.Parse()
	flag.Set("logtostderr", "true")

	// Create an InClusterConfig and use it to create a client for the controller
	// to use to communicate with Kubernetes

	var config *rest.Config
	var err error
	if *master != "" || *kubeconfig != "" {
		config, err = clientcmd.BuildConfigFromFlags(*master, *kubeconfig)
	} else {
		config, err = rest.InClusterConfig()
	}

	prId := string(uuid.NewUUID())

	if *id != "" {
		prId = *id
	}

	if err != nil {
		glog.Fatalf("Failed to create config: %v", err)
	}
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		glog.Fatalf("Failed to create client: %v", err)
	}

	// The controller needs to know what the server version is because out-of-tree
	// provisioners aren't officially supported until 1.5
	serverVersion, err := clientset.Discovery().ServerVersion()
	if err != nil {
		glog.Fatalf("Error getting server version: %v", err)
	}

	// Create the provisioner: it implements the Provisioner interface expected by
	// the controller
	glusterBlockProvisioner := NewglusterBlockProvisioner(clientset, prId)

	// Start the provision controller which will dynamically provision glusterblock
	// PVs

	pc := controller.NewProvisionController(
		clientset,
		provisionerName,
		glusterBlockProvisioner,
		serverVersion.GitVersion,
	)

	pc.Run(wait.NeverStop)
}
<commit_msg>Add more PV annotations for identity<commit_after>/*
Copyright 2017 The Kubernetes Authors.

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

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

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

package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	exec "os/exec"
	"strconv"
	dstrings "strings"

	"github.com/golang/glog"
	"github.com/kubernetes-incubator/external-storage/lib/controller"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/uuid"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	//storage "k8s.io/client-go/pkg/apis/storage/v1beta1"
)

const (
	provisionerName  = "gluster.org/glusterblock"
	defaultExecPath  = "./createiscsi"
	secretKeyName    = "key"
	shareIDAnn       = "glusterBlockShare"
	provisionerIDAnn = "glusterBlockProvisionerIdentity"
	creatorAnn       = "kubernetes.io/createdby"
	volumeTypeAnn    = "gluster.org/type"
	descriptionAnn   = "Description"
)

type glusterBlockProvisioner struct {
	// Kubernetes Client. Use to retrieve Gluster admin secret
	client kubernetes.Interface

	// Identity of this glusterBlockProvisioner, generated. Used to identify "this"
	// provisioner's PVs.
	identity string

	// Configuration of gluster block provisioner
	provConfig provisionerConfig
}

type provisionerConfig struct {
	// Required:  this is the Rest Service Url ( ex: Heketi) for Gluster Block
	url string

	// Optional: Rest user who is capable of creating gluster block volumes.
	user string

	// Optional: Rest user key for above RestUser.
	userKey string

	// Optional:  secret name, namespace.
	secretNamespace string
	secretName      string
	secretValue     string

	// Optional:  clusterID from which the provisioner create the block volume
	clusterID string

	// Optional: high availability count in case of multipathing
	haCount int

	// Optional: Operation mode  (rest, executable)
	opMode string

	// Optional: Executable path if we are operating in executable mode.
	execPath string
}

func NewglusterBlockProvisioner(client kubernetes.Interface, id string) controller.Provisioner {
	return &glusterBlockProvisioner{
		client:   client,
		identity: id,
	}
}

var _ controller.Provisioner = &glusterBlockProvisioner{}

// Provision creates a storage asset and returns a PV object representing it.
func (p *glusterBlockProvisioner) Provision(options controller.VolumeOptions) (*v1.PersistentVolume, error) {

	var err error
	if options.PVC.Spec.Selector != nil {
		return nil, fmt.Errorf("claim Selector is not supported")
	}

	glog.V(4).Infof("glusterblock: VolumeOptions %v", options)

	// If we want to retrieve storage class name.
	// scName := storageutil.GetClaimStorageClass(r.options.PVC)

	cfg, err := parseClassParameters(options.Parameters, p.client)
	if err != nil {
		return nil, err
	}
	p.provConfig = *cfg

	glog.V(4).Infof("glusterfs: creating volume with configuration %+v", p.provConfig)

	target, iqn, err := p.createVolume(options.PVName)
	if err != nil {
		return nil, err
	}
	glog.V(1).Infof("Target Portal and IQN returned :%v %v", target, iqn)

	// Create unique PVC identity.
	blockVolIdentity := fmt.Sprintf("kubernetes-dynamic-pvc-%s", uuid.NewUUID())

	pv := &v1.PersistentVolume{
		ObjectMeta: metav1.ObjectMeta{
			Name: options.PVName,
			Annotations: map[string]string{
				provisionerIDAnn: p.identity,
				shareIDAnn:       blockVolIdentity,
				creatorAnn:       "heketi-dynamic-provisioner",
				volumeTypeAnn:    "block",
				descriptionAnn:   "Gluster: Dynamically provisioned PV",
			},
		},
		Spec: v1.PersistentVolumeSpec{
			PersistentVolumeReclaimPolicy: options.PersistentVolumeReclaimPolicy,
			AccessModes:                   options.PVC.Spec.AccessModes,
			Capacity: v1.ResourceList{
				v1.ResourceName(v1.ResourceStorage): options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)],
			},
			PersistentVolumeSource: v1.PersistentVolumeSource{
				ISCSI: &v1.ISCSIVolumeSource{
					TargetPortal: target,
					IQN:          iqn,
					Lun:          0,
					FSType:       "ext4",
					ReadOnly:     false,
				},
			},
		},
	}
	glog.Infof("successfully created Gluster Block volume %+v", pv.Spec.PersistentVolumeSource.ISCSI)
	return pv, nil
}

// createVolume creates a gluster block volume i.e. the storage asset.

func (p *glusterBlockProvisioner) createVolume(PVName string) (string, string, error) {
	var dtarget, diqn string
	if p.provConfig.opMode == "executable" {
		cmd := exec.Command("sh", p.provConfig.execPath)
		err := cmd.Run()
		if err != nil {
			glog.Errorf("%v", err)
		}
		dtarget = os.Getenv("TARGET")
		diqn = os.Getenv("IQN")
	}
	return dtarget, diqn, nil
}

// Delete removes the storage asset that was created by Provision represented
// by the given PV.
func (p *glusterBlockProvisioner) Delete(volume *v1.PersistentVolume) error {
	ann, ok := volume.Annotations[provisionerIDAnn]

	if !ok {
		return errors.New("identity annotation not found on PV")
	}
	if ann != p.identity {
		return &controller.IgnoredError{"identity annotation on PV does not match this provisioners identity"}
	}

	blockVol, ok := volume.Annotations[shareIDAnn]
	if !ok {
		return errors.New("gluster block share annotation not found on PV")
	}

	// Delete this blockVol
	glog.V(1).Infof("blockVolume  %v", blockVol)

	// Unset the variables.
	os.Setenv("TARGET", "")
	os.Setenv("IQN", "")

	return nil
}

func parseClassParameters(params map[string]string, kubeclient kubernetes.Interface) (*provisionerConfig, error) {
	var cfg provisionerConfig
	var err error

	authEnabled := true

	// Default multipath count has been set to 3
	haCount := 3

	for k, v := range params {
		switch dstrings.ToLower(k) {
		case "resturl":
			cfg.url = v
		case "restuser":
			cfg.user = v
		case "restuserkey":
			cfg.userKey = v
		case "secretname":
			cfg.secretName = v
		case "secretnamespace":
			cfg.secretNamespace = v
		case "clusterID":
			if len(v) != 0 {
				cfg.clusterID = v
			}
		case "restauthenabled":
			authEnabled = dstrings.ToLower(v) == "true"
		case "hacount":
			haCount, err = strconv.Atoi(v)
			if err != nil {
				return nil, fmt.Errorf("glusterblock: failed to parse hacount %v ", k)
			}
		case "opmode":
			cfg.opMode = v
		case "execpath":
			cfg.execPath = v
		default:
			return nil, fmt.Errorf("glusterblock: invalid option %q for volume plugin %s", k, "glusterblock")
		}
	}

	if len(cfg.url) == 0 {
		return nil, fmt.Errorf("StorageClass for provisioner %s must contain 'resturl' parameter", "glusterblock")
	}

	if haCount == 0 {
		cfg.haCount = haCount
	}

	if len(cfg.opMode) == 0 {
		cfg.opMode = "executable"
	}

	if len(cfg.execPath) == 0 {
		cfg.execPath = defaultExecPath
	}
	if !authEnabled {
		cfg.user = ""
		cfg.secretName = ""
		cfg.secretNamespace = ""
		cfg.userKey = ""
		cfg.secretValue = ""
	}

	if len(cfg.secretName) != 0 || len(cfg.secretNamespace) != 0 {
		// secretName + Namespace has precedence over userKey
		if len(cfg.secretName) != 0 && len(cfg.secretNamespace) != 0 {
			cfg.secretValue, err = parseSecret(cfg.secretNamespace, cfg.secretName, kubeclient)
			if err != nil {
				return nil, err
			}
		} else {
			return nil, fmt.Errorf("StorageClass for provisioner %q must have secretNamespace and secretName either both set or both empty", "glusterblock")
		}
	} else {
		cfg.secretValue = cfg.userKey
	}

	return &cfg, nil
}

// parseSecret finds a given Secret instance and reads user password from it.
func parseSecret(namespace, secretName string, kubeClient kubernetes.Interface) (string, error) {

	secretMap, err := GetSecretForPV(namespace, secretName, "glusterblock", kubeClient)
	if err != nil {
		glog.Errorf("failed to get secret %s/%s: %v", namespace, secretName, err)
		return "", fmt.Errorf("failed to get secret %s/%s: %v", namespace, secretName, err)
	}
	if len(secretMap) == 0 {
		return "", fmt.Errorf("empty secret map")
	}
	secret := ""
	for k, v := range secretMap {
		if k == secretKeyName {
			return v, nil
		}
		secret = v
	}
	// If not found, the last secret in the map wins as done before
	return secret, nil
}

// GetSecretForPV locates secret by name and namespace, verifies the secret type, and returns secret map

func GetSecretForPV(secretNamespace, secretName, volumePluginName string, kubeClient kubernetes.Interface) (map[string]string, error) {
	secret := make(map[string]string)
	if kubeClient == nil {
		return secret, fmt.Errorf("Cannot get kube client")
	}
	secrets, err := kubeClient.Core().Secrets(secretNamespace).Get(secretName, metav1.GetOptions{})
	if err != nil {
		return secret, err
	}
	if secrets.Type != v1.SecretType(volumePluginName) {
		return secret, fmt.Errorf("Cannot get secret of type %s", volumePluginName)
	}
	for name, data := range secrets.Data {
		secret[name] = string(data)
	}
	return secret, nil
}

var (
	master     = flag.String("master", "", "Master URL")
	kubeconfig = flag.String("kubeconfig", "", "Absolute path to the kubeconfig")
	id         = flag.String("id", "", "Unique provisioner identity")
)

func main() {
	flag.Parse()
	flag.Set("logtostderr", "true")

	// Create an InClusterConfig and use it to create a client for the controller
	// to use to communicate with Kubernetes

	var config *rest.Config
	var err error
	if *master != "" || *kubeconfig != "" {
		config, err = clientcmd.BuildConfigFromFlags(*master, *kubeconfig)
	} else {
		config, err = rest.InClusterConfig()
	}

	prId := string(uuid.NewUUID())

	if *id != "" {
		prId = *id
	}

	if err != nil {
		glog.Fatalf("Failed to create config: %v", err)
	}
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		glog.Fatalf("Failed to create client: %v", err)
	}

	// The controller needs to know what the server version is because out-of-tree
	// provisioners aren't officially supported until 1.5
	serverVersion, err := clientset.Discovery().ServerVersion()
	if err != nil {
		glog.Fatalf("Error getting server version: %v", err)
	}

	// Create the provisioner: it implements the Provisioner interface expected by
	// the controller
	glusterBlockProvisioner := NewglusterBlockProvisioner(clientset, prId)

	// Start the provision controller which will dynamically provision glusterblock
	// PVs

	pc := controller.NewProvisionController(
		clientset,
		provisionerName,
		glusterBlockProvisioner,
		serverVersion.GitVersion,
	)

	pc.Run(wait.NeverStop)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"

	collectd "github.com/kimor79/gollectd"
)

func main() {
	typesPath := flag.String("typesdb", "", "Path to types.db")
	flag.Parse()

	if *typesPath == "" {
		flag.Usage()
		os.Exit(1)
	}

	types, err := collectd.TypesDBFile(*typesPath)

	if err != nil {
		fmt.Printf("%s\n", err)
		os.Exit(1)
	}

	for k, pv := range types {
		fmt.Printf("%s:\n", k)
		for _, v := range pv {
			fmt.Printf("\t%+v\n", *v)
		}
	}
}
<commit_msg>Remove the "examples" directory.<commit_after><|endoftext|>


<commit_before>// Copyright 2018 Anapaya Systems
//
// 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 handlers

import (
	"context"

	"github.com/scionproto/scion/go/lib/common"
	"github.com/scionproto/scion/go/lib/ctrl/path_mgmt"
	"github.com/scionproto/scion/go/lib/infra"
	"github.com/scionproto/scion/go/lib/infra/messenger"
	"github.com/scionproto/scion/go/lib/infra/modules/segverifier"
	"github.com/scionproto/scion/go/lib/log"
	"github.com/scionproto/scion/go/proto"
)

type revocHandler struct {
	*baseHandler
}

func NewRevocHandler(args HandlerArgs) infra.Handler {
	f := func(r *infra.Request) *infra.HandlerResult {
		handler := &revocHandler{
			baseHandler: newBaseHandler(r, args),
		}
		return handler.Handle()
	}
	return infra.HandlerFunc(f)
}

func (h *revocHandler) Handle() *infra.HandlerResult {
	logger := log.FromCtx(h.request.Context())
	logger = logger.New("from", h.request.Peer)
	revocation, ok := h.request.Message.(*path_mgmt.SignedRevInfo)
	if !ok {
		logger.Error("[revocHandler] wrong message type, expected path_mgmt.SignedRevInfo",
			"msg", h.request.Message, "type", common.TypeOf(h.request.Message))
		return infra.MetricsErrInternal
	}
	rw, ok := infra.ResponseWriterFromContext(h.request.Context())
	if !ok {
		logger.Error("[revocHandler] Unable to service request, no Messenger found")
		return infra.MetricsErrInternal
	}
	subCtx, cancelF := context.WithTimeout(h.request.Context(), HandlerTimeout)
	defer cancelF()
	logger = logger.New("signer", revocation.Sign.Src)

	sendAck := messenger.SendAckHelper(subCtx, rw)
	revInfo, err := revocation.RevInfo()
	if err != nil {
		logger.Warn("[revocHandler] Couldn't parse revocation", "err", err)
		sendAck(proto.Ack_ErrCode_reject, messenger.AckRejectFailedToParse)
		return infra.MetricsErrInvalid
	}
	logger = logger.New("revInfo", revInfo)
	logger.Debug("[revocHandler] Received revocation")

	err = segverifier.VerifyRevInfo(subCtx, h.trustStore.NewVerifier(), h.request.Peer,
		revocation)
	if err != nil {
		logger.Warn("Couldn't verify revocation", "err", err)
		sendAck(proto.Ack_ErrCode_reject, messenger.AckRejectFailedToVerify)
		return infra.MetricsErrInvalid
	}

	_, err = h.revCache.Insert(subCtx, revocation)
	if err != nil {
		logger.Error("Failed to insert revInfo", "err", err)
		sendAck(proto.Ack_ErrCode_retry, messenger.AckRetryDBError)
		return infra.MetricsErrRevCache(err)
	}
	sendAck(proto.Ack_ErrCode_ok, "")
	return infra.MetricsResultOk
}
<commit_msg>PS: Revocation handler should not query BR (#2729)<commit_after>// Copyright 2018 Anapaya Systems
//
// 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 handlers

import (
	"context"

	"github.com/scionproto/scion/go/lib/common"
	"github.com/scionproto/scion/go/lib/ctrl/path_mgmt"
	"github.com/scionproto/scion/go/lib/infra"
	"github.com/scionproto/scion/go/lib/infra/messenger"
	"github.com/scionproto/scion/go/lib/infra/modules/segverifier"
	"github.com/scionproto/scion/go/lib/log"
	"github.com/scionproto/scion/go/proto"
)

type revocHandler struct {
	*baseHandler
}

func NewRevocHandler(args HandlerArgs) infra.Handler {
	f := func(r *infra.Request) *infra.HandlerResult {
		handler := &revocHandler{
			baseHandler: newBaseHandler(r, args),
		}
		return handler.Handle()
	}
	return infra.HandlerFunc(f)
}

func (h *revocHandler) Handle() *infra.HandlerResult {
	logger := log.FromCtx(h.request.Context())
	logger = logger.New("from", h.request.Peer)
	revocation, ok := h.request.Message.(*path_mgmt.SignedRevInfo)
	if !ok {
		logger.Error("[revocHandler] wrong message type, expected path_mgmt.SignedRevInfo",
			"msg", h.request.Message, "type", common.TypeOf(h.request.Message))
		return infra.MetricsErrInternal
	}
	rw, ok := infra.ResponseWriterFromContext(h.request.Context())
	if !ok {
		logger.Error("[revocHandler] Unable to service request, no Messenger found")
		return infra.MetricsErrInternal
	}
	subCtx, cancelF := context.WithTimeout(h.request.Context(), HandlerTimeout)
	defer cancelF()
	logger = logger.New("signer", revocation.Sign.Src)

	sendAck := messenger.SendAckHelper(subCtx, rw)
	revInfo, err := revocation.RevInfo()
	if err != nil {
		logger.Warn("[revocHandler] Couldn't parse revocation", "err", err)
		sendAck(proto.Ack_ErrCode_reject, messenger.AckRejectFailedToParse)
		return infra.MetricsErrInvalid
	}
	logger = logger.New("revInfo", revInfo)
	logger.Debug("[revocHandler] Received revocation")

	err = segverifier.VerifyRevInfo(subCtx, h.trustStore.NewVerifier(), nil, revocation)
	if err != nil {
		logger.Warn("Couldn't verify revocation", "err", err)
		sendAck(proto.Ack_ErrCode_reject, messenger.AckRejectFailedToVerify)
		return infra.MetricsErrInvalid
	}

	_, err = h.revCache.Insert(subCtx, revocation)
	if err != nil {
		logger.Error("Failed to insert revInfo", "err", err)
		sendAck(proto.Ack_ErrCode_retry, messenger.AckRetryDBError)
		return infra.MetricsErrRevCache(err)
	}
	sendAck(proto.Ack_ErrCode_ok, "")
	return infra.MetricsResultOk
}
<|endoftext|>


<commit_before>package nugugame

// Init when the bot starts up
import (
	"regexp"
	"strings"

	"github.com/Seklfreak/Robyul2/helpers"
	"github.com/bwmarrin/discordgo"
)

// module struct
type Module struct{}

var gameGenders = map[string]string{
	"boy":   "boy",
	"boys":  "boy",
	"girl":  "girl",
	"girls": "girl",
	"mixed": "mixed",
}

func (m *Module) Init(session *discordgo.Session) {
	go func() {

		// refresh idols in difficulties
		idolsByDifficultyMutex.Lock()
		getModuleCache(NUGUGAME_DIFFICULTY_IDOLS_KEY, &idolsByDifficulty)
		idolsByDifficultyMutex.Unlock()

		// regex for idol and group names
		var err error
		alphaNumericRegex, err = regexp.Compile("[^a-zA-Z0-9가-힣]+")
		helpers.Relax(err)

		currentNuguGames = make(map[string][]*nuguGame)

		startDifficultyCacheLoop()

		// load all images and information
		loadMiscImages()
	}()
}

// Uninit called when bot is shutting down
func (m *Module) Uninit(session *discordgo.Session) {

}

// Will validate if the passed command entered is used for this plugin
func (m *Module) Commands() []string {
	return []string{
		"nugugame",
	}
}

// Main Entry point for the plugin
func (m *Module) Action(command string, content string, msg *discordgo.Message, session *discordgo.Session) {
	if !helpers.ModuleIsAllowed(msg.ChannelID, msg.ID, msg.Author.ID, helpers.ModulePermGames) {
		return
	}

	// process text after the initial command
	commandArgs := strings.Fields(content)

	if command == "nugugame" {
		if len(commandArgs) > 0 {

			switch commandArgs[0] {
			case "list":
				listIdolsByDifficulty(msg, commandArgs)
			case "refresh-nugugame":
				manualRefreshDifficulties(msg)
			default:
				startNuguGame(msg, commandArgs)
			}
		} else {
			startNuguGame(msg, commandArgs)
		}
	}
}

func (m *Module) OnMessage(content string, msg *discordgo.Message, session *discordgo.Session) {
	for _, game := range getNuguGamesByChannelID(msg.ChannelID) {
		if game.WaitingForGuess {
			// if the game is not multiplayer, check the message author is the one who created the game
			if !game.IsMultigame && msg.Author.ID != game.User.ID {
				continue
			}
			game.GuessChannel <- msg
			break
		}
	}
}

///// Unused functions requried by ExtendedPlugin interface
func (m *Module) OnReactionAdd(reaction *discordgo.MessageReactionAdd, session *discordgo.Session) {
}
func (m *Module) OnMessageDelete(msg *discordgo.MessageDelete, session *discordgo.Session) {
}
func (m *Module) OnGuildMemberAdd(member *discordgo.Member, session *discordgo.Session) {
}
func (m *Module) OnGuildMemberRemove(member *discordgo.Member, session *discordgo.Session) {
}
func (m *Module) OnReactionRemove(reaction *discordgo.MessageReactionRemove, session *discordgo.Session) {
}
func (m *Module) OnGuildBanAdd(user *discordgo.GuildBanAdd, session *discordgo.Session) {
}
func (m *Module) OnGuildBanRemove(user *discordgo.GuildBanRemove, session *discordgo.Session) {
}
<commit_msg>[nugugame] allows _ng instead of _nugugame<commit_after>package nugugame

// Init when the bot starts up
import (
	"regexp"
	"strings"

	"github.com/Seklfreak/Robyul2/helpers"
	"github.com/bwmarrin/discordgo"
)

// module struct
type Module struct{}

var gameGenders = map[string]string{
	"boy":   "boy",
	"boys":  "boy",
	"girl":  "girl",
	"girls": "girl",
	"mixed": "mixed",
}

func (m *Module) Init(session *discordgo.Session) {
	go func() {

		// refresh idols in difficulties
		idolsByDifficultyMutex.Lock()
		getModuleCache(NUGUGAME_DIFFICULTY_IDOLS_KEY, &idolsByDifficulty)
		idolsByDifficultyMutex.Unlock()

		// regex for idol and group names
		var err error
		alphaNumericRegex, err = regexp.Compile("[^a-zA-Z0-9가-힣]+")
		helpers.Relax(err)

		currentNuguGames = make(map[string][]*nuguGame)

		startDifficultyCacheLoop()

		// load all images and information
		loadMiscImages()
	}()
}

// Uninit called when bot is shutting down
func (m *Module) Uninit(session *discordgo.Session) {

}

// Will validate if the passed command entered is used for this plugin
func (m *Module) Commands() []string {
	return []string{
		"nugugame",
		"ng",
	}
}

// Main Entry point for the plugin
func (m *Module) Action(command string, content string, msg *discordgo.Message, session *discordgo.Session) {
	if !helpers.ModuleIsAllowed(msg.ChannelID, msg.ID, msg.Author.ID, helpers.ModulePermGames) {
		return
	}

	// process text after the initial command
	commandArgs := strings.Fields(content)

	if command == "nugugame" || command == "ng" {
		if len(commandArgs) > 0 {

			switch commandArgs[0] {
			case "list":

				helpers.RequireRobyulMod(msg, func() {
					listIdolsByDifficulty(msg, commandArgs)
				})
			case "refresh-nugugame":
				helpers.RequireRobyulMod(msg, func() {
					manualRefreshDifficulties(msg)
				})
			default:
				startNuguGame(msg, commandArgs)
			}
		} else {
			startNuguGame(msg, commandArgs)
		}
	}
}

func (m *Module) OnMessage(content string, msg *discordgo.Message, session *discordgo.Session) {
	for _, game := range getNuguGamesByChannelID(msg.ChannelID) {
		if game.WaitingForGuess {
			// if the game is not multiplayer, check the message author is the one who created the game
			if !game.IsMultigame && msg.Author.ID != game.User.ID {
				continue
			}
			game.GuessChannel <- msg
			break
		}
	}
}

///// Unused functions requried by ExtendedPlugin interface
func (m *Module) OnReactionAdd(reaction *discordgo.MessageReactionAdd, session *discordgo.Session) {
}
func (m *Module) OnMessageDelete(msg *discordgo.MessageDelete, session *discordgo.Session) {
}
func (m *Module) OnGuildMemberAdd(member *discordgo.Member, session *discordgo.Session) {
}
func (m *Module) OnGuildMemberRemove(member *discordgo.Member, session *discordgo.Session) {
}
func (m *Module) OnReactionRemove(reaction *discordgo.MessageReactionRemove, session *discordgo.Session) {
}
func (m *Module) OnGuildBanAdd(user *discordgo.GuildBanAdd, session *discordgo.Session) {
}
func (m *Module) OnGuildBanRemove(user *discordgo.GuildBanRemove, session *discordgo.Session) {
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Vitess Authors.

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

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

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

package tabletserver

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"text/template"

	"vitess.io/vitess/go/acl"
	"vitess.io/vitess/go/vt/log"
	"vitess.io/vitess/go/vt/logz"
)

var (
	livequeryzHeader = []byte(`

			Type
			Query
			Context
			Duration
			Start
			ConnectionID
			Terminate

	`)
	livequeryzTmpl = template.Must(template.New("example").Parse(`

			{{.Type}}
			{{.Query}}
			{{.ContextHTML}}
			{{.Duration}}
			{{.Start}}
			{{.ConnID}}
			Terminate

	`))
)

func livequeryzHandler(queryLists []*QueryList, w http.ResponseWriter, r *http.Request) {
	if err := acl.CheckAccessHTTP(r, acl.DEBUGGING); err != nil {
		acl.SendError(w, err)
		return
	}
	var rows []QueryDetailzRow
	for _, ql := range queryLists {
		rows = ql.AppendQueryzRows(rows)
	}
	if err := r.ParseForm(); err != nil {
		http.Error(w, fmt.Sprintf("cannot parse form: %s", err), http.StatusInternalServerError)
		return
	}
	format := r.FormValue("format")
	if format == "json" {
		js, err := json.Marshal(rows)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		w.Write(js)
		return
	}
	logz.StartHTMLTable(w)
	defer logz.EndHTMLTable(w)
	w.Write(livequeryzHeader)
	for i := range rows {
		if err := livequeryzTmpl.Execute(w, rows[i]); err != nil {
			log.Errorf("livequeryz: couldn't execute template: %v", err)
		}
	}
}

func livequeryzTerminateHandler(queryLists []*QueryList, w http.ResponseWriter, r *http.Request) {
	if err := acl.CheckAccessHTTP(r, acl.ADMIN); err != nil {
		acl.SendError(w, err)
		return
	}
	if err := r.ParseForm(); err != nil {
		http.Error(w, fmt.Sprintf("cannot parse form: %s", err), http.StatusInternalServerError)
		return
	}
	connID := r.FormValue("connID")
	c, err := strconv.Atoi(connID)
	if err != nil {
		http.Error(w, "invalid connID", http.StatusInternalServerError)
		return
	}
	for _, ql := range queryLists {
		if ql.Terminate(int64(c)) {
			break
		}
	}
	livequeryzHandler(queryLists, w, r)
}
<commit_msg>livequeryz: livequeryz/terminate link should be relative<commit_after>/*
Copyright 2019 The Vitess Authors.

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

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

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

package tabletserver

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"text/template"

	"vitess.io/vitess/go/acl"
	"vitess.io/vitess/go/vt/log"
	"vitess.io/vitess/go/vt/logz"
)

var (
	livequeryzHeader = []byte(`

			Type
			Query
			Context
			Duration
			Start
			ConnectionID
			Terminate

	`)
	livequeryzTmpl = template.Must(template.New("example").Parse(`

			{{.Type}}
			{{.Query}}
			{{.ContextHTML}}
			{{.Duration}}
			{{.Start}}
			{{.ConnID}}
			Terminate

	`))
)

func livequeryzHandler(queryLists []*QueryList, w http.ResponseWriter, r *http.Request) {
	if err := acl.CheckAccessHTTP(r, acl.DEBUGGING); err != nil {
		acl.SendError(w, err)
		return
	}
	var rows []QueryDetailzRow
	for _, ql := range queryLists {
		rows = ql.AppendQueryzRows(rows)
	}
	if err := r.ParseForm(); err != nil {
		http.Error(w, fmt.Sprintf("cannot parse form: %s", err), http.StatusInternalServerError)
		return
	}
	format := r.FormValue("format")
	if format == "json" {
		js, err := json.Marshal(rows)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		w.Write(js)
		return
	}
	logz.StartHTMLTable(w)
	defer logz.EndHTMLTable(w)
	w.Write(livequeryzHeader)
	for i := range rows {
		if err := livequeryzTmpl.Execute(w, rows[i]); err != nil {
			log.Errorf("livequeryz: couldn't execute template: %v", err)
		}
	}
}

func livequeryzTerminateHandler(queryLists []*QueryList, w http.ResponseWriter, r *http.Request) {
	if err := acl.CheckAccessHTTP(r, acl.ADMIN); err != nil {
		acl.SendError(w, err)
		return
	}
	if err := r.ParseForm(); err != nil {
		http.Error(w, fmt.Sprintf("cannot parse form: %s", err), http.StatusInternalServerError)
		return
	}
	connID := r.FormValue("connID")
	c, err := strconv.Atoi(connID)
	if err != nil {
		http.Error(w, "invalid connID", http.StatusInternalServerError)
		return
	}
	for _, ql := range queryLists {
		if ql.Terminate(int64(c)) {
			break
		}
	}
	livequeryzHandler(queryLists, w, r)
}
<|endoftext|>