<commit_before>package service

import (
	"bufio"
	"io"
	"time"

	"github.com/syou6162/go-active-learning/lib/cache"
	"github.com/syou6162/go-active-learning/lib/model"
	"github.com/syou6162/go-active-learning/lib/repository"
)

type GoActiveLearningApp interface {
	InsertOrUpdateExample(e *model.Example) error
	InsertExampleFromScanner(scanner *bufio.Scanner) (*model.Example, error)
	InsertExamplesFromReader(reader io.Reader) error
	ReadExamples() (model.Examples, error)
	ReadRecentExamples(from time.Time) (model.Examples, error)
	ReadExamplesByLabel(label model.LabelType, limit int) (model.Examples, error)
	ReadLabeledExamples(limit int) (model.Examples, error)
	ReadPositiveExamples(limit int) (model.Examples, error)
	ReadNegativeExamples(limit int) (model.Examples, error)
	ReadUnlabeledExamples(limit int) (model.Examples, error)
	SearchExamplesByUlr(url string) (*model.Example, error)
	SearchExamplesByUlrs(urls []string) (model.Examples, error)
	DeleteAllExamples() error
	Ping() error
	Close() error
}

func NewApp(repo repository.Repository, c cache.Cache) GoActiveLearningApp {
	return &goActiveLearningApp{repo: repo, cache: c}
}

type goActiveLearningApp struct {
	repo  repository.Repository
	cache cache.Cache
}

func (app *goActiveLearningApp) Ping() error {
	return app.repo.Ping()
}

func (app *goActiveLearningApp) Close() error {
	return app.repo.Close()
}
<commit_msg>pingとcloseでcacheも考慮する<commit_after>package service

import (
	"bufio"
	"io"
	"time"

	"github.com/syou6162/go-active-learning/lib/cache"
	"github.com/syou6162/go-active-learning/lib/model"
	"github.com/syou6162/go-active-learning/lib/repository"
)

type GoActiveLearningApp interface {
	InsertOrUpdateExample(e *model.Example) error
	InsertExampleFromScanner(scanner *bufio.Scanner) (*model.Example, error)
	InsertExamplesFromReader(reader io.Reader) error
	ReadExamples() (model.Examples, error)
	ReadRecentExamples(from time.Time) (model.Examples, error)
	ReadExamplesByLabel(label model.LabelType, limit int) (model.Examples, error)
	ReadLabeledExamples(limit int) (model.Examples, error)
	ReadPositiveExamples(limit int) (model.Examples, error)
	ReadNegativeExamples(limit int) (model.Examples, error)
	ReadUnlabeledExamples(limit int) (model.Examples, error)
	SearchExamplesByUlr(url string) (*model.Example, error)
	SearchExamplesByUlrs(urls []string) (model.Examples, error)
	DeleteAllExamples() error
	Ping() error
	Close() error
}

func NewApp(repo repository.Repository, c cache.Cache) GoActiveLearningApp {
	return &goActiveLearningApp{repo: repo, cache: c}
}

type goActiveLearningApp struct {
	repo  repository.Repository
	cache cache.Cache
}

func (app *goActiveLearningApp) Ping() error {
	if err := app.repo.Ping(); err != nil {
		return err
	}
	if err := app.cache.Ping(); err != nil {
		return err
	}
	return nil
}

func (app *goActiveLearningApp) Close() error {
	if err := app.repo.Close(); err != nil {
		return err
	}
	if err := app.cache.Close(); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

package tlsutil

import (
	"bufio"
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"io"
	"math/big"
	mr "math/rand"
	"net"
	"os"
	"time"
)

var (
	ErrIdentificationFailed = fmt.Errorf("failed to identify socket type")
)

func NewCertificate(certFile, keyFile, tlsDefaultCommonName string, tlsRSABits int) (tls.Certificate, error) {
	priv, err := rsa.GenerateKey(rand.Reader, tlsRSABits)
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("generate key: %s", err)
	}

	notBefore := time.Now()
	notAfter := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC)

	template := x509.Certificate{
		SerialNumber: new(big.Int).SetInt64(mr.Int63()),
		Subject: pkix.Name{
			CommonName: tlsDefaultCommonName,
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
		BasicConstraintsValid: true,
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("create cert: %s", err)
	}

	certOut, err := os.Create(certFile)
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("save cert: %s", err)
	}
	err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("save cert: %s", err)
	}
	err = certOut.Close()
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("save cert: %s", err)
	}

	keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("save key: %s", err)
	}
	err = pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("save key: %s", err)
	}
	err = keyOut.Close()
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("save key: %s", err)
	}

	return tls.LoadX509KeyPair(certFile, keyFile)
}

type DowngradingListener struct {
	net.Listener
	TLSConfig *tls.Config
}

func (l *DowngradingListener) Accept() (net.Conn, error) {
	conn, isTLS, err := l.AcceptNoWrap()

	// We failed to identify the socket type, pretend that everything is fine,
	// and pass it to the underlying handler, and let them deal with it.
	if err == ErrIdentificationFailed {
		return conn, nil
	}

	if err != nil {
		return conn, err
	}

	if isTLS {
		return tls.Server(conn, l.TLSConfig), nil
	}
	return conn, nil
}

func (l *DowngradingListener) AcceptNoWrap() (net.Conn, bool, error) {
	conn, err := l.Listener.Accept()
	if err != nil {
		return nil, false, err
	}

	br := bufio.NewReader(conn)
	conn.SetReadDeadline(time.Now().Add(1 * time.Second))
	bs, err := br.Peek(1)
	conn.SetReadDeadline(time.Time{})
	if err != nil {
		// We hit a read error here, but the Accept() call succeeded so we must not return an error.
		// We return the connection as is with a special error which handles this
		// special case in Accept().
		return conn, false, ErrIdentificationFailed
	}

	return &WrappedConnection{br, conn}, bs[0] == 0x16, nil
}

type WrappedConnection struct {
	io.Reader
	net.Conn
}

func (c *WrappedConnection) Read(b []byte) (n int, err error) {
	return c.Reader.Read(b)
}
<commit_msg>Clarify names<commit_after>// Copyright (C) 2014 The Syncthing Authors.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

package tlsutil

import (
	"bufio"
	"crypto/rand"
	"crypto/rsa"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"fmt"
	"io"
	"math/big"
	mr "math/rand"
	"net"
	"os"
	"time"
)

var (
	ErrIdentificationFailed = fmt.Errorf("failed to identify socket type")
)

func NewCertificate(certFile, keyFile, tlsDefaultCommonName string, tlsRSABits int) (tls.Certificate, error) {
	priv, err := rsa.GenerateKey(rand.Reader, tlsRSABits)
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("generate key: %s", err)
	}

	notBefore := time.Now()
	notAfter := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC)

	template := x509.Certificate{
		SerialNumber: new(big.Int).SetInt64(mr.Int63()),
		Subject: pkix.Name{
			CommonName: tlsDefaultCommonName,
		},
		NotBefore: notBefore,
		NotAfter:  notAfter,

		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
		BasicConstraintsValid: true,
	}

	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("create cert: %s", err)
	}

	certOut, err := os.Create(certFile)
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("save cert: %s", err)
	}
	err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("save cert: %s", err)
	}
	err = certOut.Close()
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("save cert: %s", err)
	}

	keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("save key: %s", err)
	}
	err = pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("save key: %s", err)
	}
	err = keyOut.Close()
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("save key: %s", err)
	}

	return tls.LoadX509KeyPair(certFile, keyFile)
}

type DowngradingListener struct {
	net.Listener
	TLSConfig *tls.Config
}

func (l *DowngradingListener) Accept() (net.Conn, error) {
	conn, isTLS, err := l.AcceptNoWrapTLS()

	// We failed to identify the socket type, pretend that everything is fine,
	// and pass it to the underlying handler, and let them deal with it.
	if err == ErrIdentificationFailed {
		return conn, nil
	}

	if err != nil {
		return conn, err
	}

	if isTLS {
		return tls.Server(conn, l.TLSConfig), nil
	}
	return conn, nil
}

func (l *DowngradingListener) AcceptNoWrapTLS() (net.Conn, bool, error) {
	conn, err := l.Listener.Accept()
	if err != nil {
		return nil, false, err
	}

	br := bufio.NewReader(conn)
	conn.SetReadDeadline(time.Now().Add(1 * time.Second))
	bs, err := br.Peek(1)
	conn.SetReadDeadline(time.Time{})
	if err != nil {
		// We hit a read error here, but the Accept() call succeeded so we must not return an error.
		// We return the connection as is with a special error which handles this
		// special case in Accept().
		return conn, false, ErrIdentificationFailed
	}

	return &UnionedConnection{br, conn}, bs[0] == 0x16, nil
}

type UnionedConnection struct {
	io.Reader
	net.Conn
}

func (c *UnionedConnection) Read(b []byte) (n int, err error) {
	return c.Reader.Read(b)
}
<|endoftext|>


<commit_before>// Package libdocker provides docker related library functions.
package libdocker

import (
	dockerclient "github.com/fsouza/go-dockerclient"
	"github.com/resourced/resourced/libstring"
	"os"
	"path"
	"strconv"
	"sync"
)

var connections map[string]*dockerclient.Client

type CompleteDockerContainer struct {
	NiceImageName string `json:"NiceImageName,omitempty" yaml:"NiceImageName,omitempty"`
	Command       string `json:"Command,omitempty" yaml:"Command,omitempty"`
	Status        string `json:"Status,omitempty" yaml:"Status,omitempty"`
	dockerclient.Container
}

type CompleteDockerImage struct {
	RepoTags    []string `json:"RepoTags,omitempty" yaml:"RepoTags,omitempty"`
	VirtualSize int64    `json:"VirtualSize,omitempty" yaml:"VirtualSize,omitempty"`
	ParentID    string   `json:"ParentId,omitempty" yaml:"ParentId,omitempty"`
	dockerclient.Image
}

// DockerClient returns dockerclient.Client which handles Docker connection.
func DockerClient(endpoint string) (*dockerclient.Client, error) {
	var conn *dockerclient.Client
	var err error

	if endpoint == "" {
		endpoint = os.Getenv("DOCKER_HOST")
		if endpoint == "" {
			endpoint = "unix:///var/run/docker.sock"
		}
	}

	if connections == nil {
		connections = make(map[string]*dockerclient.Client)
	}

	// Do not create connection if one already exist.
	if existingConnection, ok := connections[endpoint]; ok && existingConnection != nil {
		return existingConnection, nil
	}

	dockerCertPath := os.Getenv("DOCKER_CERT_PATH")
	if dockerCertPath != "" {
		cert := path.Join(dockerCertPath, "cert.pem")
		key := path.Join(dockerCertPath, "key.pem")
		ca := path.Join(dockerCertPath, "ca.pem")

		conn, err = dockerclient.NewTLSClient(endpoint, cert, key, ca)
	} else {
		conn, err = dockerclient.NewClient(endpoint)
	}

	if err == nil && conn != nil {
		connections[endpoint] = conn
	}

	return conn, err
}

// InfoAndVersion is a convenience function to fetch info and version data.
func InfoAndVersion(endpoint string) (map[string]interface{}, error) {
	client, err := DockerClient(endpoint)
	if err != nil {
		return nil, err
	}

	version, err := client.Version()
	if err != nil {
		return nil, err
	}

	info, err := client.Info()
	if err != nil {
		return nil, err
	}

	versionAsMap := version.Map()
	infoAsMap := info.Map()

	data := make(map[string]interface{})

	for key, value := range versionAsMap {
		data[key] = value
	}

	data["Driver"] = make(map[string]interface{})

	for key, value := range infoAsMap {
		if libstring.StringInSlice(key, []string{"NGoroutines", "Containers", "Images", "MemTotal"}) {
			data[key] = info.GetInt64(key)

		} else if key == "NFd" {
			data["NumFileDescriptors"] = info.GetInt64(key)

		} else if key == "NEventsListener" {
			data["NumEventsListeners"] = info.GetInt64(key)

		} else if key == "NCPU" {
			data["NumCPUs"] = info.GetInt64(key)

		} else if libstring.StringInSlice(key, []string{"Debug", "IPv4Forwarding", "MemoryLimit", "SwapLimit"}) {
			data[key] = info.GetBool(key)

		} else if key == "Driver" {
			driverMap := data["Driver"].(map[string]interface{})
			driverMap["Name"] = value

		} else if key == "DriverStatus" {
			tupleSlice := make([][]string, 2)
			info.GetJSON(key, &tupleSlice)

			for _, tuple := range tupleSlice {
				tupleKey := tuple[0]
				tupleValue := tuple[1]

				driverMap := data["Driver"].(map[string]interface{})

				if tupleKey == "Root Dir" {
					driverMap["RootDir"] = tupleValue
				}
				if tupleKey == "Dirs" {
					tupleValueInt64, err := strconv.ParseInt(tupleValue, 10, 64)
					if err == nil {
						driverMap[tupleKey] = tupleValueInt64
					}
				}
			}
		} else {
			data[key] = value
		}
	}

	return data, nil
}

// AllContainers is a convenience function to fetch a slice of all containers data.
func AllContainers(endpoint string) ([]dockerclient.APIContainers, error) {
	client, err := DockerClient(endpoint)
	if err != nil {
		return nil, err
	}

	return client.ListContainers(dockerclient.ListContainersOptions{})
}

