<commit_before>// Copyright 2018 The Trickuri 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
//
//     https://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.

// Trickuri generates test cases for URL spoofing vulnerabilities.
package main

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"flag"
	"fmt"
	"io"
	"log"
	"math/big"
	"net"
	"net/http"
	"os"
	"path"
	"runtime"
	"strconv"
	"strings"
	"time"
)

var (
	port      = flag.Int("p", 1270, "port on which to listen")
	httpsPort = flag.Int("h", 8443, "port on which the HTTPS proxy will listen")
	directory = flag.String("d", userHomeDir()+"/.config/trickuri", "default directory in which to save certificates")
	testIndex = flag.String("i", "index.html", "default file location contating test index")
)

var (
	caKey   crypto.PrivateKey
	caCert  *x509.Certificate
	certMap = make(map[string]*tls.Certificate)

	// TODO: fix the data race around this variable, either with a lock on this
	// variable, or (possibly better) by using a channel.
	lastTunneledHost string
)

// userHomeDir returns a suitable directory for the default certificate storage path.
func userHomeDir() string {
	if runtime.GOOS == "windows" {
		home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
		if home == "" {
			home = os.Getenv("USERPROFILE")
		}
		return home
	}
	return os.Getenv("HOME")
}

// newCertificate returns an initialized certificate with usable values.
func newCertificate() (*x509.Certificate, error) {
	maxSerial := new(big.Int).Lsh(big.NewInt(1), 128)
	serial, err := rand.Int(rand.Reader, maxSerial)
	if err != nil {
		return nil, err
	}

	return &x509.Certificate{
		SerialNumber: serial,
		Subject: pkix.Name{
			Organization: []string{"TrickUri Interception Certificate"},
		},
		NotBefore:             time.Now().AddDate(0, 0, -7), // mitigate clock-skew
		NotAfter:              time.Now().AddDate(1, 0, 7),
		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}, nil
}

// newRootCertificate returns a root certificate and its key.
func newRootCertificate() ([]byte, *rsa.PrivateKey, error) {
	private, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, nil, err
	}

	cert, err := newCertificate()
	if err != nil {
		return nil, nil, err
	}
	cert.IsCA = true
	cert.MaxPathLen = 0
	cert.MaxPathLenZero = true
	cert.Subject = pkix.Name{Organization: []string{"TrickUri Root"}}
	hash := sha256.Sum256(private.PublicKey.N.Bytes())
	cert.SubjectKeyId = hash[:]
	cert.KeyUsage |= x509.KeyUsageCertSign

	certBytes, err := x509.CreateCertificate(rand.Reader, cert, cert, &private.PublicKey, private)
	if err != nil {
		return nil, nil, err
	}

	return certBytes, private, nil
}

// writeCertificate writes the provided certificate and key to files in the specified paths.
func writeCertificate(cert []byte, key *rsa.PrivateKey, certPath, keyPath string) error {
	certFile, err := os.Create(certPath)
	if err != nil {
		return err
	}
	if err := pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: cert}); err != nil {
		return err
	}
	if err := certFile.Close(); err != nil {
		return err
	}

	keyFile, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	if err := pem.Encode(keyFile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}); err != nil {
		return err
	}
	if err := keyFile.Close(); err != nil {
		return err
	}

	return nil
}

// rootCertificate returns a root certificate, either loaded from the given
// directory, or created and saved.
func rootCertificate(directory string) (tls.Certificate, error) {
	certPath := path.Join(directory, "root.cer")
	keyPath := path.Join(directory, "root.pem")

	rootKeys, err := tls.LoadX509KeyPair(certPath, keyPath)
	if err != nil {
		log.Println("Failed to load root certificate. Recreating root certificate.")
		rootCert, rootKey, err := newRootCertificate()
		if err != nil {
			return tls.Certificate{}, err
		}
		if err := writeCertificate(rootCert, rootKey, certPath, keyPath); err != nil {
			return tls.Certificate{}, err
		}
		return tls.LoadX509KeyPair(certPath, keyPath)
	}
	return rootKeys, err
}

// newHostCertificate returns a certificate for the given hostname.
func newHostCertificate(hostname string) (*tls.Certificate, error) {
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}

	cert, err := newCertificate()
	if err != nil {
		return nil, err
	}
	if ip := net.ParseIP(hostname); ip != nil {
		cert.IPAddresses = append(cert.IPAddresses, ip)
	} else {
		cert.DNSNames = append(cert.DNSNames, hostname)
	}

	certBytes, err := x509.CreateCertificate(rand.Reader, cert, caCert, &priv.PublicKey, caKey)
	if err != nil {
		return nil, err
	}

	return &tls.Certificate{
		Certificate: [][]byte{certBytes},
		PrivateKey:  priv,
	}, nil
}

// certificate returns a matching certificate, either from a cache or by generating a new one.
func certificate(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
	var hostname string
	if len(info.ServerName) > 0 {
		hostname = info.ServerName
	} else {
		// If the SNI hostname is empty (e.g., for IP addresses), create a certificate for the last tunneled hostname.
		hostname = lastTunneledHost
	}

	if cert, ok := certMap[hostname]; ok {
		return cert, nil
	}

	cert, err := newHostCertificate(hostname)
	if err != nil {
		return nil, err
	}
	certMap[hostname] = cert

	return cert, nil
}

const pacFmt = `
function FindProxyForURL(url, host) {
        // Bypass list. See https://findproxyforurl.com/pac-functions/ for functions.
        if (shExpMatch(host, "*.google.com")) return "DIRECT";
        if (shExpMatch(host, "*.gstatic.com")) return "DIRECT";
        if (shExpMatch(host, "*.googleusercontent.com")) return "DIRECT";
        if (shExpMatch(host, "*.googleapis.com")) return "DIRECT";
        if (shExpMatch(host, "*.microsoft.com")) return "DIRECT";
        if (dnsDomainLevels(host) < 1) return "DIRECT";

        // Return a response from TrickUri.
        return "PROXY localhost:%d";
}`

// servePAC serves a proxy auto configuration script that directs the client to
// go direct for responses that should not be generated from this tool. This helps
// ensure that Chrome/Windows/etc are not unduly affected by our HTTP(S) interceptions.
func servePAC(w http.ResponseWriter, _ *http.Request) {
	w.Header().Set("Content-Type", "application/x-ns-proxy-autoconfig; charset=utf-8")
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, pacFmt, *port)
}

func serveEcho(w http.ResponseWriter, r *http.Request) {
	if err := r.Write(w); err != nil {
		log.Println(err)
	}
}

func serveRootCert(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, *directory+"/root.cer")
}

// serveHttpAuth returns whether the request contains HTTP Auth headers.
// When it does, it also writes a 401 Unauthorized response.
func serveHttpAuth(w http.ResponseWriter, r *http.Request) bool {
	if _, _, ok := r.BasicAuth(); ok {
		return true
	}
	w.Header().Set("WWW-Authenticate", "Basic realm=test")
	w.WriteHeader(401)
	w.Write([]byte("Unauthorized"))
	return false
}

func tunnelHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodConnect {
		// This is a request that doesn't require tunneling, use the default handler.
		httpHandler(w, r)
		return
	}

	// All https requests will be forwarded to the HTTPS proxy running on the set HTTPS port.
	httpsHost := "localhost:" + strconv.Itoa(*httpsPort)
	dst, err := net.DialTimeout("tcp", httpsHost, 3*time.Second)
	if err != nil {
		http.Error(w, "forwarding to "+httpsHost+" failed", http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusOK)
	hj, ok := w.(http.Hijacker)
	if !ok {
		http.Error(w, "hijacking is not supported", http.StatusInternalServerError)
		return
	}
	hijackedConn, _, err := hj.Hijack()
	if err != nil {
		http.Error(w, "error hijacking connection", http.StatusInternalServerError)
		return
	}

	// Save for certificate generation if SNI is not available.
	lastTunneledHost = r.URL.Hostname()

	go forward(dst, hijackedConn)
	go forward(hijackedConn, dst)
}

func forward(dst io.WriteCloser, src io.ReadCloser) {
	defer dst.Close()
	defer src.Close()
	io.Copy(dst, src)
}

func httpHandler(w http.ResponseWriter, r *http.Request) {
	switch r.URL.EscapedPath() {
	case "/proxy.pac":
		servePAC(w, r)
		return
	case "/echo":
		serveEcho(w, r)
		return
	case "/root.cer":
		serveRootCert(w, r)
		return
	case "/web-feature-tests/http-auth/":
		if !serveHttpAuth(w, r) {
			return
		}
	}

	if strings.HasPrefix(r.URL.EscapedPath(), "/web-feature-tests") {
		tc := http.FileServer(http.Dir("."))
		tc.ServeHTTP(w, r)
		return
	}

	// An index explaining how to use the different testcases.
	http.ServeFile(w, r, *testIndex)
}

const welcomeFmt = `

----Welcome to Trickuri!----

This tool facilitates testing of applications that displays URLs to users.
Trickuri is ready to receive requests.

1.) Download the root certificate at http://localhost:%d/root.cer and import it
into your browser/OS certificate store. See README.md for instructions on how to
import a root certificate.

2.) Set the proxy server of the application under test to
http://localhost:%[1]d/proxy.pac or localhost:%[1]d. Using the PAC file will
pass through requests to google.com and microsoft.com for common Chrome/Windows
requests. See https://www.chromium.org/developers/design-documents/network-settings
for instructions on configuring Chrome's proxy server, if you are testing Chrome.

3.) Visit https://example.com/ (or any other URL) to see a list of test cases.

`

func main() {
	flag.Parse()

	if err := os.MkdirAll(*directory, os.ModePerm); err != nil {
		log.Fatal(err)
	}

	rootCert, err := rootCertificate(*directory)
	if err != nil {
		log.Fatal(err)
	}
	caCert, err = x509.ParseCertificate(rootCert.Certificate[0])
	if err != nil {
		log.Fatal(err)
	}
	caKey = rootCert.PrivateKey

	fmt.Printf(welcomeFmt, *port)

	httpsServer := http.Server{
		Addr: "localhost:" + strconv.Itoa(*httpsPort),
		TLSConfig: &tls.Config{
			CipherSuites: []uint16{
				tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
			},
			MinVersion:               tls.VersionTLS12,
			PreferServerCipherSuites: true,
			GetCertificate:           certificate,
		},
		Handler: http.HandlerFunc(httpHandler),
	}
	go func() {
		if err := httpsServer.ListenAndServeTLS("", ""); err != nil {
			log.Fatal(err)
		}
	}()

	httpServer := http.Server{
		Addr:    "localhost:" + strconv.Itoa(*port),
		Handler: http.HandlerFunc(tunnelHandler),
	}
	if err := httpServer.ListenAndServe(); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Fixed mispelling<commit_after>// Copyright 2018 The Trickuri 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
//
//     https://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.

// Trickuri generates test cases for URL spoofing vulnerabilities.
package main

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/tls"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"flag"
	"fmt"
	"io"
	"log"
	"math/big"
	"net"
	"net/http"
	"os"
	"path"
	"runtime"
	"strconv"
	"strings"
	"time"
)

var (
	port      = flag.Int("p", 1270, "port on which to listen")
	httpsPort = flag.Int("h", 8443, "port on which the HTTPS proxy will listen")
	directory = flag.String("d", userHomeDir()+"/.config/trickuri", "default directory in which to save certificates")
	testIndex = flag.String("i", "index.html", "default file location containing test index")
)

var (
	caKey   crypto.PrivateKey
	caCert  *x509.Certificate
	certMap = make(map[string]*tls.Certificate)

	// TODO: fix the data race around this variable, either with a lock on this
	// variable, or (possibly better) by using a channel.
	lastTunneledHost string
)

// userHomeDir returns a suitable directory for the default certificate storage path.
func userHomeDir() string {
	if runtime.GOOS == "windows" {
		home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
		if home == "" {
			home = os.Getenv("USERPROFILE")
		}
		return home
	}
	return os.Getenv("HOME")
}

// newCertificate returns an initialized certificate with usable values.
func newCertificate() (*x509.Certificate, error) {
	maxSerial := new(big.Int).Lsh(big.NewInt(1), 128)
	serial, err := rand.Int(rand.Reader, maxSerial)
	if err != nil {
		return nil, err
	}

	return &x509.Certificate{
		SerialNumber: serial,
		Subject: pkix.Name{
			Organization: []string{"TrickUri Interception Certificate"},
		},
		NotBefore:             time.Now().AddDate(0, 0, -7), // mitigate clock-skew
		NotAfter:              time.Now().AddDate(1, 0, 7),
		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		BasicConstraintsValid: true,
	}, nil
}

// newRootCertificate returns a root certificate and its key.
func newRootCertificate() ([]byte, *rsa.PrivateKey, error) {
	private, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, nil, err
	}

	cert, err := newCertificate()
	if err != nil {
		return nil, nil, err
	}
	cert.IsCA = true
	cert.MaxPathLen = 0
	cert.MaxPathLenZero = true
	cert.Subject = pkix.Name{Organization: []string{"TrickUri Root"}}
	hash := sha256.Sum256(private.PublicKey.N.Bytes())
	cert.SubjectKeyId = hash[:]
	cert.KeyUsage |= x509.KeyUsageCertSign

	certBytes, err := x509.CreateCertificate(rand.Reader, cert, cert, &private.PublicKey, private)
	if err != nil {
		return nil, nil, err
	}

	return certBytes, private, nil
}

