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

package netchan

import (
	"fmt"
	"testing"
)

type value struct {
	i int
	s string
}

const count = 10

func exportSend(exp *Exporter, t *testing.T) {
	ch := make(chan value)
	err := exp.Export("exportedSend", ch, Send, new(value))
	if err != nil {
		t.Fatal("exportSend:", err)
	}
	for i := 0; i < count; i++ {
		ch <- value{23 + i, "hello"}
	}
}

func exportReceive(exp *Exporter, t *testing.T) {
	ch := make(chan value)
	err := exp.Export("exportedRecv", ch, Recv, new(value))
	if err != nil {
		t.Fatal("exportReceive:", err)
	}
	for i := 0; i < count; i++ {
		v := <-ch
		fmt.Printf("%v\n", v)
		if v.i != 45+i || v.s != "hello" {
			t.Errorf("export Receive: bad value: expected 4%d, hello; got %+v", 45+i, v)
		}
	}
}

func importReceive(imp *Importer, t *testing.T) {
	ch := make(chan value)
	err := imp.ImportNValues("exportedSend", ch, Recv, new(value), count)
	if err != nil {
		t.Fatal("importReceive:", err)
	}
	for i := 0; i < count; i++ {
		v := <-ch
		fmt.Printf("%v\n", v)
		if v.i != 23+i || v.s != "hello" {
			t.Errorf("importReceive: bad value: expected %d, hello; got %+v", 23+i, v)
		}
	}
}

func importSend(imp *Importer, t *testing.T) {
	ch := make(chan value)
	err := imp.ImportNValues("exportedRecv", ch, Send, new(value), count)
	if err != nil {
		t.Fatal("importSend:", err)
	}
	for i := 0; i < count; i++ {
		ch <- value{45 + i, "hello"}
	}
}

func TestExportSendImportReceive(t *testing.T) {
	exp, err := NewExporter("tcp", ":0")
	if err != nil {
		t.Fatal("new exporter:", err)
	}
	imp, err := NewImporter("tcp", exp.Addr().String())
	if err != nil {
		t.Fatal("new importer:", err)
	}
	go exportSend(exp, t)
	importReceive(imp, t)
}

func TestExportReceiveImportSend(t *testing.T) {
	exp, err := NewExporter("tcp", ":0")
	if err != nil {
		t.Fatal("new exporter:", err)
	}
	imp, err := NewImporter("tcp", exp.Addr().String())
	if err != nil {
		t.Fatal("new importer:", err)
	}
	go importSend(imp, t)
	exportReceive(exp, t)
}
<commit_msg>netchan: be less chatty during gotest<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package netchan

import "testing"

type value struct {
	i int
	s string
}

const count = 10

func exportSend(exp *Exporter, t *testing.T) {
	ch := make(chan value)
	err := exp.Export("exportedSend", ch, Send, new(value))
	if err != nil {
		t.Fatal("exportSend:", err)
	}
	for i := 0; i < count; i++ {
		ch <- value{23 + i, "hello"}
	}
}

func exportReceive(exp *Exporter, t *testing.T) {
	ch := make(chan value)
	err := exp.Export("exportedRecv", ch, Recv, new(value))
	if err != nil {
		t.Fatal("exportReceive:", err)
	}
	for i := 0; i < count; i++ {
		v := <-ch
		if v.i != 45+i || v.s != "hello" {
			t.Errorf("export Receive: bad value: expected 4%d, hello; got %+v", 45+i, v)
		}
	}
}

func importReceive(imp *Importer, t *testing.T) {
	ch := make(chan value)
	err := imp.ImportNValues("exportedSend", ch, Recv, new(value), count)
	if err != nil {
		t.Fatal("importReceive:", err)
	}
	for i := 0; i < count; i++ {
		v := <-ch
		if v.i != 23+i || v.s != "hello" {
			t.Errorf("importReceive: bad value: expected %d, hello; got %+v", 23+i, v)
		}
	}
}

func importSend(imp *Importer, t *testing.T) {
	ch := make(chan value)
	err := imp.ImportNValues("exportedRecv", ch, Send, new(value), count)
	if err != nil {
		t.Fatal("importSend:", err)
	}
	for i := 0; i < count; i++ {
		ch <- value{45 + i, "hello"}
	}
}

func TestExportSendImportReceive(t *testing.T) {
	exp, err := NewExporter("tcp", ":0")
	if err != nil {
		t.Fatal("new exporter:", err)
	}
	imp, err := NewImporter("tcp", exp.Addr().String())
	if err != nil {
		t.Fatal("new importer:", err)
	}
	go exportSend(exp, t)
	importReceive(imp, t)
}

func TestExportReceiveImportSend(t *testing.T) {
	exp, err := NewExporter("tcp", ":0")
	if err != nil {
		t.Fatal("new exporter:", err)
	}
	imp, err := NewImporter("tcp", exp.Addr().String())
	if err != nil {
		t.Fatal("new importer:", err)
	}
	go importSend(imp, t)
	exportReceive(exp, t)
}
<|endoftext|>


<commit_before>package auth

import (
	"crypto/md5"
	"crypto/sha256"
	"fmt"
	"math/rand"
	"net/http"
	"strings"
	"time"

	"github.com/subutai-io/base/agent/log"

	"github.com/subutai-io/gorjun/db"
	"github.com/subutai-io/gorjun/pgp"
)

func Register(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		r.ParseMultipartForm(32 << 20)
		if strings.Split(r.RemoteAddr, ":")[0] == "127.0.0.1" && len(r.MultipartForm.Value["name"]) > 0 && len(r.MultipartForm.Value["key"]) > 0 {
			name := r.MultipartForm.Value["name"][0]
			key := r.MultipartForm.Value["key"][0]

			w.Write([]byte("Name: " + name + "\n"))
			w.Write([]byte("PGP key: " + key + "\n"))

			db.RegisterUser([]byte(name), []byte(key))
			return
		} else if len(r.MultipartForm.Value["key"]) > 0 {
			key := pgp.Verify("Hub", r.MultipartForm.Value["key"][0])
			if len(key) == 0 {
				w.Write([]byte("Signature check failed"))
				w.WriteHeader(http.StatusForbidden)
				return
			}
			fingerprint := pgp.Fingerprint(key)
			if len(fingerprint) == 0 {
				w.Write([]byte("Filed to get key fingerprint"))
				w.WriteHeader(http.StatusBadRequest)
				return
			}
			db.RegisterUser([]byte(fmt.Sprintf("%x", fingerprint)), []byte(key))
			return
		}
	}
	w.WriteHeader(http.StatusUnauthorized)
	w.Write([]byte("Not allowed"))
}

func Token(w http.ResponseWriter, r *http.Request) {
	rand.Seed(time.Now().UnixNano())
	if r.Method == http.MethodGet {
		name := r.URL.Query().Get("user")
		if len(name) != 0 {
			hash := md5.New()
			hash.Write([]byte(fmt.Sprint(time.Now().String(), name, rand.Float64())))
			authID := fmt.Sprintf("%x", hash.Sum(nil))
			db.SaveAuthID(name, authID)
			w.Write([]byte(authID))
		}
	} else if r.Method == http.MethodPost {
		r.ParseMultipartForm(32 << 20)
		if len(r.MultipartForm.Value["user"]) == 0 || len(r.MultipartForm.Value["message"]) == 0 {
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte("Please specify user name and auth message"))
			log.Warn(r.RemoteAddr + " - empty user name or message filed")
			return
		}
		name := r.MultipartForm.Value["user"][0]
		message := r.MultipartForm.Value["message"][0]
		authid := pgp.Verify(name, message)
		if db.CheckAuthID(authid) == name {
			token := fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprint(time.Now().String(), name, rand.Float64()))))
			db.SaveToken(name, fmt.Sprintf("%x", sha256.Sum256([]byte(token))))
			w.Write([]byte(token))
		} else {
			w.WriteHeader(http.StatusUnauthorized)
			w.Write([]byte("Signature verification failed"))
		}
	}
}

func Validate(w http.ResponseWriter, r *http.Request) {
	token := r.URL.Query().Get("token")
	if len(token) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte("Empty token"))
		return
	}
	if len(db.CheckToken(token)) == 0 {
		w.WriteHeader(http.StatusForbidden)
		w.Write([]byte("Forbidden"))
		return
	}
	w.Write([]byte("Success"))
}

func Key(w http.ResponseWriter, r *http.Request) {
	user := r.URL.Query().Get("user")
	if len(user) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte("Empty user"))
		return
	}
	key := db.UserKey(user)
	if len(key) == 0 {
		w.WriteHeader(http.StatusNotFound)
		w.Write([]byte("User key not found"))
		return
	}
	w.Write([]byte(key))
}

func Sign(w http.ResponseWriter, r *http.Request) {
	r.ParseMultipartForm(32 << 20)
	if len(r.MultipartForm.Value["token"]) == 0 || len(db.CheckToken(r.MultipartForm.Value["token"][0])) == 0 {
		w.WriteHeader(http.StatusUnauthorized)
		w.Write([]byte("Not authorized"))
		log.Warn(r.RemoteAddr + " - rejecting unauthorized sign request")
		return
	}
	owner := db.CheckToken(r.MultipartForm.Value["token"][0])
	if len(r.MultipartForm.Value["signature"]) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte("Empty signature"))
		log.Warn("auth.Sign received empty signature")
		return
	}
	signature := r.MultipartForm.Value["signature"][0]
	hash := pgp.Verify(owner, signature)
	if len(hash) == 0 {
		w.WriteHeader(http.StatusUnauthorized)
		w.Write([]byte("Failed to verify signature with user key"))
		log.Warn("Failed to verify signature with user key")
		return
	}
	info := db.Info(hash)
	if !db.CheckOwner(owner, hash) {
		w.WriteHeader(http.StatusUnauthorized)
		w.Write([]byte("File and signature have different owner"))
		log.Warn("File and signature have different owner")
		return
	}
	db.Write(owner, hash, signature)
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("File has been signed"))
	log.Info("File " + info["Name"] + "(" + hash + ")" + " has been signed by " + owner)
	return
}
<commit_msg>Panic fix<commit_after>package auth

import (
	"crypto/md5"
	"crypto/sha256"
	"fmt"
	"math/rand"
	"net/http"
	"strings"
	"time"

	"github.com/subutai-io/base/agent/log"

	"github.com/subutai-io/gorjun/db"
	"github.com/subutai-io/gorjun/pgp"
)

func Register(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		r.ParseMultipartForm(32 << 20)
		if strings.Split(r.RemoteAddr, ":")[0] == "127.0.0.1" && len(r.MultipartForm.Value["name"]) > 0 && len(r.MultipartForm.Value["key"]) > 0 {
			name := r.MultipartForm.Value["name"][0]
			key := r.MultipartForm.Value["key"][0]

			w.Write([]byte("Name: " + name + "\n"))
			w.Write([]byte("PGP key: " + key + "\n"))

			db.RegisterUser([]byte(name), []byte(key))
			return
		} else if len(r.MultipartForm.Value["key"]) > 0 {
			key := pgp.Verify("Hub", r.MultipartForm.Value["key"][0])
			if len(key) == 0 {
				w.Write([]byte("Signature check failed"))
				w.WriteHeader(http.StatusForbidden)
				return
			}
			fingerprint := pgp.Fingerprint(key)
			if len(fingerprint) == 0 {
				w.Write([]byte("Filed to get key fingerprint"))
				w.WriteHeader(http.StatusBadRequest)
				return
			}
			db.RegisterUser([]byte(fmt.Sprintf("%x", fingerprint)), []byte(key))
			return
		}
	}
	w.WriteHeader(http.StatusUnauthorized)
	w.Write([]byte("Not allowed"))
}

func Token(w http.ResponseWriter, r *http.Request) {
	rand.Seed(time.Now().UnixNano())
	if r.Method == http.MethodGet {
		name := r.URL.Query().Get("user")
		if len(name) != 0 {
			hash := md5.New()
			hash.Write([]byte(fmt.Sprint(time.Now().String(), name, rand.Float64())))
			authID := fmt.Sprintf("%x", hash.Sum(nil))
			db.SaveAuthID(name, authID)
			w.Write([]byte(authID))
		}
	} else if r.Method == http.MethodPost {
		name := r.FormValue("user")
		message := r.FormValue("message")
		if len(name) == 0 || len(message) == 0 {
			w.WriteHeader(http.StatusBadRequest)
			w.Write([]byte("Please specify user name and auth message"))
			log.Warn(r.RemoteAddr + " - empty user name or message filed")
			return
		}
		authid := pgp.Verify(name, message)
		if db.CheckAuthID(authid) == name {
			token := fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprint(time.Now().String(), name, rand.Float64()))))
			db.SaveToken(name, fmt.Sprintf("%x", sha256.Sum256([]byte(token))))
			w.Write([]byte(token))
		} else {
			w.WriteHeader(http.StatusUnauthorized)
			w.Write([]byte("Signature verification failed"))
		}
	}
}

func Validate(w http.ResponseWriter, r *http.Request) {
	token := r.URL.Query().Get("token")
	if len(token) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte("Empty token"))
		return
	}
	if len(db.CheckToken(token)) == 0 {
		w.WriteHeader(http.StatusForbidden)
		w.Write([]byte("Forbidden"))
		return
	}
	w.Write([]byte("Success"))
}

func Key(w http.ResponseWriter, r *http.Request) {
	user := r.URL.Query().Get("user")
	if len(user) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte("Empty user"))
		return
	}
	key := db.UserKey(user)
	if len(key) == 0 {
		w.WriteHeader(http.StatusNotFound)
		w.Write([]byte("User key not found"))
		return
	}
	w.Write([]byte(key))
}

