<commit_before>// client.go
//
// Author::    Chirantan Mitra
// Copyright:: Copyright (c) 2015-2017. All rights reserved
// License::   MIT

package gocd

import (
	"fmt"
	"io/ioutil"
	"net/http"
)

const (
	maxRetries = 3
)

func fetchGocdDashboard(client *http.Client, request *http.Request) (response *http.Response, err error) {
	retries := 0

	for response == nil && retries < maxRetries {
		response, err = client.Do(request)
		if err != nil {
			err = fmt.Errorf("%s (after %d retries)", err, retries+1)
		}
		retries++
	}

	return
}

func parseHTTPResponse(response *http.Response) (PipelineGroups, error) {
	if response != nil {
		defer response.Body.Close()
	}

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, fmt.Errorf("error reading response: %s", err)
	}

	if response.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("error fetching response from Gocd: the HTTP status code was %d, body: %s", response.StatusCode, body)
	}

	groups, err := NewPipelineGroups(body)
	if err != nil {
		return nil, err
	}

	return groups, nil
}

type Client struct {
	client *http.Client
}

func NewClient() *Client {
	return &Client{client: &http.Client{}}
}

func (c *Client) Fetch(url string) (Dashboard, error) {
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, fmt.Errorf("error creating Gocd request: %s", err)
	}

	response, err := fetchGocdDashboard(c.client, request)
	if err != nil {
		return nil, fmt.Errorf("error fetching data from Gocd: %s", err)
	}

	groups, err := parseHTTPResponse(response)
	if err != nil {
		return nil, err
	}

	dashboard := groups.ToDashboard()
	return dashboard, nil
}
<commit_msg>Restructure code<commit_after>// client.go
//
// Author::    Chirantan Mitra
// Copyright:: Copyright (c) 2015-2017. All rights reserved
// License::   MIT

package gocd

import (
	"fmt"
	"io/ioutil"
	"net/http"
)

const (
	maxRetries = 3
)

type Client struct {
	client *http.Client
}

func NewClient() *Client {
	return &Client{client: &http.Client{}}
}

func (c Client) Fetch(url string) (Dashboard, error) {
	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, fmt.Errorf("error creating Gocd request: %s", err)
	}

	response, err := fetchGocdDashboard(c.client, request)
	if err != nil {
		return nil, fmt.Errorf("error fetching data from Gocd: %s", err)
	}

	groups, err := parseHTTPResponse(response)
	if err != nil {
		return nil, err
	}

	dashboard := groups.ToDashboard()
	return dashboard, nil
}

func fetchGocdDashboard(client *http.Client, request *http.Request) (response *http.Response, err error) {
	retries := 0

	for response == nil && retries < maxRetries {
		response, err = client.Do(request)
		if err != nil {
			err = fmt.Errorf("%s (after %d retries)", err, retries+1)
		}
		retries++
	}

	return
}

func parseHTTPResponse(response *http.Response) (PipelineGroups, error) {
	if response != nil {
		defer response.Body.Close()
	}

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, fmt.Errorf("error reading response: %s, the HTTP status code was %d", err, response.StatusCode)
	}

	if response.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("error fetching response from Gocd: the HTTP status code was %d, body: %s", response.StatusCode, body)
	}

	groups, err := NewPipelineGroups(body)
	if err != nil {
		return nil, err
	}

	return groups, nil
}
<|endoftext|>


<commit_before>package cli

import (
	flag "github.com/docker/docker/pkg/mflag"
	"github.com/docker/docker/pkg/tlsconfig"
)

// CommonFlags represents flags that are common to both the client and the daemon.
type CommonFlags struct {
	FlagSet   *flag.FlagSet
	PostParse func()

	Debug      bool
	Hosts      []string
	LogLevel   string
	TLS        bool
	TLSVerify  bool
	TLSOptions *tlsconfig.Options
	TrustKey   string
}

// Command is the struct contains command name and description
type Command struct {
	Name        string
	Description string
}

var dockerCommands = []Command{
	{"attach", "Attach to a running container"},
	{"build", "Build an image from a Dockerfile"},
	{"commit", "Create a new image from a container's changes"},
	{"cp", "Copy files/folders between a container and the local filesystem"},
	{"create", "Create a new container"},
	{"diff", "Inspect changes on a container's filesystem"},
	{"events", "Get real time events from the server"},
	{"exec", "Run a command in a running container"},
	{"export", "Export a container's filesystem as a tar archive"},
	{"history", "Show the history of an image"},
	{"images", "List images"},
	{"import", "Import the contents from a tarball to create a filesystem image"},
	{"info", "Display system-wide information"},
	{"inspect", "Return low-level information on a container or image"},
	{"kill", "Kill a running container"},
	{"load", "Load an image from a tar archive or STDIN"},
	{"login", "Register or log in to a Docker registry"},
	{"logout", "Log out from a Docker registry"},
	{"logs", "Fetch the logs of a container"},
	{"network", "Manage Docker networks"},
	{"pause", "Pause all processes within a container"},
	{"port", "List port mappings or a specific mapping for the CONTAINER"},
	{"ps", "List containers"},
	{"pull", "Pull an image or a repository from a registry"},
	{"push", "Push an image or a repository to a registry"},
	{"rename", "Rename a container"},
	{"restart", "Restart a container"},
	{"rm", "Remove one or more containers"},
	{"rmi", "Remove one or more images"},
	{"run", "Run a command in a new container"},
	{"save", "Save an image(s) to a tar archive"},
	{"search", "Search the Docker Hub for images"},
	{"start", "Start one or more stopped containers"},
	{"stats", "Display a live stream of container(s) resource usage statistics"},
	{"stop", "Stop a running container"},
	{"tag", "Tag an image into a repository"},
	{"top", "Display the running processes of a container"},
	{"unpause", "Unpause all processes within a container"},
	{"version", "Show the Docker version information"},
	{"volume", "Manage Docker volumes"},
	{"wait", "Block until a container stops, then print its exit code"},
}

// DockerCommands stores all the docker command
var DockerCommands = make(map[string]Command)

func init() {
	for _, cmd := range dockerCommands {
		DockerCommands[cmd.Name] = cmd
	}
}
<commit_msg>Implemet docker update command<commit_after>package cli

import (
	flag "github.com/docker/docker/pkg/mflag"
	"github.com/docker/docker/pkg/tlsconfig"
)

// CommonFlags represents flags that are common to both the client and the daemon.
type CommonFlags struct {
	FlagSet   *flag.FlagSet
	PostParse func()

	Debug      bool
	Hosts      []string
	LogLevel   string
	TLS        bool
	TLSVerify  bool
	TLSOptions *tlsconfig.Options
	TrustKey   string
}

// Command is the struct contains command name and description
type Command struct {
	Name        string
	Description string
}

var dockerCommands = []Command{
	{"attach", "Attach to a running container"},
	{"build", "Build an image from a Dockerfile"},
	{"commit", "Create a new image from a container's changes"},
	{"cp", "Copy files/folders between a container and the local filesystem"},
	{"create", "Create a new container"},
	{"diff", "Inspect changes on a container's filesystem"},
	{"events", "Get real time events from the server"},
	{"exec", "Run a command in a running container"},
	{"export", "Export a container's filesystem as a tar archive"},
	{"history", "Show the history of an image"},
	{"images", "List images"},
	{"import", "Import the contents from a tarball to create a filesystem image"},
	{"info", "Display system-wide information"},
	{"inspect", "Return low-level information on a container or image"},
	{"kill", "Kill a running container"},
	{"load", "Load an image from a tar archive or STDIN"},
	{"login", "Register or log in to a Docker registry"},
	{"logout", "Log out from a Docker registry"},
	{"logs", "Fetch the logs of a container"},
	{"network", "Manage Docker networks"},
	{"pause", "Pause all processes within a container"},
	{"port", "List port mappings or a specific mapping for the CONTAINER"},
	{"ps", "List containers"},
	{"pull", "Pull an image or a repository from a registry"},
	{"push", "Push an image or a repository to a registry"},
	{"rename", "Rename a container"},
	{"restart", "Restart a container"},
	{"rm", "Remove one or more containers"},
	{"rmi", "Remove one or more images"},
	{"run", "Run a command in a new container"},
	{"save", "Save an image(s) to a tar archive"},
	{"search", "Search the Docker Hub for images"},
	{"start", "Start one or more stopped containers"},
	{"stats", "Display a live stream of container(s) resource usage statistics"},
	{"stop", "Stop a running container"},
	{"tag", "Tag an image into a repository"},
	{"top", "Display the running processes of a container"},
	{"unpause", "Unpause all processes within a container"},
	{"update", "Update resources of one or more containers"},
	{"version", "Show the Docker version information"},
	{"volume", "Manage Docker volumes"},
	{"wait", "Block until a container stops, then print its exit code"},
}

// DockerCommands stores all the docker command
var DockerCommands = make(map[string]Command)

func init() {
	for _, cmd := range dockerCommands {
		DockerCommands[cmd.Name] = cmd
	}
}
<|endoftext|>


<commit_before>package twitch

// Channel object
type ChannelS struct {
	Name        string         `json:"name,omitempty"`
	Game        string         `json:"game,omitempty"`
	Delay       int            `json:"game,omitempty"`
	Teams       []*TeamS       `json:"teams,omitempty"`
	Title       string         `json:"title,omitempty"`
	Banner      string         `json:"banner,omitempty"`
	VideoBanner string         `json:"video_banner,omitempty"`
	Background  string         `json:"background,omitempty"`
	Links       *ChannelLinksS `json:"_links,omitempty"`
	Logo        string         `json:"logo,omitempty"`
	Mature      bool           `json:"mature,omitempty"`
	Url         string         `json:"url,omitempty"`
	DisplayName string         `json:"display_name,omitempty"`
	// authenticated
	StreamKey   string         `json:"stream_key,omitempty"`
	Login       string         `json:"login,omitempty"`
	Email       string         `json:"email,omitempty"`
}

// Team object
type TeamS struct {
	Name        string `json:"name,omitempty"`
	Background  string `json:"background,omitempty"`
	Banner      string `json:"banner,omitempty"`
	Logo        string `json:"logo,omitempty"`
	Info        string `json:"info,omitempty"`
	DisplayName string `json:"display_name,omitempty"`
}

// Stream oject
type StreamS struct {
	Game        string    `json:"game,omitempty"`
	Name        string    `json:"name,omitempty"`
	Preview     *PreviewS `json:"preview,omitempty"`
	Viewers     int       `json:"viewers,omitempty"`
	Broadcaster string    `json:"broadcaster,omitempty"`
	Geo         string    `json:"geo,omitempty"`
	Channel     *ChannelS `json:"channel,omitempty"`
	Status      string    `json:"status,omitempty"`
}

// User object
type UserS struct {
	Name        string `json:"name,omitempty"`
	Logo        string `json:"logo,omitempty"`
	ID          string `json:"_id,omitempty"`
	DisplayName string `json:"display_name,omitempty"`
}

// Video object
type VideoS struct {
	Title       string `json:"title,omitempty"`
	ID          string `json:"_id,omitempty"`
	Embed       string `json:"embed,omitempty"`
	Url         string `json:"url,omitempty"`
	Views       int    `json:"views,omitempty"`
	Preview     string `json:"preview,omitempty"`
	Length      int    `json:"length,omitempty"`
	Description string `json:"description,omitempty"`
}

type FStreamS struct {
	Stream *StreamS `json:"stream,omitempty"`
	Text   string   `json:"text,omitempty"`
	Image  string   `json:"image,omitempty"`
}

type LinksS struct {
	Summary  string `json:"summary,omitempty"`
	Followed string `json:"followed,omitempty"`
	Next     string `json:"streams,omitempty"`
	Featured string `json:"featured,omitempty"`
}

type ChannelLinksS struct {
    Chat       string `json:"chat,omitempty"`
    Commercial string `json:"commercial,omitempty"`
    Videos     string `json:"videos,omitempty"`
}

type PreviewS struct {
	Small    string `json:"small,omitempty"`
	Medium   string `json:"medium,omitempty"`
	Large    string `json:"large,omitempty"`
	Template string `json:"template,omitempty"`
}

type ListOptions struct {
	Game       string
	Channel    string
	Limit      int
	Offset     int
	Embeddable bool
	Hls        bool
	ClientId   string
	Direction  string
	Live       bool
}
<commit_msg>Formatting.<commit_after>package twitch

// Channel object
type ChannelS struct {
	Name        string         `json:"name,omitempty"`
	Game        string         `json:"game,omitempty"`
	Delay       int            `json:"game,omitempty"`
	Teams       []*TeamS       `json:"teams,omitempty"`
	Title       string         `json:"title,omitempty"`
	Banner      string         `json:"banner,omitempty"`
	VideoBanner string         `json:"video_banner,omitempty"`
	Background  string         `json:"background,omitempty"`
	Links       *ChannelLinksS `json:"_links,omitempty"`
	Logo        string         `json:"logo,omitempty"`
	Mature      bool           `json:"mature,omitempty"`
	Url         string         `json:"url,omitempty"`
	DisplayName string         `json:"display_name,omitempty"`
	// authenticated
	StreamKey   string         `json:"stream_key,omitempty"`
	Login       string         `json:"login,omitempty"`
	Email       string         `json:"email,omitempty"`
}