// writeCertificate writes the provided certificate and key to files in the specified paths.
func writeCertificate(cert []byte, key *rsa.PrivateKey, certPath, keyPath string) error {
	certFile, err := os.Create(certPath)
	if err != nil {
		return err
	}
	if err := pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: cert}); err != nil {
		return err
	}
	if err := certFile.Close(); err != nil {
		return err
	}

	keyFile, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
	if err != nil {
		return err
	}
	if err := pem.Encode(keyFile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}); err != nil {
		return err
	}
	if err := keyFile.Close(); err != nil {
		return err
	}

	return nil
}

// rootCertificate returns a root certificate, either loaded from the given
// directory, or created and saved.
func rootCertificate(directory string) (tls.Certificate, error) {
	certPath := path.Join(directory, "root.cer")
	keyPath := path.Join(directory, "root.pem")

	rootKeys, err := tls.LoadX509KeyPair(certPath, keyPath)
	if err != nil {
		log.Println("Failed to load root certificate. Recreating root certificate.")
		rootCert, rootKey, err := newRootCertificate()
		if err != nil {
			return tls.Certificate{}, err
		}
		if err := writeCertificate(rootCert, rootKey, certPath, keyPath); err != nil {
			return tls.Certificate{}, err
		}
		return tls.LoadX509KeyPair(certPath, keyPath)
	}
	return rootKeys, err
}

// newHostCertificate returns a certificate for the given hostname.
func newHostCertificate(hostname string) (*tls.Certificate, error) {
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}

	cert, err := newCertificate()
	if err != nil {
		return nil, err
	}
	if ip := net.ParseIP(hostname); ip != nil {
		cert.IPAddresses = append(cert.IPAddresses, ip)
	} else {
		cert.DNSNames = append(cert.DNSNames, hostname)
	}

	certBytes, err := x509.CreateCertificate(rand.Reader, cert, caCert, &priv.PublicKey, caKey)
	if err != nil {
		return nil, err
	}

	return &tls.Certificate{
		Certificate: [][]byte{certBytes},
		PrivateKey:  priv,
	}, nil
}

// certificate returns a matching certificate, either from a cache or by generating a new one.
func certificate(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
	var hostname string
	if len(info.ServerName) > 0 {
		hostname = info.ServerName
	} else {
		// If the SNI hostname is empty (e.g., for IP addresses), create a certificate for the last tunneled hostname.
		hostname = lastTunneledHost
	}

	if cert, ok := certMap[hostname]; ok {
		return cert, nil
	}

	cert, err := newHostCertificate(hostname)
	if err != nil {
		return nil, err
	}
	certMap[hostname] = cert

	return cert, nil
}

const pacFmt = `
function FindProxyForURL(url, host) {
        // Bypass list. See https://findproxyforurl.com/pac-functions/ for functions.
        if (shExpMatch(host, "*.google.com")) return "DIRECT";
        if (shExpMatch(host, "*.gstatic.com")) return "DIRECT";
        if (shExpMatch(host, "*.googleusercontent.com")) return "DIRECT";
        if (shExpMatch(host, "*.googleapis.com")) return "DIRECT";
        if (shExpMatch(host, "*.microsoft.com")) return "DIRECT";
        if (dnsDomainLevels(host) < 1) return "DIRECT";

        // Return a response from TrickUri.
        return "PROXY localhost:%d";
}`

// servePAC serves a proxy auto configuration script that directs the client to
// go direct for responses that should not be generated from this tool. This helps
// ensure that Chrome/Windows/etc are not unduly affected by our HTTP(S) interceptions.
func servePAC(w http.ResponseWriter, _ *http.Request) {
	w.Header().Set("Content-Type", "application/x-ns-proxy-autoconfig; charset=utf-8")
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, pacFmt, *port)
}

func serveEcho(w http.ResponseWriter, r *http.Request) {
	if err := r.Write(w); err != nil {
		log.Println(err)
	}
}

func serveRootCert(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, *directory+"/root.cer")
}

// serveHttpAuth returns whether the request contains HTTP Auth headers.
// When it does, it also writes a 401 Unauthorized response.
func serveHttpAuth(w http.ResponseWriter, r *http.Request) bool {
	if _, _, ok := r.BasicAuth(); ok {
		return true
	}
	w.Header().Set("WWW-Authenticate", "Basic realm=test")
	w.WriteHeader(401)
	w.Write([]byte("Unauthorized"))
	return false
}

func tunnelHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodConnect {
		// This is a request that doesn't require tunneling, use the default handler.
		httpHandler(w, r)
		return
	}

	// All https requests will be forwarded to the HTTPS proxy running on the set HTTPS port.
	httpsHost := "localhost:" + strconv.Itoa(*httpsPort)
	dst, err := net.DialTimeout("tcp", httpsHost, 3*time.Second)
	if err != nil {
		http.Error(w, "forwarding to "+httpsHost+" failed", http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusOK)
	hj, ok := w.(http.Hijacker)
	if !ok {
		http.Error(w, "hijacking is not supported", http.StatusInternalServerError)
		return
	}
	hijackedConn, _, err := hj.Hijack()
	if err != nil {
		http.Error(w, "error hijacking connection", http.StatusInternalServerError)
		return
	}

	// Save for certificate generation if SNI is not available.
	lastTunneledHost = r.URL.Hostname()

	go forward(dst, hijackedConn)
	go forward(hijackedConn, dst)
}

func forward(dst io.WriteCloser, src io.ReadCloser) {
	defer dst.Close()
	defer src.Close()
	io.Copy(dst, src)
}

func httpHandler(w http.ResponseWriter, r *http.Request) {
	switch r.URL.EscapedPath() {
	case "/proxy.pac":
		servePAC(w, r)
		return
	case "/echo":
		serveEcho(w, r)
		return
	case "/root.cer":
		serveRootCert(w, r)
		return
	case "/web-feature-tests/http-auth/":
		if !serveHttpAuth(w, r) {
			return
		}
	}

	if strings.HasPrefix(r.URL.EscapedPath(), "/web-feature-tests") {
		tc := http.FileServer(http.Dir("."))
		tc.ServeHTTP(w, r)
		return
	}

	// An index explaining how to use the different testcases.
	http.ServeFile(w, r, *testIndex)
}

const welcomeFmt = `

----Welcome to Trickuri!----

This tool facilitates testing of applications that displays URLs to users.
Trickuri is ready to receive requests.

1.) Download the root certificate at http://localhost:%d/root.cer and import it
into your browser/OS certificate store. See README.md for instructions on how to
import a root certificate.

2.) Set the proxy server of the application under test to
http://localhost:%[1]d/proxy.pac or localhost:%[1]d. Using the PAC file will
pass through requests to google.com and microsoft.com for common Chrome/Windows
requests. See https://www.chromium.org/developers/design-documents/network-settings
for instructions on configuring Chrome's proxy server, if you are testing Chrome.

3.) Visit https://example.com/ (or any other URL) to see a list of test cases.

`