func Sign(w http.ResponseWriter, r *http.Request) {
	r.ParseMultipartForm(32 << 20)
	if len(r.MultipartForm.Value["token"]) == 0 || len(db.CheckToken(r.MultipartForm.Value["token"][0])) == 0 {
		w.WriteHeader(http.StatusUnauthorized)
		w.Write([]byte("Not authorized"))
		log.Warn(r.RemoteAddr + " - rejecting unauthorized sign request")
		return
	}
	owner := db.CheckToken(r.MultipartForm.Value["token"][0])
	if len(r.MultipartForm.Value["signature"]) == 0 {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte("Empty signature"))
		log.Warn("auth.Sign received empty signature")
		return
	}
	signature := r.MultipartForm.Value["signature"][0]
	hash := pgp.Verify(owner, signature)
	if len(hash) == 0 {
		w.WriteHeader(http.StatusUnauthorized)
		w.Write([]byte("Failed to verify signature with user key"))
		log.Warn("Failed to verify signature with user key")
		return
	}
	info := db.Info(hash)
	if !db.CheckOwner(owner, hash) {
		w.WriteHeader(http.StatusUnauthorized)
		w.Write([]byte("File and signature have different owner"))
		log.Warn("File and signature have different owner")
		return
	}
	db.Write(owner, hash, signature)
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("File has been signed"))
	log.Info("File " + info["Name"] + "(" + hash + ")" + " has been signed by " + owner)
	return
}
<|endoftext|>


<commit_before>package auth

import (
  "fmt"
  "regexp"
  "net/http"
  "github.com/ricallinson/forgery"
  "github.com/spacedock-io/registry/config"
  "github.com/spacedock-io/registry/session"
)

var (
  tokenRegex = regexp.MustCompile(`^Token signature=([\w\-]+),repository=(.*?),access=(\w+)$`)
)

type Token struct {
  Signature, Repo, Access string
}

func LoadCheckToken(req *f.Request) bool {
  header := req.Get("Authorization")
  if header == ""{
    return false
  }

  extracted := tokenRegex.FindStringSubmatch(header)
  token := &Token{
    Signature: extracted[1],
    Repo: extracted[2],
    Access: extracted[3],
  }

  /*
   * Token Access must be compliant with the HTTP Method
  if token.Access == "read" && req.Method != "GET" { return false }
  if token.Access == "write" && req.Method != "POST" && req.Method != "PUT" { return false }
  if token.Access == "delete" && req.Method != "DELETE" { return false }
  */

  if token.Validate() {
    sx.Session(req).Set("token", token)
    sx.Session(req).Save()
    return true
  }
  return false
}

func (t *Token) Header() string {
  return "Token signature=" + t.Signature + ",repository=" + t.Repo + ",access="+ t.Access
}

func (t *Token) Validate() bool {
  client := &http.Client{}

  req, _ := http.NewRequest("GET",
    fmt.Sprintf("%s/v1/repositories/%s/images",
      config.Global.Get("index").Str(), t.Repo), nil)
  req.Header.Add("Authorization", t.Header())

  resp, err := client.Do(req)
  if err == nil && resp.StatusCode == 200 {
    return true
  }
  return false
}

func Secure(route func(*f.Request, *f.Response)) func(*f.Request, *f.Response, func()) {
  /*
   * Two types of auth are valid: Token or Session
   */
  return func(req *f.Request, res *f.Response, next func()) {
    if sx.Session(req).Get("token") != nil || LoadCheckToken(req) {
      route(req, res)
    } else {
      res.Send(401)
    }
  }
}
<commit_msg>Add quotes around repository in token string<commit_after>package auth

import (
  "fmt"
  "regexp"
  "net/http"
  "github.com/ricallinson/forgery"
  "github.com/spacedock-io/registry/config"
  "github.com/spacedock-io/registry/session"
)

var (
  tokenRegex = regexp.MustCompile(`^Token signature=([\w\-]+),repository="(.*?)",access=(\w+)$`)
)

type Token struct {
  Signature, Repo, Access string
}

func LoadCheckToken(req *f.Request) bool {
  header := req.Get("Authorization")
  if header == ""{
    return false
  }

  extracted := tokenRegex.FindStringSubmatch(header)
  token := &Token{
    Signature: extracted[1],
    Repo: extracted[2],
    Access: extracted[3],
  }

  /*
   * Token Access must be compliant with the HTTP Method
  if token.Access == "read" && req.Method != "GET" { return false }
  if token.Access == "write" && req.Method != "POST" && req.Method != "PUT" { return false }
  if token.Access == "delete" && req.Method != "DELETE" { return false }
  */

  if token.Validate() {
    sx.Session(req).Set("token", token)
    sx.Session(req).Save()
    return true
  }
  return false
}

func (t *Token) Header() string {
  return "Token signature=" + t.Signature + ",repository=\"" + t.Repo + "\",access="+ t.Access
}

func (t *Token) Validate() bool {
  client := &http.Client{}

  req, _ := http.NewRequest("GET",
    fmt.Sprintf("%s/v1/repositories/%s/images",
      config.Global.Get("index").Str(), t.Repo), nil)
  req.Header.Add("Authorization", t.Header())

  resp, err := client.Do(req)
  if err == nil && resp.StatusCode == 200 {
    return true
  }
  return false
}

func Secure(route func(*f.Request, *f.Response)) func(*f.Request, *f.Response, func()) {
  /*
   * Two types of auth are valid: Token or Session
   */
  return func(req *f.Request, res *f.Response, next func()) {
    if sx.Session(req).Get("token") != nil || LoadCheckToken(req) {
      route(req, res)
    } else {
      res.Send(401)
    }
  }
}
<|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 auth

import (
	"fmt"
	"regexp"
	"strings"

	"github.com/globalsign/mgo/bson"
	"github.com/pkg/errors"
	"github.com/tsuru/tsuru/db"
	"github.com/tsuru/tsuru/log"
	"github.com/tsuru/tsuru/permission"
	"github.com/tsuru/tsuru/storage"
	authTypes "github.com/tsuru/tsuru/types/auth"
)

var teamNameRegexp = regexp.MustCompile(`^[a-z][-@_.+\w]+$`)

type ErrTeamStillUsed struct {
	Apps             []string
	ServiceInstances []string
}

func TeamService() authTypes.TeamService {
	dbDriver, err := storage.GetCurrentDbDriver()
	if err != nil {
		dbDriver, err = storage.GetDefaultDbDriver()
		if err != nil {
			return nil
		}
	}
	return dbDriver.TeamService
}

func (e *ErrTeamStillUsed) Error() string {
	if len(e.Apps) > 0 {
		return fmt.Sprintf("Apps: %s", strings.Join(e.Apps, ", "))
	}
	return fmt.Sprintf("Service instances: %s", strings.Join(e.ServiceInstances, ", "))
}

func validateTeam(t authTypes.Team) error {
	if !teamNameRegexp.MatchString(t.Name) {
		return authTypes.ErrInvalidTeamName
	}
	return nil
}

// CreateTeam creates a team and add users to this team.
func CreateTeam(name string, user *User) error {
	if user == nil {
		return errors.New("user cannot be null")
	}
	name = strings.TrimSpace(name)
	team := authTypes.Team{
		Name:         name,
		CreatingUser: user.Email,
	}
	if err := validateTeam(team); err != nil {
		return err
	}
	err := TeamService().Insert(team)
	if err != nil {
		return err
	}
	err = user.AddRolesForEvent(permission.RoleEventTeamCreate, name)
	if err != nil {
		log.Errorf("unable to add default roles during team %q creation for %q: %s", name, user.Email, err)
	}
	return nil
}

// GetTeam find a team by name.
func GetTeam(name string) (*authTypes.Team, error) {
	return TeamService().FindByName(name)
}

// GetTeamsNames maps teams to a list of team names.
func GetTeamsNames(teams []authTypes.Team) []string {
	tn := make([]string, len(teams))
	for i, t := range teams {
		tn[i] = t.Name
	}
	return tn
}

func RemoveTeam(teamName string) error {
	conn, err := db.Conn()
	if err != nil {
		return err
	}
	defer conn.Close()
	var apps []string
	err = conn.Apps().Find(bson.M{"teams": teamName}).Distinct("name", &apps)
	if err != nil {
		return err
	}
	if len(apps) > 0 {
		return &ErrTeamStillUsed{Apps: apps}
	}
	var serviceInstances []string
	err = conn.ServiceInstances().Find(bson.M{"teams": teamName}).Distinct("name", &serviceInstances)
	if err != nil {
		return err
	}
	if len(serviceInstances) > 0 {
		return &ErrTeamStillUsed{ServiceInstances: serviceInstances}
	}
	return TeamService().Delete(authTypes.Team{Name: teamName})
}

func ListTeams() ([]authTypes.Team, error) {
	return TeamService().FindAll()
}
<commit_msg>auth: create TeamService<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 auth

import (
	"fmt"
	"regexp"
	"strings"

	"github.com/globalsign/mgo/bson"
	"github.com/pkg/errors"
	"github.com/tsuru/tsuru/db"
	"github.com/tsuru/tsuru/log"
	"github.com/tsuru/tsuru/permission"
	"github.com/tsuru/tsuru/storage"
	authTypes "github.com/tsuru/tsuru/types/auth"
)

var teamNameRegexp = regexp.MustCompile(`^[a-z][-@_.+\w]+$`)
var ts authTypes.TeamService

type ErrTeamStillUsed struct {
	Apps             []string
	ServiceInstances []string
}

type teamService struct {
	storage storage.TeamStorage
}

func (e *ErrTeamStillUsed) Error() string {
	if len(e.Apps) > 0 {
		return fmt.Sprintf("Apps: %s", strings.Join(e.Apps, ", "))
	}
	return fmt.Sprintf("Service instances: %s", strings.Join(e.ServiceInstances, ", "))
}

func (t *teamService) Insert(team authTypes.Team) error {
	return t.storage.Insert(team)
}

func (t *teamService) FindAll() ([]authTypes.Team, error) {
	return t.storage.FindAll()
}

func (t *teamService) FindByName(name string) (*authTypes.Team, error) {
	return t.storage.FindByName(name)
}

func (t *teamService) FindByNames(names []string) ([]authTypes.Team, error) {
	return t.storage.FindByNames(names)
}

func (t *teamService) Delete(team authTypes.Team) error {
	return t.storage.Delete(team)
}

func teamStorage() storage.TeamStorage {
	dbDriver, err := storage.GetCurrentDbDriver()
	if err != nil {
		dbDriver, err = storage.GetDefaultDbDriver()
		if err != nil {
			return nil
		}
	}
	return dbDriver.TeamStorage
}

func validateTeam(t authTypes.Team) error {
	if !teamNameRegexp.MatchString(t.Name) {
		return authTypes.ErrInvalidTeamName
	}
	return nil
}

func TeamService() authTypes.TeamService {
	if ts == nil {
		ts = &teamService{
			storage: teamStorage(),
		}
	}
	return ts
}

// CreateTeam creates a team and add users to this team.
func CreateTeam(name string, user *User) error {
	if user == nil {
		return errors.New("user cannot be null")
	}
	name = strings.TrimSpace(name)
	team := authTypes.Team{
		Name:         name,
		CreatingUser: user.Email,
	}
	if err := validateTeam(team); err != nil {
		return err
	}
	err := TeamService().Insert(team)
	if err != nil {
		return err
	}
	err = user.AddRolesForEvent(permission.RoleEventTeamCreate, name)
	if err != nil {
		log.Errorf("unable to add default roles during team %q creation for %q: %s", name, user.Email, err)
	}
	return nil
}

// GetTeam finds a team by name.
func GetTeam(name string) (*authTypes.Team, error) {
	return TeamService().FindByName(name)
}

// GetTeamsNames maps teams to a list of team names.
func GetTeamsNames(teams []authTypes.Team) []string {
	tn := make([]string, len(teams))
	for i, t := range teams {
		tn[i] = t.Name
	}
	return tn
}

func RemoveTeam(teamName string) error {
	conn, err := db.Conn()
	if err != nil {
		return err
	}
	defer conn.Close()
	var apps []string
	err = conn.Apps().Find(bson.M{"teams": teamName}).Distinct("name", &apps)
	if err != nil {
		return err
	}
	if len(apps) > 0 {
		return &ErrTeamStillUsed{Apps: apps}
	}
	var serviceInstances []string
	err = conn.ServiceInstances().Find(bson.M{"teams": teamName}).Distinct("name", &serviceInstances)
	if err != nil {
		return err
	}
	if len(serviceInstances) > 0 {
		return &ErrTeamStillUsed{ServiceInstances: serviceInstances}
	}
	return TeamService().Delete(authTypes.Team{Name: teamName})
}

func ListTeams() ([]authTypes.Team, error) {
	return TeamService().FindAll()
}
<|endoftext|>


<commit_before>package ssh2docker

import (
	"testing"

	. "github.com/smartystreets/goconvey/convey"
)

func TestServer_CheckConfig(t *testing.T) {
	Convey("Testing Server.CheckConfig", t, FailureContinues, func() {
		// FIXME: check with a script
		server, err := NewServer()
		So(err, ShouldBeNil)
		server.AllowedImages = []string{"alpine", "ubuntu:trusty", "abcde123"}

		So(server.CheckConfig(&ClientConfig{ImageName: "alpine"}), ShouldBeNil)
		So(server.CheckConfig(&ClientConfig{ImageName: "ubuntu:trusty"}), ShouldBeNil)
		So(server.CheckConfig(&ClientConfig{ImageName: "abcde123"}), ShouldBeNil)

		So(server.CheckConfig(&ClientConfig{ImageName: "abcde124"}), ShouldNotBeNil)
		So(server.CheckConfig(&ClientConfig{ImageName: "ubuntu:vivid"}), ShouldNotBeNil)
	})
}
<commit_msg>travis: fix auth_test.go<commit_after>package ssh2docker

