<commit_before>// weedo.go
package weedo

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/Archs/weedo/timekey"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"net/textproto"
	"os"
	"path"
	"strconv"
	"strings"
)

var defaultClient *Client

func init() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
	defaultClient = NewClient("localhost:9333")
}

type Fid struct {
	Id, Key, Cookie uint64
}

type Client struct {
	master  *Master
	volumes map[uint64]*Volume
	filers  map[string]*Filer
}

func NewClient(masterUrl string, filerUrls ...string) *Client {
	filers := make(map[string]*Filer)
	for _, url := range filerUrls {
		filer := NewFiler(url)
		filers[filer.Url] = filer
	}
	return &Client{
		master:  NewMaster(masterUrl),
		volumes: make(map[uint64]*Volume),
		filers:  filers,
	}
}

func (c *Client) Master() *Master {
	return c.master
}

func (c *Client) Volume(volumeId, collection string) (*Volume, error) {
	vid, _ := strconv.ParseUint(volumeId, 10, 32)
	if vid == 0 {
		fid, _ := ParseFid(volumeId)
		vid = fid.Id
	}

	if vid == 0 {
		return nil, errors.New("id malformed")
	}

	if v, ok := c.volumes[vid]; ok {
		return v, nil
	}
	vol, err := c.Master().lookup(volumeId, collection)
	if err != nil {
		return nil, err
	}

	c.volumes[vid] = vol

	return vol, nil
}

func (c *Client) Filer(url string) *Filer {
	filer := NewFiler(url)
	if v, ok := c.filers[filer.Url]; ok {
		return v
	}

	c.filers[filer.Url] = filer
	return filer
}

func ParseFid(s string) (fid Fid, err error) {
	a := strings.Split(s, ",")
	if len(a) != 2 || len(a[1]) <= 8 {
		return fid, errors.New("Fid format invalid")
	}
	if fid.Id, err = strconv.ParseUint(a[0], 10, 32); err != nil {
		return
	}
	index := len(a[1]) - 8
	if fid.Key, err = strconv.ParseUint(a[1][:index], 16, 64); err != nil {
		return
	}
	if fid.Cookie, err = strconv.ParseUint(a[1][index:], 16, 32); err != nil {
		return
	}

	return
}

// Fid in string form
func (f *Fid) String() string {
	return fmt.Sprintf("%d,%x%08x", f.Id, f.Key, f.Cookie)
}

// First, contact with master server and assign a fid, then upload to volume server
// It is same as the follow steps
// curl http://localhost:9333/dir/assign
// curl -F file=@example.jpg http://127.0.0.1:8080/3,01637037d6
func AssignUpload(filename, mimeType string, file io.Reader) (fid string, size int64, err error) {
	return defaultClient.AssignUpload(filename, mimeType, file)
}

func Delete(fid string, count int) (err error) {
	return defaultClient.Delete(fid, count)
}

func (c *Client) GetUrl(fid string) (publicUrl, url string, err error) {
	vol, err := c.Volume(fid, "")
	if err != nil {
		return
	}

	publicUrl = vol.PublicUrl + "/" + fid
	url = vol.Url + "/" + fid

	return
}

func (c *Client) AssignUpload(filename, mimeType string, file io.Reader) (fid string, size int64, err error) {

	fid, err = c.Master().Assign()
	if err != nil {
		return
	}

	vol, err := c.Volume(fid, "")
	if err != nil {
		return
	}
	size, err = vol.Upload(fid, filename, mimeType, file)

	return
}

// Assign Fid using timekey.Fid
func (c *Client) AssignUploadTK(fullPath string) (fid string, err error) {
	fid, err = c.Master().Assign()
	if err != nil {
		return
	}
	tkfid, err := timekey.ParseFid(fid)
	if err != nil {
		return
	}
	// insert self defined key using timekey
	err = tkfid.InsertKeyAndCookie(fullPath)
	if err != nil {
		return
	}
	fid = tkfid.String()
	// find vold
	vol, err := c.Volume(fid, "")
	if err != nil {
		return
	}
	// do upload
	r, err := os.Open(fullPath)
	if err != nil {
		return
	}
	defer r.Close()
	// get filename
	filename := path.Base(fullPath)
	// upload
	_, err = vol.Upload(fid, filename, tkfid.MimeType(), r)
	return
}

func (c *Client) Delete(fid string, count int) (err error) {
	vol, err := c.Volume(fid, "")
	if err != nil {
		return
	}
	return vol.Delete(fid, count)
}

var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")

func escapeQuotes(s string) string {
	return quoteEscaper.Replace(s)
}

func createFormFile(writer *multipart.Writer, fieldname, filename, mime string) (io.Writer, error) {
	h := make(textproto.MIMEHeader)
	h.Set("Content-Disposition",
		fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
			escapeQuotes(fieldname), escapeQuotes(filename)))
	if len(mime) == 0 {
		mime = "application/octet-stream"
	}
	h.Set("Content-Type", mime)
	return writer.CreatePart(h)
}

func makeFormData(filename, mimeType string, content io.Reader) (formData io.Reader, contentType string, err error) {
	buf := new(bytes.Buffer)
	writer := multipart.NewWriter(buf)

	part, err := createFormFile(writer, "file", filename, mimeType)
	//log.Println(filename, mimeType)
	if err != nil {
		log.Println(err)
		return
	}
	_, err = io.Copy(part, content)
	if err != nil {
		log.Println(err)
		return
	}

	formData = buf
	contentType = writer.FormDataContentType()
	//log.Println(contentType)
	writer.Close()

	return
}

type uploadResp struct {
	Fid      string
	FileName string
	FileUrl  string
	Size     int64
	Error    string
}

func upload(url string, contentType string, formData io.Reader) (r *uploadResp, err error) {
	resp, err := http.Post(url, contentType, formData)
	if err != nil {
		log.Println(err)
		return
	}
	defer resp.Body.Close()

	upload := new(uploadResp)
	if err = decodeJson(resp.Body, upload); err != nil {
		return
	}

	if upload.Error != "" {
		err = errors.New(upload.Error)
		return
	}

	r = upload

	return
}

func del(url string) error {
	client := http.Client{}
	request, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		return err
	}
	resp, err := client.Do(request)
	resp.Body.Close()
	return err
}

func decodeJson(r io.Reader, v interface{}) error {
	return json.NewDecoder(r).Decode(v)
}
<commit_msg>refine filename in AssignUploadTK<commit_after>// weedo.go
package weedo

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/Archs/weedo/timekey"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"net/textproto"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

var defaultClient *Client

func init() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
	defaultClient = NewClient("localhost:9333")
}

type Fid struct {
	Id, Key, Cookie uint64
}

type Client struct {
	master  *Master
	volumes map[uint64]*Volume
	filers  map[string]*Filer
}

func NewClient(masterUrl string, filerUrls ...string) *Client {
	filers := make(map[string]*Filer)
	for _, url := range filerUrls {
		filer := NewFiler(url)
		filers[filer.Url] = filer
	}
	return &Client{
		master:  NewMaster(masterUrl),
		volumes: make(map[uint64]*Volume),
		filers:  filers,
	}
}

func (c *Client) Master() *Master {
	return c.master
}

func (c *Client) Volume(volumeId, collection string) (*Volume, error) {
	vid, _ := strconv.ParseUint(volumeId, 10, 32)
	if vid == 0 {
		fid, _ := ParseFid(volumeId)
		vid = fid.Id
	}

	if vid == 0 {
		return nil, errors.New("id malformed")
	}

	if v, ok := c.volumes[vid]; ok {
		return v, nil
	}
	vol, err := c.Master().lookup(volumeId, collection)
	if err != nil {
		return nil, err
	}

	c.volumes[vid] = vol

	return vol, nil
}

func (c *Client) Filer(url string) *Filer {
	filer := NewFiler(url)
	if v, ok := c.filers[filer.Url]; ok {
		return v
	}

	c.filers[filer.Url] = filer
	return filer
}

func ParseFid(s string) (fid Fid, err error) {
	a := strings.Split(s, ",")
	if len(a) != 2 || len(a[1]) <= 8 {
		return fid, errors.New("Fid format invalid")
	}
	if fid.Id, err = strconv.ParseUint(a[0], 10, 32); err != nil {
		return
	}
	index := len(a[1]) - 8
	if fid.Key, err = strconv.ParseUint(a[1][:index], 16, 64); err != nil {
		return
	}
	if fid.Cookie, err = strconv.ParseUint(a[1][index:], 16, 32); err != nil {
		return
	}

	return
}

// Fid in string form
func (f *Fid) String() string {
	return fmt.Sprintf("%d,%x%08x", f.Id, f.Key, f.Cookie)
}

// First, contact with master server and assign a fid, then upload to volume server
// It is same as the follow steps
// curl http://localhost:9333/dir/assign
// curl -F file=@example.jpg http://127.0.0.1:8080/3,01637037d6
func AssignUpload(filename, mimeType string, file io.Reader) (fid string, size int64, err error) {
	return defaultClient.AssignUpload(filename, mimeType, file)
}

func Delete(fid string, count int) (err error) {
	return defaultClient.Delete(fid, count)
}

func (c *Client) GetUrl(fid string) (publicUrl, url string, err error) {
	vol, err := c.Volume(fid, "")
	if err != nil {
		return
	}

	publicUrl = vol.PublicUrl + "/" + fid
	url = vol.Url + "/" + fid

	return
}

func (c *Client) AssignUpload(filename, mimeType string, file io.Reader) (fid string, size int64, err error) {

	fid, err = c.Master().Assign()
	if err != nil {
		return
	}

	vol, err := c.Volume(fid, "")
	if err != nil {
		return
	}
	size, err = vol.Upload(fid, filename, mimeType, file)

	return
}

// Assign Fid using timekey.Fid
func (c *Client) AssignUploadTK(fullPath string) (fid string, err error) {
	fid, err = c.Master().Assign()
	if err != nil {
		return
	}
	tkfid, err := timekey.ParseFid(fid)
	if err != nil {
		return
	}
	// insert self defined key using timekey
	err = tkfid.InsertKeyAndCookie(fullPath)
	if err != nil {
		return
	}
	fid = tkfid.String()
	// find vold
	vol, err := c.Volume(fid, "")
	if err != nil {
		return
	}
	// do upload
	r, err := os.Open(fullPath)
	if err != nil {
		return
	}
	defer r.Close()
	// get filename
	filename := filepath.Base(fullPath)
	// upload
	_, err = vol.Upload(fid, filename, tkfid.MimeType(), r)
	return
}

func (c *Client) Delete(fid string, count int) (err error) {
	vol, err := c.Volume(fid, "")
	if err != nil {
		return
	}
	return vol.Delete(fid, count)
}

var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")

func escapeQuotes(s string) string {
	return quoteEscaper.Replace(s)
}

func createFormFile(writer *multipart.Writer, fieldname, filename, mime string) (io.Writer, error) {
	h := make(textproto.MIMEHeader)
	h.Set("Content-Disposition",
		fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
			escapeQuotes(fieldname), escapeQuotes(filename)))
	if len(mime) == 0 {
		mime = "application/octet-stream"
	}
	h.Set("Content-Type", mime)
	return writer.CreatePart(h)
}

func makeFormData(filename, mimeType string, content io.Reader) (formData io.Reader, contentType string, err error) {
	buf := new(bytes.Buffer)
	writer := multipart.NewWriter(buf)

	part, err := createFormFile(writer, "file", filename, mimeType)
	//log.Println(filename, mimeType)
	if err != nil {
		log.Println(err)
		return
	}
	_, err = io.Copy(part, content)
	if err != nil {
		log.Println(err)
		return
	}

	formData = buf
	contentType = writer.FormDataContentType()
	//log.Println(contentType)
	writer.Close()

	return
}

type uploadResp struct {
	Fid      string
	FileName string
	FileUrl  string
	Size     int64
	Error    string
}

func upload(url string, contentType string, formData io.Reader) (r *uploadResp, err error) {
	resp, err := http.Post(url, contentType, formData)
	if err != nil {
		log.Println(err)
		return
	}
	defer resp.Body.Close()

	upload := new(uploadResp)
	if err = decodeJson(resp.Body, upload); err != nil {
		return
	}

	if upload.Error != "" {
		err = errors.New(upload.Error)
		return
	}

	r = upload

	return
}

func del(url string) error {
	client := http.Client{}
	request, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		return err
	}
	resp, err := client.Do(request)
	resp.Body.Close()
	return err
}

func decodeJson(r io.Reader, v interface{}) error {
	return json.NewDecoder(r).Decode(v)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/gorilla/mux"
	"github.com/hashicorp/consul/api"
	stdopentracing "github.com/opentracing/opentracing-go"

	"github.com/go-kit/kit/endpoint"
	"github.com/go-kit/kit/examples/addsvc"
	addsvcgrpcclient "github.com/go-kit/kit/examples/addsvc/client/grpc"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/sd"
	consulsd "github.com/go-kit/kit/sd/consul"
	"github.com/go-kit/kit/sd/lb"
	httptransport "github.com/go-kit/kit/transport/http"
	"google.golang.org/grpc"
)