// AllInspectedContainers is a convenience function to fetch a slice of all inspected containers data.
func AllInspectedContainers(endpoint string) ([]*CompleteDockerContainer, error) {
	client, err := DockerClient(endpoint)
	if err != nil {
		return nil, err
	}

	shortDescContainers, err := client.ListContainers(dockerclient.ListContainersOptions{})
	if err != nil {
		return nil, err
	}

	containersChan := make(chan *CompleteDockerContainer)
	var wg sync.WaitGroup

	for _, shortDescContainer := range shortDescContainers {
		container := &CompleteDockerContainer{}
		container.NiceImageName = shortDescContainer.Image
		container.Command = shortDescContainer.Command
		container.Status = shortDescContainer.Status

		wg.Add(1)

		go func(container *CompleteDockerContainer) {
			defer wg.Done()

			fullDescContainer, err := client.InspectContainer(shortDescContainer.ID)
			if err == nil && fullDescContainer != nil {
				container.ID = fullDescContainer.ID
				container.Created = fullDescContainer.Created
				container.Path = fullDescContainer.Path
				container.Args = fullDescContainer.Args
				container.Config = fullDescContainer.Config
				container.State = fullDescContainer.State
				container.Image = fullDescContainer.Image
				container.NetworkSettings = fullDescContainer.NetworkSettings
				container.SysInitPath = fullDescContainer.SysInitPath
				container.ResolvConfPath = fullDescContainer.ResolvConfPath
				container.HostnamePath = fullDescContainer.HostnamePath
				container.HostsPath = fullDescContainer.HostsPath
				container.Name = fullDescContainer.Name
				container.Driver = fullDescContainer.Driver
				container.Volumes = fullDescContainer.Volumes
				container.VolumesRW = fullDescContainer.VolumesRW
				container.HostConfig = fullDescContainer.HostConfig

				containersChan <- container
			}
		}(container)
	}

	containers := make([]*CompleteDockerContainer, 0)

	go func() {
		for container := range containersChan {
			containers = append(containers, container)
		}
	}()

	wg.Wait()
	close(containersChan)

	return containers, nil
}

// AllImages is a convenience function to fetch a slice of all images data.
func AllImages(endpoint string) ([]dockerclient.APIImages, error) {
	client, err := DockerClient(endpoint)
	if err != nil {
		return nil, err
	}

	return client.ListImages(dockerclient.ListImagesOptions{})
}

// AllInspectedImages is a convenience function to fetch a slice of all inspected images data.
func AllInspectedImages(endpoint string) ([]*CompleteDockerImage, error) {
	client, err := DockerClient(endpoint)
	if err != nil {
		return nil, err
	}

	shortDescImages, err := client.ListImages(dockerclient.ListImagesOptions{})
	if err != nil {
		return nil, err
	}

	imagesChan := make(chan *CompleteDockerImage)
	var wg sync.WaitGroup

	for _, shortDescImage := range shortDescImages {
		img := &CompleteDockerImage{}
		img.ID = shortDescImage.ID
		img.RepoTags = shortDescImage.RepoTags
		img.VirtualSize = shortDescImage.VirtualSize
		img.ParentID = shortDescImage.ParentID

		wg.Add(1)

		go func(img *CompleteDockerImage) {
			defer wg.Done()

			fullDescImage, err := client.InspectImage(img.ID)
			if err == nil && fullDescImage != nil {
				img.Parent = fullDescImage.Parent
				img.Comment = fullDescImage.Comment
				img.Created = fullDescImage.Created
				img.Container = fullDescImage.Container
				img.ContainerConfig = fullDescImage.ContainerConfig
				img.DockerVersion = fullDescImage.DockerVersion
				img.Author = fullDescImage.Author
				img.Config = fullDescImage.Config
				img.Architecture = fullDescImage.Architecture
				img.Size = fullDescImage.Size

				imagesChan <- img
			}
		}(img)
	}

	images := make([]*CompleteDockerImage, 0)

	go func() {
		for image := range imagesChan {
			images = append(images, image)
		}
	}()

	wg.Wait()
	close(imagesChan)

	return images, nil
}
<commit_msg>docker RegistryConfig should return as json data.<commit_after>// Package libdocker provides docker related library functions.
package libdocker

import (
	dockerclient "github.com/fsouza/go-dockerclient"
	"github.com/resourced/resourced/libstring"
	"os"
	"path"
	"strconv"
	"sync"
)

var connections map[string]*dockerclient.Client

type CompleteDockerContainer struct {
	NiceImageName string `json:"NiceImageName,omitempty" yaml:"NiceImageName,omitempty"`
	Command       string `json:"Command,omitempty" yaml:"Command,omitempty"`
	Status        string `json:"Status,omitempty" yaml:"Status,omitempty"`
	dockerclient.Container
}

type CompleteDockerImage struct {
	RepoTags    []string `json:"RepoTags,omitempty" yaml:"RepoTags,omitempty"`
	VirtualSize int64    `json:"VirtualSize,omitempty" yaml:"VirtualSize,omitempty"`
	ParentID    string   `json:"ParentId,omitempty" yaml:"ParentId,omitempty"`
	dockerclient.Image
}

// DockerClient returns dockerclient.Client which handles Docker connection.
func DockerClient(endpoint string) (*dockerclient.Client, error) {
	var conn *dockerclient.Client
	var err error

	if endpoint == "" {
		endpoint = os.Getenv("DOCKER_HOST")
		if endpoint == "" {
			endpoint = "unix:///var/run/docker.sock"
		}
	}

	if connections == nil {
		connections = make(map[string]*dockerclient.Client)
	}

	// Do not create connection if one already exist.
	if existingConnection, ok := connections[endpoint]; ok && existingConnection != nil {
		return existingConnection, nil
	}

	dockerCertPath := os.Getenv("DOCKER_CERT_PATH")
	if dockerCertPath != "" {
		cert := path.Join(dockerCertPath, "cert.pem")
		key := path.Join(dockerCertPath, "key.pem")
		ca := path.Join(dockerCertPath, "ca.pem")

		conn, err = dockerclient.NewTLSClient(endpoint, cert, key, ca)
	} else {
		conn, err = dockerclient.NewClient(endpoint)
	}

	if err == nil && conn != nil {
		connections[endpoint] = conn
	}

	return conn, err
}

// InfoAndVersion is a convenience function to fetch info and version data.
func InfoAndVersion(endpoint string) (map[string]interface{}, error) {
	client, err := DockerClient(endpoint)
	if err != nil {
		return nil, err
	}

	version, err := client.Version()
	if err != nil {
		return nil, err
	}

	info, err := client.Info()
	if err != nil {
		return nil, err
	}

	versionAsMap := version.Map()
	infoAsMap := info.Map()

	data := make(map[string]interface{})

	for key, value := range versionAsMap {
		data[key] = value
	}

	data["Driver"] = make(map[string]interface{})

	for key, value := range infoAsMap {
		if libstring.StringInSlice(key, []string{"NGoroutines", "Containers", "Images", "MemTotal"}) {
			data[key] = info.GetInt64(key)

		} else if key == "NFd" {
			data["NumFileDescriptors"] = info.GetInt64(key)

		} else if key == "NEventsListener" {
			data["NumEventsListeners"] = info.GetInt64(key)

		} else if key == "NCPU" {
			data["NumCPUs"] = info.GetInt64(key)

		} else if libstring.StringInSlice(key, []string{"Debug", "IPv4Forwarding", "MemoryLimit", "SwapLimit"}) {
			data[key] = info.GetBool(key)

		} else if key == "Driver" {
			driverMap := data["Driver"].(map[string]interface{})
			driverMap["Name"] = value

		} else if key == "DriverStatus" {
			tupleSlice := make([][]string, 2)
			info.GetJSON(key, &tupleSlice)

			for _, tuple := range tupleSlice {
				tupleKey := tuple[0]
				tupleValue := tuple[1]

				driverMap := data["Driver"].(map[string]interface{})

				if tupleKey == "Root Dir" {
					driverMap["RootDir"] = tupleValue
				}
				if tupleKey == "Dirs" {
					tupleValueInt64, err := strconv.ParseInt(tupleValue, 10, 64)
					if err == nil {
						driverMap[tupleKey] = tupleValueInt64
					}
				}
			}

		} else if key == "RegistryConfig" {
			registryConfig := make(map[string]interface{})
			err := info.GetJSON(key, &registryConfig)
			if err == nil {
				data[key] = registryConfig
			}

		} else {
			data[key] = value
		}
	}

	return data, nil
}

// AllContainers is a convenience function to fetch a slice of all containers data.
func AllContainers(endpoint string) ([]dockerclient.APIContainers, error) {
	client, err := DockerClient(endpoint)
	if err != nil {
		return nil, err
	}

	return client.ListContainers(dockerclient.ListContainersOptions{})
}

// AllInspectedContainers is a convenience function to fetch a slice of all inspected containers data.
func AllInspectedContainers(endpoint string) ([]*CompleteDockerContainer, error) {
	client, err := DockerClient(endpoint)
	if err != nil {
		return nil, err
	}

	shortDescContainers, err := client.ListContainers(dockerclient.ListContainersOptions{})
	if err != nil {
		return nil, err
	}

	containersChan := make(chan *CompleteDockerContainer)
	var wg sync.WaitGroup

	for _, shortDescContainer := range shortDescContainers {
		container := &CompleteDockerContainer{}
		container.NiceImageName = shortDescContainer.Image
		container.Command = shortDescContainer.Command
		container.Status = shortDescContainer.Status

		wg.Add(1)

		go func(container *CompleteDockerContainer) {
			defer wg.Done()

			fullDescContainer, err := client.InspectContainer(shortDescContainer.ID)
			if err == nil && fullDescContainer != nil {
				container.ID = fullDescContainer.ID
				container.Created = fullDescContainer.Created
				container.Path = fullDescContainer.Path
				container.Args = fullDescContainer.Args
				container.Config = fullDescContainer.Config
				container.State = fullDescContainer.State
				container.Image = fullDescContainer.Image
				container.NetworkSettings = fullDescContainer.NetworkSettings
				container.SysInitPath = fullDescContainer.SysInitPath
				container.ResolvConfPath = fullDescContainer.ResolvConfPath
				container.HostnamePath = fullDescContainer.HostnamePath
				container.HostsPath = fullDescContainer.HostsPath
				container.Name = fullDescContainer.Name
				container.Driver = fullDescContainer.Driver
				container.Volumes = fullDescContainer.Volumes
				container.VolumesRW = fullDescContainer.VolumesRW
				container.HostConfig = fullDescContainer.HostConfig

				containersChan <- container
			}
		}(container)
	}

	containers := make([]*CompleteDockerContainer, 0)

	go func() {
		for container := range containersChan {
			containers = append(containers, container)
		}
	}()

	wg.Wait()
	close(containersChan)

	return containers, nil
}

// AllImages is a convenience function to fetch a slice of all images data.
func AllImages(endpoint string) ([]dockerclient.APIImages, error) {
	client, err := DockerClient(endpoint)
	if err != nil {
		return nil, err
	}

	return client.ListImages(dockerclient.ListImagesOptions{})
}

// AllInspectedImages is a convenience function to fetch a slice of all inspected images data.
func AllInspectedImages(endpoint string) ([]*CompleteDockerImage, error) {
	client, err := DockerClient(endpoint)
	if err != nil {
		return nil, err
	}

	shortDescImages, err := client.ListImages(dockerclient.ListImagesOptions{})
	if err != nil {
		return nil, err
	}

	imagesChan := make(chan *CompleteDockerImage)
	var wg sync.WaitGroup

	for _, shortDescImage := range shortDescImages {
		img := &CompleteDockerImage{}
		img.ID = shortDescImage.ID
		img.RepoTags = shortDescImage.RepoTags
		img.VirtualSize = shortDescImage.VirtualSize
		img.ParentID = shortDescImage.ParentID

		wg.Add(1)

		go func(img *CompleteDockerImage) {
			defer wg.Done()

			fullDescImage, err := client.InspectImage(img.ID)
			if err == nil && fullDescImage != nil {
				img.Parent = fullDescImage.Parent
				img.Comment = fullDescImage.Comment
				img.Created = fullDescImage.Created
				img.Container = fullDescImage.Container
				img.ContainerConfig = fullDescImage.ContainerConfig
				img.DockerVersion = fullDescImage.DockerVersion
				img.Author = fullDescImage.Author
				img.Config = fullDescImage.Config
				img.Architecture = fullDescImage.Architecture
				img.Size = fullDescImage.Size

				imagesChan <- img
			}
		}(img)
	}

	images := make([]*CompleteDockerImage, 0)

	go func() {
		for image := range imagesChan {
			images = append(images, image)
		}
	}()

	wg.Wait()
	close(imagesChan)

	return images, nil
}
<|endoftext|>


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

package math

// Ldexp is the inverse of Frexp.
// It returns frac × 2**exp.
//
// Special cases are:
//	Ldexp(±0, exp) = ±0
//	Ldexp(±Inf, exp) = ±Inf
//	Ldexp(NaN, exp) = NaN

//extern ldexp
func libc_ldexp(float64, int) float64

