<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"time"

	"github.com/ansel1/merry"
	"github.com/dghubble/sling"
	"github.com/dickeyxxx/golock"
)

func init() {
	Topics = append(Topics, &Topic{
		Name:        "update",
		Description: "update heroku-cli",
		Commands: CommandSet{
			{
				Topic:            "update",
				Hidden:           true,
				Description:      "updates the Heroku CLI",
				DisableAnalytics: true,
				Args:             []Arg{{Name: "channel", Optional: true}},
				Run: func(ctx *Context) {
					channel := ctx.Args.(map[string]string)["channel"]
					if channel == "" {
						channel = Channel
					}
					Update(channel)
				},
			},
		},
	})
}

// Autoupdate is a flag to enable/disable CLI autoupdating
var Autoupdate = "no"

var updateLockPath = filepath.Join(CacheHome, "updating.lock")
var autoupdateFile = filepath.Join(CacheHome, "autoupdate")

// Update updates the CLI and plugins
func Update(channel string) {
	touchAutoupdateFile()
	SubmitAnalytics()
	updateCLI(channel)
	userPlugins.Update()
	truncate(ErrLogPath, 1000)
	cleanTmpDirs()
}

func updateCLI(channel string) {
	if Autoupdate != "yes" {
		return
	}
	manifest := getUpdateManifest(channel)
	if manifest.Version == Version && manifest.Channel == Channel {
		return
	}
	locked, err := golock.IsLocked(updateLockPath)
	LogIfError(err)
	if locked {
		must(merry.Errorf("Update in progress"))
	}
	LogIfError(golock.Lock(updateLockPath))
	unlock := func() {
		golock.Unlock(updateLockPath)
	}
	defer unlock()
	hideCursor()
	downloadingMessage = fmt.Sprintf("heroku-cli: Updating to %s...", manifest.Version)
	if manifest.Channel != "stable" {
		downloadingMessage = fmt.Sprintf("%s (%s)", downloadingMessage, manifest.Channel)
	}
	Logln(downloadingMessage)
	build := manifest.Builds[runtime.GOOS+"-"+runtime.GOARCH]
	if build == nil {
		must(merry.Errorf("no build for %s", manifest.Channel))
	}
	reader, getSha, err := downloadXZ(build.URL)
	must(err)
	tmp := tmpDir(DataHome)
	must(extractTar(reader, tmp))
	sha := getSha()
	if sha != build.Sha256 {
		must(merry.Errorf("SHA mismatch: expected %s to be %s", sha, build.Sha256))
	}
	LogIfError(os.Rename(filepath.Join(DataHome, "cli"), filepath.Join(tmpDir(DataHome), "heroku")))
	LogIfError(os.Rename(filepath.Join(tmp, "heroku"), filepath.Join(DataHome, "cli")))
	unlock()
	Debugln("updating done, loading new cli " + manifest.Version)
	loadNewCLI()
}

// IsUpdateNeeded checks if an update is available
func IsUpdateNeeded() bool {
	if exists, _ := fileExists(expectedBinPath()); !exists {
		return true
	}
	f, err := os.Stat(autoupdateFile)
	if err != nil {
		if os.IsNotExist(err) {
			return true
		}
		LogIfError(err)
		return true
	}
	return time.Since(f.ModTime()) > 4*time.Hour
}

func touchAutoupdateFile() {
	out, err := os.OpenFile(autoupdateFile, os.O_WRONLY|os.O_CREATE, 0644)
	must(err)
	_, err = out.WriteString(time.Now().String())
	must(err)
	err = out.Close()
	must(err)
}

func getUpdateManifest(channel string) *Manifest {
	var m Manifest
	url := "https://cli-assets.heroku.com/branches/" + channel + "/manifest.json"
	rsp, err := sling.New().Get(url).ReceiveSuccess(&m)
	must(err)
	must(getHTTPError(rsp))
	return &m
}

// TriggerBackgroundUpdate will trigger an update to the client in the background
func TriggerBackgroundUpdate() {
	if IsUpdateNeeded() {
		Debugln("triggering background update")
		touchAutoupdateFile()
		exec.Command(BinPath, "update").Start()
	}
}

func cleanTmpDirs() {
	clean := func(base string) {
		dir := filepath.Join(base, "tmp")
		if exists, _ := fileExists(dir); !exists {
			return
		}
		files, err := ioutil.ReadDir(dir)
		LogIfError(err)
		for _, file := range files {
			if time.Since(file.ModTime()) > 24*time.Hour {
				path := filepath.Join(dir, file.Name())
				Debugf("removing old tmp dir %s", path)
				LogIfError(os.RemoveAll(path))
			}
		}
	}
	clean(DataHome)
	clean(CacheHome)
}

func expectedBinPath() string {
	bin := filepath.Join(DataHome, "cli", "bin", "heroku")
	if runtime.GOOS == WINDOWS {
		bin = bin + ".exe"
	}
	return bin
}

func loadNewCLI() {
	if Autoupdate == "no" {
		return
	}
	expected := expectedBinPath()
	if BinPath == expected {
		return
	}
	if exists, _ := fileExists(expected); !exists {
		if exists, _ = fileExists(npmBinPath()); !exists {
			// uh oh, npm isn't where it should be.
			// The CLI probably isn't installed right so force an update
			Update(Channel)
		}
		return
	}
	execBin(expected, os.Args...)
}
<commit_msg>force update when bin does not exist<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"time"

	"github.com/ansel1/merry"
	"github.com/dghubble/sling"
	"github.com/dickeyxxx/golock"
)

func init() {
	Topics = append(Topics, &Topic{
		Name:        "update",
		Description: "update heroku-cli",
		Commands: CommandSet{
			{
				Topic:            "update",
				Hidden:           true,
				Description:      "updates the Heroku CLI",
				DisableAnalytics: true,
				Args:             []Arg{{Name: "channel", Optional: true}},
				Run: func(ctx *Context) {
					channel := ctx.Args.(map[string]string)["channel"]
					if channel == "" {
						channel = Channel
					}
					Update(channel)
				},
			},
		},
	})
}

// Autoupdate is a flag to enable/disable CLI autoupdating
var Autoupdate = "no"

var updateLockPath = filepath.Join(CacheHome, "updating.lock")
var autoupdateFile = filepath.Join(CacheHome, "autoupdate")

// Update updates the CLI and plugins
func Update(channel string) {
	touchAutoupdateFile()
	SubmitAnalytics()
	updateCLI(channel)
	userPlugins.Update()
	truncate(ErrLogPath, 1000)
	cleanTmpDirs()
}

func updateCLI(channel string) {
	if Autoupdate != "yes" {
		return
	}
	manifest := getUpdateManifest(channel)
	binExists, _ := fileExists(expectedBinPath())
	if binExists && manifest.Version == Version && manifest.Channel == Channel {
		return
	}
	locked, err := golock.IsLocked(updateLockPath)
	LogIfError(err)
	if locked {
		must(merry.Errorf("Update in progress"))
	}
	LogIfError(golock.Lock(updateLockPath))
	unlock := func() {
		golock.Unlock(updateLockPath)
	}
	defer unlock()
	hideCursor()
	downloadingMessage = fmt.Sprintf("heroku-cli: Updating to %s...", manifest.Version)
	if manifest.Channel != "stable" {
		downloadingMessage = fmt.Sprintf("%s (%s)", downloadingMessage, manifest.Channel)
	}
	Logln(downloadingMessage)
	build := manifest.Builds[runtime.GOOS+"-"+runtime.GOARCH]
	if build == nil {
		must(merry.Errorf("no build for %s", manifest.Channel))
	}
	reader, getSha, err := downloadXZ(build.URL)
	must(err)
	tmp := tmpDir(DataHome)
	must(extractTar(reader, tmp))
	sha := getSha()
	if sha != build.Sha256 {
		must(merry.Errorf("SHA mismatch: expected %s to be %s", sha, build.Sha256))
	}
	LogIfError(os.Rename(filepath.Join(DataHome, "cli"), filepath.Join(tmpDir(DataHome), "heroku")))
	LogIfError(os.Rename(filepath.Join(tmp, "heroku"), filepath.Join(DataHome, "cli")))
	unlock()
	Debugln("updating done, loading new cli " + manifest.Version)
	loadNewCLI()
}

// IsUpdateNeeded checks if an update is available
func IsUpdateNeeded() bool {
	if exists, _ := fileExists(expectedBinPath()); !exists {
		return true
	}
	f, err := os.Stat(autoupdateFile)
	if err != nil {
		if os.IsNotExist(err) {
			return true
		}
		LogIfError(err)
		return true
	}
	return time.Since(f.ModTime()) > 4*time.Hour
}

func touchAutoupdateFile() {
	out, err := os.OpenFile(autoupdateFile, os.O_WRONLY|os.O_CREATE, 0644)
	must(err)
	_, err = out.WriteString(time.Now().String())
	must(err)
	err = out.Close()
	must(err)
}

func getUpdateManifest(channel string) *Manifest {
	var m Manifest
	url := "https://cli-assets.heroku.com/branches/" + channel + "/manifest.json"
	rsp, err := sling.New().Get(url).ReceiveSuccess(&m)
	must(err)
	must(getHTTPError(rsp))
	return &m
}

// TriggerBackgroundUpdate will trigger an update to the client in the background
func TriggerBackgroundUpdate() {
	if IsUpdateNeeded() {
		Debugln("triggering background update")
		touchAutoupdateFile()
		exec.Command(BinPath, "update").Start()
	}
}

func cleanTmpDirs() {
	clean := func(base string) {
		dir := filepath.Join(base, "tmp")
		if exists, _ := fileExists(dir); !exists {
			return
		}
		files, err := ioutil.ReadDir(dir)
		LogIfError(err)
		for _, file := range files {
			if time.Since(file.ModTime()) > 24*time.Hour {
				path := filepath.Join(dir, file.Name())
				Debugf("removing old tmp dir %s", path)
				LogIfError(os.RemoveAll(path))
			}
		}
	}
	clean(DataHome)
	clean(CacheHome)
}

func expectedBinPath() string {
	bin := filepath.Join(DataHome, "cli", "bin", "heroku")
	if runtime.GOOS == WINDOWS {
		bin = bin + ".exe"
	}
	return bin
}

func loadNewCLI() {
	if Autoupdate == "no" {
		return
	}
	expected := expectedBinPath()
	if BinPath == expected {
		return
	}
	if exists, _ := fileExists(expected); !exists {
		if exists, _ = fileExists(npmBinPath()); !exists {
			// uh oh, npm isn't where it should be.
			// The CLI probably isn't installed right so force an update
			Update(Channel)
		}
		return
	}
	execBin(expected, os.Args...)
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"flag"
	"io/ioutil"
	"path"
	"strings"
	"text/template"

	"github.com/docker-library/go-dockerlibrary/manifest"
)