func main() {
	var (
		httpAddr     = flag.String("http.addr", ":8000", "Address for HTTP (JSON) server")
		consulAddr   = flag.String("consul.addr", "", "Consul agent address")
		retryMax     = flag.Int("retry.max", 3, "per-request retries to different instances")
		retryTimeout = flag.Duration("retry.timeout", 500*time.Millisecond, "per-request timeout, including retries")
	)
	flag.Parse()

	// Logging domain.
	var logger log.Logger
	{
		logger = log.NewLogfmtLogger(os.Stderr)
		logger = log.With(logger, "ts", log.DefaultTimestampUTC)
		logger = log.With(logger, "caller", log.DefaultCaller)
	}

	// Service discovery domain. In this example we use Consul.
	var client consulsd.Client
	{
		consulConfig := api.DefaultConfig()
		if len(*consulAddr) > 0 {
			consulConfig.Address = *consulAddr
		}
		consulClient, err := api.NewClient(consulConfig)
		if err != nil {
			logger.Log("err", err)
			os.Exit(1)
		}
		client = consulsd.NewClient(consulClient)
	}

	// Transport domain.
	tracer := stdopentracing.GlobalTracer() // no-op
	ctx := context.Background()
	r := mux.NewRouter()

	// Now we begin installing the routes. Each route corresponds to a single
	// method: sum, concat, uppercase, and count.

	// addsvc routes.
	{
		// Each method gets constructed with a factory. Factories take an
		// instance string, and return a specific endpoint. In the factory we
		// dial the instance string we get from Consul, and then leverage an
		// addsvc client package to construct a complete service. We can then
		// leverage the addsvc.Make{Sum,Concat}Endpoint constructors to convert
		// the complete service to specific endpoint.

		var (
			tags        = []string{}
			passingOnly = true
			endpoints   = addsvc.Endpoints{}
			instancer   = consulsd.NewInstancer(client, logger, "addsvc", tags, passingOnly)
		)
		{
			factory := addsvcFactory(addsvc.MakeSumEndpoint, tracer, logger)
			endpointer := sd.NewEndpointer(instancer, factory, logger)
			balancer := lb.NewRoundRobin(endpointer)
			retry := lb.Retry(*retryMax, *retryTimeout, balancer)
			endpoints.SumEndpoint = retry
		}
		{
			factory := addsvcFactory(addsvc.MakeConcatEndpoint, tracer, logger)
			endpointer := sd.NewEndpointer(instancer, factory, logger)
			balancer := lb.NewRoundRobin(endpointer)
			retry := lb.Retry(*retryMax, *retryTimeout, balancer)
			endpoints.ConcatEndpoint = retry
		}

		// Here we leverage the fact that addsvc comes with a constructor for an
		// HTTP handler, and just install it under a particular path prefix in
		// our router.

		r.PathPrefix("/addsvc").Handler(http.StripPrefix("/addsvc", addsvc.MakeHTTPHandler(endpoints, tracer, logger)))
	}

	// stringsvc routes.
	{
		// addsvc had lots of nice importable Go packages we could leverage.
		// With stringsvc we are not so fortunate, it just has some endpoints
		// that we assume will exist. So we have to write that logic here. This
		// is by design, so you can see two totally different methods of
		// proxying to a remote service.

		var (
			tags        = []string{}
			passingOnly = true
			uppercase   endpoint.Endpoint
			count       endpoint.Endpoint
			instancer   = consulsd.NewInstancer(client, logger, "stringsvc", tags, passingOnly)
		)
		{
			factory := stringsvcFactory(ctx, "GET", "/uppercase")
			endpointer := sd.NewEndpointer(instancer, factory, logger)
			balancer := lb.NewRoundRobin(endpointer)
			retry := lb.Retry(*retryMax, *retryTimeout, balancer)
			uppercase = retry
		}
		{
			factory := stringsvcFactory(ctx, "GET", "/count")
			endpointer := sd.NewEndpointer(instancer, factory, logger)
			balancer := lb.NewRoundRobin(endpointer)
			retry := lb.Retry(*retryMax, *retryTimeout, balancer)
			count = retry
		}

		// We can use the transport/http.Server to act as our handler, all we
		// have to do provide it with the encode and decode functions for our
		// stringsvc methods.

		r.Handle("/stringsvc/uppercase", httptransport.NewServer(uppercase, decodeUppercaseRequest, encodeJSONResponse))
		r.Handle("/stringsvc/count", httptransport.NewServer(count, decodeCountRequest, encodeJSONResponse))
	}

	// Interrupt handler.
	errc := make(chan error)
	go func() {
		c := make(chan os.Signal)
		signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
		errc <- fmt.Errorf("%s", <-c)
	}()

	// HTTP transport.
	go func() {
		logger.Log("transport", "HTTP", "addr", *httpAddr)
		errc <- http.ListenAndServe(*httpAddr, r)
	}()

	// Run!
	logger.Log("exit", <-errc)
}

func addsvcFactory(makeEndpoint func(addsvc.Service) endpoint.Endpoint, tracer stdopentracing.Tracer, logger log.Logger) sd.Factory {
	return func(instance string) (endpoint.Endpoint, io.Closer, error) {
		// We could just as easily use the HTTP or Thrift client package to make
		// the connection to addsvc. We've chosen gRPC arbitrarily. Note that
		// the transport is an implementation detail: it doesn't leak out of
		// this function. Nice!

		conn, err := grpc.Dial(instance, grpc.WithInsecure())
		if err != nil {
			return nil, nil, err
		}
		service := addsvcgrpcclient.New(conn, tracer, logger)
		endpoint := makeEndpoint(service)

		// Notice that the addsvc gRPC client converts the connection to a
		// complete addsvc, and we just throw away everything except the method
		// we're interested in. A smarter factory would mux multiple methods
		// over the same connection. But that would require more work to manage
		// the returned io.Closer, e.g. reference counting. Since this is for
		// the purposes of demonstration, we'll just keep it simple.

		return endpoint, conn, nil
	}
}

func stringsvcFactory(ctx context.Context, method, path string) sd.Factory {
	return func(instance string) (endpoint.Endpoint, io.Closer, error) {
		if !strings.HasPrefix(instance, "http") {
			instance = "http://" + instance
		}
		tgt, err := url.Parse(instance)
		if err != nil {
			return nil, nil, err
		}
		tgt.Path = path

		// Since stringsvc doesn't have any kind of package we can import, or
		// any formal spec, we are forced to just assert where the endpoints
		// live, and write our own code to encode and decode requests and
		// responses. Ideally, if you write the service, you will want to
		// provide stronger guarantees to your clients.

		var (
			enc httptransport.EncodeRequestFunc
			dec httptransport.DecodeResponseFunc
		)
		switch path {
		case "/uppercase":
			enc, dec = encodeJSONRequest, decodeUppercaseResponse
		case "/count":
			enc, dec = encodeJSONRequest, decodeCountResponse
		default:
			return nil, nil, fmt.Errorf("unknown stringsvc path %q", path)
		}

		return httptransport.NewClient(method, tgt, enc, dec).Endpoint(), nil, nil
	}
}

func encodeJSONRequest(_ context.Context, req *http.Request, request interface{}) error {
	// Both uppercase and count requests are encoded in the same way:
	// simple JSON serialization to the request body.
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(request); err != nil {
		return err
	}
	req.Body = ioutil.NopCloser(&buf)
	return nil
}

func encodeJSONResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	return json.NewEncoder(w).Encode(response)
}

// I've just copied these functions from stringsvc3/transport.go, inlining the
// struct definitions.

func decodeUppercaseResponse(ctx context.Context, resp *http.Response) (interface{}, error) {
	var response struct {
		V   string `json:"v"`
		Err string `json:"err,omitempty"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
		return nil, err
	}
	return response, nil
}

func decodeCountResponse(ctx context.Context, resp *http.Response) (interface{}, error) {
	var response struct {
		V int `json:"v"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
		return nil, err
	}
	return response, nil
}

func decodeUppercaseRequest(ctx context.Context, req *http.Request) (interface{}, error) {
	var request struct {
		S string `json:"s"`
	}
	if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
		return nil, err
	}
	return request, nil
}

func decodeCountRequest(ctx context.Context, req *http.Request) (interface{}, error) {
	var request struct {
		S string `json:"s"`
	}
	if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
		return nil, err
	}
	return request, nil
}
<commit_msg>examples/apigateway: fix for new addsvc<commit_after>package main

import (
	"bytes"
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	consulsd "github.com/go-kit/kit/sd/consul"
	"github.com/gorilla/mux"
	"github.com/hashicorp/consul/api"
	stdopentracing "github.com/opentracing/opentracing-go"
	"google.golang.org/grpc"

	"github.com/go-kit/kit/endpoint"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/sd"
	"github.com/go-kit/kit/sd/lb"
	httptransport "github.com/go-kit/kit/transport/http"

	"github.com/go-kit/kit/examples/addsvc/pkg/addendpoint"
	"github.com/go-kit/kit/examples/addsvc/pkg/addservice"
	"github.com/go-kit/kit/examples/addsvc/pkg/addtransport"
)

func main() {
	var (
		httpAddr     = flag.String("http.addr", ":8000", "Address for HTTP (JSON) server")
		consulAddr   = flag.String("consul.addr", "", "Consul agent address")
		retryMax     = flag.Int("retry.max", 3, "per-request retries to different instances")
		retryTimeout = flag.Duration("retry.timeout", 500*time.Millisecond, "per-request timeout, including retries")
	)
	flag.Parse()

	// Logging domain.
	var logger log.Logger
	{
		logger = log.NewLogfmtLogger(os.Stderr)
		logger = log.With(logger, "ts", log.DefaultTimestampUTC)
		logger = log.With(logger, "caller", log.DefaultCaller)
	}

	// Service discovery domain. In this example we use Consul.
	var client consulsd.Client
	{
		consulConfig := api.DefaultConfig()
		if len(*consulAddr) > 0 {
			consulConfig.Address = *consulAddr
		}
		consulClient, err := api.NewClient(consulConfig)
		if err != nil {
			logger.Log("err", err)
			os.Exit(1)
		}
		client = consulsd.NewClient(consulClient)
	}

	// Transport domain.
	tracer := stdopentracing.GlobalTracer() // no-op
	ctx := context.Background()
	r := mux.NewRouter()

	// Now we begin installing the routes. Each route corresponds to a single
	// method: sum, concat, uppercase, and count.

	// addsvc routes.
	{
		// Each method gets constructed with a factory. Factories take an
		// instance string, and return a specific endpoint. In the factory we
		// dial the instance string we get from Consul, and then leverage an
		// addsvc client package to construct a complete service. We can then
		// leverage the addsvc.Make{Sum,Concat}Endpoint constructors to convert
		// the complete service to specific endpoint.
		var (
			tags        = []string{}
			passingOnly = true
			endpoints   = addendpoint.Set{}
			instancer   = consulsd.NewInstancer(client, logger, "addsvc", tags, passingOnly)
		)
		{
			factory := addsvcFactory(addendpoint.MakeSumEndpoint, tracer, logger)
			endpointer := sd.NewEndpointer(instancer, factory, logger)
			balancer := lb.NewRoundRobin(endpointer)
			retry := lb.Retry(*retryMax, *retryTimeout, balancer)
			endpoints.SumEndpoint = retry
		}
		{
			factory := addsvcFactory(addendpoint.MakeConcatEndpoint, tracer, logger)
			endpointer := sd.NewEndpointer(instancer, factory, logger)
			balancer := lb.NewRoundRobin(endpointer)
			retry := lb.Retry(*retryMax, *retryTimeout, balancer)
			endpoints.ConcatEndpoint = retry
		}

		// Here we leverage the fact that addsvc comes with a constructor for an
		// HTTP handler, and just install it under a particular path prefix in
		// our router.

		r.PathPrefix("/addsvc").Handler(http.StripPrefix("/addsvc", addtransport.NewHTTPHandler(endpoints, tracer, logger)))
	}

	// stringsvc routes.
	{
		// addsvc had lots of nice importable Go packages we could leverage.
		// With stringsvc we are not so fortunate, it just has some endpoints
		// that we assume will exist. So we have to write that logic here. This
		// is by design, so you can see two totally different methods of
		// proxying to a remote service.

		var (
			tags        = []string{}
			passingOnly = true
			uppercase   endpoint.Endpoint
			count       endpoint.Endpoint
			instancer   = consulsd.NewInstancer(client, logger, "stringsvc", tags, passingOnly)
		)
		{
			factory := stringsvcFactory(ctx, "GET", "/uppercase")
			endpointer := sd.NewEndpointer(instancer, factory, logger)
			balancer := lb.NewRoundRobin(endpointer)
			retry := lb.Retry(*retryMax, *retryTimeout, balancer)
			uppercase = retry
		}
		{
			factory := stringsvcFactory(ctx, "GET", "/count")
			endpointer := sd.NewEndpointer(instancer, factory, logger)
			balancer := lb.NewRoundRobin(endpointer)
			retry := lb.Retry(*retryMax, *retryTimeout, balancer)
			count = retry
		}

		// We can use the transport/http.Server to act as our handler, all we
		// have to do provide it with the encode and decode functions for our
		// stringsvc methods.

		r.Handle("/stringsvc/uppercase", httptransport.NewServer(uppercase, decodeUppercaseRequest, encodeJSONResponse))
		r.Handle("/stringsvc/count", httptransport.NewServer(count, decodeCountRequest, encodeJSONResponse))
	}

	// Interrupt handler.
	errc := make(chan error)
	go func() {
		c := make(chan os.Signal)
		signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
		errc <- fmt.Errorf("%s", <-c)
	}()

	// HTTP transport.
	go func() {
		logger.Log("transport", "HTTP", "addr", *httpAddr)
		errc <- http.ListenAndServe(*httpAddr, r)
	}()

	// Run!
	logger.Log("exit", <-errc)
}

func addsvcFactory(makeEndpoint func(addservice.Service) endpoint.Endpoint, tracer stdopentracing.Tracer, logger log.Logger) sd.Factory {
	return func(instance string) (endpoint.Endpoint, io.Closer, error) {
		// We could just as easily use the HTTP or Thrift client package to make
		// the connection to addsvc. We've chosen gRPC arbitrarily. Note that
		// the transport is an implementation detail: it doesn't leak out of
		// this function. Nice!

		conn, err := grpc.Dial(instance, grpc.WithInsecure())
		if err != nil {
			return nil, nil, err
		}
		service := addtransport.NewGRPCClient(conn, tracer, logger)
		endpoint := makeEndpoint(service)

		// Notice that the addsvc gRPC client converts the connection to a
		// complete addsvc, and we just throw away everything except the method
		// we're interested in. A smarter factory would mux multiple methods
		// over the same connection. But that would require more work to manage
		// the returned io.Closer, e.g. reference counting. Since this is for
		// the purposes of demonstration, we'll just keep it simple.

		return endpoint, conn, nil
	}
}