func Ldexp(frac float64, exp int) float64 {
	r := libc_ldexp(frac, exp)
	return r
}

func ldexp(frac float64, exp int) float64 {
	// special cases
	switch {
	case frac == 0:
		return frac // correctly return -0
	case IsInf(frac, 0) || IsNaN(frac):
		return frac
	}
	frac, e := normalize(frac)
	exp += e
	x := Float64bits(frac)
	exp += int(x>>shift)&mask - bias
	if exp < -1074 {
		return Copysign(0, frac) // underflow
	}
	if exp > 1023 { // overflow
		if frac < 0 {
			return Inf(-1)
		}
		return Inf(1)
	}
	var m float64 = 1
	if exp < -1022 { // denormal
		exp += 52
		m = 1.0 / (1 << 52) // 2**-52
	}
	x &^= mask << shift
	x |= uint64(exp+bias) << shift
	return m * Float64frombits(x)
}
<commit_msg>compiler: handle >32bit exponent in Ldexp<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package math

// Ldexp is the inverse of Frexp.
// It returns frac × 2**exp.
//
// Special cases are:
//	Ldexp(±0, exp) = ±0
//	Ldexp(±Inf, exp) = ±Inf
//	Ldexp(NaN, exp) = NaN

//extern ldexp
func libc_ldexp(float64, int32) float64

func Ldexp(frac float64, exp int) float64 {
	if exp > MaxInt32 {
		exp = MaxInt32
	} else if exp < MinInt32 {
		exp = MinInt32
	}
	r := libc_ldexp(frac, int32(exp))
	return r
}

func ldexp(frac float64, exp int) float64 {
	// special cases
	switch {
	case frac == 0:
		return frac // correctly return -0
	case IsInf(frac, 0) || IsNaN(frac):
		return frac
	}
	frac, e := normalize(frac)
	exp += e
	x := Float64bits(frac)
	exp += int(x>>shift)&mask - bias
	if exp < -1074 {
		return Copysign(0, frac) // underflow
	}
	if exp > 1023 { // overflow
		if frac < 0 {
			return Inf(-1)
		}
		return Inf(1)
	}
	var m float64 = 1
	if exp < -1022 { // denormal
		exp += 52
		m = 1.0 / (1 << 52) // 2**-52
	}
	x &^= mask << shift
	x |= uint64(exp+bias) << shift
	return m * Float64frombits(x)
}
<|endoftext|>


<commit_before>package libkb

import (
	"fmt"
	"github.com/keybase/go-triplesec"
)

type SignupEngine struct {
	pwsalt []byte
	tspkey TSPassKey
	uid    UID
}

func NewSignupEngine() *SignupEngine {
	return &SignupEngine{}
}

func (s *SignupEngine) Init() error {
	return nil
}

func (s *SignupEngine) CheckRegistered() (err error) {
	G.Log.Debug("+ libkb.SignupJoinEngine::CheckRegistered")
	if cr := G.Env.GetConfig(); cr == nil {
		err = fmt.Errorf("No configuration file available")
	} else if u := cr.GetUid(); u != nil {
		err = AlreadyRegisteredError{*u}
	}
	G.Log.Debug("- libkb.SignupJoinEngine::CheckRegistered -> %s", ErrToOk(err))
	return err
}

func (s *SignupEngine) PostInviteRequest(arg InviteRequestArg) error {
	return PostInviteRequest(arg)
}

type SignupEngineRunArg struct {
	Username   string
	Email      string
	InviteCode string
	Passphrase string
	DeviceName string
}

// XXX this might need to return more than error...passphraseok, postok, writeok.
func (s *SignupEngine) Run(arg SignupEngineRunArg) error {
	if err := s.genTSPassKey(arg.Passphrase); err != nil {
		return err
	}

	if err := s.join(arg.Username, arg.Email, arg.InviteCode); err != nil {
		return err
	}

	if err := s.registerDevice(arg.DeviceName); err != nil {
		fmt.Printf("register device error: %s\n", err)
		return err
	}

	if err := s.genDetKeys(); err != nil {
		return err
	}

	return nil
}

func (s *SignupEngine) genTSPassKey(passphrase string) error {
	salt, err := RandBytes(triplesec.SaltLen)
	if err != nil {
		return err
	}
	s.pwsalt = salt

	s.tspkey, err = NewTSPassKey(passphrase, salt)
	return err
}

// XXX might have to do more with the joinEngine result...for now, just returning
// error.
func (s *SignupEngine) join(username, email, inviteCode string) error {
	joinEngine := NewSignupJoinEngine()

	arg := SignupJoinEngineRunArg{
		Username:   username,
		Email:      email,
		InviteCode: inviteCode,
		PWHash:     s.tspkey.PWHash(),
		PWSalt:     s.pwsalt,
	}
	res := joinEngine.Run(arg)
	if res.Error != nil {
		return res.Error
	}
	s.uid = *res.Uid
	return nil
}

func (s *SignupEngine) registerDevice(deviceName string) error {
	eng := NewDeviceEngine()
	return eng.Run(deviceName)
}

func (s *SignupEngine) genDetKeys() error {
	return nil
}
<commit_msg>detkey engine stup<commit_after>package libkb

import (
	"fmt"
	"github.com/keybase/go-triplesec"
)

type SignupEngine struct {
	pwsalt []byte
	tspkey TSPassKey
	uid    UID
}

func NewSignupEngine() *SignupEngine {
	return &SignupEngine{}
}

func (s *SignupEngine) Init() error {
	return nil
}

func (s *SignupEngine) CheckRegistered() (err error) {
	G.Log.Debug("+ libkb.SignupJoinEngine::CheckRegistered")
	if cr := G.Env.GetConfig(); cr == nil {
		err = fmt.Errorf("No configuration file available")
	} else if u := cr.GetUid(); u != nil {
		err = AlreadyRegisteredError{*u}
	}
	G.Log.Debug("- libkb.SignupJoinEngine::CheckRegistered -> %s", ErrToOk(err))
	return err
}

func (s *SignupEngine) PostInviteRequest(arg InviteRequestArg) error {
	return PostInviteRequest(arg)
}

type SignupEngineRunArg struct {
	Username   string
	Email      string
	InviteCode string
	Passphrase string
	DeviceName string
}

// XXX this might need to return more than error...passphraseok, postok, writeok.
func (s *SignupEngine) Run(arg SignupEngineRunArg) error {
	if err := s.genTSPassKey(arg.Passphrase); err != nil {
		return err
	}

	if err := s.join(arg.Username, arg.Email, arg.InviteCode); err != nil {
		return err
	}

	if err := s.registerDevice(arg.DeviceName); err != nil {
		fmt.Printf("register device error: %s\n", err)
		return err
	}

	if err := s.genDetKeys(); err != nil {
		return err
	}

	return nil
}

func (s *SignupEngine) genTSPassKey(passphrase string) error {
	salt, err := RandBytes(triplesec.SaltLen)
	if err != nil {
		return err
	}
	s.pwsalt = salt

	s.tspkey, err = NewTSPassKey(passphrase, salt)
	return err
}

// XXX might have to do more with the joinEngine result...for now, just returning
// error.
func (s *SignupEngine) join(username, email, inviteCode string) error {
	joinEngine := NewSignupJoinEngine()

	arg := SignupJoinEngineRunArg{
		Username:   username,
		Email:      email,
		InviteCode: inviteCode,
		PWHash:     s.tspkey.PWHash(),
		PWSalt:     s.pwsalt,
	}
	res := joinEngine.Run(arg)
	if res.Error != nil {
		return res.Error
	}
	s.uid = *res.Uid
	return nil
}

func (s *SignupEngine) registerDevice(deviceName string) error {
	eng := NewDeviceEngine()
	return eng.Run(deviceName)
}

func (s *SignupEngine) genDetKeys() error {
	eng := NewDetKeyEngine()
	return eng.Run(s.tspkey.EdDSASeed(), s.tspkey.DHSeed())
}
<|endoftext|>


<commit_before>package local

import (
	"os"
	"testing"

	"github.com/cheekybits/is"
)

func TestFileData(t *testing.T) {
	is := is.New(t)

	info, err := os.Stat("./filedata_test.go")
	is.NoErr(err)
	is.OK(info)

	data := getFileMetadata("./filedata_test.go", info)

	is.Equal(data["is_dir"], false)
	is.Equal(data["ext"], ".go")
	is.Equal(data["path"], "filedata_test.go")
	is.Equal(data["name"], "filedata_test.go")
	is.True(data["mode"] == "644" || data["mode"] == "664")
	is.True(data["mode_d"] == "420" || data["mode_d"] == "436")
	is.Equal(data["perm"], "-rw-r--r--")
	is.OK(data["inode"])
	is.False(data["is_hardlink"])
	is.False(data["is_symlink"])
	is.OK(data["size"])

}

func TestDotFile(t *testing.T) {
	is := is.New(t)

	info, err := os.Stat("./testdata/.dotfile")
	is.NoErr(err)
	is.OK(info)

	data := getFileMetadata("./testdata/.dotfile", info)

	is.Equal(data["ext"], ".dotfile")
	is.Equal(data["name"], ".dotfile")
}
<commit_msg>local: fix testing issue for Travis<commit_after>package local

import (
	"os"
	"testing"

	"github.com/cheekybits/is"
)

func TestFileData(t *testing.T) {
	is := is.New(t)

	info, err := os.Stat("./filedata_test.go")
	is.NoErr(err)
	is.OK(info)

	data := getFileMetadata("./filedata_test.go", info)

	is.Equal(data["is_dir"], false)
	is.Equal(data["ext"], ".go")
	is.Equal(data["path"], "filedata_test.go")
	is.Equal(data["name"], "filedata_test.go")
	is.True(data["mode"] == "644" || data["mode"] == "664")
	is.True(data["mode_d"] == "420" || data["mode_d"] == "436")
	is.True(data["perm"] == "-rw-r--r--" || data["perm"] == "-rw-rw-r--")
	is.OK(data["inode"])
	is.False(data["is_hardlink"])
	is.False(data["is_symlink"])
	is.OK(data["size"])

}

func TestDotFile(t *testing.T) {
	is := is.New(t)

	info, err := os.Stat("./testdata/.dotfile")
	is.NoErr(err)
	is.OK(info)

	data := getFileMetadata("./testdata/.dotfile", info)

	is.Equal(data["ext"], ".dotfile")
	is.Equal(data["name"], ".dotfile")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
	"os"
	"time"

	"github.com/coreos/locksmith/third_party/github.com/coreos/go-systemd/dbus"
	"github.com/coreos/locksmith/third_party/github.com/coreos/go-systemd/login1"

	"github.com/coreos/locksmith/lock"
	"github.com/coreos/locksmith/pkg/machineid"
	"github.com/coreos/locksmith/updateengine"
)

var (
	cmdDaemon = &Command{
		Name:        "daemon",
		Summary:     "Daemon for reboot needed signal and if reboot able.",
		Description: `Daemon waits for the reboot needed signal coming out of update engine and attempts to acquire the reboot lock. If the reboot lock is acquired then the machine will reboot.`,
		Run:         runDaemon,
	}
)

const (
	initialTimeout = time.Second * 5
	maxTimeout     = time.Minute * 5
)

const (
	StrategyReboot     = "reboot"
	StrategyEtcdLock   = "etcd-lock"
	StrategyBestEffort = "best-effort"
)

func expBackoff(try int) time.Duration {
	sleep := time.Duration(math.Pow(2, float64(try))) * initialTimeout
	if sleep > maxTimeout {
		sleep = maxTimeout
	}

	return sleep
}

func rebootAndSleep(lgn *login1.Conn) {
	lgn.Reboot(false)
	fmt.Println("Reboot sent. Going to sleep.")

	// Wait a really long time for the reboot to occur.
	time.Sleep(time.Hour * 24 * 7)
}

// lockAndReboot attempts to acquire the lock and reboot the machine in an
// infinite loop. Returns if the reboot failed.
func (r rebooter) lockAndReboot(lck *lock.Lock) {
	tries := 0
	for {
		err := lck.Lock()
		if err != nil && err != lock.ErrExist {
			sleep := expBackoff(tries)
			fmt.Printf("Retrying in %v. Error locking: %v\n", sleep, err)
			time.Sleep(sleep)
			tries = tries + 1

			continue
		}

		rebootAndSleep(r.lgn)

		return
	}
}

func setupLock() (lck *lock.Lock, err error) {
	elc, err := lock.NewEtcdLockClient(nil)
	if err != nil {
		return nil, fmt.Errorf("Error initializing etcd client: %v", err)
	}

	mID := machineid.MachineID("/")
	if mID == "" {
		return nil, fmt.Errorf("Cannot read machine-id")
	}

	lck = lock.New(mID, elc)

	return lck, nil
}

// etcdActive returns true if etcd is not in an inactive state according to systemd.
func etcdActive() (running bool, err error) {
	sys, err := dbus.New()
	if err != nil {
		return false, err
	}

	prop, err := sys.GetUnitProperty("etcd.service", "ActiveState")
	if err != nil {
		return false, fmt.Errorf("Error getting etcd.service ActiveState: %v", err)
	}

	if prop.Value.Value().(string) == "inactive" {
		return false, nil
	}

	return true, nil
}