import (
	"os"
	"testing"

	"github.com/apex/log"
	"github.com/apex/log/handlers/text"
	. "github.com/smartystreets/goconvey/convey"
)

func TestServer_CheckConfig(t *testing.T) {
	log.SetHandler(text.New(os.Stderr))

	Convey("Testing Server.CheckConfig", t, FailureContinues, func() {
		// FIXME: check with a script
		server, err := NewServer()
		So(err, ShouldBeNil)
		server.AllowedImages = []string{"alpine", "ubuntu:trusty", "abcde123"}

		So(server.CheckConfig(&ClientConfig{ImageName: "alpine"}), ShouldBeNil)
		So(server.CheckConfig(&ClientConfig{ImageName: "ubuntu:trusty"}), ShouldBeNil)
		So(server.CheckConfig(&ClientConfig{ImageName: "abcde123"}), ShouldBeNil)

		So(server.CheckConfig(&ClientConfig{ImageName: "abcde124"}), ShouldNotBeNil)
		So(server.CheckConfig(&ClientConfig{ImageName: "ubuntu:vivid"}), ShouldNotBeNil)
	})
}
<|endoftext|>


<commit_before>// Package autoflags provides a convenient way of exposing fields of struct as
// command line flags. Exposed fields should have special tag attached:
//
//	var config = struct {
//		Name    string `tag:"name,name of user"`
//		Age     uint   `tag:"age"`
//		Married bool   // this won't be exposed
//	}{
//		Name: "John Doe", // default values
//		Age:  34,
//	}
//
// After declaring your flags and their default values as above, just register
// flags with flag package and call flag.Parse() as usually:
//
// 	if err := autoflags.Define(&config) ; err != nil {
// 		log.Fatal(err)
// 	}
// 	flag.Parse()
//
// Now config struct has its fields populated from command line flags.
package autoflags

import (
	"errors"
	"flag"
	"reflect"
	"strings"
	"time"
)

var (
	// ErrPointerWanted is returned when passed argument is not a pointer
	ErrPointerWanted = errors.New("pointer expected")
	// ErrInvalidArgument is returned when passed argument is nil pointer or
	// pointer to a non-struct value
	ErrInvalidArgument = errors.New("non-nil pointer to struct expected")
)

// Define takes pointer to struct and declares flags for its flag-tagged fields.
// Valid tags have the following form: `flag:"flagname"` or
// `flag:"flagname,usage string"`.
func Define(config interface{}) error {
	st := reflect.ValueOf(config)
	if st.Kind() != reflect.Ptr {
		return ErrPointerWanted
	}
	st = reflect.Indirect(st)
	if !st.IsValid() || st.Type().Kind() != reflect.Struct {
		return ErrInvalidArgument
	}
	for i := 0; i < st.NumField(); i++ {
		val := st.Field(i)
		if !val.CanAddr() {
			continue
		}
		typ := st.Type().Field(i)
		var name, usage string
		tag := typ.Tag.Get("flag")
		if len(tag) == 0 {
			continue
		}
		flagData := strings.SplitN(tag, ",", 2)
		switch len(flagData) {
		case 1:
			name = flagData[0]
		case 2:
			name, usage = flagData[0], flagData[1]
		}
		addr := val.Addr()
		switch d := val.Interface().(type) {
		case int:
			flag.IntVar(addr.Interface().(*int), name, d, usage)
		case int64:
			flag.Int64Var(addr.Interface().(*int64), name, d, usage)
		case uint:
			flag.UintVar(addr.Interface().(*uint), name, d, usage)
		case uint64:
			flag.Uint64Var(addr.Interface().(*uint64), name, d, usage)
		case float64:
			flag.Float64Var(addr.Interface().(*float64), name, d, usage)
		case bool:
			flag.BoolVar(addr.Interface().(*bool), name, d, usage)
		case string:
			flag.StringVar(addr.Interface().(*string), name, d, usage)
		case time.Duration:
			flag.DurationVar(addr.Interface().(*time.Duration), name, d, usage)
		}
	}
	return nil
}
<commit_msg>Mistyped tag name fix<commit_after>// Package autoflags provides a convenient way of exposing fields of struct as
// command line flags. Exposed fields should have special tag attached:
//
//	var config = struct {
//		Name    string `flag:"name,name of user"`
//		Age     uint   `flag:"age"`
//		Married bool   // this won't be exposed
//	}{
//		Name: "John Doe", // default values
//		Age:  34,
//	}
//
// After declaring your flags and their default values as above, just register
// flags with flag package and call flag.Parse() as usually:
//
// 	if err := autoflags.Define(&config) ; err != nil {
// 		log.Fatal(err)
// 	}
// 	flag.Parse()
//
// Now config struct has its fields populated from command line flags.
package autoflags

import (
	"errors"
	"flag"
	"reflect"
	"strings"
	"time"
)

var (
	// ErrPointerWanted is returned when passed argument is not a pointer
	ErrPointerWanted = errors.New("pointer expected")
	// ErrInvalidArgument is returned when passed argument is nil pointer or
	// pointer to a non-struct value
	ErrInvalidArgument = errors.New("non-nil pointer to struct expected")
)

// Define takes pointer to struct and declares flags for its flag-tagged fields.
// Valid tags have the following form: `flag:"flagname"` or
// `flag:"flagname,usage string"`.
func Define(config interface{}) error {
	st := reflect.ValueOf(config)
	if st.Kind() != reflect.Ptr {
		return ErrPointerWanted
	}
	st = reflect.Indirect(st)
	if !st.IsValid() || st.Type().Kind() != reflect.Struct {
		return ErrInvalidArgument
	}
	for i := 0; i < st.NumField(); i++ {
		val := st.Field(i)
		if !val.CanAddr() {
			continue
		}
		typ := st.Type().Field(i)
		var name, usage string
		tag := typ.Tag.Get("flag")
		if len(tag) == 0 {
			continue
		}
		flagData := strings.SplitN(tag, ",", 2)
		switch len(flagData) {
		case 1:
			name = flagData[0]
		case 2:
			name, usage = flagData[0], flagData[1]
		}
		addr := val.Addr()
		switch d := val.Interface().(type) {
		case int:
			flag.IntVar(addr.Interface().(*int), name, d, usage)
		case int64:
			flag.Int64Var(addr.Interface().(*int64), name, d, usage)
		case uint:
			flag.UintVar(addr.Interface().(*uint), name, d, usage)
		case uint64:
			flag.Uint64Var(addr.Interface().(*uint64), name, d, usage)
		case float64:
			flag.Float64Var(addr.Interface().(*float64), name, d, usage)
		case bool:
			flag.BoolVar(addr.Interface().(*bool), name, d, usage)
		case string:
			flag.StringVar(addr.Interface().(*string), name, d, usage)
		case time.Duration:
			flag.DurationVar(addr.Interface().(*time.Duration), name, d, usage)
		}
	}
	return nil
}
<|endoftext|>