func stringsvcFactory(ctx context.Context, method, path string) sd.Factory {
	return func(instance string) (endpoint.Endpoint, io.Closer, error) {
		if !strings.HasPrefix(instance, "http") {
			instance = "http://" + instance
		}
		tgt, err := url.Parse(instance)
		if err != nil {
			return nil, nil, err
		}
		tgt.Path = path

		// Since stringsvc doesn't have any kind of package we can import, or
		// any formal spec, we are forced to just assert where the endpoints
		// live, and write our own code to encode and decode requests and
		// responses. Ideally, if you write the service, you will want to
		// provide stronger guarantees to your clients.

		var (
			enc httptransport.EncodeRequestFunc
			dec httptransport.DecodeResponseFunc
		)
		switch path {
		case "/uppercase":
			enc, dec = encodeJSONRequest, decodeUppercaseResponse
		case "/count":
			enc, dec = encodeJSONRequest, decodeCountResponse
		default:
			return nil, nil, fmt.Errorf("unknown stringsvc path %q", path)
		}

		return httptransport.NewClient(method, tgt, enc, dec).Endpoint(), nil, nil
	}
}

func encodeJSONRequest(_ context.Context, req *http.Request, request interface{}) error {
	// Both uppercase and count requests are encoded in the same way:
	// simple JSON serialization to the request body.
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(request); err != nil {
		return err
	}
	req.Body = ioutil.NopCloser(&buf)
	return nil
}

func encodeJSONResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	return json.NewEncoder(w).Encode(response)
}

// I've just copied these functions from stringsvc3/transport.go, inlining the
// struct definitions.

func decodeUppercaseResponse(ctx context.Context, resp *http.Response) (interface{}, error) {
	var response struct {
		V   string `json:"v"`
		Err string `json:"err,omitempty"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
		return nil, err
	}
	return response, nil
}

func decodeCountResponse(ctx context.Context, resp *http.Response) (interface{}, error) {
	var response struct {
		V int `json:"v"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&response); err != nil {
		return nil, err
	}
	return response, nil
}

func decodeUppercaseRequest(ctx context.Context, req *http.Request) (interface{}, error) {
	var request struct {
		S string `json:"s"`
	}
	if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
		return nil, err
	}
	return request, nil
}

func decodeCountRequest(ctx context.Context, req *http.Request) (interface{}, error) {
	var request struct {
		S string `json:"s"`
	}
	if err := json.NewDecoder(req.Body).Decode(&request); err != nil {
		return nil, err
	}
	return request, nil
}
<|endoftext|>


<commit_before>package networkOnline

import (
	"fmt"
	"github.com/vova616/GarageEngine/engine"
	"github.com/vova616/GarageEngine/engine/components"
	_ "image/jpeg"
	_ "image/png"
	//"gl"
	"strconv"
	//"time"
	//"strings"
	//"math"
	"github.com/vova616/chipmunk"
	"github.com/vova616/chipmunk/vect"
	//"image"
)

type GameScene struct {
	*engine.SceneData
	Layer1 *engine.GameObject
	Layer2 *engine.GameObject
	Layer3 *engine.GameObject
}

var (
	GameSceneGeneral *GameScene
	cir              *engine.Texture
	box              *engine.Texture
)

func (s *GameScene) Load() {
	ArialFont, err := engine.NewFont("./data/Fonts/arial.ttf", 48)
	if err != nil {
		panic(err)
	}

	ArialFont2, err := engine.NewFont("./data/Fonts/arial.ttf", 24)
	if err != nil {
		panic(err)
	}
	_ = ArialFont2
	_ = ArialFont

	GameSceneGeneral = s

	s.Camera = engine.NewCamera()

	cam := engine.NewGameObject("Camera")
	cam.AddComponent(s.Camera)
	cam.AddComponent(NewCameraCtl(100))

	cam.Transform().SetScalef(1, 1)

	gui := engine.NewGameObject("GUI")

	Layer1 := engine.NewGameObject("Layer1")
	Layer2 := engine.NewGameObject("Layer2")
	Layer3 := engine.NewGameObject("Layer3")

	s.Layer1 = Layer1
	s.Layer2 = Layer2
	s.Layer3 = Layer3

	mouse := engine.NewGameObject("Mouse")
	mouse.AddComponent(NewMouseDebugger())
	mouse.AddComponent(engine.NewMouse())
	mouse.Transform().SetParent2(cam)

	FPSDrawer := engine.NewGameObject("FPS")
	txt := FPSDrawer.AddComponent(components.NewUIText(ArialFont2, "")).(*components.UIText)
	fps := FPSDrawer.AddComponent(engine.NewFPS()).(*engine.FPS)
	txt.SetAlign(engine.AlignLeft)
	fps.SetAction(func(fps float64) {
		txt.SetString("FPS: " + strconv.FormatFloat(fps, 'f', 2, 32))
	})
	FPSDrawer.Transform().SetParent2(cam)
	FPSDrawer.Transform().SetPositionf(-float32(engine.Width)/2+10, +float32(engine.Height)/2-20)
	FPSDrawer.Transform().SetScalef(20, 20)

	{
		FPSDrawer := engine.NewGameObject("Counter")
		txt := FPSDrawer.AddComponent(components.NewUIText(ArialFont2, "")).(*components.UIText)
		txt.SetAlign(engine.AlignLeft)
		engine.StartBehavior(func() engine.Command {
			txt.SetString(fmt.Sprintf("Bodies: %d", len(engine.Space.Bodies)))
			return engine.Restart
		})
		FPSDrawer.Transform().SetParent2(cam)
		FPSDrawer.Transform().SetPositionf(-float32(engine.Width)/2+10, +float32(engine.Height)/2-45)
		FPSDrawer.Transform().SetScalef(20, 20)
	}

	//SPACCCEEEEE
	engine.Space.Gravity.Y = -300
	engine.Space.Iterations = 10

	atlas := engine.NewManagedAtlas(512, 512)
	e := atlas.LoadGroup("./data/fire")
	if e != nil {
		fmt.Println(e)
	}
	e = atlas.LoadGroup("./data/Charecter")
	if e != nil {
		fmt.Println(e)
	}
	err, rectID := atlas.LoadImage("./data/rect.png")
	if err != nil {
		panic(err)
	}
	err, circleID := atlas.LoadImage("./data/circle.png")
	if err != nil {
		panic(err)
	}

	atlas.BuildAtlas()

	atlas.BuildMipmaps()
	atlas.SetFiltering(engine.MipMapLinearNearest, engine.Nearest)

	uvsFire, indFire := engine.AnimatedGroupUVs(atlas, "fire")
	_ = uvsFire
	_ = indFire

	clone2 := engine.NewGameObject("Sprite")
	s2 := clone2.AddComponent(engine.NewSprite3(atlas.Texture, uvsFire)).(*engine.Sprite)
	s2.BindAnimations(indFire)
	s2.AnimationSpeed = 6
	clone2.Transform().SetPositionf(775, 300)
	clone2.Transform().SetScalef(58, 58)
	clone2.Transform().SetParent2(Layer1)

	f := clone2.Clone()
	f.Transform().SetPositionf(25, 300)
	f.Transform().SetParent2(Layer1)

	box, _ = engine.LoadTexture("./data/rect.png")
	cir, _ = engine.LoadTexture("./data/circle.png")
	cir.BuildMipmaps()
	cir.SetFiltering(engine.MipMapLinearNearest, engine.Nearest)

	ball := engine.NewGameObject("Ball")
	ball.AddComponent(engine.NewSprite2(atlas.Texture, engine.IndexUV(atlas, circleID)))
	ball.Transform().SetScalef(30, 30)
	ball.AddComponent(engine.NewPhysicsShape(false, chipmunk.NewCircle(vect.Vect{0, 0}, 15)))
	ball.Physics.Body.SetMass(10)
	ball.Physics.Body.SetMoment(ball.Physics.Shape.Moment(10))
	ball.Physics.Shape.SetFriction(0.8)
	ball.Physics.Shape.SetElasticity(0.8)

	for i := 0; i < 0; i++ {
		sprite3 := engine.NewGameObject("Sprite" + fmt.Sprint(i))
		sprite3.AddComponent(engine.NewSprite2(atlas.Texture, engine.IndexUV(atlas, rectID)))
		sprite3.Transform().SetParent2(Layer2)
		sprite3.Transform().SetRotationf(180)
		sprite3.Transform().SetPositionf(160, 120+float32(i*31))
		sprite3.Transform().SetScalef(30, 30)

		phx := sprite3.AddComponent(engine.NewPhysics(false)).(*engine.Physics)
		phx.Shape.SetFriction(1)
		phx.Shape.SetElasticity(0.0)
		phx.Body.SetMass(1)
	}

	for i := 0; i < 2000; i++ {
		sprite3 := ball.Clone()
		sprite3.Transform().SetParent2(Layer2)
		sprite3.Transform().SetPositionf(200+float32(i%4)*25, float32(i*30)+120)
	}

	floor := engine.NewGameObject("Floor")
	floor.AddComponent(engine.NewSprite(box))
	floor.AddComponent(engine.NewPhysics(true))
	floor.Transform().SetParent2(Layer2)
	floor.Transform().SetPositionf(100, -20)
	floor.Transform().SetScalef(10000, 100)
	floor.Physics.Shape.SetFriction(1)
	floor.Physics.Shape.SetElasticity(1)

	floor2 := floor.Clone()
	floor2.Transform().SetParent2(Layer2)
	floor2.Transform().SetPositionf(800, -20)
	floor2.Transform().SetRotationf(90)

	floor3 := floor2.Clone()
	floor3.Transform().SetParent2(Layer2)
	floor3.Transform().SetPositionf(0, -20)

	uvs2, ind := engine.AnimatedGroupUVs(atlas, "stand", "walk")
	_ = uvs2
	_ = ind

	sprite4 := engine.NewGameObject("Sprite")
	sprite := sprite4.AddComponent(engine.NewSprite3(atlas.Texture, uvs2)).(*engine.Sprite)
	sprite.BindAnimations(ind)
	//sprite4.AddComponent(NewSprite(sp))
	sprite.AnimationSpeed = 5
	player := sprite4.AddComponent(NewPlayerController()).(*PlayerController)
	//sprite4.AddComponent(NewRotator())
	ph := sprite4.AddComponent(engine.NewPhysics(false)).(*engine.Physics)
	player.Fire = clone2
	sprite4.Transform().SetParent2(Layer1)
	sprite4.Transform().SetPositionf(900, 100)
	sprite4.Transform().SetScalef(100, 100)
	ph.Body.SetMass(100)
	ph.Body.IgnoreGravity = false
	ph.Body.SetMoment(engine.Inf)
	ph.Shape.SetFriction(1)
	ph.Shape.SetElasticity(0)

	/*
		floor = NewGameObject("Box")
		bbBox := NewSprite(box)
		floor.AddComponent(bbBox)
		phx = floor.AddComponent(NewPhysics(true, 500, 500)).(*Physics)
		floor.Transform().SetParent2(Layer2)
		floor.Transform().SetPosition(NewVector2(900, 200))
		floor.Transform().SetScale(NewVector2(500, 500))
		phx.Shape.SetFriction(1)
		phx.Shape.SetElasticity(1)
		phx.Shape.IsSensor = true
		//phx.Shape.Friction = 1
		_ = phx
	*/

	//sShadow.Sprite = bbBox
	//
	{
		sprite3 := ball.Clone()
		sprite3.Transform().SetParent2(Layer2)
		sprite3.Transform().SetPositionf(200, 120)

		joint := chipmunk.NewPivotJoint(mouse.Physics.Body, sprite3.Physics.Body)
		joint.MaxForce = 5000000
		//mouseJoint->errorBias = cpfpow(1.0f - 0.15f, 60.0f);
		engine.Space.AddConstraint(joint)
	}

	cam.Transform().SetWorldPosition(player.Transform().WorldPosition())

	s.AddGameObject(cam)
	s.AddGameObject(gui)
	s.AddGameObject(Layer1)
	s.AddGameObject(Layer2)
	s.AddGameObject(Layer3)
	//s.AddGameObject(shadowShader)

	fmt.Println("Scene loaded")
}

func (s *GameScene) New() engine.Scene {
	gs := new(GameScene)
	gs.SceneData = engine.NewScene("GameScene")
	return gs
}
<commit_msg>Change back to 200 balls.<commit_after>package networkOnline

import (
	"fmt"
	"github.com/vova616/GarageEngine/engine"
	"github.com/vova616/GarageEngine/engine/components"
	_ "image/jpeg"
	_ "image/png"
	//"gl"
	"strconv"
	//"time"
	//"strings"
	//"math"
	"github.com/vova616/chipmunk"
	"github.com/vova616/chipmunk/vect"
	//"image"
)

type GameScene struct {
	*engine.SceneData
	Layer1 *engine.GameObject
	Layer2 *engine.GameObject
	Layer3 *engine.GameObject
}

var (
	GameSceneGeneral *GameScene
	cir              *engine.Texture
	box              *engine.Texture
)