type rebooter struct {
	strategy string
	lgn *login1.Conn
}

func (r rebooter) useLock() (useLock bool, err error) {
	switch r.strategy {
	case StrategyBestEffort:
		running, err := etcdActive()
		if err != nil {
			return false, err
		}
		if running {
			fmt.Println("etcd.service is active")
			useLock = true
		} else {
			fmt.Println("etcd.service is inactive")
			useLock = false
		}
	case StrategyEtcdLock:
		useLock = true
	case StrategyReboot:
		useLock = false
	default:
		return false, fmt.Errorf("Unknown strategy: %s", r.strategy)
	}

	return useLock, nil
}

func (r rebooter) reboot() int {
	useLock, err := r.useLock()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}

	if useLock {
		lck, err := setupLock()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}

		err = unlockIfHeld(lck)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}

		r.lockAndReboot(lck)
	}

	rebootAndSleep(r.lgn)
	fmt.Println("Error: reboot attempt never finished")
	return 1
}

// unlockIfHeld will unlock a lock, if it is held by this machine, or return an error.
func unlockIfHeld(lck *lock.Lock) error {
	err := lck.Unlock()
	if err == lock.ErrNotExist {
		return nil
	} else if err == nil {
		fmt.Println("Unlocked existing lock for this machine")
		return nil
	}

	return err
}

// unlockHeldLock will loop until it can confirm that any held locks are
// released or a stop signal is sent.
func unlockHeldLocks(stop chan struct{}) {
	tries := 0
	var sleep time.Duration
	for {
		var reason string
		select {
		case <-stop:
			return
		case <-time.After(sleep):
			active, err := etcdActive()
			if err != nil {
				reason = "error checking on etcd.service"
				break
			}
			if !active {
				reason = "etcd.service is inactive"
				break
			}

			lck, err := setupLock()
			if err != nil {
				reason = "error setting up lock"
				break
			}

			err = unlockIfHeld(lck)
			if err == nil {
				return
			}
			reason = err.Error()
		}

		sleep = expBackoff(tries)
		fmt.Printf("Unlocking old locks failed: %v. Retrying in %v.\n", reason, sleep)
		tries = tries + 1
	}
}

func runDaemon(args []string) int {
	strategy := os.ExpandEnv("${REBOOT_STRATEGY}")
	if strategy == "" {
		strategy = StrategyBestEffort
	}

	ue, err := updateengine.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing update1 client:", err)
		return 1
	}

	lgn, err := login1.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing login1 client:", err)
		return 1
	}

	stopUnlock := make(chan struct{}, 1)
	go unlockHeldLocks(stopUnlock)

	ch := make(chan updateengine.Status, 1)
	go ue.RebootNeededSignal(ch)

	r := rebooter{strategy, lgn}

	result, err := ue.GetStatus()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Cannot get update engine status:", err)
		return 1
	}

	fmt.Printf("locksmithd starting currentOperation=%q strategy=%q\n",
		result.CurrentOperation,
		strategy,
	)

	if result.CurrentOperation != updateengine.UpdateStatusUpdatedNeedReboot {
		<-ch
	}

	close(stopUnlock)
	return r.reboot()
}
<commit_msg>feat(daemon): don't unlock if strategy is reboot<commit_after>package main

import (
	"fmt"
	"math"
	"os"
	"time"

	"github.com/coreos/locksmith/third_party/github.com/coreos/go-systemd/dbus"
	"github.com/coreos/locksmith/third_party/github.com/coreos/go-systemd/login1"

	"github.com/coreos/locksmith/lock"
	"github.com/coreos/locksmith/pkg/machineid"
	"github.com/coreos/locksmith/updateengine"
)

var (
	cmdDaemon = &Command{
		Name:        "daemon",
		Summary:     "Daemon for reboot needed signal and if reboot able.",
		Description: `Daemon waits for the reboot needed signal coming out of update engine and attempts to acquire the reboot lock. If the reboot lock is acquired then the machine will reboot.`,
		Run:         runDaemon,
	}
)

const (
	initialTimeout = time.Second * 5
	maxTimeout     = time.Minute * 5
)

const (
	StrategyReboot     = "reboot"
	StrategyEtcdLock   = "etcd-lock"
	StrategyBestEffort = "best-effort"
)

func expBackoff(try int) time.Duration {
	sleep := time.Duration(math.Pow(2, float64(try))) * initialTimeout
	if sleep > maxTimeout {
		sleep = maxTimeout
	}

	return sleep
}

func rebootAndSleep(lgn *login1.Conn) {
	lgn.Reboot(false)
	fmt.Println("Reboot sent. Going to sleep.")

	// Wait a really long time for the reboot to occur.
	time.Sleep(time.Hour * 24 * 7)
}

// lockAndReboot attempts to acquire the lock and reboot the machine in an
// infinite loop. Returns if the reboot failed.
func (r rebooter) lockAndReboot(lck *lock.Lock) {
	tries := 0
	for {
		err := lck.Lock()
		if err != nil && err != lock.ErrExist {
			sleep := expBackoff(tries)
			fmt.Printf("Retrying in %v. Error locking: %v\n", sleep, err)
			time.Sleep(sleep)
			tries = tries + 1

			continue
		}

		rebootAndSleep(r.lgn)

		return
	}
}

func setupLock() (lck *lock.Lock, err error) {
	elc, err := lock.NewEtcdLockClient(nil)
	if err != nil {
		return nil, fmt.Errorf("Error initializing etcd client: %v", err)
	}

	mID := machineid.MachineID("/")
	if mID == "" {
		return nil, fmt.Errorf("Cannot read machine-id")
	}

	lck = lock.New(mID, elc)

	return lck, nil
}

// etcdActive returns true if etcd is not in an inactive state according to systemd.
func etcdActive() (running bool, err error) {
	sys, err := dbus.New()
	if err != nil {
		return false, err
	}

	prop, err := sys.GetUnitProperty("etcd.service", "ActiveState")
	if err != nil {
		return false, fmt.Errorf("Error getting etcd.service ActiveState: %v", err)
	}

	if prop.Value.Value().(string) == "inactive" {
		return false, nil
	}

	return true, nil
}

type rebooter struct {
	strategy string
	lgn *login1.Conn
}

func (r rebooter) useLock() (useLock bool, err error) {
	switch r.strategy {
	case StrategyBestEffort:
		running, err := etcdActive()
		if err != nil {
			return false, err
		}
		if running {
			fmt.Println("etcd.service is active")
			useLock = true
		} else {
			fmt.Println("etcd.service is inactive")
			useLock = false
		}
	case StrategyEtcdLock:
		useLock = true
	case StrategyReboot:
		useLock = false
	default:
		return false, fmt.Errorf("Unknown strategy: %s", r.strategy)
	}

	return useLock, nil
}

func (r rebooter) reboot() int {
	useLock, err := r.useLock()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}

	if useLock {
		lck, err := setupLock()
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}

		err = unlockIfHeld(lck)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			return 1
		}

		r.lockAndReboot(lck)
	}

	rebootAndSleep(r.lgn)
	fmt.Println("Error: reboot attempt never finished")
	return 1
}

// unlockIfHeld will unlock a lock, if it is held by this machine, or return an error.
func unlockIfHeld(lck *lock.Lock) error {
	err := lck.Unlock()
	if err == lock.ErrNotExist {
		return nil
	} else if err == nil {
		fmt.Println("Unlocked existing lock for this machine")
		return nil
	}

	return err
}

// unlockHeldLock will loop until it can confirm that any held locks are
// released or a stop signal is sent.
func unlockHeldLocks(stop chan struct{}) {
	tries := 0
	var sleep time.Duration
	for {
		var reason string
		select {
		case <-stop:
			return
		case <-time.After(sleep):
			active, err := etcdActive()
			if err != nil {
				reason = "error checking on etcd.service"
				break
			}
			if !active {
				reason = "etcd.service is inactive"
				break
			}

			lck, err := setupLock()
			if err != nil {
				reason = "error setting up lock"
				break
			}

			err = unlockIfHeld(lck)
			if err == nil {
				return
			}
			reason = err.Error()
		}

		sleep = expBackoff(tries)
		fmt.Printf("Unlocking old locks failed: %v. Retrying in %v.\n", reason, sleep)
		tries = tries + 1
	}
}

func runDaemon(args []string) int {
	strategy := os.ExpandEnv("${REBOOT_STRATEGY}")
	if strategy == "" {
		strategy = StrategyBestEffort
	}

	ue, err := updateengine.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing update1 client:", err)
		return 1
	}

	lgn, err := login1.New()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error initializing login1 client:", err)
		return 1
	}

	stopUnlock := make(chan struct{}, 1)
	if strategy != StrategyReboot {
		go unlockHeldLocks(stopUnlock)
	}

	ch := make(chan updateengine.Status, 1)
	go ue.RebootNeededSignal(ch)

	r := rebooter{strategy, lgn}

	result, err := ue.GetStatus()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Cannot get update engine status:", err)
		return 1
	}

	fmt.Printf("locksmithd starting currentOperation=%q strategy=%q\n",
		result.CurrentOperation,
		strategy,
	)

	if result.CurrentOperation != updateengine.UpdateStatusUpdatedNeedReboot {
		<-ch
	}

	close(stopUnlock)
	return r.reboot()
}
<|endoftext|>


<commit_before>/*
	This file is part of LogHub.

	LogHub is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	LogHub is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with LogHub.  If not, see <http://www.gnu.org/licenses/>.
*/
package main

type logMessageHandler struct {
	logManager LogManager
}

func NewLogMessageHandler(logManager LogManager) MessageHandler {
	return &logMessageHandler{logManager}
}

func (mh *logMessageHandler) Write(entries chan *IncomingLogEntryJSON) {
	for ent := range entries {
		mh.logManager.WriteLog(IncomingLogEntryJSONToLogEntry(ent))
	}
}

func (mh *logMessageHandler) Read(chan *LogQueryJSON, chan *OutgoingLogEntryJSON) {
	//TODO: Implement.
}

func (mh *logMessageHandler) InternalRead(chan *LogQueryJSON, chan *InternalLogEntryJSON) {
	//TODO: Implement.
}

func (mh *logMessageHandler) Close() {
	mh.logManager.Close()
}
<commit_msg>Log message handler.<commit_after>/*
	This file is part of LogHub.

	LogHub is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	LogHub is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with LogHub.  If not, see <http://www.gnu.org/licenses/>.
*/
package main

type logMessageHandler struct {
	logManager LogManager
}

func NewLogMessageHandler(logManager LogManager) MessageHandler {
	return &logMessageHandler{logManager}
}

func (mh *logMessageHandler) Write(entries chan *IncomingLogEntryJSON) {
	for ent := range entries {
		mh.logManager.WriteLog(IncomingLogEntryJSONToLogEntry(ent))
	}
}

func (mh *logMessageHandler) queryMultiple(queries chan *LogQueryJSON) chan *LogEntry {
	var results chan *LogEntry = nil

	for qJSON := range queries {
		q := LogQueryJSONToLogQuery(qJSON)

		if results == nil {
			results = make(chan *LogEntry)
			q.Result = results
		} else {
			q.Result = make(chan *LogEntry)
			mergedResults := make(chan *LogEntry)
			go MergeLogs(results, q.Result, mergedResults)
			results = mergedResults
		}

		mh.logManager.ReadLog(q)
	}

	return results
}

func (mh *logMessageHandler) Read(queries chan *LogQueryJSON, resultJSON chan *OutgoingLogEntryJSON) {
	result := mh.queryMultiple(queries)

	if result != nil {
		for ent := range result {
			resultJSON <- LogEntryToOutgoingLogEntryJSON(ent)
		}
	}

	close(resultJSON)
}

func (mh *logMessageHandler) InternalRead(queries chan *LogQueryJSON, resultJSON chan *InternalLogEntryJSON) {
	result := mh.queryMultiple(queries)

	if result != nil {
		for ent := range result {
			resultJSON <- LogEntryToInternalLogEntryJSON(ent)
		}
	}

	close(resultJSON)
}

func (mh *logMessageHandler) Close() {
	mh.logManager.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"io"
	"os"
	"regexp"
	"strings"

	"github.com/Financial-Times/coco-logfilter"
)

var (
	blacklistedProperties = []string{
		"_GID",
		"_CAP_EFFECTIVE",
		"SYSLOG_FACILITY",
		"PRIORITY",
		"SYSLOG_IDENTIFIER",
		"_BOOT_ID",
		"_CMDLINE",
		"_COMM",
		"_EXE",
		"_SYSTEMD_CGROUP",
		"_SYSTEMD_SLICE",
		"_TRANSPORT",
		"_UID",
		"__CURSOR",
		"__MONOTONIC_TIMESTAMP",
		"_SELINUX_CONTEXT",
		"__REALTIME_TIMESTAMP",
		"_PID",
	}

	blacklistedUnits = map[string]bool{
		"splunk-forwarder.service":   true,
		//"docker.service":             true,
		"diamond.service":            true,
		"logstash-forwarder.service": true,
		"kubelet.service": true,
		"flanneld.service": true,

	}

	blacklistedStrings = []string{
		"transaction_id=SYNTHETIC-REQ",
	}

	blacklistedSyslogIds = []string{
		"dockerd", //
	}

	propertyMapping = map[string]string{
		"_SYSTEMD_UNIT": "SYSTEMD_UNIT",
		"_MACHINE_ID":   "MACHINE_ID",
		"_HOSTNAME":     "HOSTNAME",
	}
)

