<commit_before>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package konfig

// RecognizedKustomizationFileNames is a list of file names
// that kustomize recognizes.
// To avoid ambiguity, a kustomization directory may not
// contain more than one match to this list.
func RecognizedKustomizationFileNames() []string {
	return []string{
		"kustomization.yaml",
		"kustomization.yml",
		"Kustomization",
	}
}

func DefaultKustomizationFileName() string {
	return RecognizedKustomizationFileNames()[0]
}

// IfApiMachineryElseKyaml returns true if executing the apimachinery code
// path, else we're executing the kyaml code paths.
func IfApiMachineryElseKyaml(s1, s2 string) string {
	if !FlagEnableKyamlDefaultValue {
		return s1
	}
	return s2
}

const (
	// FlagEnableKyamlDefaultValue is the default value for the --enable_kyaml
	// flag.  This value is also used in unit tests.  See provider.DepProvider.
	//
	// TODO(#3304): eliminate branching on this constant.
	// Details: https://github.com/kubernetes-sigs/kustomize/issues/3304
	//
	// All tests should pass for either true or false values
	// of this constant, without having to check its value.
	// In the cases where there's a different outcome, either decide
	// that the difference is acceptable, or make the difference go away.
	//
	// Historically, tests passed for enable_kyaml == false, i.e. using
	// apimachinery libs.  This doesn't mean the code was better, it just
	// means regression tests preserved those outcomes.
	FlagEnableKyamlDefaultValue = true

	// An environment variable to consult for kustomization
	// configuration data.  See:
	// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
	XdgConfigHomeEnv = "XDG_CONFIG_HOME"

	// Use this when XdgConfigHomeEnv not defined.
	XdgConfigHomeEnvDefault = ".config"

	// A program name, for use in help, finding the XDG_CONFIG_DIR, etc.
	ProgramName = "kustomize"

	// ConfigAnnoDomain is configuration-related annotation namespace.
	ConfigAnnoDomain = "config.kubernetes.io"

	// If a resource has this annotation, kustomize will drop it.
	IgnoredByKustomizeAnnotation = ConfigAnnoDomain + "/local-config"

	// Label key that indicates the resources are built from Kustomize
	ManagedbyLabelKey = "app.kubernetes.io/managed-by"

	// An environment variable to turn on/off adding the ManagedByLabelKey
	EnableManagedbyLabelEnv = "KUSTOMIZE_ENABLE_MANAGEDBY_LABEL"

	// Label key that indicates the resources are validated by a validator
	ValidatedByLabelKey = "validated-by"
)
<commit_msg>Set FlagEnableKyamlDefaultValue = false<commit_after>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package konfig

// RecognizedKustomizationFileNames is a list of file names
// that kustomize recognizes.
// To avoid ambiguity, a kustomization directory may not
// contain more than one match to this list.
func RecognizedKustomizationFileNames() []string {
	return []string{
		"kustomization.yaml",
		"kustomization.yml",
		"Kustomization",
	}
}

func DefaultKustomizationFileName() string {
	return RecognizedKustomizationFileNames()[0]
}

// IfApiMachineryElseKyaml returns true if executing the apimachinery code
// path, else we're executing the kyaml code paths.
func IfApiMachineryElseKyaml(s1, s2 string) string {
	if !FlagEnableKyamlDefaultValue {
		return s1
	}
	return s2
}

const (
	// FlagEnableKyamlDefaultValue is the default value for the --enable_kyaml
	// flag.  This value is also used in unit tests.  See provider.DepProvider.
	//
	// TODO(#3304): eliminate branching on this constant.
	// Details: https://github.com/kubernetes-sigs/kustomize/issues/3304
	//
	// All tests should pass for either true or false values
	// of this constant, without having to check its value.
	// In the cases where there's a different outcome, either decide
	// that the difference is acceptable, or make the difference go away.
	//
	// Historically, tests passed for enable_kyaml == false, i.e. using
	// apimachinery libs.  This doesn't mean the code was better, it just
	// means regression tests preserved those outcomes.
	FlagEnableKyamlDefaultValue = false

	// An environment variable to consult for kustomization
	// configuration data.  See:
	// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
	XdgConfigHomeEnv = "XDG_CONFIG_HOME"

	// Use this when XdgConfigHomeEnv not defined.
	XdgConfigHomeEnvDefault = ".config"

	// A program name, for use in help, finding the XDG_CONFIG_DIR, etc.
	ProgramName = "kustomize"

	// ConfigAnnoDomain is configuration-related annotation namespace.
	ConfigAnnoDomain = "config.kubernetes.io"

	// If a resource has this annotation, kustomize will drop it.
	IgnoredByKustomizeAnnotation = ConfigAnnoDomain + "/local-config"

	// Label key that indicates the resources are built from Kustomize
	ManagedbyLabelKey = "app.kubernetes.io/managed-by"

	// An environment variable to turn on/off adding the ManagedByLabelKey
	EnableManagedbyLabelEnv = "KUSTOMIZE_ENABLE_MANAGEDBY_LABEL"

	// Label key that indicates the resources are validated by a validator
	ValidatedByLabelKey = "validated-by"
)
<|endoftext|>


<commit_before>package response

import (
	"encoding/json"
)

type Error interface {
	Code() int
	Error() string
}

type ErrorResp struct {
	code int
	err  string
}

func WrapError(e error) *ErrorResp {
	if _, ok := e.(*ErrorResp); ok {
		return e.(*ErrorResp)
	}
	resp := &ErrorResp{
		err:  e.Error(),
		code: 500,
	}
	if _, ok := e.(Error); ok {
		resp.code = e.(Error).Code()
	}

	return resp
}

type TagDBError struct {
	Error string `json:"error"`
}

// graphite's http tagdb client requires a specific error format
func WrapErrorForTagDB(e error) *ErrorResp {
	b, err := json.Marshal(TagDBError{Error: e.Error()})
	if err != nil {
		return &ErrorResp{
			err:  "{\"error\": \"failed to encode error message\"}",
			code: 500,
		}
	}

	resp := &ErrorResp{
		err:  string(b),
		code: 500,
	}

	if _, ok := e.(Error); ok {
		resp.code = e.(Error).Code()
	}

	// 599 is max HTTP status code (but 512-599 are unassigned at the time of this writing)
	if resp.code > 599 {
		resp.code = 500
	}

	return resp
}

func NewError(code int, err string) *ErrorResp {
	return &ErrorResp{
		code: code,
		err:  err,
	}
}

func (r *ErrorResp) Error() string {
	return r.err
}

func (r *ErrorResp) Code() int {
	return r.code
}

func (r *ErrorResp) Close() {
	return
}

func (r *ErrorResp) Body() ([]byte, error) {
	return []byte(r.err), nil
}

func (r *ErrorResp) Headers() (headers map[string]string) {
	headers = map[string]string{"content-type": "text/plain"}
	return headers
}

var RequestCanceledErr = NewError(499, "request canceled")
<commit_msg>Fix both spots<commit_after>package response

import (
	"encoding/json"
)

type Error interface {
	Code() int
	Error() string
}

type ErrorResp struct {
	code int
	err  string
}

func WrapError(e error) *ErrorResp {
	if _, ok := e.(*ErrorResp); ok {
		return e.(*ErrorResp)
	}
	resp := &ErrorResp{
		err:  e.Error(),
		code: 500,
	}
	if _, ok := e.(Error); ok {
		resp.code = e.(Error).Code()
	}

	// 599 is max HTTP status code
	if resp.code > 599 {
		resp.code = 500
	}

	return resp
}

type TagDBError struct {
	Error string `json:"error"`
}

// graphite's http tagdb client requires a specific error format
func WrapErrorForTagDB(e error) *ErrorResp {
	b, err := json.Marshal(TagDBError{Error: e.Error()})
	if err != nil {
		return &ErrorResp{
			err:  "{\"error\": \"failed to encode error message\"}",
			code: 500,
		}
	}

	resp := &ErrorResp{
		err:  string(b),
		code: 500,
	}

	if _, ok := e.(Error); ok {
		resp.code = e.(Error).Code()
	}

	// 599 is max HTTP status code
	if resp.code > 599 {
		resp.code = 500
	}

	return resp
}

func NewError(code int, err string) *ErrorResp {
	return &ErrorResp{
		code: code,
		err:  err,
	}
}

func (r *ErrorResp) Error() string {
	return r.err
}

func (r *ErrorResp) Code() int {
	return r.code
}

func (r *ErrorResp) Close() {
	return
}

func (r *ErrorResp) Body() ([]byte, error) {
	return []byte(r.err), nil
}

func (r *ErrorResp) Headers() (headers map[string]string) {
	headers = map[string]string{"content-type": "text/plain"}
	return headers
}

var RequestCanceledErr = NewError(499, "request canceled")
<|endoftext|>


<commit_before>package server

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Version of IronFunctions
var Version = "0.0.78"

func handleVersion(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"version": Version})
}
<commit_msg>functions: 0.0.79 release [skip ci]<commit_after>package server

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// Version of IronFunctions
var Version = "0.0.79"

func handleVersion(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"version": Version})
}
<|endoftext|>


<commit_before>// Copyright 2012 tsuru 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 main

import (
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/api"
	"github.com/globocom/tsuru/api/auth"
	"github.com/globocom/tsuru/api/service/consumption"
	"github.com/globocom/tsuru/api/service/provision"
	"github.com/globocom/tsuru/db"
	"github.com/globocom/tsuru/log"
	stdlog "log"
	"log/syslog"
	"net/http"
	"os"
)

func fatal(err error) {
	fmt.Fprintln(os.Stderr, err)
	log.Fatal(err)
}