// Team object
type TeamS struct {
	Name        string `json:"name,omitempty"`
	Background  string `json:"background,omitempty"`
	Banner      string `json:"banner,omitempty"`
	Logo        string `json:"logo,omitempty"`
	Info        string `json:"info,omitempty"`
	DisplayName string `json:"display_name,omitempty"`
}

// Stream oject
type StreamS struct {
	Game        string    `json:"game,omitempty"`
	Name        string    `json:"name,omitempty"`
	Preview     *PreviewS `json:"preview,omitempty"`
	Viewers     int       `json:"viewers,omitempty"`
	Broadcaster string    `json:"broadcaster,omitempty"`
	Geo         string    `json:"geo,omitempty"`
	Channel     *ChannelS `json:"channel,omitempty"`
	Status      string    `json:"status,omitempty"`
}

// User object
type UserS struct {
	Name        string `json:"name,omitempty"`
	Logo        string `json:"logo,omitempty"`
	ID          string `json:"_id,omitempty"`
	DisplayName string `json:"display_name,omitempty"`
}

// Video object
type VideoS struct {
	Title       string `json:"title,omitempty"`
	ID          string `json:"_id,omitempty"`
	Embed       string `json:"embed,omitempty"`
	Url         string `json:"url,omitempty"`
	Views       int    `json:"views,omitempty"`
	Preview     string `json:"preview,omitempty"`
	Length      int    `json:"length,omitempty"`
	Description string `json:"description,omitempty"`
}

type FStreamS struct {
	Stream *StreamS `json:"stream,omitempty"`
	Text   string   `json:"text,omitempty"`
	Image  string   `json:"image,omitempty"`
}

type LinksS struct {
	Summary  string `json:"summary,omitempty"`
	Followed string `json:"followed,omitempty"`
	Next     string `json:"streams,omitempty"`
	Featured string `json:"featured,omitempty"`
}

type ChannelLinksS struct {
	Chat       string `json:"chat,omitempty"`
	Commercial string `json:"commercial,omitempty"`
	Videos     string `json:"videos,omitempty"`
}

type PreviewS struct {
	Small    string `json:"small,omitempty"`
	Medium   string `json:"medium,omitempty"`
	Large    string `json:"large,omitempty"`
	Template string `json:"template,omitempty"`
}

type ListOptions struct {
	Game       string
	Channel    string
	Limit      int
	Offset     int
	Embeddable bool
	Hls        bool
	ClientId   string
	Direction  string
	Live       bool
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package btcwire

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/binary"
	"fmt"
	"io"
	"math"
)

// Maximum payload size for a variable length integer.
const maxVarIntPayload = 9

// readElement reads the next sequence of bytes from r using little endian
// depending on the concrete type of element pointed to.
func readElement(r io.Reader, element interface{}) error {
	return binary.Read(r, binary.LittleEndian, element)
}

// readElements reads multiple items from r.  It is equivalent to multiple
// calls to readElement.
func readElements(r io.Reader, elements ...interface{}) error {
	for _, element := range elements {
		err := readElement(r, element)
		if err != nil {
			return err
		}
	}
	return nil
}

// writeElement writes the little endian representation of element to w.
func writeElement(w io.Writer, element interface{}) error {
	return binary.Write(w, binary.LittleEndian, element)
}

// writeElements writes multiple items to w.  It is equivalent to multiple
// calls to writeElement.
func writeElements(w io.Writer, elements ...interface{}) error {
	for _, element := range elements {
		err := writeElement(w, element)
		if err != nil {
			return err
		}
	}
	return nil
}

// readVarInt reads a variable length integer from r and returns it as a uint64.
func readVarInt(r io.Reader, pver uint32) (uint64, error) {
	b := make([]byte, 8)
	_, err := io.ReadFull(r, b[0:1])
	if err != nil {
		return 0, err
	}

	var rv uint64
	discriminant := uint8(b[0])
	switch discriminant {
	case 0xff:
		_, err := io.ReadFull(r, b)
		if err != nil {
			return 0, err
		}
		rv = binary.LittleEndian.Uint64(b)

	case 0xfe:
		_, err := io.ReadFull(r, b[0:4])
		if err != nil {
			return 0, err
		}
		rv = uint64(binary.LittleEndian.Uint32(b))

	case 0xfd:
		_, err := io.ReadFull(r, b[0:2])
		if err != nil {
			return 0, err
		}
		rv = uint64(binary.LittleEndian.Uint16(b))

	default:
		rv = uint64(discriminant)
	}

	return rv, nil
}

// writeVarInt serializes val to w using a variable number of bytes depending
// on its value.
func writeVarInt(w io.Writer, pver uint32, val uint64) error {
	if val < 0xfd {
		_, err := w.Write([]byte{uint8(val)})
		return err
	}

	if val <= math.MaxUint16 {
		buf := make([]byte, 3)
		buf[0] = 0xfd
		binary.LittleEndian.PutUint16(buf[1:], uint16(val))
		_, err := w.Write(buf)
		return err
	}

	if val <= math.MaxUint32 {
		buf := make([]byte, 5)
		buf[0] = 0xfe
		binary.LittleEndian.PutUint32(buf[1:], uint32(val))
		_, err := w.Write(buf)
		return err
	}

	buf := make([]byte, 9)
	buf[0] = 0xff
	binary.LittleEndian.PutUint64(buf[1:], val)
	_, err := w.Write(buf)
	return err
}

// varIntSerializeSize returns the number of bytes it would take to serialize
// val as a variable length integer.
func varIntSerializeSize(val uint64) int {
	// The value is small enough to be represented by itself, so it's
	// just 1 byte.
	if val < 0xfd {
		return 1
	}

	// Discriminant 1 byte plus 2 bytes for the uint16.
	if val <= math.MaxUint16 {
		return 3
	}

	// Discriminant 1 byte plus 4 bytes for the uint32.
	if val <= math.MaxUint32 {
		return 5
	}

	// Discriminant 1 byte plus 8 bytes for the uint64.
	return 9
}

// readVarString reads a variable length string from r and returns it as a Go
// string.  A varString is encoded as a varInt containing the length of the
// string, and the bytes that represent the string itself.  An error is returned
// if the length is greater than the maximum block payload size, since it would
// not be possible to put a varString of that size into a block anyways and it
// also helps protect against memory exhuastion attacks and forced panics
// through malformed messages.
func readVarString(r io.Reader, pver uint32) (string, error) {
	count, err := readVarInt(r, pver)
	if err != nil {
		return "", err
	}

	// Prevent variable length strings that are larger than the maximum
	// message size.  It would be possible to cause memory exhaustion and
	// panics without a sane upper bound on this count.
	if count > maxMessagePayload {
		str := fmt.Sprintf("variable length string is too long "+
			"[count %d, max %d]", count, maxMessagePayload)
		return "", messageError("readVarString", str)
	}

	buf := make([]byte, count)
	err = readElement(r, buf)
	if err != nil {
		return "", err
	}
	return string(buf), nil
}

// writeVarString serializes str to w as a varInt containing the length of the
// string followed by the bytes that represent the string itself.
func writeVarString(w io.Writer, pver uint32, str string) error {
	err := writeVarInt(w, pver, uint64(len(str)))
	if err != nil {
		return err
	}
	err = writeElement(w, []byte(str))
	if err != nil {
		return err
	}
	return nil
}

// randomUint64 returns a cryptographically random uint64 value.  This
// unexported version takes a reader primarily to ensure the error paths
// can be properly tested by passing a fake reader in the tests.
func randomUint64(r io.Reader) (uint64, error) {
	b := make([]byte, 8)
	n, err := r.Read(b)
	if n != len(b) {
		return 0, io.ErrShortBuffer
	}
	if err != nil {
		return 0, err
	}
	return binary.BigEndian.Uint64(b), nil
}

// RandomUint64 returns a cryptographically random uint64 value.
func RandomUint64() (uint64, error) {
	return randomUint64(rand.Reader)
}

// DoubleSha256 calculates sha256(sha256(b)) and returns the resulting bytes.
func DoubleSha256(b []byte) []byte {
	hasher := sha256.New()
	hasher.Write(b)
	sum := hasher.Sum(nil)
	hasher.Reset()
	hasher.Write(sum)
	return hasher.Sum(nil)
}
<commit_msg>Optimize readVarString.<commit_after>// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package btcwire

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/binary"
	"fmt"
	"io"
	"math"
)

// Maximum payload size for a variable length integer.
const maxVarIntPayload = 9

// readElement reads the next sequence of bytes from r using little endian
// depending on the concrete type of element pointed to.
func readElement(r io.Reader, element interface{}) error {
	return binary.Read(r, binary.LittleEndian, element)
}

// readElements reads multiple items from r.  It is equivalent to multiple
// calls to readElement.
func readElements(r io.Reader, elements ...interface{}) error {
	for _, element := range elements {
		err := readElement(r, element)
		if err != nil {
			return err
		}
	}
	return nil
}

// writeElement writes the little endian representation of element to w.
func writeElement(w io.Writer, element interface{}) error {
	return binary.Write(w, binary.LittleEndian, element)
}

// writeElements writes multiple items to w.  It is equivalent to multiple
// calls to writeElement.
func writeElements(w io.Writer, elements ...interface{}) error {
	for _, element := range elements {
		err := writeElement(w, element)
		if err != nil {
			return err
		}
	}
	return nil
}

// readVarInt reads a variable length integer from r and returns it as a uint64.
func readVarInt(r io.Reader, pver uint32) (uint64, error) {
	b := make([]byte, 8)
	_, err := io.ReadFull(r, b[0:1])
	if err != nil {
		return 0, err
	}

	var rv uint64
	discriminant := uint8(b[0])
	switch discriminant {
	case 0xff:
		_, err := io.ReadFull(r, b)
		if err != nil {
			return 0, err
		}
		rv = binary.LittleEndian.Uint64(b)

	case 0xfe:
		_, err := io.ReadFull(r, b[0:4])
		if err != nil {
			return 0, err
		}
		rv = uint64(binary.LittleEndian.Uint32(b))

	case 0xfd:
		_, err := io.ReadFull(r, b[0:2])
		if err != nil {
			return 0, err
		}
		rv = uint64(binary.LittleEndian.Uint16(b))

	default:
		rv = uint64(discriminant)
	}

	return rv, nil
}

// writeVarInt serializes val to w using a variable number of bytes depending
// on its value.
func writeVarInt(w io.Writer, pver uint32, val uint64) error {
	if val < 0xfd {
		_, err := w.Write([]byte{uint8(val)})
		return err
	}

	if val <= math.MaxUint16 {
		buf := make([]byte, 3)
		buf[0] = 0xfd
		binary.LittleEndian.PutUint16(buf[1:], uint16(val))
		_, err := w.Write(buf)
		return err
	}

	if val <= math.MaxUint32 {
		buf := make([]byte, 5)
		buf[0] = 0xfe
		binary.LittleEndian.PutUint32(buf[1:], uint32(val))
		_, err := w.Write(buf)
		return err
	}

	buf := make([]byte, 9)
	buf[0] = 0xff
	binary.LittleEndian.PutUint64(buf[1:], val)
	_, err := w.Write(buf)
	return err
}

// varIntSerializeSize returns the number of bytes it would take to serialize
// val as a variable length integer.
func varIntSerializeSize(val uint64) int {
	// The value is small enough to be represented by itself, so it's
	// just 1 byte.
	if val < 0xfd {
		return 1
	}

	// Discriminant 1 byte plus 2 bytes for the uint16.
	if val <= math.MaxUint16 {
		return 3
	}

	// Discriminant 1 byte plus 4 bytes for the uint32.
	if val <= math.MaxUint32 {
		return 5
	}

	// Discriminant 1 byte plus 8 bytes for the uint64.
	return 9
}

// readVarString reads a variable length string from r and returns it as a Go
// string.  A varString is encoded as a varInt containing the length of the
// string, and the bytes that represent the string itself.  An error is returned
// if the length is greater than the maximum block payload size, since it would
// not be possible to put a varString of that size into a block anyways and it
// also helps protect against memory exhuastion attacks and forced panics
// through malformed messages.
func readVarString(r io.Reader, pver uint32) (string, error) {
	count, err := readVarInt(r, pver)
	if err != nil {
		return "", err
	}

	// Prevent variable length strings that are larger than the maximum
	// message size.  It would be possible to cause memory exhaustion and
	// panics without a sane upper bound on this count.
	if count > maxMessagePayload {
		str := fmt.Sprintf("variable length string is too long "+
			"[count %d, max %d]", count, maxMessagePayload)
		return "", messageError("readVarString", str)
	}

	buf := make([]byte, count)
	_, err = io.ReadFull(r, buf)
	if err != nil {
		return "", err
	}
	return string(buf), nil
}

// writeVarString serializes str to w as a varInt containing the length of the
// string followed by the bytes that represent the string itself.
func writeVarString(w io.Writer, pver uint32, str string) error {
	err := writeVarInt(w, pver, uint64(len(str)))
	if err != nil {
		return err
	}
	err = writeElement(w, []byte(str))
	if err != nil {
		return err
	}
	return nil
}