var environmentTag *string = new(string)

func main() {
	*environmentTag = os.Getenv("ENV")

	dec := json.NewDecoder(os.Stdin)
	enc := json.NewEncoder(os.Stdout)
	for {
		m := make(map[string]interface{})
		err := dec.Decode(&m)
		if err != nil {
			if err == io.EOF {
				return
			}
			panic(err)
		}
		unit := m["_SYSTEMD_UNIT"]
		if unitString, ok := unit.(string); ok {
			if blacklistedUnits[unitString] {
				continue
			}
		}

		syslogId := m["SYSLOG_IDENTIFIER"]
		if syslogIdString, ok := syslogId.(string); ok {
			if blacklistedSyslogIds[syslogIdString] {
				continue
			}
		}

		message := fixBytesToString(m["MESSAGE"]).(string)

		if containsBlacklistedString(message) {
			continue
		}

		munge(m, message)
		removeBlacklistedProperties(m)
		renameProperties(m)
		enc.Encode(m)
	}
}

func containsBlacklistedString(message string) bool {
	for _, blacklistedString := range blacklistedStrings {
		if strings.Contains(message, blacklistedString) {
			return true
		}
	}
	return false
}

func munge(m map[string]interface{}, message string) {

	m["platform"] = "up-coco"
	if *environmentTag != "" {
		m["environment"] = *environmentTag
	}

	message = fixNewLines(message)
	m["MESSAGE"] = message

	trans_id := extractTransactionId(message)
	if trans_id != "" {
		m["transaction_id"] = trans_id
	}

	ent, ok := logfilter.Extract(message)
	if !ok {
		return
	}

	// hackity
	j, err := json.Marshal(ent)
	if err != nil {
		panic(err)
	}
	entMap := make(map[string]interface{})
	err = json.Unmarshal(j, &entMap)
	if err != nil {
		panic(err)
	}
	for k, v := range entMap {
		m[k] = v
	}
}

var trans_regex = regexp.MustCompile(`\btransaction_id=([\w-]*)`)

func extractTransactionId(message string) string {
	matches := trans_regex.FindAllStringSubmatch(message, -1)
	if len(matches) != 0 {
		return matches[0][1]
	}

	return ""
}

// workaround for cases where a string has been turned into a
// byte array, or more accurately an array of float64, since
// we've been via json.
// TODO: remove this hack once the underlying cause is found
func fixBytesToString(message interface{}) interface{} {
	intArray, ok := message.([]interface{})
	if !ok {
		return message
	}

	data := make([]byte, len(intArray))
	for i, v := range intArray {
		f64, ok := v.(float64)
		if !ok {
			return message
		}
		data[i] = byte(f64)
	}
	return string(data)
}

func fixNewLines(message string) string {
	return strings.Replace(message, "|", "\n", -1)
}

func removeBlacklistedProperties(m map[string]interface{}) {
	for _, p := range blacklistedProperties {
		delete(m, p)
	}
}

func renameProperties(m map[string]interface{}) {
	for p, r := range propertyMapping {
		value := m[p]
		if value != nil {
			delete(m, p)
			m[r] = value
		}
	}

}
<commit_msg>Fixed compilation<commit_after>package main

import (
	"encoding/json"
	"io"
	"os"
	"regexp"
	"strings"

	"github.com/Financial-Times/coco-logfilter"
)

var (
	blacklistedProperties = []string{
		"_GID",
		"_CAP_EFFECTIVE",
		"SYSLOG_FACILITY",
		"PRIORITY",
		"SYSLOG_IDENTIFIER",
		"_BOOT_ID",
		"_CMDLINE",
		"_COMM",
		"_EXE",
		"_SYSTEMD_CGROUP",
		"_SYSTEMD_SLICE",
		"_TRANSPORT",
		"_UID",
		"__CURSOR",
		"__MONOTONIC_TIMESTAMP",
		"_SELINUX_CONTEXT",
		"__REALTIME_TIMESTAMP",
		"_PID",
	}

	blacklistedUnits = map[string]bool{
		"splunk-forwarder.service":   true,
		//"docker.service":             true,
		"diamond.service":            true,
		"logstash-forwarder.service": true,
		"kubelet.service": true,
		"flanneld.service": true,

	}

	blacklistedStrings = []string{
		"transaction_id=SYNTHETIC-REQ",
	}

	blacklistedSyslogIds = map[string]bool{
		"dockerd": true,
	}

	propertyMapping = map[string]string{
		"_SYSTEMD_UNIT": "SYSTEMD_UNIT",
		"_MACHINE_ID":   "MACHINE_ID",
		"_HOSTNAME":     "HOSTNAME",
	}
)

var environmentTag *string = new(string)

func main() {
	*environmentTag = os.Getenv("ENV")

	dec := json.NewDecoder(os.Stdin)
	enc := json.NewEncoder(os.Stdout)
	for {
		m := make(map[string]interface{})
		err := dec.Decode(&m)
		if err != nil {
			if err == io.EOF {
				return
			}
			panic(err)
		}
		unit := m["_SYSTEMD_UNIT"]
		if unitString, ok := unit.(string); ok {
			if blacklistedUnits[unitString] {
				continue
			}
		}

		syslogId := m["SYSLOG_IDENTIFIER"]
		if syslogIdString, ok := syslogId.(string); ok {
			if blacklistedSyslogIds[syslogIdString] {
				continue
			}
		}

		message := fixBytesToString(m["MESSAGE"]).(string)

		if containsBlacklistedString(message) {
			continue
		}

		munge(m, message)
		removeBlacklistedProperties(m)
		renameProperties(m)
		enc.Encode(m)
	}
}

func containsBlacklistedString(message string) bool {
	for _, blacklistedString := range blacklistedStrings {
		if strings.Contains(message, blacklistedString) {
			return true
		}
	}
	return false
}

func munge(m map[string]interface{}, message string) {

	m["platform"] = "up-coco"
	if *environmentTag != "" {
		m["environment"] = *environmentTag
	}

	message = fixNewLines(message)
	m["MESSAGE"] = message

	trans_id := extractTransactionId(message)
	if trans_id != "" {
		m["transaction_id"] = trans_id
	}

	ent, ok := logfilter.Extract(message)
	if !ok {
		return
	}

	// hackity
	j, err := json.Marshal(ent)
	if err != nil {
		panic(err)
	}
	entMap := make(map[string]interface{})
	err = json.Unmarshal(j, &entMap)
	if err != nil {
		panic(err)
	}
	for k, v := range entMap {
		m[k] = v
	}
}

var trans_regex = regexp.MustCompile(`\btransaction_id=([\w-]*)`)

func extractTransactionId(message string) string {
	matches := trans_regex.FindAllStringSubmatch(message, -1)
	if len(matches) != 0 {
		return matches[0][1]
	}

	return ""
}

// workaround for cases where a string has been turned into a
// byte array, or more accurately an array of float64, since
// we've been via json.
// TODO: remove this hack once the underlying cause is found
func fixBytesToString(message interface{}) interface{} {
	intArray, ok := message.([]interface{})
	if !ok {
		return message
	}

	data := make([]byte, len(intArray))
	for i, v := range intArray {
		f64, ok := v.(float64)
		if !ok {
			return message
		}
		data[i] = byte(f64)
	}
	return string(data)
}

func fixNewLines(message string) string {
	return strings.Replace(message, "|", "\n", -1)
}

func removeBlacklistedProperties(m map[string]interface{}) {
	for _, p := range blacklistedProperties {
		delete(m, p)
	}
}

func renameProperties(m map[string]interface{}) {
	for p, r := range propertyMapping {
		value := m[p]
		if value != nil {
			delete(m, p)
			m[r] = value
		}
	}

}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"os/exec"
	"strings"

	"github.com/dustinkirkland/golang-petname"
	"github.com/gorilla/websocket"
	"github.com/lxc/lxd/lxd/migration"
	"github.com/lxc/lxd/shared"
)

func extractImage(hash string, name string, d *Daemon) error {
	/*
	 * We want to use archive/tar for this, but that doesn't appear
	 * to be working for us (see lxd/images.go)
	 */
	dpath := shared.VarPath("lxc", name)
	imagefile := shared.VarPath("images", hash)

	err := untar(imagefile, dpath)
	if err != nil {
		return err
	}

	if shared.PathExists(imagefile + ".rootfs") {
		err := untar(imagefile+".rootfs", dpath+"/rootfs/")
		if err != nil {
			return err
		}
	}

	return nil
}

func shiftRootfs(c *lxdContainer, d *Daemon) error {
	dpath := shared.VarPath("lxc", c.name)
	rpath := shared.VarPath("lxc", c.name, "rootfs")
	err := c.idmapset.ShiftRootfs(rpath)
	if err != nil {
		shared.Debugf("Shift of rootfs %s failed: %s\n", rpath, err)
		removeContainer(d, c)
		return err
	}

	/* Set an acl so the container root can descend the container dir */
	err = setUnprivUserAcl(c, dpath)
	if err != nil {
		shared.Debugf("Error adding acl for container root: falling back to chmod\n")
		output, err := exec.Command("chmod", "+x", dpath).CombinedOutput()
		if err != nil {
			shared.Debugf("Error chmoding the container root\n")
			shared.Debugf(string(output))
			return err
		}
	}

	return nil
}

func setUnprivUserAcl(c *lxdContainer, dpath string) error {
	if c.idmapset == nil {
		return nil
	}
	uid, _ := c.idmapset.ShiftIntoNs(0, 0)
	switch uid {
	case -1:
		shared.Debugf("setUnprivUserAcl: no root id mapping")
		return nil
	case 0:
		return nil
	}
	acl := fmt.Sprintf("%d:rx", uid)
	output, err := exec.Command("setfacl", "-m", acl, dpath).CombinedOutput()
	if err != nil {
		shared.Debugf("setfacl failed:\n%s", output)
	}
	return err
}

func extractShiftIfExists(d *Daemon, c *lxdContainer, hash string, name string) error {
	if hash == "" {
		return nil
	}

	_, err := dbImageGet(d.db, hash, false)
	if err == nil {
		if err := extractImage(hash, name, d); err != nil {
			return err
		}

		if !c.isPrivileged() {
			if err := shiftRootfs(c, d); err != nil {
				return err
			}
		}
	}

	return nil
}

func createFromImage(d *Daemon, req *containerPostReq) Response {
	var hash string
	var err error
	var run func() shared.OperationResult

	if req.Source.Alias != "" {
		if req.Source.Mode == "pull" && req.Source.Server != "" {
			hash, err = remoteGetImageFingerprint(d, req.Source.Server, req.Source.Alias)
			if err != nil {
				return InternalError(err)
			}
		} else {

			hash, err = dbImageAliasGet(d.db, req.Source.Alias)
			if err != nil {
				return InternalError(err)
			}
		}
	} else if req.Source.Fingerprint != "" {
		hash = req.Source.Fingerprint
	} else {
		return BadRequest(fmt.Errorf("must specify one of alias or fingerprint for init from image"))
	}

	if req.Source.Server != "" {
		err := ensureLocalImage(d, req.Source.Server, hash, req.Source.Secret)
		if err != nil {
			return InternalError(err)
		}
	}

	imgInfo, err := dbImageGet(d.db, hash, false)
	if err != nil {
		return SmartError(err)
	}
	hash = imgInfo.Fingerprint

	dpath := shared.VarPath("lxc", req.Name)
	if shared.PathExists(dpath) {
		return InternalError(fmt.Errorf("Container exists"))
	}

	name := req.Name

	args := containerLXDArgs{
		Ctype:        cTypeRegular,
		Config:       req.Config,
		Profiles:     req.Profiles,
		Ephemeral:    req.Ephemeral,
		BaseImage:    hash,
		Architecture: imgInfo.Architecture,
	}

	_, err = dbContainerCreate(d.db, name, args)
	if err != nil {
		return SmartError(err)
	}

	c, err := newLxdContainer(name, d)
	if err != nil {
		removeContainer(d, c)
		return SmartError(err)
	}

	run = shared.OperationWrap(func() error {
		err := d.Storage.ContainerCreate(c, hash)
		if err != nil {
			removeContainer(d, c)
		}
		return err
	})

	resources := make(map[string][]string)
	resources["containers"] = []string{c.name}

	return &asyncResponse{run: run, resources: resources}
}

func createFromNone(d *Daemon, req *containerPostReq) Response {
	args := containerLXDArgs{
		Ctype:     cTypeRegular,
		Config:    req.Config,
		Profiles:  req.Profiles,
		Ephemeral: req.Ephemeral,
	}

	_, err := dbContainerCreate(d.db, req.Name, args)
	if err != nil {
		return SmartError(err)
	}

	run := shared.OperationWrap(func() error {
		c, err := newLxdContainer(req.Name, d)
		if err != nil {
			return err
		}

		err = templateApply(c, "create")
		if err != nil {
			return err
		}

		return nil
	})

	resources := make(map[string][]string)
	resources["containers"] = []string{req.Name}

	return &asyncResponse{run: run, resources: resources}
}