func main() {
	logger, err := syslog.NewLogger(syslog.LOG_INFO, stdlog.LstdFlags)
	if err != nil {
		stdlog.Fatal(err)
	}
	log.SetLogger(logger)
	configFile := flag.String("config", "/etc/tsuru/tsuru.conf", "tsuru config file")
	dry := flag.Bool("dry", false, "dry-run: does not start the server (for testing purpose)")
	flag.Parse()
	err = config.ReadConfigFile(*configFile)
	if err != nil {
		fatal(err)
	}
	connString, err := config.GetString("database:url")
	if err != nil {
		fatal(err)
	}
	dbName, err := config.GetString("database:name")
	if err != nil {
		fatal(err)
	}
	db.Session, err = db.Open(connString, dbName)
	if err != nil {
		fatal(err)
	}
	defer db.Session.Close()
	fmt.Printf("Connected to MongoDB server at %s.\n", connString)
	fmt.Printf("Using the database %q.\n\n", dbName)

	m := pat.New()

	m.Get("/services/instances", AuthorizationRequiredHandler(consumption.ServicesInstancesHandler))
	m.Post("/services/instances", AuthorizationRequiredHandler(consumption.CreateInstanceHandler))
	m.Put("/services/instances/:instance/:app", AuthorizationRequiredHandler(api.BindHandler))
	m.Del("/services/instances/:instance/:app", AuthorizationRequiredHandler(api.UnbindHandler))
	m.Del("/services/c/instances/:name", AuthorizationRequiredHandler(consumption.RemoveServiceInstanceHandler))
	m.Get("/services/instances/:instance/status", AuthorizationRequiredHandler(consumption.ServiceInstanceStatusHandler))

	m.Get("/services", AuthorizationRequiredHandler(provision.ServicesHandler))
	m.Post("/services", AuthorizationRequiredHandler(provision.CreateHandler))
	m.Put("/services", AuthorizationRequiredHandler(provision.UpdateHandler))
	m.Del("/services/:name", AuthorizationRequiredHandler(provision.DeleteHandler))
	m.Get("/services/:name", AuthorizationRequiredHandler(consumption.ServiceInfoHandler))
	m.Get("/services/c/:name/doc", AuthorizationRequiredHandler(consumption.Doc))
	m.Get("/services/:name/doc", AuthorizationRequiredHandler(provision.GetDocHandler))
	m.Put("/services/:name/doc", AuthorizationRequiredHandler(provision.AddDocHandler))
	m.Put("/services/:service/:team", AuthorizationRequiredHandler(provision.GrantAccessToTeamHandler))
	m.Del("/services/:service/:team", AuthorizationRequiredHandler(provision.RevokeAccessFromTeamHandler))

	m.Del("/apps/:name", AuthorizationRequiredHandler(api.AppDelete))
	m.Get("/apps/:name/repository/clone", Handler(api.CloneRepositoryHandler))
	m.Get("/apps/:name/avaliable", Handler(api.AppIsAvaliableHandler))
	m.Get("/apps/:name", AuthorizationRequiredHandler(api.AppInfo))
	m.Post("/apps/:name/run", AuthorizationRequiredHandler(api.RunCommand))
	m.Get("/apps/:name/restart", AuthorizationRequiredHandler(api.RestartHandler))
	m.Get("/apps/:name/env", AuthorizationRequiredHandler(api.GetEnv))
	m.Post("/apps/:name/env", AuthorizationRequiredHandler(api.SetEnv))
	m.Del("/apps/:name/env", AuthorizationRequiredHandler(api.UnsetEnv))
	m.Get("/apps", AuthorizationRequiredHandler(api.AppList))
	m.Post("/apps", AuthorizationRequiredHandler(api.CreateAppHandler))
	m.Put("/apps/:app/:team", AuthorizationRequiredHandler(api.GrantAccessToTeamHandler))
	m.Del("/apps/:app/:team", AuthorizationRequiredHandler(api.RevokeAccessFromTeamHandler))
	m.Get("/apps/:name/log", AuthorizationRequiredHandler(api.AppLog))
	m.Post("/apps/:name/log", Handler(api.AddLogHandler))

	m.Post("/users", Handler(auth.CreateUser))
	m.Post("/users/:email/tokens", Handler(auth.Login))
	m.Put("/users/password", AuthorizationRequiredHandler(auth.ChangePassword))
	m.Del("/users", AuthorizationRequiredHandler(auth.RemoveUser))
	m.Post("/users/keys", AuthorizationRequiredHandler(auth.AddKeyToUser))
	m.Del("/users/keys", AuthorizationRequiredHandler(auth.RemoveKeyFromUser))

	m.Get("/teams", AuthorizationRequiredHandler(auth.ListTeams))
	m.Post("/teams", AuthorizationRequiredHandler(auth.CreateTeam))
	m.Del("/teams/:name", AuthorizationRequiredHandler(auth.RemoveTeam))
	m.Put("/teams/:team/:user", AuthorizationRequiredHandler(auth.AddUserToTeam))
	m.Del("/teams/:team/:user", AuthorizationRequiredHandler(auth.RemoveUserFromTeam))

	if !*dry {
		listen, err := config.GetString("listen")
		if err != nil {
			fatal(err)
		}
		fmt.Printf("tsuru HTTP server listening at %s...\n", listen)
		fatal(http.ListenAndServe(listen, m))
	}
}
<commit_msg>api/webserver: initialize app.Provisioner on server start<commit_after>// Copyright 2012 tsuru 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 main

import (
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/api"
	"github.com/globocom/tsuru/api/auth"
	"github.com/globocom/tsuru/api/service/consumption"
	service_provision "github.com/globocom/tsuru/api/service/provision"
	"github.com/globocom/tsuru/app"
	"github.com/globocom/tsuru/db"
	"github.com/globocom/tsuru/log"
	"github.com/globocom/tsuru/provision"
	_ "github.com/globocom/tsuru/provision/juju"
	stdlog "log"
	"log/syslog"
	"net/http"
	"os"
)

func fatal(err error) {
	fmt.Fprintln(os.Stderr, err)
	log.Fatal(err)
}

func main() {
	logger, err := syslog.NewLogger(syslog.LOG_INFO, stdlog.LstdFlags)
	if err != nil {
		stdlog.Fatal(err)
	}
	log.SetLogger(logger)
	configFile := flag.String("config", "/etc/tsuru/tsuru.conf", "tsuru config file")
	dry := flag.Bool("dry", false, "dry-run: does not start the server (for testing purpose)")
	flag.Parse()
	err = config.ReadConfigFile(*configFile)
	if err != nil {
		fatal(err)
	}
	connString, err := config.GetString("database:url")
	if err != nil {
		fatal(err)
	}
	dbName, err := config.GetString("database:name")
	if err != nil {
		fatal(err)
	}
	db.Session, err = db.Open(connString, dbName)
	if err != nil {
		fatal(err)
	}
	defer db.Session.Close()
	fmt.Printf("Connected to MongoDB server at %s.\n", connString)
	fmt.Printf("Using the database %q.\n\n", dbName)

	m := pat.New()

	m.Get("/services/instances", AuthorizationRequiredHandler(consumption.ServicesInstancesHandler))
	m.Post("/services/instances", AuthorizationRequiredHandler(consumption.CreateInstanceHandler))
	m.Put("/services/instances/:instance/:app", AuthorizationRequiredHandler(api.BindHandler))
	m.Del("/services/instances/:instance/:app", AuthorizationRequiredHandler(api.UnbindHandler))
	m.Del("/services/c/instances/:name", AuthorizationRequiredHandler(consumption.RemoveServiceInstanceHandler))
	m.Get("/services/instances/:instance/status", AuthorizationRequiredHandler(consumption.ServiceInstanceStatusHandler))

	m.Get("/services", AuthorizationRequiredHandler(service_provision.ServicesHandler))
	m.Post("/services", AuthorizationRequiredHandler(service_provision.CreateHandler))
	m.Put("/services", AuthorizationRequiredHandler(service_provision.UpdateHandler))
	m.Del("/services/:name", AuthorizationRequiredHandler(service_provision.DeleteHandler))
	m.Get("/services/:name", AuthorizationRequiredHandler(consumption.ServiceInfoHandler))
	m.Get("/services/c/:name/doc", AuthorizationRequiredHandler(consumption.Doc))
	m.Get("/services/:name/doc", AuthorizationRequiredHandler(service_provision.GetDocHandler))
	m.Put("/services/:name/doc", AuthorizationRequiredHandler(service_provision.AddDocHandler))
	m.Put("/services/:service/:team", AuthorizationRequiredHandler(service_provision.GrantAccessToTeamHandler))
	m.Del("/services/:service/:team", AuthorizationRequiredHandler(service_provision.RevokeAccessFromTeamHandler))

	m.Del("/apps/:name", AuthorizationRequiredHandler(api.AppDelete))
	m.Get("/apps/:name/repository/clone", Handler(api.CloneRepositoryHandler))
	m.Get("/apps/:name/avaliable", Handler(api.AppIsAvaliableHandler))
	m.Get("/apps/:name", AuthorizationRequiredHandler(api.AppInfo))
	m.Post("/apps/:name/run", AuthorizationRequiredHandler(api.RunCommand))
	m.Get("/apps/:name/restart", AuthorizationRequiredHandler(api.RestartHandler))
	m.Get("/apps/:name/env", AuthorizationRequiredHandler(api.GetEnv))
	m.Post("/apps/:name/env", AuthorizationRequiredHandler(api.SetEnv))
	m.Del("/apps/:name/env", AuthorizationRequiredHandler(api.UnsetEnv))
	m.Get("/apps", AuthorizationRequiredHandler(api.AppList))
	m.Post("/apps", AuthorizationRequiredHandler(api.CreateAppHandler))
	m.Put("/apps/:app/:team", AuthorizationRequiredHandler(api.GrantAccessToTeamHandler))
	m.Del("/apps/:app/:team", AuthorizationRequiredHandler(api.RevokeAccessFromTeamHandler))
	m.Get("/apps/:name/log", AuthorizationRequiredHandler(api.AppLog))
	m.Post("/apps/:name/log", Handler(api.AddLogHandler))

	m.Post("/users", Handler(auth.CreateUser))
	m.Post("/users/:email/tokens", Handler(auth.Login))
	m.Put("/users/password", AuthorizationRequiredHandler(auth.ChangePassword))
	m.Del("/users", AuthorizationRequiredHandler(auth.RemoveUser))
	m.Post("/users/keys", AuthorizationRequiredHandler(auth.AddKeyToUser))
	m.Del("/users/keys", AuthorizationRequiredHandler(auth.RemoveKeyFromUser))

	m.Get("/teams", AuthorizationRequiredHandler(auth.ListTeams))
	m.Post("/teams", AuthorizationRequiredHandler(auth.CreateTeam))
	m.Del("/teams/:name", AuthorizationRequiredHandler(auth.RemoveTeam))
	m.Put("/teams/:team/:user", AuthorizationRequiredHandler(auth.AddUserToTeam))
	m.Del("/teams/:team/:user", AuthorizationRequiredHandler(auth.RemoveUserFromTeam))

	if !*dry {
		provisioner, err := config.GetString("provisioner")
		if err != nil {
			fmt.Printf("Warning: %q didn't declare a provisioner, using default provisioner.\n", configFile)
			provisioner = "juju"
		}
		app.Provisioner, err = provision.Get(provisioner)
		if err != nil {
			fatal(err)
		}
		fmt.Printf("Using %q provisioner.\n\n", provisioner)

		listen, err := config.GetString("listen")
		if err != nil {
			fatal(err)
		}
		fmt.Printf("tsuru HTTP server listening at %s...\n", listen)
		fatal(http.ListenAndServe(listen, m))
	}
}
<|endoftext|>


<commit_before>package chart

import (
	"bufio"
	"bytes"
	"testing"
	"time"

	"github.com/tomarus/chart/svg"
)