// randomUint64 returns a cryptographically random uint64 value.  This
// unexported version takes a reader primarily to ensure the error paths
// can be properly tested by passing a fake reader in the tests.
func randomUint64(r io.Reader) (uint64, error) {
	b := make([]byte, 8)
	n, err := r.Read(b)
	if n != len(b) {
		return 0, io.ErrShortBuffer
	}
	if err != nil {
		return 0, err
	}
	return binary.BigEndian.Uint64(b), nil
}

// RandomUint64 returns a cryptographically random uint64 value.
func RandomUint64() (uint64, error) {
	return randomUint64(rand.Reader)
}

// DoubleSha256 calculates sha256(sha256(b)) and returns the resulting bytes.
func DoubleSha256(b []byte) []byte {
	hasher := sha256.New()
	hasher.Write(b)
	sum := hasher.Sum(nil)
	hasher.Reset()
	hasher.Write(sum)
	return hasher.Sum(nil)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"path"

	"github.com/jinzhu/gorm"
	_ "github.com/lib/pq"
)

const ThumbnailExtension = ".jpg"

type ThumbnailSize struct {
	Width  int
	Height int
}

var ThumbnailSizes = map[string]ThumbnailSize{
	"small": ThumbnailSize{100, 100},
	"large": ThumbnailSize{500, 500},
}

type Config struct {
	SourceFolderPath         string `json:"source_folder_path"`
	DestinationFolderPath    string `json:"destination_folder_path"`
	ThumbnailsFolderPath     string `json:"thumbnails_folder_path"`
	DatabaseConnectionString string `json:"database_connection_string"`
}

func LoadConfig(configPath string) (Config, error) {
	var config Config
	file, err := ioutil.ReadFile(configPath)
	if err != nil {
		return config, err
	}
	err = json.Unmarshal(file, &config)
	return config, err
}

func SetupDatabase(connectionString string) gorm.DB {
	db, err := gorm.Open("postgres", connectionString)
	if err != nil {
		panic("Unable to open database")
	}

	db.AutoMigrate(&Photo{}, &SimilarPhoto{})
	return db
}

func PartitionIdAsPath(input int64) string {
	inputRunes := []rune(fmt.Sprintf("%09d", input))
	return path.Join(
		string(inputRunes[0:3]),
		string(inputRunes[3:6]),
		string(inputRunes[6:]),
	)
}
<commit_msg>Change the thumbnail sizes — also add large thumbnail format<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"path"

	"github.com/jinzhu/gorm"
	_ "github.com/lib/pq"
)

const ThumbnailExtension = ".jpg"

type ThumbnailSize struct {
	Width  int
	Height int
}

var ThumbnailSizes = map[string]ThumbnailSize{
	"small":  ThumbnailSize{100, 100},
	"medium": ThumbnailSize{300, 200},
	"large":  ThumbnailSize{1200, 666},
}

type Config struct {
	SourceFolderPath         string `json:"source_folder_path"`
	DestinationFolderPath    string `json:"destination_folder_path"`
	ThumbnailsFolderPath     string `json:"thumbnails_folder_path"`
	DatabaseConnectionString string `json:"database_connection_string"`
}

func LoadConfig(configPath string) (Config, error) {
	var config Config
	file, err := ioutil.ReadFile(configPath)
	if err != nil {
		return config, err
	}
	err = json.Unmarshal(file, &config)
	return config, err
}

func SetupDatabase(connectionString string) gorm.DB {
	db, err := gorm.Open("postgres", connectionString)
	if err != nil {
		panic("Unable to open database")
	}

	db.AutoMigrate(&Photo{}, &SimilarPhoto{})
	return db
}

func PartitionIdAsPath(input int64) string {
	inputRunes := []rune(fmt.Sprintf("%09d", input))
	return path.Join(
		string(inputRunes[0:3]),
		string(inputRunes[3:6]),
		string(inputRunes[6:]),
	)
}
<|endoftext|>


<commit_before>package neustar

import (
	"crypto/md5"
	"fmt"
	"strconv"
	"time"
)

// Configuration contains configuration.. duh
type Configuration struct {
	API struct {
		Key    string `json:"key"`
		Secret string `json:"secret"`
	} `json:"api"`
}

// Configuration contains configuration.. duh
/*
type Configuration struct {
	API struct {
		Key    string `json:"key"`
		Secret string `json:"secret"`
	} `json:"api"`
}
*/

// DigitalSignature creates an MD5 hash of the key, the secret and a timestamp
func (c *Configuration) DigitalSignature() string {
	now := time.Now()
	epoch := now.Unix()
	data := md5.Sum(
		[]byte(fmt.Sprintf("%s%s%s",
			c.API.Key, c.API.Secret, strconv.FormatInt(epoch, 10)),
		),
	)
	return fmt.Sprintf("%x", data)
}

// LoadConfig builds a config obj
func LoadConfig(key, secret string) *Configuration {
	return &Configuration{
		Key:    key,
		secret: secret,
	}
}

// LoadConfig builds a config obj
/*
func LoadConfig(cf string) (*Configuration, error) {
	confFile, err := os.Open(cf)
	if err != nil {
		return nil, err
	}
	decoder := json.NewDecoder(confFile)
	conf := &Configuration{}
	err = decoder.Decode(conf)
	if err != nil {
		return nil, err
	}
	return conf, nil
}
*/
<commit_msg>change how config works and then make it work<commit_after>package neustar

import (
	"crypto/md5"
	"fmt"
	"strconv"
	"time"
)

// Configuration contains configuration.. duh
type Configuration struct {
	API struct {
		Key    string
		Secret string
	}
}

// Configuration contains configuration.. duh
/*
type Configuration struct {
	API struct {
		Key    string `json:"key"`
		Secret string `json:"secret"`
	} `json:"api"`
}
*/

// DigitalSignature creates an MD5 hash of the key, the secret and a timestamp
func (c *Configuration) DigitalSignature() string {
	now := time.Now()
	epoch := now.Unix()
	data := md5.Sum(
		[]byte(fmt.Sprintf("%s%s%s",
			c.API.Key, c.API.Secret, strconv.FormatInt(epoch, 10)),
		),
	)
	return fmt.Sprintf("%x", data)
}

// LoadConfig builds a config obj
func LoadConfig(key, secret string) *Configuration {
	return &Configuration{
		API: struct {
			Key:    key,
			secret: secret,
		}
	}
}

// LoadConfig builds a config obj
/*
func LoadConfig(cf string) (*Configuration, error) {
	confFile, err := os.Open(cf)
	if err != nil {
		return nil, err
	}
	decoder := json.NewDecoder(confFile)
	conf := &Configuration{}
	err = decoder.Decode(conf)
	if err != nil {
		return nil, err
	}
	return conf, nil
}
*/
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"math"
	"net"
	"os"
	"strings"
	"time"

	"encoding/gob"
	"encoding/json"
	"encoding/xml"
)

type Config struct {
	serverAddr     string
	logFilename    string
	sampleFilename string
	format         string

	ServerAddr *net.TCPAddr
	TimeLimit  time.Duration
	MeterID    uint

	CenterFreq int

	SymbolLength int

	BlockSize  uint
	SampleRate uint

	PreambleLength uint
	PacketLength   uint

	Log     *log.Logger
	LogFile *os.File

	GobUnsafe bool
	Encoder   Encoder

	SampleFile *os.File

	Quiet  bool
	Single bool
}

func (c *Config) Parse() (err error) {
	flag.StringVar(&c.serverAddr, "server", "127.0.0.1:1234", "address or hostname of rtl_tcp instance")
	flag.StringVar(&c.logFilename, "logfile", "/dev/stdout", "log statement dump file")
	flag.StringVar(&c.sampleFilename, "samplefile", os.DevNull, "received message signal dump file, offset and message length are displayed to log when enabled")

	flag.IntVar(&c.CenterFreq, "centerfreq", 920299072, "center frequency to receive on")
	flag.IntVar(&c.SymbolLength, "symbollength", 73, `symbol length in samples, bandwidth and performance are determined by this value
	narrow/fast:   ( 8, 262.144 kHz)
	medium/medium: (32,   1.048 MHz), (48, 1.572 MHz)
	wide/slow:     (56,   1.835 MHz), (64, 2.097 MHz), (73, 2.392 MHz)
	valid lengths: [7, 8, 9, 28, 32, 48, 50, 56, 64, 72, 73]`)

	flag.DurationVar(&c.TimeLimit, "duration", 0, "time to run for, 0 for infinite")
	flag.UintVar(&c.MeterID, "filterid", 0, "display only messages matching given id")
	flag.StringVar(&c.format, "format", "plain", "format to write log messages in: plain, json, xml or gob")
	flag.BoolVar(&c.GobUnsafe, "gobunsafe", false, "allow gob output to stdout")
	flag.BoolVar(&c.Quiet, "quiet", false, "suppress state information printed at startup")
	flag.BoolVar(&c.Single, "single", false, "provides one shot execution, listens until exactly one message is recieved")

	flag.Parse()

	// Parse and resolve rtl_tcp server address.
	c.ServerAddr, err = net.ResolveTCPAddr("tcp", c.serverAddr)
	if err != nil {
		return
	}

	// Open or create the log file.
	if c.logFilename == "/dev/stdout" {
		c.LogFile = os.Stdout
	} else {
		c.LogFile, err = os.Create(c.logFilename)
	}

	// Create a new logger with the log file as output.
	c.Log = log.New(c.LogFile, "", log.Ldate|log.Lmicroseconds)
	if err != nil {
		return
	}

	// Create the sample file.
	c.SampleFile, err = os.Create(c.sampleFilename)
	if err != nil {
		return
	}

	validSymbolLengths := map[int]bool{7: true, 8: true, 9: true, 28: true, 32: true, 48: true, 50: true, 56: true, 64: true, 72: true, 73: true}

	if !validSymbolLengths[c.SymbolLength] {
		log.Printf("warning: invalid symbol length, probably won't receive anything")
	}

	c.SampleRate = DataRate * uint(c.SymbolLength)

	c.PreambleLength = PreambleSymbols * uint(c.SymbolLength)
	c.PacketLength = PacketSymbols * uint(c.SymbolLength)

	// Power of two sized DFT requires BlockSize to also be power of two.
	// BlockSize must be greater than the preamble length, so calculate next
	// largest power of two from preamble length.
	c.BlockSize = NextPowerOf2(c.PreambleLength)

	// Create encoder for specified logging format.
	switch strings.ToLower(c.format) {
	case "plain":
		break
	case "json":
		c.Encoder = json.NewEncoder(c.LogFile)
	case "xml":
		c.Encoder = xml.NewEncoder(c.LogFile)
	case "gob":
		c.Encoder = gob.NewEncoder(c.LogFile)

		// Don't let the user output gob to stdout unless they really want to.
		if !c.GobUnsafe && c.logFilename == "/dev/stdout" {
			fmt.Println("Gob encoded messages are not stdout safe, specify logfile or use gobunsafe flag.")
			os.Exit(1)
		}
	default:
		// We didn't get a valid encoder, exit and say so.
		log.Fatal("Invalid log format:", c.format)
	}

	return
}

func (c Config) Close() {
	c.LogFile.Close()
	c.SampleFile.Close()
}

// JSON, XML and GOB all implement this interface so we can simplify log
// output formatting.
type Encoder interface {
	Encode(interface{}) error
}

func NextPowerOf2(v uint) uint {
	return 1 << uint(math.Ceil(math.Log2(float64(v))))
}
<commit_msg>Update valid symbol lengths. Accounts for valid sample rates of rtl-sdr dongles.<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"math"
	"net"
	"os"
	"strings"
	"time"

	"encoding/gob"
	"encoding/json"
	"encoding/xml"
)

type Config struct {
	serverAddr     string
	logFilename    string
	sampleFilename string
	format         string

	ServerAddr *net.TCPAddr
	TimeLimit  time.Duration
	MeterID    uint

	CenterFreq int

	SymbolLength int

	BlockSize  uint
	SampleRate uint

	PreambleLength uint
	PacketLength   uint

	Log     *log.Logger
	LogFile *os.File

	GobUnsafe bool
	Encoder   Encoder

	SampleFile *os.File

	Quiet  bool
	Single bool
}