func createFromMigration(d *Daemon, req *containerPostReq) Response {
	if req.Source.Mode != "pull" {
		return NotImplemented
	}

	createArgs := containerLXDArgs{
		Ctype:     cTypeRegular,
		Config:    req.Config,
		Profiles:  req.Profiles,
		Ephemeral: req.Ephemeral,
		BaseImage: req.Source.BaseImage,
	}

	_, err := dbContainerCreate(d.db, req.Name, createArgs)
	if err != nil {
		return SmartError(err)
	}

	c, err := newLxdContainer(req.Name, d)
	if err != nil {
		removeContainer(d, c)
		return SmartError(err)
	}

	// rsync complaisn if the parent directory for the rootfs sync doesn't
	// exist
	dpath := shared.VarPath("lxc", req.Name)
	if err := os.MkdirAll(dpath, 0700); err != nil {
		removeContainer(d, c)
		return InternalError(err)
	}

	if err := extractShiftIfExists(d, c, req.Source.BaseImage, req.Name); err != nil {
		removeContainer(d, c)
		return InternalError(err)
	}

	config, err := shared.GetTLSConfig(d.certf, d.keyf)
	if err != nil {
		removeContainer(d, c)
		return InternalError(err)
	}

	args := migration.MigrationSinkArgs{
		Url: req.Source.Operation,
		Dialer: websocket.Dialer{
			TLSClientConfig: config,
			NetDial:         shared.RFC3493Dialer},
		Container: c.c,
		Secrets:   req.Source.Websockets,
		IdMapSet:  c.idmapset,
	}

	sink, err := migration.NewMigrationSink(&args)
	if err != nil {
		removeContainer(d, c)
		return BadRequest(err)
	}

	run := func() shared.OperationResult {
		err := sink()
		if err != nil {
			removeContainer(d, c)
			return shared.OperationError(err)
		}

		c, err := newLxdContainer(req.Name, d)
		if err != nil {
			return shared.OperationError(err)
		}

		err = templateApply(c, "copy")
		if err != nil {
			return shared.OperationError(err)
		}

		return shared.OperationError(nil)
	}

	resources := make(map[string][]string)
	resources["containers"] = []string{req.Name}

	return &asyncResponse{run: run, resources: resources}
}

func createFromCopy(d *Daemon, req *containerPostReq) Response {
	if req.Source.Source == "" {
		return BadRequest(fmt.Errorf("must specify a source container"))
	}

	// Make sure the source exists.
	source, err := newLxdContainer(req.Source.Source, d)
	if err != nil {
		return SmartError(err)
	}

	if req.Config == nil {
		config := make(map[string]string)
		for key, value := range source.config {
			if key[0:8] == "volatile" {
				shared.Debugf("skipping: %s\n", key)
				continue
			}
			req.Config[key] = value
		}
		req.Config = config
	}

	if req.Profiles == nil {
		req.Profiles = source.profiles
	}

	args := containerLXDArgs{
		Ctype:     cTypeRegular,
		Config:    req.Config,
		Profiles:  req.Profiles,
		Ephemeral: req.Ephemeral,
		BaseImage: req.Source.BaseImage,
	}

	_, err = dbContainerCreate(d.db, req.Name, args)
	if err != nil {
		return SmartError(err)
	}

	run := func() shared.OperationResult {
		c, err := newLxdContainer(req.Name, d)
		if err != nil {
			return shared.OperationError(err)
		}

		s, err := storageForContainer(d, source)
		if err != nil {
			return shared.OperationError(err)
		}
		if err := s.ContainerCopy(c, source); err != nil {
			removeContainer(d, c)
			return shared.OperationError(err)
		}

		return shared.OperationError(nil)
	}

	resources := make(map[string][]string)
	resources["containers"] = []string{req.Name, req.Source.Source}

	return &asyncResponse{run: run, resources: resources}
}

func containersPost(d *Daemon, r *http.Request) Response {
	shared.Debugf("responding to create")

	if d.IdmapSet == nil {
		return BadRequest(fmt.Errorf("shared's user has no subuids"))
	}

	req := containerPostReq{}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return BadRequest(err)
	}

	if req.Name == "" {
		req.Name = strings.ToLower(petname.Generate(2, "-"))
		shared.Debugf("no name provided, creating %s", req.Name)
	}

	switch req.Source.Type {
	case "image":
		return createFromImage(d, &req)
	case "none":
		return createFromNone(d, &req)
	case "migration":
		return createFromMigration(d, &req)
	case "copy":
		return createFromCopy(d, &req)
	default:
		return BadRequest(fmt.Errorf("unknown source type %s", req.Source.Type))
	}

}
<commit_msg>containers POST: don't allow '/' in container names<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"os/exec"
	"strings"

	"github.com/dustinkirkland/golang-petname"
	"github.com/gorilla/websocket"
	"github.com/lxc/lxd/lxd/migration"
	"github.com/lxc/lxd/shared"
)

func extractImage(hash string, name string, d *Daemon) error {
	/*
	 * We want to use archive/tar for this, but that doesn't appear
	 * to be working for us (see lxd/images.go)
	 */
	dpath := shared.VarPath("lxc", name)
	imagefile := shared.VarPath("images", hash)

	err := untar(imagefile, dpath)
	if err != nil {
		return err
	}

	if shared.PathExists(imagefile + ".rootfs") {
		err := untar(imagefile+".rootfs", dpath+"/rootfs/")
		if err != nil {
			return err
		}
	}

	return nil
}

func shiftRootfs(c *lxdContainer, d *Daemon) error {
	dpath := shared.VarPath("lxc", c.name)
	rpath := shared.VarPath("lxc", c.name, "rootfs")
	err := c.idmapset.ShiftRootfs(rpath)
	if err != nil {
		shared.Debugf("Shift of rootfs %s failed: %s\n", rpath, err)
		removeContainer(d, c)
		return err
	}

	/* Set an acl so the container root can descend the container dir */
	err = setUnprivUserAcl(c, dpath)
	if err != nil {
		shared.Debugf("Error adding acl for container root: falling back to chmod\n")
		output, err := exec.Command("chmod", "+x", dpath).CombinedOutput()
		if err != nil {
			shared.Debugf("Error chmoding the container root\n")
			shared.Debugf(string(output))
			return err
		}
	}

	return nil
}

func setUnprivUserAcl(c *lxdContainer, dpath string) error {
	if c.idmapset == nil {
		return nil
	}
	uid, _ := c.idmapset.ShiftIntoNs(0, 0)
	switch uid {
	case -1:
		shared.Debugf("setUnprivUserAcl: no root id mapping")
		return nil
	case 0:
		return nil
	}
	acl := fmt.Sprintf("%d:rx", uid)
	output, err := exec.Command("setfacl", "-m", acl, dpath).CombinedOutput()
	if err != nil {
		shared.Debugf("setfacl failed:\n%s", output)
	}
	return err
}

func extractShiftIfExists(d *Daemon, c *lxdContainer, hash string, name string) error {
	if hash == "" {
		return nil
	}

	_, err := dbImageGet(d.db, hash, false)
	if err == nil {
		if err := extractImage(hash, name, d); err != nil {
			return err
		}

		if !c.isPrivileged() {
			if err := shiftRootfs(c, d); err != nil {
				return err
			}
		}
	}

	return nil
}

func createFromImage(d *Daemon, req *containerPostReq) Response {
	var hash string
	var err error
	var run func() shared.OperationResult

	if req.Source.Alias != "" {
		if req.Source.Mode == "pull" && req.Source.Server != "" {
			hash, err = remoteGetImageFingerprint(d, req.Source.Server, req.Source.Alias)
			if err != nil {
				return InternalError(err)
			}
		} else {

			hash, err = dbImageAliasGet(d.db, req.Source.Alias)
			if err != nil {
				return InternalError(err)
			}
		}
	} else if req.Source.Fingerprint != "" {
		hash = req.Source.Fingerprint
	} else {
		return BadRequest(fmt.Errorf("must specify one of alias or fingerprint for init from image"))
	}

	if req.Source.Server != "" {
		err := ensureLocalImage(d, req.Source.Server, hash, req.Source.Secret)
		if err != nil {
			return InternalError(err)
		}
	}

	imgInfo, err := dbImageGet(d.db, hash, false)
	if err != nil {
		return SmartError(err)
	}
	hash = imgInfo.Fingerprint

	dpath := shared.VarPath("lxc", req.Name)
	if shared.PathExists(dpath) {
		return InternalError(fmt.Errorf("Container exists"))
	}

	name := req.Name

	args := containerLXDArgs{
		Ctype:        cTypeRegular,
		Config:       req.Config,
		Profiles:     req.Profiles,
		Ephemeral:    req.Ephemeral,
		BaseImage:    hash,
		Architecture: imgInfo.Architecture,
	}

	_, err = dbContainerCreate(d.db, name, args)
	if err != nil {
		return SmartError(err)
	}

	c, err := newLxdContainer(name, d)
	if err != nil {
		removeContainer(d, c)
		return SmartError(err)
	}

	run = shared.OperationWrap(func() error {
		err := d.Storage.ContainerCreate(c, hash)
		if err != nil {
			removeContainer(d, c)
		}
		return err
	})

	resources := make(map[string][]string)
	resources["containers"] = []string{c.name}

	return &asyncResponse{run: run, resources: resources}
}

func createFromNone(d *Daemon, req *containerPostReq) Response {
	args := containerLXDArgs{
		Ctype:     cTypeRegular,
		Config:    req.Config,
		Profiles:  req.Profiles,
		Ephemeral: req.Ephemeral,
	}

	_, err := dbContainerCreate(d.db, req.Name, args)
	if err != nil {
		return SmartError(err)
	}

	run := shared.OperationWrap(func() error {
		c, err := newLxdContainer(req.Name, d)
		if err != nil {
			return err
		}

		err = templateApply(c, "create")
		if err != nil {
			return err
		}

		return nil
	})

	resources := make(map[string][]string)
	resources["containers"] = []string{req.Name}

	return &asyncResponse{run: run, resources: resources}
}

func createFromMigration(d *Daemon, req *containerPostReq) Response {
	if req.Source.Mode != "pull" {
		return NotImplemented
	}

	createArgs := containerLXDArgs{
		Ctype:     cTypeRegular,
		Config:    req.Config,
		Profiles:  req.Profiles,
		Ephemeral: req.Ephemeral,
		BaseImage: req.Source.BaseImage,
	}

	_, err := dbContainerCreate(d.db, req.Name, createArgs)
	if err != nil {
		return SmartError(err)
	}

	c, err := newLxdContainer(req.Name, d)
	if err != nil {
		removeContainer(d, c)
		return SmartError(err)
	}

	// rsync complaisn if the parent directory for the rootfs sync doesn't
	// exist
	dpath := shared.VarPath("lxc", req.Name)
	if err := os.MkdirAll(dpath, 0700); err != nil {
		removeContainer(d, c)
		return InternalError(err)
	}

	if err := extractShiftIfExists(d, c, req.Source.BaseImage, req.Name); err != nil {
		removeContainer(d, c)
		return InternalError(err)
	}

	config, err := shared.GetTLSConfig(d.certf, d.keyf)
	if err != nil {
		removeContainer(d, c)
		return InternalError(err)
	}

	args := migration.MigrationSinkArgs{
		Url: req.Source.Operation,
		Dialer: websocket.Dialer{
			TLSClientConfig: config,
			NetDial:         shared.RFC3493Dialer},
		Container: c.c,
		Secrets:   req.Source.Websockets,
		IdMapSet:  c.idmapset,
	}

	sink, err := migration.NewMigrationSink(&args)
	if err != nil {
		removeContainer(d, c)
		return BadRequest(err)
	}

	run := func() shared.OperationResult {
		err := sink()
		if err != nil {
			removeContainer(d, c)
			return shared.OperationError(err)
		}

		c, err := newLxdContainer(req.Name, d)
		if err != nil {
			return shared.OperationError(err)
		}

		err = templateApply(c, "copy")
		if err != nil {
			return shared.OperationError(err)
		}

		return shared.OperationError(nil)
	}

	resources := make(map[string][]string)
	resources["containers"] = []string{req.Name}

	return &asyncResponse{run: run, resources: resources}
}

func createFromCopy(d *Daemon, req *containerPostReq) Response {
	if req.Source.Source == "" {
		return BadRequest(fmt.Errorf("must specify a source container"))
	}

	// Make sure the source exists.
	source, err := newLxdContainer(req.Source.Source, d)
	if err != nil {
		return SmartError(err)
	}

	if req.Config == nil {
		config := make(map[string]string)
		for key, value := range source.config {
			if key[0:8] == "volatile" {
				shared.Debugf("skipping: %s\n", key)
				continue
			}
			req.Config[key] = value
		}
		req.Config = config
	}

	if req.Profiles == nil {
		req.Profiles = source.profiles
	}

	args := containerLXDArgs{
		Ctype:     cTypeRegular,
		Config:    req.Config,
		Profiles:  req.Profiles,
		Ephemeral: req.Ephemeral,
		BaseImage: req.Source.BaseImage,
	}

	_, err = dbContainerCreate(d.db, req.Name, args)
	if err != nil {
		return SmartError(err)
	}

	run := func() shared.OperationResult {
		c, err := newLxdContainer(req.Name, d)
		if err != nil {
			return shared.OperationError(err)
		}

		s, err := storageForContainer(d, source)
		if err != nil {
			return shared.OperationError(err)
		}
		if err := s.ContainerCopy(c, source); err != nil {
			removeContainer(d, c)
			return shared.OperationError(err)
		}

		return shared.OperationError(nil)
	}

	resources := make(map[string][]string)
	resources["containers"] = []string{req.Name, req.Source.Source}

	return &asyncResponse{run: run, resources: resources}
}