func TestChart(t *testing.T) {
	var out bytes.Buffer
	w := bufio.NewWriter(&out)

	opts := &Options{
		Title:  "Test Title",
		Image:  svg.New(),
		Size:   "small",
		Scheme: "random",
		Theme:  "light",
		Start:  uint64(time.Now().AddDate(0, 0, -1).Unix()),
		End:    uint64(time.Now().Unix()),
		Xdiv:   12,
		Ydiv:   5,
		W:      w,
	}

	// test sizes

	c, err := NewChart(opts)
	if err != nil {
		t.Fatal(err)
	}
	if c.width != 720 {
		t.Fatal("width should be 720")
	}

	opts.Size = "big"
	c, _ = NewChart(opts)
	if c.width != 1440 {
		t.Fatal("width should be 1440")
	}

	opts.Width = 320
	opts.Height = 240
	c, _ = NewChart(opts)
	if c.width != 320 || c.height != 240 {
		t.Fatal("expected width/ehgith 320x240")
	}

	// test palette

	opts.Width = 0
	opts.Height = 0
	opts.Size = "auto"
	opts.Scheme = ""
	c, _ = NewChart(opts)
	if c.palette.GetHexColor("background") != "#fff" {
		t.Fatal("default scheme should be white")
	}

	// test data

	c.AddData("area", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12})
	if c.width != 12 {
		// A width of 12px is actually unviewable
		t.Errorf("Expected width of 10, got %d", c.width)
	}
	c.Render()

	c, _ = NewChart(opts)
	err = c.Render()
	if err == nil {
		t.Fatal("expected error no data available")
	}

	c, _ = NewChart(opts)
	c.AddData("area", []float64{1, 2, 3, 4, 5, 6})
	err = c.Render()
	if err == nil {
		t.Fatal("expected error xdiv <= datalen")
	}

	opts.Width = 720
	opts.Height = 540
	c, _ = NewChart(opts)
	c.AddData("area", []float64{1, 2, 3, 4, 5, 6})
	err = c.Render()
	if err != nil {
		t.Fatalf("unexpected error %v", err)
	}

	// t.Log(out.String())
}
<commit_msg>Test rendering png image.<commit_after>package chart

import (
	"bufio"
	"bytes"
	"testing"
	"time"

	"github.com/tomarus/chart/png"
	"github.com/tomarus/chart/svg"
)

func TestChart(t *testing.T) {
	var out bytes.Buffer
	w := bufio.NewWriter(&out)

	opts := &Options{
		Title:  "Test Title",
		Image:  svg.New(),
		Size:   "small",
		Scheme: "random",
		Theme:  "light",
		Start:  uint64(time.Now().AddDate(0, 0, -1).Unix()),
		End:    uint64(time.Now().Unix()),
		Xdiv:   12,
		Ydiv:   5,
		W:      w,
	}

	// test sizes

	c, err := NewChart(opts)
	if err != nil {
		t.Fatal(err)
	}
	if c.width != 720 {
		t.Fatal("width should be 720")
	}

	opts.Size = "big"
	c, _ = NewChart(opts)
	if c.width != 1440 {
		t.Fatal("width should be 1440")
	}

	opts.Width = 320
	opts.Height = 240
	c, _ = NewChart(opts)
	if c.width != 320 || c.height != 240 {
		t.Fatal("expected width/ehgith 320x240")
	}

	// test palette

	opts.Width = 0
	opts.Height = 0
	opts.Size = "auto"
	opts.Scheme = ""
	c, _ = NewChart(opts)
	if c.palette.GetHexColor("background") != "#fff" {
		t.Fatal("default scheme should be white")
	}

	// test data

	c.AddData("area", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12})
	if c.width != 12 {
		// A width of 12px is actually unviewable
		t.Errorf("Expected width of 10, got %d", c.width)
	}
	c.Render()

	c, _ = NewChart(opts)
	err = c.Render()
	if err == nil {
		t.Fatal("expected error no data available")
	}

	c, _ = NewChart(opts)
	c.AddData("area", []float64{1, 2, 3, 4, 5, 6})
	err = c.Render()
	if err == nil {
		t.Fatal("expected error xdiv <= datalen")
	}

	opts.Width = 720
	opts.Height = 540
	c, _ = NewChart(opts)
	c.AddData("area", []float64{1, 2, 3, 4, 5, 6})
	err = c.Render()
	if err != nil {
		t.Fatalf("unexpected error %v", err)
	}
	// TODO: actually test svg output somehow

	opts.Image = png.New()
	c, _ = NewChart(opts)
	c.AddData("area", []float64{1, 2, 3, 4, 5, 6})
	err = c.Render()
	if err != nil {
		t.Fatalf("unexpected error %v", err)
	}
	// TODO: actually test png output somehow
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Mute Communications Ltd.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cipher

import (
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
)

// SHA1 computes the SHA1 hash of the given buffer.
// In Mute SHA1 is only used for tokens.
func SHA1(buffer []byte) []byte {
	hash := sha1.New()
	hash.Write(buffer)
	return hash.Sum(make([]byte, 0, sha1.Size))
}

// SHA256 computes the SHA256 hash of the given buffer.
// In Mute SHA256 is only used for hash chain operations.
func SHA256(buffer []byte) []byte {
	hash := sha256.New()
	hash.Write(buffer)
	return hash.Sum(make([]byte, 0, sha256.Size))
}

// SHA512 computes the SHA512 hash of the given buffer.
// In Mute SHA512 is used for everything except tokens and hash chain
// operations. For example, key material is hashed with SHA512 and message
// authentication uses SHA512.
func SHA512(buffer []byte) []byte {
	hash := sha512.New()
	hash.Write(buffer)
	return hash.Sum(make([]byte, 0, sha512.Size))
}
<commit_msg>cipher: simplify implementation of SHA helpers<commit_after>// Copyright (c) 2015 Mute Communications Ltd.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cipher

import (
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
)

// SHA1 computes the SHA1 hash of the given buffer.
// In Mute SHA1 is only used for tokens.
func SHA1(buffer []byte) []byte {
	hash := sha1.Sum(buffer)
	return hash[:]
}

// SHA256 computes the SHA256 hash of the given buffer.
// In Mute SHA256 is only used for hash chain operations.
func SHA256(buffer []byte) []byte {
	hash := sha256.Sum256(buffer)
	return hash[:]
}

// SHA512 computes the SHA512 hash of the given buffer.
// In Mute SHA512 is used for everything except tokens and hash chain
// operations. For example, key material is hashed with SHA512 and message
// authentication uses SHA512.
func SHA512(buffer []byte) []byte {
	hash := sha512.Sum512(buffer)
	return hash[:]
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"compress/gzip"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"time"

	cfg "github.com/flynn/flynn/cli/config"
	"github.com/flynn/flynn/pkg/random"
	"github.com/flynn/flynn/pkg/tufconfig"
	"github.com/flynn/flynn/pkg/tufutil"
	"github.com/flynn/flynn/pkg/version"
	tuf "github.com/flynn/go-tuf/client"
	"github.com/kardianos/osext"
	"gopkg.in/inconshreveable/go-update.v0"
)

const upcktimePath = "cktime"

var updateDir = filepath.Join(cfg.Dir(), "update")
var updater = &Updater{}

func runUpdate() error {
	if version.Dev() {
		return errors.New("Dev builds don't support auto-updates")
	}
	return updater.update()
}

type Updater struct{}

func (u *Updater) backgroundRun() {
	if u == nil {
		return
	}
	if !u.wantUpdate() {
		return
	}
	self, err := osext.Executable()
	if err != nil {
		// fail update, couldn't figure out path to self
		return
	}
	// TODO(titanous): logger isn't on Windows. Replace with proper error reports.
	l := exec.Command("logger", "-tflynn")
	c := exec.Command(self, "update")
	if w, err := l.StdinPipe(); err == nil && l.Start() == nil {
		c.Stdout = w
		c.Stderr = w
	}
	c.Start()
}

func (u *Updater) wantUpdate() bool {
	path := filepath.Join(updateDir, upcktimePath)
	if version.Dev() || readTime(path).After(time.Now()) {
		return false
	}
	wait := 12*time.Hour + randDuration(8*time.Hour)
	return writeTime(path, time.Now().Add(wait))
}

func (u *Updater) update() error {
	up := update.New()
	if err := up.CanUpdate(); err != nil {
		return err
	}

	if err := os.MkdirAll(updateDir, 0755); err != nil {
		return err
	}
	local, err := tuf.FileLocalStore(filepath.Join(updateDir, "tuf.db"))
	if err != nil {
		return err
	}
	plat := fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH)
	opts := &tuf.HTTPRemoteOptions{
		UserAgent: fmt.Sprintf("flynn-cli/%s %s", version.String(), plat),
		Retries:   tufutil.DefaultHTTPRetries,
	}
	remote, err := tuf.HTTPRemoteStore(tufconfig.Repository, opts)
	if err != nil {
		return err
	}
	client := tuf.NewClient(local, remote)
	if err := u.updateTUFClient(client); err != nil {
		return err
	}

	name := fmt.Sprintf("/flynn-%s.gz", plat)

	latestVersion, err := tufutil.GetVersion(client, name)
	if err != nil {
		return err
	}
	if latestVersion == version.String() {
		return nil
	}

	bin := &tufBuffer{}
	if err := client.Download(name, bin); err != nil {
		return err
	}
	gr, err := gzip.NewReader(bin)
	if err != nil {
		return err
	}

	err, errRecover := up.FromStream(gr)
	if errRecover != nil {
		return fmt.Errorf("update and recovery errors: %q %q", err, errRecover)
	}
	if err != nil {
		return err
	}
	log.Printf("Updated %s -> %s.", version.String(), latestVersion)
	return nil
}

// updateTUFClient updates the given client, initializing and re-running the
// update if ErrNoRootKeys is returned.
func (u *Updater) updateTUFClient(client *tuf.Client) error {
	_, err := client.Update()
	if err == nil || tuf.IsLatestSnapshot(err) {
		return nil
	}
	if err == tuf.ErrNoRootKeys {
		if err := client.Init(tufconfig.RootKeys, len(tufconfig.RootKeys)); err != nil {
			return err
		}
		return u.updateTUFClient(client)
	}
	return err
}

// returns a random duration in [0,n).
func randDuration(n time.Duration) time.Duration {
	return time.Duration(random.Math.Int63n(int64(n)))
}

func readTime(path string) time.Time {
	p, err := ioutil.ReadFile(path)
	if os.IsNotExist(err) {
		return time.Time{}
	}
	if err != nil {
		return time.Now().Add(1000 * time.Hour)
	}
	t, err := time.Parse(time.RFC3339, string(p))
	if err != nil {
		return time.Now().Add(1000 * time.Hour)
	}
	return t
}

func writeTime(path string, t time.Time) bool {
	return ioutil.WriteFile(path, []byte(t.Format(time.RFC3339)), 0644) == nil
}

type tufBuffer struct {
	bytes.Buffer
}

func (b *tufBuffer) Delete() error {
	b.Reset()
	return nil
}
<commit_msg>cli: Fix update version check<commit_after>package main

import (
	"bytes"
	"compress/gzip"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"time"

	cfg "github.com/flynn/flynn/cli/config"
	"github.com/flynn/flynn/pkg/random"
	"github.com/flynn/flynn/pkg/tufconfig"
	"github.com/flynn/flynn/pkg/tufutil"
	"github.com/flynn/flynn/pkg/version"
	tuf "github.com/flynn/go-tuf/client"
	"github.com/kardianos/osext"
	"gopkg.in/inconshreveable/go-update.v0"
)