func (c *Config) Parse() (err error) {
	flag.StringVar(&c.serverAddr, "server", "127.0.0.1:1234", "address or hostname of rtl_tcp instance")
	flag.StringVar(&c.logFilename, "logfile", "/dev/stdout", "log statement dump file")
	flag.StringVar(&c.sampleFilename, "samplefile", os.DevNull, "received message signal dump file, offset and message length are displayed to log when enabled")

	flag.IntVar(&c.CenterFreq, "centerfreq", 920299072, "center frequency to receive on")
	flag.IntVar(&c.SymbolLength, "symbollength", 73, `symbol length in samples, bandwidth and performance are determined by this value
	narrow/fast:   ( 8, 262.144 kHz)
	medium/medium: (32,   1.048 MHz), (48, 1.572 MHz)
	wide/slow:     (56,   1.835 MHz), (64, 2.097 MHz), (73, 2.392 MHz)
	valid lengths: [7, 8, 9, 28, 32, 48, 50, 56, 64, 72, 73]`)

	flag.DurationVar(&c.TimeLimit, "duration", 0, "time to run for, 0 for infinite")
	flag.UintVar(&c.MeterID, "filterid", 0, "display only messages matching given id")
	flag.StringVar(&c.format, "format", "plain", "format to write log messages in: plain, json, xml or gob")
	flag.BoolVar(&c.GobUnsafe, "gobunsafe", false, "allow gob output to stdout")
	flag.BoolVar(&c.Quiet, "quiet", false, "suppress state information printed at startup")
	flag.BoolVar(&c.Single, "single", false, "provides one shot execution, listens until exactly one message is recieved")

	flag.Parse()

	// Parse and resolve rtl_tcp server address.
	c.ServerAddr, err = net.ResolveTCPAddr("tcp", c.serverAddr)
	if err != nil {
		return
	}

	// Open or create the log file.
	if c.logFilename == "/dev/stdout" {
		c.LogFile = os.Stdout
	} else {
		c.LogFile, err = os.Create(c.logFilename)
	}

	// Create a new logger with the log file as output.
	c.Log = log.New(c.LogFile, "", log.Ldate|log.Lmicroseconds)
	if err != nil {
		return
	}

	// Create the sample file.
	c.SampleFile, err = os.Create(c.sampleFilename)
	if err != nil {
		return
	}

	validSymbolLengths := map[int]bool{
		7: true, 8: true, 9: true, 28: true, 29: true, 30: true, 31: true,
		32: true, 33: true, 34: true, 35: true, 36: true, 37: true, 38: true,
		39: true, 40: true, 41: true, 42: true, 43: true, 44: true, 45: true,
		46: true, 47: true, 48: true, 49: true, 50: true, 51: true, 52: true,
		53: true, 54: true, 55: true, 56: true, 57: true, 58: true, 59: true,
		60: true, 61: true, 62: true, 63: true, 64: true, 65: true, 66: true,
		67: true, 68: true, 69: true, 70: true, 71: true, 72: true, 73: true,
		74: true, 75: true, 76: true, 77: true, 78: true, 79: true, 80: true,
		81: true, 82: true, 83: true, 84: true, 85: true, 86: true, 87: true,
		88: true, 89: true, 90: true, 91: true, 92: true, 93: true, 94: true,
		95: true, 96: true, 97: true,
	}

	if !validSymbolLengths[c.SymbolLength] {
		log.Printf("warning: invalid symbol length, probably won't receive anything")
	}

	c.SampleRate = DataRate * uint(c.SymbolLength)

	c.PreambleLength = PreambleSymbols * uint(c.SymbolLength)
	c.PacketLength = PacketSymbols * uint(c.SymbolLength)

	// Power of two sized DFT requires BlockSize to also be power of two.
	// BlockSize must be greater than the preamble length, so calculate next
	// largest power of two from preamble length.
	c.BlockSize = NextPowerOf2(c.PreambleLength)

	// Create encoder for specified logging format.
	switch strings.ToLower(c.format) {
	case "plain":
		break
	case "json":
		c.Encoder = json.NewEncoder(c.LogFile)
	case "xml":
		c.Encoder = xml.NewEncoder(c.LogFile)
	case "gob":
		c.Encoder = gob.NewEncoder(c.LogFile)

		// Don't let the user output gob to stdout unless they really want to.
		if !c.GobUnsafe && c.logFilename == "/dev/stdout" {
			fmt.Println("Gob encoded messages are not stdout safe, specify logfile or use gobunsafe flag.")
			os.Exit(1)
		}
	default:
		// We didn't get a valid encoder, exit and say so.
		log.Fatal("Invalid log format:", c.format)
	}

	return
}

func (c Config) Close() {
	c.LogFile.Close()
	c.SampleFile.Close()
}

// JSON, XML and GOB all implement this interface so we can simplify log
// output formatting.
type Encoder interface {
	Encode(interface{}) error
}

func NextPowerOf2(v uint) uint {
	return 1 << uint(math.Ceil(math.Log2(float64(v))))
}
<|endoftext|>


<commit_before>package connector

import (
	"os"
	"time"

	"github.com/apex/log"
)

const (
	defaultBufferSize = 500
)

type Config struct {
	// AppName is the application name.
	AppName string

	// StreamName is the Kinesis stream.
	StreamName string

	// FlushInterval is a regular interval for flushing the buffer. Defaults to 1s.
	FlushInterval time.Duration

	// BufferSize determines the batch request size. Must not exceed 500. Defaults to 500.
	BufferSize int

	// Logger is the logger used. Defaults to log.Log.
	Logger log.Interface
}

// defaults for configuration.
func (c *Config) setDefaults() {
	if c.Logger == nil {
		c.Logger = log.Log
	}

	c.Logger = c.Logger.WithFields(log.Fields{
		"package": "kinesis-connectors",
	})

	if c.AppName == "" {
		c.Logger.WithField("type", "config").Error("AppName required")
		os.Exit(1)
	}

	if c.StreamName == "" {
		c.Logger.WithField("type", "config").Error("AppName required")
		os.Exit(1)
	}

	c.Logger = c.Logger.WithFields(log.Fields{
		"app":    c.AppName,
		"stream": c.StreamName,
	})

	if c.BufferSize == 0 {
		c.BufferSize = defaultBufferSize
	}

	if c.FlushInterval == 0 {
		c.FlushInterval = time.Second
	}
}
<commit_msg>Update stream name label<commit_after>package connector

import (
	"os"
	"time"

	"github.com/apex/log"
)

const (
	defaultBufferSize = 500
)

type Config struct {
	// AppName is the application name.
	AppName string

	// StreamName is the Kinesis stream.
	StreamName string

	// FlushInterval is a regular interval for flushing the buffer. Defaults to 1s.
	FlushInterval time.Duration

	// BufferSize determines the batch request size. Must not exceed 500. Defaults to 500.
	BufferSize int

	// Logger is the logger used. Defaults to log.Log.
	Logger log.Interface
}

// defaults for configuration.
func (c *Config) setDefaults() {
	if c.Logger == nil {
		c.Logger = log.Log
	}

	c.Logger = c.Logger.WithFields(log.Fields{
		"package": "kinesis-connectors",
	})

	if c.AppName == "" {
		c.Logger.WithField("type", "config").Error("AppName required")
		os.Exit(1)
	}

	if c.StreamName == "" {
		c.Logger.WithField("type", "config").Error("StreamName required")
		os.Exit(1)
	}

	c.Logger = c.Logger.WithFields(log.Fields{
		"app":    c.AppName,
		"stream": c.StreamName,
	})

	if c.BufferSize == 0 {
		c.BufferSize = defaultBufferSize
	}

	if c.FlushInterval == 0 {
		c.FlushInterval = time.Second
	}
}
<|endoftext|>


<commit_before>// (c) 2012 Alexander Solovyov
// under terms of ISC license

package main

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"regexp"
	"strings"
)

type Command string

type CommandList []Command

type Rule struct {
	Deps     []string
	Commands CommandList
}

type RuleMap map[string]*Rule

type SiteConfig struct {
	Templates []string
	Base      string
	Source    string
	Output    string
	Rules     RuleMap
	Other     map[string]string
}

func NewSiteConfig(path string) (*SiteConfig, error) {
	source, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	basepath, _ := filepath.Split(path)
	cfg := &SiteConfig{
		Rules: make(RuleMap),
		Other: make(map[string]string),
		Base:  basepath,
	}

	indent := 0
	level := 0
	prefix := regexp.MustCompile("^[ \t]*")
	comment := regexp.MustCompile(`[^\\]#`)

	var current *Rule

	for i, line := range strings.Split(string(source), "\n") {
		// check indent
		indnew := len(prefix.FindString(line))
		switch {
		case indnew > indent:
			level += 1
		case indnew < indent:
			level -= 1
		}
		indent = indnew

		// remove useless stuff from line
		line = line[indent:]
		commentloc := comment.FindIndex([]byte(line))
		if commentloc != nil {
			line = line[:commentloc[0]]
		}
		line = strings.Replace(line, "\\#", "#", -1)
		line = strings.TrimSpace(line)

		if len(line) == 0 {
			continue
		}

		// is this a constant declaration?
		if level == 0 && strings.Index(line, "=") != -1 {
			cfg.ParseVariable(basepath, line)
			continue
		}

		// not a constant, then a Rule start?
		if level == 0 {
			current = cfg.ParseRule(line)
			continue
		}

		if level == 1 {
			if current == nil {
				return nil, fmt.Errorf("Indent without rules, line %d", i+1)
			}
			current.ParseCommand(line)
			continue
		}

		return nil, fmt.Errorf("Unhandled situation on line %d: %s",
			i+1, line)
	}

	return cfg, nil
}

// *** Parsing methods

func (cfg *SiteConfig) ParseVariable(base string, line string) {
	bits := TrimSplitN(line, "=", 2)
	switch bits[0] {
	case "TEMPLATES":
		cfg.Templates = strings.Split(bits[1], " ")
		for i, template := range cfg.Templates {
			cfg.Templates[i] = filepath.Join(base, template)
		}
	case "SOURCE":
		cfg.Source = filepath.Join(base, bits[1])
	case "OUTPUT":
		cfg.Output = filepath.Join(base, bits[1])
	default:
		cfg.Other[Capitalize(bits[0])] = bits[1]
	}
}

func (cfg *SiteConfig) ParseRule(line string) *Rule {
	bits := TrimSplitN(line, ":", 2)
	deps := NonEmptySplit(bits[1], " ")
	rd := &Rule{
		Deps:     deps,
		Commands: make(CommandList, 0),
	}

	cfg.Rules[bits[0]] = rd

	return rd
}

func (rule *Rule) ParseCommand(line string) {
	rule.Commands = append(rule.Commands, Command(line))
}

// *** Traversing methods

func (cmd Command) Matches(prefix Command) bool {
	return cmd == prefix || strings.HasPrefix(string(cmd), string(prefix)+" ")
}

func (cmd Command) MatchesAny(prefixes CommandList) bool {
	for _, prefix := range prefixes {
		if cmd.Matches(prefix) {
			return true
		}
	}
	return false
}

func (commands CommandList) MatchedIndex(prefix Command) int {
	for i, cmd := range commands {
		if cmd.Matches(prefix) {
			return i
		}
	}
	return -1
}

func (rule Rule) MatchedCommand(prefix Command) *Command {
	i := rule.Commands.MatchedIndex(prefix)
	if i == -1 {
		return nil
	}

	return &rule.Commands[i]
}

func (rule *Rule) IsDep(page *Page) bool {
	for _, dep := range rule.Deps {
		matches, err := filepath.Match(dep, page.Source)
		if err == nil && matches {
			return true
		}
	}
	return false
}

func (rules RuleMap) MatchedRule(path string) (string, *Rule) {
	if rules[path] != nil {
		return path, rules[path]
	}

	_, name := filepath.Split(path)
	if rules[name] != nil {
		return name, rules[name]
	}

	for pat, rule := range rules {
		matched, err := filepath.Match(pat, path)
		errhandle(err)
		if matched {
			return pat, rule
		}
	}

	for pat, rule := range rules {
		matched, err := filepath.Match(pat, name)
		errhandle(err)
		if matched {
			return pat, rule
		}
	}

	return "", nil
}
<commit_msg>Handle comments in configuration file<commit_after>// (c) 2012 Alexander Solovyov
// under terms of ISC license

package main

import (
	"fmt"
	"io/ioutil"
	"path/filepath"
	"regexp"
	"strings"
)

type Command string

type CommandList []Command

type Rule struct {
	Deps     []string
	Commands CommandList
}

type RuleMap map[string]*Rule

type SiteConfig struct {
	Templates []string
	Base      string
	Source    string
	Output    string
	Rules     RuleMap
	Other     map[string]string
}

func NewSiteConfig(path string) (*SiteConfig, error) {
	source, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	basepath, _ := filepath.Split(path)
	cfg := &SiteConfig{
		Rules: make(RuleMap),
		Other: make(map[string]string),
		Base:  basepath,
	}

	indent := 0
	level := 0
	prefix := regexp.MustCompile("^[ \t]*")
	comment := regexp.MustCompile(`[^\\]#`)

	var current *Rule

	for i, line := range strings.Split(string(source), "\n") {
		// check indent
		indnew := len(prefix.FindString(line))
		switch {
		case indnew > indent:
			level += 1
		case indnew < indent:
			level -= 1
		}
		indent = indnew

		// remove useless stuff from line
		line = line[indent:]
		commentloc := comment.FindIndex([]byte(line))
		if commentloc != nil {
			line = line[:commentloc[0]]
		}
		line = strings.Replace(line, "\\#", "#", -1)
		line = strings.TrimSpace(line)

		if len(line) == 0 {
			continue
		}

		if strings.HasPrefix(line, "#") {
			continue
		}

		// is this a constant declaration?
		if level == 0 && strings.Index(line, "=") != -1 {
			cfg.ParseVariable(basepath, line)
			continue
		}

		// not a constant, then a Rule start?
		if level == 0 {
			current = cfg.ParseRule(line)
			continue
		}

		if level == 1 {
			if current == nil {
				return nil, fmt.Errorf("Indent without rules, line %d", i+1)
			}
			current.ParseCommand(line)
			continue
		}

		return nil, fmt.Errorf("Unhandled situation on line %d: %s",
			i+1, line)
	}

	return cfg, nil
}

// *** Parsing methods