func (s *GameScene) Load() {
	ArialFont, err := engine.NewFont("./data/Fonts/arial.ttf", 48)
	if err != nil {
		panic(err)
	}

	ArialFont2, err := engine.NewFont("./data/Fonts/arial.ttf", 24)
	if err != nil {
		panic(err)
	}
	_ = ArialFont2
	_ = ArialFont

	GameSceneGeneral = s

	s.Camera = engine.NewCamera()

	cam := engine.NewGameObject("Camera")
	cam.AddComponent(s.Camera)
	cam.AddComponent(NewCameraCtl(100))

	cam.Transform().SetScalef(1, 1)

	gui := engine.NewGameObject("GUI")

	Layer1 := engine.NewGameObject("Layer1")
	Layer2 := engine.NewGameObject("Layer2")
	Layer3 := engine.NewGameObject("Layer3")

	s.Layer1 = Layer1
	s.Layer2 = Layer2
	s.Layer3 = Layer3

	mouse := engine.NewGameObject("Mouse")
	mouse.AddComponent(NewMouseDebugger())
	mouse.AddComponent(engine.NewMouse())
	mouse.Transform().SetParent2(cam)

	FPSDrawer := engine.NewGameObject("FPS")
	txt := FPSDrawer.AddComponent(components.NewUIText(ArialFont2, "")).(*components.UIText)
	fps := FPSDrawer.AddComponent(engine.NewFPS()).(*engine.FPS)
	txt.SetAlign(engine.AlignLeft)
	fps.SetAction(func(fps float64) {
		txt.SetString("FPS: " + strconv.FormatFloat(fps, 'f', 2, 32))
	})
	FPSDrawer.Transform().SetParent2(cam)
	FPSDrawer.Transform().SetPositionf(-float32(engine.Width)/2+10, +float32(engine.Height)/2-20)
	FPSDrawer.Transform().SetScalef(20, 20)

	{
		FPSDrawer := engine.NewGameObject("Counter")
		txt := FPSDrawer.AddComponent(components.NewUIText(ArialFont2, "")).(*components.UIText)
		txt.SetAlign(engine.AlignLeft)
		engine.StartBehavior(func() engine.Command {
			txt.SetString(fmt.Sprintf("Bodies: %d", len(engine.Space.Bodies)))
			return engine.Restart
		})
		FPSDrawer.Transform().SetParent2(cam)
		FPSDrawer.Transform().SetPositionf(-float32(engine.Width)/2+10, +float32(engine.Height)/2-45)
		FPSDrawer.Transform().SetScalef(20, 20)
	}

	//SPACCCEEEEE
	engine.Space.Gravity.Y = -300
	engine.Space.Iterations = 10

	atlas := engine.NewManagedAtlas(512, 512)
	e := atlas.LoadGroup("./data/fire")
	if e != nil {
		fmt.Println(e)
	}
	e = atlas.LoadGroup("./data/Charecter")
	if e != nil {
		fmt.Println(e)
	}
	err, rectID := atlas.LoadImage("./data/rect.png")
	if err != nil {
		panic(err)
	}
	err, circleID := atlas.LoadImage("./data/circle.png")
	if err != nil {
		panic(err)
	}

	atlas.BuildAtlas()

	atlas.BuildMipmaps()
	atlas.SetFiltering(engine.MipMapLinearNearest, engine.Nearest)

	uvsFire, indFire := engine.AnimatedGroupUVs(atlas, "fire")
	_ = uvsFire
	_ = indFire

	clone2 := engine.NewGameObject("Sprite")
	s2 := clone2.AddComponent(engine.NewSprite3(atlas.Texture, uvsFire)).(*engine.Sprite)
	s2.BindAnimations(indFire)
	s2.AnimationSpeed = 6
	clone2.Transform().SetPositionf(775, 300)
	clone2.Transform().SetScalef(58, 58)
	clone2.Transform().SetParent2(Layer1)

	f := clone2.Clone()
	f.Transform().SetPositionf(25, 300)
	f.Transform().SetParent2(Layer1)

	box, _ = engine.LoadTexture("./data/rect.png")
	cir, _ = engine.LoadTexture("./data/circle.png")
	cir.BuildMipmaps()
	cir.SetFiltering(engine.MipMapLinearNearest, engine.Nearest)

	ball := engine.NewGameObject("Ball")
	ball.AddComponent(engine.NewSprite2(atlas.Texture, engine.IndexUV(atlas, circleID)))
	ball.Transform().SetScalef(30, 30)
	ball.AddComponent(engine.NewPhysicsShape(false, chipmunk.NewCircle(vect.Vect{0, 0}, 15)))
	ball.Physics.Body.SetMass(10)
	ball.Physics.Body.SetMoment(ball.Physics.Shape.Moment(10))
	ball.Physics.Shape.SetFriction(0.8)
	ball.Physics.Shape.SetElasticity(0.8)

	for i := 0; i < 0; i++ {
		sprite3 := engine.NewGameObject("Sprite" + fmt.Sprint(i))
		sprite3.AddComponent(engine.NewSprite2(atlas.Texture, engine.IndexUV(atlas, rectID)))
		sprite3.Transform().SetParent2(Layer2)
		sprite3.Transform().SetRotationf(180)
		sprite3.Transform().SetPositionf(160, 120+float32(i*31))
		sprite3.Transform().SetScalef(30, 30)

		phx := sprite3.AddComponent(engine.NewPhysics(false)).(*engine.Physics)
		phx.Shape.SetFriction(1)
		phx.Shape.SetElasticity(0.0)
		phx.Body.SetMass(1)
	}

	for i := 0; i < 200; i++ {
		sprite3 := ball.Clone()
		sprite3.Transform().SetParent2(Layer2)
		sprite3.Transform().SetPositionf(200+float32(i%4)*25, float32(i*30)+120)
	}

	floor := engine.NewGameObject("Floor")
	floor.AddComponent(engine.NewSprite(box))
	floor.AddComponent(engine.NewPhysics(true))
	floor.Transform().SetParent2(Layer2)
	floor.Transform().SetPositionf(100, -20)
	floor.Transform().SetScalef(10000, 100)
	floor.Physics.Shape.SetFriction(1)
	floor.Physics.Shape.SetElasticity(1)

	floor2 := floor.Clone()
	floor2.Transform().SetParent2(Layer2)
	floor2.Transform().SetPositionf(800, -20)
	floor2.Transform().SetRotationf(90)

	floor3 := floor2.Clone()
	floor3.Transform().SetParent2(Layer2)
	floor3.Transform().SetPositionf(0, -20)

	uvs2, ind := engine.AnimatedGroupUVs(atlas, "stand", "walk")
	_ = uvs2
	_ = ind

	sprite4 := engine.NewGameObject("Sprite")
	sprite := sprite4.AddComponent(engine.NewSprite3(atlas.Texture, uvs2)).(*engine.Sprite)
	sprite.BindAnimations(ind)
	//sprite4.AddComponent(NewSprite(sp))
	sprite.AnimationSpeed = 5
	player := sprite4.AddComponent(NewPlayerController()).(*PlayerController)
	//sprite4.AddComponent(NewRotator())
	ph := sprite4.AddComponent(engine.NewPhysics(false)).(*engine.Physics)
	player.Fire = clone2
	sprite4.Transform().SetParent2(Layer1)
	sprite4.Transform().SetPositionf(900, 100)
	sprite4.Transform().SetScalef(100, 100)
	ph.Body.SetMass(100)
	ph.Body.IgnoreGravity = false
	ph.Body.SetMoment(engine.Inf)
	ph.Shape.SetFriction(1)
	ph.Shape.SetElasticity(0)

	/*
		floor = NewGameObject("Box")
		bbBox := NewSprite(box)
		floor.AddComponent(bbBox)
		phx = floor.AddComponent(NewPhysics(true, 500, 500)).(*Physics)
		floor.Transform().SetParent2(Layer2)
		floor.Transform().SetPosition(NewVector2(900, 200))
		floor.Transform().SetScale(NewVector2(500, 500))
		phx.Shape.SetFriction(1)
		phx.Shape.SetElasticity(1)
		phx.Shape.IsSensor = true
		//phx.Shape.Friction = 1
		_ = phx
	*/

	//sShadow.Sprite = bbBox
	//
	{
		sprite3 := ball.Clone()
		sprite3.Transform().SetParent2(Layer2)
		sprite3.Transform().SetPositionf(200, 120)

		joint := chipmunk.NewPivotJoint(mouse.Physics.Body, sprite3.Physics.Body)
		joint.MaxForce = 5000000
		//mouseJoint->errorBias = cpfpow(1.0f - 0.15f, 60.0f);
		engine.Space.AddConstraint(joint)
	}

	cam.Transform().SetWorldPosition(player.Transform().WorldPosition())

	s.AddGameObject(cam)
	s.AddGameObject(gui)
	s.AddGameObject(Layer1)
	s.AddGameObject(Layer2)
	s.AddGameObject(Layer3)
	//s.AddGameObject(shadowShader)

	fmt.Println("Scene loaded")
}

func (s *GameScene) New() engine.Scene {
	gs := new(GameScene)
	gs.SceneData = engine.NewScene("GameScene")
	return gs
}
<|endoftext|>


<commit_before>package communicator

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"time"

	packerssh "github.com/hashicorp/packer/communicator/ssh"
	"github.com/hashicorp/packer/helper/multistep"
	helperssh "github.com/hashicorp/packer/helper/ssh"
	"github.com/hashicorp/packer/template/interpolate"
	"github.com/masterzen/winrm"
	"golang.org/x/crypto/ssh"
	"golang.org/x/crypto/ssh/agent"
)

// Config is the common configuration that communicators allow within
// a builder.
type Config struct {
	Type string `mapstructure:"communicator"`

	// SSH
	SSHHost                   string        `mapstructure:"ssh_host"`
	SSHPort                   int           `mapstructure:"ssh_port"`
	SSHUsername               string        `mapstructure:"ssh_username"`
	SSHPassword               string        `mapstructure:"ssh_password"`
	SSHPublicKey              []byte        `mapstructure:"ssh_public_key"`
	SSHPrivateKey             []byte        `mapstructure:"ssh_private_key"`
	SSHKeyPairName            string        `mapstructure:"ssh_keypair_name"`
	SSHPrivateKeyFile         string        `mapstructure:"ssh_private_key_file"`
	SSHPty                    bool          `mapstructure:"ssh_pty"`
	SSHTimeout                time.Duration `mapstructure:"ssh_timeout"`
	SSHAgentAuth              bool          `mapstructure:"ssh_agent_auth"`
	SSHDisableAgentForwarding bool          `mapstructure:"ssh_disable_agent_forwarding"`
	SSHHandshakeAttempts      int           `mapstructure:"ssh_handshake_attempts"`
	SSHBastionHost            string        `mapstructure:"ssh_bastion_host"`
	SSHBastionPort            int           `mapstructure:"ssh_bastion_port"`
	SSHBastionAgentAuth       bool          `mapstructure:"ssh_bastion_agent_auth"`
	SSHBastionUsername        string        `mapstructure:"ssh_bastion_username"`
	SSHBastionPassword        string        `mapstructure:"ssh_bastion_password"`
	SSHBastionPrivateKeyFile  string        `mapstructure:"ssh_bastion_private_key_file"`
	SSHFileTransferMethod     string        `mapstructure:"ssh_file_transfer_method"`
	SSHProxyHost              string        `mapstructure:"ssh_proxy_host"`
	SSHProxyPort              int           `mapstructure:"ssh_proxy_port"`
	SSHProxyUsername          string        `mapstructure:"ssh_proxy_username"`
	SSHProxyPassword          string        `mapstructure:"ssh_proxy_password"`
	SSHKeepAliveInterval      time.Duration `mapstructure:"ssh_keep_alive_interval"`
	SSHReadWriteTimeout       time.Duration `mapstructure:"ssh_read_write_timeout"`

	// WinRM
	WinRMUser               string        `mapstructure:"winrm_username"`
	WinRMPassword           string        `mapstructure:"winrm_password"`
	WinRMHost               string        `mapstructure:"winrm_host"`
	WinRMPort               int           `mapstructure:"winrm_port"`
	WinRMTimeout            time.Duration `mapstructure:"winrm_timeout"`
	WinRMUseSSL             bool          `mapstructure:"winrm_use_ssl"`
	WinRMInsecure           bool          `mapstructure:"winrm_insecure"`
	WinRMUseNTLM            bool          `mapstructure:"winrm_use_ntlm"`
	WinRMTransportDecorator func() winrm.Transporter
}

// SSHConfigFunc returns a function that can be used for the SSH communicator
// config for connecting to the instance created over SSH using the private key
// or password.
func (c *Config) SSHConfigFunc() func(multistep.StateBag) (*ssh.ClientConfig, error) {
	return func(state multistep.StateBag) (*ssh.ClientConfig, error) {
		sshConfig := &ssh.ClientConfig{
			User:            c.SSHUsername,
			HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		}

		if c.SSHAgentAuth {
			authSock := os.Getenv("SSH_AUTH_SOCK")
			if authSock == "" {
				return nil, fmt.Errorf("SSH_AUTH_SOCK is not set")
			}

			sshAgent, err := net.Dial("unix", authSock)
			if err != nil {
				return nil, fmt.Errorf("Cannot connect to SSH Agent socket %q: %s", authSock, err)
			}

			sshConfig.Auth = append(sshConfig.Auth, ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers))
		}

		var privateKeys [][]byte
		if c.SSHPrivateKeyFile != "" {
			// key based auth
			bytes, err := ioutil.ReadFile(c.SSHPrivateKeyFile)
			if err != nil {
				return nil, fmt.Errorf("Error setting up SSH config: %s", err)
			}
			privateKeys = append(privateKeys, bytes)
		}

		// aws,alicloud,cloudstack,digitalOcean,oneAndOne,openstack,oracle & profitbricks key
		if iKey, hasKey := state.GetOk("privateKey"); hasKey {
			privateKeys = append(privateKeys, []byte(iKey.(string)))
		}

		if len(c.SSHPrivateKey) != 0 {
			privateKeys = append(privateKeys, c.SSHPrivateKey)
		}

		for _, key := range privateKeys {
			signer, err := ssh.ParsePrivateKey(key)
			if err != nil {
				return nil, fmt.Errorf("Error setting up SSH config: %s", err)
			}
			sshConfig.Auth = append(sshConfig.Auth, ssh.PublicKeys(signer))
		}

		if c.SSHPassword != "" {
			sshConfig.Auth = append(sshConfig.Auth,
				ssh.Password(c.SSHPassword),
				ssh.KeyboardInteractive(packerssh.PasswordKeyboardInteractive(c.SSHPassword)),
			)
		}
		return sshConfig, nil
	}
}

// Port returns the port that will be used for access based on config.
func (c *Config) Port() int {
	switch c.Type {
	case "ssh":
		return c.SSHPort
	case "winrm":
		return c.WinRMPort
	default:
		return 0
	}
}

// Host returns the port that will be used for access based on config.
func (c *Config) Host() string {
	switch c.Type {
	case "ssh":
		return c.SSHHost
	case "winrm":
		return c.WinRMHost
	default:
		return ""
	}
}