const upcktimePath = "cktime"

var updateDir = filepath.Join(cfg.Dir(), "update")
var updater = &Updater{}

func runUpdate() error {
	if version.Dev() {
		return errors.New("Dev builds don't support auto-updates")
	}
	return updater.update()
}

type Updater struct{}

func (u *Updater) backgroundRun() {
	if u == nil {
		return
	}
	if !u.wantUpdate() {
		return
	}
	self, err := osext.Executable()
	if err != nil {
		// fail update, couldn't figure out path to self
		return
	}
	// TODO(titanous): logger isn't on Windows. Replace with proper error reports.
	l := exec.Command("logger", "-tflynn")
	c := exec.Command(self, "update")
	if w, err := l.StdinPipe(); err == nil && l.Start() == nil {
		c.Stdout = w
		c.Stderr = w
	}
	c.Start()
}

func (u *Updater) wantUpdate() bool {
	path := filepath.Join(updateDir, upcktimePath)
	if version.Dev() || readTime(path).After(time.Now()) {
		return false
	}
	wait := 12*time.Hour + randDuration(8*time.Hour)
	return writeTime(path, time.Now().Add(wait))
}

func (u *Updater) update() error {
	up := update.New()
	if err := up.CanUpdate(); err != nil {
		return err
	}

	if err := os.MkdirAll(updateDir, 0755); err != nil {
		return err
	}
	local, err := tuf.FileLocalStore(filepath.Join(updateDir, "tuf.db"))
	if err != nil {
		return err
	}
	plat := fmt.Sprintf("%s-%s", runtime.GOOS, runtime.GOARCH)
	opts := &tuf.HTTPRemoteOptions{
		UserAgent: fmt.Sprintf("flynn-cli/%s %s", version.String(), plat),
		Retries:   tufutil.DefaultHTTPRetries,
	}
	remote, err := tuf.HTTPRemoteStore(tufconfig.Repository, opts)
	if err != nil {
		return err
	}
	client := tuf.NewClient(local, remote)
	if err := u.updateTUFClient(client); err != nil {
		return err
	}

	name := fmt.Sprintf("/flynn-%s.gz", plat)

	latestVersion, err := tufutil.GetVersion(client, name)
	if err != nil {
		return err
	}
	if latestVersion == version.Release() {
		return nil
	}

	bin := &tufBuffer{}
	if err := client.Download(name, bin); err != nil {
		return err
	}
	gr, err := gzip.NewReader(bin)
	if err != nil {
		return err
	}

	err, errRecover := up.FromStream(gr)
	if errRecover != nil {
		return fmt.Errorf("update and recovery errors: %q %q", err, errRecover)
	}
	if err != nil {
		return err
	}
	log.Printf("Updated %s -> %s.", version.Release(), latestVersion)
	return nil
}

// updateTUFClient updates the given client, initializing and re-running the
// update if ErrNoRootKeys is returned.
func (u *Updater) updateTUFClient(client *tuf.Client) error {
	_, err := client.Update()
	if err == nil || tuf.IsLatestSnapshot(err) {
		return nil
	}
	if err == tuf.ErrNoRootKeys {
		if err := client.Init(tufconfig.RootKeys, len(tufconfig.RootKeys)); err != nil {
			return err
		}
		return u.updateTUFClient(client)
	}
	return err
}

// returns a random duration in [0,n).
func randDuration(n time.Duration) time.Duration {
	return time.Duration(random.Math.Int63n(int64(n)))
}

func readTime(path string) time.Time {
	p, err := ioutil.ReadFile(path)
	if os.IsNotExist(err) {
		return time.Time{}
	}
	if err != nil {
		return time.Now().Add(1000 * time.Hour)
	}
	t, err := time.Parse(time.RFC3339, string(p))
	if err != nil {
		return time.Now().Add(1000 * time.Hour)
	}
	return t
}

func writeTime(path string, t time.Time) bool {
	return ioutil.WriteFile(path, []byte(t.Format(time.RFC3339)), 0644) == nil
}

type tufBuffer struct {
	bytes.Buffer
}

func (b *tufBuffer) Delete() error {
	b.Reset()
	return nil
}
<|endoftext|>


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

/*
Package client provides clients for accessing the various
externally-facing Cockroach database endpoints.

KV Client

The KV client is a fully-featured client of Cockroach's key-value
database. It provides a simple, synchronous interface well-suited to
parallel updates and queries.

The simplest way to use the client is through the Call method. Call
synchronously invokes the method and returns the reply and an
error. The example below shows a get and a put.

  kv := client.NewKV(client.NewHTTPSender("localhost:8080", tlsConfig), clock)

  getResp := &proto.GetResponse{}
  if err := kv.Call(proto.Get, proto.GetArgs(proto.Key("a")), getResp); err != nil {
    log.Fatal(err)
  }
  putResp := &proto.PutResponse{}
  if _, err := kv.Call(proto.Put, proto.PutArgs(proto.Key("b"), getResp.Value.Bytes), putResp) err != nil {
    log.Fatal(err)
  }

The API is synchronous, but accommodates efficient parallel updates
and queries using the Prepare method. An arbitrary number of Prepare
invocations are followed up with a call to Flush. Until the Flush,
requests are buffered locally in anticipation of being sent to
Cockroach as part of a batch. The Flush batches prepared calls and
sends them together. Note however that API calls which are buffered
and sent together are not guaranteed to have atomic semantics. A
transaction must be used to guarantee atomicity. A simple example of
using the API which does two scans in parallel and then sends a
sequence of puts in parallel:

  kv := client.NewKV(client.NewHTTPSender("localhost:8080", tlsConfig), clock)

  acResp, xzResp := &proto.ScanResponse{}, &proto.ScanResponse{}
  kv.Prepare(proto.Scan, proto.ScanArgs(proto.Key("a"), proto.Key("c").Next()), acResp)
  kv.Prepare(proto.Scan, proto.ScanArgs(proto.Key("x"), proto.Key("z").Next()), xzResp)

  // Flush sends both scans in parallel and returns first error or nil.
  if err := kv.Flush(); err != nil {
    log.Fatal(err)
  }

  // Append maximum value from "a"-"c" to all values from "x"-"z".
  max := []byte(nil)
  for _, keyVal := range acResp.Rows {
    if bytes.Compare(max, keyVal.Value.Bytes) < 0 {
      max = keyVal.Value.Bytes
    }
  }
  for keyVal := range xzResp.Rows {
    putReq := proto.PutArgs(keyVal.Key, bytes.Join([][]byte{keyVal.Value.Bytes, max}, []byte(nil)))
    kv.Prepare(proto.Put, putReq, &proto.PutReponse{})
  }

  // Flush all puts for parallel execution.
  if _, err := kv.Flush(); err != nil {
    log.Fatal(err)
  }

Transactions are supported through the RunTransaction() method, which
takes a retryable function, itself composed of the same simple mix of
API calls typical of a non-transactional operation. Within the context
of the RunTransaction call, all method invocations are transparently
given necessary transactional details, and conflicts are handled with
backoff/retry loops and transaction restarts as necessary. An example
of using transactions with parallel writes:

  kv := client.NewKV(client.NewHTTPSender("localhost:8080", tlsConfig), clock)

  opts := client.TransactionOptions{Name: "test", Isolation: proto.SERIALIZABLE}
  err := kv.RunTransaction(opts, func(txn *client.KV) error {
    for i := 0; i < 100; i++ {
      key := proto.Key(fmt.Sprintf("testkey-%02d", i))
      txn.Prepare(proto.Put, proto.PutArgs(key, []byte("test value")), &proto.PutResponse{})
    }

    // Note that the KV client is flushed automatically on transaction
    // commit. Invoking Flush after individual API methods is only
    // required if the result needs to be received to take conditional
    // action.
    return nil
  })
  if err != nil {
    log.Fatal(err)
  }

Note that with Cockroach's lock-free transactions, clients should
expect retries as a matter of course. This is why the transaction
functionality is exposed through a retryable function. The retryable
function should have no side effects which are not idempotent.

Transactions should endeavor to write using KV.Prepare calls. This
allows writes to the same range to be batched together. In cases where
the entire transaction affects only a single range, transactions can
commit in a single round trip.
*/
package client
<commit_msg>Using nil as default clock argument<commit_after>// Copyright 2014 The Cockroach Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License. See the AUTHORS file
// for names of contributors.
//
// Author: Spencer Kimball (spencer.kimball@gmail.com)

/*
Package client provides clients for accessing the various
externally-facing Cockroach database endpoints.

KV Client

The KV client is a fully-featured client of Cockroach's key-value
database. It provides a simple, synchronous interface well-suited to
parallel updates and queries.

The simplest way to use the client is through the Call method. Call
synchronously invokes the method and returns the reply and an
error. The example below shows a get and a put.

  kv := client.NewKV(client.NewHTTPSender("localhost:8080", tlsConfig), nil)

  getResp := &proto.GetResponse{}
  if err := kv.Call(proto.Get, proto.GetArgs(proto.Key("a")), getResp); err != nil {
    log.Fatal(err)
  }
  putResp := &proto.PutResponse{}
  if _, err := kv.Call(proto.Put, proto.PutArgs(proto.Key("b"), getResp.Value.Bytes), putResp) err != nil {
    log.Fatal(err)
  }

The API is synchronous, but accommodates efficient parallel updates
and queries using the Prepare method. An arbitrary number of Prepare
invocations are followed up with a call to Flush. Until the Flush,
requests are buffered locally in anticipation of being sent to
Cockroach as part of a batch. The Flush batches prepared calls and
sends them together. Note however that API calls which are buffered
and sent together are not guaranteed to have atomic semantics. A
transaction must be used to guarantee atomicity. A simple example of
using the API which does two scans in parallel and then sends a
sequence of puts in parallel:

  kv := client.NewKV(client.NewHTTPSender("localhost:8080", tlsConfig), nil)

  acResp, xzResp := &proto.ScanResponse{}, &proto.ScanResponse{}
  kv.Prepare(proto.Scan, proto.ScanArgs(proto.Key("a"), proto.Key("c").Next()), acResp)
  kv.Prepare(proto.Scan, proto.ScanArgs(proto.Key("x"), proto.Key("z").Next()), xzResp)

  // Flush sends both scans in parallel and returns first error or nil.
  if err := kv.Flush(); err != nil {
    log.Fatal(err)
  }

  // Append maximum value from "a"-"c" to all values from "x"-"z".
  max := []byte(nil)
  for _, keyVal := range acResp.Rows {
    if bytes.Compare(max, keyVal.Value.Bytes) < 0 {
      max = keyVal.Value.Bytes
    }
  }
  for keyVal := range xzResp.Rows {
    putReq := proto.PutArgs(keyVal.Key, bytes.Join([][]byte{keyVal.Value.Bytes, max}, []byte(nil)))
    kv.Prepare(proto.Put, putReq, &proto.PutReponse{})
  }

  // Flush all puts for parallel execution.
  if _, err := kv.Flush(); err != nil {
    log.Fatal(err)
  }

Transactions are supported through the RunTransaction() method, which
takes a retryable function, itself composed of the same simple mix of
API calls typical of a non-transactional operation. Within the context
of the RunTransaction call, all method invocations are transparently
given necessary transactional details, and conflicts are handled with
backoff/retry loops and transaction restarts as necessary. An example
of using transactions with parallel writes:

  kv := client.NewKV(client.NewHTTPSender("localhost:8080", tlsConfig), nil)

  opts := client.TransactionOptions{Name: "test", Isolation: proto.SERIALIZABLE}
  err := kv.RunTransaction(opts, func(txn *client.KV) error {
    for i := 0; i < 100; i++ {
      key := proto.Key(fmt.Sprintf("testkey-%02d", i))
      txn.Prepare(proto.Put, proto.PutArgs(key, []byte("test value")), &proto.PutResponse{})
    }

    // Note that the KV client is flushed automatically on transaction
    // commit. Invoking Flush after individual API methods is only
    // required if the result needs to be received to take conditional
    // action.
    return nil
  })
  if err != nil {
    log.Fatal(err)
  }

Note that with Cockroach's lock-free transactions, clients should
expect retries as a matter of course. This is why the transaction
functionality is exposed through a retryable function. The retryable
function should have no side effects which are not idempotent.

Transactions should endeavor to write using KV.Prepare calls. This
allows writes to the same range to be batched together. In cases where
the entire transaction affects only a single range, transactions can
commit in a single round trip.
*/
package client
<|endoftext|>