func (cfg *SiteConfig) ParseVariable(base string, line string) {
	bits := TrimSplitN(line, "=", 2)
	switch bits[0] {
	case "TEMPLATES":
		cfg.Templates = strings.Split(bits[1], " ")
		for i, template := range cfg.Templates {
			cfg.Templates[i] = filepath.Join(base, template)
		}
	case "SOURCE":
		cfg.Source = filepath.Join(base, bits[1])
	case "OUTPUT":
		cfg.Output = filepath.Join(base, bits[1])
	default:
		cfg.Other[Capitalize(bits[0])] = bits[1]
	}
}

func (cfg *SiteConfig) ParseRule(line string) *Rule {
	bits := TrimSplitN(line, ":", 2)
	deps := NonEmptySplit(bits[1], " ")
	rd := &Rule{
		Deps:     deps,
		Commands: make(CommandList, 0),
	}

	cfg.Rules[bits[0]] = rd

	return rd
}

func (rule *Rule) ParseCommand(line string) {
	rule.Commands = append(rule.Commands, Command(line))
}

// *** Traversing methods

func (cmd Command) Matches(prefix Command) bool {
	return cmd == prefix || strings.HasPrefix(string(cmd), string(prefix)+" ")
}

func (cmd Command) MatchesAny(prefixes CommandList) bool {
	for _, prefix := range prefixes {
		if cmd.Matches(prefix) {
			return true
		}
	}
	return false
}

func (commands CommandList) MatchedIndex(prefix Command) int {
	for i, cmd := range commands {
		if cmd.Matches(prefix) {
			return i
		}
	}
	return -1
}

func (rule Rule) MatchedCommand(prefix Command) *Command {
	i := rule.Commands.MatchedIndex(prefix)
	if i == -1 {
		return nil
	}

	return &rule.Commands[i]
}

func (rule *Rule) IsDep(page *Page) bool {
	for _, dep := range rule.Deps {
		matches, err := filepath.Match(dep, page.Source)
		if err == nil && matches {
			return true
		}
	}
	return false
}

func (rules RuleMap) MatchedRule(path string) (string, *Rule) {
	if rules[path] != nil {
		return path, rules[path]
	}

	_, name := filepath.Split(path)
	if rules[name] != nil {
		return name, rules[name]
	}

	for pat, rule := range rules {
		matched, err := filepath.Match(pat, path)
		errhandle(err)
		if matched {
			return pat, rule
		}
	}

	for pat, rule := range rules {
		matched, err := filepath.Match(pat, name)
		errhandle(err)
		if matched {
			return pat, rule
		}
	}

	return "", nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Intel Corporation
//
// 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"
	"fmt"
	"io/ioutil"
	goruntime "runtime"
	"strings"

	"github.com/BurntSushi/toml"
	vc "github.com/containers/virtcontainers"
	"github.com/containers/virtcontainers/pkg/oci"
	"github.com/sirupsen/logrus"
)

const (
	defaultHypervisor = vc.QemuHypervisor
	defaultProxy      = vc.CCProxyType
	defaultShim       = vc.CCShimType
	defaultAgent      = vc.HyperstartAgent
)

// The TOML configuration file contains a number of sections (or
// tables). The names of these tables are in dotted ("nested table")
// form:
//
//   [<component>.<type>]
//
// The components are hypervisor, proxy, shim and agent. For example,
//
//   [proxy.cc]
//
// The currently supported types are listed below:
const (
	// supported hypervisor component types
	qemuHypervisorTableType = "qemu"

	// supported proxy component types
	ccProxyTableType = "cc"

	// supported shim component types
	ccShimTableType = "cc"

	// supported agent component types
	hyperstartAgentTableType = "hyperstart"

	// the maximum amount of PCI bridges that can be cold plugged in a VM
	maxPCIBridges uint32 = 5
)

var (
	errUnknownHypervisor = errors.New("unknown hypervisor")
	errUnknownAgent      = errors.New("unknown agent")
)

type tomlConfig struct {
	Hypervisor map[string]hypervisor
	Proxy      map[string]proxy
	Shim       map[string]shim
	Agent      map[string]agent
	Runtime    runtime
}

type hypervisor struct {
	Path                  string `toml:"path"`
	Kernel                string `toml:"kernel"`
	Image                 string `toml:"image"`
	Firmware              string `toml:"firmware"`
	MachineAccelerators   string `toml:"machine_accelerators"`
	KernelParams          string `toml:"kernel_params"`
	MachineType           string `toml:"machine_type"`
	DefaultVCPUs          int32  `toml:"default_vcpus"`
	DefaultMemSz          uint32 `toml:"default_memory"`
	DefaultBridges        uint32 `toml:"default_bridges"`
	DisableBlockDeviceUse bool   `toml:"disable_block_device_use"`
	MemPrealloc           bool   `toml:"enable_mem_prealloc"`
	HugePages             bool   `toml:"enable_hugepages"`
	Swap                  bool   `toml:"enable_swap"`
	Debug                 bool   `toml:"enable_debug"`
	DisableNestingChecks  bool   `toml:"disable_nesting_checks"`
}

type proxy struct {
	Path  string `toml:"path"`
	Debug bool   `toml:"enable_debug"`
}

type runtime struct {
	Debug bool `toml:"enable_debug"`
}

type shim struct {
	Path  string `toml:"path"`
	Debug bool   `toml:"enable_debug"`
}

type agent struct {
}

func (h hypervisor) path() (string, error) {
	p := h.Path

	if h.Path == "" {
		p = defaultHypervisorPath
	}

	return resolvePath(p)
}

func (h hypervisor) kernel() (string, error) {
	p := h.Kernel

	if p == "" {
		p = defaultKernelPath
	}

	return resolvePath(p)
}

func (h hypervisor) image() (string, error) {
	p := h.Image

	if p == "" {
		p = defaultImagePath
	}

	return resolvePath(p)
}

func (h hypervisor) firmware() (string, error) {
	p := h.Firmware

	if p == "" {
		if defaultFirmwarePath == "" {
			return "", nil
		}
		p = defaultFirmwarePath
	}

	return resolvePath(p)
}

func (h hypervisor) machineAccelerators() string {
	var machineAccelerators string
	accelerators := strings.Split(h.MachineAccelerators, ",")
	acceleratorsLen := len(accelerators)
	for i := 0; i < acceleratorsLen; i++ {
		if accelerators[i] != "" {
			machineAccelerators += strings.Trim(accelerators[i], "\r\t\n ") + ","
		}
	}

	machineAccelerators = strings.Trim(machineAccelerators, ",")

	return machineAccelerators
}

func (h hypervisor) kernelParams() string {
	if h.KernelParams == "" {
		return defaultKernelParams
	}

	return h.KernelParams
}

func (h hypervisor) machineType() string {
	if h.MachineType == "" {
		return defaultMachineType
	}

	return h.MachineType
}

func (h hypervisor) defaultVCPUs() uint32 {
	if h.DefaultVCPUs < 0 {
		return uint32(goruntime.NumCPU())
	}
	if h.DefaultVCPUs == 0 { // or unspecified
		return defaultVCPUCount
	}
	if h.DefaultVCPUs > 255 { // qemu supports max 255
		return 255
	}

	return uint32(h.DefaultVCPUs)
}

func (h hypervisor) defaultMemSz() uint32 {
	if h.DefaultMemSz < 8 {
		return defaultMemSize // MiB
	}

	return h.DefaultMemSz
}

func (h hypervisor) defaultBridges() uint32 {
	if h.DefaultBridges == 0 {
		return defaultBridgesCount
	}

	if h.DefaultBridges > maxPCIBridges {
		return maxPCIBridges
	}

	return h.DefaultBridges
}

func (p proxy) path() string {
	if p.Path == "" {
		return defaultProxyPath
	}

	return p.Path
}

func (p proxy) debug() bool {
	return p.Debug
}

func (s shim) path() (string, error) {
	p := s.Path

	if p == "" {
		p = defaultShimPath
	}

	return resolvePath(p)
}

func (s shim) debug() bool {
	return s.Debug
}

func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
	hypervisor, err := h.path()
	if err != nil {
		return vc.HypervisorConfig{}, err
	}

	kernel, err := h.kernel()
	if err != nil {
		return vc.HypervisorConfig{}, err
	}

	image, err := h.image()
	if err != nil {
		return vc.HypervisorConfig{}, err
	}

	firmware, err := h.firmware()
	if err != nil {
		return vc.HypervisorConfig{}, err
	}

	machineAccelerators := h.machineAccelerators()
	kernelParams := h.kernelParams()
	machineType := h.machineType()

	return vc.HypervisorConfig{
		HypervisorPath:        hypervisor,
		KernelPath:            kernel,
		ImagePath:             image,
		FirmwarePath:          firmware,
		MachineAccelerators:   machineAccelerators,
		KernelParams:          vc.DeserializeParams(strings.Fields(kernelParams)),
		HypervisorMachineType: machineType,
		DefaultVCPUs:          h.defaultVCPUs(),
		DefaultMemSz:          h.defaultMemSz(),
		DefaultBridges:        h.defaultBridges(),
		DisableBlockDeviceUse: h.DisableBlockDeviceUse,
		MemPrealloc:           h.MemPrealloc,
		HugePages:             h.HugePages,
		Mlock:                 !h.Swap,
		Debug:                 h.Debug,
		DisableNestingChecks:  h.DisableNestingChecks,
	}, nil
}

func newShimConfig(s shim) (vc.ShimConfig, error) {
	path, err := s.path()
	if err != nil {
		return vc.ShimConfig{}, err
	}

	return vc.ShimConfig{
		Path:  path,
		Debug: s.debug(),
	}, nil
}

func updateRuntimeConfig(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig) error {
	for k, hypervisor := range tomlConf.Hypervisor {
		switch k {
		case qemuHypervisorTableType:
			hConfig, err := newQemuHypervisorConfig(hypervisor)
			if err != nil {
				return fmt.Errorf("%v: %v", configPath, err)
			}

			config.HypervisorConfig = hConfig
		}
	}

	for k, proxy := range tomlConf.Proxy {
		switch k {
		case ccProxyTableType:
			pConfig := vc.ProxyConfig{
				Path:  proxy.path(),
				Debug: proxy.debug(),
			}

			config.ProxyType = vc.CCProxyType
			config.ProxyConfig = pConfig
		}
	}

	for k := range tomlConf.Agent {
		switch k {
		case hyperstartAgentTableType:
			config.AgentConfig = vc.HyperConfig{}
		}
	}

	for k, shim := range tomlConf.Shim {
		switch k {
		case ccShimTableType:
			shConfig, err := newShimConfig(shim)
			if err != nil {
				return fmt.Errorf("%v: %v", configPath, err)
			}

			config.ShimType = vc.CCShimType
			config.ShimConfig = shConfig
		}
	}

	return nil
}

// loadConfiguration loads the configuration file and converts it into a
// runtime configuration.
//
// If ignoreLogging is true, the system logger will not be initialised nor
// will this function make any log calls.
//
// All paths are resolved fully meaning if this function does not return an
// error, all paths are valid at the time of the call.
func loadConfiguration(configPath string, ignoreLogging bool) (resolvedConfigPath string, config oci.RuntimeConfig, err error) {
	defaultHypervisorConfig := vc.HypervisorConfig{
		HypervisorPath:        defaultHypervisorPath,
		KernelPath:            defaultKernelPath,
		ImagePath:             defaultImagePath,
		FirmwarePath:          defaultFirmwarePath,
		MachineAccelerators:   defaultMachineAccelerators,
		HypervisorMachineType: defaultMachineType,
		DefaultVCPUs:          defaultVCPUCount,
		DefaultMemSz:          defaultMemSize,
		DefaultBridges:        defaultBridgesCount,
		MemPrealloc:           defaultEnableMemPrealloc,
		HugePages:             defaultEnableHugePages,
		Mlock:                 !defaultEnableSwap,
		Debug:                 defaultEnableDebug,
		DisableNestingChecks:  defaultDisableNestingChecks,
	}

	defaultAgentConfig := vc.HyperConfig{}

	config = oci.RuntimeConfig{
		HypervisorType:   defaultHypervisor,
		HypervisorConfig: defaultHypervisorConfig,
		AgentType:        defaultAgent,
		AgentConfig:      defaultAgentConfig,
		ProxyType:        defaultProxy,
		ShimType:         defaultShim,
	}

	var resolved string

	if configPath == "" {
		resolved, err = getDefaultConfigFile()
	} else {
		resolved, err = resolvePath(configPath)
	}

	if err != nil {
		return "", config, fmt.Errorf("Cannot find usable config file (%v)", err)
	}

	configData, err := ioutil.ReadFile(resolved)
	if err != nil {
		return "", config, err
	}

	var tomlConf tomlConfig
	_, err = toml.Decode(string(configData), &tomlConf)
	if err != nil {
		return "", config, err
	}

	if !tomlConf.Runtime.Debug {
		// If debug is not required, switch back to the original
		// default log priority, otherwise continue in debug mode.
		ccLog.Logger.Level = originalLoggerLevel
	}

	if !ignoreLogging {
		err = handleSystemLog("", "")
		if err != nil {
			return "", config, err
		}

		ccLog.WithFields(
			logrus.Fields{
				"format": "TOML",
			}).Debugf("loaded configuration")
	}

	if err := updateRuntimeConfig(resolved, tomlConf, &config); err != nil {
		return "", config, err
	}

	return resolved, config, nil
}