func main() {
	flag.Parse()

	if err := os.MkdirAll(*directory, os.ModePerm); err != nil {
		log.Fatal(err)
	}

	rootCert, err := rootCertificate(*directory)
	if err != nil {
		log.Fatal(err)
	}
	caCert, err = x509.ParseCertificate(rootCert.Certificate[0])
	if err != nil {
		log.Fatal(err)
	}
	caKey = rootCert.PrivateKey

	fmt.Printf(welcomeFmt, *port)

	httpsServer := http.Server{
		Addr: "localhost:" + strconv.Itoa(*httpsPort),
		TLSConfig: &tls.Config{
			CipherSuites: []uint16{
				tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
			},
			MinVersion:               tls.VersionTLS12,
			PreferServerCipherSuites: true,
			GetCertificate:           certificate,
		},
		Handler: http.HandlerFunc(httpHandler),
	}
	go func() {
		if err := httpsServer.ListenAndServeTLS("", ""); err != nil {
			log.Fatal(err)
		}
	}()

	httpServer := http.Server{
		Addr:    "localhost:" + strconv.Itoa(*port),
		Handler: http.HandlerFunc(tunnelHandler),
	}
	if err := httpServer.ListenAndServe(); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All Rights Reserved.
//
// 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 info

import (
	"fmt"
	"reflect"
	"sort"
	"time"
)

type CpuSpecMask struct {
	Data []uint64 `json:"data,omitempty"`
}

type CpuSpec struct {
	Limit    uint64      `json:"limit"`
	MaxLimit uint64      `json:"max_limit"`
	Mask     CpuSpecMask `json:"mask,omitempty"`
}

type MemorySpec struct {
	// The amount of memory requested. Default is unlimited (-1).
	// Units: bytes.
	Limit uint64 `json:"limit,omitempty"`

	// The amount of guaranteed memory.  Default is 0.
	// Units: bytes.
	Reservation uint64 `json:"reservation,omitempty"`

	// The amount of swap space requested. Default is unlimited (-1).
	// Units: bytes.
	SwapLimit uint64 `json:"swap_limit,omitempty"`
}

type ContainerSpec struct {
	Cpu    *CpuSpec    `json:"cpu,omitempty"`
	Memory *MemorySpec `json:"memory,omitempty"`
}

// Container reference contains enough information to uniquely identify a container
type ContainerReference struct {
	// The absolute name of the container.
	Name string `json:"name"`

	Aliases []string `json:"aliases,omitempty"`
}

// ContainerInfoQuery is used when users check a container info from the REST api.
// It specifies how much data users want to get about a container
type ContainerInfoRequest struct {
	// Max number of stats to return.
	NumStats int `json:"num_stats,omitempty"`
	// Max number of samples to return.
	NumSamples int `json:"num_samples,omitempty"`

	// Different percentiles of CPU usage within a period. The values must be within [0, 100]
	CpuUsagePercentiles []int `json:"cpu_usage_percentiles,omitempty"`
	// Different percentiles of memory usage within a period. The values must be within [0, 100]
	MemoryUsagePercentages []int `json:"memory_usage_percentiles,omitempty"`
}

func (self *ContainerInfoRequest) FillDefaults() *ContainerInfoRequest {
	ret := self
	if ret == nil {
		ret = new(ContainerInfoRequest)
	}
	if ret.NumStats <= 0 {
		ret.NumStats = 1024
	}
	if ret.NumSamples <= 0 {
		ret.NumSamples = 1024
	}
	if len(ret.CpuUsagePercentiles) == 0 {
		ret.CpuUsagePercentiles = []int{50, 80, 90, 99}
	}
	if len(ret.MemoryUsagePercentages) == 0 {
		ret.MemoryUsagePercentages = []int{50, 80, 90, 99}
	}
	return ret
}

type ContainerInfo struct {
	ContainerReference

	// The direct subcontainers of the current container.
	Subcontainers []ContainerReference `json:"subcontainers,omitempty"`

	// The isolation used in the container.
	Spec *ContainerSpec `json:"spec,omitempty"`

	// Historical statistics gathered from the container.
	Stats []*ContainerStats `json:"stats,omitempty"`

	// Randomly sampled container states.
	Samples []*ContainerStatsSample `json:"samples,omitempty"`

	StatsPercentiles *ContainerStatsPercentiles `json:"stats_summary,omitempty"`
}

func (self *ContainerInfo) StatsAfter(ref time.Time) []*ContainerStats {
	n := len(self.Stats) + 1
	for i, s := range self.Stats {
		if s.Timestamp.After(ref) {
			n = i
			break
		}
	}
	if n > len(self.Stats) {
		return nil
	}
	return self.Stats[n:]
}

func (self *ContainerInfo) StatsStartTime() time.Time {
	var ret time.Time
	for _, s := range self.Stats {
		if s.Timestamp.Before(ret) || ret.IsZero() {
			ret = s.Timestamp
		}
	}
	return ret
}

func (self *ContainerInfo) StatsEndTime() time.Time {
	var ret time.Time
	for i := len(self.Stats) - 1; i >= 0; i-- {
		s := self.Stats[i]
		if s.Timestamp.After(ret) {
			ret = s.Timestamp
		}
	}
	return ret
}

// All CPU usage metrics are cumulative from the creation of the container
type CpuStats struct {
	Usage struct {
		// Total CPU usage.
		// Units: nanoseconds
		Total uint64 `json:"total"`

		// Per CPU/core usage of the container.
		// Unit: nanoseconds.
		PerCpu []uint64 `json:"per_cpu_usage,omitempty"`

		// Time spent in user space.
		// Unit: nanoseconds
		User uint64 `json:"user"`

		// Time spent in kernel space.
		// Unit: nanoseconds
		System uint64 `json:"system"`
	} `json:"usage"`
	Load int32 `json:"load"`
}

type MemoryStats struct {
	// Memory limit, equivalent to "limit" in MemorySpec.
	// Units: Bytes.
	Limit uint64 `json:"limit,omitempty"`

	// Usage statistics.

	// Current memory usage, this includes all memory regardless of when it was
	// accessed.
	// Units: Bytes.
	Usage uint64 `json:"usage,omitempty"`

	// The amount of working set memory, this includes recently accessed memory,
	// dirty memory, and kernel memory. Working set is <= "usage".
	// Units: Bytes.
	WorkingSet uint64 `json:"working_set,omitempty"`

	ContainerData    MemoryStatsMemoryData `json:"container_data,omitempty"`
	HierarchicalData MemoryStatsMemoryData `json:"hierarchical_data,omitempty"`
}

type MemoryStatsMemoryData struct {
	Pgfault    uint64 `json:"pgfault,omitempty"`
	Pgmajfault uint64 `json:"pgmajfault,omitempty"`
}

type ContainerStats struct {
	// The time of this stat point.
	Timestamp time.Time    `json:"timestamp"`
	Cpu       *CpuStats    `json:"cpu,omitempty"`
	Memory    *MemoryStats `json:"memory,omitempty"`
}

// Makes a deep copy of the ContainerStats and returns a pointer to the new
// copy. Copy() will allocate a new ContainerStats object if dst is nil.
func (self *ContainerStats) Copy(dst *ContainerStats) *ContainerStats {
	if dst == nil {
		dst = new(ContainerStats)
	}
	dst.Timestamp = self.Timestamp
	if self.Cpu != nil {
		if dst.Cpu == nil {
			dst.Cpu = new(CpuStats)
		}
		// To make a deep copy of a slice, we need to copy every value
		// in the slice. To make less memory allocation, we would like
		// to reuse the slice in dst if possible.
		percpu := dst.Cpu.Usage.PerCpu
		if len(percpu) != len(self.Cpu.Usage.PerCpu) {
			percpu = make([]uint64, len(self.Cpu.Usage.PerCpu))
		}
		dst.Cpu.Usage = self.Cpu.Usage
		dst.Cpu.Load = self.Cpu.Load
		copy(percpu, self.Cpu.Usage.PerCpu)
		dst.Cpu.Usage.PerCpu = percpu
	} else {
		dst.Cpu = nil
	}
	if self.Memory != nil {
		if dst.Memory == nil {
			dst.Memory = new(MemoryStats)
		}
		*dst.Memory = *self.Memory
	} else {
		dst.Memory = nil
	}
	return dst
}

type ContainerStatsSample struct {
	// Timetamp of the end of the sample period
	Timestamp time.Time `json:"timestamp"`
	// Duration of the sample period
	Duration time.Duration `json:"duration"`
	Cpu      struct {
		// number of nanoseconds of CPU time used by the container
		Usage uint64 `json:"usage"`

		// Per-core usage of the container. (unit: nanoseconds)
		PerCpuUsage []uint64 `json:"per_cpu_usage,omitempty"`
	} `json:"cpu"`
	Memory struct {
		// Units: Bytes.
		Usage uint64 `json:"usage"`
	} `json:"memory"`
}

func timeEq(t1, t2 time.Time, tolerance time.Duration) bool {
	// t1 should not be later than t2
	if t1.After(t2) {
		t1, t2 = t2, t1
	}
	diff := t2.Sub(t1)
	if diff <= tolerance {
		return true
	}
	return false
}

func durationEq(a, b time.Duration, tolerance time.Duration) bool {
	if a > b {
		a, b = b, a
	}
	diff := a - b
	if diff <= tolerance {
		return true
	}
	return false
}

const (
	// 10ms, i.e. 0.01s
	timePrecision time.Duration = 10 * time.Millisecond
)

// This function is useful because we do not require precise time
// representation.
func (a *ContainerStats) Eq(b *ContainerStats) bool {
	if !timeEq(a.Timestamp, b.Timestamp, timePrecision) {
		return false
	}
	if !reflect.DeepEqual(a.Cpu, b.Cpu) {
		return false
	}
	if !reflect.DeepEqual(a.Memory, b.Memory) {
		return false
	}
	return true
}

// This function is useful because we do not require precise time
// representation.
func (a *ContainerStatsSample) Eq(b *ContainerStatsSample) bool {
	if !timeEq(a.Timestamp, b.Timestamp, timePrecision) {
		return false
	}
	if !durationEq(a.Duration, b.Duration, timePrecision) {
		return false
	}
	if !reflect.DeepEqual(a.Cpu, b.Cpu) {
		return false
	}
	if !reflect.DeepEqual(a.Memory, b.Memory) {
		return false
	}
	return true
}

type Percentile struct {
	Percentage int    `json:"percentage"`
	Value      uint64 `json:"value"`
}

type ContainerStatsPercentiles struct {
	MaxMemoryUsage         uint64       `json:"max_memory_usage,omitempty"`
	MemoryUsagePercentiles []Percentile `json:"memory_usage_percentiles,omitempty"`
	CpuUsagePercentiles    []Percentile `json:"cpu_usage_percentiles,omitempty"`
}

// Each sample needs two stats because the cpu usage in ContainerStats is
// cumulative.
// prev should be an earlier observation than current.
// This method is not thread/goroutine safe.
func NewSample(prev, current *ContainerStats) (*ContainerStatsSample, error) {
	if prev == nil || current == nil {
		return nil, fmt.Errorf("empty stats")
	}
	// Ignore this sample if it is incomplete
	if prev.Cpu == nil || prev.Memory == nil || current.Cpu == nil || current.Memory == nil {
		return nil, fmt.Errorf("incomplete stats")
	}
	// prev must be an early observation
	if !current.Timestamp.After(prev.Timestamp) {
		return nil, fmt.Errorf("wrong stats order")
	}
	// This data is invalid.
	if current.Cpu.Usage.Total < prev.Cpu.Usage.Total {
		return nil, fmt.Errorf("current CPU usage is less than prev CPU usage (cumulative).")
	}

	var percpu []uint64

	if len(current.Cpu.Usage.PerCpu) > 0 {
		curNumCpus := len(current.Cpu.Usage.PerCpu)
		percpu = make([]uint64, curNumCpus)

		for i, currUsage := range current.Cpu.Usage.PerCpu {
			var prevUsage uint64 = 0
			if i < len(prev.Cpu.Usage.PerCpu) {
				prevUsage = prev.Cpu.Usage.PerCpu[i]
			}
			if currUsage < prevUsage {
				return nil, fmt.Errorf("current per-core CPU usage is less than prev per-core CPU usage (cumulative).")
			}
			percpu[i] = currUsage - prevUsage
		}
	}
	sample := new(ContainerStatsSample)
	// Calculate the diff to get the CPU usage within the time interval.
	sample.Cpu.Usage = current.Cpu.Usage.Total - prev.Cpu.Usage.Total
	sample.Cpu.PerCpuUsage = percpu
	// Memory usage is current memory usage
	sample.Memory.Usage = current.Memory.Usage
	sample.Timestamp = current.Timestamp
	sample.Duration = current.Timestamp.Sub(prev.Timestamp)

	return sample, nil
}

/*
func NewSamplesFromStats(stats ...*ContainerStats) ([]*ContainerStatsSample, error) {
	if len(stats) < 2 {
		return nil, nil
	}
	samples := make([]*ContainerStatsSample, 0, len(stats)-1)
	for i, s := range stats[1:] {
		prev := stats[i]
		sample, err := NewSample(prev, s)
		if err != nil {
			return nil, fmt.Errorf("Unable to generate sample from %+v and %+v: %v",
				prev, s, err)
		}
		samples = append(samples, sample)
	}
	return samples, nil
}
*/

type uint64Slice []uint64

func (self uint64Slice) Len() int {
	return len(self)
}

func (self uint64Slice) Less(i, j int) bool {
	return self[i] < self[j]
}

func (self uint64Slice) Swap(i, j int) {
	self[i], self[j] = self[j], self[i]
}

func (self uint64Slice) Percentiles(requestedPercentiles ...int) []Percentile {
	if len(self) == 0 {
		return nil
	}
	ret := make([]Percentile, 0, len(requestedPercentiles))
	sort.Sort(self)
	for _, p := range requestedPercentiles {
		idx := (len(self) * p / 100) - 1
		if idx < 0 {
			idx = 0
		}
		ret = append(
			ret,
			Percentile{
				Percentage: p,
				Value:      self[idx],
			},
		)
	}
	return ret
}

func NewPercentiles(samples []*ContainerStatsSample, cpuPercentages, memoryPercentages []int) *ContainerStatsPercentiles {
	if len(samples) == 0 {
		return nil
	}
	cpuUsages := make([]uint64, 0, len(samples))
	memUsages := make([]uint64, 0, len(samples))

	for _, sample := range samples {
		if sample == nil {
			continue
		}
		cpuUsages = append(cpuUsages, sample.Cpu.Usage)
		memUsages = append(memUsages, sample.Memory.Usage)
	}

	ret := new(ContainerStatsPercentiles)
	ret.CpuUsagePercentiles = uint64Slice(cpuUsages).Percentiles(cpuPercentages...)
	ret.MemoryUsagePercentiles = uint64Slice(memUsages).Percentiles(memoryPercentages...)
	return ret
}
<commit_msg>remove some commented out code<commit_after>// Copyright 2014 Google Inc. All Rights Reserved.
//
// 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 info

import (
	"fmt"
	"reflect"
	"sort"
	"time"
)

type CpuSpecMask struct {
	Data []uint64 `json:"data,omitempty"`
}

type CpuSpec struct {
	Limit    uint64      `json:"limit"`
	MaxLimit uint64      `json:"max_limit"`
	Mask     CpuSpecMask `json:"mask,omitempty"`
}

type MemorySpec struct {
	// The amount of memory requested. Default is unlimited (-1).
	// Units: bytes.
	Limit uint64 `json:"limit,omitempty"`

	// The amount of guaranteed memory.  Default is 0.
	// Units: bytes.
	Reservation uint64 `json:"reservation,omitempty"`

	// The amount of swap space requested. Default is unlimited (-1).
	// Units: bytes.
	SwapLimit uint64 `json:"swap_limit,omitempty"`
}

type ContainerSpec struct {
	Cpu    *CpuSpec    `json:"cpu,omitempty"`
	Memory *MemorySpec `json:"memory,omitempty"`
}

// Container reference contains enough information to uniquely identify a container
type ContainerReference struct {
	// The absolute name of the container.
	Name string `json:"name"`

	Aliases []string `json:"aliases,omitempty"`
}

// ContainerInfoQuery is used when users check a container info from the REST api.
// It specifies how much data users want to get about a container
type ContainerInfoRequest struct {
	// Max number of stats to return.
	NumStats int `json:"num_stats,omitempty"`
	// Max number of samples to return.
	NumSamples int `json:"num_samples,omitempty"`

	// Different percentiles of CPU usage within a period. The values must be within [0, 100]
	CpuUsagePercentiles []int `json:"cpu_usage_percentiles,omitempty"`
	// Different percentiles of memory usage within a period. The values must be within [0, 100]
	MemoryUsagePercentages []int `json:"memory_usage_percentiles,omitempty"`
}

func (self *ContainerInfoRequest) FillDefaults() *ContainerInfoRequest {
	ret := self
	if ret == nil {
		ret = new(ContainerInfoRequest)
	}
	if ret.NumStats <= 0 {
		ret.NumStats = 1024
	}
	if ret.NumSamples <= 0 {
		ret.NumSamples = 1024
	}
	if len(ret.CpuUsagePercentiles) == 0 {
		ret.CpuUsagePercentiles = []int{50, 80, 90, 99}
	}
	if len(ret.MemoryUsagePercentages) == 0 {
		ret.MemoryUsagePercentages = []int{50, 80, 90, 99}
	}
	return ret
}

type ContainerInfo struct {
	ContainerReference

	// The direct subcontainers of the current container.
	Subcontainers []ContainerReference `json:"subcontainers,omitempty"`

	// The isolation used in the container.
	Spec *ContainerSpec `json:"spec,omitempty"`

	// Historical statistics gathered from the container.
	Stats []*ContainerStats `json:"stats,omitempty"`

	// Randomly sampled container states.
	Samples []*ContainerStatsSample `json:"samples,omitempty"`

	StatsPercentiles *ContainerStatsPercentiles `json:"stats_summary,omitempty"`
}

func (self *ContainerInfo) StatsAfter(ref time.Time) []*ContainerStats {
	n := len(self.Stats) + 1
	for i, s := range self.Stats {
		if s.Timestamp.After(ref) {
			n = i
			break
		}
	}
	if n > len(self.Stats) {
		return nil
	}
	return self.Stats[n:]
}

func (self *ContainerInfo) StatsStartTime() time.Time {
	var ret time.Time
	for _, s := range self.Stats {
		if s.Timestamp.Before(ret) || ret.IsZero() {
			ret = s.Timestamp
		}
	}
	return ret
}

func (self *ContainerInfo) StatsEndTime() time.Time {
	var ret time.Time
	for i := len(self.Stats) - 1; i >= 0; i-- {
		s := self.Stats[i]
		if s.Timestamp.After(ret) {
			ret = s.Timestamp
		}
	}
	return ret
}

// All CPU usage metrics are cumulative from the creation of the container
type CpuStats struct {
	Usage struct {
		// Total CPU usage.
		// Units: nanoseconds
		Total uint64 `json:"total"`

		// Per CPU/core usage of the container.
		// Unit: nanoseconds.
		PerCpu []uint64 `json:"per_cpu_usage,omitempty"`

		// Time spent in user space.
		// Unit: nanoseconds
		User uint64 `json:"user"`

		// Time spent in kernel space.
		// Unit: nanoseconds
		System uint64 `json:"system"`
	} `json:"usage"`
	Load int32 `json:"load"`
}

type MemoryStats struct {
	// Memory limit, equivalent to "limit" in MemorySpec.
	// Units: Bytes.
	Limit uint64 `json:"limit,omitempty"`

	// Usage statistics.

	// Current memory usage, this includes all memory regardless of when it was
	// accessed.
	// Units: Bytes.
	Usage uint64 `json:"usage,omitempty"`

	// The amount of working set memory, this includes recently accessed memory,
	// dirty memory, and kernel memory. Working set is <= "usage".
	// Units: Bytes.
	WorkingSet uint64 `json:"working_set,omitempty"`

	ContainerData    MemoryStatsMemoryData `json:"container_data,omitempty"`
	HierarchicalData MemoryStatsMemoryData `json:"hierarchical_data,omitempty"`
}

type MemoryStatsMemoryData struct {
	Pgfault    uint64 `json:"pgfault,omitempty"`
	Pgmajfault uint64 `json:"pgmajfault,omitempty"`
}

type ContainerStats struct {
	// The time of this stat point.
	Timestamp time.Time    `json:"timestamp"`
	Cpu       *CpuStats    `json:"cpu,omitempty"`
	Memory    *MemoryStats `json:"memory,omitempty"`
}

// Makes a deep copy of the ContainerStats and returns a pointer to the new
// copy. Copy() will allocate a new ContainerStats object if dst is nil.
func (self *ContainerStats) Copy(dst *ContainerStats) *ContainerStats {
	if dst == nil {
		dst = new(ContainerStats)
	}
	dst.Timestamp = self.Timestamp
	if self.Cpu != nil {
		if dst.Cpu == nil {
			dst.Cpu = new(CpuStats)
		}
		// To make a deep copy of a slice, we need to copy every value
		// in the slice. To make less memory allocation, we would like
		// to reuse the slice in dst if possible.
		percpu := dst.Cpu.Usage.PerCpu
		if len(percpu) != len(self.Cpu.Usage.PerCpu) {
			percpu = make([]uint64, len(self.Cpu.Usage.PerCpu))
		}
		dst.Cpu.Usage = self.Cpu.Usage
		dst.Cpu.Load = self.Cpu.Load
		copy(percpu, self.Cpu.Usage.PerCpu)
		dst.Cpu.Usage.PerCpu = percpu
	} else {
		dst.Cpu = nil
	}
	if self.Memory != nil {
		if dst.Memory == nil {
			dst.Memory = new(MemoryStats)
		}
		*dst.Memory = *self.Memory
	} else {
		dst.Memory = nil
	}
	return dst
}

type ContainerStatsSample struct {
	// Timetamp of the end of the sample period
	Timestamp time.Time `json:"timestamp"`
	// Duration of the sample period
	Duration time.Duration `json:"duration"`
	Cpu      struct {
		// number of nanoseconds of CPU time used by the container
		Usage uint64 `json:"usage"`

		// Per-core usage of the container. (unit: nanoseconds)
		PerCpuUsage []uint64 `json:"per_cpu_usage,omitempty"`
	} `json:"cpu"`
	Memory struct {
		// Units: Bytes.
		Usage uint64 `json:"usage"`
	} `json:"memory"`
}

func timeEq(t1, t2 time.Time, tolerance time.Duration) bool {
	// t1 should not be later than t2
	if t1.After(t2) {
		t1, t2 = t2, t1
	}
	diff := t2.Sub(t1)
	if diff <= tolerance {
		return true
	}
	return false
}

func durationEq(a, b time.Duration, tolerance time.Duration) bool {
	if a > b {
		a, b = b, a
	}
	diff := a - b
	if diff <= tolerance {
		return true
	}
	return false
}

const (
	// 10ms, i.e. 0.01s
	timePrecision time.Duration = 10 * time.Millisecond
)

// This function is useful because we do not require precise time
// representation.
func (a *ContainerStats) Eq(b *ContainerStats) bool {
	if !timeEq(a.Timestamp, b.Timestamp, timePrecision) {
		return false
	}
	if !reflect.DeepEqual(a.Cpu, b.Cpu) {
		return false
	}
	if !reflect.DeepEqual(a.Memory, b.Memory) {
		return false
	}
	return true
}

// This function is useful because we do not require precise time
// representation.
func (a *ContainerStatsSample) Eq(b *ContainerStatsSample) bool {
	if !timeEq(a.Timestamp, b.Timestamp, timePrecision) {
		return false
	}
	if !durationEq(a.Duration, b.Duration, timePrecision) {
		return false
	}
	if !reflect.DeepEqual(a.Cpu, b.Cpu) {
		return false
	}
	if !reflect.DeepEqual(a.Memory, b.Memory) {
		return false
	}
	return true
}

type Percentile struct {
	Percentage int    `json:"percentage"`
	Value      uint64 `json:"value"`
}

type ContainerStatsPercentiles struct {
	MaxMemoryUsage         uint64       `json:"max_memory_usage,omitempty"`
	MemoryUsagePercentiles []Percentile `json:"memory_usage_percentiles,omitempty"`
	CpuUsagePercentiles    []Percentile `json:"cpu_usage_percentiles,omitempty"`
}

// Each sample needs two stats because the cpu usage in ContainerStats is
// cumulative.
// prev should be an earlier observation than current.
// This method is not thread/goroutine safe.
func NewSample(prev, current *ContainerStats) (*ContainerStatsSample, error) {
	if prev == nil || current == nil {
		return nil, fmt.Errorf("empty stats")
	}
	// Ignore this sample if it is incomplete
	if prev.Cpu == nil || prev.Memory == nil || current.Cpu == nil || current.Memory == nil {
		return nil, fmt.Errorf("incomplete stats")
	}
	// prev must be an early observation
	if !current.Timestamp.After(prev.Timestamp) {
		return nil, fmt.Errorf("wrong stats order")
	}
	// This data is invalid.
	if current.Cpu.Usage.Total < prev.Cpu.Usage.Total {
		return nil, fmt.Errorf("current CPU usage is less than prev CPU usage (cumulative).")
	}

	var percpu []uint64

	if len(current.Cpu.Usage.PerCpu) > 0 {
		curNumCpus := len(current.Cpu.Usage.PerCpu)
		percpu = make([]uint64, curNumCpus)

		for i, currUsage := range current.Cpu.Usage.PerCpu {
			var prevUsage uint64 = 0
			if i < len(prev.Cpu.Usage.PerCpu) {
				prevUsage = prev.Cpu.Usage.PerCpu[i]
			}
			if currUsage < prevUsage {
				return nil, fmt.Errorf("current per-core CPU usage is less than prev per-core CPU usage (cumulative).")
			}
			percpu[i] = currUsage - prevUsage
		}
	}
	sample := new(ContainerStatsSample)
	// Calculate the diff to get the CPU usage within the time interval.
	sample.Cpu.Usage = current.Cpu.Usage.Total - prev.Cpu.Usage.Total
	sample.Cpu.PerCpuUsage = percpu
	// Memory usage is current memory usage
	sample.Memory.Usage = current.Memory.Usage
	sample.Timestamp = current.Timestamp
	sample.Duration = current.Timestamp.Sub(prev.Timestamp)

	return sample, nil
}

type uint64Slice []uint64

func (self uint64Slice) Len() int {
	return len(self)
}

func (self uint64Slice) Less(i, j int) bool {
	return self[i] < self[j]
}

func (self uint64Slice) Swap(i, j int) {
	self[i], self[j] = self[j], self[i]
}

func (self uint64Slice) Percentiles(requestedPercentiles ...int) []Percentile {
	if len(self) == 0 {
		return nil
	}
	ret := make([]Percentile, 0, len(requestedPercentiles))
	sort.Sort(self)
	for _, p := range requestedPercentiles {
		idx := (len(self) * p / 100) - 1
		if idx < 0 {
			idx = 0
		}
		ret = append(
			ret,
			Percentile{
				Percentage: p,
				Value:      self[idx],
			},
		)
	}
	return ret
}

func NewPercentiles(samples []*ContainerStatsSample, cpuPercentages, memoryPercentages []int) *ContainerStatsPercentiles {
	if len(samples) == 0 {
		return nil
	}
	cpuUsages := make([]uint64, 0, len(samples))
	memUsages := make([]uint64, 0, len(samples))

	for _, sample := range samples {
		if sample == nil {
			continue
		}
		cpuUsages = append(cpuUsages, sample.Cpu.Usage)
		memUsages = append(memUsages, sample.Memory.Usage)
	}

	ret := new(ContainerStatsPercentiles)
	ret.CpuUsagePercentiles = uint64Slice(cpuUsages).Percentiles(cpuPercentages...)
	ret.MemoryUsagePercentiles = uint64Slice(memUsages).Percentiles(memoryPercentages...)
	return ret
}
<|endoftext|>


<commit_before>package ethutil

import (
	checker "gopkg.in/check.v1"
)

type BytesSuite struct{}

var _ = checker.Suite(&BytesSuite{})

func (s *BytesSuite) TestByteString(c *checker.C) {
	var data Bytes
	data = []byte{102, 111, 111}
	exp := "foo"
	res := data.String()

	c.Assert(res, checker.Equals, exp)
}

/*
func (s *BytesSuite) TestDeleteFromByteSlice(c *checker.C) {
	data := []byte{1, 2, 3, 4}
	slice := []byte{1, 2, 3, 4}
	exp := []byte{1, 4}
	res := DeleteFromByteSlice(data, slice)
	if bytes.Compare(res, exp) != 0 {
		t.Errorf("Expected % x Got % x", exp, res)
	}
}

*/
func (s *BytesSuite) TestNumberToBytes(c *checker.C) {
	// data1 := int(1)
	// res1 := NumberToBytes(data1, 16)
	// c.Check(res1, checker.Panics)

	var data2 float64 = 3.141592653
	exp2 := []byte{0xe9, 0x38}
	res2 := NumberToBytes(data2, 16)
	c.Assert(res2, checker.DeepEquals, exp2)
}

func (s *BytesSuite) TestBytesToNumber(c *checker.C) {
	datasmall := []byte{0, 1}
	datalarge := []byte{1, 2, 3}
	expsmall := uint64(0)
	explarge := uint64(0)
	// TODO this fails. why?
	ressmall := BytesToNumber(datasmall)
	reslarge := BytesToNumber(datalarge)

	c.Assert(ressmall, checker.DeepEquals, expsmall)
	c.Assert(reslarge, checker.DeepEquals, explarge)

}

func (s *BytesSuite) TestReadVarInt(c *checker.C) {
	data8 := []byte{1, 2, 3, 4, 5, 6, 7, 8}
	data4 := []byte{1, 2, 3, 4}
	data2 := []byte{1, 2}
	data1 := []byte{1}

	exp8 := uint64(72623859790382856)
	exp4 := uint64(16909060)
	exp2 := uint64(258)
	exp1 := uint64(1)

	res8 := ReadVarInt(data8)
	res4 := ReadVarInt(data4)
	res2 := ReadVarInt(data2)
	res1 := ReadVarInt(data1)

	c.Assert(res8, checker.Equals, exp8)
	c.Assert(res4, checker.Equals, exp4)
	c.Assert(res2, checker.Equals, exp2)
	c.Assert(res1, checker.Equals, exp1)
}

func (s *BytesSuite) TestBinaryLength(c *checker.C) {
	data1 := 0
	data2 := 920987656789

	exp1 := 0
	exp2 := 5

	res1 := BinaryLength(data1)
	res2 := BinaryLength(data2)

	c.Assert(res1, checker.Equals, exp1)
	c.Assert(res2, checker.Equals, exp2)
}

func (s *BytesSuite) TestCopyBytes(c *checker.C) {
	data1 := []byte{1, 2, 3, 4}
	exp1 := []byte{1, 2, 3, 4}
	res1 := CopyBytes(data1)
	c.Assert(res1, checker.DeepEquals, exp1)
}

func (s *BytesSuite) TestIsHex(c *checker.C) {
	data1 := "a9e67e"
	exp1 := false
	res1 := IsHex(data1)
	c.Assert(res1, checker.DeepEquals, exp1)

	data2 := "0xa9e67e00"
	exp2 := true
	res2 := IsHex(data2)
	c.Assert(res2, checker.DeepEquals, exp2)

}

func (s *BytesSuite) TestParseDataString(c *checker.C) {
	res1 := ParseData("hello", "world", "0x0106")
	data := "68656c6c6f000000000000000000000000000000000000000000000000000000776f726c640000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000"
	exp1 := Hex2Bytes(data)
	c.Assert(res1, checker.DeepEquals, exp1)
}

func (s *BytesSuite) TestParseDataBytes(c *checker.C) {
	data1 := []byte{232, 212, 165, 16, 0}
	exp1 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 212, 165, 16, 0}

	res1 := ParseData(data1)
	c.Assert(res1, checker.DeepEquals, exp1)

}