<commit_before>package lxd

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"
	"sync"

	"github.com/gorilla/websocket"
	"gopkg.in/macaroon-bakery.v2/bakery"
	"gopkg.in/macaroon-bakery.v2/httpbakery"

	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/logger"

	neturl "net/url"
)

// ProtocolLXD represents a LXD API server
type ProtocolLXD struct {
	server      *api.Server
	chConnected chan struct{}

	eventListeners     []*EventListener
	eventListenersLock sync.Mutex

	http            *http.Client
	httpCertificate string
	httpHost        string
	httpUnixPath    string
	httpProtocol    string
	httpUserAgent   string

	bakeryClient         *httpbakery.Client
	bakeryInteractor     []httpbakery.Interactor
	requireAuthenticated bool

	clusterTarget string
	project       string
}

// Disconnect gets rid of any background goroutines
func (r *ProtocolLXD) Disconnect() {
	if r.chConnected != nil {
		close(r.chConnected)
	}
}

// GetConnectionInfo returns the basic connection information used to interact with the server
func (r *ProtocolLXD) GetConnectionInfo() (*ConnectionInfo, error) {
	info := ConnectionInfo{}
	info.Certificate = r.httpCertificate
	info.Protocol = "lxd"
	info.URL = r.httpHost
	info.SocketPath = r.httpUnixPath
	info.Project = r.project
	if info.Project == "" {
		info.Project = "default"
	}

	urls := []string{}
	if r.httpProtocol == "https" {
		urls = append(urls, r.httpHost)
	}

	if r.server != nil && len(r.server.Environment.Addresses) > 0 {
		for _, addr := range r.server.Environment.Addresses {
			if strings.HasPrefix(addr, ":") {
				continue
			}

			url := fmt.Sprintf("https://%s", addr)
			if !shared.StringInSlice(url, urls) {
				urls = append(urls, url)
			}
		}
	}
	info.Addresses = urls

	return &info, nil
}

// GetHTTPClient returns the http client used for the connection. This can be used to set custom http options.
func (r *ProtocolLXD) GetHTTPClient() (*http.Client, error) {
	if r.http == nil {
		return nil, fmt.Errorf("HTTP client isn't set, bad connection")
	}

	return r.http, nil
}

// Do performs a Request, using macaroon authentication if set.
func (r *ProtocolLXD) do(req *http.Request) (*http.Response, error) {
	if r.bakeryClient != nil {
		r.addMacaroonHeaders(req)
		return r.bakeryClient.Do(req)
	}

	return r.http.Do(req)
}

func (r *ProtocolLXD) addMacaroonHeaders(req *http.Request) {
	req.Header.Set(httpbakery.BakeryProtocolHeader, fmt.Sprint(bakery.LatestVersion))

	for _, cookie := range r.http.Jar.Cookies(req.URL) {
		req.AddCookie(cookie)
	}
}

// RequireAuthenticated sets whether we expect to be authenticated with the server
func (r *ProtocolLXD) RequireAuthenticated(authenticated bool) {
	r.requireAuthenticated = authenticated
}

// RawQuery allows directly querying the LXD API
//
// This should only be used by internal LXD tools.
func (r *ProtocolLXD) RawQuery(method string, path string, data interface{}, ETag string) (*api.Response, string, error) {
	// Generate the URL
	url := fmt.Sprintf("%s%s", r.httpHost, path)

	return r.rawQuery(method, url, data, ETag)
}

// RawWebsocket allows directly connection to LXD API websockets
//
// This should only be used by internal LXD tools.
func (r *ProtocolLXD) RawWebsocket(path string) (*websocket.Conn, error) {
	return r.websocket(path)
}

// RawOperation allows direct querying of a LXD API endpoint returning
// background operations.
func (r *ProtocolLXD) RawOperation(method string, path string, data interface{}, ETag string) (Operation, string, error) {
	return r.queryOperation(method, path, data, ETag)
}

// Internal functions
func lxdParseResponse(resp *http.Response) (*api.Response, string, error) {
	// Get the ETag
	etag := resp.Header.Get("ETag")

	// Decode the response
	decoder := json.NewDecoder(resp.Body)
	response := api.Response{}

	err := decoder.Decode(&response)
	if err != nil {
		// Check the return value for a cleaner error
		if resp.StatusCode != http.StatusOK {
			return nil, "", fmt.Errorf("Failed to fetch %s: %s", resp.Request.URL.String(), resp.Status)
		}

		return nil, "", err
	}

	// Handle errors
	if response.Type == api.ErrorResponse {
		return nil, "", fmt.Errorf(response.Error)
	}

	return &response, etag, nil
}

func (r *ProtocolLXD) rawQuery(method string, url string, data interface{}, ETag string) (*api.Response, string, error) {
	var req *http.Request
	var err error

	// Log the request
	logger.Debug("Sending request to LXD",
		"method", method,
		"url", url,
		"etag", ETag,
	)

	// Get a new HTTP request setup
	if data != nil {
		switch data := data.(type) {
		case io.Reader:
			// Some data to be sent along with the request
			req, err = http.NewRequest(method, url, data)
			if err != nil {
				return nil, "", err
			}

			// Set the encoding accordingly
			req.Header.Set("Content-Type", "application/octet-stream")
		default:
			// Encode the provided data
			buf := bytes.Buffer{}
			err := json.NewEncoder(&buf).Encode(data)
			if err != nil {
				return nil, "", err
			}

			// Some data to be sent along with the request
			// Use a reader since the request body needs to be seekable
			req, err = http.NewRequest(method, url, bytes.NewReader(buf.Bytes()))
			if err != nil {
				return nil, "", err
			}

			// Set the encoding accordingly
			req.Header.Set("Content-Type", "application/json")

			// Log the data
			logger.Debugf(logger.Pretty(data))
		}
	} else {
		// No data to be sent along with the request
		req, err = http.NewRequest(method, url, nil)
		if err != nil {
			return nil, "", err
		}
	}

	// Set the user agent
	if r.httpUserAgent != "" {
		req.Header.Set("User-Agent", r.httpUserAgent)
	}

	// Set the ETag
	if ETag != "" {
		req.Header.Set("If-Match", ETag)
	}

	// Set the authentication header
	if r.requireAuthenticated {
		req.Header.Set("X-LXD-authenticated", "true")
	}

	// Send the request
	resp, err := r.do(req)
	if err != nil {
		return nil, "", err
	}
	defer resp.Body.Close()

	return lxdParseResponse(resp)
}

func (r *ProtocolLXD) setQueryAttributes(uri string) (string, error) {
	// Parse the full URI
	fields, err := neturl.Parse(uri)
	if err != nil {
		return "", err
	}

	// Extract query fields and update for cluster targeting or project
	values := fields.Query()
	if r.clusterTarget != "" {
		if values.Get("target") == "" {
			values.Set("target", r.clusterTarget)
		}
	}

	if r.project != "" {
		if values.Get("project") == "" {
			values.Set("project", r.project)
		}
	}
	fields.RawQuery = values.Encode()

	return fields.String(), nil
}

func (r *ProtocolLXD) query(method string, path string, data interface{}, ETag string) (*api.Response, string, error) {
	// Generate the URL
	url := fmt.Sprintf("%s/1.0%s", r.httpHost, path)

	// Add project/target
	url, err := r.setQueryAttributes(url)
	if err != nil {
		return nil, "", err
	}

	// Run the actual query
	return r.rawQuery(method, url, data, ETag)
}

func (r *ProtocolLXD) queryStruct(method string, path string, data interface{}, ETag string, target interface{}) (string, error) {
	resp, etag, err := r.query(method, path, data, ETag)
	if err != nil {
		return "", err
	}

	err = resp.MetadataAsStruct(&target)
	if err != nil {
		return "", err
	}

	// Log the data
	logger.Debugf("Got response struct from LXD")
	logger.Debugf(logger.Pretty(target))

	return etag, nil
}

func (r *ProtocolLXD) queryOperation(method string, path string, data interface{}, ETag string) (Operation, string, error) {
	// Attempt to setup an early event listener
	listener, err := r.GetEvents()
	if err != nil {
		listener = nil
	}

	// Send the query
	resp, etag, err := r.query(method, path, data, ETag)
	if err != nil {
		if listener != nil {
			listener.Disconnect()
		}

		return nil, "", err
	}

	// Get to the operation
	respOperation, err := resp.MetadataAsOperation()
	if err != nil {
		if listener != nil {
			listener.Disconnect()
		}

		return nil, "", err
	}

	// Setup an Operation wrapper
	op := operation{
		Operation: *respOperation,
		r:         r,
		listener:  listener,
		chActive:  make(chan bool),
	}

	// Log the data
	logger.Debugf("Got operation from LXD")
	logger.Debugf(logger.Pretty(op.Operation))

	return &op, etag, nil
}

func (r *ProtocolLXD) rawWebsocket(url string) (*websocket.Conn, error) {
	// Grab the http transport handler
	httpTransport := r.http.Transport.(*http.Transport)

	// Setup a new websocket dialer based on it
	dialer := websocket.Dialer{
		NetDial:         httpTransport.Dial,
		TLSClientConfig: httpTransport.TLSClientConfig,
		Proxy:           httpTransport.Proxy,
	}

	// Set the user agent
	headers := http.Header{}
	if r.httpUserAgent != "" {
		headers.Set("User-Agent", r.httpUserAgent)
	}

	if r.requireAuthenticated {
		headers.Set("X-LXD-authenticated", "true")
	}

	// Set macaroon headers if needed
	if r.bakeryClient != nil {
		u, err := neturl.Parse(r.httpHost) // use the http url, not the ws one
		if err != nil {
			return nil, err
		}
		req := &http.Request{URL: u, Header: headers}
		r.addMacaroonHeaders(req)
	}

	// Establish the connection
	conn, _, err := dialer.Dial(url, headers)
	if err != nil {
		return nil, err
	}

	// Log the data
	logger.Debugf("Connected to the websocket: %v", url)

	return conn, err
}