var manifestURL = "https://github.com/docker-library/official-images/raw/master/library/caddy"

var maintainers = []string{"Ambrose Chua <ambrose@makerforce.io> (@serverwentdown)"}
var gitRepo = "https://github.com/productionwentdown/caddy.git"

var dockerfileTemplate = template.Must(template.New("name").Parse(`FROM caddy:{{.Tag}} as build

RUN apk add --no-cache upx ca-certificates \
    && upx --ultra-brute /usr/bin/caddy \
    && caddy version

FROM scratch

COPY --from=build /etc/caddy/Caddyfile /etc/caddy/Caddyfile
COPY --from=build /usr/share/caddy/index.html /usr/share/caddy/index.html
COPY --from=build /usr/bin/caddy /usr/bin/caddy
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=build /etc/nsswitch.conf /etc/nsswitch.conf

ENV XDG_CONFIG_HOME=/config
ENV XDG_DATA_HOME=/data
ENV HOME=/

VOLUME /config
VOLUME /data

LABEL org.opencontainers.image.version=v{{.Version}}
LABEL org.opencontainers.image.title="Caddy (productionwentdown build)"
LABEL org.opencontainers.image.description="a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go"
LABEL org.opencontainers.image.url=https://productionwentdown.makerforce.io
LABEL org.opencontainers.image.documentation=https://caddyserver.com/docs
LABEL org.opencontainers.image.vendor="productionwentdown"
LABEL org.opencontainers.image.licenses=Apache-2.0
LABEL org.opencontainers.image.source="https://github.com/productionwentdown/caddy"

EXPOSE 80
EXPOSE 443
EXPOSE 2019

WORKDIR /srv

CMD ["/usr/bin/caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
`))

type dockerfileData struct {
	Tag     string
	Version string
	Arch string
}

func main() {
	doDockerfiles := flag.Bool("dockerfiles", false, "Update Dockerfiles")
	doManifest := flag.Bool("manifest", false, "Update manifest")
	commit := flag.String("commit", "", "Current commit hash")
	flag.Parse()

	_, _, man, err := manifest.Fetch("nonexistent", manifestURL)
	if err != nil {
		panic(err)
	}

	man = subsetManifest(man)

	if *doDockerfiles {
		err = updateDockerfiles(man)
		if err != nil {
			panic(err)
		}
	}
	if *doManifest {
		err = updateManifest(man, *commit)
		if err != nil {
			panic(err)
		}
	}
}

// subsetManifest returns the subset of the manifest that can be built
func subsetManifest(man *manifest.Manifest2822) *manifest.Manifest2822 {
	entries := make([]manifest.Manifest2822Entry, 0, 1)
	for _, entry := range man.Entries {

		hasWindows := false
		for _, arch := range entry.Architectures {
			if strings.HasPrefix(arch, "windows") {
				hasWindows = true
			}
		}

		isBuilder := false
		for _, tag := range entry.Tags {
			if strings.HasSuffix(tag, "builder") {
				isBuilder = true
			}
		}

		if hasWindows || isBuilder {
			continue
		}
		entries = append(entries, entry)
	}
	return &manifest.Manifest2822{
		Global:  man.Global,
		Entries: entries,
	}
}

// updateDockerfiles generates a new set of Dockerfiles based on the manifest
func updateDockerfiles(man *manifest.Manifest2822) error {
	for _, entry := range man.Entries {
		tag := entry.Tags[0]
		version := strings.Split(entry.Tags[0], "-")[0]
		for _, arch := range entry.Architectures {
			data := dockerfileData{Tag: tag, Version: version, Arch: arch}
			err := writeDockerfile(entry, data)
			if err != nil {
				return err
			}
		}
	}
	// TODO: Remove old Dockerfiles
	return nil
}