// getDefaultConfigFilePaths returns a list of paths that will be
// considered as configuration files in priority order.
func getDefaultConfigFilePaths() []string {
	return []string{
		// normally below "/etc"
		defaultSysConfRuntimeConfiguration,

		// normally below "/usr/share"
		defaultRuntimeConfiguration,
	}
}

// getDefaultConfigFile looks in multiple default locations for a
// configuration file and returns the resolved path for the first file
// found, or an error if no config files can be found.
func getDefaultConfigFile() (string, error) {
	var errs []string

	for _, file := range getDefaultConfigFilePaths() {
		resolved, err := resolvePath(file)
		if err == nil {
			return resolved, nil
		}
		s := fmt.Sprintf("config file %q unresolvable: %v", file, err)
		errs = append(errs, s)
	}

	return "", errors.New(strings.Join(errs, ", "))
}
<commit_msg>config: Add Kata Containers possibility<commit_after>// Copyright (c) 2017 Intel Corporation
//
// 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"
	"fmt"
	"io/ioutil"
	goruntime "runtime"
	"strings"

	"github.com/BurntSushi/toml"
	vc "github.com/containers/virtcontainers"
	"github.com/containers/virtcontainers/pkg/oci"
	"github.com/sirupsen/logrus"
)

const (
	defaultHypervisor = vc.QemuHypervisor
	defaultProxy      = vc.CCProxyType
	defaultShim       = vc.CCShimType
	defaultAgent      = vc.HyperstartAgent
)

// The TOML configuration file contains a number of sections (or
// tables). The names of these tables are in dotted ("nested table")
// form:
//
//   [<component>.<type>]
//
// The components are hypervisor, proxy, shim and agent. For example,
//
//   [proxy.cc]
//
// The currently supported types are listed below:
const (
	// supported hypervisor component types
	qemuHypervisorTableType = "qemu"

	// supported proxy component types
	ccProxyTableType   = "cc"
	kataProxyTableType = "kata"

	// supported shim component types
	ccShimTableType   = "cc"
	kataShimTableType = "kata"

	// supported agent component types
	hyperstartAgentTableType = "hyperstart"
	kataAgentTableType       = "kata"

	// the maximum amount of PCI bridges that can be cold plugged in a VM
	maxPCIBridges uint32 = 5
)

var (
	errUnknownHypervisor = errors.New("unknown hypervisor")
	errUnknownAgent      = errors.New("unknown agent")
)

type tomlConfig struct {
	Hypervisor map[string]hypervisor
	Proxy      map[string]proxy
	Shim       map[string]shim
	Agent      map[string]agent
	Runtime    runtime
}

type hypervisor struct {
	Path                  string `toml:"path"`
	Kernel                string `toml:"kernel"`
	Image                 string `toml:"image"`
	Firmware              string `toml:"firmware"`
	MachineAccelerators   string `toml:"machine_accelerators"`
	KernelParams          string `toml:"kernel_params"`
	MachineType           string `toml:"machine_type"`
	DefaultVCPUs          int32  `toml:"default_vcpus"`
	DefaultMemSz          uint32 `toml:"default_memory"`
	DefaultBridges        uint32 `toml:"default_bridges"`
	DisableBlockDeviceUse bool   `toml:"disable_block_device_use"`
	MemPrealloc           bool   `toml:"enable_mem_prealloc"`
	HugePages             bool   `toml:"enable_hugepages"`
	Swap                  bool   `toml:"enable_swap"`
	Debug                 bool   `toml:"enable_debug"`
	DisableNestingChecks  bool   `toml:"disable_nesting_checks"`
}

type proxy struct {
	Path  string `toml:"path"`
	Debug bool   `toml:"enable_debug"`
}

type runtime struct {
	Debug bool `toml:"enable_debug"`
}

type shim struct {
	Path  string `toml:"path"`
	Debug bool   `toml:"enable_debug"`
}

type agent struct {
}

func (h hypervisor) path() (string, error) {
	p := h.Path

	if h.Path == "" {
		p = defaultHypervisorPath
	}

	return resolvePath(p)
}

func (h hypervisor) kernel() (string, error) {
	p := h.Kernel

	if p == "" {
		p = defaultKernelPath
	}

	return resolvePath(p)
}

func (h hypervisor) image() (string, error) {
	p := h.Image

	if p == "" {
		p = defaultImagePath
	}

	return resolvePath(p)
}

func (h hypervisor) firmware() (string, error) {
	p := h.Firmware

	if p == "" {
		if defaultFirmwarePath == "" {
			return "", nil
		}
		p = defaultFirmwarePath
	}

	return resolvePath(p)
}

func (h hypervisor) machineAccelerators() string {
	var machineAccelerators string
	accelerators := strings.Split(h.MachineAccelerators, ",")
	acceleratorsLen := len(accelerators)
	for i := 0; i < acceleratorsLen; i++ {
		if accelerators[i] != "" {
			machineAccelerators += strings.Trim(accelerators[i], "\r\t\n ") + ","
		}
	}

	machineAccelerators = strings.Trim(machineAccelerators, ",")

	return machineAccelerators
}

func (h hypervisor) kernelParams() string {
	if h.KernelParams == "" {
		return defaultKernelParams
	}

	return h.KernelParams
}

func (h hypervisor) machineType() string {
	if h.MachineType == "" {
		return defaultMachineType
	}

	return h.MachineType
}

func (h hypervisor) defaultVCPUs() uint32 {
	if h.DefaultVCPUs < 0 {
		return uint32(goruntime.NumCPU())
	}
	if h.DefaultVCPUs == 0 { // or unspecified
		return defaultVCPUCount
	}
	if h.DefaultVCPUs > 255 { // qemu supports max 255
		return 255
	}

	return uint32(h.DefaultVCPUs)
}

func (h hypervisor) defaultMemSz() uint32 {
	if h.DefaultMemSz < 8 {
		return defaultMemSize // MiB
	}

	return h.DefaultMemSz
}

func (h hypervisor) defaultBridges() uint32 {
	if h.DefaultBridges == 0 {
		return defaultBridgesCount
	}

	if h.DefaultBridges > maxPCIBridges {
		return maxPCIBridges
	}

	return h.DefaultBridges
}

func (p proxy) path() string {
	if p.Path == "" {
		return defaultProxyPath
	}

	return p.Path
}

func (p proxy) debug() bool {
	return p.Debug
}

func (s shim) path() (string, error) {
	p := s.Path

	if p == "" {
		p = defaultShimPath
	}

	return resolvePath(p)
}

func (s shim) debug() bool {
	return s.Debug
}

func newQemuHypervisorConfig(h hypervisor) (vc.HypervisorConfig, error) {
	hypervisor, err := h.path()
	if err != nil {
		return vc.HypervisorConfig{}, err
	}

	kernel, err := h.kernel()
	if err != nil {
		return vc.HypervisorConfig{}, err
	}

	image, err := h.image()
	if err != nil {
		return vc.HypervisorConfig{}, err
	}

	firmware, err := h.firmware()
	if err != nil {
		return vc.HypervisorConfig{}, err
	}

	machineAccelerators := h.machineAccelerators()
	kernelParams := h.kernelParams()
	machineType := h.machineType()

	return vc.HypervisorConfig{
		HypervisorPath:        hypervisor,
		KernelPath:            kernel,
		ImagePath:             image,
		FirmwarePath:          firmware,
		MachineAccelerators:   machineAccelerators,
		KernelParams:          vc.DeserializeParams(strings.Fields(kernelParams)),
		HypervisorMachineType: machineType,
		DefaultVCPUs:          h.defaultVCPUs(),
		DefaultMemSz:          h.defaultMemSz(),
		DefaultBridges:        h.defaultBridges(),
		DisableBlockDeviceUse: h.DisableBlockDeviceUse,
		MemPrealloc:           h.MemPrealloc,
		HugePages:             h.HugePages,
		Mlock:                 !h.Swap,
		Debug:                 h.Debug,
		DisableNestingChecks:  h.DisableNestingChecks,
	}, nil
}

func newShimConfig(s shim) (vc.ShimConfig, error) {
	path, err := s.path()
	if err != nil {
		return vc.ShimConfig{}, err
	}

	return vc.ShimConfig{
		Path:  path,
		Debug: s.debug(),
	}, nil
}

func updateRuntimeConfig(configPath string, tomlConf tomlConfig, config *oci.RuntimeConfig) error {
	for k, hypervisor := range tomlConf.Hypervisor {
		switch k {
		case qemuHypervisorTableType:
			hConfig, err := newQemuHypervisorConfig(hypervisor)
			if err != nil {
				return fmt.Errorf("%v: %v", configPath, err)
			}

			config.HypervisorConfig = hConfig
		}
	}

	for k, proxy := range tomlConf.Proxy {
		switch k {
		case ccProxyTableType:
			config.ProxyType = vc.CCProxyType
		case kataProxyTableType:
			config.ProxyType = vc.KataProxyType
		}

		config.ProxyConfig = vc.ProxyConfig{
			Path:  proxy.path(),
			Debug: proxy.debug(),
		}
	}

	for k := range tomlConf.Agent {
		switch k {
		case hyperstartAgentTableType:
			config.AgentConfig = vc.HyperConfig{}
		case kataAgentTableType:
			config.AgentConfig = vc.KataAgentConfig{}
		}
	}

	for k, shim := range tomlConf.Shim {
		switch k {
		case ccShimTableType:
			config.ShimType = vc.CCShimType
		case kataShimTableType:
			config.ShimType = vc.KataShimType
		}

		shConfig, err := newShimConfig(shim)
		if err != nil {
			return fmt.Errorf("%v: %v", configPath, err)
		}

		config.ShimConfig = shConfig
	}

	return nil
}

// loadConfiguration loads the configuration file and converts it into a
// runtime configuration.
//
// If ignoreLogging is true, the system logger will not be initialised nor
// will this function make any log calls.
//
// All paths are resolved fully meaning if this function does not return an
// error, all paths are valid at the time of the call.
func loadConfiguration(configPath string, ignoreLogging bool) (resolvedConfigPath string, config oci.RuntimeConfig, err error) {
	defaultHypervisorConfig := vc.HypervisorConfig{
		HypervisorPath:        defaultHypervisorPath,
		KernelPath:            defaultKernelPath,
		ImagePath:             defaultImagePath,
		FirmwarePath:          defaultFirmwarePath,
		MachineAccelerators:   defaultMachineAccelerators,
		HypervisorMachineType: defaultMachineType,
		DefaultVCPUs:          defaultVCPUCount,
		DefaultMemSz:          defaultMemSize,
		DefaultBridges:        defaultBridgesCount,
		MemPrealloc:           defaultEnableMemPrealloc,
		HugePages:             defaultEnableHugePages,
		Mlock:                 !defaultEnableSwap,
		Debug:                 defaultEnableDebug,
		DisableNestingChecks:  defaultDisableNestingChecks,
	}

	defaultAgentConfig := vc.HyperConfig{}

	config = oci.RuntimeConfig{
		HypervisorType:   defaultHypervisor,
		HypervisorConfig: defaultHypervisorConfig,
		AgentType:        defaultAgent,
		AgentConfig:      defaultAgentConfig,
		ProxyType:        defaultProxy,
		ShimType:         defaultShim,
	}

	var resolved string

	if configPath == "" {
		resolved, err = getDefaultConfigFile()
	} else {
		resolved, err = resolvePath(configPath)
	}

	if err != nil {
		return "", config, fmt.Errorf("Cannot find usable config file (%v)", err)
	}

	configData, err := ioutil.ReadFile(resolved)
	if err != nil {
		return "", config, err
	}

	var tomlConf tomlConfig
	_, err = toml.Decode(string(configData), &tomlConf)
	if err != nil {
		return "", config, err
	}

	if !tomlConf.Runtime.Debug {
		// If debug is not required, switch back to the original
		// default log priority, otherwise continue in debug mode.
		ccLog.Logger.Level = originalLoggerLevel
	}

	if !ignoreLogging {
		err = handleSystemLog("", "")
		if err != nil {
			return "", config, err
		}

		ccLog.WithFields(
			logrus.Fields{
				"format": "TOML",
			}).Debugf("loaded configuration")
	}

	if err := updateRuntimeConfig(resolved, tomlConf, &config); err != nil {
		return "", config, err
	}

	return resolved, config, nil
}

// getDefaultConfigFilePaths returns a list of paths that will be
// considered as configuration files in priority order.
func getDefaultConfigFilePaths() []string {
	return []string{
		// normally below "/etc"
		defaultSysConfRuntimeConfiguration,

		// normally below "/usr/share"
		defaultRuntimeConfiguration,
	}
}

// getDefaultConfigFile looks in multiple default locations for a
// configuration file and returns the resolved path for the first file
// found, or an error if no config files can be found.
func getDefaultConfigFile() (string, error) {
	var errs []string

	for _, file := range getDefaultConfigFilePaths() {
		resolved, err := resolvePath(file)
		if err == nil {
			return resolved, nil
		}
		s := fmt.Sprintf("config file %q unresolvable: %v", file, err)
		errs = append(errs, s)
	}

	return "", errors.New(strings.Join(errs, ", "))
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"html/template"
	"io/ioutil"
	"net/http"
	"path"
	"path/filepath"
	"sync"
)