func (r *ProtocolLXD) websocket(path string) (*websocket.Conn, error) {
	// Generate the URL
	var url string
	if strings.HasPrefix(r.httpHost, "https://") {
		url = fmt.Sprintf("wss://%s/1.0%s", strings.TrimPrefix(r.httpHost, "https://"), path)
	} else {
		url = fmt.Sprintf("ws://%s/1.0%s", strings.TrimPrefix(r.httpHost, "http://"), path)
	}

	return r.rawWebsocket(url)
}

func (r *ProtocolLXD) setupBakeryClient() {
	r.bakeryClient = httpbakery.NewClient()
	r.bakeryClient.Client = r.http
	if r.bakeryInteractor != nil {
		for _, interactor := range r.bakeryInteractor {
			r.bakeryClient.AddInteractor(interactor)
		}
	}
}
<commit_msg>client/lxd: Don't treat % chars from LXD server response as placeholders in lxdParseResponse<commit_after>package lxd

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"strings"
	"sync"

	"github.com/gorilla/websocket"
	"gopkg.in/macaroon-bakery.v2/bakery"
	"gopkg.in/macaroon-bakery.v2/httpbakery"

	"github.com/lxc/lxd/shared"
	"github.com/lxc/lxd/shared/api"
	"github.com/lxc/lxd/shared/logger"

	neturl "net/url"
)

// ProtocolLXD represents a LXD API server
type ProtocolLXD struct {
	server      *api.Server
	chConnected chan struct{}

	eventListeners     []*EventListener
	eventListenersLock sync.Mutex

	http            *http.Client
	httpCertificate string
	httpHost        string
	httpUnixPath    string
	httpProtocol    string
	httpUserAgent   string

	bakeryClient         *httpbakery.Client
	bakeryInteractor     []httpbakery.Interactor
	requireAuthenticated bool

	clusterTarget string
	project       string
}

// Disconnect gets rid of any background goroutines
func (r *ProtocolLXD) Disconnect() {
	if r.chConnected != nil {
		close(r.chConnected)
	}
}

// GetConnectionInfo returns the basic connection information used to interact with the server
func (r *ProtocolLXD) GetConnectionInfo() (*ConnectionInfo, error) {
	info := ConnectionInfo{}
	info.Certificate = r.httpCertificate
	info.Protocol = "lxd"
	info.URL = r.httpHost
	info.SocketPath = r.httpUnixPath
	info.Project = r.project
	if info.Project == "" {
		info.Project = "default"
	}

	urls := []string{}
	if r.httpProtocol == "https" {
		urls = append(urls, r.httpHost)
	}

	if r.server != nil && len(r.server.Environment.Addresses) > 0 {
		for _, addr := range r.server.Environment.Addresses {
			if strings.HasPrefix(addr, ":") {
				continue
			}

			url := fmt.Sprintf("https://%s", addr)
			if !shared.StringInSlice(url, urls) {
				urls = append(urls, url)
			}
		}
	}
	info.Addresses = urls

	return &info, nil
}

// GetHTTPClient returns the http client used for the connection. This can be used to set custom http options.
func (r *ProtocolLXD) GetHTTPClient() (*http.Client, error) {
	if r.http == nil {
		return nil, fmt.Errorf("HTTP client isn't set, bad connection")
	}

	return r.http, nil
}

// Do performs a Request, using macaroon authentication if set.
func (r *ProtocolLXD) do(req *http.Request) (*http.Response, error) {
	if r.bakeryClient != nil {
		r.addMacaroonHeaders(req)
		return r.bakeryClient.Do(req)
	}

	return r.http.Do(req)
}

func (r *ProtocolLXD) addMacaroonHeaders(req *http.Request) {
	req.Header.Set(httpbakery.BakeryProtocolHeader, fmt.Sprint(bakery.LatestVersion))

	for _, cookie := range r.http.Jar.Cookies(req.URL) {
		req.AddCookie(cookie)
	}
}

// RequireAuthenticated sets whether we expect to be authenticated with the server
func (r *ProtocolLXD) RequireAuthenticated(authenticated bool) {
	r.requireAuthenticated = authenticated
}

// RawQuery allows directly querying the LXD API
//
// This should only be used by internal LXD tools.
func (r *ProtocolLXD) RawQuery(method string, path string, data interface{}, ETag string) (*api.Response, string, error) {
	// Generate the URL
	url := fmt.Sprintf("%s%s", r.httpHost, path)

	return r.rawQuery(method, url, data, ETag)
}

// RawWebsocket allows directly connection to LXD API websockets
//
// This should only be used by internal LXD tools.
func (r *ProtocolLXD) RawWebsocket(path string) (*websocket.Conn, error) {
	return r.websocket(path)
}

// RawOperation allows direct querying of a LXD API endpoint returning
// background operations.
func (r *ProtocolLXD) RawOperation(method string, path string, data interface{}, ETag string) (Operation, string, error) {
	return r.queryOperation(method, path, data, ETag)
}

// Internal functions
func lxdParseResponse(resp *http.Response) (*api.Response, string, error) {
	// Get the ETag
	etag := resp.Header.Get("ETag")

	// Decode the response
	decoder := json.NewDecoder(resp.Body)
	response := api.Response{}

	err := decoder.Decode(&response)
	if err != nil {
		// Check the return value for a cleaner error
		if resp.StatusCode != http.StatusOK {
			return nil, "", fmt.Errorf("Failed to fetch %s: %s", resp.Request.URL.String(), resp.Status)
		}

		return nil, "", err
	}

	// Handle errors
	if response.Type == api.ErrorResponse {
		return nil, "", errors.New(response.Error)
	}

	return &response, etag, nil
}

func (r *ProtocolLXD) rawQuery(method string, url string, data interface{}, ETag string) (*api.Response, string, error) {
	var req *http.Request
	var err error

	// Log the request
	logger.Debug("Sending request to LXD",
		"method", method,
		"url", url,
		"etag", ETag,
	)

	// Get a new HTTP request setup
	if data != nil {
		switch data := data.(type) {
		case io.Reader:
			// Some data to be sent along with the request
			req, err = http.NewRequest(method, url, data)
			if err != nil {
				return nil, "", err
			}

			// Set the encoding accordingly
			req.Header.Set("Content-Type", "application/octet-stream")
		default:
			// Encode the provided data
			buf := bytes.Buffer{}
			err := json.NewEncoder(&buf).Encode(data)
			if err != nil {
				return nil, "", err
			}

			// Some data to be sent along with the request
			// Use a reader since the request body needs to be seekable
			req, err = http.NewRequest(method, url, bytes.NewReader(buf.Bytes()))
			if err != nil {
				return nil, "", err
			}

			// Set the encoding accordingly
			req.Header.Set("Content-Type", "application/json")

			// Log the data
			logger.Debugf(logger.Pretty(data))
		}
	} else {
		// No data to be sent along with the request
		req, err = http.NewRequest(method, url, nil)
		if err != nil {
			return nil, "", err
		}
	}

	// Set the user agent
	if r.httpUserAgent != "" {
		req.Header.Set("User-Agent", r.httpUserAgent)
	}

	// Set the ETag
	if ETag != "" {
		req.Header.Set("If-Match", ETag)
	}

	// Set the authentication header
	if r.requireAuthenticated {
		req.Header.Set("X-LXD-authenticated", "true")
	}

	// Send the request
	resp, err := r.do(req)
	if err != nil {
		return nil, "", err
	}
	defer resp.Body.Close()

	return lxdParseResponse(resp)
}

func (r *ProtocolLXD) setQueryAttributes(uri string) (string, error) {
	// Parse the full URI
	fields, err := neturl.Parse(uri)
	if err != nil {
		return "", err
	}

	// Extract query fields and update for cluster targeting or project
	values := fields.Query()
	if r.clusterTarget != "" {
		if values.Get("target") == "" {
			values.Set("target", r.clusterTarget)
		}
	}

	if r.project != "" {
		if values.Get("project") == "" {
			values.Set("project", r.project)
		}
	}
	fields.RawQuery = values.Encode()

	return fields.String(), nil
}

func (r *ProtocolLXD) query(method string, path string, data interface{}, ETag string) (*api.Response, string, error) {
	// Generate the URL
	url := fmt.Sprintf("%s/1.0%s", r.httpHost, path)

	// Add project/target
	url, err := r.setQueryAttributes(url)
	if err != nil {
		return nil, "", err
	}

	// Run the actual query
	return r.rawQuery(method, url, data, ETag)
}

func (r *ProtocolLXD) queryStruct(method string, path string, data interface{}, ETag string, target interface{}) (string, error) {
	resp, etag, err := r.query(method, path, data, ETag)
	if err != nil {
		return "", err
	}

	err = resp.MetadataAsStruct(&target)
	if err != nil {
		return "", err
	}

	// Log the data
	logger.Debugf("Got response struct from LXD")
	logger.Debugf(logger.Pretty(target))

	return etag, nil
}

func (r *ProtocolLXD) queryOperation(method string, path string, data interface{}, ETag string) (Operation, string, error) {
	// Attempt to setup an early event listener
	listener, err := r.GetEvents()
	if err != nil {
		listener = nil
	}

	// Send the query
	resp, etag, err := r.query(method, path, data, ETag)
	if err != nil {
		if listener != nil {
			listener.Disconnect()
		}

		return nil, "", err
	}

	// Get to the operation
	respOperation, err := resp.MetadataAsOperation()
	if err != nil {
		if listener != nil {
			listener.Disconnect()
		}

		return nil, "", err
	}

	// Setup an Operation wrapper
	op := operation{
		Operation: *respOperation,
		r:         r,
		listener:  listener,
		chActive:  make(chan bool),
	}

	// Log the data
	logger.Debugf("Got operation from LXD")
	logger.Debugf(logger.Pretty(op.Operation))

	return &op, etag, nil
}

func (r *ProtocolLXD) rawWebsocket(url string) (*websocket.Conn, error) {
	// Grab the http transport handler
	httpTransport := r.http.Transport.(*http.Transport)

	// Setup a new websocket dialer based on it
	dialer := websocket.Dialer{
		NetDial:         httpTransport.Dial,
		TLSClientConfig: httpTransport.TLSClientConfig,
		Proxy:           httpTransport.Proxy,
	}

	// Set the user agent
	headers := http.Header{}
	if r.httpUserAgent != "" {
		headers.Set("User-Agent", r.httpUserAgent)
	}

	if r.requireAuthenticated {
		headers.Set("X-LXD-authenticated", "true")
	}

	// Set macaroon headers if needed
	if r.bakeryClient != nil {
		u, err := neturl.Parse(r.httpHost) // use the http url, not the ws one
		if err != nil {
			return nil, err
		}
		req := &http.Request{URL: u, Header: headers}
		r.addMacaroonHeaders(req)
	}

	// Establish the connection
	conn, _, err := dialer.Dial(url, headers)
	if err != nil {
		return nil, err
	}

	// Log the data
	logger.Debugf("Connected to the websocket: %v", url)

	return conn, err
}