// User returns the port that will be used for access based on config.
func (c *Config) User() string {
	switch c.Type {
	case "ssh":
		return c.SSHUsername
	case "winrm":
		return c.WinRMUser
	default:
		return ""
	}
}

// Password returns the port that will be used for access based on config.
func (c *Config) Password() string {
	switch c.Type {
	case "ssh":
		return c.SSHPassword
	case "winrm":
		return c.WinRMPassword
	default:
		return ""
	}
}

func (c *Config) Prepare(ctx *interpolate.Context) []error {
	if c.Type == "" {
		c.Type = "ssh"
	}

	var errs []error
	switch c.Type {
	case "ssh":
		if es := c.prepareSSH(ctx); len(es) > 0 {
			errs = append(errs, es...)
		}
	case "winrm":
		if es := c.prepareWinRM(ctx); len(es) > 0 {
			errs = append(errs, es...)
		}
	case "docker", "none":
		break
	default:
		return []error{fmt.Errorf("Communicator type %s is invalid", c.Type)}
	}

	return errs
}

func (c *Config) prepareSSH(ctx *interpolate.Context) []error {
	if c.SSHPort == 0 {
		c.SSHPort = 22
	}

	if c.SSHTimeout == 0 {
		c.SSHTimeout = 5 * time.Minute
	}

	if c.SSHKeepAliveInterval == 0 {
		c.SSHKeepAliveInterval = 5 * time.Second
	}

	if c.SSHHandshakeAttempts == 0 {
		c.SSHHandshakeAttempts = 10
	}

	if c.SSHBastionHost != "" {
		if c.SSHBastionPort == 0 {
			c.SSHBastionPort = 22
		}

		if c.SSHBastionPrivateKeyFile == "" && c.SSHPrivateKeyFile != "" {
			c.SSHBastionPrivateKeyFile = c.SSHPrivateKeyFile
		}
	}

	if c.SSHProxyHost != "" {
		if c.SSHProxyPort == 0 {
			c.SSHProxyPort = 1080
		}
	}

	if c.SSHFileTransferMethod == "" {
		c.SSHFileTransferMethod = "scp"
	}

	// Validation
	var errs []error
	if c.SSHUsername == "" {
		errs = append(errs, errors.New("An ssh_username must be specified\n  Note: some builders used to default ssh_username to \"root\"."))
	}

	if c.SSHPrivateKeyFile != "" {
		if _, err := os.Stat(c.SSHPrivateKeyFile); err != nil {
			errs = append(errs, fmt.Errorf(
				"ssh_private_key_file is invalid: %s", err))
		} else if _, err := helperssh.FileSigner(c.SSHPrivateKeyFile); err != nil {
			errs = append(errs, fmt.Errorf(
				"ssh_private_key_file is invalid: %s", err))
		}
	}

	if c.SSHBastionHost != "" && !c.SSHBastionAgentAuth {
		if c.SSHBastionPassword == "" && c.SSHBastionPrivateKeyFile == "" {
			errs = append(errs, errors.New(
				"ssh_bastion_password or ssh_bastion_private_key_file must be specified"))
		}
	}

	if c.SSHFileTransferMethod != "scp" && c.SSHFileTransferMethod != "sftp" {
		errs = append(errs, fmt.Errorf(
			"ssh_file_transfer_method ('%s') is invalid, valid methods: sftp, scp",
			c.SSHFileTransferMethod))
	}

	if c.SSHBastionHost != "" && c.SSHProxyHost != "" {
		errs = append(errs, errors.New("please specify either ssh_bastion_host or ssh_proxy_host, not both"))
	}

	return errs
}

func (c *Config) prepareWinRM(ctx *interpolate.Context) []error {
	if c.WinRMPort == 0 && c.WinRMUseSSL {
		c.WinRMPort = 5986
	} else if c.WinRMPort == 0 {
		c.WinRMPort = 5985
	}

	if c.WinRMTimeout == 0 {
		c.WinRMTimeout = 30 * time.Minute
	}

	if c.WinRMUseNTLM == true {
		c.WinRMTransportDecorator = func() winrm.Transporter { return &winrm.ClientNTLM{} }
	}

	var errs []error
	if c.WinRMUser == "" {
		errs = append(errs, errors.New("winrm_username must be specified."))
	}

	return errs
}
<commit_msg>add SSHTemporaryKeyPairName to communicator.Config<commit_after>package communicator

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"time"

	packerssh "github.com/hashicorp/packer/communicator/ssh"
	"github.com/hashicorp/packer/helper/multistep"
	helperssh "github.com/hashicorp/packer/helper/ssh"
	"github.com/hashicorp/packer/template/interpolate"
	"github.com/masterzen/winrm"
	"golang.org/x/crypto/ssh"
	"golang.org/x/crypto/ssh/agent"
)

// Config is the common configuration that communicators allow within
// a builder.
type Config struct {
	Type string `mapstructure:"communicator"`

	// SSH
	SSHHost                   string        `mapstructure:"ssh_host"`
	SSHPort                   int           `mapstructure:"ssh_port"`
	SSHUsername               string        `mapstructure:"ssh_username"`
	SSHPassword               string        `mapstructure:"ssh_password"`
	SSHPublicKey              []byte        `mapstructure:"ssh_public_key"`
	SSHPrivateKey             []byte        `mapstructure:"ssh_private_key"`
	SSHKeyPairName            string        `mapstructure:"ssh_keypair_name"`
	SSHTemporaryKeyPairName   string        `mapstructure:"temporary_key_pair_name"`
	SSHPrivateKeyFile         string        `mapstructure:"ssh_private_key_file"`
	SSHPty                    bool          `mapstructure:"ssh_pty"`
	SSHTimeout                time.Duration `mapstructure:"ssh_timeout"`
	SSHAgentAuth              bool          `mapstructure:"ssh_agent_auth"`
	SSHDisableAgentForwarding bool          `mapstructure:"ssh_disable_agent_forwarding"`
	SSHHandshakeAttempts      int           `mapstructure:"ssh_handshake_attempts"`
	SSHBastionHost            string        `mapstructure:"ssh_bastion_host"`
	SSHBastionPort            int           `mapstructure:"ssh_bastion_port"`
	SSHBastionAgentAuth       bool          `mapstructure:"ssh_bastion_agent_auth"`
	SSHBastionUsername        string        `mapstructure:"ssh_bastion_username"`
	SSHBastionPassword        string        `mapstructure:"ssh_bastion_password"`
	SSHBastionPrivateKeyFile  string        `mapstructure:"ssh_bastion_private_key_file"`
	SSHFileTransferMethod     string        `mapstructure:"ssh_file_transfer_method"`
	SSHProxyHost              string        `mapstructure:"ssh_proxy_host"`
	SSHProxyPort              int           `mapstructure:"ssh_proxy_port"`
	SSHProxyUsername          string        `mapstructure:"ssh_proxy_username"`
	SSHProxyPassword          string        `mapstructure:"ssh_proxy_password"`
	SSHKeepAliveInterval      time.Duration `mapstructure:"ssh_keep_alive_interval"`
	SSHReadWriteTimeout       time.Duration `mapstructure:"ssh_read_write_timeout"`

	// WinRM
	WinRMUser               string        `mapstructure:"winrm_username"`
	WinRMPassword           string        `mapstructure:"winrm_password"`
	WinRMHost               string        `mapstructure:"winrm_host"`
	WinRMPort               int           `mapstructure:"winrm_port"`
	WinRMTimeout            time.Duration `mapstructure:"winrm_timeout"`
	WinRMUseSSL             bool          `mapstructure:"winrm_use_ssl"`
	WinRMInsecure           bool          `mapstructure:"winrm_insecure"`
	WinRMUseNTLM            bool          `mapstructure:"winrm_use_ntlm"`
	WinRMTransportDecorator func() winrm.Transporter
}

// SSHConfigFunc returns a function that can be used for the SSH communicator
// config for connecting to the instance created over SSH using the private key
// or password.
func (c *Config) SSHConfigFunc() func(multistep.StateBag) (*ssh.ClientConfig, error) {
	return func(state multistep.StateBag) (*ssh.ClientConfig, error) {
		sshConfig := &ssh.ClientConfig{
			User:            c.SSHUsername,
			HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		}

		if c.SSHAgentAuth {
			authSock := os.Getenv("SSH_AUTH_SOCK")
			if authSock == "" {
				return nil, fmt.Errorf("SSH_AUTH_SOCK is not set")
			}

			sshAgent, err := net.Dial("unix", authSock)
			if err != nil {
				return nil, fmt.Errorf("Cannot connect to SSH Agent socket %q: %s", authSock, err)
			}

			sshConfig.Auth = append(sshConfig.Auth, ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers))
		}

		var privateKeys [][]byte
		if c.SSHPrivateKeyFile != "" {
			// key based auth
			bytes, err := ioutil.ReadFile(c.SSHPrivateKeyFile)
			if err != nil {
				return nil, fmt.Errorf("Error setting up SSH config: %s", err)
			}
			privateKeys = append(privateKeys, bytes)
		}

		// aws,alicloud,cloudstack,digitalOcean,oneAndOne,openstack,oracle & profitbricks key
		if iKey, hasKey := state.GetOk("privateKey"); hasKey {
			privateKeys = append(privateKeys, []byte(iKey.(string)))
		}

		if len(c.SSHPrivateKey) != 0 {
			privateKeys = append(privateKeys, c.SSHPrivateKey)
		}

		for _, key := range privateKeys {
			signer, err := ssh.ParsePrivateKey(key)
			if err != nil {
				return nil, fmt.Errorf("Error setting up SSH config: %s", err)
			}
			sshConfig.Auth = append(sshConfig.Auth, ssh.PublicKeys(signer))
		}

		if c.SSHPassword != "" {
			sshConfig.Auth = append(sshConfig.Auth,
				ssh.Password(c.SSHPassword),
				ssh.KeyboardInteractive(packerssh.PasswordKeyboardInteractive(c.SSHPassword)),
			)
		}
		return sshConfig, nil
	}
}

// Port returns the port that will be used for access based on config.
func (c *Config) Port() int {
	switch c.Type {
	case "ssh":
		return c.SSHPort
	case "winrm":
		return c.WinRMPort
	default:
		return 0
	}
}

// Host returns the port that will be used for access based on config.
func (c *Config) Host() string {
	switch c.Type {
	case "ssh":
		return c.SSHHost
	case "winrm":
		return c.WinRMHost
	default:
		return ""
	}
}

// User returns the port that will be used for access based on config.
func (c *Config) User() string {
	switch c.Type {
	case "ssh":
		return c.SSHUsername
	case "winrm":
		return c.WinRMUser
	default:
		return ""
	}
}

// Password returns the port that will be used for access based on config.
func (c *Config) Password() string {
	switch c.Type {
	case "ssh":
		return c.SSHPassword
	case "winrm":
		return c.WinRMPassword
	default:
		return ""
	}
}

func (c *Config) Prepare(ctx *interpolate.Context) []error {
	if c.Type == "" {
		c.Type = "ssh"
	}

	var errs []error
	switch c.Type {
	case "ssh":
		if es := c.prepareSSH(ctx); len(es) > 0 {
			errs = append(errs, es...)
		}
	case "winrm":
		if es := c.prepareWinRM(ctx); len(es) > 0 {
			errs = append(errs, es...)
		}
	case "docker", "none":
		break
	default:
		return []error{fmt.Errorf("Communicator type %s is invalid", c.Type)}
	}

	return errs
}

func (c *Config) prepareSSH(ctx *interpolate.Context) []error {
	if c.SSHPort == 0 {
		c.SSHPort = 22
	}

	if c.SSHTimeout == 0 {
		c.SSHTimeout = 5 * time.Minute
	}

	if c.SSHKeepAliveInterval == 0 {
		c.SSHKeepAliveInterval = 5 * time.Second
	}

	if c.SSHHandshakeAttempts == 0 {
		c.SSHHandshakeAttempts = 10
	}

	if c.SSHBastionHost != "" {
		if c.SSHBastionPort == 0 {
			c.SSHBastionPort = 22
		}

		if c.SSHBastionPrivateKeyFile == "" && c.SSHPrivateKeyFile != "" {
			c.SSHBastionPrivateKeyFile = c.SSHPrivateKeyFile
		}
	}

	if c.SSHProxyHost != "" {
		if c.SSHProxyPort == 0 {
			c.SSHProxyPort = 1080
		}
	}

	if c.SSHFileTransferMethod == "" {
		c.SSHFileTransferMethod = "scp"
	}

	// Validation
	var errs []error
	if c.SSHUsername == "" {
		errs = append(errs, errors.New("An ssh_username must be specified\n  Note: some builders used to default ssh_username to \"root\"."))
	}

	if c.SSHPrivateKeyFile != "" {
		if _, err := os.Stat(c.SSHPrivateKeyFile); err != nil {
			errs = append(errs, fmt.Errorf(
				"ssh_private_key_file is invalid: %s", err))
		} else if _, err := helperssh.FileSigner(c.SSHPrivateKeyFile); err != nil {
			errs = append(errs, fmt.Errorf(
				"ssh_private_key_file is invalid: %s", err))
		}
	}

	if c.SSHBastionHost != "" && !c.SSHBastionAgentAuth {
		if c.SSHBastionPassword == "" && c.SSHBastionPrivateKeyFile == "" {
			errs = append(errs, errors.New(
				"ssh_bastion_password or ssh_bastion_private_key_file must be specified"))
		}
	}

	if c.SSHFileTransferMethod != "scp" && c.SSHFileTransferMethod != "sftp" {
		errs = append(errs, fmt.Errorf(
			"ssh_file_transfer_method ('%s') is invalid, valid methods: sftp, scp",
			c.SSHFileTransferMethod))
	}

	if c.SSHBastionHost != "" && c.SSHProxyHost != "" {
		errs = append(errs, errors.New("please specify either ssh_bastion_host or ssh_proxy_host, not both"))
	}

	return errs
}