var staticConfig *GlobalSection
var configLock = new(sync.RWMutex)

var allTemplates = template.New("allTemplates")
var templateLock = new(sync.RWMutex)

// GlobalSection is the top level section of a config
//  * Indexes is a child section - it's an array of IndexSection
//  * Redirects is a child section - it's an array of RedirectSection
type GlobalSection struct {
	Address     string
	Port        string
	Hostname    string
	TemplateDir string
	CertFile    string
	KeyFile     string
	Indexes     []IndexSection
	Redirects   []RedirectSection
}

// RedirectSection details each redirect to serve
type RedirectSection struct {
	Requested string
	Target    string
	Code      int
}

// IndexSection details each index to open. If IndexPath is nil, no index is
//  used but handlers underneath are still processed.
//  * Handlers is a child section - array of ServerSections
type IndexSection struct {
	WatchDirs      map[string]string // physical -> URI Location that we will be watching for updates
	WatchExtension string            // file extensions that we will watch for within that dir
	IndexPath      string            //location to store the index
	IndexType      string            // type of index - likely "en"
	IndexName      string            // name of the index
	Restricted     []string          // Tags to restrict indexing on
	Handlers       []ServerSection
}

// ServerSection details a handler to lay out
type ServerSection struct {
	Path             string   // filesystem path to serve out
	Prefix           string   // Web URL Prefix - alternatively the prefix for a search handler
	Default          string   // Default page to serve if empty URI - alternatively the facet to list against
	Template         string   // Template file to build the response from
	FallbackTemplate string   // template to fall back to for each handlers
	ServerType       string   // markdown, raw, search, or facet to denote the type of Server handle
	TopicURL         string   // URI prefix to redirect to topic pages
	Restricted       []string // list of restricts - extensions for raw, topics for markdown
}

// GetConfig safely returns the config file
func GetConfig() *GlobalSection {
	configLock.RLock()
	defer configLock.RUnlock()
	return staticConfig
}

// LoadConfig reads in a config file, cleans it up, and sets it to the global
func LoadConfig(configFile string) error {
	// set a default file
	if configFile == "" {
		configFile = "config.json"
	}

	// have to read in the line into a byte[] array
	fileContents, err := ioutil.ReadFile(configFile)
	if err != nil {
		return &Error{Code: ErrReadConfig, innerError: err, value: configFile}
	}

	// UnMarshal the config file that was read in
	temp := new(GlobalSection)

	err = json.Unmarshal(fileContents, temp)
	//Make sure you were able to read it in
	if err != nil {
		return &Error{Code: ErrParseConfig, value: temp, innerError: err}
	}

	CleanConfig(temp)

	configLock.Lock()
	staticConfig = temp
	configLock.Unlock()

	return nil
}

// CleanConfig takes a given config struct, and makes sure values are valid
func CleanConfig(config *GlobalSection) {
	config.TemplateDir = filepath.Clean(config.TemplateDir)
	for r := range config.Redirects {
		config.Redirects[r].Requested = path.Clean(config.Redirects[r].Requested)
		config.Redirects[r].Target = path.Clean(config.Redirects[r].Target)
		if config.Redirects[r].Code == 0 {
			config.Redirects[r].Code = 301
		}
	}

	for _, indexSection := range config.Indexes {
		for origDirPath, origWebPath := range indexSection.WatchDirs {
			delete(indexSection.WatchDirs, origDirPath)
			indexSection.WatchDirs[filepath.Clean(origDirPath)] = path.Clean(origWebPath)
		}

		for i := range indexSection.Handlers {
			indexSection.Handlers[i].Path = filepath.Clean(indexSection.Handlers[i].Path)
			indexSection.Handlers[i].Prefix = path.Clean(indexSection.Handlers[i].Prefix)
			indexSection.Handlers[i].Default = path.Clean(indexSection.Handlers[i].Default)
			indexSection.Handlers[i].TopicURL = path.Clean(indexSection.Handlers[i].TopicURL)
		}
	}
}

// RenderTemplate runs a given template as you would expect - it needs:
// * a http.ResponseWrtier for output
// * a template to render
// * a chunk of data
func RenderTemplate(responsePipe http.ResponseWriter, templateName string,
	data interface{}) error {
	templateLock.RLock()
	defer templateLock.RUnlock()

	return allTemplates.ExecuteTemplate(responsePipe, templateName, data)
}

// ParseTemplates parses all templates in a folder into one global template
func ParseTemplates(globalConfig GlobalSection) error {
	newTemplate, err := template.ParseGlob(globalConfig.TemplateDir + "*")
	if err != nil {
		return &Error{Code: ErrParseTemplates, innerError: err}
	}

	templateLock.Lock()
	defer templateLock.Unlock()
	allTemplates = newTemplate
	return nil
}
<commit_msg>fixed the handler paths stuff<commit_after>package main

import (
	"encoding/json"
	"html/template"
	"io/ioutil"
	"net/http"
	"path"
	"path/filepath"
	"strings"
	"sync"
)

var staticConfig *GlobalSection
var configLock = new(sync.RWMutex)

var allTemplates = template.New("allTemplates")
var templateLock = new(sync.RWMutex)

// GlobalSection is the top level section of a config
//  * Indexes is a child section - it's an array of IndexSection
//  * Redirects is a child section - it's an array of RedirectSection
type GlobalSection struct {
	Address     string
	Port        string
	Hostname    string
	TemplateDir string
	CertFile    string
	KeyFile     string
	Indexes     []IndexSection
	Redirects   []RedirectSection
}

// RedirectSection details each redirect to serve
type RedirectSection struct {
	Requested string
	Target    string
	Code      int
}

// IndexSection details each index to open. If IndexPath is nil, no index is
//  used but handlers underneath are still processed.
//  * Handlers is a child section - array of ServerSections
type IndexSection struct {
	WatchDirs      map[string]string // physical -> URI Location that we will be watching for updates
	WatchExtension string            // file extensions that we will watch for within that dir
	IndexPath      string            //location to store the index
	IndexType      string            // type of index - likely "en"
	IndexName      string            // name of the index
	Restricted     []string          // Tags to restrict indexing on
	Handlers       []ServerSection
}

// ServerSection details a handler to lay out
type ServerSection struct {
	Path             string   // filesystem path to serve out
	Prefix           string   // Web URL Prefix - alternatively the prefix for a search handler
	Default          string   // Default page to serve if empty URI - alternatively the facet to list against
	Template         string   // Template file to build the response from
	FallbackTemplate string   // template to fall back to for each handlers
	ServerType       string   // markdown, raw, search, or facet to denote the type of Server handle
	TopicURL         string   // URI prefix to redirect to topic pages
	Restricted       []string // list of restricts - extensions for raw, topics for markdown
}

// GetConfig safely returns the config file
func GetConfig() *GlobalSection {
	configLock.RLock()
	defer configLock.RUnlock()
	return staticConfig
}

// LoadConfig reads in a config file, cleans it up, and sets it to the global
func LoadConfig(configFile string) error {
	// set a default file
	if configFile == "" {
		configFile = "config.json"
	}

	// have to read in the line into a byte[] array
	fileContents, err := ioutil.ReadFile(configFile)
	if err != nil {
		return &Error{Code: ErrReadConfig, innerError: err, value: configFile}
	}

	// UnMarshal the config file that was read in
	temp := new(GlobalSection)

	err = json.Unmarshal(fileContents, temp)
	//Make sure you were able to read it in
	if err != nil {
		return &Error{Code: ErrParseConfig, value: temp, innerError: err}
	}

	CleanConfig(temp)

	configLock.Lock()
	staticConfig = temp
	configLock.Unlock()

	return nil
}

// CleanConfig takes a given config struct, and makes sure values are valid
func CleanConfig(config *GlobalSection) {
	config.TemplateDir = filepath.Clean(config.TemplateDir)
	for r := range config.Redirects {
		config.Redirects[r].Requested = path.Clean(config.Redirects[r].Requested)
		config.Redirects[r].Target = path.Clean(config.Redirects[r].Target)
		if config.Redirects[r].Code == 0 {
			config.Redirects[r].Code = 301
		}
	}

	for _, indexSection := range config.Indexes {
		for origDirPath, origWebPath := range indexSection.WatchDirs {
			delete(indexSection.WatchDirs, origDirPath)
			indexSection.WatchDirs[filepath.Clean(origDirPath)] = path.Clean(origWebPath)
		}

		for i := range indexSection.Handlers {
			indexSection.Handlers[i].Path = filepath.Clean(indexSection.Handlers[i].Path)
			indexSection.Handlers[i].Default = path.Clean(indexSection.Handlers[i].Default)
			indexSection.Handlers[i].TopicURL = path.Clean(indexSection.Handlers[i].TopicURL)
			indexSection.Handlers[i].Prefix = path.Clean(indexSection.Handlers[i].Prefix)
			if !strings.HasSuffix(indexSection.Handlers[i].Prefix, "/") {
				indexSection.Handlers[i].Prefix += "/"
			}
		}
	}
}

// RenderTemplate runs a given template as you would expect - it needs:
// * a http.ResponseWrtier for output
// * a template to render
// * a chunk of data
func RenderTemplate(responsePipe http.ResponseWriter, templateName string,
	data interface{}) error {
	templateLock.RLock()
	defer templateLock.RUnlock()

	return allTemplates.ExecuteTemplate(responsePipe, templateName, data)
}

// ParseTemplates parses all templates in a folder into one global template
func ParseTemplates(globalConfig GlobalSection) error {
	newTemplate, err := template.ParseGlob(globalConfig.TemplateDir + "*")
	if err != nil {
		return &Error{Code: ErrParseTemplates, innerError: err}
	}

	templateLock.Lock()
	defer templateLock.Unlock()
	allTemplates = newTemplate
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"os"

	"code.google.com/p/gcfg"
)

// Configuration is Ourd's configuration
type Configuration struct {
	HTTP struct {
		Host string
	}
	App struct {
		Name   string
		APIKey string `gcfg:"api-key"`
	}
	DB struct {
		ImplName string `gcfg:"implementation"`
		Option   string
	}
	TokenStore struct {
		Path string `gcfg:"path"`
	} `gcfg:"token-store"`
	Subscription struct {
		Enabled bool
	}
	APNS struct {
		Env      string
		Cert     string
		Key      string
		CertPath string `gcfg:"cert-path"`
		KeyPath  string `gcfg:"key-path"`
	}
	LOG struct {
		Level string
	}
}

// ReadFileInto reads a configuration from file specified by path
func ReadFileInto(config *Configuration, path string) error {
	if err := gcfg.ReadFileInto(config, path); err != nil {
		return err
	}
	if config.HTTP.Host == "" {
		port := os.Getenv("PORT")
		if port == "" {
			port = "3000"
		}
		config.HTTP.Host = ":" + port
	}

	appAPIKey := os.Getenv("API_KEY")
	if appAPIKey != "" {
		config.App.APIKey = appAPIKey
	}

	dbImplName := os.Getenv("DB_IMPL_NAME")
	if dbImplName != "" {
		config.DB.ImplName = dbImplName
	}

	if config.DB.ImplName == "pq" && os.Getenv("DATABASE_URL") != "" {
		config.DB.Option = os.Getenv("DATABASE_URL")
	}

	shouldEnableSubscription := os.Getenv("ENABLE_SUBSCRIPTION")
	if shouldEnableSubscription != "" {
		config.Subscription.Enabled = shouldEnableSubscription == "1"
	}

	cert, key := os.Getenv("APNS_CERTIFICATE"), os.Getenv("APNS_PRIVATE_KEY")
	if cert != "" {
		config.APNS.Cert = cert
	}
	if key != "" {
		config.APNS.Key = key
	}

	if config.APNS.Cert == "" && config.APNS.CertPath != "" {
		certPEMBlock, err := ioutil.ReadFile(config.APNS.CertPath)
		if err != nil {
			return err
		}
		config.APNS.Cert = string(certPEMBlock)
	}

	if config.APNS.Key == "" && config.APNS.KeyPath != "" {
		keyPEMBlock, err := ioutil.ReadFile(config.APNS.KeyPath)
		if err != nil {
			return err
		}
		config.APNS.Key = string(keyPEMBlock)
	}

	return nil
}
<commit_msg>Read config apns.env from envvar<commit_after>package main

import (
	"io/ioutil"
	"os"

	"code.google.com/p/gcfg"
)

// Configuration is Ourd's configuration
type Configuration struct {
	HTTP struct {
		Host string
	}
	App struct {
		Name   string
		APIKey string `gcfg:"api-key"`
	}
	DB struct {
		ImplName string `gcfg:"implementation"`
		Option   string
	}
	TokenStore struct {
		Path string `gcfg:"path"`
	} `gcfg:"token-store"`
	Subscription struct {
		Enabled bool
	}
	APNS struct {
		Env      string
		Cert     string
		Key      string
		CertPath string `gcfg:"cert-path"`
		KeyPath  string `gcfg:"key-path"`
	}
	LOG struct {
		Level string
	}
}