func (r *ProtocolLXD) websocket(path string) (*websocket.Conn, error) {
	// Generate the URL
	var url string
	if strings.HasPrefix(r.httpHost, "https://") {
		url = fmt.Sprintf("wss://%s/1.0%s", strings.TrimPrefix(r.httpHost, "https://"), path)
	} else {
		url = fmt.Sprintf("ws://%s/1.0%s", strings.TrimPrefix(r.httpHost, "http://"), path)
	}

	return r.rawWebsocket(url)
}

func (r *ProtocolLXD) setupBakeryClient() {
	r.bakeryClient = httpbakery.NewClient()
	r.bakeryClient.Client = r.http
	if r.bakeryInteractor != nil {
		for _, interactor := range r.bakeryInteractor {
			r.bakeryClient.AddInteractor(interactor)
		}
	}
}
<|endoftext|>


<commit_before>package client

import (
	"fmt"
	"github.com/coreos/fleet/schema"
	"github.com/juju/errgo"
	execPkg "os/exec"
	"strings"
)

const (
	FLEETCTL            = "fleetctl"
	ENDPOINT_OPTION     = "--endpoint"
	ENDPOINT_VALUE      = "http://172.17.42.1:4001"
	ETCD_PREFIX_OPTION  = "--etcd-key-prefix"
	DEFAULT_ETCD_PREFIX = "/_coreos.com/fleet/"
)

type ClientCLI struct {
	etcdPeer   string
	driver     string
	etcdPrefix string
}

func NewClientCLI() FleetClient {
	return NewClientCLIWithPeer(ENDPOINT_VALUE)
}

func getDriver() string {
	driver := ""
	cmd := execPkg.Command(FLEETCTL, "--version")
	output, err := exec(cmd)
	if err != nil {
		return ""
	}

	if strings.Contains(output, "0.10") {
		fmt.Printf("Adding driver option for version 0.10\n")
		driver = "--driver=etcd"
	} else {
		fmt.Printf("Not adding driver option: %s\n", output)
	}
	return driver

}

func NewClientCLIWithPeer(etcdPeer string) FleetClient {
	return &ClientCLI{
		etcdPeer:   etcdPeer,
		driver:     getDriver(),
		etcdPrefix: DEFAULT_ETCD_PREFIX,
	}
}

func NewClientCLIWithPeerAndPrefix(etcdPeer, etcdPrefix string) FleetClient {
	client := NewClientCLIWithPeer(etcdPeer)
	if etcdPrefix == "" {
		etcdPrefix = DEFAULT_ETCD_PREFIX
	}
	return &ClientCLI{
		etcdPeer:   etcdPeer,
		driver:     getDriver(),
		etcdPrefix: etcdPrefix,
	}

	return client
}

func args(extras []string, required ...string) []string {
	return append(required, extras...)
}

func (this *ClientCLI) Submit(filePath ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(filePath, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "submit")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(filePath, ENDPOINT_OPTION, this.etcdPeer, "submit")...)
	}
	output, err := exec(cmd)
	if err != nil {
		fmt.Printf("Error in submit: %s %s\n", err, output)
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Unit(name string) (*schema.Unit, error) {
	return nil, fmt.Errorf("Method not implemented: ClientCLI.Unit")
}

func (this *ClientCLI) Start(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "start", "--no-block=true")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "start", "--no-block=true")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Stop(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "stop", "--no-block=true")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "stop", "--no-block=true")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Load(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "load", "--no-block=true")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "load", "--no-block=true")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Destroy(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "destroy")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "destroy")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}
<commit_msg>updated the driver flag to be required<commit_after>package client

import (
	"fmt"
	"github.com/coreos/fleet/schema"
	"github.com/juju/errgo"
	execPkg "os/exec"
	"strings"
)

const (
	FLEETCTL            = "fleetctl"
	ENDPOINT_OPTION     = "--endpoint"
	ENDPOINT_VALUE      = "http://172.17.42.1:4001"
	ETCD_PREFIX_OPTION  = "--etcd-key-prefix"
	DEFAULT_ETCD_PREFIX = "/_coreos.com/fleet/"
)

type ClientCLI struct {
	etcdPeer   string
	driver     string
	etcdPrefix string
}

func NewClientCLI() FleetClient {
	return NewClientCLIWithPeer(ENDPOINT_VALUE)
}

func NewClientCLIWithPeer(etcdPeer string) FleetClient {
	return &ClientCLI{
		etcdPeer:   etcdPeer,
		driver:     "--driver=etcd",
		etcdPrefix: DEFAULT_ETCD_PREFIX,
	}
}

func NewClientCLIWithPeerAndPrefix(etcdPeer, etcdPrefix string) FleetClient {
	client := NewClientCLIWithPeer(etcdPeer)
	if etcdPrefix == "" {
		etcdPrefix = DEFAULT_ETCD_PREFIX
	}
	return &ClientCLI{
		etcdPeer:   etcdPeer,
		driver:     getDriver(),
		etcdPrefix: etcdPrefix,
	}

	return client
}

func args(extras []string, required ...string) []string {
	return append(required, extras...)
}

func (this *ClientCLI) Submit(filePath ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(filePath, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "submit")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(filePath, ENDPOINT_OPTION, this.etcdPeer, "submit")...)
	}
	output, err := exec(cmd)
	if err != nil {
		fmt.Printf("Error in submit: %s %s\n", err, output)
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Unit(name string) (*schema.Unit, error) {
	return nil, fmt.Errorf("Method not implemented: ClientCLI.Unit")
}

func (this *ClientCLI) Start(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "start", "--no-block=true")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "start", "--no-block=true")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Stop(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "stop", "--no-block=true")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "stop", "--no-block=true")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Load(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "load", "--no-block=true")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "load", "--no-block=true")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Destroy(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "destroy")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "destroy")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}
<|endoftext|>


<commit_before>package modbusone

import (
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"time"
)

//RTUClient implements Client/Master side logic for RTU over a SerialContext to
//be used by a ProtocalHandler
type RTUClient struct {
	com                  SerialContext
	packetReader         io.Reader
	SlaveID              byte
	serverProcessingTime time.Duration
	actions              chan rtuAction
}

//RTUClient is a Server
var _ Server = &RTUClient{}

//NewRTUCLient create a new client communicating over SerialContext with the
//give slaveID as default.
func NewRTUCLient(com SerialContext, slaveID byte) *RTUClient {
	r := RTUClient{
		com:                  com,
		packetReader:         NewRTUPacketReader(com, true, StartingSerialBufferSide),
		SlaveID:              slaveID,
		serverProcessingTime: time.Second,
		actions:              make(chan rtuAction),
	}
	return &r
}

//SetServerProcessingTime sets the time to wait for a server response, the total
//wait time also includes the time needed for data transmission
func (c *RTUClient) SetServerProcessingTime(t time.Duration) {
	c.serverProcessingTime = t
}

//GetTransactionTimeOut returns the total time to wait for a transaction
//(server response) to time out, given the expected length of RTU packets.
//This function is also used internally to calculate timeout.
func (c *RTUClient) GetTransactionTimeOut(reqLen, ansLen int) time.Duration {
	l := reqLen + ansLen
	return c.com.BytesDelay(l) + c.serverProcessingTime
}

type rtuAction struct {
	t       actionType
	data    RTU
	errChan chan<- error
}

//ErrServerTimeOut is the time out error for StartTransaction
var ErrServerTimeOut = errors.New("server timed out")

type actionType int

const (
	start actionType = 1
	read  actionType = 2
)

func (a actionType) String() string {
	switch a {
	case start:
		return "start"
	case read:
		return "read"
	}
	return fmt.Sprintf("actionType %d", a)
}

//Serve serves RTUClient side handlers, must close SerialContext after error is
//returned, to clean up.
func (c *RTUClient) Serve(handler ProtocalHandler) error {
	delay := c.com.MinDelay()

	var ioerr error //irrecoverable io errors
	var readerr error
	go func() {
		//Reader loop that always ready to received data. This make sure that read
		//data is always new(ish), to dump data out that is received during an
		//unexpected time.
		rb := make([]byte, MaxRTUSize)
		for {
			n, err := c.packetReader.Read(rb)
			if err != nil {
				readerr = err
				debugf("RTUClient read err:%v\n", err)
			}
			r := RTU(rb[:n])
			debugf("RTUClient read packet:%v\n", hex.EncodeToString(r))
			c.actions <- rtuAction{read, r, nil}
		}
	}()

	hasError := func() bool {
		return ioerr != nil || readerr != nil
	}
	getError := func() error {
		if ioerr != nil {
			return ioerr
		}
		return readerr
	}
	sendError := func(ec chan<- error, err error) error {
		if ec != nil {
			ec <- err
		}
		return err
	}
	sendGetError := func(ec chan<- error) error {
		return sendError(ec, getError())
	}

	for {
		act, ok := <-c.actions
		if !ok {
			debugf("RTUClient actions closed\n")
			return getError()
		}
		if act.t != start {
			debugf("RTUClient drop unexpected action:%s\n", act.t)
			continue
		}
		ap := act.data.fastGetPDU()
		afc := ap.GetFunctionCode()
		if afc.IsWriteToServer() {
			data, err := handler.OnRead(ap)
			if err != nil {
				sendError(act.errChan, err)
				continue
			}
			act.data = MakeRTU(act.data[0], ap.MakeWriteRequest(data))
			ap = act.data.fastGetPDU()
		}
		time.Sleep(delay)
		_, ioerr = c.com.Write(act.data)
		if hasError() {
			return sendGetError(act.errChan)
		}
		if act.data[0] == 0 {
			continue // do not wait for read on multicast
		}
		timeOutChan := time.After(c.GetTransactionTimeOut(len(act.data), MaxRTUSize))

	READ_LOOP:
		for {
		SELECT:
			select {
			case <-timeOutChan:
				sendError(act.errChan, ErrServerTimeOut)
				break READ_LOOP
			case react, ok := <-c.actions:
				if !ok {
					debugf("RTUClient actions closed\n")
					return sendGetError(act.errChan)
				}
				if react.t != read {
					ioerr = fmt.Errorf("unexpected action:%s", react.t)
					return sendGetError(act.errChan)
				}
				if react.data[0] != act.data[0] {
					debugf("RTUClient unexpected slaveId:%v in %v\n", act.data[0], hex.EncodeToString(react.data))
					break SELECT
				}
				rp, err := react.data.GetPDU()
				if err != nil {
					sendError(act.errChan, err)
					break READ_LOOP
				}
				hasErr, fc := rp.GetFunctionCode().SeparateError()
				if hasErr && fc == afc {
					handler.OnError(ap, rp)
					sendError(act.errChan, fmt.Errorf("server reply with exception:%v", hex.EncodeToString(rp)))
					break READ_LOOP
				}
				if !MatchPDU(act.data.fastGetPDU(), rp) {
					sendError(act.errChan, fmt.Errorf("unexpected reply:%v", hex.EncodeToString(rp)))
					break READ_LOOP
				}
				if !afc.IsWriteToServer() {
					//read from server, write here
					bs, err := rp.GetReplyValues()
					if err != nil {
						sendError(act.errChan, err)
						break READ_LOOP
					}
					err = handler.OnWrite(ap, bs)
					sendError(act.errChan, err)
					break READ_LOOP
				}
				sendError(act.errChan, nil)
				break READ_LOOP
			}
		}
	}
}