func (c *Config) prepareWinRM(ctx *interpolate.Context) []error {
	if c.WinRMPort == 0 && c.WinRMUseSSL {
		c.WinRMPort = 5986
	} else if c.WinRMPort == 0 {
		c.WinRMPort = 5985
	}

	if c.WinRMTimeout == 0 {
		c.WinRMTimeout = 30 * time.Minute
	}

	if c.WinRMUseNTLM == true {
		c.WinRMTransportDecorator = func() winrm.Transporter { return &winrm.ClientNTLM{} }
	}

	var errs []error
	if c.WinRMUser == "" {
		errs = append(errs, errors.New("winrm_username must be specified."))
	}

	return errs
}
<|endoftext|>


<commit_before>package atomic

import (
	"io/ioutil"
	"os"
	"path/filepath"

	. "gopkg.in/check.v1"
)

const (
	// default permissions
	defaultFilePerms = 0600
)

type WriterTests struct {
	dir string
}

var _ = Suite(&WriterTests{})

func (t *WriterTests) SetUpTest(c *C) {
	t.dir = c.MkDir()
}

func (t *WriterTests) TestTmpFileCreation(c *C) {
	testFilePath := filepath.Join(t.dir, "testfile")
	writer, err := NewWriter(testFilePath, "testprefix", defaultFilePerms)
	c.Assert(err, IsNil)

	_, err = os.Stat(writer.tmpPath())
	c.Assert(err, IsNil)

	_, err = os.Stat(testFilePath)
	c.Assert(os.IsNotExist(err), Equals, true)
}

func (t *WriterTests) TestClose(c *C) {
	testFilePath := filepath.Join(t.dir, "testfile")
	writer, err := NewWriter(testFilePath, "testprefix", defaultFilePerms)
	c.Assert(err, IsNil)

	err = writer.Close()
	c.Assert(err, IsNil)

	_, err = os.Stat(writer.tmpPath())
	c.Assert(os.IsNotExist(err), Equals, true)

	_, err = os.Stat(testFilePath)
	c.Assert(err, IsNil)
}

func (t *WriterTests) TestWrite(c *C) {
	testFilePath := filepath.Join(t.dir, "testfile")
	writer, err := NewWriter(testFilePath, "testprefix", defaultFilePerms)
	c.Assert(err, IsNil)

	testBytes := []byte("This is a small test")
	_, err = writer.Write(testBytes)
	c.Assert(err, IsNil)

	err = writer.Close()
	c.Assert(err, IsNil)

	data, err := ioutil.ReadFile(testFilePath)
	c.Assert(err, IsNil)

	c.Assert(data, DeepEquals, testBytes)
}

func (t *WriterTests) TestFileModeWrite(c *C) {
	testFilePath := filepath.Join(t.dir, "testfile")
	writer, err := NewStandardWriter(testFilePath, 0770)

	writer.Close()

	stat, err := os.Stat(testFilePath)
	c.Assert(err, IsNil)
	var fileMode os.FileMode
	fileMode = 0770

	c.Assert(stat.Mode(), Equals, fileMode)
}

func (t *WriterTests) TestAbort(c *C) {
	testFilePath := filepath.Join(t.dir, "testfile")
	writer, err := NewStandardWriter(testFilePath, 0770)
	c.Assert(err, IsNil)
	writer.Write([]byte("this is a testfile"))
	writer.Abort()
	err = writer.Close()
	c.Assert(err, IsNil)

	_, err = os.Stat(testFilePath)
	c.Assert(os.IsNotExist(err), Equals, true)
}

func (t *WriterTests) TestAbortNoOverwrite(c *C) {
	testFilePath := filepath.Join(t.dir, "testfile")
	oldFileData := []byte("oldfiledata")
	err := ioutil.WriteFile(testFilePath, oldFileData, defaultFilePerms)
	c.Assert(err, IsNil)
	writer, err := NewStandardWriter(testFilePath, 0770)
	c.Assert(err, IsNil)

	writer.Write([]byte("newfiledata"))
	writer.Abort()
	writer.Close()
	d, err := ioutil.ReadFile(testFilePath)
	c.Assert(d, DeepEquals, oldFileData)
}
<commit_msg>helpers: skipping a file permission set check on the windows platform.<commit_after>package atomic

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"

	. "gopkg.in/check.v1"
)

const (
	// default permissions
	defaultFilePerms = 0600
)

type WriterTests struct {
	dir string
}

var _ = Suite(&WriterTests{})

func (t *WriterTests) SetUpTest(c *C) {
	t.dir = c.MkDir()
}

func (t *WriterTests) TestTmpFileCreation(c *C) {
	testFilePath := filepath.Join(t.dir, "testfile")
	writer, err := NewWriter(testFilePath, "testprefix", defaultFilePerms)
	c.Assert(err, IsNil)

	_, err = os.Stat(writer.tmpPath())
	c.Assert(err, IsNil)

	_, err = os.Stat(testFilePath)
	c.Assert(os.IsNotExist(err), Equals, true)
}

func (t *WriterTests) TestClose(c *C) {
	testFilePath := filepath.Join(t.dir, "testfile")
	writer, err := NewWriter(testFilePath, "testprefix", defaultFilePerms)
	c.Assert(err, IsNil)

	err = writer.Close()
	c.Assert(err, IsNil)

	_, err = os.Stat(writer.tmpPath())
	c.Assert(os.IsNotExist(err), Equals, true)

	_, err = os.Stat(testFilePath)
	c.Assert(err, IsNil)
}

func (t *WriterTests) TestWrite(c *C) {
	testFilePath := filepath.Join(t.dir, "testfile")
	writer, err := NewWriter(testFilePath, "testprefix", defaultFilePerms)
	c.Assert(err, IsNil)

	testBytes := []byte("This is a small test")
	_, err = writer.Write(testBytes)
	c.Assert(err, IsNil)

	err = writer.Close()
	c.Assert(err, IsNil)

	data, err := ioutil.ReadFile(testFilePath)
	c.Assert(err, IsNil)

	c.Assert(data, DeepEquals, testBytes)
}

func (t *WriterTests) TestFileModeWrite(c *C) {
	if runtime.GOOS == "windows" {
		c.Skip("File Mode is not set on windows at the moment.")
		return
	}

	testFilePath := filepath.Join(t.dir, "testfile")
	writer, err := NewStandardWriter(testFilePath, 0770)

	writer.Close()

	stat, err := os.Stat(testFilePath)
	c.Assert(err, IsNil)
	var fileMode os.FileMode
	fileMode = 0770

	c.Assert(stat.Mode(), Equals, fileMode)
}

func (t *WriterTests) TestAbort(c *C) {
	testFilePath := filepath.Join(t.dir, "testfile")
	writer, err := NewStandardWriter(testFilePath, 0770)
	c.Assert(err, IsNil)
	writer.Write([]byte("this is a testfile"))
	writer.Abort()
	err = writer.Close()
	c.Assert(err, IsNil)

	_, err = os.Stat(testFilePath)
	c.Assert(os.IsNotExist(err), Equals, true)
}

func (t *WriterTests) TestAbortNoOverwrite(c *C) {
	testFilePath := filepath.Join(t.dir, "testfile")
	oldFileData := []byte("oldfiledata")
	err := ioutil.WriteFile(testFilePath, oldFileData, defaultFilePerms)
	c.Assert(err, IsNil)
	writer, err := NewStandardWriter(testFilePath, 0770)
	c.Assert(err, IsNil)

	writer.Write([]byte("newfiledata"))
	writer.Abort()
	writer.Close()
	d, err := ioutil.ReadFile(testFilePath)
	c.Assert(d, DeepEquals, oldFileData)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
)

type Record struct {
	Content      string
	DomainID     int64 `json:"domain_id"`
	ID           int64
	Name         string
	RecordType   string `json:"record_type"`
	SystemRecord bool   `json:"system_record"`
}

type MultipleRecords struct {
	Record Record
}

func listRecordsDomain(domain string) {
	// Default domain is empty, use the value from the cli
	if domain != "" {
		config.Domain = domain
	} else if config.Domain == "" {
		fmt.Println("Set a domain in your configuration file or provide one.")
		os.Exit(1)
	}

	// Compose url and headers
	url := config.ApiURL + config.Domain + "/records/"
	r := setHeaders("GET", url)
	httpClient := http.Client{}

	response, err := httpClient.Do(r)
	if err != nil {
		log.Fatal("HTTPClient: ", err)
	}
	defer response.Body.Close()

	dataResponse := new([]MultipleRecords)
	err = json.NewDecoder(response.Body).Decode(&dataResponse)
	if err != nil {
		log.Fatal("Decode-Body: ", err)
	}

	//TODO: Filter and process response
	fmt.Println(dataResponse)
}
<commit_msg>Better struct to work with records<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
)

type Record struct {
	Content      string
	DomainID     int64 `json:"domain_id"`
	ID           int64
	Name         string
	RecordType   string `json:"record_type"`
	SystemRecord bool   `json:"system_record"`
	TTL          int
}

func (r *Record) String() string {
	return "Record"
}

type MultipleRecords []map[string]Record

func listRecordsDomain(domain string) {
	// Default domain is empty, use the value from the cli
	if domain != "" {
		config.Domain = domain
	} else if config.Domain == "" {
		fmt.Println("Set a domain in your configuration file or provide one.")
		os.Exit(1)
	}

	// Compose url and headers
	url := config.ApiURL + config.Domain + "/records/"
	r := setHeaders("GET", url)
	httpClient := http.Client{}

	response, err := httpClient.Do(r)
	if err != nil {
		log.Fatal("HTTPClient: ", err)
	}
	defer response.Body.Close()

	dataResponse := MultipleRecords{}
	err = json.NewDecoder(response.Body).Decode(&dataResponse)
	if err != nil {
		log.Fatal("Decode-Body: ", err)
	}

	//TODO: Filter and process response
	filterRecords(dataResponse)
}
<|endoftext|>


<commit_before>package shell

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"os/exec"
	"os/signal"
	"path"
	"path/filepath"
	"strings"
	"syscall"

	"github.com/buildkite/agent/env"
	"github.com/buildkite/agent/process"
	shellwords "github.com/mattn/go-shellwords"
)

// Shell represents a virtual shell, handles logging, executing commands and
// provides hooks for capturing output and exit conditions.
//
// Provides a lowest-common denominator abstraction over macOS, Linux and Windows
type Shell struct {
	Logger

	// The running environment for the shell
	Env *env.Environment

	// Whether the shell is a PTY
	PTY bool

	// Current working directory that shell commands get executed in
	wd string

	// The context for the shell
	ctx context.Context
}

// New returns a new Shell
func New() (*Shell, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, fmt.Errorf("Failed to find current working directory: %v", err)
	}

	return &Shell{
		Logger: StderrLogger,
		Env:    env.FromSlice(os.Environ()),
		wd:     wd,
		ctx:    context.Background(),
	}, nil
}

// Getwd returns the current working directory of the shell
func (s *Shell) Getwd() string {
	return s.wd
}

// Chdir changes the working directory of the shell
func (s *Shell) Chdir(path string) error {
	// If the path isn't absolute, prefix it with the current working directory.
	if !filepath.IsAbs(path) {
		path = filepath.Join(s.wd, path)
	}

	s.Commentf("Changing working directory to \"%s\"", path)

	if _, err := os.Stat(path); err != nil {
		return fmt.Errorf("Failed to change working: directory does not exist")
	}

	s.wd = path
	return nil
}

// AbsolutePath returns the absolute path to an executable based on the PATH and
// PATHEXT of the Shell
func (s *Shell) AbsolutePath(executable string) (string, error) {
	// Is the path already absolute?
	if path.IsAbs(executable) {
		return executable, nil
	}

	var envPath = s.Env.Get("PATH")
	var fileExtensions = s.Env.Get("PATHEXT") // For searching .exe, .bat, etc on Windows

	// Use our custom lookPath that takes a specific path
	absolutePath, err := lookPath(executable, envPath, fileExtensions)
	if err != nil {
		return "", err
	}

	// Since the path returned by LookPath is relative to the current working
	// directory, we need to get the absolute version of that.
	return filepath.Abs(absolutePath)
}

// Run runs a command, write to the logger and return an error if it fails
func (s *Shell) Run(command string, args ...interface{}) error {
	words, err := shellwords.Parse(fmt.Sprintf(command, args...))
	if err != nil {
		return err
	}

	cmd, err := s.buildCommand(words[0], words[1:]...)
	if err != nil {
		s.Errorf("Error building command: %v", err)
		return err
	}

	return s.executeCommand(cmd, os.Stderr, false)
}

// RunAndCapture runs a command and captures the output, nothing else is logged
func (s *Shell) RunAndCapture(command string, args ...interface{}) (string, error) {
	words, err := shellwords.Parse(fmt.Sprintf(command, args...))
	if err != nil {
		return "", err
	}

	cmd, err := s.buildCommand(words[0], words[1:]...)
	if err != nil {
		return "", err
	}

	var b bytes.Buffer

	err = s.executeCommand(cmd, &b, true)
	if err != nil {
		return "", err
	}

	return strings.TrimSpace(b.String()), nil
}

// buildCommand returns an exec.Cmd that runs in the context of the shell
func (s *Shell) buildCommand(command string, args ...string) (*exec.Cmd, error) {
	// Always use absolute path as Windows has a hard time finding executables in it's path
	absPath, err := s.AbsolutePath(command)
	if err != nil {
		return nil, err
	}

	cmd := exec.Command(absPath, args...)
	cmd.Env = s.Env.ToSlice()
	cmd.Dir = s.wd

	return cmd, nil
}