func (s *BytesSuite) TestLeftPadBytes(c *checker.C) {
	val1 := []byte{1, 2, 3, 4}
	exp1 := []byte{0, 0, 0, 0, 1, 2, 3, 4}

	res1 := LeftPadBytes(val1, 8)
	res2 := LeftPadBytes(val1, 2)

	c.Assert(res1, checker.DeepEquals, exp1)
	c.Assert(res2, checker.DeepEquals, val1)
}

func (s *BytesSuite) TestFormatData(c *checker.C) {
	data1 := ""
	data2 := "0xa9e67e00"
	data3 := "a9e67e"
	data4 := "\"a9e67e00\""

	// exp1 := []byte{}
	exp2 := []byte{00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0xa9, 0xe6, 0x7e, 00}
	exp3 := []byte{00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00}
	exp4 := []byte{0x61, 0x39, 0x65, 0x36, 0x37, 0x65, 0x30, 0x30, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00}

	res1 := FormatData(data1)
	res2 := FormatData(data2)
	res3 := FormatData(data3)
	res4 := FormatData(data4)

	c.Assert(res1, checker.IsNil)
	c.Assert(res2, checker.DeepEquals, exp2)
	c.Assert(res3, checker.DeepEquals, exp3)
	c.Assert(res4, checker.DeepEquals, exp4)
}