func writeDockerfile(entry manifest.Manifest2822Entry, data dockerfileData) error {
	dockerfilePath := path.Join(entry.ArchDirectory(data.Arch), entry.ArchFile(data.Arch))
	err := os.MkdirAll(entry.ArchDirectory(data.Arch), 0755)
	if err != nil {
		return err
	}
	dockerfileFile, err := os.OpenFile(dockerfilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer dockerfileFile.Close()

	err = dockerfileTemplate.Execute(dockerfileFile, data)
	if err != nil {
		return err
	}

	return nil
}

// updateManifest replaces upstream maintainer and Git info with this repo
func updateManifest(man *manifest.Manifest2822, gitCommit string) error {
	man.Global.Maintainers = maintainers
	for i := range man.Entries {
		entry := &man.Entries[i]
		entry.Maintainers = maintainers
		entry.GitRepo = gitRepo
		entry.GitCommit = gitCommit
	}
	manifestPath := path.Join("library", "caddy")
	err := os.MkdirAll("library", 0755)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(manifestPath, []byte(man.String()), 0644)
}
<commit_msg>Exclude builder image<commit_after>package main

import (
	"os"
	"flag"
	"io/ioutil"
	"path"
	"strings"
	"text/template"

	"github.com/docker-library/go-dockerlibrary/manifest"
)

var manifestURL = "https://github.com/docker-library/official-images/raw/master/library/caddy"

var maintainers = []string{"Ambrose Chua <ambrose@makerforce.io> (@serverwentdown)"}
var gitRepo = "https://github.com/productionwentdown/caddy.git"

var dockerfileTemplate = template.Must(template.New("name").Parse(`FROM caddy:{{.Tag}} as build

RUN apk add --no-cache upx ca-certificates \
    && upx --ultra-brute /usr/bin/caddy \
    && caddy version

FROM scratch

COPY --from=build /etc/caddy/Caddyfile /etc/caddy/Caddyfile
COPY --from=build /usr/share/caddy/index.html /usr/share/caddy/index.html
COPY --from=build /usr/bin/caddy /usr/bin/caddy
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=build /etc/nsswitch.conf /etc/nsswitch.conf

ENV XDG_CONFIG_HOME=/config
ENV XDG_DATA_HOME=/data
ENV HOME=/

VOLUME /config
VOLUME /data

LABEL org.opencontainers.image.version=v{{.Version}}
LABEL org.opencontainers.image.title="Caddy (productionwentdown build)"
LABEL org.opencontainers.image.description="a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go"
LABEL org.opencontainers.image.url=https://productionwentdown.makerforce.io
LABEL org.opencontainers.image.documentation=https://caddyserver.com/docs
LABEL org.opencontainers.image.vendor="productionwentdown"
LABEL org.opencontainers.image.licenses=Apache-2.0
LABEL org.opencontainers.image.source="https://github.com/productionwentdown/caddy"

EXPOSE 80
EXPOSE 443
EXPOSE 2019

WORKDIR /srv

CMD ["/usr/bin/caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
`))

type dockerfileData struct {
	Tag     string
	Version string
	Arch string
}

func main() {
	doDockerfiles := flag.Bool("dockerfiles", false, "Update Dockerfiles")
	doManifest := flag.Bool("manifest", false, "Update manifest")
	commit := flag.String("commit", "", "Current commit hash")
	flag.Parse()

	_, _, man, err := manifest.Fetch("nonexistent", manifestURL)
	if err != nil {
		panic(err)
	}

	man = subsetManifest(man)

	if *doDockerfiles {
		err = updateDockerfiles(man)
		if err != nil {
			panic(err)
		}
	}
	if *doManifest {
		err = updateManifest(man, *commit)
		if err != nil {
			panic(err)
		}
	}
}

// subsetManifest returns the subset of the manifest that can be built
func subsetManifest(man *manifest.Manifest2822) *manifest.Manifest2822 {
	entries := make([]manifest.Manifest2822Entry, 0, 1)
	for _, entry := range man.Entries {

		isWindows := false
		for _, arch := range entry.Architectures {
			if strings.Contains(arch, "windows") {
				isWindows = true
			}
		}

		isBuilder := false
		for _, tag := range entry.Tags {
			if strings.Contains(tag, "builder") {
				isBuilder = true
			}
		}

		if isWindows || isBuilder {
			continue
		}
		entries = append(entries, entry)
	}
	return &manifest.Manifest2822{
		Global:  man.Global,
		Entries: entries,
	}
}

// updateDockerfiles generates a new set of Dockerfiles based on the manifest
func updateDockerfiles(man *manifest.Manifest2822) error {
	for _, entry := range man.Entries {
		tag := entry.Tags[0]
		version := strings.Split(entry.Tags[0], "-")[0]
		for _, arch := range entry.Architectures {
			data := dockerfileData{Tag: tag, Version: version, Arch: arch}
			err := writeDockerfile(entry, data)
			if err != nil {
				return err
			}
		}
	}
	// TODO: Remove old Dockerfiles
	return nil
}

func writeDockerfile(entry manifest.Manifest2822Entry, data dockerfileData) error {
	dockerfilePath := path.Join(entry.ArchDirectory(data.Arch), entry.ArchFile(data.Arch))
	err := os.MkdirAll(entry.ArchDirectory(data.Arch), 0755)
	if err != nil {
		return err
	}
	dockerfileFile, err := os.OpenFile(dockerfilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer dockerfileFile.Close()

	err = dockerfileTemplate.Execute(dockerfileFile, data)
	if err != nil {
		return err
	}

	return nil
}

// updateManifest replaces upstream maintainer and Git info with this repo
func updateManifest(man *manifest.Manifest2822, gitCommit string) error {
	man.Global.Maintainers = maintainers
	for i := range man.Entries {
		entry := &man.Entries[i]
		entry.Maintainers = maintainers
		entry.GitRepo = gitRepo
		entry.GitCommit = gitCommit
	}
	manifestPath := path.Join("library", "caddy")
	err := os.MkdirAll("library", 0755)
	if err != nil {
		return err
	}
	return ioutil.WriteFile(manifestPath, []byte(man.String()), 0644)
}
<|endoftext|>


<commit_before>// Package testpkg contains bound functions for testing the cgo-JNI interface.
package testpkg

import (
	"errors"
	"fmt"
	"runtime"
	"time"
)

type I interface {
	F()
}

func Call(i I) {
	i.F()
}

var keep []I

func Keep(i I) {
	keep = append(keep, i)
}

var numSCollected int

type S struct {
	// *S already has a finalizer, so we need another object
	// to count successful collections.
	innerObj *int
}

func (*S) F() {
	fmt.Println("called F on *S")
}

func finalizeInner(*int) {
	numSCollected++
}

func New() *S {
	s := &S{innerObj: new(int)}
	runtime.SetFinalizer(s.innerObj, finalizeInner)
	return s
}

func GC() {
	runtime.GC()
	time.Sleep(10 * time.Millisecond)
	runtime.GC()
}

func Add(x, y int) int {
	return x + y
}

func NumSCollected() int {
	return numSCollected
}

func StrDup(s string) string {
	return s
}

func Err(s string) error {
	if s != "" {
		return errors.New(s)
	}
	return nil
}

func BytesAppend(a []byte, b []byte) []byte {
	return append(a, b...)
}
<commit_msg>bind/java/testpkg: use go generate to run gobind on testpkg.<commit_after>// Package testpkg contains bound functions for testing the cgo-JNI interface.
package testpkg

//go:generate gobind -lang=go -output=go_testpkg/go_testpkg.go .
//go:generate gobind -lang=java -output=Testpkg.java .
import (
	"errors"
	"fmt"
	"runtime"
	"time"
)

type I interface {
	F()
}

func Call(i I) {
	i.F()
}

var keep []I

func Keep(i I) {
	keep = append(keep, i)
}

var numSCollected int

type S struct {
	// *S already has a finalizer, so we need another object
	// to count successful collections.
	innerObj *int
}

func (*S) F() {
	fmt.Println("called F on *S")
}

func finalizeInner(*int) {
	numSCollected++
}

func New() *S {
	s := &S{innerObj: new(int)}
	runtime.SetFinalizer(s.innerObj, finalizeInner)
	return s
}

func GC() {
	runtime.GC()
	time.Sleep(10 * time.Millisecond)
	runtime.GC()
}

func Add(x, y int) int {
	return x + y
}

func NumSCollected() int {
	return numSCollected
}

func StrDup(s string) string {
	return s
}

func Err(s string) error {
	if s != "" {
		return errors.New(s)
	}
	return nil
}

func BytesAppend(a []byte, b []byte) []byte {
	return append(a, b...)
}
<|endoftext|>


<commit_before>/*
 * Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2015, 2016 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package minio

import (
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/minio/minio-go/pkg/s3utils"
)

// BucketExists verify if bucket exists and you have permission to access it.
func (c Client) BucketExists(bucketName string) (bool, error) {
	// Input validation.
	if err := s3utils.CheckValidBucketName(bucketName); err != nil {
		return false, err
	}

	// Execute HEAD on bucketName.
	resp, err := c.executeMethod("HEAD", requestMetadata{
		bucketName:         bucketName,
		contentSHA256Bytes: emptySHA256,
	})
	defer closeResponse(resp)
	if err != nil {
		if ToErrorResponse(err).Code == "NoSuchBucket" {
			return false, nil
		}
		return false, err
	}
	if resp != nil {
		if resp.StatusCode != http.StatusOK {
			return false, httpRespToErrorResponse(resp, bucketName, "")
		}
	}
	return true, nil
}

// List of header keys to be filtered, usually
// from all S3 API http responses.
var defaultFilterKeys = []string{
	"Transfer-Encoding",
	"Accept-Ranges",
	"Date",
	"Server",
	"Vary",
	"x-amz-request-id",
	"x-amz-id-2",
	// Add new headers to be ignored.
}

// Extract only necessary metadata header key/values by
// filtering them out with a list of custom header keys.
func extractObjMetadata(header http.Header) http.Header {
	filterKeys := append([]string{
		"ETag",
		"Content-Length",
		"Last-Modified",
		"Content-Type",
	}, defaultFilterKeys...)
	return filterHeader(header, filterKeys)
}

// StatObject verifies if object exists and you have permission to access.
func (c Client) StatObject(bucketName, objectName string) (ObjectInfo, error) {
	// Input validation.
	if err := s3utils.CheckValidBucketName(bucketName); err != nil {
		return ObjectInfo{}, err
	}
	if err := s3utils.CheckValidObjectName(objectName); err != nil {
		return ObjectInfo{}, err
	}
	reqHeaders := NewHeadReqHeaders()
	return c.statObject(bucketName, objectName, reqHeaders)
}

// Lower level API for statObject supporting pre-conditions and range headers.
func (c Client) statObject(bucketName, objectName string, reqHeaders RequestHeaders) (ObjectInfo, error) {
	// Input validation.
	if err := s3utils.CheckValidBucketName(bucketName); err != nil {
		return ObjectInfo{}, err
	}
	if err := s3utils.CheckValidObjectName(objectName); err != nil {
		return ObjectInfo{}, err
	}

	customHeader := make(http.Header)
	for k, v := range reqHeaders.Header {
		customHeader[k] = v
	}

	// Execute HEAD on objectName.
	resp, err := c.executeMethod("HEAD", requestMetadata{
		bucketName:         bucketName,
		objectName:         objectName,
		contentSHA256Bytes: emptySHA256,
		customHeader:       customHeader,
	})
	defer closeResponse(resp)
	if err != nil {
		return ObjectInfo{}, err
	}
	if resp != nil {
		if resp.StatusCode != http.StatusOK {
			return ObjectInfo{}, httpRespToErrorResponse(resp, bucketName, objectName)
		}
	}

	// Trim off the odd double quotes from ETag in the beginning and end.
	md5sum := strings.TrimPrefix(resp.Header.Get("ETag"), "\"")
	md5sum = strings.TrimSuffix(md5sum, "\"")

	// Parse content length is exists
	var size int64 = -1
	contentLengthStr := resp.Header.Get("Content-Length")
	if contentLengthStr != "" {
		size, err = strconv.ParseInt(contentLengthStr, 10, 64)
		if err != nil {
			// Content-Length is not valid
			return ObjectInfo{}, ErrorResponse{
				Code:       "InternalError",
				Message:    "Content-Length is invalid. " + reportIssue,
				BucketName: bucketName,
				Key:        objectName,
				RequestID:  resp.Header.Get("x-amz-request-id"),
				HostID:     resp.Header.Get("x-amz-id-2"),
				Region:     resp.Header.Get("x-amz-bucket-region"),
			}
		}
	}

	// Parse Last-Modified has http time format.
	date, err := time.Parse(http.TimeFormat, resp.Header.Get("Last-Modified"))
	if err != nil {
		return ObjectInfo{}, ErrorResponse{
			Code:       "InternalError",
			Message:    "Last-Modified time format is invalid. " + reportIssue,
			BucketName: bucketName,
			Key:        objectName,
			RequestID:  resp.Header.Get("x-amz-request-id"),
			HostID:     resp.Header.Get("x-amz-id-2"),
			Region:     resp.Header.Get("x-amz-bucket-region"),
		}
	}

	// Fetch content type if any present.
	contentType := strings.TrimSpace(resp.Header.Get("Content-Type"))
	if contentType == "" {
		contentType = "application/octet-stream"
	}

	// Extract only the relevant header keys describing the object.
	// following function filters out a list of standard set of keys
	// which are not part of object metadata.
	metadata := extractObjMetadata(resp.Header)

	// Save object metadata info.
	return ObjectInfo{
		ETag:         md5sum,
		Key:          objectName,
		Size:         size,
		LastModified: date,
		ContentType:  contentType,
		Metadata:     metadata,
	}, nil
}
<commit_msg>api: objectInfo filtering should include more headers. (#724)<commit_after>/*
 * Minio Go Library for Amazon S3 Compatible Cloud Storage (C) 2015, 2016 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package minio

import (
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/minio/minio-go/pkg/s3utils"
)

// BucketExists verify if bucket exists and you have permission to access it.
func (c Client) BucketExists(bucketName string) (bool, error) {
	// Input validation.
	if err := s3utils.CheckValidBucketName(bucketName); err != nil {
		return false, err
	}

	// Execute HEAD on bucketName.
	resp, err := c.executeMethod("HEAD", requestMetadata{
		bucketName:         bucketName,
		contentSHA256Bytes: emptySHA256,
	})
	defer closeResponse(resp)
	if err != nil {
		if ToErrorResponse(err).Code == "NoSuchBucket" {
			return false, nil
		}
		return false, err
	}
	if resp != nil {
		if resp.StatusCode != http.StatusOK {
			return false, httpRespToErrorResponse(resp, bucketName, "")
		}
	}
	return true, nil
}

// List of header keys to be filtered, usually
// from all S3 API http responses.
var defaultFilterKeys = []string{
	"Connection",
	"Transfer-Encoding",
	"Accept-Ranges",
	"Date",
	"Server",
	"Vary",
	"x-amz-bucket-region",
	"x-amz-request-id",
	"x-amz-id-2",
	// Add new headers to be ignored.
}

// Extract only necessary metadata header key/values by
// filtering them out with a list of custom header keys.
func extractObjMetadata(header http.Header) http.Header {
	filterKeys := append([]string{
		"ETag",
		"Content-Length",
		"Last-Modified",
		"Content-Type",
	}, defaultFilterKeys...)
	return filterHeader(header, filterKeys)
}

// StatObject verifies if object exists and you have permission to access.
func (c Client) StatObject(bucketName, objectName string) (ObjectInfo, error) {
	// Input validation.
	if err := s3utils.CheckValidBucketName(bucketName); err != nil {
		return ObjectInfo{}, err
	}
	if err := s3utils.CheckValidObjectName(objectName); err != nil {
		return ObjectInfo{}, err
	}
	reqHeaders := NewHeadReqHeaders()
	return c.statObject(bucketName, objectName, reqHeaders)
}

// Lower level API for statObject supporting pre-conditions and range headers.
func (c Client) statObject(bucketName, objectName string, reqHeaders RequestHeaders) (ObjectInfo, error) {
	// Input validation.
	if err := s3utils.CheckValidBucketName(bucketName); err != nil {
		return ObjectInfo{}, err
	}
	if err := s3utils.CheckValidObjectName(objectName); err != nil {
		return ObjectInfo{}, err
	}

	customHeader := make(http.Header)
	for k, v := range reqHeaders.Header {
		customHeader[k] = v
	}

	// Execute HEAD on objectName.
	resp, err := c.executeMethod("HEAD", requestMetadata{
		bucketName:         bucketName,
		objectName:         objectName,
		contentSHA256Bytes: emptySHA256,
		customHeader:       customHeader,
	})
	defer closeResponse(resp)
	if err != nil {
		return ObjectInfo{}, err
	}
	if resp != nil {
		if resp.StatusCode != http.StatusOK {
			return ObjectInfo{}, httpRespToErrorResponse(resp, bucketName, objectName)
		}
	}

	// Trim off the odd double quotes from ETag in the beginning and end.
	md5sum := strings.TrimPrefix(resp.Header.Get("ETag"), "\"")
	md5sum = strings.TrimSuffix(md5sum, "\"")

	// Parse content length is exists
	var size int64 = -1
	contentLengthStr := resp.Header.Get("Content-Length")
	if contentLengthStr != "" {
		size, err = strconv.ParseInt(contentLengthStr, 10, 64)
		if err != nil {
			// Content-Length is not valid
			return ObjectInfo{}, ErrorResponse{
				Code:       "InternalError",
				Message:    "Content-Length is invalid. " + reportIssue,
				BucketName: bucketName,
				Key:        objectName,
				RequestID:  resp.Header.Get("x-amz-request-id"),
				HostID:     resp.Header.Get("x-amz-id-2"),
				Region:     resp.Header.Get("x-amz-bucket-region"),
			}
		}
	}

	// Parse Last-Modified has http time format.
	date, err := time.Parse(http.TimeFormat, resp.Header.Get("Last-Modified"))
	if err != nil {
		return ObjectInfo{}, ErrorResponse{
			Code:       "InternalError",
			Message:    "Last-Modified time format is invalid. " + reportIssue,
			BucketName: bucketName,
			Key:        objectName,
			RequestID:  resp.Header.Get("x-amz-request-id"),
			HostID:     resp.Header.Get("x-amz-id-2"),
			Region:     resp.Header.Get("x-amz-bucket-region"),
		}
	}

	// Fetch content type if any present.
	contentType := strings.TrimSpace(resp.Header.Get("Content-Type"))
	if contentType == "" {
		contentType = "application/octet-stream"
	}

	// Extract only the relevant header keys describing the object.
	// following function filters out a list of standard set of keys
	// which are not part of object metadata.
	metadata := extractObjMetadata(resp.Header)

	// Save object metadata info.
	return ObjectInfo{
		ETag:         md5sum,
		Key:          objectName,
		Size:         size,
		LastModified: date,
		ContentType:  contentType,
		Metadata:     metadata,
	}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha1"
	"encoding/hex"
	"errors"
	"fmt"
	"log"
	"net"
	"os"
	"path/filepath"
	"regexp"
	"time"

	"golang.org/x/crypto/ssh"
	"golang.org/x/crypto/ssh/agent"

	"github.com/atotto/clipboard"
	"github.com/deckarep/gosx-notifier"
	"github.com/fsnotify/fsnotify"
	"github.com/tmc/scp"
)

// Config contains all the configuration options
type Config struct {
	UserName string // Username used on the remote server
	HostName string // Hostname of the remote server
	Port     string // Port used for SSH on remote server
	RPath    string // Remote Path where files should be moved on the remote server
	RUrl     string // URL where the image will be accessible on the remote server
	LPath    string // Local Path where we are going to watch for new additions
	Archive  string // Path to directory where files will be archived
	Filter   string // Regex to filter out files that should be automatically uploaded
}

// File contains all the information about a file
type File struct {
	Path      string
	Extension string
	Name      string
	URL       string
}

var cfg Config

func init() {
	cfg = Config{
		UserName: os.Getenv("USER"),
		HostName: os.Getenv("HOST"),
		Port:     os.Getenv("PORT"),
		RPath:    os.Getenv("RPATH"),
		LPath:    os.Getenv("LPATH"),
		Archive:  os.Getenv("ARCHIVE"),
		Filter:   os.Getenv("FILTER"),
	}

	// set default values
	if os.Getenv("PORT") == "" {
		cfg.Port = "22"
	}
	if os.Getenv("FILTER") == "" {
		cfg.Filter = `^Screen.Shot.[0-9-]*.\w*.[0-9.]*.png`
	}
}

func main() {
	var reFilename = regexp.MustCompile(cfg.Filter)

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				if event.Op == fsnotify.Create {
					if event.Op == fsnotify.Create && reFilename.MatchString(filepath.Base(event.Name)) {
						err := upload(cfg, File{
							Path:      event.Name,
							Extension: filepath.Ext(event.Name),
							Name:      filepath.Base(event.Name),
						})
						if err != nil {
							log.Fatal(err)
						}
					}
				}
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()

	err = watcher.Add(cfg.LPath)
	if err != nil {
		log.Fatal(err)
	}
	<-done
}

// upload is uploading a given file to a remote server via SCP
func upload(cfg Config, f File) error {
	agent, err := getAgent()
	if err != nil {
		log.Fatalln("failed to connect to SSH_AUTH_SOCK:", err)
	}

	// use existing public keys
	client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", cfg.HostName, cfg.Port), &ssh.ClientConfig{
		User: cfg.UserName,
		Auth: []ssh.AuthMethod{
			ssh.PublicKeysCallback(agent.Signers),
		},
	})

	if err != nil {
		log.Fatalln("failed to dial:", err)
	}

	session, err := client.NewSession()
	if err != nil {
		log.Fatalln("failed to create session: " + err.Error())
	}

	// rename or rename and archive if enabled
	fn, err := rename(cfg, f)
	if err != nil {
		return err
	}

	err = scp.CopyPath(fn.Path, cfg.RPath, session)
	if err != nil {
		return err
	}

	// remove renamed file after upload
	if cfg.Archive == "" {
		err := trash(cfg, fn)
		if err != nil {
			return err
		}
	}

	// send notification using OS default notifier
	fn.URL = fmt.Sprintf("%s/%s", cfg.RUrl, fn.Name)

	// add url to clipboard
	clipboard.WriteAll(fn.URL)

	err = notify(fn)
	if err != nil {
		return err
	}
	return nil
}

// getAgent will use the system ssh agent
func getAgent() (agent.Agent, error) {
	agentConn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
	return agent.NewClient(agentConn), err
}

// generateHash will return a sha1 hash for a given filename
func generateHash(str string) (hash string, err error) {
	if str != "" {
		h := sha1.New()
		h.Write([]byte(str))
		s := hex.EncodeToString(h.Sum(nil))
		return s, nil
	}
	return "", errors.New("error generating hash")
}

func notify(f File) error {
	//At a minimum specifiy a message to display to end-user.
	n := gosxnotifier.NewNotification("The URL is now in your clipboard.")
	n.Title = "Screen Upload"
	n.Subtitle = "Upload finished"
	n.Sender = "com.apple.Terminal"
	n.Link = f.URL
	err := n.Push()

	if err != nil {
		return err
	}
	return nil
}

// Rename will rename and/or remove a file
func rename(cfg Config, f File) (file File, err error) {
	hash, err := generateHash(fmt.Sprintf("%s:%d", f.Name, int32(time.Now().Unix())))
	if err != nil {
		return File{}, errors.New("error generating filename")
	}
	fn := File{
		Extension: f.Extension,
		Name:      fmt.Sprintf("%s%s", hash, f.Extension),
	}

	// if we are not archiving a file just rename it without moving
	if cfg.Archive == "" {
		fn.Path = fmt.Sprintf("%s%s", filepath.Join(cfg.LPath, hash), f.Extension)
		err = os.Rename(f.Path, fn.Path)
		if err != nil {
			return File{}, err
		}
	} else {
		fn.Path = fmt.Sprintf("%s%s", filepath.Join(cfg.Archive, hash), f.Extension)
		err = os.Rename(f.Path, fn.Path)
		if err != nil {
			return File{}, err
		}
	}
	return fn, nil
}

// Trash removes a given file
func trash(cfg Config, f File) error {
	err := os.Remove(f.Path)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>Forgot to assign URL variable<commit_after>package main

import (
	"crypto/sha1"
	"encoding/hex"
	"errors"
	"fmt"
	"log"
	"net"
	"os"
	"path/filepath"
	"regexp"
	"time"

	"golang.org/x/crypto/ssh"
	"golang.org/x/crypto/ssh/agent"

	"github.com/atotto/clipboard"
	"github.com/deckarep/gosx-notifier"
	"github.com/fsnotify/fsnotify"
	"github.com/tmc/scp"
)

// Config contains all the configuration options
type Config struct {
	UserName string // Username used on the remote server
	HostName string // Hostname of the remote server
	Port     string // Port used for SSH on remote server
	RPath    string // Remote Path where files should be moved on the remote server
	RUrl     string // URL where the image will be accessible on the remote server
	LPath    string // Local Path where we are going to watch for new additions
	Archive  string // Path to directory where files will be archived
	Filter   string // Regex to filter out files that should be automatically uploaded
}

// File contains all the information about a file
type File struct {
	Path      string
	Extension string
	Name      string
	URL       string
}

var cfg Config

func init() {
	cfg = Config{
		UserName: os.Getenv("USER"),
		HostName: os.Getenv("HOST"),
		Port:     os.Getenv("PORT"),
		RPath:    os.Getenv("RPATH"),
		LPath:    os.Getenv("LPATH"),
		RUrl:     os.Getenv("RURL"),
		Archive:  os.Getenv("ARCHIVE"),
		Filter:   os.Getenv("FILTER"),
	}

	// set default values
	if os.Getenv("PORT") == "" {
		cfg.Port = "22"
	}
	if os.Getenv("FILTER") == "" {
		cfg.Filter = `^Screen.Shot.[0-9-]*.\w*.[0-9.]*.png`
	}
}

func main() {
	var reFilename = regexp.MustCompile(cfg.Filter)

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				if event.Op == fsnotify.Create {
					if event.Op == fsnotify.Create && reFilename.MatchString(filepath.Base(event.Name)) {
						err := upload(cfg, File{
							Path:      event.Name,
							Extension: filepath.Ext(event.Name),
							Name:      filepath.Base(event.Name),
						})
						if err != nil {
							log.Fatal(err)
						}
					}
				}
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()

	err = watcher.Add(cfg.LPath)
	if err != nil {
		log.Fatal(err)
	}
	<-done
}

// upload is uploading a given file to a remote server via SCP
func upload(cfg Config, f File) error {
	agent, err := getAgent()
	if err != nil {
		log.Fatalln("failed to connect to SSH_AUTH_SOCK:", err)
	}

	// use existing public keys
	client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%s", cfg.HostName, cfg.Port), &ssh.ClientConfig{
		User: cfg.UserName,
		Auth: []ssh.AuthMethod{
			ssh.PublicKeysCallback(agent.Signers),
		},
	})

	if err != nil {
		log.Fatalln("failed to dial:", err)
	}

	session, err := client.NewSession()
	if err != nil {
		log.Fatalln("failed to create session: " + err.Error())
	}

	// rename or rename and archive if enabled
	fn, err := rename(cfg, f)
	if err != nil {
		return err
	}

	err = scp.CopyPath(fn.Path, cfg.RPath, session)
	if err != nil {
		return err
	}

	// remove renamed file after upload
	if cfg.Archive == "" {
		err := trash(cfg, fn)
		if err != nil {
			return err
		}
	}

	// send notification using OS default notifier
	fn.URL = fmt.Sprintf("%s/%s", cfg.RUrl, fn.Name)

	// add url to clipboard
	clipboard.WriteAll(fn.URL)

	err = notify(fn)
	if err != nil {
		return err
	}
	return nil
}

// getAgent will use the system ssh agent
func getAgent() (agent.Agent, error) {
	agentConn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
	return agent.NewClient(agentConn), err
}

// generateHash will return a sha1 hash for a given filename
func generateHash(str string) (hash string, err error) {
	if str != "" {
		h := sha1.New()
		h.Write([]byte(str))
		s := hex.EncodeToString(h.Sum(nil))
		return s, nil
	}
	return "", errors.New("error generating hash")
}

func notify(f File) error {
	//At a minimum specifiy a message to display to end-user.
	n := gosxnotifier.NewNotification("The URL is now in your clipboard.")
	n.Title = "Screen Upload"
	n.Subtitle = "Upload finished"
	n.Sender = "com.apple.Terminal"
	n.Link = f.URL
	err := n.Push()

	if err != nil {
		return err
	}
	return nil
}

// Rename will rename and/or remove a file
func rename(cfg Config, f File) (file File, err error) {
	hash, err := generateHash(fmt.Sprintf("%s:%d", f.Name, int32(time.Now().Unix())))
	if err != nil {
		return File{}, errors.New("error generating filename")
	}
	fn := File{
		Extension: f.Extension,
		Name:      fmt.Sprintf("%s%s", hash, f.Extension),
	}

	// if we are not archiving a file just rename it without moving
	if cfg.Archive == "" {
		fn.Path = fmt.Sprintf("%s%s", filepath.Join(cfg.LPath, hash), f.Extension)
		err = os.Rename(f.Path, fn.Path)
		if err != nil {
			return File{}, err
		}
	} else {
		fn.Path = fmt.Sprintf("%s%s", filepath.Join(cfg.Archive, hash), f.Extension)
		err = os.Rename(f.Path, fn.Path)
		if err != nil {
			return File{}, err
		}
	}
	return fn, nil
}

// Trash removes a given file
func trash(cfg Config, f File) error {
	err := os.Remove(f.Path)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// +build !windows,!darwin

package open

import (
	"os/exec"
)

func open(input string) *exec.Cmd {
	return exec.Command("xdg-open", input)
}

func openWith(input string, appName string) *exec.Cmd {
	return exec.Command(appName, input)
}
<commit_msg>adding links to xdg-open source code in case we want to use it someday<commit_after>// +build !windows,!darwin

package open

import (
	"os/exec"
)

// http://sources.debian.net/src/xdg-utils/1.1.0~rc1%2Bgit20111210-7.1/scripts/xdg-open/
// http://sources.debian.net/src/xdg-utils/1.1.0~rc1%2Bgit20111210-7.1/scripts/xdg-mime/

func open(input string) *exec.Cmd {
	return exec.Command("xdg-open", input)
}

func openWith(input string, appName string) *exec.Cmd {
	return exec.Command(appName, input)
}
<|endoftext|>


<commit_before>package pb

import "fmt"

const (
	// AverageMetricAge average over a one-minute period, which means the average
	// age of the metrics is in the period of 30 seconds
	AverageMetricAge float64 = 30.0

	// Decay formula for computing the decay factor for average metric age
	Decay float64 = 2 / (float64(AverageMetricAge) + 1)
)

// EWMA represents the exponentially weighted moving average of a series of numbers.
type EWMA struct {
	value float64 // The current value of the average.
}

// Add a value to the series and update the moving average.
func (e *EWMA) Add(value float64) {
	if e.value == 0 { // perhaps first input, no decay factor needed
		e.value = value
		return
	}
	e.value = (value * Decay) + (e.value * (1 - Decay))
}

// Value returns the current value of the moving average.
func (e *EWMA) Value() float64 {
	return e.value
}
<commit_msg>Errors--<commit_after>package pb

const (
	// AverageMetricAge average over a one-minute period, which means the average
	// age of the metrics is in the period of 30 seconds
	AverageMetricAge float64 = 30.0

	// Decay formula for computing the decay factor for average metric age
	Decay float64 = 2 / (float64(AverageMetricAge) + 1)
)

// EWMA represents the exponentially weighted moving average of a series of numbers.
type EWMA struct {
	value float64 // The current value of the average.
}

// Add a value to the series and update the moving average.
func (e *EWMA) Add(value float64) {
	if e.value == 0 { // perhaps first input, no decay factor needed
		e.value = value
		return
	}
	e.value = (value * Decay) + (e.value * (1 - Decay))
}

// Value returns the current value of the moving average.
func (e *EWMA) Value() float64 {
	return e.value
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/app"
	"github.com/globocom/tsuru/log"
	"github.com/globocom/tsuru/provision"
	_ "github.com/globocom/tsuru/provision/juju"
	_ "github.com/globocom/tsuru/provision/local"
	stdlog "log"
	"log/syslog"
	"net/http"
	"os"
)

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

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

	m := pat.New()

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

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

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

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

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

	m.Get("/healers", Handler(healers))
	m.Get("/healers/:healer", Handler(healer))

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

		listen, err := config.GetString("listen")
		if err != nil {
			fatal(err)
		}
		tls, _ := config.GetBool("use-tls")
		if tls {
			certFile, err := config.GetString("tls-cert-file")
			if err != nil {
				fatal(err)
			}
			keyFile, err := config.GetString("tls-key-file")
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP/TLS server listening at %s...\n", listen)
			fatal(http.ListenAndServeTLS(listen, certFile, keyFile, m))
		} else {
			fmt.Printf("tsuru HTTP server listening at %s...\n", listen)
			fatal(http.ListenAndServe(listen, m))
		}
	}
}
<commit_msg>api: map url to setCName<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"github.com/bmizerany/pat"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/app"
	"github.com/globocom/tsuru/log"
	"github.com/globocom/tsuru/provision"
	_ "github.com/globocom/tsuru/provision/juju"
	_ "github.com/globocom/tsuru/provision/local"
	stdlog "log"
	"log/syslog"
	"net/http"
	"os"
)

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

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

	m := pat.New()

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

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

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

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

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

	m.Get("/healers", Handler(healers))
	m.Get("/healers/:healer", Handler(healer))

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

		listen, err := config.GetString("listen")
		if err != nil {
			fatal(err)
		}
		tls, _ := config.GetBool("use-tls")
		if tls {
			certFile, err := config.GetString("tls-cert-file")
			if err != nil {
				fatal(err)
			}
			keyFile, err := config.GetString("tls-key-file")
			if err != nil {
				fatal(err)
			}
			fmt.Printf("tsuru HTTP/TLS server listening at %s...\n", listen)
			fatal(http.ListenAndServeTLS(listen, certFile, keyFile, m))
		} else {
			fmt.Printf("tsuru HTTP server listening at %s...\n", listen)
			fatal(http.ListenAndServe(listen, m))
		}
	}
}
<|endoftext|>


<commit_before>//go:build !js
// +build !js

package main

import (
	"errors"
	"fmt"
	"net"
	"os"
	"time"

	"github.com/pion/interceptor"
	"github.com/pion/rtcp"
	"github.com/pion/rtp"
	"github.com/pion/webrtc/v3"
	"github.com/pion/webrtc/v3/examples/internal/signal"
)

type udpConn struct {
	conn        *net.UDPConn
	port        int
	payloadType uint8
}

func main() {
	// Everything below is the Pion WebRTC API! Thanks for using it ❤.

	// Create a MediaEngine object to configure the supported codec
	m := &webrtc.MediaEngine{}

	// Setup the codecs you want to use.
	// We'll use a VP8 and Opus but you can also define your own
	if err := m.RegisterCodec(webrtc.RTPCodecParameters{
		RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil},
	}, webrtc.RTPCodecTypeVideo); err != nil {
		panic(err)
	}
	if err := m.RegisterCodec(webrtc.RTPCodecParameters{
		RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus, ClockRate: 48000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil},
	}, webrtc.RTPCodecTypeAudio); err != nil {
		panic(err)
	}

	// Create a InterceptorRegistry. This is the user configurable RTP/RTCP Pipeline.
	// This provides NACKs, RTCP Reports and other features. If you use `webrtc.NewPeerConnection`
	// this is enabled by default. If you are manually managing You MUST create a InterceptorRegistry
	// for each PeerConnection.
	i := &interceptor.Registry{}

	// Use the default set of Interceptors
	if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil {
		panic(err)
	}

	// Create the API object with the MediaEngine
	api := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i))

	// Prepare the configuration
	config := webrtc.Configuration{
		ICEServers: []webrtc.ICEServer{
			{
				URLs: []string{"stun:stun.l.google.com:19302"},
			},
		},
	}

	// Create a new RTCPeerConnection
	peerConnection, err := api.NewPeerConnection(config)
	if err != nil {
		panic(err)
	}
	defer func() {
		if cErr := peerConnection.Close(); cErr != nil {
			fmt.Printf("cannot close peerConnection: %v\n", cErr)
		}
	}()

	// Allow us to receive 1 audio track, and 1 video track
	if _, err = peerConnection.AddTransceiverFromKind(webrtc.RTPCodecTypeAudio); err != nil {
		panic(err)
	} else if _, err = peerConnection.AddTransceiverFromKind(webrtc.RTPCodecTypeVideo); err != nil {
		panic(err)
	}

	// Create a local addr
	var laddr *net.UDPAddr
	if laddr, err = net.ResolveUDPAddr("udp", "127.0.0.1:"); err != nil {
		panic(err)
	}

	// Prepare udp conns
	// Also update incoming packets with expected PayloadType, the browser may use
	// a different value. We have to modify so our stream matches what rtp-forwarder.sdp expects
	udpConns := map[string]*udpConn{
		"audio": {port: 4000, payloadType: 111},
		"video": {port: 4002, payloadType: 96},
	}
	for _, c := range udpConns {
		// Create remote addr
		var raddr *net.UDPAddr
		if raddr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("127.0.0.1:%d", c.port)); err != nil {
			panic(err)
		}

		// Dial udp
		if c.conn, err = net.DialUDP("udp", laddr, raddr); err != nil {
			panic(err)
		}
		defer func(conn net.PacketConn) {
			if closeErr := conn.Close(); closeErr != nil {
				panic(closeErr)
			}
		}(c.conn)
	}

	// Set a handler for when a new remote track starts, this handler will forward data to
	// our UDP listeners.
	// In your application this is where you would handle/process audio/video
	peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
		// Retrieve udp connection
		c, ok := udpConns[track.Kind().String()]
		if !ok {
			return
		}

		// Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval
		go func() {
			ticker := time.NewTicker(time.Second * 2)
			for range ticker.C {
				if rtcpErr := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}}); rtcpErr != nil {
					fmt.Println(rtcpErr)
				}
			}
		}()

		b := make([]byte, 1500)
		rtpPacket := &rtp.Packet{}
		for {
			// Read
			n, _, readErr := track.Read(b)
			if readErr != nil {
				panic(readErr)
			}

			// Unmarshal the packet and update the PayloadType
			if err = rtpPacket.Unmarshal(b[:n]); err != nil {
				panic(err)
			}
			rtpPacket.PayloadType = c.payloadType

			// Marshal into original buffer with updated PayloadType
			if n, err = rtpPacket.MarshalTo(b); err != nil {
				panic(err)
			}

			// Write
			if _, err = c.conn.Write(b[:n]); err != nil {
				// For this particular example, third party applications usually timeout after a short
				// amount of time during which the user doesn't have enough time to provide the answer
				// to the browser.
				// That's why, for this particular example, the user first needs to provide the answer
				// to the browser then open the third party application. Therefore we must not kill
				// the forward on "connection refused" errors
				var opError *net.OpError
				if errors.As(err, &opError); ok && opError.Err.Error() == "write: connection refused" {
					continue
				}
				panic(err)
			}
		}
	})

	// Set the handler for ICE connection state
	// This will notify you when the peer has connected/disconnected
	peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {
		fmt.Printf("Connection State has changed %s \n", connectionState.String())

		if connectionState == webrtc.ICEConnectionStateConnected {
			fmt.Println("Ctrl+C the remote client to stop the demo")
		}
	})

	// Set the handler for Peer connection state
	// This will notify you when the peer has connected/disconnected
	peerConnection.OnConnectionStateChange(func(s webrtc.PeerConnectionState) {
		fmt.Printf("Peer Connection State has changed: %s\n", s.String())

		if s == webrtc.PeerConnectionStateFailed {
			// Wait until PeerConnection has had no network activity for 30 seconds or another failure. It may be reconnected using an ICE Restart.
			// Use webrtc.PeerConnectionStateDisconnected if you are interested in detecting faster timeout.
			// Note that the PeerConnection may come back from PeerConnectionStateDisconnected.
			fmt.Println("Done forwarding")
			os.Exit(0)
		}
	})

	// Wait for the offer to be pasted
	offer := webrtc.SessionDescription{}
	signal.Decode(signal.MustReadStdin(), &offer)

	// Set the remote SessionDescription
	if err = peerConnection.SetRemoteDescription(offer); err != nil {
		panic(err)
	}

	// Create answer
	answer, err := peerConnection.CreateAnswer(nil)
	if err != nil {
		panic(err)
	}

	// Create channel that is blocked until ICE Gathering is complete
	gatherComplete := webrtc.GatheringCompletePromise(peerConnection)

	// Sets the LocalDescription, and starts our UDP listeners
	if err = peerConnection.SetLocalDescription(answer); err != nil {
		panic(err)
	}

	// Block until ICE Gathering is complete, disabling trickle ICE
	// we do this because we only can exchange one signaling message
	// in a production application you should exchange ICE Candidates via OnICECandidate
	<-gatherComplete

	// Output the answer in base64 so we can paste it in browser
	fmt.Println(signal.Encode(*peerConnection.LocalDescription()))

	// Block forever
	select {}
}
<commit_msg>Use a new error variable to avoid race condition<commit_after>//go:build !js
// +build !js

package main

import (
	"errors"
	"fmt"
	"net"
	"os"
	"time"

	"github.com/pion/interceptor"
	"github.com/pion/rtcp"
	"github.com/pion/rtp"
	"github.com/pion/webrtc/v3"
	"github.com/pion/webrtc/v3/examples/internal/signal"
)

type udpConn struct {
	conn        *net.UDPConn
	port        int
	payloadType uint8
}

func main() {
	// Everything below is the Pion WebRTC API! Thanks for using it ❤.

	// Create a MediaEngine object to configure the supported codec
	m := &webrtc.MediaEngine{}

	// Setup the codecs you want to use.
	// We'll use a VP8 and Opus but you can also define your own
	if err := m.RegisterCodec(webrtc.RTPCodecParameters{
		RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeVP8, ClockRate: 90000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil},
	}, webrtc.RTPCodecTypeVideo); err != nil {
		panic(err)
	}
	if err := m.RegisterCodec(webrtc.RTPCodecParameters{
		RTPCodecCapability: webrtc.RTPCodecCapability{MimeType: webrtc.MimeTypeOpus, ClockRate: 48000, Channels: 0, SDPFmtpLine: "", RTCPFeedback: nil},
	}, webrtc.RTPCodecTypeAudio); err != nil {
		panic(err)
	}

	// Create a InterceptorRegistry. This is the user configurable RTP/RTCP Pipeline.
	// This provides NACKs, RTCP Reports and other features. If you use `webrtc.NewPeerConnection`
	// this is enabled by default. If you are manually managing You MUST create a InterceptorRegistry
	// for each PeerConnection.
	i := &interceptor.Registry{}

	// Use the default set of Interceptors
	if err := webrtc.RegisterDefaultInterceptors(m, i); err != nil {
		panic(err)
	}

	// Create the API object with the MediaEngine
	api := webrtc.NewAPI(webrtc.WithMediaEngine(m), webrtc.WithInterceptorRegistry(i))

	// Prepare the configuration
	config := webrtc.Configuration{
		ICEServers: []webrtc.ICEServer{
			{
				URLs: []string{"stun:stun.l.google.com:19302"},
			},
		},
	}

	// Create a new RTCPeerConnection
	peerConnection, err := api.NewPeerConnection(config)
	if err != nil {
		panic(err)
	}
	defer func() {
		if cErr := peerConnection.Close(); cErr != nil {
			fmt.Printf("cannot close peerConnection: %v\n", cErr)
		}
	}()

	// Allow us to receive 1 audio track, and 1 video track
	if _, err = peerConnection.AddTransceiverFromKind(webrtc.RTPCodecTypeAudio); err != nil {
		panic(err)
	} else if _, err = peerConnection.AddTransceiverFromKind(webrtc.RTPCodecTypeVideo); err != nil {
		panic(err)
	}

	// Create a local addr
	var laddr *net.UDPAddr
	if laddr, err = net.ResolveUDPAddr("udp", "127.0.0.1:"); err != nil {
		panic(err)
	}

	// Prepare udp conns
	// Also update incoming packets with expected PayloadType, the browser may use
	// a different value. We have to modify so our stream matches what rtp-forwarder.sdp expects
	udpConns := map[string]*udpConn{
		"audio": {port: 4000, payloadType: 111},
		"video": {port: 4002, payloadType: 96},
	}
	for _, c := range udpConns {
		// Create remote addr
		var raddr *net.UDPAddr
		if raddr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("127.0.0.1:%d", c.port)); err != nil {
			panic(err)
		}

		// Dial udp
		if c.conn, err = net.DialUDP("udp", laddr, raddr); err != nil {
			panic(err)
		}
		defer func(conn net.PacketConn) {
			if closeErr := conn.Close(); closeErr != nil {
				panic(closeErr)
			}
		}(c.conn)
	}

	// Set a handler for when a new remote track starts, this handler will forward data to
	// our UDP listeners.
	// In your application this is where you would handle/process audio/video
	peerConnection.OnTrack(func(track *webrtc.TrackRemote, receiver *webrtc.RTPReceiver) {
		// Retrieve udp connection
		c, ok := udpConns[track.Kind().String()]
		if !ok {
			return
		}

		// Send a PLI on an interval so that the publisher is pushing a keyframe every rtcpPLIInterval
		go func() {
			ticker := time.NewTicker(time.Second * 2)
			for range ticker.C {
				if rtcpErr := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}}); rtcpErr != nil {
					fmt.Println(rtcpErr)
				}
			}
		}()

		b := make([]byte, 1500)
		rtpPacket := &rtp.Packet{}
		for {
			// Read
			n, _, readErr := track.Read(b)
			if readErr != nil {
				panic(readErr)
			}

			// Unmarshal the packet and update the PayloadType
			if err = rtpPacket.Unmarshal(b[:n]); err != nil {
				panic(err)
			}
			rtpPacket.PayloadType = c.payloadType

			// Marshal into original buffer with updated PayloadType
			if n, err = rtpPacket.MarshalTo(b); err != nil {
				panic(err)
			}

			// Write
			if _, writeErr := c.conn.Write(b[:n]); writeErr != nil {
				// For this particular example, third party applications usually timeout after a short
				// amount of time during which the user doesn't have enough time to provide the answer
				// to the browser.
				// That's why, for this particular example, the user first needs to provide the answer
				// to the browser then open the third party application. Therefore we must not kill
				// the forward on "connection refused" errors
				var opError *net.OpError
				if errors.As(writeErr, &opError) && opError.Err.Error() == "write: connection refused" {
					continue
				}
				panic(err)
			}
		}
	})

	// Set the handler for ICE connection state
	// This will notify you when the peer has connected/disconnected
	peerConnection.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) {
		fmt.Printf("Connection State has changed %s \n", connectionState.String())

		if connectionState == webrtc.ICEConnectionStateConnected {
			fmt.Println("Ctrl+C the remote client to stop the demo")
		}
	})

	// Set the handler for Peer connection state
	// This will notify you when the peer has connected/disconnected
	peerConnection.OnConnectionStateChange(func(s webrtc.PeerConnectionState) {
		fmt.Printf("Peer Connection State has changed: %s\n", s.String())

		if s == webrtc.PeerConnectionStateFailed {
			// Wait until PeerConnection has had no network activity for 30 seconds or another failure. It may be reconnected using an ICE Restart.
			// Use webrtc.PeerConnectionStateDisconnected if you are interested in detecting faster timeout.
			// Note that the PeerConnection may come back from PeerConnectionStateDisconnected.
			fmt.Println("Done forwarding")
			os.Exit(0)
		}
	})

	// Wait for the offer to be pasted
	offer := webrtc.SessionDescription{}
	signal.Decode(signal.MustReadStdin(), &offer)

	// Set the remote SessionDescription
	if err = peerConnection.SetRemoteDescription(offer); err != nil {
		panic(err)
	}

	// Create answer
	answer, err := peerConnection.CreateAnswer(nil)
	if err != nil {
		panic(err)
	}

	// Create channel that is blocked until ICE Gathering is complete
	gatherComplete := webrtc.GatheringCompletePromise(peerConnection)

	// Sets the LocalDescription, and starts our UDP listeners
	if err = peerConnection.SetLocalDescription(answer); err != nil {
		panic(err)
	}

	// Block until ICE Gathering is complete, disabling trickle ICE
	// we do this because we only can exchange one signaling message
	// in a production application you should exchange ICE Candidates via OnICECandidate
	<-gatherComplete

	// Output the answer in base64 so we can paste it in browser
	fmt.Println(signal.Encode(*peerConnection.LocalDescription()))

	// Block forever
	select {}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

func home() string {
	file, err := ioutil.TempDir(os.TempDir(), "antibody")
	if err != nil {
		panic(err.Error())
	}
	defer os.RemoveAll(file)
	os.Setenv("ANTIBODY_HOME", file+"/")
	return file + "/"
}

func expectError(t *testing.T) {
	if err := recover(); err != nil {
		t.Log("Recovered from expected error")
	} else {
		t.Error("Expected an error here!")
	}
}

func TestProcessesArgsBunde(t *testing.T) {
	home := home()
	ProcessArgs([]string{"bundle", "caarlos0/zsh-pg"}, home)
}

func TestUpdate(t *testing.T) {
	home := home()
	ProcessArgs([]string{"update"}, home)
}

func TestBundlesSinglePlugin(t *testing.T) {
	home := home()
	Bundle("caarlos0/zsh-pg", home)
}

func TestLoadsDefaultHome(t *testing.T) {
	os.Unsetenv("ANTIBODY_HOME")
	if !strings.HasSuffix(Home(), "/.antibody/") {
		t.Error("Expected default ANTIBODY_HOME")
	}
}

func TestLoadsCustomHome(t *testing.T) {
	home := home()
	if home != Home() {
		t.Error("Expected custom ANTIBODY_HOME")
	}
}

func TestAddsTrailingSlashToHome(t *testing.T) {
	home := "/tmp/whatever"
	os.Setenv("ANTIBODY_HOME", home)
	if Home() != home+"/" {
		t.Error("Expected a trailing slash in", Home())
	}
}

func TestFailsToBundleInvalidRepos(t *testing.T) {
	home := home()
	defer expectError(t)
	Bundle("csadsadp", home)
}

func TestFailsToProcessInvalidArgs(t *testing.T) {
	home := home()
	defer expectError(t)
	ProcessArgs([]string{"nope", "caarlos0/zsh-pg"}, home)
}

func TestReadsStdinIsFalse(t *testing.T) {
	if ReadStdin() {
		t.Error("Not reading STDIN")
	}
}

func TestReadsStdinIsTrue(t *testing.T) {
	os.Stdin.Write([]byte("Some STDIN"))
	if ReadStdin() {
		t.Error("Not reading STDIN")
	}
}

func TestProcessStdin(t *testing.T) {
	home := home()
	bundles := bytes.NewBufferString("caarlos0/zsh-pg\ncaarlos0/zsh-add-upstream")
	ProcessStdin(bundles, home)
	dirs, _ := ioutil.ReadDir(home)
	if len(dirs) != 2 {
		t.Error("Expected to bundle 2 plugins, but was", len(dirs))
	}
}
<commit_msg>Improved tests, got a bug!<commit_after>package main

import (
	"bytes"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

func home() string {
	file, err := ioutil.TempDir(os.TempDir(), "antibody")
	if err != nil {
		panic(err.Error())
	}
	defer os.RemoveAll(file)
	os.Setenv("ANTIBODY_HOME", file+"/")
	return file + "/"
}

func expectError(t *testing.T) {
	if err := recover(); err != nil {
		t.Log("Recovered from expected error")
	} else {
		t.Error("Expected an error here!")
	}
}

func assertBundledPlugins(t *testing.T, total int, home string) {
	plugins, _ := ioutil.ReadDir(home)
	if len(plugins) != total {
		t.Error("Expected to bundle", total, "plugins, but was", len(plugins))
	}
}

func TestProcessesArgsBunde(t *testing.T) {
	home := home()
	ProcessArgs([]string{"bundle", "caarlos0/zsh-pg"}, home)
	assertBundledPlugins(t, 1, home)
}

func TestUpdateWithNoPlugins(t *testing.T) {
	home := home()
	ProcessArgs([]string{"update"}, home)
	assertBundledPlugins(t, 0, home)
}

func TestUpdateWithPlugins(t *testing.T) {
	home := home()
	Bundle("caarlos0/zsh-pg", home)
	ProcessArgs([]string{"update"}, home)
	assertBundledPlugins(t, 1, home)
}

func TestBundlesSinglePlugin(t *testing.T) {
	home := home()
	Bundle("caarlos0/zsh-pg", home)
}

func TestLoadsDefaultHome(t *testing.T) {
	os.Unsetenv("ANTIBODY_HOME")
	if !strings.HasSuffix(Home(), "/.antibody/") {
		t.Error("Expected default ANTIBODY_HOME")
	}
}

func TestLoadsCustomHome(t *testing.T) {
	home := home()
	if home != Home() {
		t.Error("Expected custom ANTIBODY_HOME")
	}
}

func TestAddsTrailingSlashToHome(t *testing.T) {
	home := "/tmp/whatever"
	os.Setenv("ANTIBODY_HOME", home)
	if Home() != home+"/" {
		t.Error("Expected a trailing slash in", Home())
	}
}

func TestFailsToBundleInvalidRepos(t *testing.T) {
	home := home()
	defer expectError(t)
	Bundle("csadsadp", home)
}

func TestFailsToProcessInvalidArgs(t *testing.T) {
	home := home()
	defer expectError(t)
	ProcessArgs([]string{"nope", "caarlos0/zsh-pg"}, home)
}

func TestReadsStdinIsFalse(t *testing.T) {
	if ReadStdin() {
		t.Error("Not reading STDIN")
	}
}

func TestReadsStdinIsTrue(t *testing.T) {
	os.Stdin.Write([]byte("Some STDIN"))
	if ReadStdin() {
		t.Error("Not reading STDIN")
	}
}

func TestProcessStdin(t *testing.T) {
	home := home()
	bundles := bytes.NewBufferString("caarlos0/zsh-pg\ncaarlos0/zsh-add-upstream")
	ProcessStdin(bundles, home)
	assertBundledPlugins(t, 2, home)
}
<|endoftext|>


<commit_before>package js

import (
	// "github.com/robertkrimen/otto"
	log "github.com/Sirupsen/logrus"
	"github.com/loadimpact/speedboat/lib"
	"github.com/loadimpact/speedboat/stats"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httptrace"
	"strings"
	"time"
)

var (
	MetricReqs          = stats.New("http_reqs", stats.Counter)
	MetricReqDuration   = stats.New("http_req_duration", stats.Trend, stats.Time)
	MetricReqBlocked    = stats.New("http_req_blocked", stats.Trend, stats.Time)
	MetricReqLookingUp  = stats.New("http_req_looking_up", stats.Trend, stats.Time)
	MetricReqConnecting = stats.New("http_req_connecting", stats.Trend, stats.Time)
	MetricReqSending    = stats.New("http_req_sending", stats.Trend, stats.Time)
	MetricReqWaiting    = stats.New("http_req_waiting", stats.Trend, stats.Time)
	MetricReqReceiving  = stats.New("http_req_receiving", stats.Trend, stats.Time)
)

type HTTPResponse struct {
	Status int
}

func (a JSAPI) HTTPRequest(method, url, body string, params map[string]interface{}) map[string]interface{} {
	log.WithFields(log.Fields{
		"method": method,
		"url":    url,
		"body":   body,
	}).Debug("JS: Request")
	bodyReader := io.Reader(nil)
	if body != "" {
		bodyReader = strings.NewReader(body)
	}
	req, err := http.NewRequest(method, url, bodyReader)
	if err != nil {
		throw(a.vu.vm, err)
	}

	if h, ok := params["headers"]; ok {
		headers, ok := h.(map[string]interface{})
		if !ok {
			panic(a.vu.vm.MakeTypeError("headers must be an object"))
		}
		for key, v := range headers {
			value, ok := v.(string)
			if !ok {
				panic(a.vu.vm.MakeTypeError("header values must be strings"))
			}
			req.Header.Set(key, value)
		}
	}

	tracer := lib.Tracer{}
	res, err := a.vu.HTTPClient.Do(req.WithContext(httptrace.WithClientTrace(a.vu.ctx, tracer.Trace())))
	if err != nil {
		throw(a.vu.vm, err)
	}

	resBody, err := ioutil.ReadAll(res.Body)
	if err != nil {
		throw(a.vu.vm, err)
	}
	res.Body.Close()

	trail := tracer.Done()
	t := time.Now()
	tags := map[string]string{
		"vu":     a.vu.IDString,
		"method": method,
		"url":    url,
	}
	a.vu.Samples = append(a.vu.Samples,
		stats.Sample{Metric: MetricReqs, Time: t, Tags: tags, Value: 1},
		stats.Sample{Metric: MetricReqDuration, Time: t, Tags: tags, Value: float64(trail.Duration)},
		stats.Sample{Metric: MetricReqBlocked, Time: t, Tags: tags, Value: float64(trail.Blocked)},
		stats.Sample{Metric: MetricReqLookingUp, Time: t, Tags: tags, Value: float64(trail.LookingUp)},
		stats.Sample{Metric: MetricReqConnecting, Time: t, Tags: tags, Value: float64(trail.Connecting)},
		stats.Sample{Metric: MetricReqSending, Time: t, Tags: tags, Value: float64(trail.Sending)},
		stats.Sample{Metric: MetricReqWaiting, Time: t, Tags: tags, Value: float64(trail.Waiting)},
		stats.Sample{Metric: MetricReqReceiving, Time: t, Tags: tags, Value: float64(trail.Receiving)},
	)

	headers := make(map[string]string)
	for k, v := range res.Header {
		headers[k] = strings.Join(v, ", ")
	}
	return map[string]interface{}{
		"status":  res.StatusCode,
		"body":    string(resBody),
		"headers": headers,
	}
}

func (a JSAPI) HTTPSetMaxRedirects(n int) {
	a.vu.MaxRedirects = n
}
<commit_msg>[feat] Metrics tagged with group IDs<commit_after>package js

import (
	// "github.com/robertkrimen/otto"
	log "github.com/Sirupsen/logrus"
	"github.com/loadimpact/speedboat/lib"
	"github.com/loadimpact/speedboat/stats"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httptrace"
	"strconv"
	"strings"
	"time"
)

var (
	MetricReqs          = stats.New("http_reqs", stats.Counter)
	MetricReqDuration   = stats.New("http_req_duration", stats.Trend, stats.Time)
	MetricReqBlocked    = stats.New("http_req_blocked", stats.Trend, stats.Time)
	MetricReqLookingUp  = stats.New("http_req_looking_up", stats.Trend, stats.Time)
	MetricReqConnecting = stats.New("http_req_connecting", stats.Trend, stats.Time)
	MetricReqSending    = stats.New("http_req_sending", stats.Trend, stats.Time)
	MetricReqWaiting    = stats.New("http_req_waiting", stats.Trend, stats.Time)
	MetricReqReceiving  = stats.New("http_req_receiving", stats.Trend, stats.Time)
)

type HTTPResponse struct {
	Status int
}

func (a JSAPI) HTTPRequest(method, url, body string, params map[string]interface{}) map[string]interface{} {
	log.WithFields(log.Fields{
		"method": method,
		"url":    url,
		"body":   body,
	}).Debug("JS: Request")
	bodyReader := io.Reader(nil)
	if body != "" {
		bodyReader = strings.NewReader(body)
	}
	req, err := http.NewRequest(method, url, bodyReader)
	if err != nil {
		throw(a.vu.vm, err)
	}

	if h, ok := params["headers"]; ok {
		headers, ok := h.(map[string]interface{})
		if !ok {
			panic(a.vu.vm.MakeTypeError("headers must be an object"))
		}
		for key, v := range headers {
			value, ok := v.(string)
			if !ok {
				panic(a.vu.vm.MakeTypeError("header values must be strings"))
			}
			req.Header.Set(key, value)
		}
	}

	tracer := lib.Tracer{}
	res, err := a.vu.HTTPClient.Do(req.WithContext(httptrace.WithClientTrace(a.vu.ctx, tracer.Trace())))
	if err != nil {
		throw(a.vu.vm, err)
	}

	resBody, err := ioutil.ReadAll(res.Body)
	if err != nil {
		throw(a.vu.vm, err)
	}
	res.Body.Close()

	trail := tracer.Done()
	t := time.Now()
	tags := map[string]string{
		"vu":       a.vu.IDString,
		"method":   method,
		"url":      url,
		"group_id": strconv.FormatInt(a.vu.group.ID, 10),
	}
	a.vu.Samples = append(a.vu.Samples,
		stats.Sample{Metric: MetricReqs, Time: t, Tags: tags, Value: 1},
		stats.Sample{Metric: MetricReqDuration, Time: t, Tags: tags, Value: float64(trail.Duration)},
		stats.Sample{Metric: MetricReqBlocked, Time: t, Tags: tags, Value: float64(trail.Blocked)},
		stats.Sample{Metric: MetricReqLookingUp, Time: t, Tags: tags, Value: float64(trail.LookingUp)},
		stats.Sample{Metric: MetricReqConnecting, Time: t, Tags: tags, Value: float64(trail.Connecting)},
		stats.Sample{Metric: MetricReqSending, Time: t, Tags: tags, Value: float64(trail.Sending)},
		stats.Sample{Metric: MetricReqWaiting, Time: t, Tags: tags, Value: float64(trail.Waiting)},
		stats.Sample{Metric: MetricReqReceiving, Time: t, Tags: tags, Value: float64(trail.Receiving)},
	)

	headers := make(map[string]string)
	for k, v := range res.Header {
		headers[k] = strings.Join(v, ", ")
	}
	return map[string]interface{}{
		"status":  res.StatusCode,
		"body":    string(resBody),
		"headers": headers,
	}
}

func (a JSAPI) HTTPSetMaxRedirects(n int) {
	a.vu.MaxRedirects = n
}
<|endoftext|>


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

package jaeger

import (
	"fmt"
	"reflect"
	"testing"
	"time"

	gen "go.opencensus.io/exporter/jaeger/internal/gen-go/jaeger"
	"go.opencensus.io/trace"
)

// TODO(jbd): Test export.

func Test_bytesToInt64(t *testing.T) {
	type args struct {
	}
	tests := []struct {
		buf  []byte
		want int64
	}{
		{
			buf:  []byte{255, 0, 0, 0, 0, 0, 0, 0},
			want: -72057594037927936,
		},
		{
			buf:  []byte{0, 0, 0, 0, 0, 0, 0, 1},
			want: 1,
		},
		{
			buf:  []byte{0, 0, 0, 0, 0, 0, 0, 0},
			want: 0,
		},
	}
	for _, tt := range tests {
		t.Run(fmt.Sprintf("%d", tt.want), func(t *testing.T) {
			if got := bytesToInt64(tt.buf); got != tt.want {
				t.Errorf("bytesToInt64() = \n%v, \n want \n%v", got, tt.want)
			}
		})
	}
}

func Test_spanDataToThrift(t *testing.T) {
	now := time.Now()

	answerValue := int64(42)
	keyValue := "value"
	resultValue := true
	statusCodeValue := int64(2)
	doubleValue := float64(123.456)
	statusMessage := "error"

	tests := []struct {
		name string
		data *trace.SpanData
		want *gen.Span
	}{
		{
			name: "no parent",
			data: &trace.SpanData{
				SpanContext: trace.SpanContext{
					TraceID: trace.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
					SpanID:  trace.SpanID{1, 2, 3, 4, 5, 6, 7, 8},
				},
				Name:      "/foo",
				StartTime: now,
				EndTime:   now,
				Attributes: map[string]interface{}{
					"double": doubleValue,
					"key":    keyValue,
				},
				Annotations: []trace.Annotation{
					{
						Time:    now,
						Message: statusMessage,
						Attributes: map[string]interface{}{
							"answer": answerValue,
						},
					},
					{
						Time:    now,
						Message: statusMessage,
						Attributes: map[string]interface{}{
							"result": resultValue,
						},
					},
				},
				Status: trace.Status{Code: trace.StatusCodeUnknown, Message: "error"},
			},
			want: &gen.Span{
				TraceIdLow:    651345242494996240,
				TraceIdHigh:   72623859790382856,
				SpanId:        72623859790382856,
				OperationName: "/foo",
				StartTime:     now.UnixNano() / 1000,
				Duration:      0,
				Tags: []*gen.Tag{
					{Key: "double", VType: gen.TagType_DOUBLE, VDouble: &doubleValue},
					{Key: "key", VType: gen.TagType_STRING, VStr: &keyValue},
					{Key: "status.code", VType: gen.TagType_LONG, VLong: &statusCodeValue},
					{Key: "status.message", VType: gen.TagType_STRING, VStr: &statusMessage},
				},
				Logs: []*gen.Log{
					{Timestamp: now.UnixNano() / 1000, Fields: []*gen.Tag{
						{Key: "answer", VType: gen.TagType_LONG, VLong: &answerValue},
						{Key: "message", VType: gen.TagType_STRING, VStr: &statusMessage},
					}},
					{Timestamp: now.UnixNano() / 1000, Fields: []*gen.Tag{
						{Key: "result", VType: gen.TagType_BOOL, VBool: &resultValue},
						{Key: "message", VType: gen.TagType_STRING, VStr: &statusMessage},
					}},
				},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := spanDataToThrift(tt.data); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("spanDataToThrift() = %v, want %v", got, tt.want)
			}
		})
	}
}
<commit_msg>fix inconsistent jaeger test. (#1038)<commit_after>// Copyright 2018, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package jaeger

import (
	"fmt"
	"reflect"
	"testing"
	"time"

	gen "go.opencensus.io/exporter/jaeger/internal/gen-go/jaeger"
	"go.opencensus.io/trace"
	"sort"
)

// TODO(jbd): Test export.

func Test_bytesToInt64(t *testing.T) {
	type args struct {
	}
	tests := []struct {
		buf  []byte
		want int64
	}{
		{
			buf:  []byte{255, 0, 0, 0, 0, 0, 0, 0},
			want: -72057594037927936,
		},
		{
			buf:  []byte{0, 0, 0, 0, 0, 0, 0, 1},
			want: 1,
		},
		{
			buf:  []byte{0, 0, 0, 0, 0, 0, 0, 0},
			want: 0,
		},
	}
	for _, tt := range tests {
		t.Run(fmt.Sprintf("%d", tt.want), func(t *testing.T) {
			if got := bytesToInt64(tt.buf); got != tt.want {
				t.Errorf("bytesToInt64() = \n%v, \n want \n%v", got, tt.want)
			}
		})
	}
}

func Test_spanDataToThrift(t *testing.T) {
	now := time.Now()

	answerValue := int64(42)
	keyValue := "value"
	resultValue := true
	statusCodeValue := int64(2)
	doubleValue := float64(123.456)
	statusMessage := "error"

	tests := []struct {
		name string
		data *trace.SpanData
		want *gen.Span
	}{
		{
			name: "no parent",
			data: &trace.SpanData{
				SpanContext: trace.SpanContext{
					TraceID: trace.TraceID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
					SpanID:  trace.SpanID{1, 2, 3, 4, 5, 6, 7, 8},
				},
				Name:      "/foo",
				StartTime: now,
				EndTime:   now,
				Attributes: map[string]interface{}{
					"double": doubleValue,
					"key":    keyValue,
				},
				Annotations: []trace.Annotation{
					{
						Time:    now,
						Message: statusMessage,
						Attributes: map[string]interface{}{
							"answer": answerValue,
						},
					},
					{
						Time:    now,
						Message: statusMessage,
						Attributes: map[string]interface{}{
							"result": resultValue,
						},
					},
				},
				Status: trace.Status{Code: trace.StatusCodeUnknown, Message: "error"},
			},
			want: &gen.Span{
				TraceIdLow:    651345242494996240,
				TraceIdHigh:   72623859790382856,
				SpanId:        72623859790382856,
				OperationName: "/foo",
				StartTime:     now.UnixNano() / 1000,
				Duration:      0,
				Tags: []*gen.Tag{
					{Key: "double", VType: gen.TagType_DOUBLE, VDouble: &doubleValue},
					{Key: "key", VType: gen.TagType_STRING, VStr: &keyValue},
					{Key: "status.code", VType: gen.TagType_LONG, VLong: &statusCodeValue},
					{Key: "status.message", VType: gen.TagType_STRING, VStr: &statusMessage},
				},
				Logs: []*gen.Log{
					{Timestamp: now.UnixNano() / 1000, Fields: []*gen.Tag{
						{Key: "answer", VType: gen.TagType_LONG, VLong: &answerValue},
						{Key: "message", VType: gen.TagType_STRING, VStr: &statusMessage},
					}},
					{Timestamp: now.UnixNano() / 1000, Fields: []*gen.Tag{
						{Key: "result", VType: gen.TagType_BOOL, VBool: &resultValue},
						{Key: "message", VType: gen.TagType_STRING, VStr: &statusMessage},
					}},
				},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := spanDataToThrift(tt.data)
			sort.Slice(got.Tags, func(i, j int) bool {
				return got.Tags[i].Key < got.Tags[j].Key
			})
			sort.Slice(tt.want.Tags, func(i, j int) bool {
				return tt.want.Tags[i].Key < tt.want.Tags[j].Key
			})
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("spanDataToThrift() = %v, want %v", got, tt.want)
			}
		})
	}
}
<|endoftext|>


<commit_before>/*
 Copyright 2018 Padduck, LLC

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

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

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

package environments

import (
	"github.com/pufferpanel/pufferpanel/v2/environments/tty"
)

func loadAdditionalModules(mapping map[string]pufferpanel.EnvironmentFactory) {
	mapping["standard"] = tty.EnvironmentFactory{}
	mapping["tty"] = tty.EnvironmentFactory{}
	//mapping["lxd"] = lxd.EnvironmentFactory{}
}
<commit_msg>Update environmentloader_darwin.go<commit_after>/*
 Copyright 2018 Padduck, LLC

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

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

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

package environments

import (
	"github.com/pufferpanel/pufferpanel/v2"
	"github.com/pufferpanel/pufferpanel/v2/environments/tty"
)

func loadAdditionalModules(mapping map[string]pufferpanel.EnvironmentFactory) {
	mapping["standard"] = tty.EnvironmentFactory{}
	mapping["tty"] = tty.EnvironmentFactory{}
	//mapping["lxd"] = lxd.EnvironmentFactory{}
}
<|endoftext|>