func (s *Shell) executeCommand(cmd *exec.Cmd, w io.Writer, silent bool) error {
	signals := make(chan os.Signal, 1)
	signal.Notify(signals, os.Interrupt,
		syscall.SIGHUP,
		syscall.SIGTERM,
		syscall.SIGINT,
		syscall.SIGQUIT)
	defer signal.Stop(signals)

	var handleError = func(prefix string, err error) error {
		if !silent {
			s.Errorf("%s%v", prefix, err)
		}
		return err
	}

	go func() {
		// forward signals to the process
		for sig := range signals {
			if err := signalProcess(cmd, sig); err != nil {
				_ = handleError("Error passing signal to child process: ", err)
			}
		}
	}()

	cmdStr := process.FormatCommand(cmd.Path, cmd.Args)
	if silent {
		s.Promptf("%s", cmdStr)
	}

	if s.PTY {
		pty, err := process.StartPTY(cmd)
		if err != nil {
			return handleError("Error starting PTY: ", err)
		}

		// Copy the pty to our buffer. This will block until it EOF's
		// or something breaks.
		_, err = io.Copy(w, pty)
		if e, ok := err.(*os.PathError); ok && e.Err == syscall.EIO {
			// We can safely ignore this error, because it's just the PTY telling us
			// that it closed successfully.
			// See https://github.com/buildkite/agent/pull/34#issuecomment-46080419
		}
	} else {
		cmd.Stdout = w
		cmd.Stderr = w
		cmd.Stdin = nil

		if err := cmd.Start(); err != nil {
			return handleError(fmt.Sprintf("Error starting `%s`: ", cmdStr), err)
		}
	}

	if err := cmd.Wait(); err != nil {
		return handleError(fmt.Sprintf("Error running `%s`: ", cmdStr), err)
	}

	return nil
}

// Quote takes a line of commands and uses shell word splitting on them and then
// quotes anything with spaces or special characters. This is used or making things
// like sets of flags safe to literally include in commands
func QuoteArguments(line string) (string, error) {
	words, err := shellwords.Parse(line)
	if err != nil {
		return "", err
	}
	for idx, word := range words {
		words[idx] = fmt.Sprintf("%q", word)
	}
	return strings.Join(words, " "), nil
}

// GetExitCode extracts an exit code from an error where the platform supports it,
// otherwise returns 0 for no error and 1 for an error
func GetExitCode(err error) int {
	if err == nil {
		return 0
	}
	if exiterr, ok := err.(*exec.ExitError); ok {
		// The program has exited with an exit code != 0
		// There is no platform independent way to retrieve
		// the exit code, but the following will work on Unix/macOS
		if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
			return status.ExitStatus()
		}
	}
	return 1
}
<commit_msg>Cmd.Args includes the Path as arg 0<commit_after>package shell

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"os/exec"
	"os/signal"
	"path"
	"path/filepath"
	"strings"
	"syscall"

	"github.com/buildkite/agent/env"
	"github.com/buildkite/agent/process"
	shellwords "github.com/mattn/go-shellwords"
)

// Shell represents a virtual shell, handles logging, executing commands and
// provides hooks for capturing output and exit conditions.
//
// Provides a lowest-common denominator abstraction over macOS, Linux and Windows
type Shell struct {
	Logger

	// The running environment for the shell
	Env *env.Environment

	// Whether the shell is a PTY
	PTY bool

	// Current working directory that shell commands get executed in
	wd string

	// The context for the shell
	ctx context.Context
}

// New returns a new Shell
func New() (*Shell, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, fmt.Errorf("Failed to find current working directory: %v", err)
	}

	return &Shell{
		Logger: StderrLogger,
		Env:    env.FromSlice(os.Environ()),
		wd:     wd,
		ctx:    context.Background(),
	}, nil
}

// Getwd returns the current working directory of the shell
func (s *Shell) Getwd() string {
	return s.wd
}

// Chdir changes the working directory of the shell
func (s *Shell) Chdir(path string) error {
	// If the path isn't absolute, prefix it with the current working directory.
	if !filepath.IsAbs(path) {
		path = filepath.Join(s.wd, path)
	}

	s.Commentf("Changing working directory to \"%s\"", path)

	if _, err := os.Stat(path); err != nil {
		return fmt.Errorf("Failed to change working: directory does not exist")
	}

	s.wd = path
	return nil
}

// AbsolutePath returns the absolute path to an executable based on the PATH and
// PATHEXT of the Shell
func (s *Shell) AbsolutePath(executable string) (string, error) {
	// Is the path already absolute?
	if path.IsAbs(executable) {
		return executable, nil
	}

	var envPath = s.Env.Get("PATH")
	var fileExtensions = s.Env.Get("PATHEXT") // For searching .exe, .bat, etc on Windows

	// Use our custom lookPath that takes a specific path
	absolutePath, err := lookPath(executable, envPath, fileExtensions)
	if err != nil {
		return "", err
	}

	// Since the path returned by LookPath is relative to the current working
	// directory, we need to get the absolute version of that.
	return filepath.Abs(absolutePath)
}

// Run runs a command, write to the logger and return an error if it fails
func (s *Shell) Run(command string, args ...interface{}) error {
	words, err := shellwords.Parse(fmt.Sprintf(command, args...))
	if err != nil {
		return err
	}

	cmd, err := s.buildCommand(words[0], words[1:]...)
	if err != nil {
		s.Errorf("Error building command: %v", err)
		return err
	}

	return s.executeCommand(cmd, os.Stderr, false)
}

// RunAndCapture runs a command and captures the output, nothing else is logged
func (s *Shell) RunAndCapture(command string, args ...interface{}) (string, error) {
	words, err := shellwords.Parse(fmt.Sprintf(command, args...))
	if err != nil {
		return "", err
	}

	cmd, err := s.buildCommand(words[0], words[1:]...)
	if err != nil {
		return "", err
	}

	var b bytes.Buffer

	err = s.executeCommand(cmd, &b, true)
	if err != nil {
		return "", err
	}

	return strings.TrimSpace(b.String()), nil
}

// buildCommand returns an exec.Cmd that runs in the context of the shell
func (s *Shell) buildCommand(command string, args ...string) (*exec.Cmd, error) {
	// Always use absolute path as Windows has a hard time finding executables in it's path
	absPath, err := s.AbsolutePath(command)
	if err != nil {
		return nil, err
	}

	cmd := exec.Command(absPath, args...)
	cmd.Env = s.Env.ToSlice()
	cmd.Dir = s.wd

	return cmd, nil
}

func (s *Shell) executeCommand(cmd *exec.Cmd, w io.Writer, silent bool) error {
	signals := make(chan os.Signal, 1)
	signal.Notify(signals, os.Interrupt,
		syscall.SIGHUP,
		syscall.SIGTERM,
		syscall.SIGINT,
		syscall.SIGQUIT)
	defer signal.Stop(signals)

	var handleError = func(prefix string, err error) error {
		if !silent {
			s.Errorf("%s%v", prefix, err)
		}
		return err
	}

	go func() {
		// forward signals to the process
		for sig := range signals {
			if err := signalProcess(cmd, sig); err != nil {
				_ = handleError("Error passing signal to child process: ", err)
			}
		}
	}()

	cmdStr := process.FormatCommand(cmd.Path, cmd.Args[1:])
	if silent {
		s.Promptf("%s", cmdStr)
	}

	if s.PTY {
		pty, err := process.StartPTY(cmd)
		if err != nil {
			return handleError("Error starting PTY: ", err)
		}

		// Copy the pty to our buffer. This will block until it EOF's
		// or something breaks.
		_, err = io.Copy(w, pty)
		if e, ok := err.(*os.PathError); ok && e.Err == syscall.EIO {
			// We can safely ignore this error, because it's just the PTY telling us
			// that it closed successfully.
			// See https://github.com/buildkite/agent/pull/34#issuecomment-46080419
		}
	} else {
		cmd.Stdout = w
		cmd.Stderr = w
		cmd.Stdin = nil

		if err := cmd.Start(); err != nil {
			return handleError(fmt.Sprintf("Error starting `%s`: ", cmdStr), err)
		}
	}

	if err := cmd.Wait(); err != nil {
		return handleError(fmt.Sprintf("Error running `%s`: ", cmdStr), err)
	}

	return nil
}

// Quote takes a line of commands and uses shell word splitting on them and then
// quotes anything with spaces or special characters. This is used or making things
// like sets of flags safe to literally include in commands
func QuoteArguments(line string) (string, error) {
	words, err := shellwords.Parse(line)
	if err != nil {
		return "", err
	}
	for idx, word := range words {
		words[idx] = fmt.Sprintf("%q", word)
	}
	return strings.Join(words, " "), nil
}

// GetExitCode extracts an exit code from an error where the platform supports it,
// otherwise returns 0 for no error and 1 for an error
func GetExitCode(err error) int {
	if err == nil {
		return 0
	}
	if exiterr, ok := err.(*exec.ExitError); ok {
		// The program has exited with an exit code != 0
		// There is no platform independent way to retrieve
		// the exit code, but the following will work on Unix/macOS
		if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
			return status.ExitStatus()
		}
	}
	return 1
}
<|endoftext|>


<commit_before>// +build darwin dragonfly freebsd netbsd openbsd

import "log"

func checkprivsep(l *log.Logger) {
}
<commit_msg>Add missing package decl.<commit_after>// +build darwin dragonfly freebsd netbsd openbsd

package bot

import "log"

func checkprivsep(l *log.Logger) {
}
<|endoftext|>


<commit_before>package interfaces

type Message struct {
}

func (message *Message) DecodeRecord(record interface{}) error {
	return nil
}

func (message *Message) DecodeRequest(request map[string]interface{}) error {
	return nil
}
<commit_msg>Rename interface.Message to LogEntry<commit_after>package interfaces

// LogEntry is an interface consisted of a ``message`` arg, an an optional
// ``params`` arg for formatting, and an optional ``formatted`` message which
// is the result of ``message`` combined with ``params``.
//
// If your message cannot be parameterized, then the message interface
// will serve no benefit.
//
// - ``message`` must be no more than 1000 characters in length.
//
// {
//     "message": "My raw message with interpreted strings like %s",
//     "formatted": "My raw message with interpreted strings like this",
//     "params": ["this"]
// }
type LogEntry struct {
	Message   string        `kv:"message"   in:"message"   json:"-"`
	Formatted string        `kv:"formatted" in:"formatted" json:"-"`
	Params    []interface{} `kv:"params"    in:"params"    json:"-"`
}

func (entry *LogEntry) DecodeRecord(record interface{}) error {
	return nil
}

func (entry *LogEntry) DecodeRequest(request map[string]interface{}) error {
	err := DecodeRequest("logentry", "sentry.interfaces.Message", request, entry)
	return err
}
<|endoftext|>


<commit_before>package kv

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/movio/kasper/util"
	"golang.org/x/net/context"
	elastic "gopkg.in/olivere/elastic.v5"
	"log"
)

const indexSettings = `{
	"index.translog.durability": "async",
	"index.translog.sync_interval": "60s",
	"index.translog.flush_threshold_size": "512m"
}`

const indexMapping = `{
	"_all" : {
		"enabled" : false
	},
	"dynamic_templates": [{
		"no_index": {
			"mapping": {
				"index": "no"
			},
			"match": "*"
		}
	}]
}`

// ElasticsearchKeyValueStore is a key-value storage that uses ElasticSearch.
// In this key-value store, all keys must have the format "<index>/<type>/<_id>".
// For performance reasons, this implementation create indexes with async durability.
// You must call Flush() at appropriate times to ensure Elasticsearch syncs it's translog to disk.
// See: https://www.elastic.co/products/elasticsearch
type ElasticsearchKeyValueStore struct {
	witness         *util.StructPtrWitness
	client          *elastic.Client
	context         context.Context
	existingIndexes []string
}

// NewElasticsearchKeyValueStore creates new ElasticsearchKeyValueStore instance.
// Host must of the format hostname:port.
// StructPtr should be a pointer to struct type that is used
// for serialization and deserialization of store values.
func NewElasticsearchKeyValueStore(host string, structPtr interface{}) *ElasticsearchKeyValueStore {
	url := fmt.Sprintf("http://%s", host)
	client, err := elastic.NewClient(
		elastic.SetURL(url),
		elastic.SetSniff(false), // FIXME: workaround for issues with ES in docker
	)
	if err != nil {
		panic(fmt.Sprintf("Cannot create ElasticSearch Client to '%s': %s", url, err))
	}
	return &ElasticsearchKeyValueStore{
		witness: util.NewStructPtrWitness(structPtr),
		client:  client,
		context: context.Background(),
	}
}

func (s *ElasticsearchKeyValueStore) checkOrCreateIndex(indexName string, indexType string) {
	index := strings.Join([]string{indexName, indexType}, "/")
	for _, existingIndex := range s.existingIndexes {
		if existingIndex == index {
			return
		}
	}
	exists, err := s.client.IndexExists(indexName).Do(s.context)
	if err != nil {
		panic(fmt.Sprintf("Failed to check if index exists: %s", err))
	}
	if !exists {
		_, err = s.client.CreateIndex(indexName).BodyString(indexSettings).Do(s.context)
		if err != nil {
			panic(fmt.Sprintf("Failed to create index: %s", err))
		}
		s.putMapping(indexName, indexType)
	}

	s.existingIndexes = append(s.existingIndexes, index)
}

func (s *ElasticsearchKeyValueStore) putMapping(indexName string, indexType string) {
	resp, err := s.client.PutMapping().Index(indexName).Type(indexType).BodyString(indexMapping).Do(s.context)
	if err != nil {
		panic(fmt.Sprintf("Failed to put mapping for index: %s/%s: %s", indexName, indexType, err))
	}
	if resp == nil {
		panic(fmt.Sprintf("Expected put mapping response; got: %v", resp))
	}
	if !resp.Acknowledged {
		panic(fmt.Sprintf("Expected put mapping ack; got: %v", resp.Acknowledged))
	}
}

// Get gets value by key from store
func (s *ElasticsearchKeyValueStore) Get(key string) (interface{}, error) {
	keyParts := strings.Split(key, "/")
	if len(keyParts) != 3 {
		return nil, fmt.Errorf("invalid key: '%s'", key)
	}
	indexName := keyParts[0]
	indexType := keyParts[1]
	valueID := keyParts[2]

	s.checkOrCreateIndex(indexName, indexType)

	rawValue, err := s.client.Get().
		Index(indexName).
		Type(indexType).
		Id(valueID).
		Do(s.context)

	if fmt.Sprintf("%s", err) == "elastic: Error 404 (Not Found)" {
		return s.witness.Nil(), nil
	}

	if err != nil {
		return s.witness.Nil(), err
	}

	if !rawValue.Found {
		return s.witness.Nil(), nil
	}

	structPtr := s.witness.Allocate()
	err = json.Unmarshal(*rawValue.Source, structPtr)
	if err != nil {
		return s.witness.Nil(), err
	}
	return structPtr, nil
}