func (s *BytesSuite) TestRightPadBytes(c *checker.C) {
	val := []byte{1, 2, 3, 4}
	exp := []byte{1, 2, 3, 4, 0, 0, 0, 0}

	resstd := RightPadBytes(val, 8)
	resshrt := RightPadBytes(val, 2)

	c.Assert(resstd, checker.DeepEquals, exp)
	c.Assert(resshrt, checker.DeepEquals, val)
}

func (s *BytesSuite) TestLeftPadString(c *checker.C) {
	val := "test"
	exp := "\x30\x30\x30\x30" + val

	resstd := LeftPadString(val, 8)
	resshrt := LeftPadString(val, 2)

	c.Assert(resstd, checker.Equals, exp)
	c.Assert(resshrt, checker.Equals, val)
}

func (s *BytesSuite) TestRightPadString(c *checker.C) {
	val := "test"
	exp := val + "\x30\x30\x30\x30"

	resstd := RightPadString(val, 8)
	resshrt := RightPadString(val, 2)

	c.Assert(resstd, checker.Equals, exp)
	c.Assert(resshrt, checker.Equals, val)
}
<commit_msg>Fix TestBytestoNumber<commit_after>package ethutil

import (
	checker "gopkg.in/check.v1"
)

type BytesSuite struct{}

var _ = checker.Suite(&BytesSuite{})

func (s *BytesSuite) TestByteString(c *checker.C) {
	var data Bytes
	data = []byte{102, 111, 111}
	exp := "foo"
	res := data.String()

	c.Assert(res, checker.Equals, exp)
}

/*
func (s *BytesSuite) TestDeleteFromByteSlice(c *checker.C) {
	data := []byte{1, 2, 3, 4}
	slice := []byte{1, 2, 3, 4}
	exp := []byte{1, 4}
	res := DeleteFromByteSlice(data, slice)
	if bytes.Compare(res, exp) != 0 {
		t.Errorf("Expected % x Got % x", exp, res)
	}
}

*/
func (s *BytesSuite) TestNumberToBytes(c *checker.C) {
	// data1 := int(1)
	// res1 := NumberToBytes(data1, 16)
	// c.Check(res1, checker.Panics)

	var data2 float64 = 3.141592653
	exp2 := []byte{0xe9, 0x38}
	res2 := NumberToBytes(data2, 16)
	c.Assert(res2, checker.DeepEquals, exp2)
}

func (s *BytesSuite) TestBytesToNumber(c *checker.C) {
	datasmall := []byte{0xe9, 0x38, 0xe9, 0x38}
	datalarge := []byte{0xe9, 0x38, 0xe9, 0x38, 0xe9, 0x38, 0xe9, 0x38}

	var expsmall uint64 = 0xe938e938
	var explarge uint64 = 0x0

	ressmall := BytesToNumber(datasmall)
	reslarge := BytesToNumber(datalarge)

	c.Assert(ressmall, checker.Equals, expsmall)
	c.Assert(reslarge, checker.Equals, explarge)

}

func (s *BytesSuite) TestReadVarInt(c *checker.C) {
	data8 := []byte{1, 2, 3, 4, 5, 6, 7, 8}
	data4 := []byte{1, 2, 3, 4}
	data2 := []byte{1, 2}
	data1 := []byte{1}

	exp8 := uint64(72623859790382856)
	exp4 := uint64(16909060)
	exp2 := uint64(258)
	exp1 := uint64(1)

	res8 := ReadVarInt(data8)
	res4 := ReadVarInt(data4)
	res2 := ReadVarInt(data2)
	res1 := ReadVarInt(data1)

	c.Assert(res8, checker.Equals, exp8)
	c.Assert(res4, checker.Equals, exp4)
	c.Assert(res2, checker.Equals, exp2)
	c.Assert(res1, checker.Equals, exp1)
}

func (s *BytesSuite) TestBinaryLength(c *checker.C) {
	data1 := 0
	data2 := 920987656789

	exp1 := 0
	exp2 := 5

	res1 := BinaryLength(data1)
	res2 := BinaryLength(data2)

	c.Assert(res1, checker.Equals, exp1)
	c.Assert(res2, checker.Equals, exp2)
}

func (s *BytesSuite) TestCopyBytes(c *checker.C) {
	data1 := []byte{1, 2, 3, 4}
	exp1 := []byte{1, 2, 3, 4}
	res1 := CopyBytes(data1)
	c.Assert(res1, checker.DeepEquals, exp1)
}

func (s *BytesSuite) TestIsHex(c *checker.C) {
	data1 := "a9e67e"
	exp1 := false
	res1 := IsHex(data1)
	c.Assert(res1, checker.DeepEquals, exp1)

	data2 := "0xa9e67e00"
	exp2 := true
	res2 := IsHex(data2)
	c.Assert(res2, checker.DeepEquals, exp2)

}

func (s *BytesSuite) TestParseDataString(c *checker.C) {
	res1 := ParseData("hello", "world", "0x0106")
	data := "68656c6c6f000000000000000000000000000000000000000000000000000000776f726c640000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000"
	exp1 := Hex2Bytes(data)
	c.Assert(res1, checker.DeepEquals, exp1)
}

func (s *BytesSuite) TestParseDataBytes(c *checker.C) {
	data1 := []byte{232, 212, 165, 16, 0}
	exp1 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 212, 165, 16, 0}

	res1 := ParseData(data1)
	c.Assert(res1, checker.DeepEquals, exp1)

}

func (s *BytesSuite) TestLeftPadBytes(c *checker.C) {
	val1 := []byte{1, 2, 3, 4}
	exp1 := []byte{0, 0, 0, 0, 1, 2, 3, 4}

	res1 := LeftPadBytes(val1, 8)
	res2 := LeftPadBytes(val1, 2)

	c.Assert(res1, checker.DeepEquals, exp1)
	c.Assert(res2, checker.DeepEquals, val1)
}

func (s *BytesSuite) TestFormatData(c *checker.C) {
	data1 := ""
	data2 := "0xa9e67e00"
	data3 := "a9e67e"
	data4 := "\"a9e67e00\""

	// exp1 := []byte{}
	exp2 := []byte{00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0xa9, 0xe6, 0x7e, 00}
	exp3 := []byte{00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00}
	exp4 := []byte{0x61, 0x39, 0x65, 0x36, 0x37, 0x65, 0x30, 0x30, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00}

	res1 := FormatData(data1)
	res2 := FormatData(data2)
	res3 := FormatData(data3)
	res4 := FormatData(data4)

	c.Assert(res1, checker.IsNil)
	c.Assert(res2, checker.DeepEquals, exp2)
	c.Assert(res3, checker.DeepEquals, exp3)
	c.Assert(res4, checker.DeepEquals, exp4)
}

func (s *BytesSuite) TestRightPadBytes(c *checker.C) {
	val := []byte{1, 2, 3, 4}
	exp := []byte{1, 2, 3, 4, 0, 0, 0, 0}

	resstd := RightPadBytes(val, 8)
	resshrt := RightPadBytes(val, 2)

	c.Assert(resstd, checker.DeepEquals, exp)
	c.Assert(resshrt, checker.DeepEquals, val)
}

func (s *BytesSuite) TestLeftPadString(c *checker.C) {
	val := "test"
	exp := "\x30\x30\x30\x30" + val

	resstd := LeftPadString(val, 8)
	resshrt := LeftPadString(val, 2)

	c.Assert(resstd, checker.Equals, exp)
	c.Assert(resshrt, checker.Equals, val)
}