// ReadFileInto reads a configuration from file specified by path
func ReadFileInto(config *Configuration, path string) error {
	if err := gcfg.ReadFileInto(config, path); err != nil {
		return err
	}
	if config.HTTP.Host == "" {
		port := os.Getenv("PORT")
		if port == "" {
			port = "3000"
		}
		config.HTTP.Host = ":" + port
	}

	appAPIKey := os.Getenv("API_KEY")
	if appAPIKey != "" {
		config.App.APIKey = appAPIKey
	}

	dbImplName := os.Getenv("DB_IMPL_NAME")
	if dbImplName != "" {
		config.DB.ImplName = dbImplName
	}

	if config.DB.ImplName == "pq" && os.Getenv("DATABASE_URL") != "" {
		config.DB.Option = os.Getenv("DATABASE_URL")
	}

	shouldEnableSubscription := os.Getenv("ENABLE_SUBSCRIPTION")
	if shouldEnableSubscription != "" {
		config.Subscription.Enabled = shouldEnableSubscription == "1"
	}

	env := os.Getenv("APNS_ENV")
	if env != "" {
		config.APNS.Env = env
	}

	cert, key := os.Getenv("APNS_CERTIFICATE"), os.Getenv("APNS_PRIVATE_KEY")
	if cert != "" {
		config.APNS.Cert = cert
	}
	if key != "" {
		config.APNS.Key = key
	}

	if config.APNS.Cert == "" && config.APNS.CertPath != "" {
		certPEMBlock, err := ioutil.ReadFile(config.APNS.CertPath)
		if err != nil {
			return err
		}
		config.APNS.Cert = string(certPEMBlock)
	}

	if config.APNS.Key == "" && config.APNS.KeyPath != "" {
		keyPEMBlock, err := ioutil.ReadFile(config.APNS.KeyPath)
		if err != nil {
			return err
		}
		config.APNS.Key = string(keyPEMBlock)
	}

	return nil
}
<|endoftext|>


<commit_before>package lazycache

import (
	"fmt"
	flag "github.com/spf13/pflag"
	"github.com/spf13/viper"
	"strings"
)

func ViperConfiguration() {

	// Configuration
	viper.SetDefault("port", 8080)
	viper.SetDefault("bind", "0.0.0.0")
	viper.SetDefault("imagestore", "")
	viper.SetDefault("imagestore.bucket", "camhd-image-cache")

	viper.SetDefault("quicktimestore", "")
	viper.SetDefault("directorystore", "")

	viper.SetConfigName("lazycache")
	viper.AddConfigPath("/etc/lazycache")
	viper.AddConfigPath(".")
	err := viper.ReadInConfig() // Find and read the config file
	if err != nil {             // Handle errors reading the config file
		switch err.(type) {
		case viper.ConfigFileNotFoundError:
			// ignore
		default:
			panic(fmt.Errorf("Fatal error config file: %s \n", err))
		}
	}

	viper.SetEnvPrefix("lazycache")
	viper.AutomaticEnv()
	// Convert '.' to '_' in configuration variable names
	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

	// var (
	// 	bindFlag          = flag.String("bind", "0.0.0.0", "Network interface to bind to (defaults to 0.0.0.0)")
	// 	ImageStoreFlag   = flag.String("image-store", "", "Type of image store (none, google)")
	// 	ImageBucketFlag = flag.String("image-store-bucket", "", "Bucket used for Google image store")
	// )
	flag.Int("port", 80, "Network port to listen on (default: 8080)")
	flag.String("bind", "0.0.0.0", "Network interface to bind to (defaults to 0.0.0.0)")

	flag.String("image-store", "", "Type of image store (none, local, google)")
	flag.String("image-store-bucket", "camhd-image-cache", "Bucket used for Google image store")
	flag.String("image-local-root", "", "Bucket used for Google image store")
	flag.String("image-url-root", "", "Bucket used for Google image store")

	flag.String("quicktime-store", "", "Type of quicktime store (none, redis)")
	flag.String("directory-store", "", "Type of directory store (none, redis)")
	flag.String("redis-host", "localhost:6379", "Host used for redis store")

	viper.BindPFlag("port", flag.Lookup("port"))
	viper.BindPFlag("bind", flag.Lookup("bind"))
	viper.BindPFlag("imagestore", flag.Lookup("image-store"))

	viper.BindPFlag("imagestore.bucket", flag.Lookup("image-store-bucket"))
	viper.BindPFlag("imagestore.localroot", flag.Lookup("image-local-root"))

	viper.BindPFlag("directorystore", flag.Lookup("directory-store"))
	viper.BindPFlag("quicktimestore", flag.Lookup("quicktime-store"))
	viper.BindPFlag("redishost", flag.Lookup("redis-host"))

	flag.Parse()
}

func ConfigureImageStoreFromViper() {
	switch strings.ToLower(viper.GetString("imagestore")) {
	default:
		DefaultLogger.Log("msg", "Unable to determine type of image store from \"%s\"", viper.GetString("imagestore"))
		DefaultImageStore = NullImageStore{}
	case "", "none":
		DefaultLogger.Log("msg", "No image store configured.")
		DefaultImageStore = NullImageStore{}
	case "local":
		DefaultImageStore = CreateLocalStore(viper.GetString("imagestore.localRoot"),
			viper.GetString("imagestore.bind"))
	case "google":
		DefaultImageStore = CreateGoogleStore(viper.GetString("imagestore.bucket"))
	}
}

func ConfigureQuicktimeStoreFromViper() {

	switch strings.ToLower(viper.GetString("quicktimestore")) {
	default:
		DefaultLogger.Log("msg", "Unable to determine type of image store from \"%s\"", viper.GetString("quicktimestore"))
		QTMetadataStore = CreateMapJSONStore()
	case "", "none":
		DefaultLogger.Log("msg", "Using default QuicktimeStore.")
		QTMetadataStore = CreateMapJSONStore()
	case "redis":
		hostname := viper.GetString("redishost")
		redis, err := CreateRedisJSONStore(hostname, "qt")
		if err != nil {
			DefaultLogger.Log("msg", fmt.Sprintf("Failed to configure Redis Quicktime store to host \"%s\"", hostname))
		}

		DefaultLogger.Log("msg", fmt.Sprintf("Logging movie metadata to Redis at %s", hostname))
		QTMetadataStore = redis
	}
}

func ConfigureDirectoryStoreFromViper() {

	switch strings.ToLower(viper.GetString("directorystore")) {
	default:
		DefaultLogger.Log("msg", "Unable to determine type of directory store from \"%s\"", viper.GetString("directorystore"))
		DirKeyStore = CreateMapJSONStore()
	case "", "none":
		DefaultLogger.Log("msg", "Using default directory store.")
		DirKeyStore = CreateMapJSONStore()
	case "redis":
		hostname := viper.GetString("redishost")
		redis, err := CreateRedisJSONStore(hostname, "dir")
		if err != nil {
			DefaultLogger.Log("msg", fmt.Sprintf("Failed to configure Redis directory store to host \"%s\"", hostname))
		}

		DefaultLogger.Log("msg", fmt.Sprintf("Logging directory metadata to Redis at %s", hostname))
		DirKeyStore = redis
	}
}

func ConfigureFromViper() {
	ConfigureImageStoreFromViper()
	ConfigureDirectoryStoreFromViper()
	ConfigureQuicktimeStoreFromViper()
}
<commit_msg>Added more debugging output when configurating map stores.<commit_after>package lazycache

import (
	"fmt"
	flag "github.com/spf13/pflag"
	"github.com/spf13/viper"
	"strings"
)

func ViperConfiguration() {

	// Configuration
	viper.SetDefault("port", 8080)
	viper.SetDefault("bind", "0.0.0.0")
	viper.SetDefault("imagestore", "")
	viper.SetDefault("imagestore.bucket", "camhd-image-cache")

	viper.SetDefault("quicktimestore", "")
	viper.SetDefault("directorystore", "")

	viper.SetConfigName("lazycache")
	viper.AddConfigPath("/etc/lazycache")
	viper.AddConfigPath(".")
	err := viper.ReadInConfig() // Find and read the config file
	if err != nil {             // Handle errors reading the config file
		switch err.(type) {
		case viper.ConfigFileNotFoundError:
			// ignore
		default:
			panic(fmt.Errorf("Fatal error config file: %s \n", err))
		}
	}

	viper.SetEnvPrefix("lazycache")
	viper.AutomaticEnv()
	// Convert '.' to '_' in configuration variable names
	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

	// var (
	// 	bindFlag          = flag.String("bind", "0.0.0.0", "Network interface to bind to (defaults to 0.0.0.0)")
	// 	ImageStoreFlag   = flag.String("image-store", "", "Type of image store (none, google)")
	// 	ImageBucketFlag = flag.String("image-store-bucket", "", "Bucket used for Google image store")
	// )
	flag.Int("port", 80, "Network port to listen on (default: 8080)")
	flag.String("bind", "0.0.0.0", "Network interface to bind to (defaults to 0.0.0.0)")

	flag.String("image-store", "", "Type of image store (none, local, google)")
	flag.String("image-store-bucket", "camhd-image-cache", "Bucket used for Google image store")
	flag.String("image-local-root", "", "Bucket used for Google image store")
	flag.String("image-url-root", "", "Bucket used for Google image store")

	flag.String("quicktime-store", "", "Type of quicktime store (none, redis)")
	flag.String("directory-store", "", "Type of directory store (none, redis)")
	flag.String("redis-host", "localhost:6379", "Host used for redis store")

	viper.BindPFlag("port", flag.Lookup("port"))
	viper.BindPFlag("bind", flag.Lookup("bind"))
	viper.BindPFlag("imagestore", flag.Lookup("image-store"))

	viper.BindPFlag("imagestore.bucket", flag.Lookup("image-store-bucket"))
	viper.BindPFlag("imagestore.localroot", flag.Lookup("image-local-root"))

	viper.BindPFlag("directorystore", flag.Lookup("directory-store"))
	viper.BindPFlag("quicktimestore", flag.Lookup("quicktime-store"))
	viper.BindPFlag("redishost", flag.Lookup("redis-host"))

	flag.Parse()
}

func ConfigureImageStoreFromViper() {
	storeKey := viper.GetString("imagestore")
	DefaultLogger.Log("msg", fmt.Sprintf("Configuring image store with type \"%s\"", storeKey))
	switch strings.ToLower(storeKey) {
	default:
		DefaultLogger.Log("msg", fmt.Sprintf("Unable to determine type of image store from \"%s\"", storeKey))
		DefaultImageStore = NullImageStore{}
	case "", "none":
		DefaultLogger.Log("msg", "No image store configured.")
		DefaultImageStore = NullImageStore{}
	case "local":
		DefaultImageStore = CreateLocalStore(viper.GetString("imagestore.localRoot"),
			viper.GetString("imagestore.bind"))
	case "google":
		DefaultImageStore = CreateGoogleStore(viper.GetString("imagestore.bucket"))
	}
}

func ConfigureQuicktimeStoreFromViper() {
	storeKey := viper.GetString("quicktimestore")
	DefaultLogger.Log("msg", fmt.Sprintf("Configuring quicktime store with type \"%s\"", storeKey))

	switch strings.ToLower(storeKey) {
	default:
		DefaultLogger.Log("msg", fmt.Sprintf("Unable to determine type of image store from \"%s\"", storeKey))
		QTMetadataStore = CreateMapJSONStore()
	case "", "none":
		DefaultLogger.Log("msg", "Using default QuicktimeStore.")
		QTMetadataStore = CreateMapJSONStore()
	case "redis":
		hostname := viper.GetString("redishost")
		DefaultLogger.Log("msg", fmt.Sprintf("Connecting to redis host \"%s\"", hostname))
		redis, err := CreateRedisJSONStore(hostname, "qt")
		if err != nil {
			DefaultLogger.Log("msg", fmt.Sprintf("Failed to configure Redis Quicktime store to host \"%s\"", hostname))
		}

		DefaultLogger.Log("msg", fmt.Sprintf("Logging movie metadata to Redis at %s", hostname))
		QTMetadataStore = redis
	}
}

func ConfigureDirectoryStoreFromViper() {
	storeKey := viper.GetString("directorystore")
	DefaultLogger.Log("msg", fmt.Sprintf("Configuring directory store with type \"%s\"", storeKey))

	switch strings.ToLower(storeKey) {
	default:
		DefaultLogger.Log("msg", fmt.Sprintf("Unable to determine type of directory store from \"%s\"", storeKey))
		DirKeyStore = CreateMapJSONStore()
	case "", "none":
		DefaultLogger.Log("msg", "Using default directory store.")
		DirKeyStore = CreateMapJSONStore()
	case "redis":
		hostname := viper.GetString("redishost")
		DefaultLogger.Log("msg", fmt.Sprintf("Connecting to redis host \"%s\"", hostname))
		redis, err := CreateRedisJSONStore(hostname, "dir")
		if err != nil {
			DefaultLogger.Log("msg", fmt.Sprintf("Failed to configure Redis directory store to host \"%s\"", hostname))
		}

		DefaultLogger.Log("msg", fmt.Sprintf("Logging directory metadata to Redis at %s", hostname))
		DirKeyStore = redis
	}
}

func ConfigureFromViper() {
	ConfigureImageStoreFromViper()
	ConfigureDirectoryStoreFromViper()
	ConfigureQuicktimeStoreFromViper()
}
<|endoftext|>