// Put updates key in store with serialized value
func (s *ElasticsearchKeyValueStore) Put(key string, structPtr interface{}) error {
	s.witness.Assert(structPtr)
	keyParts := strings.Split(key, "/")
	if len(keyParts) != 3 {
		return fmt.Errorf("invalid key: '%s'", key)
	}
	indexName := keyParts[0]
	indexType := keyParts[1]
	valueID := keyParts[2]

	s.checkOrCreateIndex(indexName, indexType)

	_, err := s.client.Index().
		Index(indexName).
		Type(indexType).
		Id(valueID).
		BodyJson(structPtr).
		Do(s.context)

	return err
}

func (s *ElasticsearchKeyValueStore) PutAll(entries []*Entry) error {
	bulk := s.client.Bulk()
	for _, entry := range entries {
		keyParts := strings.Split(entry.key, "/")
		if len(keyParts) != 3 {
			return fmt.Errorf("invalid key: '%s'", entry.key)
		}
		indexName := keyParts[0]
		indexType := keyParts[1]
		valueID := keyParts[2]
		s.witness.Assert(entry.value)
		bulk.Add(elastic.NewBulkIndexRequest().
			Index(indexName).
			Type(indexType).
			Id(valueID).
			Doc(entry.value),
		)
	}
	_, err := bulk.Do(s.context)
	return err
}

// Delete removes key from store
func (s *ElasticsearchKeyValueStore) Delete(key string) error {
	keyParts := strings.Split(key, "/")
	if len(keyParts) != 3 {
		return fmt.Errorf("invalid key: '%s'", key)
	}
	indexName := keyParts[0]
	indexType := keyParts[1]
	valueID := keyParts[2]

	s.checkOrCreateIndex(indexName, indexType)

	_, err := s.client.Delete().
		Index(indexName).
		Type(indexType).
		Id(valueID).
		Do(s.context)

	return err
}

// Flush the Elasticsearch translog to disk
func (s* ElasticsearchKeyValueStore) Flush() error {
	log.Println("Flusing ES indexes...")
	_, err := s.client.Flush(s.existingIndexes...).
		WaitIfOngoing(true).
		Do(s.context)
	log.Println("Done flusing ES indexes.")
	return err
}
<commit_msg>Fix bug: PutAll must create ES index if necessary<commit_after>package kv

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/movio/kasper/util"
	"golang.org/x/net/context"
	elastic "gopkg.in/olivere/elastic.v5"
	"log"
)

const indexSettings = `{
	"index.translog.durability": "async",
	"index.translog.sync_interval": "60s",
	"index.translog.flush_threshold_size": "512m"
}`

const indexMapping = `{
	"_all" : {
		"enabled" : false
	},
	"dynamic_templates": [{
		"no_index": {
			"mapping": {
				"index": "no"
			},
			"match": "*"
		}
	}]
}`

// ElasticsearchKeyValueStore is a key-value storage that uses ElasticSearch.
// In this key-value store, all keys must have the format "<index>/<type>/<_id>".
// For performance reasons, this implementation create indexes with async durability.
// You must call Flush() at appropriate times to ensure Elasticsearch syncs it's translog to disk.
// See: https://www.elastic.co/products/elasticsearch
type ElasticsearchKeyValueStore struct {
	witness         *util.StructPtrWitness
	client          *elastic.Client
	context         context.Context
	existingIndexes []string
}

// NewElasticsearchKeyValueStore creates new ElasticsearchKeyValueStore instance.
// Host must of the format hostname:port.
// StructPtr should be a pointer to struct type that is used
// for serialization and deserialization of store values.
func NewElasticsearchKeyValueStore(host string, structPtr interface{}) *ElasticsearchKeyValueStore {
	url := fmt.Sprintf("http://%s", host)
	client, err := elastic.NewClient(
		elastic.SetURL(url),
		elastic.SetSniff(false), // FIXME: workaround for issues with ES in docker
	)
	if err != nil {
		panic(fmt.Sprintf("Cannot create ElasticSearch Client to '%s': %s", url, err))
	}
	return &ElasticsearchKeyValueStore{
		witness: util.NewStructPtrWitness(structPtr),
		client:  client,
		context: context.Background(),
	}
}

func (s *ElasticsearchKeyValueStore) checkOrCreateIndex(indexName string, indexType string) {
	index := strings.Join([]string{indexName, indexType}, "/")
	for _, existingIndex := range s.existingIndexes {
		if existingIndex == index {
			return
		}
	}
	exists, err := s.client.IndexExists(indexName).Do(s.context)
	if err != nil {
		panic(fmt.Sprintf("Failed to check if index exists: %s", err))
	}
	if !exists {
		_, err = s.client.CreateIndex(indexName).BodyString(indexSettings).Do(s.context)
		if err != nil {
			panic(fmt.Sprintf("Failed to create index: %s", err))
		}
		s.putMapping(indexName, indexType)
	}

	s.existingIndexes = append(s.existingIndexes, index)
}

func (s *ElasticsearchKeyValueStore) putMapping(indexName string, indexType string) {
	resp, err := s.client.PutMapping().Index(indexName).Type(indexType).BodyString(indexMapping).Do(s.context)
	if err != nil {
		panic(fmt.Sprintf("Failed to put mapping for index: %s/%s: %s", indexName, indexType, err))
	}
	if resp == nil {
		panic(fmt.Sprintf("Expected put mapping response; got: %v", resp))
	}
	if !resp.Acknowledged {
		panic(fmt.Sprintf("Expected put mapping ack; got: %v", resp.Acknowledged))
	}
}

// Get gets value by key from store
func (s *ElasticsearchKeyValueStore) Get(key string) (interface{}, error) {
	keyParts := strings.Split(key, "/")
	if len(keyParts) != 3 {
		return nil, fmt.Errorf("invalid key: '%s'", key)
	}
	indexName := keyParts[0]
	indexType := keyParts[1]
	valueID := keyParts[2]

	s.checkOrCreateIndex(indexName, indexType)

	rawValue, err := s.client.Get().
		Index(indexName).
		Type(indexType).
		Id(valueID).
		Do(s.context)

	if fmt.Sprintf("%s", err) == "elastic: Error 404 (Not Found)" {
		return s.witness.Nil(), nil
	}

	if err != nil {
		return s.witness.Nil(), err
	}

	if !rawValue.Found {
		return s.witness.Nil(), nil
	}

	structPtr := s.witness.Allocate()
	err = json.Unmarshal(*rawValue.Source, structPtr)
	if err != nil {
		return s.witness.Nil(), err
	}
	return structPtr, nil
}

// Put updates key in store with serialized value
func (s *ElasticsearchKeyValueStore) Put(key string, structPtr interface{}) error {
	s.witness.Assert(structPtr)
	keyParts := strings.Split(key, "/")
	if len(keyParts) != 3 {
		return fmt.Errorf("invalid key: '%s'", key)
	}
	indexName := keyParts[0]
	indexType := keyParts[1]
	valueID := keyParts[2]

	s.checkOrCreateIndex(indexName, indexType)

	_, err := s.client.Index().
		Index(indexName).
		Type(indexType).
		Id(valueID).
		BodyJson(structPtr).
		Do(s.context)

	return err
}

func (s *ElasticsearchKeyValueStore) PutAll(entries []*Entry) error {
	bulk := s.client.Bulk()
	for _, entry := range entries {
		keyParts := strings.Split(entry.key, "/")
		if len(keyParts) != 3 {
			return fmt.Errorf("invalid key: '%s'", entry.key)
		}
		indexName := keyParts[0]
		indexType := keyParts[1]
		valueID := keyParts[2]

		s.witness.Assert(entry.value)
		s.checkOrCreateIndex(indexName, indexType)

		bulk.Add(elastic.NewBulkIndexRequest().
			Index(indexName).
			Type(indexType).
			Id(valueID).
			Doc(entry.value),
		)
	}
	_, err := bulk.Do(s.context)
	return err
}

// Delete removes key from store
func (s *ElasticsearchKeyValueStore) Delete(key string) error {
	keyParts := strings.Split(key, "/")
	if len(keyParts) != 3 {
		return fmt.Errorf("invalid key: '%s'", key)
	}
	indexName := keyParts[0]
	indexType := keyParts[1]
	valueID := keyParts[2]

	s.checkOrCreateIndex(indexName, indexType)

	_, err := s.client.Delete().
		Index(indexName).
		Type(indexType).
		Id(valueID).
		Do(s.context)

	return err
}

// Flush the Elasticsearch translog to disk
func (s* ElasticsearchKeyValueStore) Flush() error {
	log.Println("Flusing ES indexes...")
	_, err := s.client.Flush(s.existingIndexes...).
		WaitIfOngoing(true).
		Do(s.context)
	log.Println("Done flusing ES indexes.")
	return err
}
<|endoftext|>


<commit_before>package kvexpress

import (
	"bytes"
	"crypto/sha256"
	"fmt"
	"github.com/aryann/difflib"
	"os/exec"
	"strings"
)

func init() {
	// Nothing happens here.
}

func LengthCheck(data string, min_length int, direction string) bool {
	length := LineCount(data)
	Log(fmt.Sprintf("%s: length='%d' min_length='%d'", direction, length, min_length), "debug")
	if length >= min_length {
		return true
	} else {
		return false
	}
}

func LineCount(data string) int {
	var length int
	if strings.ContainsAny(data, "\n") {
		length = strings.Count(data, "\n")
	} else {
		length = 1
	}
	return length
}

func ComputeChecksum(data string, direction string) string {
	data_bytes := []byte(data)
	computed_checksum := sha256.Sum256(data_bytes)
	final_checksum := fmt.Sprintf("%x\n", computed_checksum)
	Log(fmt.Sprintf("%s: computed_checksum='%s'", direction, final_checksum), "debug")
	return final_checksum
}

func ChecksumCompare(data string, checksum string, direction string) bool {
	computed_checksum := ComputeChecksum(data, direction)
	Log(fmt.Sprintf("%s: checksum='%s' computed_checksum='%s'", direction, checksum, computed_checksum), "debug")
	if strings.TrimSpace(computed_checksum) == strings.TrimSpace(checksum) {
		return true
	} else {
		return false
	}
}

func UnixDiff(old, new string) string {
	diff, _ := exec.Command("diff", "-u", old, new).Output()
	return string(diff)
}

func Diff(last string, current string) string {
	var buffer bytes.Buffer

	// Split lines.
	last_strings := strings.Split(string(last), "\n")
	current_strings := strings.Split(string(current), "\n")

	diff := difflib.Diff(last_strings, current_strings)
	diffString := fmt.Sprintf("%v", diff)

	Log("in: doing the diff", "debug")
	buffer.WriteString(diffString)
	return buffer.String()
}

func RunCommand(command string) bool {
	parts := strings.Fields(command)
	cli := parts[0]
	args := parts[1:len(parts)]
	cmd := exec.Command(cli, args...)
	var out bytes.Buffer
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		Log(fmt.Sprintf("exec='error' message='%v'", err), "info")
		return false
	} else {
		return true
	}
}
<commit_msg>Strip the top 3 lines from the Datadog output - makes it nicer. Closes #36 and #48.<commit_after>package kvexpress

import (
	"bytes"
	"crypto/sha256"
	"fmt"
	"github.com/aryann/difflib"
	"os/exec"
	"strings"
)

func init() {
	// Nothing happens here.
}

func LengthCheck(data string, min_length int, direction string) bool {
	length := LineCount(data)
	Log(fmt.Sprintf("%s: length='%d' min_length='%d'", direction, length, min_length), "debug")
	if length >= min_length {
		return true
	} else {
		return false
	}
}

func LineCount(data string) int {
	var length int
	if strings.ContainsAny(data, "\n") {
		length = strings.Count(data, "\n")
	} else {
		length = 1
	}
	return length
}

func ComputeChecksum(data string, direction string) string {
	data_bytes := []byte(data)
	computed_checksum := sha256.Sum256(data_bytes)
	final_checksum := fmt.Sprintf("%x\n", computed_checksum)
	Log(fmt.Sprintf("%s: computed_checksum='%s'", direction, final_checksum), "debug")
	return final_checksum
}

func ChecksumCompare(data string, checksum string, direction string) bool {
	computed_checksum := ComputeChecksum(data, direction)
	Log(fmt.Sprintf("%s: checksum='%s' computed_checksum='%s'", direction, checksum, computed_checksum), "debug")
	if strings.TrimSpace(computed_checksum) == strings.TrimSpace(checksum) {
		return true
	} else {
		return false
	}
}

func UnixDiff(old, new string) string {
	diff, _ := exec.Command("diff", "-u", old, new).Output()
	text := string(diff)
	finalText := removeLines(text, 3)
	return finalText
}

func removeLines(text string, number int) string {
	lines := strings.Split(text, "\n")
	cleaned := make([]string, 0)
	cleaned = append(cleaned, lines[number:]...)
	finalText := strings.Join(cleaned, "\n")
	return finalText
}

func Diff(last string, current string) string {
	var buffer bytes.Buffer

	// Split lines.
	last_strings := strings.Split(string(last), "\n")
	current_strings := strings.Split(string(current), "\n")

	diff := difflib.Diff(last_strings, current_strings)
	diffString := fmt.Sprintf("%v", diff)

	Log("in: doing the diff", "debug")
	buffer.WriteString(diffString)
	return buffer.String()
}

func RunCommand(command string) bool {
	parts := strings.Fields(command)
	cli := parts[0]
	args := parts[1:len(parts)]
	cmd := exec.Command(cli, args...)
	var out bytes.Buffer
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		Log(fmt.Sprintf("exec='error' message='%v'", err), "info")
		return false
	} else {
		return true
	}
}
<|endoftext|>