func containersPost(d *Daemon, r *http.Request) Response {
	shared.Debugf("responding to create")

	if d.IdmapSet == nil {
		return BadRequest(fmt.Errorf("shared's user has no subuids"))
	}

	req := containerPostReq{}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		return BadRequest(err)
	}

	if req.Name == "" {
		req.Name = strings.ToLower(petname.Generate(2, "-"))
		shared.Debugf("no name provided, creating %s", req.Name)
	}

	if strings.Contains(req.Name, "/") {
		return BadRequest(fmt.Errorf("Invalid container name: '/' is reserved for snapshots"))
	}

	switch req.Source.Type {
	case "image":
		return createFromImage(d, &req)
	case "none":
		return createFromNone(d, &req)
	case "migration":
		return createFromMigration(d, &req)
	case "copy":
		return createFromCopy(d, &req)
	default:
		return BadRequest(fmt.Errorf("unknown source type %s", req.Source.Type))
	}

}
<|endoftext|>


<commit_before>package db

import _ "github.com/mattn/go-sqlite3"

// CertInfo is here to pass the certificates content
// from the database around
type CertInfo struct {
	ID          int
	Fingerprint string
	Type        int
	Name        string
	Certificate string
}

// CertsGet returns all certificates from the DB as CertBaseInfo objects.
func (n *Node) CertsGet() (certs []*CertInfo, err error) {
	rows, err := dbQuery(
		n.db,
		"SELECT id, fingerprint, type, name, certificate FROM certificates",
	)
	if err != nil {
		return certs, err
	}

	defer rows.Close()

	for rows.Next() {
		cert := new(CertInfo)
		rows.Scan(
			&cert.ID,
			&cert.Fingerprint,
			&cert.Type,
			&cert.Name,
			&cert.Certificate,
		)
		certs = append(certs, cert)
	}

	return certs, nil
}

// CertGet gets an CertBaseInfo object from the database.
// The argument fingerprint will be queried with a LIKE query, means you can
// pass a shortform and will get the full fingerprint.
// There can never be more than one image with a given fingerprint, as it is
// enforced by a UNIQUE constraint in the schema.
func (n *Node) CertGet(fingerprint string) (cert *CertInfo, err error) {
	cert = new(CertInfo)

	inargs := []interface{}{fingerprint + "%"}
	outfmt := []interface{}{
		&cert.ID,
		&cert.Fingerprint,
		&cert.Type,
		&cert.Name,
		&cert.Certificate,
	}

	query := `
		SELECT
			id, fingerprint, type, name, certificate
		FROM
			certificates
		WHERE fingerprint LIKE ?`

	if err = dbQueryRowScan(n.db, query, inargs, outfmt); err != nil {
		return nil, err
	}

	return cert, err
}

// CertSave stores a CertBaseInfo object in the db,
// it will ignore the ID field from the CertInfo.
func (n *Node) CertSave(cert *CertInfo) error {
	tx, err := begin(n.db)
	if err != nil {
		return err
	}
	stmt, err := tx.Prepare(`
			INSERT INTO certificates (
				fingerprint,
				type,
				name,
				certificate
			) VALUES (?, ?, ?, ?)`,
	)
	if err != nil {
		tx.Rollback()
		return err
	}
	defer stmt.Close()
	_, err = stmt.Exec(
		cert.Fingerprint,
		cert.Type,
		cert.Name,
		cert.Certificate,
	)
	if err != nil {
		tx.Rollback()
		return err
	}

	return TxCommit(tx)
}

// CertDelete deletes a certificate from the db.
func (n *Node) CertDelete(fingerprint string) error {
	_, err := exec(n.db, "DELETE FROM certificates WHERE fingerprint=?", fingerprint)
	if err != nil {
		return err
	}

	return nil
}

func (n *Node) CertUpdate(fingerprint string, certName string, certType int) error {
	tx, err := begin(n.db)
	if err != nil {
		return err
	}

	_, err = tx.Exec("UPDATE certificates SET name=?, type=? WHERE fingerprint=?", certName, certType, fingerprint)
	if err != nil {
		tx.Rollback()
		return err
	}

	err = TxCommit(tx)

	return err
}
<commit_msg>Drop unused import in lxd/db/certificates.go<commit_after>package db

// CertInfo is here to pass the certificates content
// from the database around
type CertInfo struct {
	ID          int
	Fingerprint string
	Type        int
	Name        string
	Certificate string
}

// CertsGet returns all certificates from the DB as CertBaseInfo objects.
func (n *Node) CertsGet() (certs []*CertInfo, err error) {
	rows, err := dbQuery(
		n.db,
		"SELECT id, fingerprint, type, name, certificate FROM certificates",
	)
	if err != nil {
		return certs, err
	}

	defer rows.Close()

	for rows.Next() {
		cert := new(CertInfo)
		rows.Scan(
			&cert.ID,
			&cert.Fingerprint,
			&cert.Type,
			&cert.Name,
			&cert.Certificate,
		)
		certs = append(certs, cert)
	}

	return certs, nil
}

// CertGet gets an CertBaseInfo object from the database.
// The argument fingerprint will be queried with a LIKE query, means you can
// pass a shortform and will get the full fingerprint.
// There can never be more than one image with a given fingerprint, as it is
// enforced by a UNIQUE constraint in the schema.
func (n *Node) CertGet(fingerprint string) (cert *CertInfo, err error) {
	cert = new(CertInfo)

	inargs := []interface{}{fingerprint + "%"}
	outfmt := []interface{}{
		&cert.ID,
		&cert.Fingerprint,
		&cert.Type,
		&cert.Name,
		&cert.Certificate,
	}

	query := `
		SELECT
			id, fingerprint, type, name, certificate
		FROM
			certificates
		WHERE fingerprint LIKE ?`

	if err = dbQueryRowScan(n.db, query, inargs, outfmt); err != nil {
		return nil, err
	}

	return cert, err
}

// CertSave stores a CertBaseInfo object in the db,
// it will ignore the ID field from the CertInfo.
func (n *Node) CertSave(cert *CertInfo) error {
	tx, err := begin(n.db)
	if err != nil {
		return err
	}
	stmt, err := tx.Prepare(`
			INSERT INTO certificates (
				fingerprint,
				type,
				name,
				certificate
			) VALUES (?, ?, ?, ?)`,
	)
	if err != nil {
		tx.Rollback()
		return err
	}
	defer stmt.Close()
	_, err = stmt.Exec(
		cert.Fingerprint,
		cert.Type,
		cert.Name,
		cert.Certificate,
	)
	if err != nil {
		tx.Rollback()
		return err
	}

	return TxCommit(tx)
}

// CertDelete deletes a certificate from the db.
func (n *Node) CertDelete(fingerprint string) error {
	_, err := exec(n.db, "DELETE FROM certificates WHERE fingerprint=?", fingerprint)
	if err != nil {
		return err
	}

	return nil
}

func (n *Node) CertUpdate(fingerprint string, certName string, certType int) error {
	tx, err := begin(n.db)
	if err != nil {
		return err
	}

	_, err = tx.Exec("UPDATE certificates SET name=?, type=? WHERE fingerprint=?", certName, certType, fingerprint)
	if err != nil {
		tx.Rollback()
		return err
	}

	err = TxCommit(tx)

	return err
}
<|endoftext|>


<commit_before>package aws

import (
	"encoding/xml"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"reflect"

	"github.com/crowdmob/goamz/aws"
)

type QueryClient struct {
	Client     *http.Client
	Region     string
	Endpoint   string
	Prefix     string
	Key        string
	Secret     string
	APIVersion string
}

func (c *QueryClient) Do(op, method, uri string, req, resp interface{}) error {
	v := url.Values{"Action": {op}, "Version": {c.APIVersion}}
	if err := loadValues(v, req); err != nil {
		return err
	}

	u, err := url.Parse(c.Endpoint + uri + "?" + v.Encode())
	if err != nil {
		return err
	}

	httpReq, err := http.NewRequest(method, u.String(), nil)
	if err != nil {
		return err
	}

	signer := aws.NewV4Signer(aws.Auth{
		AccessKey: c.Key,
		SecretKey: c.Secret,
	}, c.Prefix, aws.Region{Name: c.Region})
	signer.Sign(httpReq)

	httpResp, err := c.Client.Do(httpReq)
	if err != nil {
		return err
	}
	defer httpResp.Body.Close()

	b, err := ioutil.ReadAll(httpResp.Body)
	if err != nil {
		return err
	}

	if httpResp.StatusCode != 200 {
		return errors.New(string(b))
	}

	fmt.Println(string(b))

	return xml.Unmarshal(b, resp)
}

func loadValues(v url.Values, i interface{}) error {
	value := reflect.ValueOf(i)
	if value.Kind() == reflect.Ptr {
		value = value.Elem()
	}
	t := value.Type()
	for i := 0; i < value.NumField(); i++ {
		value := value.Field(i)
		name := t.Field(i).Tag.Get("xml")
		switch casted := value.Interface().(type) {
		case string:
			if casted != "" {
				v.Set(name, casted)
			}
		case bool:
			if casted {
				v.Set(name, "true")
			}
		case int64:
			if casted != 0 {
				v.Set(name, fmt.Sprintf("%d", casted))
			}
		case int:
			if casted != 0 {
				v.Set(name, fmt.Sprintf("%d", casted))
			}
		case []string:
			if len(casted) != 0 {
				for i, val := range casted {
					v.Set(fmt.Sprintf("%s.member.%d", name, i+1), val)
				}
			}
		}
	}
	return nil
}
<commit_msg>Remove debugging from query client.<commit_after>package aws

import (
	"encoding/xml"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"reflect"

	"github.com/crowdmob/goamz/aws"
)

type QueryClient struct {
	Client     *http.Client
	Region     string
	Endpoint   string
	Prefix     string
	Key        string
	Secret     string
	APIVersion string
}

func (c *QueryClient) Do(op, method, uri string, req, resp interface{}) error {
	v := url.Values{"Action": {op}, "Version": {c.APIVersion}}
	if err := loadValues(v, req); err != nil {
		return err
	}

	u, err := url.Parse(c.Endpoint + uri + "?" + v.Encode())
	if err != nil {
		return err
	}

	httpReq, err := http.NewRequest(method, u.String(), nil)
	if err != nil {
		return err
	}

	signer := aws.NewV4Signer(aws.Auth{
		AccessKey: c.Key,
		SecretKey: c.Secret,
	}, c.Prefix, aws.Region{Name: c.Region})
	signer.Sign(httpReq)

	httpResp, err := c.Client.Do(httpReq)
	if err != nil {
		return err
	}
	defer httpResp.Body.Close()

	b, err := ioutil.ReadAll(httpResp.Body)
	if err != nil {
		return err
	}

	if httpResp.StatusCode != 200 {
		return errors.New(string(b))
	}

	return xml.Unmarshal(b, resp)
}