func (s *BytesSuite) TestRightPadString(c *checker.C) {
	val := "test"
	exp := val + "\x30\x30\x30\x30"

	resstd := RightPadString(val, 8)
	resshrt := RightPadString(val, 2)

	c.Assert(resstd, checker.Equals, exp)
	c.Assert(resshrt, checker.Equals, val)
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2016 Huawei Technologies Co., Ltd. All Rights Reserved.

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 client

import (
	"fmt"
	"github.com/opensds/opensds/client"
	"github.com/opensds/opensds/pkg/model"
	"os"
	"strconv"
)

const (
	// OpenSDSEndPoint environment variable name
	OpenSDSEndPoint = "OPENSDS_ENDPOINT"

	// OpenSDSAuthStrategy environment variable name
	OpenSDSAuthStrategy = "OPENSDS_AUTH_STRATEGY"
)

const (
	KVolumeName       = "kubernetes.io/volumeName"
	KVolumeSize       = "kubernetes.io/size"
	KAvailabilityZone = "kubernetes.io/availabilityZone"
	KVolumeId         = "volumeId"
	KFsType           = "kubernetes.io/type"
)

type SdsClient struct {
	client *client.Client
}

type WarpOpensdsClient interface {
	Provision(opts map[string]string) (string, error)
	Delete(volumeId string) error
}

var _ WarpOpensdsClient = &SdsClient{}

func NewSdsClient(endpoint string, authStrategy string) WarpOpensdsClient {
	client := getSdsClient(endpoint, authStrategy)
	return &SdsClient{
		client: client,
	}
}

func (c *SdsClient) Provision(opts map[string]string) (string, error) {
	err := optionCheck([]string{KVolumeName, KVolumeSize}, opts)
	if err != nil {
		return "", err
	}

	size, _ := strconv.ParseInt(opts[KVolumeSize], 10, 0)
	volSpec := &model.VolumeSpec{
		Name: opts[KVolumeName],
		Size: size,
	}

	if zone, exist := opts[KAvailabilityZone]; exist {
		volSpec.AvailabilityZone = zone
	}

	vol, errCreate := c.client.CreateVolume(volSpec)
	if errCreate != nil {
		return "", nil
	}

	return vol.Id, nil
}

func (c *SdsClient) Delete(volumeId string) error {
	return c.client.DeleteVolume(volumeId, &model.VolumeSpec{})
}

// getSdsClient return OpenSDS Client
func getSdsClient(endpoint string, authStrategy string) *client.Client {
	if endpoint == "" {
		// Get endpoint from environment
		endpoint = os.Getenv(OpenSDSEndPoint)
	}

	if endpoint == "" {
		// Using default endpoint
		endpoint = "http://localhost:50040"
	}

	if authStrategy == "" {
		// Get auth strategy from environment
		authStrategy = os.Getenv(OpenSDSAuthStrategy)
	}

	if authStrategy == "" {
		// Using default auth strategy
		authStrategy = "noauth"
	}

	cfg := &client.Config{Endpoint: endpoint}

	switch authStrategy {
	case client.Keystone:
		cfg.AuthOptions = client.LoadKeystoneAuthOptionsFromEnv()
	case client.Noauth:
		cfg.AuthOptions = client.LoadNoAuthOptionsFromEnv()
	default:
		cfg.AuthOptions = client.NewNoauthOptions(constants.DefaultTenantId)
	}

	return client.NewClient(cfg)
}

func optionCheck(optCheckList []string, opts map[string]string) error {
	for _, value := range optCheckList {
		if _, exist := opts[value]; !exist {
			return fmt.Errorf("option %s not specified", value)
		}
	}

	return nil
}
<commit_msg>import opensds/opensds/pkg/utils/constants<commit_after>/*
Copyright (c) 2016 Huawei Technologies Co., Ltd. All Rights Reserved.

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 client

import (
	"fmt"
	"github.com/opensds/opensds/client"
	"github.com/opensds/opensds/pkg/model"
	"github.com/opensds/opensds/pkg/utils/constants"
	"os"
	"strconv"
)

const (
	// OpenSDSEndPoint environment variable name
	OpenSDSEndPoint = "OPENSDS_ENDPOINT"

	// OpenSDSAuthStrategy environment variable name
	OpenSDSAuthStrategy = "OPENSDS_AUTH_STRATEGY"
)

const (
	KVolumeName       = "kubernetes.io/volumeName"
	KVolumeSize       = "kubernetes.io/size"
	KAvailabilityZone = "kubernetes.io/availabilityZone"
	KVolumeId         = "volumeId"
	KFsType           = "kubernetes.io/type"
)

type SdsClient struct {
	client *client.Client
}

type WarpOpensdsClient interface {
	Provision(opts map[string]string) (string, error)
	Delete(volumeId string) error
}

var _ WarpOpensdsClient = &SdsClient{}

func NewSdsClient(endpoint string, authStrategy string) WarpOpensdsClient {
	client := getSdsClient(endpoint, authStrategy)
	return &SdsClient{
		client: client,
	}
}

func (c *SdsClient) Provision(opts map[string]string) (string, error) {
	err := optionCheck([]string{KVolumeName, KVolumeSize}, opts)
	if err != nil {
		return "", err
	}

	size, _ := strconv.ParseInt(opts[KVolumeSize], 10, 0)
	volSpec := &model.VolumeSpec{
		Name: opts[KVolumeName],
		Size: size,
	}

	if zone, exist := opts[KAvailabilityZone]; exist {
		volSpec.AvailabilityZone = zone
	}

	vol, errCreate := c.client.CreateVolume(volSpec)
	if errCreate != nil {
		return "", nil
	}

	return vol.Id, nil
}

func (c *SdsClient) Delete(volumeId string) error {
	return c.client.DeleteVolume(volumeId, &model.VolumeSpec{})
}

// getSdsClient return OpenSDS Client
func getSdsClient(endpoint string, authStrategy string) *client.Client {
	if endpoint == "" {
		// Get endpoint from environment
		endpoint = os.Getenv(OpenSDSEndPoint)
	}

	if endpoint == "" {
		// Using default endpoint
		endpoint = "http://localhost:50040"
	}

	if authStrategy == "" {
		// Get auth strategy from environment
		authStrategy = os.Getenv(OpenSDSAuthStrategy)
	}

	if authStrategy == "" {
		// Using default auth strategy
		authStrategy = "noauth"
	}

	cfg := &client.Config{Endpoint: endpoint}

	switch authStrategy {
	case client.Keystone:
		cfg.AuthOptions = client.LoadKeystoneAuthOptionsFromEnv()
	case client.Noauth:
		cfg.AuthOptions = client.LoadNoAuthOptionsFromEnv()
	default:
		cfg.AuthOptions = client.NewNoauthOptions(constants.DefaultTenantId)
	}

	return client.NewClient(cfg)
}

func optionCheck(optCheckList []string, opts map[string]string) error {
	for _, value := range optCheckList {
		if _, exist := opts[value]; !exist {
			return fmt.Errorf("option %s not specified", value)
		}
	}

	return nil
}
<|endoftext|>


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

// An app that makes a sound as the gopher hits the walls of the screen.
//
// Note: This demo is an early preview of Go 1.5. In order to build this
// program as an Android APK using the gomobile tool.
//
// See http://godoc.org/golang.org/x/mobile/cmd/gomobile to install gomobile.
//
// Get the audio example and use gomobile to build or install it on your device.
//
//   $ go get -d golang.org/x/mobile/example/audio
//   $ gomobile build golang.org/x/mobile/example/audio # will build an APK
//
//   # plug your Android device to your computer or start an Android emulator.
//   # if you have adb installed on your machine, use gomobile install to
//   # build and deploy the APK to an Android target.
//   $ gomobile install golang.org/x/mobile/example/audio
//
// Additionally, you can run the sample on your desktop environment
// by using the go tool.
//
//   $ go install golang.org/x/mobile/example/audio && audio
//
// On Linux, you need to install OpenAL developer library by
// running the command below.
//
//   $ apt-get install libopenal-dev
package main

import (
	"image"
	"log"
	"time"

	_ "image/jpeg"

	"golang.org/x/mobile/app"
	"golang.org/x/mobile/asset"
	"golang.org/x/mobile/event/config"
	"golang.org/x/mobile/event/lifecycle"
	"golang.org/x/mobile/event/paint"
	"golang.org/x/mobile/exp/app/debug"
	"golang.org/x/mobile/exp/audio"
	"golang.org/x/mobile/exp/f32"
	"golang.org/x/mobile/exp/sprite"
	"golang.org/x/mobile/exp/sprite/clock"
	"golang.org/x/mobile/exp/sprite/glsprite"
	"golang.org/x/mobile/gl"
)

const (
	width  = 72
	height = 60
)

var (
	startTime = time.Now()

	eng   = glsprite.Engine()
	scene *sprite.Node

	player *audio.Player
)

func main() {
	app.Main(func(a app.App) {
		var c config.Event
		for e := range a.Events() {
			switch e := app.Filter(e).(type) {
			case lifecycle.Event:
				switch e.Crosses(lifecycle.StageVisible) {
				case lifecycle.CrossOn:
					onStart()
				case lifecycle.CrossOff:
					onStop()
				}
			case config.Event:
				c = e
			case paint.Event:
				onPaint(c)
				a.EndPaint()
			}
		}
	})
}

func onStart() {
	rc, err := asset.Open("boing.wav")
	if err != nil {
		log.Fatal(err)
	}
	player, err = audio.NewPlayer(rc, 0, 0)
	if err != nil {
		log.Fatal(err)
	}
}

func onStop() {
	player.Close()
}

func onPaint(c config.Event) {
	if scene == nil {
		loadScene(c)
	}
	gl.ClearColor(1, 1, 1, 1)
	gl.Clear(gl.COLOR_BUFFER_BIT)
	now := clock.Time(time.Since(startTime) * 60 / time.Second)
	eng.Render(scene, now, c)
	debug.DrawFPS(c)
}

func newNode() *sprite.Node {
	n := &sprite.Node{}
	eng.Register(n)
	scene.AppendChild(n)
	return n
}

func loadScene(c config.Event) {
	gopher := loadGopher()
	scene = &sprite.Node{}
	eng.Register(scene)
	eng.SetTransform(scene, f32.Affine{
		{1, 0, 0},
		{0, 1, 0},
	})

	var x, y float32
	dx, dy := float32(1), float32(1)

	n := newNode()
	n.Arranger = arrangerFunc(func(eng sprite.Engine, n *sprite.Node, t clock.Time) {
		eng.SetSubTex(n, gopher)

		if x < 0 {
			dx = 1
			boing()
		}
		if y < 0 {
			dy = 1
			boing()
		}
		if x+width > float32(c.Width) {
			dx = -1
			boing()
		}
		if y+height > float32(c.Height) {
			dy = -1
			boing()
		}

		x += dx
		y += dy

		eng.SetTransform(n, f32.Affine{
			{width, 0, x},
			{0, height, y},
		})
	})
}

func boing() {
	player.Seek(0)
	player.Play()
}

func loadGopher() sprite.SubTex {
	a, err := asset.Open("gopher.jpeg")
	if err != nil {
		log.Fatal(err)
	}
	defer a.Close()

	img, _, err := image.Decode(a)
	if err != nil {
		log.Fatal(err)
	}
	t, err := eng.LoadTexture(img)
	if err != nil {
		log.Fatal(err)
	}
	return sprite.SubTex{t, image.Rect(0, 0, 360, 300)}
}

type arrangerFunc func(e sprite.Engine, n *sprite.Node, t clock.Time)

func (a arrangerFunc) Arrange(e sprite.Engine, n *sprite.Node, t clock.Time) { a(e, n, t) }
<commit_msg>example/audio: use the latest config.Event in arranger func.<commit_after>// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// An app that makes a sound as the gopher hits the walls of the screen.
//
// Note: This demo is an early preview of Go 1.5. In order to build this
// program as an Android APK using the gomobile tool.
//
// See http://godoc.org/golang.org/x/mobile/cmd/gomobile to install gomobile.
//
// Get the audio example and use gomobile to build or install it on your device.
//
//   $ go get -d golang.org/x/mobile/example/audio
//   $ gomobile build golang.org/x/mobile/example/audio # will build an APK
//
//   # plug your Android device to your computer or start an Android emulator.
//   # if you have adb installed on your machine, use gomobile install to
//   # build and deploy the APK to an Android target.
//   $ gomobile install golang.org/x/mobile/example/audio
//
// Additionally, you can run the sample on your desktop environment
// by using the go tool.
//
//   $ go install golang.org/x/mobile/example/audio && audio
//
// On Linux, you need to install OpenAL developer library by
// running the command below.
//
//   $ apt-get install libopenal-dev
package main

import (
	"image"
	"log"
	"time"

	_ "image/jpeg"

	"golang.org/x/mobile/app"
	"golang.org/x/mobile/asset"
	"golang.org/x/mobile/event/config"
	"golang.org/x/mobile/event/lifecycle"
	"golang.org/x/mobile/event/paint"
	"golang.org/x/mobile/exp/app/debug"
	"golang.org/x/mobile/exp/audio"
	"golang.org/x/mobile/exp/f32"
	"golang.org/x/mobile/exp/sprite"
	"golang.org/x/mobile/exp/sprite/clock"
	"golang.org/x/mobile/exp/sprite/glsprite"
	"golang.org/x/mobile/gl"
)

const (
	width  = 72
	height = 60
)

var (
	startTime = time.Now()

	eng   = glsprite.Engine()
	scene *sprite.Node

	player *audio.Player

	cfg config.Event
)

func main() {
	app.Main(func(a app.App) {
		for e := range a.Events() {
			switch e := app.Filter(e).(type) {
			case lifecycle.Event:
				switch e.Crosses(lifecycle.StageVisible) {
				case lifecycle.CrossOn:
					onStart()
				case lifecycle.CrossOff:
					onStop()
				}
			case config.Event:
				cfg = e
			case paint.Event:
				onPaint()
				a.EndPaint()
			}
		}
	})
}

func onStart() {
	rc, err := asset.Open("boing.wav")
	if err != nil {
		log.Fatal(err)
	}
	player, err = audio.NewPlayer(rc, 0, 0)
	if err != nil {
		log.Fatal(err)
	}
}

func onStop() {
	player.Close()
}

func onPaint() {
	if scene == nil {
		loadScene()
	}
	gl.ClearColor(1, 1, 1, 1)
	gl.Clear(gl.COLOR_BUFFER_BIT)
	now := clock.Time(time.Since(startTime) * 60 / time.Second)
	eng.Render(scene, now, cfg)
	debug.DrawFPS(cfg)
}

func newNode() *sprite.Node {
	n := &sprite.Node{}
	eng.Register(n)
	scene.AppendChild(n)
	return n
}

func loadScene() {
	gopher := loadGopher()
	scene = &sprite.Node{}
	eng.Register(scene)
	eng.SetTransform(scene, f32.Affine{
		{1, 0, 0},
		{0, 1, 0},
	})

	var x, y float32
	dx, dy := float32(1), float32(1)

	n := newNode()
	// TODO: Shouldn't arranger pass the config.Event?
	n.Arranger = arrangerFunc(func(eng sprite.Engine, n *sprite.Node, t clock.Time) {
		eng.SetSubTex(n, gopher)

		if x < 0 {
			dx = 1
			boing()
		}
		if y < 0 {
			dy = 1
			boing()
		}
		if x+width > float32(cfg.Width) {
			dx = -1
			boing()
		}
		if y+height > float32(cfg.Height) {
			dy = -1
			boing()
		}

		x += dx
		y += dy

		eng.SetTransform(n, f32.Affine{
			{width, 0, x},
			{0, height, y},
		})
	})
}

func boing() {
	player.Seek(0)
	player.Play()
}

func loadGopher() sprite.SubTex {
	a, err := asset.Open("gopher.jpeg")
	if err != nil {
		log.Fatal(err)
	}
	defer a.Close()

	img, _, err := image.Decode(a)
	if err != nil {
		log.Fatal(err)
	}
	t, err := eng.LoadTexture(img)
	if err != nil {
		log.Fatal(err)
	}
	return sprite.SubTex{t, image.Rect(0, 0, 360, 300)}
}

type arrangerFunc func(e sprite.Engine, n *sprite.Node, t clock.Time)

func (a arrangerFunc) Arrange(e sprite.Engine, n *sprite.Node, t clock.Time) { a(e, n, t) }
<|endoftext|>


<commit_before>package common

import (
	"bytes"
	"fmt"
	"github.com/hashicorp/go-version"
	"log"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"

	packer "github.com/hashicorp/packer/common"
)

type VBox42Driver struct {
	// This is the path to the "VBoxManage" application.
	VBoxManagePath string
}

func (d *VBox42Driver) CreateSATAController(vmName string, name string, portcount int) error {
	version, err := d.Version()
	if err != nil {
		return err
	}

	portCountArg := "--portcount"

	currentVersion, err := version.NewVersion(version)
	if err != nil {
		return err
	}
	versionUsingPortCount, err := version.NewVersion("4.3")
	if err != nil {
		return err
	}

	if currentVersion.LessThan(versionUsingPortCount) {
		portCountArg = "--sataportcount"
	}

	command := []string{
		"storagectl", vmName,
		"--name", name,
		"--add", "sata",
		portCountArg, strconv.Itoa(portcount),
	}

	return d.VBoxManage(command...)
}

func (d *VBox42Driver) CreateSCSIController(vmName string, name string) error {

	command := []string{
		"storagectl", vmName,
		"--name", name,
		"--add", "scsi",
		"--controller", "LSILogic",
	}

	return d.VBoxManage(command...)
}

func (d *VBox42Driver) Delete(name string) error {
	return packer.Retry(1, 1, 5, func(i uint) (bool, error) {
		if err := d.VBoxManage("unregistervm", name, "--delete"); err != nil {
			if i+1 == 5 {
				return false, err
			}
			return false, nil
		}
		return true, nil
	})
}

func (d *VBox42Driver) Iso() (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.VBoxManagePath, "list", "systemproperties")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	DefaultGuestAdditionsRe := regexp.MustCompile("Default Guest Additions ISO:(.+)")

	for _, line := range strings.Split(stdout.String(), "\n") {
		// Need to trim off CR character when running in windows
		// Trimming whitespaces at this point helps to filter out empty value
		line = strings.TrimRight(line, " \r")

		matches := DefaultGuestAdditionsRe.FindStringSubmatch(line)
		if matches == nil {
			continue
		}

		isoname := strings.Trim(matches[1], " \r\n")
		log.Printf("Found Default Guest Additions ISO: %s", isoname)

		return isoname, nil
	}

	return "", fmt.Errorf("Cannot find \"Default Guest Additions ISO\" in vboxmanage output (or it is empty)")
}

func (d *VBox42Driver) Import(name string, path string, flags []string) error {
	args := []string{
		"import", path,
		"--vsys", "0",
		"--vmname", name,
	}
	args = append(args, flags...)

	return d.VBoxManage(args...)
}

func (d *VBox42Driver) IsRunning(name string) (bool, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.VBoxManagePath, "showvminfo", name, "--machinereadable")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return false, err
	}

	for _, line := range strings.Split(stdout.String(), "\n") {
		// Need to trim off CR character when running in windows
		line = strings.TrimRight(line, "\r")

		if line == `VMState="running"` {
			return true, nil
		}

		// We consider "stopping" to still be running. We wait for it to
		// be completely stopped or some other state.
		if line == `VMState="stopping"` {
			return true, nil
		}

		// We consider "paused" to still be running. We wait for it to
		// be completely stopped or some other state.
		if line == `VMState="paused"` {
			return true, nil
		}
	}

	return false, nil
}

func (d *VBox42Driver) Stop(name string) error {
	if err := d.VBoxManage("controlvm", name, "poweroff"); err != nil {
		return err
	}

	// We sleep here for a little bit to let the session "unlock"
	time.Sleep(2 * time.Second)

	return nil
}

func (d *VBox42Driver) SuppressMessages() error {
	extraData := map[string]string{
		"GUI/RegistrationData": "triesLeft=0",
		"GUI/SuppressMessages": "confirmInputCapture,remindAboutAutoCapture,remindAboutMouseIntegrationOff,remindAboutMouseIntegrationOn,remindAboutWrongColorDepth",
		"GUI/UpdateDate":       fmt.Sprintf("1 d, %d-01-01, stable", time.Now().Year()+1),
		"GUI/UpdateCheckCount": "60",
	}

	for k, v := range extraData {
		if err := d.VBoxManage("setextradata", "global", k, v); err != nil {
			return err
		}
	}

	return nil
}

func (d *VBox42Driver) VBoxManage(args ...string) error {
	var stdout, stderr bytes.Buffer

	log.Printf("Executing VBoxManage: %#v", args)
	cmd := exec.Command(d.VBoxManagePath, args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("VBoxManage error: %s", stderrString)
	}

	if err == nil {
		// Sometimes VBoxManage gives us an error with a zero exit code,
		// so we also regexp match an error string.
		m, _ := regexp.MatchString("VBoxManage([.a-z]+?): error:", stderrString)
		if m {
			err = fmt.Errorf("VBoxManage error: %s", stderrString)
		}
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	return err
}

func (d *VBox42Driver) Verify() error {
	return nil
}

func (d *VBox42Driver) Version() (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.VBoxManagePath, "--version")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	versionOutput := strings.TrimSpace(stdout.String())
	log.Printf("VBoxManage --version output: %s", versionOutput)

	// If the "--version" output contains vboxdrv, then this is indicative
	// of problems with the VirtualBox setup and we shouldn't really continue,
	// whether or not we can read the version.
	if strings.Contains(versionOutput, "vboxdrv") {
		return "", fmt.Errorf("VirtualBox is not properly setup: %s", versionOutput)
	}

	versionRe := regexp.MustCompile("^([.0-9]+)(?:_(?:RC|OSEr)[0-9]+)?")
	matches := versionRe.FindAllStringSubmatch(versionOutput, 1)
	if matches == nil || len(matches[0]) != 2 {
		return "", fmt.Errorf("No version found: %s", versionOutput)
	}

	log.Printf("VirtualBox version: %s", matches[0][1])
	return matches[0][1], nil
}
<commit_msg>rename clashing import<commit_after>package common

import (
	"bytes"
	"fmt"
	versionUtil "github.com/hashicorp/go-version"
	"log"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"

	packer "github.com/hashicorp/packer/common"
)

type VBox42Driver struct {
	// This is the path to the "VBoxManage" application.
	VBoxManagePath string
}

func (d *VBox42Driver) CreateSATAController(vmName string, name string, portcount int) error {
	version, err := d.Version()
	if err != nil {
		return err
	}

	portCountArg := "--portcount"

	currentVersion, err := versionUtil.NewVersion(version)
	if err != nil {
		return err
	}
	firstVersionUsingPortCount, err := versionUtil.NewVersion("4.3")
	if err != nil {
		return err
	}

	if currentVersion.LessThan(firstVersionUsingPortCount) {
		portCountArg = "--sataportcount"
	}

	command := []string{
		"storagectl", vmName,
		"--name", name,
		"--add", "sata",
		portCountArg, strconv.Itoa(portcount),
	}

	return d.VBoxManage(command...)
}

func (d *VBox42Driver) CreateSCSIController(vmName string, name string) error {

	command := []string{
		"storagectl", vmName,
		"--name", name,
		"--add", "scsi",
		"--controller", "LSILogic",
	}

	return d.VBoxManage(command...)
}

func (d *VBox42Driver) Delete(name string) error {
	return packer.Retry(1, 1, 5, func(i uint) (bool, error) {
		if err := d.VBoxManage("unregistervm", name, "--delete"); err != nil {
			if i+1 == 5 {
				return false, err
			}
			return false, nil
		}
		return true, nil
	})
}

func (d *VBox42Driver) Iso() (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.VBoxManagePath, "list", "systemproperties")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	DefaultGuestAdditionsRe := regexp.MustCompile("Default Guest Additions ISO:(.+)")

	for _, line := range strings.Split(stdout.String(), "\n") {
		// Need to trim off CR character when running in windows
		// Trimming whitespaces at this point helps to filter out empty value
		line = strings.TrimRight(line, " \r")

		matches := DefaultGuestAdditionsRe.FindStringSubmatch(line)
		if matches == nil {
			continue
		}

		isoname := strings.Trim(matches[1], " \r\n")
		log.Printf("Found Default Guest Additions ISO: %s", isoname)

		return isoname, nil
	}

	return "", fmt.Errorf("Cannot find \"Default Guest Additions ISO\" in vboxmanage output (or it is empty)")
}

func (d *VBox42Driver) Import(name string, path string, flags []string) error {
	args := []string{
		"import", path,
		"--vsys", "0",
		"--vmname", name,
	}
	args = append(args, flags...)

	return d.VBoxManage(args...)
}

func (d *VBox42Driver) IsRunning(name string) (bool, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.VBoxManagePath, "showvminfo", name, "--machinereadable")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return false, err
	}

	for _, line := range strings.Split(stdout.String(), "\n") {
		// Need to trim off CR character when running in windows
		line = strings.TrimRight(line, "\r")

		if line == `VMState="running"` {
			return true, nil
		}

		// We consider "stopping" to still be running. We wait for it to
		// be completely stopped or some other state.
		if line == `VMState="stopping"` {
			return true, nil
		}

		// We consider "paused" to still be running. We wait for it to
		// be completely stopped or some other state.
		if line == `VMState="paused"` {
			return true, nil
		}
	}

	return false, nil
}

func (d *VBox42Driver) Stop(name string) error {
	if err := d.VBoxManage("controlvm", name, "poweroff"); err != nil {
		return err
	}

	// We sleep here for a little bit to let the session "unlock"
	time.Sleep(2 * time.Second)

	return nil
}

func (d *VBox42Driver) SuppressMessages() error {
	extraData := map[string]string{
		"GUI/RegistrationData": "triesLeft=0",
		"GUI/SuppressMessages": "confirmInputCapture,remindAboutAutoCapture,remindAboutMouseIntegrationOff,remindAboutMouseIntegrationOn,remindAboutWrongColorDepth",
		"GUI/UpdateDate":       fmt.Sprintf("1 d, %d-01-01, stable", time.Now().Year()+1),
		"GUI/UpdateCheckCount": "60",
	}

	for k, v := range extraData {
		if err := d.VBoxManage("setextradata", "global", k, v); err != nil {
			return err
		}
	}

	return nil
}

func (d *VBox42Driver) VBoxManage(args ...string) error {
	var stdout, stderr bytes.Buffer

	log.Printf("Executing VBoxManage: %#v", args)
	cmd := exec.Command(d.VBoxManagePath, args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("VBoxManage error: %s", stderrString)
	}

	if err == nil {
		// Sometimes VBoxManage gives us an error with a zero exit code,
		// so we also regexp match an error string.
		m, _ := regexp.MatchString("VBoxManage([.a-z]+?): error:", stderrString)
		if m {
			err = fmt.Errorf("VBoxManage error: %s", stderrString)
		}
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	return err
}

func (d *VBox42Driver) Verify() error {
	return nil
}

func (d *VBox42Driver) Version() (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.VBoxManagePath, "--version")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	versionOutput := strings.TrimSpace(stdout.String())
	log.Printf("VBoxManage --version output: %s", versionOutput)

	// If the "--version" output contains vboxdrv, then this is indicative
	// of problems with the VirtualBox setup and we shouldn't really continue,
	// whether or not we can read the version.
	if strings.Contains(versionOutput, "vboxdrv") {
		return "", fmt.Errorf("VirtualBox is not properly setup: %s", versionOutput)
	}

	versionRe := regexp.MustCompile("^([.0-9]+)(?:_(?:RC|OSEr)[0-9]+)?")
	matches := versionRe.FindAllStringSubmatch(versionOutput, 1)
	if matches == nil || len(matches[0]) != 2 {
		return "", fmt.Errorf("No version found: %s", versionOutput)
	}

	log.Printf("VirtualBox version: %s", matches[0][1])
	return matches[0][1], nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"

	"github.com/abronan/proton"
	"github.com/coreos/etcd/raft/raftpb"
)

var (
	nodes = make(map[int]*proton.Node)
)

func main() {
	id := proton.GenID("Host1")
	nodes[1] = proton.NewNode(id, "")
	nodes[1].Raft.Campaign(nodes[1].Ctx)
	go nodes[1].Start()

	id = proton.GenID("Host2")
	nodes[2] = proton.NewNode(id, "")
	go nodes[2].Start()

	id = proton.GenID("Host3")
	nodes[3] = proton.NewNode(id, "")
	go nodes[3].Start()
	nodes[2].Raft.ProposeConfChange(nodes[2].Ctx, raftpb.ConfChange{
		ID:      3,
		Type:    raftpb.ConfChangeAddNode,
		NodeID:  3,
		Context: []byte(""),
	})

	// Wait for leader, is there a better way to do this
	for nodes[1].Raft.Status().Lead != 1 {
		time.Sleep(100 * time.Millisecond)
	}

	nodes[1].Raft.Propose(nodes[1].Ctx, []byte("mykey1:myvalue1"))
	nodes[2].Raft.Propose(nodes[2].Ctx, []byte("mykey2:myvalue2"))
	nodes[3].Raft.Propose(nodes[3].Ctx, []byte("mykey3:myvalue3"))

	// Wait for proposed entry to be commited in cluster.
	// Apperently when should add an uniq id to the message and wait until it is
	// commited in the node.
	fmt.Printf("** Sleeping to visualize heartbeat between nodes **\n")
	time.Sleep(2000 * time.Millisecond)

	// Just check that data has been persited
	for i, node := range nodes {
		fmt.Printf("** Node %v **\n", i)
		for k, v := range node.PStore {
			fmt.Printf("%v = %v\n", k, v)
		}
		fmt.Printf("*************\n")
	}
}
<commit_msg>remove local example<commit_after><|endoftext|>


<commit_before>package github

import (
	"fmt"
	"net/url"
	"strings"

	"github.com/google/go-github/github"
	"github.com/hashicorp/vault/helper/policyutil"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
)

func pathLogin(b *backend) *framework.Path {
	return &framework.Path{
		Pattern: "login",
		Fields: map[string]*framework.FieldSchema{
			"token": &framework.FieldSchema{
				Type:        framework.TypeString,
				Description: "GitHub personal API token",
			},
		},

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: b.pathLogin,
		},
	}
}

func (b *backend) pathLogin(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {

	token := data.Get("token").(string)

	var verifyResp *verifyCredentialsResp
	if verifyResponse, resp, err := b.verifyCredentials(req, token); err != nil {
		return nil, err
	} else if resp != nil {
		return resp, nil
	} else {
		verifyResp = verifyResponse
	}

	config, err := b.Config(req.Storage)
	if err != nil {
		return nil, err
	}

	ttl, _, err := b.SanitizeTTLStr(config.TTL.String(), config.MaxTTL.String())
	if err != nil {
		return logical.ErrorResponse(fmt.Sprintf("[ERR]:%s", err)), nil
	}

	return &logical.Response{
		Auth: &logical.Auth{
			InternalData: map[string]interface{}{
				"token": token,
			},
			Policies: verifyResp.Policies,
			Metadata: map[string]string{
				"username": *verifyResp.User.Login,
				"org":      *verifyResp.Org.Login,
			},
			DisplayName: *verifyResp.User.Login,
			LeaseOptions: logical.LeaseOptions{
				TTL:       ttl,
				Renewable: true,
			},
		},
	}, nil
}

func (b *backend) pathLoginRenew(
	req *logical.Request, d *framework.FieldData) (*logical.Response, error) {

	if req.Auth == nil {
		return nil, fmt.Errorf("request auth was nil")
	}

	tokenRaw, ok := req.Auth.InternalData["token"]
	if !ok {
		return nil, fmt.Errorf("token created in previous version of Vault cannot be validated properly at renewal time")
	}
	token := tokenRaw.(string)

	var verifyResp *verifyCredentialsResp
	if verifyResponse, resp, err := b.verifyCredentials(req, token); err != nil {
		return nil, err
	} else if resp != nil {
		return resp, nil
	} else {
		verifyResp = verifyResponse
	}
	if !policyutil.EquivalentPolicies(verifyResp.Policies, req.Auth.Policies) {
		return nil, fmt.Errorf("policies do not match")
	}

	config, err := b.Config(req.Storage)
	if err != nil {
		return nil, err
	}
	return framework.LeaseExtend(config.TTL, config.MaxTTL, b.System())(req, d)
}

func (b *backend) verifyCredentials(req *logical.Request, token string) (*verifyCredentialsResp, *logical.Response, error) {
	config, err := b.Config(req.Storage)
	if err != nil {
		return nil, nil, err
	}
	if config.Org == "" {
		return nil, logical.ErrorResponse(
			"configure the github credential backend first"), nil
	}

	client, err := b.Client(token)
	if err != nil {
		return nil, nil, err
	}

	if config.BaseURL != "" {
		parsedURL, err := url.Parse(config.BaseURL)
		if err != nil {
			return nil, nil, fmt.Errorf("Successfully parsed base_url when set but failing to parse now: %s", err)
		}
		client.BaseURL = parsedURL
	}

	// Get the user
	user, _, err := client.Users.Get("")
	if err != nil {
		return nil, nil, err
	}

	// Verify that the user is part of the organization
	var org *github.Organization

	orgOpt := &github.ListOptions{
		PerPage: 100,
	}

	var allOrgs []github.Organization
	for {
		orgs, resp, err := client.Organizations.List("", orgOpt)
		if err != nil {
			return nil, nil, err
		}
		allOrgs = append(allOrgs, orgs...)
		if resp.NextPage == 0 {
			break
		}
		orgOpt.Page = resp.NextPage
	}

	for _, o := range allOrgs {
		if strings.ToLower(*o.Login) == strings.ToLower(config.Org) {
			org = &o
			break
		}
	}
	if org == nil {
		return nil, logical.ErrorResponse("user is not part of required org"), nil
	}

	// Get the teams that this user is part of to determine the policies
	var teamNames []string

	teamOpt := &github.ListOptions{
		PerPage: 100,
	}

	var allTeams []github.Team
	for {
		teams, resp, err := client.Organizations.ListUserTeams(teamOpt)
		if err != nil {
			return nil, nil, err
		}
		allTeams = append(allTeams, teams...)
		if resp.NextPage == 0 {
			break
		}
		teamOpt.Page = resp.NextPage
	}

	for _, t := range allTeams {
		// We only care about teams that are part of the organization we use
		if *t.Organization.ID != *org.ID {
			continue
		}

		// Append the names so we can get the policies
		teamNames = append(teamNames, *t.Name)
		if *t.Name != *t.Slug {
			teamNames = append(teamNames, *t.Slug)
		}
	}

	policiesList, err := b.Map.Policies(req.Storage, teamNames...)
	if err != nil {
		return nil, nil, err
	}
	return &verifyCredentialsResp{
		User:     user,
		Org:      org,
		Policies: policiesList,
	}, nil, nil
}

type verifyCredentialsResp struct {
	User     *github.User
	Org      *github.Organization
	Policies []string
}
<commit_msg>Fix up breakage from bumping deps<commit_after>package github

import (
	"fmt"
	"net/url"
	"strings"

	"github.com/google/go-github/github"
	"github.com/hashicorp/vault/helper/policyutil"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
)

func pathLogin(b *backend) *framework.Path {
	return &framework.Path{
		Pattern: "login",
		Fields: map[string]*framework.FieldSchema{
			"token": &framework.FieldSchema{
				Type:        framework.TypeString,
				Description: "GitHub personal API token",
			},
		},

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: b.pathLogin,
		},
	}
}

func (b *backend) pathLogin(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {

	token := data.Get("token").(string)

	var verifyResp *verifyCredentialsResp
	if verifyResponse, resp, err := b.verifyCredentials(req, token); err != nil {
		return nil, err
	} else if resp != nil {
		return resp, nil
	} else {
		verifyResp = verifyResponse
	}

	config, err := b.Config(req.Storage)
	if err != nil {
		return nil, err
	}

	ttl, _, err := b.SanitizeTTLStr(config.TTL.String(), config.MaxTTL.String())
	if err != nil {
		return logical.ErrorResponse(fmt.Sprintf("[ERR]:%s", err)), nil
	}

	return &logical.Response{
		Auth: &logical.Auth{
			InternalData: map[string]interface{}{
				"token": token,
			},
			Policies: verifyResp.Policies,
			Metadata: map[string]string{
				"username": *verifyResp.User.Login,
				"org":      *verifyResp.Org.Login,
			},
			DisplayName: *verifyResp.User.Login,
			LeaseOptions: logical.LeaseOptions{
				TTL:       ttl,
				Renewable: true,
			},
		},
	}, nil
}

func (b *backend) pathLoginRenew(
	req *logical.Request, d *framework.FieldData) (*logical.Response, error) {

	if req.Auth == nil {
		return nil, fmt.Errorf("request auth was nil")
	}

	tokenRaw, ok := req.Auth.InternalData["token"]
	if !ok {
		return nil, fmt.Errorf("token created in previous version of Vault cannot be validated properly at renewal time")
	}
	token := tokenRaw.(string)

	var verifyResp *verifyCredentialsResp
	if verifyResponse, resp, err := b.verifyCredentials(req, token); err != nil {
		return nil, err
	} else if resp != nil {
		return resp, nil
	} else {
		verifyResp = verifyResponse
	}
	if !policyutil.EquivalentPolicies(verifyResp.Policies, req.Auth.Policies) {
		return nil, fmt.Errorf("policies do not match")
	}

	config, err := b.Config(req.Storage)
	if err != nil {
		return nil, err
	}
	return framework.LeaseExtend(config.TTL, config.MaxTTL, b.System())(req, d)
}

func (b *backend) verifyCredentials(req *logical.Request, token string) (*verifyCredentialsResp, *logical.Response, error) {
	config, err := b.Config(req.Storage)
	if err != nil {
		return nil, nil, err
	}
	if config.Org == "" {
		return nil, logical.ErrorResponse(
			"configure the github credential backend first"), nil
	}

	client, err := b.Client(token)
	if err != nil {
		return nil, nil, err
	}

	if config.BaseURL != "" {
		parsedURL, err := url.Parse(config.BaseURL)
		if err != nil {
			return nil, nil, fmt.Errorf("Successfully parsed base_url when set but failing to parse now: %s", err)
		}
		client.BaseURL = parsedURL
	}

	// Get the user
	user, _, err := client.Users.Get("")
	if err != nil {
		return nil, nil, err
	}

	// Verify that the user is part of the organization
	var org *github.Organization

	orgOpt := &github.ListOptions{
		PerPage: 100,
	}

	var allOrgs []*github.Organization
	for {
		orgs, resp, err := client.Organizations.List("", orgOpt)
		if err != nil {
			return nil, nil, err
		}
		allOrgs = append(allOrgs, orgs...)
		if resp.NextPage == 0 {
			break
		}
		orgOpt.Page = resp.NextPage
	}

	for _, o := range allOrgs {
		if strings.ToLower(*o.Login) == strings.ToLower(config.Org) {
			org = o
			break
		}
	}
	if org == nil {
		return nil, logical.ErrorResponse("user is not part of required org"), nil
	}

	// Get the teams that this user is part of to determine the policies
	var teamNames []string

	teamOpt := &github.ListOptions{
		PerPage: 100,
	}

	var allTeams []*github.Team
	for {
		teams, resp, err := client.Organizations.ListUserTeams(teamOpt)
		if err != nil {
			return nil, nil, err
		}
		allTeams = append(allTeams, teams...)
		if resp.NextPage == 0 {
			break
		}
		teamOpt.Page = resp.NextPage
	}

	for _, t := range allTeams {
		// We only care about teams that are part of the organization we use
		if *t.Organization.ID != *org.ID {
			continue
		}

		// Append the names so we can get the policies
		teamNames = append(teamNames, *t.Name)
		if *t.Name != *t.Slug {
			teamNames = append(teamNames, *t.Slug)
		}
	}

	policiesList, err := b.Map.Policies(req.Storage, teamNames...)
	if err != nil {
		return nil, nil, err
	}
	return &verifyCredentialsResp{
		User:     user,
		Org:      org,
		Policies: policiesList,
	}, nil, nil
}

type verifyCredentialsResp struct {
	User     *github.User
	Org      *github.Organization
	Policies []string
}
<|endoftext|>


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

package main

import (
	"flag"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/db"
	"github.com/globocom/tsuru/log"
	stdlog "log"
	"log/syslog"
	"time"
)

func jujuCollect(ticker <-chan time.Time) {
	for _ = range ticker {
		data, _ := collect()
		output := parse(data)
		update(output)
	}
}

func main() {
	var (
		configFile string
		dry        bool
	)
	logger, err := syslog.NewLogger(syslog.LOG_INFO, stdlog.LstdFlags)
	if err != nil {
		panic(err)
	}
	log.SetLogger(logger)
	flag.StringVar(&configFile, "config", "/etc/tsuru/tsuru.conf", "tsuru config file")
	flag.BoolVar(&dry, "dry", false, "dry-run: does not start the agent (for testing purposes)")
	flag.Parse()
	err = config.ReadConfigFile(configFile)
	if err != nil {
		log.Panic(err)
	}
	connString, err := config.GetString("database:url")
	if err != nil {
		log.Panic(err)
	}
	dbName, err := config.GetString("database:name")
	if err != nil {
		log.Panic(err)
	}
	db.Session, err = db.Open(connString, dbName)
	if err != nil {
		log.Panic(err)
	}
	defer db.Session.Close()

	if !dry {
		ticker := time.Tick(time.Minute)
		jujuCollect(ticker)
	}
}
<commit_msg>collector: start the queue server with the agent<commit_after>// Copyright 2012 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"github.com/globocom/config"
	"github.com/globocom/tsuru/db"
	"github.com/globocom/tsuru/log"
	stdlog "log"
	"log/syslog"
	"time"
)

func jujuCollect(ticker <-chan time.Time) {
	for _ = range ticker {
		data, _ := collect()
		output := parse(data)
		update(output)
	}
}

func main() {
	var (
		configFile string
		dry        bool
	)
	logger, err := syslog.NewLogger(syslog.LOG_INFO, stdlog.LstdFlags)
	if err != nil {
		panic(err)
	}
	log.SetLogger(logger)
	flag.StringVar(&configFile, "config", "/etc/tsuru/tsuru.conf", "tsuru config file")
	flag.BoolVar(&dry, "dry", false, "dry-run: does not start the agent neither the queue (for testing purposes)")
	flag.Parse()
	err = config.ReadConfigFile(configFile)
	if err != nil {
		log.Panic(err)
	}
	connString, err := config.GetString("database:url")
	if err != nil {
		log.Panic(err)
	}
	dbName, err := config.GetString("database:name")
	if err != nil {
		log.Panic(err)
	}
	db.Session, err = db.Open(connString, dbName)
	if err != nil {
		log.Panic(err)
	}
	defer db.Session.Close()

	if !dry {
		handler := MessageHandler{}
		handler.start()
		defer handler.stop()
		ticker := time.Tick(time.Minute)
		jujuCollect(ticker)
	}
}
<|endoftext|>