<commit_before>/*
    DNS-over-HTTPS
    Copyright (C) 2017 Star Brilliant <m13253@hotmail.com>

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

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

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

package jsonDNS

import (
	"net"
	"strconv"
	"strings"
	"time"
	"github.com/miekg/dns"
)

func Marshal(msg *dns.Msg) *Response {
	now := time.Now().UTC()

	resp := new(Response)
	resp.Status = uint32(msg.Rcode)
	resp.TC = msg.Truncated
	resp.RD = msg.RecursionDesired
	resp.RA = msg.RecursionAvailable
	resp.AD = msg.AuthenticatedData
	resp.CD = msg.CheckingDisabled

	resp.Question = make([]Question, 0, len(msg.Question))
	for _, question := range msg.Question {
		jsonQuestion := Question {
			Name: question.Name,
			Type: question.Qtype,
		}
		resp.Question = append(resp.Question, jsonQuestion)
	}

	resp.Answer = make([]RR, 0, len(msg.Answer))
	for _, rr := range msg.Answer {
		jsonAnswer := marshalRR(rr, now)
		if !resp.HaveTTL || jsonAnswer.TTL < resp.LeastTTL {
			resp.HaveTTL = true
			resp.LeastTTL = jsonAnswer.TTL
			resp.EarliestExpires = jsonAnswer.Expires
		}
		resp.Answer = append(resp.Answer, jsonAnswer)
	}

	resp.Authority = make([]RR, 0, len(msg.Ns))
	for _, rr := range msg.Ns {
		jsonAuthority := marshalRR(rr, now)
		if !resp.HaveTTL || jsonAuthority.TTL < resp.LeastTTL {
			resp.HaveTTL = true
			resp.LeastTTL = jsonAuthority.TTL
			resp.EarliestExpires = jsonAuthority.Expires
		}
		resp.Authority = append(resp.Authority, jsonAuthority)
	}

	resp.Additional = make([]RR, 0, len(msg.Extra))
	for _, rr := range msg.Extra {
		jsonAdditional := marshalRR(rr, now)
		header := rr.Header()
		if header.Rrtype == dns.TypeOPT {
			opt := rr.(*dns.OPT)
			resp.Status = ((opt.Hdr.Ttl & 0xff000000) >> 20) | (resp.Status & 0xff)
			for _, option := range opt.Option {
				if option.Option() == dns.EDNS0SUBNET {
					edns0 := option.(*dns.EDNS0_SUBNET)
					scopeMask := net.CIDRMask(int(edns0.SourceScope), len(edns0.Address))
					resp.EdnsClientSubnet = edns0.Address.Mask(scopeMask).String() + "/" + strconv.Itoa(int(edns0.SourceScope))
				}
			}
			continue
		}
		if !resp.HaveTTL || jsonAdditional.TTL < resp.LeastTTL {
			resp.HaveTTL = true
			resp.LeastTTL = jsonAdditional.TTL
			resp.EarliestExpires = jsonAdditional.Expires
		}
		resp.Additional = append(resp.Additional, jsonAdditional)
	}

	return resp
}

func marshalRR(rr dns.RR, now time.Time) RR {
	jsonRR := RR {}
	rrHeader := rr.Header()
	jsonRR.Name = rrHeader.Name
	jsonRR.Type = rrHeader.Rrtype
	jsonRR.TTL = rrHeader.Ttl
	jsonRR.Expires = now.Add(time.Duration(jsonRR.TTL) * time.Second)
	jsonRR.ExpiresStr = jsonRR.Expires.Format(time.RFC1123)
	data := strings.SplitN(rr.String(), "\t", 5)
	if len(data) >= 5 {
		jsonRR.Data = data[4]
	}
	return jsonRR
}
<commit_msg>Workaround bug https://github.com/miekg/dns/pull/530<commit_after>/*
    DNS-over-HTTPS
    Copyright (C) 2017 Star Brilliant <m13253@hotmail.com>

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

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

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

package jsonDNS

import (
	"net"
	"strconv"
	"strings"
	"time"
	"github.com/miekg/dns"
)

func Marshal(msg *dns.Msg) *Response {
	now := time.Now().UTC()

	resp := new(Response)
	resp.Status = uint32(msg.Rcode)
	resp.TC = msg.Truncated
	resp.RD = msg.RecursionDesired
	resp.RA = msg.RecursionAvailable
	resp.AD = msg.AuthenticatedData
	resp.CD = msg.CheckingDisabled

	resp.Question = make([]Question, 0, len(msg.Question))
	for _, question := range msg.Question {
		jsonQuestion := Question {
			Name: question.Name,
			Type: question.Qtype,
		}
		resp.Question = append(resp.Question, jsonQuestion)
	}

	resp.Answer = make([]RR, 0, len(msg.Answer))
	for _, rr := range msg.Answer {
		jsonAnswer := marshalRR(rr, now)
		if !resp.HaveTTL || jsonAnswer.TTL < resp.LeastTTL {
			resp.HaveTTL = true
			resp.LeastTTL = jsonAnswer.TTL
			resp.EarliestExpires = jsonAnswer.Expires
		}
		resp.Answer = append(resp.Answer, jsonAnswer)
	}

	resp.Authority = make([]RR, 0, len(msg.Ns))
	for _, rr := range msg.Ns {
		jsonAuthority := marshalRR(rr, now)
		if !resp.HaveTTL || jsonAuthority.TTL < resp.LeastTTL {
			resp.HaveTTL = true
			resp.LeastTTL = jsonAuthority.TTL
			resp.EarliestExpires = jsonAuthority.Expires
		}
		resp.Authority = append(resp.Authority, jsonAuthority)
	}

	resp.Additional = make([]RR, 0, len(msg.Extra))
	for _, rr := range msg.Extra {
		jsonAdditional := marshalRR(rr, now)
		header := rr.Header()
		if header.Rrtype == dns.TypeOPT {
			opt := rr.(*dns.OPT)
			resp.Status = ((opt.Hdr.Ttl & 0xff000000) >> 20) | (resp.Status & 0xff)
			for _, option := range opt.Option {
				if option.Option() == dns.EDNS0SUBNET {
					edns0 := option.(*dns.EDNS0_SUBNET)
					clientAddress := edns0.Address
					if clientAddress == nil {
						clientAddress = net.IPv4(0, 0, 0, 0)
					}
					scopeMask := net.CIDRMask(int(edns0.SourceScope), len(edns0.Address))
					resp.EdnsClientSubnet = clientAddress.Mask(scopeMask).String() + "/" + strconv.Itoa(int(edns0.SourceScope))
				}
			}
			continue
		}
		if !resp.HaveTTL || jsonAdditional.TTL < resp.LeastTTL {
			resp.HaveTTL = true
			resp.LeastTTL = jsonAdditional.TTL
			resp.EarliestExpires = jsonAdditional.Expires
		}
		resp.Additional = append(resp.Additional, jsonAdditional)
	}

	return resp
}

func marshalRR(rr dns.RR, now time.Time) RR {
	jsonRR := RR {}
	rrHeader := rr.Header()
	jsonRR.Name = rrHeader.Name
	jsonRR.Type = rrHeader.Rrtype
	jsonRR.TTL = rrHeader.Ttl
	jsonRR.Expires = now.Add(time.Duration(jsonRR.TTL) * time.Second)
	jsonRR.ExpiresStr = jsonRR.Expires.Format(time.RFC1123)
	data := strings.SplitN(rr.String(), "\t", 5)
	if len(data) >= 5 {
		jsonRR.Data = data[4]
	}
	return jsonRR
}
<|endoftext|>


<commit_before>/*
   Copyright The containerd Authors.

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

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

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

package estargz

import (
	"context"
	"fmt"
	"io"

	"github.com/containerd/containerd/content"
	"github.com/containerd/containerd/errdefs"
	"github.com/containerd/containerd/images"
	"github.com/containerd/stargz-snapshotter/estargz"
	"github.com/containerd/stargz-snapshotter/nativeconverter"
	"github.com/containerd/stargz-snapshotter/nativeconverter/uncompress"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// LayerConvertFunc converts legacy tar.gz layers into eStargz tar.gz layers.
// Media type is unchanged.
//
// Should be used in conjunction with WithDockerToOCI().
//
// Otherwise "containerd.io/snapshot/stargz/toc.digest" annotation will be lost,
// because the Docker media type does not support layer annotations.
func LayerConvertFunc(opts ...estargz.Option) nativeconverter.ConvertFunc {
	return func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) {
		if !images.IsLayerType(desc.MediaType) {
			// No conversion. No need to return an error here.
			return nil, nil
		}
		uncompressedDesc := &desc
		// We need to uncompress the archive first to call estargz.Build.
		if !uncompress.IsUncompressedType(desc.MediaType) {
			var err error
			uncompressedDesc, err = uncompress.LayerConvertFunc(ctx, cs, desc)
			if err != nil {
				return nil, err
			}
			if uncompressedDesc == nil {
				return nil, errors.Errorf("unexpectedly got the same blob aftr compression (%s, %q)", desc.Digest, desc.MediaType)
			}
			defer func() {
				if err := cs.Delete(ctx, uncompressedDesc.Digest); err != nil {
					logrus.WithError(err).WithField("uncompressedDesc", uncompressedDesc).Warn("failed to remove tmp uncompressed layer")
				}
			}()
			logrus.Debugf("estargz: uncompressed %s into %s", desc.Digest, uncompressedDesc.Digest)
		}

		info, err := cs.Info(ctx, desc.Digest)
		if err != nil {
			return nil, err
		}
		labels := info.Labels

		uncompressedReaderAt, err := cs.ReaderAt(ctx, *uncompressedDesc)
		if err != nil {
			return nil, err
		}
		defer uncompressedReaderAt.Close()
		uncompressedSR := io.NewSectionReader(uncompressedReaderAt, 0, uncompressedDesc.Size)
		blob, err := estargz.Build(uncompressedSR, opts...)
		if err != nil {
			return nil, err
		}
		defer blob.Close()
		ref := fmt.Sprintf("convert-estargz-from-%s", desc.Digest)
		w, err := cs.Writer(ctx, content.WithRef(ref))
		if err != nil {
			return nil, err
		}
		defer w.Close()
		n, err := io.Copy(w, blob)
		if err != nil {
			return nil, err
		}
		if err := blob.Close(); err != nil {
			return nil, err
		}
		// update diffID label
		labels[nativeconverter.LabelUncompressed] = blob.DiffID().String()
		if err = w.Commit(ctx, n, "", content.WithLabels(labels)); err != nil && !errdefs.IsAlreadyExists(err) {
			return nil, err
		}
		if err := w.Close(); err != nil {
			return nil, err
		}
		newDesc := desc
		if uncompress.IsUncompressedType(newDesc.MediaType) {
			if nativeconverter.IsDockerType(newDesc.MediaType) {
				newDesc.MediaType += ".gzip"
			} else {
				newDesc.MediaType += "+gzip"
			}
		}
		newDesc.Digest = w.Digest()
		newDesc.Size = n
		if newDesc.Annotations == nil {
			newDesc.Annotations = make(map[string]string, 1)
		}
		newDesc.Annotations[estargz.TOCJSONDigestAnnotation] = blob.TOCDigest().String()
		return &newDesc, nil
	}
}
<commit_msg>estargz: fix nil panic<commit_after>/*
   Copyright The containerd Authors.

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

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

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

package estargz

import (
	"context"
	"fmt"
	"io"

	"github.com/containerd/containerd/content"
	"github.com/containerd/containerd/errdefs"
	"github.com/containerd/containerd/images"
	"github.com/containerd/stargz-snapshotter/estargz"
	"github.com/containerd/stargz-snapshotter/nativeconverter"
	"github.com/containerd/stargz-snapshotter/nativeconverter/uncompress"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// LayerConvertFunc converts legacy tar.gz layers into eStargz tar.gz layers.
// Media type is unchanged.
//
// Should be used in conjunction with WithDockerToOCI().
//
// Otherwise "containerd.io/snapshot/stargz/toc.digest" annotation will be lost,
// because the Docker media type does not support layer annotations.
func LayerConvertFunc(opts ...estargz.Option) nativeconverter.ConvertFunc {
	return func(ctx context.Context, cs content.Store, desc ocispec.Descriptor) (*ocispec.Descriptor, error) {
		if !images.IsLayerType(desc.MediaType) {
			// No conversion. No need to return an error here.
			return nil, nil
		}
		uncompressedDesc := &desc
		// We need to uncompress the archive first to call estargz.Build.
		if !uncompress.IsUncompressedType(desc.MediaType) {
			var err error
			uncompressedDesc, err = uncompress.LayerConvertFunc(ctx, cs, desc)
			if err != nil {
				return nil, err
			}
			if uncompressedDesc == nil {
				return nil, errors.Errorf("unexpectedly got the same blob aftr compression (%s, %q)", desc.Digest, desc.MediaType)
			}
			defer func() {
				if err := cs.Delete(ctx, uncompressedDesc.Digest); err != nil {
					logrus.WithError(err).WithField("uncompressedDesc", uncompressedDesc).Warn("failed to remove tmp uncompressed layer")
				}
			}()
			logrus.Debugf("estargz: uncompressed %s into %s", desc.Digest, uncompressedDesc.Digest)
		}

		info, err := cs.Info(ctx, desc.Digest)
		if err != nil {
			return nil, err
		}
		labels := info.Labels
		if labels == nil {
			labels = make(map[string]string)
		}

		uncompressedReaderAt, err := cs.ReaderAt(ctx, *uncompressedDesc)
		if err != nil {
			return nil, err
		}
		defer uncompressedReaderAt.Close()
		uncompressedSR := io.NewSectionReader(uncompressedReaderAt, 0, uncompressedDesc.Size)
		blob, err := estargz.Build(uncompressedSR, opts...)
		if err != nil {
			return nil, err
		}
		defer blob.Close()
		ref := fmt.Sprintf("convert-estargz-from-%s", desc.Digest)
		w, err := cs.Writer(ctx, content.WithRef(ref))
		if err != nil {
			return nil, err
		}
		defer w.Close()
		n, err := io.Copy(w, blob)
		if err != nil {
			return nil, err
		}
		if err := blob.Close(); err != nil {
			return nil, err
		}
		// update diffID label
		labels[nativeconverter.LabelUncompressed] = blob.DiffID().String()
		if err = w.Commit(ctx, n, "", content.WithLabels(labels)); err != nil && !errdefs.IsAlreadyExists(err) {
			return nil, err
		}
		if err := w.Close(); err != nil {
			return nil, err
		}
		newDesc := desc
		if uncompress.IsUncompressedType(newDesc.MediaType) {
			if nativeconverter.IsDockerType(newDesc.MediaType) {
				newDesc.MediaType += ".gzip"
			} else {
				newDesc.MediaType += "+gzip"
			}
		}
		newDesc.Digest = w.Digest()
		newDesc.Size = n
		if newDesc.Annotations == nil {
			newDesc.Annotations = make(map[string]string, 1)
		}
		newDesc.Annotations[estargz.TOCJSONDigestAnnotation] = blob.TOCDigest().String()
		return &newDesc, nil
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"reflect"
	"syscall"
	"unsafe"
)

func lowerProcessPrio() {
	// TODO: implement me
}

type Mapping struct {
	mapping syscall.Handle
	addr    uintptr
}

func createMapping(name string, size int) (*Mapping, []byte) {
	f, err := os.OpenFile(name, os.O_RDWR, 0)
	if err != nil {
		log.Fatalf("failed to open comm file: %v", err)
	}
	defer f.Close()
	mapping, err := syscall.CreateFileMapping(syscall.InvalidHandle, nil, syscall.PAGE_READWRITE, 0, uint32(size), nil)
	if err != nil {
		log.Fatalf("failed to create file mapping: %v", err)
	}
	const FILE_MAP_ALL_ACCESS = 0xF001F
	addr, err := syscall.MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, uintptr(size))
	if err != nil {
		log.Fatalf("failed to mmap comm file: %v", err)
	}
	hdr := reflect.SliceHeader{addr, size, size}
	mem := *(*[]byte)(unsafe.Pointer(&hdr))
	mem[0] = 1 // test access
	return &Mapping{mapping, addr}, mem
}

func (m *Mapping) destroy() {
	syscall.UnmapViewOfFile(m.addr)
	syscall.CloseHandle(m.mapping)
}

func setupCommMapping(cmd *exec.Cmd, comm *Mapping, rOut, wIn *os.File) {
	cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_COMM_FD=%v", comm.mapping))
	cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_IN_FD=%v", rOut.Fd()))
	cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_OUT_FD=%v", wIn.Fd()))
}
<commit_msg>make handles inheritable on windows<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"reflect"
	"syscall"
	"unsafe"
)

func lowerProcessPrio() {
	// TODO: implement me
}

type Mapping struct {
	mapping syscall.Handle
	addr    uintptr
}

func createMapping(name string, size int) (*Mapping, []byte) {
	f, err := os.OpenFile(name, os.O_RDWR, 0)
	if err != nil {
		log.Fatalf("failed to open comm file: %v", err)
	}
	defer f.Close()
	mapping, err := syscall.CreateFileMapping(syscall.InvalidHandle, nil, syscall.PAGE_READWRITE, 0, uint32(size), nil)
	if err != nil {
		log.Fatalf("failed to create file mapping: %v", err)
	}
	const FILE_MAP_ALL_ACCESS = 0xF001F
	addr, err := syscall.MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, uintptr(size))
	if err != nil {
		log.Fatalf("failed to mmap comm file: %v", err)
	}
	hdr := reflect.SliceHeader{addr, size, size}
	mem := *(*[]byte)(unsafe.Pointer(&hdr))
	mem[0] = 1 // test access
	return &Mapping{mapping, addr}, mem
}

func (m *Mapping) destroy() {
	syscall.UnmapViewOfFile(m.addr)
	syscall.CloseHandle(m.mapping)
}

func setupCommMapping(cmd *exec.Cmd, comm *Mapping, rOut, wIn *os.File) {
	syscall.SetHandleInformation(Handle(comm.mapping), syscall.HANDLE_FLAG_INHERIT, 0)
	syscall.SetHandleInformation(Handle(rOut.Fd()), syscall.HANDLE_FLAG_INHERIT, 0)
	syscall.SetHandleInformation(Handle(wIn.Fd()), syscall.HANDLE_FLAG_INHERIT, 0)
	cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_COMM_FD=%v", comm.mapping))
	cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_IN_FD=%v", rOut.Fd()))
	cmd.Env = append(cmd.Env, fmt.Sprintf("GO_FUZZ_OUT_FD=%v", wIn.Fd()))
}
<|endoftext|>


<commit_before>// CT log client package contains types and code for interacting with
// RFC6962-compliant CT Log instances.
// See http://tools.ietf.org/html/rfc6962 for details
package client

import (
	"bytes"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"time"

	"github.com/mreiferson/go-httpclient"
)

// URI paths for CT Log endpoints
const (
	AddChainPath    = "/ct/v1/add-chain"
	AddPreChainPath = "/ct/v1/add-pre-chain"
	GetSTHPath      = "/ct/v1/get-sth"
	GetEntriesPath  = "/ct/v1/get-entries"
)

const (
	IssuerKeyHashLength = 32
)

// LogClient represents a client for a given CT Log instance
type LogClient struct {
	uri        string       // the base URI of the log. e.g. http://ct.googleapis/pilot
	httpClient *http.Client // used to interact with the log via HTTP
}

//////////////////////////////////////////////////////////////////////////////////
// JSON structures follow.
// These represent the structures returned by the CT Log server.
//////////////////////////////////////////////////////////////////////////////////

// addChainRequest represents the JSON request body sent to the add-chain CT
// method.
type addChainRequest struct {
	Chain []string `json:"chain"`
}

// addChainResponse represents the JSON response to the add-chain CT method.
// An SCT represents a Log's promise to integrate a [pre-]certificate into the
// log within a defined period of time.
type addChainResponse struct {
	SCTVersion Version `json:"sct_version"` // SCT structure version
	ID         string  `json:"id"`          // Log ID
	Timestamp  uint64  `json:"timestamp"`   // Timestamp of issuance
	Extensions string  `json:"extensions"`  // Holder for any CT extensions
	Signature  string  `json:"signature"`   // Log signature for this SCT
}

// getSTHResponse respresents the JSON response to the get-sth CT method
type getSTHResponse struct {
	TreeSize          uint64 `json:"tree_size"`           // Number of certs in the current tree
	Timestamp         uint64 `json:"timestamp"`           // Time that the tree was created
	SHA256RootHash    string `json:"sha256_root_hash"`    // Root hash of the tree
	TreeHeadSignature string `json:"tree_head_signature"` // Log signature for this STH
}

// base64LeafEntry respresents a Base64 encoded leaf entry
type base64LeafEntry struct {
	LeafInput string `json:"leaf_input"`
	ExtraData string `json:"extra_data"`
}

// getEntriesReponse respresents the JSON response to the CT get-entries method
type getEntriesResponse struct {
	Entries []base64LeafEntry `json:"entries"` // the list of returned entries
}

// getConsistencyProofResponse represents the JSON response to the CT get-consistency-proof method
type getConsistencyProofResponse struct {
	Consistency []string `json:"consistency"`
}

// getAuditProofResponse represents the JSON response to the CT get-audit-proof method
type getAuditProofResponse struct {
	Hash     []string `json:"hash"`      // the hashes which make up the proof
	TreeSize uint64   `json:"tree_size"` // the tree size against which this proof is constructed
}

// getAcceptedRootsResponse represents the JSON response to the CT get-roots method.
type getAcceptedRootsResponse struct {
	Certificates []string `json:"certificates"`
}

// getEntryAndProodReponse represents the JSON response to the CT get-entry-and-proof method
type getEntryAndProofResponse struct {
	LeafInput string   `json:"leaf_input"` // the entry itself
	ExtraData string   `json:"extra_data"` // any chain provided when the entry was added to the log
	AuditPath []string `json:"audit_path"` // the corresponding proof
}

// Constructs a new LogClient instance.
// |uri| is the base URI of the CT log instance to interact with, e.g.
// http://ct.googleapis.com/pilot
func New(uri string) *LogClient {
	var c LogClient
	c.uri = uri
	transport := &httpclient.Transport{
		ConnectTimeout:        10 * time.Second,
		RequestTimeout:        30 * time.Second,
		ResponseHeaderTimeout: 30 * time.Second,
		MaxIdleConnsPerHost:   10,
		DisableKeepAlives:     false,
	}
	c.httpClient = &http.Client{Transport: transport}
	return &c
}

// Makes a HTTP call to |uri|, and attempts to parse the response as a JSON
// representation of the structure in |res|.
// Returns a non-nil |error| if there was a problem.
func (c *LogClient) fetchAndParse(uri string, res interface{}) error {
	req, err := http.NewRequest("GET", uri, nil)
	if err != nil {
		return err
	}
	req.Header.Set("Keep-Alive", "timeout=15, max=100")
	resp, err := c.httpClient.Do(req)
	var body []byte
	if resp != nil {
		body, err = ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			return err
		}
	}
	if err != nil {
		return err
	}
	if err = json.Unmarshal(body, &res); err != nil {
		return err
	}
	return nil
}

// Makes a HTTP POST call to |uri|, and attempts to parse the response as a JSON
// representation of the structure in |res|.
// Returns a non-nil |error| if there was a problem.
func (c *LogClient) postAndParse(uri string, req interface{}, res interface{}) (*http.Response, string, error) {
	post_body, err := json.Marshal(req)
	if err != nil {
		return nil, "", err
	}
	httpReq, err := http.NewRequest("POST", uri, bytes.NewReader(post_body))
	if err != nil {
		return nil, "", err
	}
	httpReq.Header.Set("Keep-Alive", "timeout=15, max=100")
	httpReq.Header.Set("Content-Type", "application/json")
	resp, err := c.httpClient.Do(httpReq)
	// Read all of the body, if there is one, so that the http.Client can do
	// Keep-Alive:
	var body []byte
	if resp != nil {
		body, err = ioutil.ReadAll(resp.Body)
		resp.Body.Close()
	}
	if err != nil {
		return resp, string(body), err
	}
	if resp.StatusCode == 200 {
		if err != nil {
			return resp, string(body), err
		}
		if err = json.Unmarshal(body, &res); err != nil {
			return resp, string(body), err
		}
	}
	return resp, "", nil
}

// Attempts to add |chain| to the log, using the api end-point specified by
// |path|.
func (c *LogClient) addChainWithRetry(path string, chain []ASN1Cert) (*SignedCertificateTimestamp, error) {
	var resp addChainResponse
	var req addChainRequest
	for _, link := range chain {
		req.Chain = append(req.Chain, base64.StdEncoding.EncodeToString(link))
	}
	done := false
	for !done {
		backoffSeconds := 0
		httpResp, errorBody, err := c.postAndParse(c.uri+path, &req, &resp)
		if err != nil {
			log.Printf("Got %s, backing off.", err)
			backoffSeconds = 10
		} else {
			switch {
			case httpResp.StatusCode == 200:
				done = true
				break
			case httpResp.StatusCode == 408:
			case httpResp.StatusCode == 503:
				// Retry
				backoffSeconds = 10
				if retryAfter := httpResp.Header.Get("Retry-After"); retryAfter != "" {
					if seconds, err := strconv.Atoi(retryAfter); err != nil {
						backoffSeconds = seconds
					}
				}
			default:
				return nil, fmt.Errorf("Got HTTP Status %s: %s", httpResp.Status, errorBody)
			}
		}
		// Now back-off before retrying
		log.Printf("Got %s, backing-off %d seconds.", httpResp.Status, backoffSeconds)
		time.Sleep(time.Duration(backoffSeconds) * time.Second)
	}

	rawLogId, err := base64.StdEncoding.DecodeString(resp.ID)
	if err != nil {
		return nil, err
	}
	rawSignature, err := base64.StdEncoding.DecodeString(resp.Signature)
	if err != nil {
		return nil, err
	}
	return &SignedCertificateTimestamp{
		SCTVersion: resp.SCTVersion,
		LogID:      rawLogId,
		Timestamp:  resp.Timestamp,
		Extensions: CTExtensions(resp.Extensions),
		Signature:  rawSignature}, nil
}

// Adds the (DER represented) X509 |chain| to the log.
func (c *LogClient) AddChain(chain []ASN1Cert) (*SignedCertificateTimestamp, error) {
	return c.addChainWithRetry(AddChainPath, chain)
}

// Add the (DER represented) Precertificate |chain| to the log.
func (c *LogClient) AddPreChain(chain []ASN1Cert) (*SignedCertificateTimestamp, error) {
	return c.addChainWithRetry(AddPreChainPath, chain)
}

// Retrieves the current STH from the log.
// Returns a populated SignedTreeHead, or a non-nil error.
func (c *LogClient) GetSTH() (sth *SignedTreeHead, err error) {
	var resp getSTHResponse
	if err = c.fetchAndParse(c.uri+GetSTHPath, &resp); err != nil {
		return
	}
	sth = &SignedTreeHead{
		TreeSize:  resp.TreeSize,
		Timestamp: resp.Timestamp,
	}
	if sth.SHA256RootHash, err = base64.StdEncoding.DecodeString(resp.SHA256RootHash); err != nil {
		return nil, errors.New("invalid base64 encoding in sha256_root_hash")
	}
	if len(sth.SHA256RootHash) != sha256.Size {
		return nil, errors.New("sha256_root_hash is invalid length")
	}
	if sth.TreeHeadSignature, err = base64.StdEncoding.DecodeString(resp.TreeHeadSignature); err != nil {
		return nil, errors.New("invalid base64 encoding in tree_head_signature")
	}
	// TODO(alcutter): Verify signature
	return
}

// Attempts to retrieve the entries in the sequence [|start|, |end|] from the CT
// log server. (see section 4.6.)
// Returns a slice of LeafInputs or a non-nil error.
func (c *LogClient) GetEntries(start, end int64) ([]LogEntry, error) {
	if end < 0 {
		return nil, errors.New("end should be >= 0")
	}
	if end < start {
		return nil, errors.New("start should be <= end")
	}
	var resp getEntriesResponse
	err := c.fetchAndParse(fmt.Sprintf("%s%s?start=%d&end=%d", c.uri, GetEntriesPath, start, end), &resp)
	if err != nil {
		return nil, err
	}
	entries := make([]LogEntry, end-start+1, end-start+1)
	for index, entry := range resp.Entries {
		leafBytes, err := base64.StdEncoding.DecodeString(entry.LeafInput)
		leaf, err := ReadMerkleTreeLeaf(bytes.NewBuffer(leafBytes))
		if err != nil {
			return nil, err
		}
		entries[index].Leaf = *leaf
		chainBytes, err := base64.StdEncoding.DecodeString(entry.ExtraData)

		var chain []ASN1Cert
		switch leaf.TimestampedEntry.EntryType {
		case X509LogEntryType:
			chain, err = UnmarshalX509ChainArray(chainBytes)

		case PrecertLogEntryType:
			chain, err = UnmarshalPrecertChainArray(chainBytes)

		default:
			return nil, fmt.Errorf("saw unknown entry type: %v", leaf.TimestampedEntry.EntryType)
		}
		if err != nil {
			return nil, err
		}
		entries[index].Chain = chain
		entries[index].Index = start + int64(index)
	}
	return entries, nil
}
<commit_msg>Fix possible nil-dereference.<commit_after>// CT log client package contains types and code for interacting with
// RFC6962-compliant CT Log instances.
// See http://tools.ietf.org/html/rfc6962 for details
package client

import (
	"bytes"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"time"

	"github.com/mreiferson/go-httpclient"
)

// URI paths for CT Log endpoints
const (
	AddChainPath    = "/ct/v1/add-chain"
	AddPreChainPath = "/ct/v1/add-pre-chain"
	GetSTHPath      = "/ct/v1/get-sth"
	GetEntriesPath  = "/ct/v1/get-entries"
)

const (
	IssuerKeyHashLength = 32
)

// LogClient represents a client for a given CT Log instance
type LogClient struct {
	uri        string       // the base URI of the log. e.g. http://ct.googleapis/pilot
	httpClient *http.Client // used to interact with the log via HTTP
}

//////////////////////////////////////////////////////////////////////////////////
// JSON structures follow.
// These represent the structures returned by the CT Log server.
//////////////////////////////////////////////////////////////////////////////////

// addChainRequest represents the JSON request body sent to the add-chain CT
// method.
type addChainRequest struct {
	Chain []string `json:"chain"`
}

// addChainResponse represents the JSON response to the add-chain CT method.
// An SCT represents a Log's promise to integrate a [pre-]certificate into the
// log within a defined period of time.
type addChainResponse struct {
	SCTVersion Version `json:"sct_version"` // SCT structure version
	ID         string  `json:"id"`          // Log ID
	Timestamp  uint64  `json:"timestamp"`   // Timestamp of issuance
	Extensions string  `json:"extensions"`  // Holder for any CT extensions
	Signature  string  `json:"signature"`   // Log signature for this SCT
}

// getSTHResponse respresents the JSON response to the get-sth CT method
type getSTHResponse struct {
	TreeSize          uint64 `json:"tree_size"`           // Number of certs in the current tree
	Timestamp         uint64 `json:"timestamp"`           // Time that the tree was created
	SHA256RootHash    string `json:"sha256_root_hash"`    // Root hash of the tree
	TreeHeadSignature string `json:"tree_head_signature"` // Log signature for this STH
}

// base64LeafEntry respresents a Base64 encoded leaf entry
type base64LeafEntry struct {
	LeafInput string `json:"leaf_input"`
	ExtraData string `json:"extra_data"`
}

// getEntriesReponse respresents the JSON response to the CT get-entries method
type getEntriesResponse struct {
	Entries []base64LeafEntry `json:"entries"` // the list of returned entries
}

// getConsistencyProofResponse represents the JSON response to the CT get-consistency-proof method
type getConsistencyProofResponse struct {
	Consistency []string `json:"consistency"`
}

// getAuditProofResponse represents the JSON response to the CT get-audit-proof method
type getAuditProofResponse struct {
	Hash     []string `json:"hash"`      // the hashes which make up the proof
	TreeSize uint64   `json:"tree_size"` // the tree size against which this proof is constructed
}

// getAcceptedRootsResponse represents the JSON response to the CT get-roots method.
type getAcceptedRootsResponse struct {
	Certificates []string `json:"certificates"`
}

// getEntryAndProodReponse represents the JSON response to the CT get-entry-and-proof method
type getEntryAndProofResponse struct {
	LeafInput string   `json:"leaf_input"` // the entry itself
	ExtraData string   `json:"extra_data"` // any chain provided when the entry was added to the log
	AuditPath []string `json:"audit_path"` // the corresponding proof
}

// Constructs a new LogClient instance.
// |uri| is the base URI of the CT log instance to interact with, e.g.
// http://ct.googleapis.com/pilot
func New(uri string) *LogClient {
	var c LogClient
	c.uri = uri
	transport := &httpclient.Transport{
		ConnectTimeout:        10 * time.Second,
		RequestTimeout:        30 * time.Second,
		ResponseHeaderTimeout: 30 * time.Second,
		MaxIdleConnsPerHost:   10,
		DisableKeepAlives:     false,
	}
	c.httpClient = &http.Client{Transport: transport}
	return &c
}

// Makes a HTTP call to |uri|, and attempts to parse the response as a JSON
// representation of the structure in |res|.
// Returns a non-nil |error| if there was a problem.
func (c *LogClient) fetchAndParse(uri string, res interface{}) error {
	req, err := http.NewRequest("GET", uri, nil)
	if err != nil {
		return err
	}
	req.Header.Set("Keep-Alive", "timeout=15, max=100")
	resp, err := c.httpClient.Do(req)
	var body []byte
	if resp != nil {
		body, err = ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			return err
		}
	}
	if err != nil {
		return err
	}
	if err = json.Unmarshal(body, &res); err != nil {
		return err
	}
	return nil
}

// Makes a HTTP POST call to |uri|, and attempts to parse the response as a JSON
// representation of the structure in |res|.
// Returns a non-nil |error| if there was a problem.
func (c *LogClient) postAndParse(uri string, req interface{}, res interface{}) (*http.Response, string, error) {
	post_body, err := json.Marshal(req)
	if err != nil {
		return nil, "", err
	}
	httpReq, err := http.NewRequest("POST", uri, bytes.NewReader(post_body))
	if err != nil {
		return nil, "", err
	}
	httpReq.Header.Set("Keep-Alive", "timeout=15, max=100")
	httpReq.Header.Set("Content-Type", "application/json")
	resp, err := c.httpClient.Do(httpReq)
	// Read all of the body, if there is one, so that the http.Client can do
	// Keep-Alive:
	var body []byte
	if resp != nil {
		body, err = ioutil.ReadAll(resp.Body)
		resp.Body.Close()
	}
	if err != nil {
		return resp, string(body), err
	}
	if resp.StatusCode == 200 {
		if err != nil {
			return resp, string(body), err
		}
		if err = json.Unmarshal(body, &res); err != nil {
			return resp, string(body), err
		}
	}
	return resp, "", nil
}

// Attempts to add |chain| to the log, using the api end-point specified by
// |path|.
func (c *LogClient) addChainWithRetry(path string, chain []ASN1Cert) (*SignedCertificateTimestamp, error) {
	var resp addChainResponse
	var req addChainRequest
	for _, link := range chain {
		req.Chain = append(req.Chain, base64.StdEncoding.EncodeToString(link))
	}
	done := false
	httpStatus := "Unknown"
	for !done {
		backoffSeconds := 0
		httpResp, errorBody, err := c.postAndParse(c.uri+path, &req, &resp)
		if err != nil {
			log.Printf("Got %s, backing off.", err)
			backoffSeconds = 10
		} else {
			switch {
			case httpResp.StatusCode == 200:
				done = true
				break
			case httpResp.StatusCode == 408:
			case httpResp.StatusCode == 503:
				// Retry
				backoffSeconds = 10
				if retryAfter := httpResp.Header.Get("Retry-After"); retryAfter != "" {
					if seconds, err := strconv.Atoi(retryAfter); err != nil {
						backoffSeconds = seconds
					}
				}
			default:
				return nil, fmt.Errorf("Got HTTP Status %s: %s", httpResp.Status, errorBody)
			}
			httpStatus = httpResp.Status
		}
		// Now back-off before retrying
		log.Printf("Got %s, backing-off %d seconds.", httpStatus, backoffSeconds)
		time.Sleep(time.Duration(backoffSeconds) * time.Second)
	}

	rawLogId, err := base64.StdEncoding.DecodeString(resp.ID)
	if err != nil {
		return nil, err
	}
	rawSignature, err := base64.StdEncoding.DecodeString(resp.Signature)
	if err != nil {
		return nil, err
	}
	return &SignedCertificateTimestamp{
		SCTVersion: resp.SCTVersion,
		LogID:      rawLogId,
		Timestamp:  resp.Timestamp,
		Extensions: CTExtensions(resp.Extensions),
		Signature:  rawSignature}, nil
}

// Adds the (DER represented) X509 |chain| to the log.
func (c *LogClient) AddChain(chain []ASN1Cert) (*SignedCertificateTimestamp, error) {
	return c.addChainWithRetry(AddChainPath, chain)
}

// Add the (DER represented) Precertificate |chain| to the log.
func (c *LogClient) AddPreChain(chain []ASN1Cert) (*SignedCertificateTimestamp, error) {
	return c.addChainWithRetry(AddPreChainPath, chain)
}

// Retrieves the current STH from the log.
// Returns a populated SignedTreeHead, or a non-nil error.
func (c *LogClient) GetSTH() (sth *SignedTreeHead, err error) {
	var resp getSTHResponse
	if err = c.fetchAndParse(c.uri+GetSTHPath, &resp); err != nil {
		return
	}
	sth = &SignedTreeHead{
		TreeSize:  resp.TreeSize,
		Timestamp: resp.Timestamp,
	}
	if sth.SHA256RootHash, err = base64.StdEncoding.DecodeString(resp.SHA256RootHash); err != nil {
		return nil, errors.New("invalid base64 encoding in sha256_root_hash")
	}
	if len(sth.SHA256RootHash) != sha256.Size {
		return nil, errors.New("sha256_root_hash is invalid length")
	}
	if sth.TreeHeadSignature, err = base64.StdEncoding.DecodeString(resp.TreeHeadSignature); err != nil {
		return nil, errors.New("invalid base64 encoding in tree_head_signature")
	}
	// TODO(alcutter): Verify signature
	return
}

// Attempts to retrieve the entries in the sequence [|start|, |end|] from the CT
// log server. (see section 4.6.)
// Returns a slice of LeafInputs or a non-nil error.
func (c *LogClient) GetEntries(start, end int64) ([]LogEntry, error) {
	if end < 0 {
		return nil, errors.New("end should be >= 0")
	}
	if end < start {
		return nil, errors.New("start should be <= end")
	}
	var resp getEntriesResponse
	err := c.fetchAndParse(fmt.Sprintf("%s%s?start=%d&end=%d", c.uri, GetEntriesPath, start, end), &resp)
	if err != nil {
		return nil, err
	}
	entries := make([]LogEntry, end-start+1, end-start+1)
	for index, entry := range resp.Entries {
		leafBytes, err := base64.StdEncoding.DecodeString(entry.LeafInput)
		leaf, err := ReadMerkleTreeLeaf(bytes.NewBuffer(leafBytes))
		if err != nil {
			return nil, err
		}
		entries[index].Leaf = *leaf
		chainBytes, err := base64.StdEncoding.DecodeString(entry.ExtraData)

		var chain []ASN1Cert
		switch leaf.TimestampedEntry.EntryType {
		case X509LogEntryType:
			chain, err = UnmarshalX509ChainArray(chainBytes)

		case PrecertLogEntryType:
			chain, err = UnmarshalPrecertChainArray(chainBytes)

		default:
			return nil, fmt.Errorf("saw unknown entry type: %v", leaf.TimestampedEntry.EntryType)
		}
		if err != nil {
			return nil, err
		}
		entries[index].Chain = chain
		entries[index].Index = start + int64(index)
	}
	return entries, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Vitess Authors.

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

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

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

package main

import (
	"context"
	"flag"
	"io"
	"os"
	"time"

	"github.com/spf13/cobra"

	"vitess.io/vitess/go/trace"
	"vitess.io/vitess/go/vt/log"
	"vitess.io/vitess/go/vt/vtadmin"
	"vitess.io/vitess/go/vt/vtadmin/cluster"
	"vitess.io/vitess/go/vt/vtadmin/grpcserver"
	vtadminhttp "vitess.io/vitess/go/vt/vtadmin/http"
	"vitess.io/vitess/go/vt/vtadmin/http/debug"
	"vitess.io/vitess/go/vt/vtadmin/rbac"
)

var (
	opts                 grpcserver.Options
	httpOpts             vtadminhttp.Options
	clusterConfigs       cluster.ClustersFlag
	clusterFileConfig    cluster.FileConfig
	defaultClusterConfig cluster.Config

	rbacConfigPath string
	enableRBAC     bool
	disableRBAC    bool

	traceCloser io.Closer = &noopCloser{}

	rootCmd = &cobra.Command{
		Use: "vtadmin",
		PreRun: func(cmd *cobra.Command, args []string) {
			tmp := os.Args
			os.Args = os.Args[0:1]
			flag.Parse()
			os.Args = tmp

			if opts.EnableTracing || httpOpts.EnableTracing {
				startTracing(cmd)
			}
		},
		Run: run,
		PostRun: func(cmd *cobra.Command, args []string) {
			trace.LogErrorsWhenClosing(traceCloser)
		},
	}
)

// fatal ensures the tracer is closed and final spans are sent before issuing
// a log.Fatal call with the given args.
func fatal(args ...any) {
	trace.LogErrorsWhenClosing(traceCloser)
	log.Fatal(args...)
}

// startTracing checks the value of --tracer and then starts tracing, populating
// the private global traceCloser
func startTracing(cmd *cobra.Command) {
	tracer, err := cmd.Flags().GetString("tracer")
	if err != nil {
		log.Warningf("not starting tracer; err: %s", err)
		return
	}

	if tracer == "" || tracer == "noop" {
		log.Warningf("starting tracing with noop tracer")
	}

	traceCloser = trace.StartTracing("vtadmin")
}

func run(cmd *cobra.Command, args []string) {
	bootSpan, _ := trace.NewSpan(context.Background(), "vtadmin.boot")
	defer bootSpan.Finish()

	configs := clusterFileConfig.Combine(defaultClusterConfig, clusterConfigs)
	clusters := make([]*cluster.Cluster, len(configs))

	if len(configs) == 0 {
		bootSpan.Finish()
		fatal("must specify at least one cluster")
	}

	var rbacConfig *rbac.Config
	if disableRBAC {
		rbacConfig = rbac.DefaultConfig()
	} else if enableRBAC && rbacConfigPath != "" {
		cfg, err := rbac.LoadConfig(rbacConfigPath)
		if err != nil {
			fatal(err)
		}

		rbacConfig = cfg
	} else if enableRBAC && rbacConfigPath == "" {
		fatal("must pass --rbac-config path when enabling rbac")
	} else {
		fatal("must explicitly enable or disable RBAC by passing --no-rbac or --rbac")
	}

	for i, cfg := range configs {
		cluster, err := cfg.Cluster()
		if err != nil {
			bootSpan.Finish()
			fatal(err)
		}

		clusters[i] = cluster
	}

	s := vtadmin.NewAPI(clusters, vtadmin.Options{
		GRPCOpts: opts,
		HTTPOpts: httpOpts,
		RBAC:     rbacConfig,
	})
	bootSpan.Finish()

	if err := s.ListenAndServe(); err != nil {
		fatal(err)
	}
}

func main() {
	rootCmd.Flags().StringVar(&opts.Addr, "addr", ":15000", "address to serve on")
	rootCmd.Flags().DurationVar(&opts.CMuxReadTimeout, "lmux-read-timeout", time.Second, "how long to spend connection muxing")
	rootCmd.Flags().DurationVar(&opts.LameDuckDuration, "lame-duck-duration", time.Second*5, "length of lame duck period at shutdown")
	rootCmd.Flags().Var(&clusterConfigs, "cluster", "per-cluster configuration. any values here take precedence over those in -cluster-defaults or -cluster-config")
	rootCmd.Flags().Var(&clusterFileConfig, "cluster-config", "path to a yaml cluster configuration. see clusters.example.yaml") // (TODO:@amason) provide example config.
	rootCmd.Flags().Var(&defaultClusterConfig, "cluster-defaults", "default options for all clusters")

	rootCmd.Flags().AddGoFlag(flag.Lookup("tracer"))                 // defined in go/vt/trace
	rootCmd.Flags().AddGoFlag(flag.Lookup("tracing-enable-logging")) // defined in go/vt/trace
	rootCmd.Flags().AddGoFlag(flag.Lookup("tracing-sampling-type"))  // defined in go/vt/trace
	rootCmd.Flags().AddGoFlag(flag.Lookup("tracing-sampling-rate"))  // defined in go/vt/trace
	rootCmd.Flags().BoolVar(&opts.EnableTracing, "grpc-tracing", false, "whether to enable tracing on the gRPC server")
	rootCmd.Flags().BoolVar(&httpOpts.EnableTracing, "http-tracing", false, "whether to enable tracing on the HTTP server")

	rootCmd.Flags().BoolVar(&httpOpts.DisableCompression, "http-no-compress", false, "whether to disable compression of HTTP API responses")
	rootCmd.Flags().BoolVar(&httpOpts.DisableDebug, "http-no-debug", false, "whether to disable /debug/pprof/* and /debug/env HTTP endpoints")
	rootCmd.Flags().Var(&debug.OmitEnv, "http-debug-omit-env", "name of an environment variable to omit from /debug/env, if http debug endpoints are enabled. specify multiple times to omit multiple env vars")
	rootCmd.Flags().Var(&debug.SanitizeEnv, "http-debug-sanitize-env", "name of an environment variable to sanitize in /debug/env, if http debug endpoints are enabled. specify multiple times to sanitize multiple env vars")
	rootCmd.Flags().StringSliceVar(&httpOpts.CORSOrigins, "http-origin", []string{}, "repeated, comma-separated flag of allowed CORS origins. omit to disable CORS")
	rootCmd.Flags().StringVar(&httpOpts.ExperimentalOptions.TabletURLTmpl,
		"http-tablet-url-tmpl",
		"https://{{ .Tablet.Hostname }}:80",
		"[EXPERIMENTAL] Go template string to generate a reachable http(s) "+
			"address for a tablet. Currently used to make passthrough "+
			"requests to /debug/vars endpoints.",
	)
	rootCmd.Flags().BoolVar(&httpOpts.EnableDynamicClusters, "http-enable-dynamic-clusters", false, "whether to enable dynamic clusters that are set by request header cookies")

	// rbac flags
	rootCmd.Flags().StringVar(&rbacConfigPath, "rbac-config", "", "path to an RBAC config file. must be set if passing --rbac")
	rootCmd.Flags().BoolVar(&enableRBAC, "rbac", false, "whether to enable RBAC. must be set if not passing --rbac")
	rootCmd.Flags().BoolVar(&disableRBAC, "no-rbac", false, "whether to disable RBAC. must be set if not passing --no-rbac")

	// glog flags, no better way to do this
	rootCmd.Flags().AddGoFlag(flag.Lookup("v"))
	rootCmd.Flags().AddGoFlag(flag.Lookup("logtostderr"))
	rootCmd.Flags().AddGoFlag(flag.Lookup("alsologtostderr"))
	rootCmd.Flags().AddGoFlag(flag.Lookup("stderrthreshold"))
	rootCmd.Flags().AddGoFlag(flag.Lookup("log_dir"))

	if err := rootCmd.Execute(); err != nil {
		log.Fatal(err)
	}

	log.Flush()
}

type noopCloser struct{}

func (nc *noopCloser) Close() error { return nil }
<commit_msg>Update dynamic clusters to accept no clusters (#10016)<commit_after>/*
Copyright 2020 The Vitess Authors.

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

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

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

package main

import (
	"context"
	"flag"
	"io"
	"os"
	"time"

	"github.com/spf13/cobra"

	"vitess.io/vitess/go/trace"
	"vitess.io/vitess/go/vt/log"
	"vitess.io/vitess/go/vt/vtadmin"
	"vitess.io/vitess/go/vt/vtadmin/cluster"
	"vitess.io/vitess/go/vt/vtadmin/grpcserver"
	vtadminhttp "vitess.io/vitess/go/vt/vtadmin/http"
	"vitess.io/vitess/go/vt/vtadmin/http/debug"
	"vitess.io/vitess/go/vt/vtadmin/rbac"
)

var (
	opts                 grpcserver.Options
	httpOpts             vtadminhttp.Options
	clusterConfigs       cluster.ClustersFlag
	clusterFileConfig    cluster.FileConfig
	defaultClusterConfig cluster.Config

	rbacConfigPath string
	enableRBAC     bool
	disableRBAC    bool

	traceCloser io.Closer = &noopCloser{}

	rootCmd = &cobra.Command{
		Use: "vtadmin",
		PreRun: func(cmd *cobra.Command, args []string) {
			tmp := os.Args
			os.Args = os.Args[0:1]
			flag.Parse()
			os.Args = tmp

			if opts.EnableTracing || httpOpts.EnableTracing {
				startTracing(cmd)
			}
		},
		Run: run,
		PostRun: func(cmd *cobra.Command, args []string) {
			trace.LogErrorsWhenClosing(traceCloser)
		},
	}
)

// fatal ensures the tracer is closed and final spans are sent before issuing
// a log.Fatal call with the given args.
func fatal(args ...any) {
	trace.LogErrorsWhenClosing(traceCloser)
	log.Fatal(args...)
}

// startTracing checks the value of --tracer and then starts tracing, populating
// the private global traceCloser
func startTracing(cmd *cobra.Command) {
	tracer, err := cmd.Flags().GetString("tracer")
	if err != nil {
		log.Warningf("not starting tracer; err: %s", err)
		return
	}

	if tracer == "" || tracer == "noop" {
		log.Warningf("starting tracing with noop tracer")
	}

	traceCloser = trace.StartTracing("vtadmin")
}

func run(cmd *cobra.Command, args []string) {
	bootSpan, _ := trace.NewSpan(context.Background(), "vtadmin.boot")
	defer bootSpan.Finish()

	configs := clusterFileConfig.Combine(defaultClusterConfig, clusterConfigs)
	clusters := make([]*cluster.Cluster, len(configs))

	if len(configs) == 0 && !httpOpts.EnableDynamicClusters {
		bootSpan.Finish()
		fatal("must specify at least one cluster")
	}

	var rbacConfig *rbac.Config
	if disableRBAC {
		rbacConfig = rbac.DefaultConfig()
	} else if enableRBAC && rbacConfigPath != "" {
		cfg, err := rbac.LoadConfig(rbacConfigPath)
		if err != nil {
			fatal(err)
		}

		rbacConfig = cfg
	} else if enableRBAC && rbacConfigPath == "" {
		fatal("must pass --rbac-config path when enabling rbac")
	} else {
		fatal("must explicitly enable or disable RBAC by passing --no-rbac or --rbac")
	}

	for i, cfg := range configs {
		cluster, err := cfg.Cluster()
		if err != nil {
			bootSpan.Finish()
			fatal(err)
		}

		clusters[i] = cluster
	}

	s := vtadmin.NewAPI(clusters, vtadmin.Options{
		GRPCOpts: opts,
		HTTPOpts: httpOpts,
		RBAC:     rbacConfig,
	})
	bootSpan.Finish()

	if err := s.ListenAndServe(); err != nil {
		fatal(err)
	}
}

func main() {
	rootCmd.Flags().StringVar(&opts.Addr, "addr", ":15000", "address to serve on")
	rootCmd.Flags().DurationVar(&opts.CMuxReadTimeout, "lmux-read-timeout", time.Second, "how long to spend connection muxing")
	rootCmd.Flags().DurationVar(&opts.LameDuckDuration, "lame-duck-duration", time.Second*5, "length of lame duck period at shutdown")
	rootCmd.Flags().Var(&clusterConfigs, "cluster", "per-cluster configuration. any values here take precedence over those in -cluster-defaults or -cluster-config")
	rootCmd.Flags().Var(&clusterFileConfig, "cluster-config", "path to a yaml cluster configuration. see clusters.example.yaml") // (TODO:@amason) provide example config.
	rootCmd.Flags().Var(&defaultClusterConfig, "cluster-defaults", "default options for all clusters")

	rootCmd.Flags().AddGoFlag(flag.Lookup("tracer"))                 // defined in go/vt/trace
	rootCmd.Flags().AddGoFlag(flag.Lookup("tracing-enable-logging")) // defined in go/vt/trace
	rootCmd.Flags().AddGoFlag(flag.Lookup("tracing-sampling-type"))  // defined in go/vt/trace
	rootCmd.Flags().AddGoFlag(flag.Lookup("tracing-sampling-rate"))  // defined in go/vt/trace
	rootCmd.Flags().BoolVar(&opts.EnableTracing, "grpc-tracing", false, "whether to enable tracing on the gRPC server")
	rootCmd.Flags().BoolVar(&httpOpts.EnableTracing, "http-tracing", false, "whether to enable tracing on the HTTP server")

	rootCmd.Flags().BoolVar(&httpOpts.DisableCompression, "http-no-compress", false, "whether to disable compression of HTTP API responses")
	rootCmd.Flags().BoolVar(&httpOpts.DisableDebug, "http-no-debug", false, "whether to disable /debug/pprof/* and /debug/env HTTP endpoints")
	rootCmd.Flags().Var(&debug.OmitEnv, "http-debug-omit-env", "name of an environment variable to omit from /debug/env, if http debug endpoints are enabled. specify multiple times to omit multiple env vars")
	rootCmd.Flags().Var(&debug.SanitizeEnv, "http-debug-sanitize-env", "name of an environment variable to sanitize in /debug/env, if http debug endpoints are enabled. specify multiple times to sanitize multiple env vars")
	rootCmd.Flags().StringSliceVar(&httpOpts.CORSOrigins, "http-origin", []string{}, "repeated, comma-separated flag of allowed CORS origins. omit to disable CORS")
	rootCmd.Flags().StringVar(&httpOpts.ExperimentalOptions.TabletURLTmpl,
		"http-tablet-url-tmpl",
		"https://{{ .Tablet.Hostname }}:80",
		"[EXPERIMENTAL] Go template string to generate a reachable http(s) "+
			"address for a tablet. Currently used to make passthrough "+
			"requests to /debug/vars endpoints.",
	)
	rootCmd.Flags().BoolVar(&httpOpts.EnableDynamicClusters, "http-enable-dynamic-clusters", false, "whether to enable dynamic clusters that are set by request header cookies")

	// rbac flags
	rootCmd.Flags().StringVar(&rbacConfigPath, "rbac-config", "", "path to an RBAC config file. must be set if passing --rbac")
	rootCmd.Flags().BoolVar(&enableRBAC, "rbac", false, "whether to enable RBAC. must be set if not passing --rbac")
	rootCmd.Flags().BoolVar(&disableRBAC, "no-rbac", false, "whether to disable RBAC. must be set if not passing --no-rbac")

	// glog flags, no better way to do this
	rootCmd.Flags().AddGoFlag(flag.Lookup("v"))
	rootCmd.Flags().AddGoFlag(flag.Lookup("logtostderr"))
	rootCmd.Flags().AddGoFlag(flag.Lookup("alsologtostderr"))
	rootCmd.Flags().AddGoFlag(flag.Lookup("stderrthreshold"))
	rootCmd.Flags().AddGoFlag(flag.Lookup("log_dir"))

	if err := rootCmd.Execute(); err != nil {
		log.Fatal(err)
	}

	log.Flush()
}

type noopCloser struct{}

func (nc *noopCloser) Close() error { return nil }
<|endoftext|>


<commit_before>package azmo

import (
	"context"
	"fmt"
	"io"
	"net"
	"os"
	"testing"

	pb "github.com/azmodb/azmo/azmopb"
	"github.com/azmodb/db"
)

const defaultTestServerAddress = "localhost:7979"

var listener net.Listener

func newServer(addr string) (listener net.Listener, err error) {
	listener, err = net.Listen("tcp", addr)
	if err != nil {
		return nil, err
	}

	go func() {
		if err := Listen(db.New(), listener, "", ""); err != nil {
			panic(fmt.Sprintf("azmo server failed: %v", err))
		}
	}()
	return listener, err
}

func init() {
	l, err := newServer(defaultTestServerAddress)
	if err != nil {
		panic(fmt.Sprintf("azmo server failed: %v", err))
	}
	listener = l
}

type fmtEncoder struct {
	w io.Writer
}

func (e fmtEncoder) Encode(ev *pb.Event) error {
	_, err := fmt.Fprintln(e.w, ev)
	return err
}

func TestBasicServerClient(t *testing.T) {
	c, err := Dial(defaultTestServerAddress, 0)
	if err != nil {
		t.Fatalf("cannot dial server: %v", err)
	}
	defer c.Close()

	e := fmtEncoder{w: os.Stdout}
	err = c.Put(context.TODO(), e, &pb.PutRequest{
		Key:   []byte("k1"),
		Value: []byte("v1"),
	})
	if err != nil {
		t.Fatalf("put k1: %v", err)
	}

	err = c.Get(context.TODO(), e, &pb.GetRequest{
		Key:       []byte("k1"),
		Revision:  0,
		MustEqual: false,
	})
	if err != nil {
		t.Fatalf("get k1: %v", err)
	}
}
<commit_msg>improve basic test case<commit_after>package azmo

import (
	"bytes"
	"context"
	"fmt"
	"net"
	"testing"

	pb "github.com/azmodb/azmo/azmopb"
	"github.com/azmodb/db"
)

const defaultTestServerAddress = "localhost:7979"

var listener net.Listener

func newServer(addr string) (listener net.Listener, err error) {
	listener, err = net.Listen("tcp", addr)
	if err != nil {
		return nil, err
	}

	go func() {
		if err := Listen(db.New(), listener, "", ""); err != nil {
			panic(fmt.Sprintf("azmo server failed: %v", err))
		}
	}()
	return listener, err
}

func init() {
	l, err := newServer(defaultTestServerAddress)
	if err != nil {
		panic(fmt.Sprintf("azmo server failed: %v", err))
	}
	listener = l
}

/*
type fmtEncoder struct {
	w io.Writer
}

func (e fmtEncoder) Encode(ev *pb.Event) error {
	_, err := fmt.Fprintln(e.w, ev)
	return err
}
*/