//DoTransaction starts a transaction, and returns a channel that returns an error
//or nil, with the default slaveID.
//
//DoTransaction is blocking.
//
//For read from server, the PDU is sent as is (after been warped up in RTU)
//For write to server, the data part given will be ignored, and filled in by data from handler.
func (c *RTUClient) DoTransaction(req PDU) error {
	errChan := make(chan error)
	c.StartTransactionToServer(c.SlaveID, req, errChan)
	return <-errChan
}

//StartTransactionToServer starts a transaction, with a custom slaveID.
//errChan is required and usable, an error is set is the transaction failed, or
//nil for success.
//
//StartTransactionToServer is not blocking.
//
//For read from server, the PDU is sent as is (after been warped up in RTU)
//For write to server, the data part given will be ignored, and filled in by data from handler.
func (c *RTUClient) StartTransactionToServer(slaveID byte, req PDU, errChan chan error) {
	c.actions <- rtuAction{start, MakeRTU(slaveID, req), errChan}
}

//RTUTransactionStarter is an interface implemented by RTUClient.
type RTUTransactionStarter interface {
	StartTransactionToServer(slaveID byte, req PDU, errChan chan error)
}

//DoTransactions runs the reqs transactions in order.
//If any error is encountered, it returns early and reports the index number and
//error message
func DoTransactions(c RTUTransactionStarter, slaveID byte, reqs []PDU) (int, error) {
	errChan := make(chan error)
	for i, r := range reqs {
		c.StartTransactionToServer(slaveID, r, errChan)
		err := <-errChan
		if err != nil {
			return i, err
		}
	}
	return len(reqs), nil
}

//MakePDURequestHeaders generates the list of PDU request headers by spliting quantity
//into allowed sizes.
//Returns an error if quantitiy is out of range.
func MakePDURequestHeaders(fc FunctionCode, address uint16, quantity uint16, appendTO []PDU) ([]PDU, error) {
	if uint(address)+uint(quantity) > uint(fc.MaxRange()) {
		return nil, fmt.Errorf("quantitiy is out of range")
	}
	r := fc.MaxPerPacket()
	q := r
	for quantity > 0 {
		if quantity < r {
			q = quantity
		}
		pdu, err := fc.MakeRequestHeader(address, q)
		if err != nil {
			return nil, err
		}
		appendTO = append(appendTO, pdu)
		quantity -= q
	}
	return appendTO, nil
}
<commit_msg>fix address not increasing<commit_after>package modbusone

import (
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"time"
)

//RTUClient implements Client/Master side logic for RTU over a SerialContext to
//be used by a ProtocalHandler
type RTUClient struct {
	com                  SerialContext
	packetReader         io.Reader
	SlaveID              byte
	serverProcessingTime time.Duration
	actions              chan rtuAction
}

//RTUClient is a Server
var _ Server = &RTUClient{}

//NewRTUCLient create a new client communicating over SerialContext with the
//give slaveID as default.
func NewRTUCLient(com SerialContext, slaveID byte) *RTUClient {
	r := RTUClient{
		com:                  com,
		packetReader:         NewRTUPacketReader(com, true, StartingSerialBufferSide),
		SlaveID:              slaveID,
		serverProcessingTime: time.Second,
		actions:              make(chan rtuAction),
	}
	return &r
}

//SetServerProcessingTime sets the time to wait for a server response, the total
//wait time also includes the time needed for data transmission
func (c *RTUClient) SetServerProcessingTime(t time.Duration) {
	c.serverProcessingTime = t
}

//GetTransactionTimeOut returns the total time to wait for a transaction
//(server response) to time out, given the expected length of RTU packets.
//This function is also used internally to calculate timeout.
func (c *RTUClient) GetTransactionTimeOut(reqLen, ansLen int) time.Duration {
	l := reqLen + ansLen
	return c.com.BytesDelay(l) + c.serverProcessingTime
}

type rtuAction struct {
	t       actionType
	data    RTU
	errChan chan<- error
}

//ErrServerTimeOut is the time out error for StartTransaction
var ErrServerTimeOut = errors.New("server timed out")

type actionType int

const (
	start actionType = 1
	read  actionType = 2
)

func (a actionType) String() string {
	switch a {
	case start:
		return "start"
	case read:
		return "read"
	}
	return fmt.Sprintf("actionType %d", a)
}

//Serve serves RTUClient side handlers, must close SerialContext after error is
//returned, to clean up.
func (c *RTUClient) Serve(handler ProtocalHandler) error {
	delay := c.com.MinDelay()

	var ioerr error //irrecoverable io errors
	var readerr error
	go func() {
		//Reader loop that always ready to received data. This make sure that read
		//data is always new(ish), to dump data out that is received during an
		//unexpected time.
		rb := make([]byte, MaxRTUSize)
		for {
			n, err := c.packetReader.Read(rb)
			if err != nil {
				readerr = err
				debugf("RTUClient read err:%v\n", err)
			}
			r := RTU(rb[:n])
			debugf("RTUClient read packet:%v\n", hex.EncodeToString(r))
			c.actions <- rtuAction{read, r, nil}
		}
	}()

	hasError := func() bool {
		return ioerr != nil || readerr != nil
	}
	getError := func() error {
		if ioerr != nil {
			return ioerr
		}
		return readerr
	}
	sendError := func(ec chan<- error, err error) error {
		if ec != nil {
			ec <- err
		}
		return err
	}
	sendGetError := func(ec chan<- error) error {
		return sendError(ec, getError())
	}

	for {
		act, ok := <-c.actions
		if !ok {
			debugf("RTUClient actions closed\n")
			return getError()
		}
		if act.t != start {
			debugf("RTUClient drop unexpected action:%s\n", act.t)
			continue
		}
		ap := act.data.fastGetPDU()
		afc := ap.GetFunctionCode()
		if afc.IsWriteToServer() {
			data, err := handler.OnRead(ap)
			if err != nil {
				sendError(act.errChan, err)
				continue
			}
			act.data = MakeRTU(act.data[0], ap.MakeWriteRequest(data))
			ap = act.data.fastGetPDU()
		}
		time.Sleep(delay)
		_, ioerr = c.com.Write(act.data)
		if hasError() {
			return sendGetError(act.errChan)
		}
		if act.data[0] == 0 {
			continue // do not wait for read on multicast
		}
		timeOutChan := time.After(c.GetTransactionTimeOut(len(act.data), MaxRTUSize))

	READ_LOOP:
		for {
		SELECT:
			select {
			case <-timeOutChan:
				sendError(act.errChan, ErrServerTimeOut)
				break READ_LOOP
			case react, ok := <-c.actions:
				if !ok {
					debugf("RTUClient actions closed\n")
					return sendGetError(act.errChan)
				}
				if react.t != read {
					ioerr = fmt.Errorf("unexpected action:%s", react.t)
					return sendGetError(act.errChan)
				}
				if react.data[0] != act.data[0] {
					debugf("RTUClient unexpected slaveId:%v in %v\n", act.data[0], hex.EncodeToString(react.data))
					break SELECT
				}
				rp, err := react.data.GetPDU()
				if err != nil {
					sendError(act.errChan, err)
					break READ_LOOP
				}
				hasErr, fc := rp.GetFunctionCode().SeparateError()
				if hasErr && fc == afc {
					handler.OnError(ap, rp)
					sendError(act.errChan, fmt.Errorf("server reply with exception:%v", hex.EncodeToString(rp)))
					break READ_LOOP
				}
				if !MatchPDU(act.data.fastGetPDU(), rp) {
					sendError(act.errChan, fmt.Errorf("unexpected reply:%v", hex.EncodeToString(rp)))
					break READ_LOOP
				}
				if !afc.IsWriteToServer() {
					//read from server, write here
					bs, err := rp.GetReplyValues()
					if err != nil {
						sendError(act.errChan, err)
						break READ_LOOP
					}
					err = handler.OnWrite(ap, bs)
					sendError(act.errChan, err)
					break READ_LOOP
				}
				sendError(act.errChan, nil)
				break READ_LOOP
			}
		}
	}
}

//DoTransaction starts a transaction, and returns a channel that returns an error
//or nil, with the default slaveID.
//
//DoTransaction is blocking.
//
//For read from server, the PDU is sent as is (after been warped up in RTU)
//For write to server, the data part given will be ignored, and filled in by data from handler.
func (c *RTUClient) DoTransaction(req PDU) error {
	errChan := make(chan error)
	c.StartTransactionToServer(c.SlaveID, req, errChan)
	return <-errChan
}

//StartTransactionToServer starts a transaction, with a custom slaveID.
//errChan is required and usable, an error is set is the transaction failed, or
//nil for success.
//
//StartTransactionToServer is not blocking.
//
//For read from server, the PDU is sent as is (after been warped up in RTU)
//For write to server, the data part given will be ignored, and filled in by data from handler.
func (c *RTUClient) StartTransactionToServer(slaveID byte, req PDU, errChan chan error) {
	c.actions <- rtuAction{start, MakeRTU(slaveID, req), errChan}
}

//RTUTransactionStarter is an interface implemented by RTUClient.
type RTUTransactionStarter interface {
	StartTransactionToServer(slaveID byte, req PDU, errChan chan error)
}

//DoTransactions runs the reqs transactions in order.
//If any error is encountered, it returns early and reports the index number and
//error message
func DoTransactions(c RTUTransactionStarter, slaveID byte, reqs []PDU) (int, error) {
	errChan := make(chan error)
	for i, r := range reqs {
		c.StartTransactionToServer(slaveID, r, errChan)
		err := <-errChan
		if err != nil {
			return i, err
		}
	}
	return len(reqs), nil
}

//MakePDURequestHeaders generates the list of PDU request headers by spliting quantity
//into allowed sizes.
//Returns an error if quantitiy is out of range.
func MakePDURequestHeaders(fc FunctionCode, address uint16, quantity uint16, appendTO []PDU) ([]PDU, error) {
	if uint(address)+uint(quantity) > uint(fc.MaxRange()) {
		return nil, fmt.Errorf("quantitiy is out of range")
	}
	r := fc.MaxPerPacket()
	q := r
	for quantity > 0 {
		if quantity < r {
			q = quantity
		}
		pdu, err := fc.MakeRequestHeader(address, q)
		if err != nil {
			return nil, err
		}
		appendTO = append(appendTO, pdu)
		address += q
		quantity -= q
	}
	return appendTO, nil
}
<|endoftext|>