func loadValues(v url.Values, i interface{}) error {
	value := reflect.ValueOf(i)
	if value.Kind() == reflect.Ptr {
		value = value.Elem()
	}
	t := value.Type()
	for i := 0; i < value.NumField(); i++ {
		value := value.Field(i)
		name := t.Field(i).Tag.Get("xml")
		switch casted := value.Interface().(type) {
		case string:
			if casted != "" {
				v.Set(name, casted)
			}
		case bool:
			if casted {
				v.Set(name, "true")
			}
		case int64:
			if casted != 0 {
				v.Set(name, fmt.Sprintf("%d", casted))
			}
		case int:
			if casted != 0 {
				v.Set(name, fmt.Sprintf("%d", casted))
			}
		case []string:
			if len(casted) != 0 {
				for i, val := range casted {
					v.Set(fmt.Sprintf("%s.member.%d", name, i+1), val)
				}
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package aws

import (
	"encoding/xml"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"reflect"

	"github.com/crowdmob/goamz/aws"
)

type QueryClient struct {
	Client     *http.Client
	Region     string
	Endpoint   string
	Prefix     string
	Key        string
	Secret     string
	APIVersion string
}

func (c *QueryClient) Do(op, method, uri string, req, resp interface{}) error {
	v := url.Values{"Action": {op}, "Version": {c.APIVersion}}
	if err := loadValues(v, req); err != nil {
		return err
	}

	u, err := url.Parse(c.Endpoint + uri + "?" + v.Encode())
	if err != nil {
		return err
	}

	httpReq, err := http.NewRequest(method, u.String(), nil)
	if err != nil {
		return err
	}

	signer := aws.NewV4Signer(aws.Auth{
		AccessKey: c.Key,
		SecretKey: c.Secret,
	}, c.Prefix, aws.Region{Name: c.Region})
	signer.Sign(httpReq)

	httpResp, e := c.Client.Do(httpReq)
	if e != nil {
		return e
	}
	defer httpResp.Body.Close()

	b, err := ioutil.ReadAll(httpResp.Body)
	if err != nil {
		return err
	}

	if httpResp.StatusCode != 200 {
		return errors.New(string(b))
	}

	fmt.Println(string(b))

	return xml.Unmarshal(b, resp)
}

func loadValues(v url.Values, i interface{}) error {
	value := reflect.ValueOf(i)
	if value.Kind() == reflect.Ptr {
		value = value.Elem()
	}
	t := value.Type()
	for i := 0; i < value.NumField(); i++ {
		value := value.Field(i)
		name := t.Field(i).Tag.Get("xml")
		switch casted := value.Interface().(type) {
		case string:
			if casted != "" {
				v.Set(name, casted)
			}
		case bool:
			if casted {
				v.Set(name, "true")
			}
		case int64:
			if casted != 0 {
				v.Set(name, fmt.Sprintf("%d", casted))
			}
		case int:
			if casted != 0 {
				v.Set(name, fmt.Sprintf("%d", casted))
			}
		case []string:
			if len(casted) != 0 {
				for i, val := range casted {
					v.Set(fmt.Sprintf("%s.member.%d", name, i+1), val)
				}
			}
		}
	}
	return nil
}
<commit_msg>Fix error variable name.<commit_after>package aws

import (
	"encoding/xml"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"reflect"

	"github.com/crowdmob/goamz/aws"
)

type QueryClient struct {
	Client     *http.Client
	Region     string
	Endpoint   string
	Prefix     string
	Key        string
	Secret     string
	APIVersion string
}

func (c *QueryClient) Do(op, method, uri string, req, resp interface{}) error {
	v := url.Values{"Action": {op}, "Version": {c.APIVersion}}
	if err := loadValues(v, req); err != nil {
		return err
	}

	u, err := url.Parse(c.Endpoint + uri + "?" + v.Encode())
	if err != nil {
		return err
	}

	httpReq, err := http.NewRequest(method, u.String(), nil)
	if err != nil {
		return err
	}

	signer := aws.NewV4Signer(aws.Auth{
		AccessKey: c.Key,
		SecretKey: c.Secret,
	}, c.Prefix, aws.Region{Name: c.Region})
	signer.Sign(httpReq)

	httpResp, err := c.Client.Do(httpReq)
	if err != nil {
		return err
	}
	defer httpResp.Body.Close()

	b, err := ioutil.ReadAll(httpResp.Body)
	if err != nil {
		return err
	}

	if httpResp.StatusCode != 200 {
		return errors.New(string(b))
	}

	fmt.Println(string(b))

	return xml.Unmarshal(b, resp)
}

func loadValues(v url.Values, i interface{}) error {
	value := reflect.ValueOf(i)
	if value.Kind() == reflect.Ptr {
		value = value.Elem()
	}
	t := value.Type()
	for i := 0; i < value.NumField(); i++ {
		value := value.Field(i)
		name := t.Field(i).Tag.Get("xml")
		switch casted := value.Interface().(type) {
		case string:
			if casted != "" {
				v.Set(name, casted)
			}
		case bool:
			if casted {
				v.Set(name, "true")
			}
		case int64:
			if casted != 0 {
				v.Set(name, fmt.Sprintf("%d", casted))
			}
		case int:
			if casted != 0 {
				v.Set(name, fmt.Sprintf("%d", casted))
			}
		case []string:
			if len(casted) != 0 {
				for i, val := range casted {
					v.Set(fmt.Sprintf("%s.member.%d", name, i+1), val)
				}
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package axis

import (
	"time"

	"github.com/tomarus/chart/format"
	"github.com/tomarus/chart/image"
)

// Axis defines an axis (doh)
type Axis struct {
	position Position
	format   Formatter
	duration time.Duration
	grid     int
	ticks    int
	center   bool
}

// Formatter is the callback interface function used to format a label.
type Formatter func(value float64) string

// Liner is the callback interface function to draw a line.
// Any padding/margin offsets should be applied by the caller.
type Liner func(x1, y1, x2, y2 int)

// Position defines the position for the axis. Bottom, Top, Left or Right
type Position int

const (
	// Bottom defines an axis aligned to the bottom of the image.
	Bottom Position = iota

	// Left defines an axis aligned to the let of the image.
	// Only Bottom and Left are defined at the moment.
	Left
)

// New creates a new Axis on the specified position using the formatter.
func New(p Position, f Formatter) *Axis {
	return &Axis{
		position: p,
		format:   f,
	}
}

// NewSI creates a new Axis on the specified position using the default SI formatter.
func NewSI(p Position, base int) *Axis {
	return New(p, func(in float64) string {
		return format.SI(in, 1, float64(base), "", "", "")
	})
}

// NewTime creates a new Axis on the specified position using the default Time formatter.
// A timefmt is specified using the default Go Time format, e.g. 2006-01-02 15:04
func NewTime(p Position, timefmt string) *Axis {
	return New(p, func(in float64) string {
		return time.Unix(int64(in), 0).Format(timefmt)
	})
}

// Ticks sets the number of gridlines/labels or ticks for this axis.
// This configures an equally centered grid pattern for an axis.
// Use either one of Ticks() or Duration()
func (a *Axis) Ticks(n int) *Axis {
	a.ticks = n
	return a
}

// Duration sets the time period for the gridlines/labels or ticks for the axis.
// This configures a grid aligned to the nearest time unit.
// Use either one of Ticks() or Duration()
func (a *Axis) Duration(d time.Duration) *Axis {
	a.duration = d
	return a
}

// Grid displays a grid for this axis. By default it doesn't show a grid.
// n is the amount of gridlines to draw between axis ticks. If your axis
// spans 4 hours and n = 2 then a gridline will be drawn every 2 hours.
func (a *Axis) Grid(n int) *Axis {
	a.grid = n
	return a
}

// Center aligns the label in tne center of the grid instead of the start/end of grid.
func (a *Axis) Center() *Axis {
	a.center = true
	return a
}

// Draw renders the grid and labels.
// mx/my is the top-left start position, the margin (or offset).
// FIXME there are text-margin constants in this function which are probably dependent on the font and size used.
// It also depends a bit too much on the actual font/line/color drawing stuff.
func (a *Axis) Draw(img image.Image, w, h, mx, my int, min, max float64) {
	const col = "title2"

	switch a.position {
	case Bottom:
		off := 0 // grid line offset, TODO calculate from rounded time.Duration
		if a.duration > 0 {
			t := int(a.duration / time.Second)
			a.ticks = 1
			if t > 0 {
				a.ticks = int(max-min) / t
			}
		}
		if a.grid > 0 {
			t := a.ticks * a.grid
			o := w / t
			for dx := o; dx < w; dx += o {
				col := "grid"
				if dx/o%a.grid != 0 {
					col = "grid2"
				}
				img.Line(col, dx+mx+off, my, dx+mx+off, my+h)
			}
		}

		toff := 0 // text offset
		if a.center {
			toff = w / a.ticks / 2
		}
		for dx := (w / a.ticks) - off; dx < w+toff; dx += w / a.ticks {
			str := a.format(min + ((max-min)/float64(w))*(float64(dx)-float64(toff)))
			img.TextID("grid", col, "middle", image.GridRole, dx+mx+off-toff, my+h+14, str) // FIXME "14" (padding/offset)
		}
	case Left:
		if a.grid > 0 {
			t := a.ticks * a.grid
			o := h / t
			for dy := o; dy < h; dy += o {
				col := "grid"
				if dy/o%a.grid != 0 {
					col = "grid2"
				}
				img.Line(col, mx, dy+my, mx+w, dy+my)
			}
		}
		sc := a.Scales(h, min, max)
		i := 0
		// TODO if show or hide zero value option
		for dy := 0; dy <= h; dy += h / a.ticks {
			str := sc[i]
			i++
			img.TextID("ygrid", col, "end", image.GridRole, mx-4, dy+my+4, str) // FIXME "4" (padding/spacing)
		}
	}
}

// Scales creates and formats the Y-axis scale.
func (a *Axis) Scales(h int, min, max float64) []string {
	s := []string{}
	switch a.position {
	case Left:
		for dy := 0; dy <= h; dy += h / a.ticks {
			str := a.format(max - ((max-min)/float64(h))*float64(dy))
			s = append(s, str)
		}
	}
	return s
}
<commit_msg>Fix a rounding error.<commit_after>package axis

import (
	"math"
	"time"

	"github.com/tomarus/chart/format"
	"github.com/tomarus/chart/image"
)

// Axis defines an axis (doh)
type Axis struct {
	position Position
	format   Formatter
	duration time.Duration
	grid     int
	ticks    int
	center   bool
}

// Formatter is the callback interface function used to format a label.
type Formatter func(value float64) string

// Liner is the callback interface function to draw a line.
// Any padding/margin offsets should be applied by the caller.
type Liner func(x1, y1, x2, y2 int)

// Position defines the position for the axis. Bottom, Top, Left or Right
type Position int

const (
	// Bottom defines an axis aligned to the bottom of the image.
	Bottom Position = iota

	// Left defines an axis aligned to the let of the image.
	// Only Bottom and Left are defined at the moment.
	Left
)

// New creates a new Axis on the specified position using the formatter.
func New(p Position, f Formatter) *Axis {
	return &Axis{
		position: p,
		format:   f,
	}
}

// NewSI creates a new Axis on the specified position using the default SI formatter.
func NewSI(p Position, base int) *Axis {
	return New(p, func(in float64) string {
		return format.SI(in, 1, float64(base), "", "", "")
	})
}

// NewTime creates a new Axis on the specified position using the default Time formatter.
// A timefmt is specified using the default Go Time format, e.g. 2006-01-02 15:04
func NewTime(p Position, timefmt string) *Axis {
	return New(p, func(in float64) string {
		return time.Unix(int64(in), 0).Format(timefmt)
	})
}

// Ticks sets the number of gridlines/labels or ticks for this axis.
// This configures an equally centered grid pattern for an axis.
// Use either one of Ticks() or Duration()
func (a *Axis) Ticks(n int) *Axis {
	a.ticks = n
	return a
}

// Duration sets the time period for the gridlines/labels or ticks for the axis.
// This configures a grid aligned to the nearest time unit.
// Use either one of Ticks() or Duration()
func (a *Axis) Duration(d time.Duration) *Axis {
	a.duration = d
	return a
}

// Grid displays a grid for this axis. By default it doesn't show a grid.
// n is the amount of gridlines to draw between axis ticks. If your axis
// spans 4 hours and n = 2 then a gridline will be drawn every 2 hours.
func (a *Axis) Grid(n int) *Axis {
	a.grid = n
	return a
}

// Center aligns the label in tne center of the grid instead of the start/end of grid.
func (a *Axis) Center() *Axis {
	a.center = true
	return a
}

// Draw renders the grid and labels.
// mx/my is the top-left start position, the margin (or offset).
// FIXME there are text-margin constants in this function which are probably dependent on the font and size used.
// It also depends a bit too much on the actual font/line/color drawing stuff.
func (a *Axis) Draw(img image.Image, w, h, mx, my int, min, max float64) {
	const col = "title2"

	switch a.position {
	case Bottom:
		off := 0 // grid line offset, TODO calculate from rounded time.Duration
		if a.duration > 0 {
			t := int(a.duration / time.Second)
			a.ticks = 1
			if t > 0 {
				a.ticks = int(math.Round((max - min) / float64(t)))
			}
		}
		if a.grid > 0 {
			t := a.ticks * a.grid
			o := w / t
			for dx := o; dx < w; dx += o {
				col := "grid"
				if dx/o%a.grid != 0 {
					col = "grid2"
				}
				img.Line(col, dx+mx+off, my, dx+mx+off, my+h)
			}
		}

		toff := 0 // text offset
		if a.center {
			toff = w / a.ticks / 2
		}
		for dx := (w / a.ticks) - off; dx < w+toff; dx += w / a.ticks {
			str := a.format(min + ((max-min)/float64(w))*(float64(dx)-float64(toff)))
			img.TextID("grid", col, "middle", image.GridRole, dx+mx+off-toff, my+h+14, str) // FIXME "14" (padding/offset)
		}
	case Left:
		if a.grid > 0 {
			t := a.ticks * a.grid
			o := h / t
			for dy := o; dy < h; dy += o {
				col := "grid"
				if dy/o%a.grid != 0 {
					col = "grid2"
				}
				img.Line(col, mx, dy+my, mx+w, dy+my)
			}
		}
		sc := a.Scales(h, min, max)
		i := 0
		// TODO if show or hide zero value option
		for dy := 0; dy <= h; dy += h / a.ticks {
			str := sc[i]
			i++
			img.TextID("ygrid", col, "end", image.GridRole, mx-4, dy+my+4, str) // FIXME "4" (padding/spacing)
		}
	}
}

// Scales creates and formats the Y-axis scale.
func (a *Axis) Scales(h int, min, max float64) []string {
	s := []string{}
	switch a.position {
	case Left:
		for dy := 0; dy <= h; dy += h / a.ticks {
			str := a.format(max - ((max-min)/float64(h))*float64(dy))
			s = append(s, str)
		}
	}
	return s
}
<|endoftext|>