type testEncoder struct {
	typ     pb.Event_Type
	key     []byte
	content []byte
	created int64
	current int64
}

func (e testEncoder) Encode(ev *pb.Event) error {
	if e.typ != ev.Type {
		return fmt.Errorf("expected event type %v, have %v", e.typ, ev.Type)
	}
	if bytes.Compare(e.key, ev.Key) != 0 {
		return fmt.Errorf("expected event key %v, have %v", e.key, ev.Key)
	}
	if bytes.Compare(e.content, ev.Content) != 0 {
		return fmt.Errorf("expected event content %v, have %v", e.content, ev.Content)
	}
	if e.created != ev.Created {
		return fmt.Errorf("expected created rev %d, have %d", e.created, ev.Created)
	}
	if e.current != ev.Current {
		return fmt.Errorf("expected current rev %d, have %d", e.current, ev.Current)
	}
	return nil
}

func TestPutGet(t *testing.T) {
	c, err := Dial(defaultTestServerAddress, 0)
	if err != nil {
		t.Fatalf("cannot dial server: %v", err)
	}
	defer c.Close()

	putTest := testEncoder{typ: pb.Put, key: []byte("k1"), created: 1, current: 1}
	err = c.Put(context.TODO(), putTest, &pb.PutRequest{
		Key:   []byte("k1"),
		Value: []byte("v1"),
	})
	if err != nil {
		t.Fatalf("put k1: %v", err)
	}

	getTest := testEncoder{typ: pb.Get, key: []byte("k1"), content: []byte("v1"), created: 1, current: 1}
	err = c.Get(context.TODO(), getTest, &pb.GetRequest{
		Key:       []byte("k1"),
		Revision:  0,
		MustEqual: false,
	})
	if err != nil {
		t.Fatalf("get k1: %v", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"path"
	"net/http"
	"io"
	"archive/tar"
	"compress/gzip"
	"github.com/Sirupsen/logrus"
	"github.com/samalba/dockerclient"
)

// instance of DockerClient allowing for making calls to the docker daemon
// remote API
var dockerClient *dockerclient.DockerClient

func main() {

	// init docker client object
	var err error
	dockerClient, err = dockerclient.NewDockerClient("unix:///var/run/docker.sock", nil)
	if err != nil {
		logrus.Fatal(err.Error())
	}

	// get the version of the docker daemon so we can be sure the corresponding
	// docker client is installed and install it if necessary
	version, err := dockerClient.Version()
	if err != nil {
		logrus.Fatal(err.Error())
	}
	dockerDaemonVersion := version.Version

	// name of docker binary that is needed
	dockerBinaryName := "docker-" + dockerDaemonVersion
	logrus.Println("looking for docker binary named:", dockerBinaryName)

        filename := path.Join("/bin", dockerBinaryName)

	if _, err := os.Stat(filename); os.IsNotExist(err) {

		logrus.Println("docker binary (version " + dockerDaemonVersion + ") not found.")
		logrus.Println("downloading", dockerBinaryName, "...")

		out, err := os.Create(filename)
		if err != nil {
			logrus.Fatal(err.Error())
		}
		defer out.Close()
		resp, err := http.Get("https://get.docker.com/builds/Linux/x86_64/docker-" + dockerDaemonVersion + ".tgz")
		if err != nil {
			logrus.Fatal(err.Error())
		}
		defer resp.Body.Close()

		gr, err := gzip.NewReader(resp.Body)
                defer gr.Close()
                if err != nil {
                       logrus.Fatal(err.Error())
                }

                tr := tar.NewReader(gr)
                for {
                        hdr, err := tr.Next()
                        if err == io.EOF {
                               break
                        }
                        if err != nil {
                               logrus.Fatal(err.Error())
                        }

                        if hdr.Typeflag == tar.TypeReg && hdr.Name == "docker/docker" {
                                _, err = io.Copy(out, tr)
                                if err != nil {
                                        logrus.Fatal(err.Error())
		                }
                                break
                        }
                        logrus.Println("not yet")
                }

		err = os.Chmod(filename, 0700)
		if err != nil {
			logrus.Fatal(err.Error())
		}
    }
}
<commit_msg>Run 'go fmt' to clean up formatting<commit_after>package main

import (
	"archive/tar"
	"compress/gzip"
	"github.com/Sirupsen/logrus"
	"github.com/samalba/dockerclient"
	"io"
	"net/http"
	"os"
	"path"
)

// instance of DockerClient allowing for making calls to the docker daemon
// remote API
var dockerClient *dockerclient.DockerClient

func main() {

	// init docker client object
	var err error
	dockerClient, err = dockerclient.NewDockerClient("unix:///var/run/docker.sock", nil)
	if err != nil {
		logrus.Fatal(err.Error())
	}

	// get the version of the docker daemon so we can be sure the corresponding
	// docker client is installed and install it if necessary
	version, err := dockerClient.Version()
	if err != nil {
		logrus.Fatal(err.Error())
	}
	dockerDaemonVersion := version.Version

	// name of docker binary that is needed
	dockerBinaryName := "docker-" + dockerDaemonVersion
	logrus.Println("looking for docker binary named:", dockerBinaryName)

	filename := path.Join("/bin", dockerBinaryName)

	if _, err := os.Stat(filename); os.IsNotExist(err) {

		logrus.Println("docker binary (version " + dockerDaemonVersion + ") not found.")
		logrus.Println("downloading", dockerBinaryName, "...")

		out, err := os.Create(filename)
		if err != nil {
			logrus.Fatal(err.Error())
		}
		defer out.Close()
		resp, err := http.Get("https://get.docker.com/builds/Linux/x86_64/docker-" + dockerDaemonVersion + ".tgz")
		if err != nil {
			logrus.Fatal(err.Error())
		}
		defer resp.Body.Close()

		gr, err := gzip.NewReader(resp.Body)
		defer gr.Close()
		if err != nil {
			logrus.Fatal(err.Error())
		}

		tr := tar.NewReader(gr)
		for {
			hdr, err := tr.Next()
			if err == io.EOF {
				break
			}
			if err != nil {
				logrus.Fatal(err.Error())
			}

			if hdr.Typeflag == tar.TypeReg && hdr.Name == "docker/docker" {
				_, err = io.Copy(out, tr)
				if err != nil {
					logrus.Fatal(err.Error())
				}
				break
			}
			logrus.Println("not yet")
		}

		err = os.Chmod(filename, 0700)
		if err != nil {
			logrus.Fatal(err.Error())
		}
	}
}
<|endoftext|>


<commit_before>package gocd

import (
	"context"
	"encoding/json"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"net/http"
	"strings"
)

// APIClientRequest helper struct to reduce amount of code.
type APIClientRequest struct {
	Method       string
	Path         string
	APIVersion   string
	RequestBody  interface{}
	ResponseType string
	ResponseBody interface{}
	Headers      map[string]string
}

// Handles any call to HEAD by returning whether or not we got a 2xx code.
func (c *Client) genericHeadAction(ctx context.Context, path string, apiversion string) (bool, *APIResponse, error) {
	_, resp, err := c.httpAction(ctx, &APIClientRequest{
		Method:       "HEAD",
		Path:         path,
		APIVersion:   apiversion,
		ResponseType: responseTypeJSON,
	})

	exists := resp.HTTP.StatusCode >= 300 || resp.HTTP.StatusCode < 200

	return exists, resp, err

}

func (c *Client) patchAction(ctx context.Context, r *APIClientRequest) (interface{}, *APIResponse, error) {
	r.Method = "PATCH"
	return c.httpAction(ctx, r)
}

func (c *Client) getAction(ctx context.Context, r *APIClientRequest) (interface{}, *APIResponse, error) {
	r.Method = "GET"
	return c.httpAction(ctx, r)
}

func (c *Client) postAction(ctx context.Context, r *APIClientRequest) (interface{}, *APIResponse, error) {
	r.Method = "POST"
	return c.httpAction(ctx, r)
}

func (c *Client) putAction(ctx context.Context, r *APIClientRequest) (interface{}, *APIResponse, error) {
	r.Method = "PUT"
	return c.httpAction(ctx, r)
}

// Returns a message from the DELETE action on the provided HTTP resource.
func (c *Client) deleteAction(ctx context.Context, path string, apiversion string) (string, *APIResponse, error) {
	a := StringResponse{}
	_, resp, err := c.httpAction(ctx, &APIClientRequest{
		Method:       "DELETE",
		Path:         path,
		APIVersion:   apiversion,
		ResponseType: responseTypeJSON,
		ResponseBody: &a,
	})

	return a.Message, resp, err
}

func (c *Client) httpAction(ctx context.Context, r *APIClientRequest) (responeBody interface{}, resp *APIResponse, err error) {

	log.Debugf("HTTP Request\n%s %s", r.Method, r.Path)

	if r.ResponseType == "" {
		r.ResponseType = responseTypeJSON
	}

	if ver, isVersioned := (r.RequestBody).(Versioned); isVersioned {
		if r.Headers == nil {
			r.Headers = map[string]string{}
		}
		r.Headers["If-Match"] = fmt.Sprintf("\"%s\"", ver.GetVersion())
	}

	// Build the request
	var req *APIRequest
	if req, err = c.NewRequest(r.Method, r.Path, r.RequestBody, r.APIVersion); err != nil {
		return false, nil, err
	}
	if r.RequestBody != nil {
		log.Debugf("\n%s\n\n", r.RequestBody)
	}

	if len(r.Headers) > 0 {
		for key, value := range r.Headers {
			req.HTTP.Header.Set(key, value)
		}
	}

	printHeaderDebug(req.HTTP.Header)

	if resp, err = c.Do(ctx, req, r.ResponseBody, r.ResponseType); err != nil {
		log.Error(err)
		return r.ResponseBody, resp, err
	}

	if ver, isVersioned := (r.ResponseBody).(Versioned); isVersioned {
		parseVersions(resp.HTTP, ver)
	}

	if r.ResponseType == responseTypeJSON {
		log.Debugf("\nResponse\n%s %s\n", resp.HTTP.Proto, resp.HTTP.Status)
		printHeaderDebug(resp.HTTP.Header)
		b, _ := json.Marshal(r.ResponseBody)
		log.Debugf("\n%s", b)
	}

	return r.ResponseBody, resp, err
}

func printHeaderDebug(headers http.Header) {
	for header, values := range headers {
		for _, value := range values {
			log.Debugf("%s: %s", header, value)
		}
	}
}

func parseVersions(response *http.Response, versioned Versioned) {
	etag := response.Header.Get("Etag")
	versioned.SetVersion(
		strings.Replace(etag, "\"", "", -1),
	)
}
<commit_msg>Simplified Version actions<commit_after>package gocd

import (
	"context"
	"encoding/json"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"net/http"
	"strings"
)

// APIClientRequest helper struct to reduce amount of code.
type APIClientRequest struct {
	Method       string
	Path         string
	APIVersion   string
	RequestBody  interface{}
	ResponseType string
	ResponseBody interface{}
	Headers      map[string]string
}

// Handles any call to HEAD by returning whether or not we got a 2xx code.
func (c *Client) genericHeadAction(ctx context.Context, path string, apiversion string) (bool, *APIResponse, error) {
	_, resp, err := c.httpAction(ctx, &APIClientRequest{
		Method:       "HEAD",
		Path:         path,
		APIVersion:   apiversion,
		ResponseType: responseTypeJSON,
	})

	exists := resp.HTTP.StatusCode >= 300 || resp.HTTP.StatusCode < 200

	return exists, resp, err

}

func (c *Client) patchAction(ctx context.Context, r *APIClientRequest) (interface{}, *APIResponse, error) {
	r.Method = "PATCH"
	return c.httpAction(ctx, r)
}

func (c *Client) getAction(ctx context.Context, r *APIClientRequest) (interface{}, *APIResponse, error) {
	r.Method = "GET"
	return c.httpAction(ctx, r)
}

func (c *Client) postAction(ctx context.Context, r *APIClientRequest) (interface{}, *APIResponse, error) {
	r.Method = "POST"
	return c.httpAction(ctx, r)
}

func (c *Client) putAction(ctx context.Context, r *APIClientRequest) (interface{}, *APIResponse, error) {
	r.Method = "PUT"
	return c.httpAction(ctx, r)
}

// Returns a message from the DELETE action on the provided HTTP resource.
func (c *Client) deleteAction(ctx context.Context, path string, apiversion string) (string, *APIResponse, error) {
	a := StringResponse{}
	_, resp, err := c.httpAction(ctx, &APIClientRequest{
		Method:       "DELETE",
		Path:         path,
		APIVersion:   apiversion,
		ResponseType: responseTypeJSON,
		ResponseBody: &a,
	})

	return a.Message, resp, err
}

func (c *Client) httpAction(ctx context.Context, r *APIClientRequest) (responeBody interface{}, resp *APIResponse, err error) {

	log.Debugf("HTTP Request\n%s %s", r.Method, r.Path)

	if r.ResponseType == "" {
		r.ResponseType = responseTypeJSON
	}

	versionAction(r.RequestBody, func(ver Versioned) {
		if r.Headers == nil {
			r.Headers = map[string]string{}
		}
		r.Headers["If-Match"] = fmt.Sprintf("\"%s\"", ver.GetVersion())
	})

	// Build the request
	var req *APIRequest
	if req, err = c.NewRequest(r.Method, r.Path, r.RequestBody, r.APIVersion); err != nil {
		return false, nil, err
	}
	if r.RequestBody != nil {
		log.Debugf("\n%s\n\n", r.RequestBody)
	}

	if len(r.Headers) > 0 {
		for key, value := range r.Headers {
			req.HTTP.Header.Set(key, value)
		}
	}

	printHeaderDebug(req.HTTP.Header)

	if resp, err = c.Do(ctx, req, r.ResponseBody, r.ResponseType); err != nil {
		log.Error(err)
		return r.ResponseBody, resp, err
	}

	versionAction(r.ResponseBody, func(ver Versioned) {
		parseVersions(resp.HTTP, ver)
	})

	if r.ResponseType == responseTypeJSON {
		log.Debugf("\nResponse\n%s %s\n", resp.HTTP.Proto, resp.HTTP.Status)
		printHeaderDebug(resp.HTTP.Header)
		b, _ := json.Marshal(r.ResponseBody)
		log.Debugf("\n%s", b)
	}

	return r.ResponseBody, resp, err
}

func versionAction(versioned interface{}, verFunc func(versionsed Versioned)) {
	if ver, isVersioned := (versioned).(Versioned); isVersioned {
		verFunc(ver)
	}
}

func printHeaderDebug(headers http.Header) {
	for header, values := range headers {
		for _, value := range values {
			log.Debugf("%s: %s", header, value)
		}
	}
}

func parseVersions(response *http.Response, versioned Versioned) {
	etag := response.Header.Get("Etag")
	versioned.SetVersion(
		strings.Replace(etag, "\"", "", -1),
	)
}
<|endoftext|>