<commit_before>package commands

import (
	"fmt"
	"regexp"
	"time"

	table "github.com/crackcomm/go-clitable"
	"github.com/github/hub/cmd"
	"github.com/wolfeidau/buildkite-cli/config"
	"github.com/wolfeidau/buildkite-cli/git"
	"github.com/wolfeidau/buildkite-cli/utils"
	bk "github.com/wolfeidau/go-buildkite/buildkite"
)

var projectColumns = []string{"ID", "NAME", "BUILD", "BRANCH", "MESSAGE", "STATE", "FINISHED"}
var buildColumns = []string{"PROJECT", "NUMBER", "BRANCH", "MESSAGE", "STATE", "COMMIT"}

var projectOrgRegex = regexp.MustCompile(`\/organizations\/([\w_-]+)\/`)

// BkCli manages the config and state for the buildkite cli
type bkCli struct {
	config *config.Config
	client *bk.Client
}

// NewBkCli configure the buildkite cli using the supplied config
func newBkCli() (*bkCli, error) {
	config := config.CurrentConfig()

	client, err := newClient(config)

	if err != nil {
		return nil, err
	}

	return &bkCli{config, client}, nil
}

// Get List of Projects for all the orginizations.
func (cli *bkCli) projectList(quietList bool) error {

	t := time.Now()

	projects, err := cli.listProjects()

	if err != nil {
		return err
	}

	if quietList {
		for _, proj := range projects {
			fmt.Printf("%-36s\n", *proj.ID)
		}
		return nil // we are done
	}

	tb := table.New(projectColumns)
	vals := make(map[string]interface{})

	for _, proj := range projects {
		if proj.FeaturedBuild != nil {
			vals = utils.ToMap(projectColumns, []interface{}{*proj.ID, *proj.Name, *proj.FeaturedBuild.Number, *proj.FeaturedBuild.Branch, *proj.FeaturedBuild.Message, *proj.FeaturedBuild.State, *proj.FeaturedBuild.FinishedAt})
		} else {
			vals = utils.ToMap(projectColumns, []interface{}{*proj.ID, *proj.Name, 0, "", "", "", ""})
		}
		tb.AddRow(vals)
	}
	tb.Markdown = true
	tb.Print()

	fmt.Printf("\nTime taken: %s\n", time.Now().Sub(t))

	return err
}

// List Get List of Builds
func (cli *bkCli) buildList(quietList bool) error {

	var (
		builds []bk.Build
		err    error
	)

	t := time.Now()

	projects, err := cli.listProjects()

	if err != nil {
		return err
	}

	// did we locate a project
	project := git.LocateProject(projects)

	if project != nil {
		fmt.Printf("Listing for project = %s\n\n", *project.Name)

		org := extractOrg(*project.URL)

		builds, _, err = cli.client.Builds.ListByProject(org, *project.Slug, nil)

	} else {
		utils.Check(fmt.Errorf("Failed to locate the buildkite project using git.")) // TODO tidy this up
		return nil
	}

	if err != nil {
		return err
	}

	if quietList {
		for _, build := range builds {
			fmt.Printf("%-36s\n", *build.ID)
		}
		return nil // we are done
	}

	tb := table.New(buildColumns)

	for _, build := range builds {
		vals := utils.ToMap(buildColumns, []interface{}{*build.Project.Name, *build.Number, *build.Branch, *build.Message, *build.State, *build.Commit})
		tb.AddRow(vals)
	}

	tb.Markdown = true
	tb.Print()

	fmt.Printf("\nTime taken: %s\n", time.Now().Sub(t))

	return nil
}

func (cli *bkCli) openProjectBuilds() error {

	projects, err := cli.listProjects()

	if err != nil {
		return err
	}

	// did we locate a project
	project := git.LocateProject(projects)

	if project != nil {
		fmt.Printf("Opening project = %s\n\n", *project.Name)

	} else {
		utils.Check(fmt.Errorf("Failed to locate the buildkite project using git.")) // TODO tidy this up
		return nil
	}

	org := extractOrg(*project.URL)

	projectURL := fmt.Sprintf("https://buildkite.com/%s/%s/builds", org, *project.Slug) // TODO URL should come from REST interface

	args, err := utils.BrowserLauncher()

	utils.Check(err) // TODO tidy this up

	cmd := cmd.New(args[0])

	args = append(args, projectURL)

	cmd.WithArgs(args[1:]...)

	_, err = cmd.CombinedOutput()

	return err
}

func (cli *bkCli) setup() error {
	return cli.config.PromptForConfig()
}

func (cli *bkCli) listProjects() ([]bk.Project, error) {
	var projects []bk.Project

	orgs, _, err := cli.client.Organizations.List(nil)

	if err != nil {
		return nil, err
	}

	for _, org := range orgs {
		projs, _, err := cli.client.Projects.List(*org.Slug, nil)

		if err != nil {
			return nil, err
		}

		projects = append(projects, projs...)
	}

	return projects, nil
}

func newClient(config *config.Config) (*bk.Client, error) {

	if config.OAuthToken == "" {
		err := config.PromptForConfig()
		if err != nil {
			return nil, err
		}
	}

	tconf, err := bk.NewTokenConfig(config.OAuthToken)

	if err != nil {
		return nil, err
	}

	return bk.NewClient(tconf.Client()), nil
}

// ProjectList just get a list of projects
func ProjectList(quietList bool) error {
	cli, err := newBkCli()
	if err != nil {
		return err
	}

	return cli.projectList(quietList)
}

// BuildsList retrieve a list of builds for the current project using the git remote to locate it.
func BuildsList(quietList bool) error {
	cli, err := newBkCli()
	if err != nil {
		return err
	}

	return cli.buildList(quietList)
}

// Open buildkite project for the current project using the git remote to locate it.
func Open() error {
	cli, err := newBkCli()
	if err != nil {
		return err
	}

	return cli.openProjectBuilds()
}

// Setup configure the buildkite cli with a new token.
func Setup() error {
	cli, err := newBkCli()
	if err != nil {
		return err
	}

	return cli.setup()
}

func extractOrg(url string) string {
	m := projectOrgRegex.FindStringSubmatch(url)

	if len(m) == 2 {
		return m[1]
	}

	return ""
}
<commit_msg>Started tidying up this thing.<commit_after>package commands

import (
	"fmt"
	"regexp"
	"time"

	table "github.com/crackcomm/go-clitable"
	"github.com/github/hub/cmd"
	"github.com/wolfeidau/buildkite-cli/config"
	"github.com/wolfeidau/buildkite-cli/git"
	"github.com/wolfeidau/buildkite-cli/utils"
	bk "github.com/wolfeidau/go-buildkite/buildkite"
)

var (
	projectColumns = []string{"ID", "NAME", "BUILD", "BRANCH", "MESSAGE", "STATE", "FINISHED"}
	buildColumns   = []string{"PROJECT", "NUMBER", "BRANCH", "MESSAGE", "STATE", "COMMIT"}

	projectOrgRegex = regexp.MustCompile(`\/organizations\/([\w_-]+)\/`)
)

// BkCli manages the config and state for the buildkite cli
type bkCli struct {
	config *config.Config
	client *bk.Client
}

// NewBkCli configure the buildkite cli using the supplied config
func newBkCli() (*bkCli, error) {
	config := config.CurrentConfig()

	client, err := newClient(config)

	if err != nil {
		return nil, err
	}

	return &bkCli{config, client}, nil
}

// Get List of Projects for all the orginizations.
func (cli *bkCli) projectList(quietList bool) error {

	t := time.Now()

	projects, err := cli.listProjects()

	if err != nil {
		return err
	}

	if quietList {
		for _, proj := range projects {
			fmt.Printf("%-36s\n", *proj.ID)
		}
		return nil // we are done
	}

	tb := table.New(projectColumns)
	vals := make(map[string]interface{})

	for _, proj := range projects {
		if proj.FeaturedBuild != nil {
			vals = utils.ToMap(projectColumns, []interface{}{*proj.ID, *proj.Name, *proj.FeaturedBuild.Number, *proj.FeaturedBuild.Branch, *proj.FeaturedBuild.Message, *proj.FeaturedBuild.State, *proj.FeaturedBuild.FinishedAt})
		} else {
			vals = utils.ToMap(projectColumns, []interface{}{*proj.ID, *proj.Name, 0, "", "", "", ""})
		}
		tb.AddRow(vals)
	}
	tb.Markdown = true
	tb.Print()

	fmt.Printf("\nTime taken: %s\n", time.Now().Sub(t))

	return err
}

// List Get List of Builds
func (cli *bkCli) buildList(quietList bool) error {

	var (
		builds []bk.Build
		err    error
	)

	t := time.Now()

	projects, err := cli.listProjects()

	if err != nil {
		return err
	}

	// did we locate a project
	project := git.LocateProject(projects)

	if project != nil {
		fmt.Printf("Listing for project = %s\n\n", *project.Name)

		org := extractOrg(*project.URL)

		builds, _, err = cli.client.Builds.ListByProject(org, *project.Slug, nil)

	} else {
		utils.Check(fmt.Errorf("Failed to locate the buildkite project using git.")) // TODO tidy this up
		return nil
	}

	if err != nil {
		return err
	}

	if quietList {
		for _, build := range builds {
			fmt.Printf("%-36s\n", *build.ID)
		}
		return nil // we are done
	}

	tb := table.New(buildColumns)

	for _, build := range builds {
		vals := utils.ToMap(buildColumns, []interface{}{*build.Project.Name, *build.Number, *build.Branch, *build.Message, *build.State, *build.Commit})
		tb.AddRow(vals)
	}

	tb.Markdown = true
	tb.Print()

	fmt.Printf("\nTime taken: %s\n", time.Now().Sub(t))

	return nil
}

func (cli *bkCli) openProjectBuilds() error {

	projects, err := cli.listProjects()

	if err != nil {
		return err
	}

	// did we locate a project
	project := git.LocateProject(projects)

	if project != nil {
		fmt.Printf("Opening project = %s\n\n", *project.Name)

	} else {
		utils.Check(fmt.Errorf("Failed to locate the buildkite project using git.")) // TODO tidy this up
		return nil
	}

	org := extractOrg(*project.URL)

	projectURL := fmt.Sprintf("https://buildkite.com/%s/%s/builds", org, *project.Slug) // TODO URL should come from REST interface

	args, err := utils.BrowserLauncher()

	utils.Check(err) // TODO tidy this up

	cmd := cmd.New(args[0])

	args = append(args, projectURL)

	cmd.WithArgs(args[1:]...)

	_, err = cmd.CombinedOutput()

	return err
}

func (cli *bkCli) setup() error {
	return cli.config.PromptForConfig()
}

func (cli *bkCli) listProjects() ([]bk.Project, error) {
	var projects []bk.Project

	orgs, _, err := cli.client.Organizations.List(nil)

	if err != nil {
		return nil, err
	}

	for _, org := range orgs {
		projs, _, err := cli.client.Projects.List(*org.Slug, nil)

		if err != nil {
			return nil, err
		}

		projects = append(projects, projs...)
	}

	return projects, nil
}

func newClient(config *config.Config) (*bk.Client, error) {

	if config.OAuthToken == "" {
		err := config.PromptForConfig()
		if err != nil {
			return nil, err
		}
	}

	tconf, err := bk.NewTokenConfig(config.OAuthToken)

	if err != nil {
		return nil, err
	}

	return bk.NewClient(tconf.Client()), nil
}

// ProjectList just get a list of projects
func ProjectList(quietList bool) error {
	cli, err := newBkCli()
	if err != nil {
		return err
	}

	return cli.projectList(quietList)
}

// BuildsList retrieve a list of builds for the current project using the git remote to locate it.
func BuildsList(quietList bool) error {
	cli, err := newBkCli()
	if err != nil {
		return err
	}

	return cli.buildList(quietList)
}

// Open buildkite project for the current project using the git remote to locate it.
func Open() error {
	cli, err := newBkCli()
	if err != nil {
		return err
	}

	return cli.openProjectBuilds()
}

// Setup configure the buildkite cli with a new token.
func Setup() error {
	cli, err := newBkCli()
	if err != nil {
		return err
	}

	return cli.setup()
}

func extractOrg(url string) string {
	m := projectOrgRegex.FindStringSubmatch(url)

	if len(m) == 2 {
		return m[1]
	}

	return ""
}
<|endoftext|>


<commit_before>package commands

var cmdSubmodule = &Command{
	Run:          submodule,
	GitExtension: true,
	Usage:        "submodule add [-p] OPTIONS [USER/]REPOSITORY DIRECTORY",
	Short:        "Initialize, update or inspect submodules",
	Long: `Submodule repository "git://github.com/USER/REPOSITORY.git" into
DIRECTORY as  with  git-submodule(1).  When  USER/  is  omitted,
assumes   your   GitHub  login.  With  -p,  use  private  remote
"git@github.com:USER/REPOSITORY.git".`,
}

func init() {
	CmdRunner.Use(cmdSubmodule)
}

/**
  $ gh submodule add jingweno/gh vendor/gh
  > git submodule add git://github.com/jingweno/gh.git vendor/gh

  $ gh submodule add -p jingweno/gh vendor/gh
  > git submodule add git@github.com:jingweno/gh.git vendor/gh

  $ gh submodule add -b gh --name gh jingweno/gh vendor/gh
  > git submodule add -b gh --name gh git://github.com/jingweno/gh.git vendor/gh
**/

func submodule(command *Command, args *Args) {
	fmt.Println(args)
	if !args.IsParamsEmpty() {
		transformSubmoduleArgs(args)
	}
}

func transformSubmoduleArgs(args *Args) {
	var idx int
	if idx = args.IndexOfParam("add"); idx == -1 {
		fmt.Println("`add` not found, skipping")
		return
	}
	fmt.Println("`add` found")
	args.RemoveParam(idx)
	transformCloneArgs(args)
	args.InsertParam(idx, "add")
	fmt.Println(args)
}
<commit_msg>Import fmt.<commit_after>package commands

import "fmt"

var cmdSubmodule = &Command{
	Run:          submodule,
	GitExtension: true,
	Usage:        "submodule add [-p] OPTIONS [USER/]REPOSITORY DIRECTORY",
	Short:        "Initialize, update or inspect submodules",
	Long: `Submodule repository "git://github.com/USER/REPOSITORY.git" into
DIRECTORY as  with  git-submodule(1).  When  USER/  is  omitted,
assumes   your   GitHub  login.  With  -p,  use  private  remote
"git@github.com:USER/REPOSITORY.git".`,
}

func init() {
	CmdRunner.Use(cmdSubmodule)
}

/**
  $ gh submodule add jingweno/gh vendor/gh
  > git submodule add git://github.com/jingweno/gh.git vendor/gh

  $ gh submodule add -p jingweno/gh vendor/gh
  > git submodule add git@github.com:jingweno/gh.git vendor/gh

  $ gh submodule add -b gh --name gh jingweno/gh vendor/gh
  > git submodule add -b gh --name gh git://github.com/jingweno/gh.git vendor/gh
**/

func submodule(command *Command, args *Args) {
	fmt.Println(args)
	if !args.IsParamsEmpty() {
		transformSubmoduleArgs(args)
	}
}

func transformSubmoduleArgs(args *Args) {
	var idx int
	if idx = args.IndexOfParam("add"); idx == -1 {
		fmt.Println("`add` not found, skipping")
		return
	}
	fmt.Println("`add` found")
	args.RemoveParam(idx)
	transformCloneArgs(args)
	args.InsertParam(idx, "add")
	fmt.Println(args)
}
<|endoftext|>


<commit_before>package crypto

import (
	"crypto/cipher"
	"crypto/rand"
	"io"

	"v2ray.com/core/common"
	"v2ray.com/core/common/buf"
	"v2ray.com/core/common/protocol"
)

type BytesGenerator func() []byte

func GenerateEmptyBytes() BytesGenerator {
	var b [1]byte
	return func() []byte {
		return b[:0]
	}
}

func GenerateStaticBytes(content []byte) BytesGenerator {
	return func() []byte {
		return content
	}
}

func GenerateIncreasingNonce(nonce []byte) BytesGenerator {
	c := append([]byte(nil), nonce...)
	return func() []byte {
		for i := range c {
			c[i]++
			if c[i] != 0 {
				break
			}
		}
		return c
	}
}

func GenerateInitialAEADNonce() BytesGenerator {
	return GenerateIncreasingNonce([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
}

type Authenticator interface {
	NonceSize() int
	Overhead() int
	Open(dst, cipherText []byte) ([]byte, error)
	Seal(dst, plainText []byte) ([]byte, error)
}

type AEADAuthenticator struct {
	cipher.AEAD
	NonceGenerator          BytesGenerator
	AdditionalDataGenerator BytesGenerator
}

func (v *AEADAuthenticator) Open(dst, cipherText []byte) ([]byte, error) {
	iv := v.NonceGenerator()
	if len(iv) != v.AEAD.NonceSize() {
		return nil, newError("invalid AEAD nonce size: ", len(iv))
	}

	var additionalData []byte
	if v.AdditionalDataGenerator != nil {
		additionalData = v.AdditionalDataGenerator()
	}
	return v.AEAD.Open(dst, iv, cipherText, additionalData)
}

func (v *AEADAuthenticator) Seal(dst, plainText []byte) ([]byte, error) {
	iv := v.NonceGenerator()
	if len(iv) != v.AEAD.NonceSize() {
		return nil, newError("invalid AEAD nonce size: ", len(iv))
	}

	var additionalData []byte
	if v.AdditionalDataGenerator != nil {
		additionalData = v.AdditionalDataGenerator()
	}
	return v.AEAD.Seal(dst, iv, plainText, additionalData), nil
}

type AuthenticationReader struct {
	auth         Authenticator
	reader       *buf.BufferedReader
	sizeParser   ChunkSizeDecoder
	transferType protocol.TransferType
	padding      PaddingLengthGenerator
	size         int32
	paddingLen   int32
}

func NewAuthenticationReader(auth Authenticator, sizeParser ChunkSizeDecoder, reader io.Reader, transferType protocol.TransferType, paddingLen PaddingLengthGenerator) *AuthenticationReader {
	return &AuthenticationReader{
		auth:         auth,
		reader:       &buf.BufferedReader{Reader: buf.NewReader(reader)},
		sizeParser:   sizeParser,
		transferType: transferType,
		padding:      paddingLen,
		size:         -1,
	}
}

func (r *AuthenticationReader) readSize() (int32, int32, error) {
	if r.size != -1 {
		s := r.size
		r.size = -1
		return s, r.paddingLen, nil
	}
	sizeBytes := make([]byte, r.sizeParser.SizeBytes())
	if _, err := io.ReadFull(r.reader, sizeBytes); err != nil {
		return 0, 0, err
	}
	var padding int32
	if r.padding != nil {
		padding = int32(r.padding.NextPaddingLen())
	}
	size, err := r.sizeParser.Decode(sizeBytes)
	return int32(size), padding, err
}

var errSoft = newError("waiting for more data")

func (r *AuthenticationReader) readInternal(soft bool) (*buf.Buffer, error) {
	if soft && r.reader.BufferedBytes() < r.sizeParser.SizeBytes() {
		return nil, errSoft
	}

	size, padding, err := r.readSize()
	if err != nil {
		return nil, err
	}

	if size == -2 || size == int32(r.auth.Overhead())+padding {
		r.size = -2
		return nil, io.EOF
	}

	if soft && size > r.reader.BufferedBytes() {
		r.size = size
		r.paddingLen = padding
		return nil, errSoft
	}

	b := buf.NewSize(size)
	if err := b.Reset(buf.ReadFullFrom(r.reader, size)); err != nil {
		b.Release()
		return nil, err
	}

	size -= padding

	rb, err := r.auth.Open(b.BytesTo(0), b.BytesTo(size))
	if err != nil {
		b.Release()
		return nil, err
	}
	b.Resize(0, int32(len(rb)))

	return b, nil
}

func (r *AuthenticationReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
	b, err := r.readInternal(false)
	if err != nil {
		return nil, err
	}

	mb := buf.NewMultiBufferCap(32)
	mb.Append(b)

	for {
		b, err := r.readInternal(true)
		if err == errSoft || err == io.EOF {
			break
		}
		if err != nil {
			mb.Release()
			return nil, err
		}
		mb.Append(b)
	}

	return mb, nil
}

type AuthenticationWriter struct {
	auth         Authenticator
	writer       buf.Writer
	sizeParser   ChunkSizeEncoder
	transferType protocol.TransferType
	padding      PaddingLengthGenerator
}

func NewAuthenticationWriter(auth Authenticator, sizeParser ChunkSizeEncoder, writer io.Writer, transferType protocol.TransferType, padding PaddingLengthGenerator) *AuthenticationWriter {
	return &AuthenticationWriter{
		auth:         auth,
		writer:       buf.NewWriter(writer),
		sizeParser:   sizeParser,
		transferType: transferType,
		padding:      padding,
	}
}

func (w *AuthenticationWriter) seal(b *buf.Buffer) (*buf.Buffer, error) {
	encryptedSize := int(b.Len()) + w.auth.Overhead()
	paddingSize := 0
	if w.padding != nil {
		paddingSize = int(w.padding.NextPaddingLen())
	}

	eb := buf.New()
	common.Must(eb.Reset(func(bb []byte) (int, error) {
		w.sizeParser.Encode(uint16(encryptedSize+paddingSize), bb[:0])
		return int(w.sizeParser.SizeBytes()), nil
	}))
	if err := eb.AppendSupplier(func(bb []byte) (int, error) {
		_, err := w.auth.Seal(bb[:0], b.Bytes())
		return encryptedSize, err
	}); err != nil {
		eb.Release()
		return nil, err
	}
	if paddingSize > 0 {
		if err := eb.AppendSupplier(func(bb []byte) (int, error) {
			common.Must2(rand.Read(bb[:paddingSize]))
			return paddingSize, nil
		}); err != nil {
			eb.Release()
			return nil, err
		}
	}

	return eb, nil
}

func (w *AuthenticationWriter) writeStream(mb buf.MultiBuffer) error {
	defer mb.Release()

	var maxPadding int32
	if w.padding != nil {
		maxPadding = int32(w.padding.MaxPaddingLen())
	}

	payloadSize := buf.Size - int32(w.auth.Overhead()) - w.sizeParser.SizeBytes() - maxPadding
	mb2Write := buf.NewMultiBufferCap(int32(len(mb) + 10))

	for {
		b := buf.New()
		common.Must(b.Reset(func(bb []byte) (int, error) {
			return mb.Read(bb[:payloadSize])
		}))
		eb, err := w.seal(b)
		b.Release()

		if err != nil {
			mb2Write.Release()
			return err
		}
		mb2Write.Append(eb)
		if mb.IsEmpty() {
			break
		}
	}

	return w.writer.WriteMultiBuffer(mb2Write)
}

func (w *AuthenticationWriter) writePacket(mb buf.MultiBuffer) error {
	defer mb.Release()

	mb2Write := buf.NewMultiBufferCap(int32(len(mb)) + 1)

	for !mb.IsEmpty() {
		b := mb.SplitFirst()
		if b == nil {
			continue
		}
		eb, err := w.seal(b)
		b.Release()
		if err != nil {
			mb2Write.Release()
			return err
		}
		mb2Write.Append(eb)
	}

	return w.writer.WriteMultiBuffer(mb2Write)
}

func (w *AuthenticationWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
	if mb.IsEmpty() {
		b := buf.New()
		defer b.Release()

		eb, _ := w.seal(b)
		return w.writer.WriteMultiBuffer(buf.NewMultiBufferValue(eb))
	}

	if w.transferType == protocol.TransferTypeStream {
		return w.writeStream(mb)
	}

	return w.writePacket(mb)
}
<commit_msg>prepare to remove constructor of AuthenticationReader<commit_after>package crypto

import (
	"crypto/cipher"
	"crypto/rand"
	"io"

	"v2ray.com/core/common"
	"v2ray.com/core/common/buf"
	"v2ray.com/core/common/protocol"
)

type BytesGenerator func() []byte

func GenerateEmptyBytes() BytesGenerator {
	var b [1]byte
	return func() []byte {
		return b[:0]
	}
}

func GenerateStaticBytes(content []byte) BytesGenerator {
	return func() []byte {
		return content
	}
}

func GenerateIncreasingNonce(nonce []byte) BytesGenerator {
	c := append([]byte(nil), nonce...)
	return func() []byte {
		for i := range c {
			c[i]++
			if c[i] != 0 {
				break
			}
		}
		return c
	}
}

func GenerateInitialAEADNonce() BytesGenerator {
	return GenerateIncreasingNonce([]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF})
}

type Authenticator interface {
	NonceSize() int
	Overhead() int
	Open(dst, cipherText []byte) ([]byte, error)
	Seal(dst, plainText []byte) ([]byte, error)
}

type AEADAuthenticator struct {
	cipher.AEAD
	NonceGenerator          BytesGenerator
	AdditionalDataGenerator BytesGenerator
}

func (v *AEADAuthenticator) Open(dst, cipherText []byte) ([]byte, error) {
	iv := v.NonceGenerator()
	if len(iv) != v.AEAD.NonceSize() {
		return nil, newError("invalid AEAD nonce size: ", len(iv))
	}

	var additionalData []byte
	if v.AdditionalDataGenerator != nil {
		additionalData = v.AdditionalDataGenerator()
	}
	return v.AEAD.Open(dst, iv, cipherText, additionalData)
}

func (v *AEADAuthenticator) Seal(dst, plainText []byte) ([]byte, error) {
	iv := v.NonceGenerator()
	if len(iv) != v.AEAD.NonceSize() {
		return nil, newError("invalid AEAD nonce size: ", len(iv))
	}

	var additionalData []byte
	if v.AdditionalDataGenerator != nil {
		additionalData = v.AdditionalDataGenerator()
	}
	return v.AEAD.Seal(dst, iv, plainText, additionalData), nil
}

type AuthenticationReader struct {
	auth         Authenticator
	reader       *buf.BufferedReader
	sizeParser   ChunkSizeDecoder
	transferType protocol.TransferType
	padding      PaddingLengthGenerator
	size         uint16
	paddingLen   uint16
	hasSize      bool
	done         bool
}

func NewAuthenticationReader(auth Authenticator, sizeParser ChunkSizeDecoder, reader io.Reader, transferType protocol.TransferType, paddingLen PaddingLengthGenerator) *AuthenticationReader {
	return &AuthenticationReader{
		auth:         auth,
		reader:       &buf.BufferedReader{Reader: buf.NewReader(reader)},
		sizeParser:   sizeParser,
		transferType: transferType,
		padding:      paddingLen,
	}
}

func (r *AuthenticationReader) readSize() (uint16, uint16, error) {
	if r.hasSize {
		r.hasSize = false
		return r.size, r.paddingLen, nil
	}
	sizeBytes := make([]byte, r.sizeParser.SizeBytes())
	if _, err := io.ReadFull(r.reader, sizeBytes); err != nil {
		return 0, 0, err
	}
	var padding uint16
	if r.padding != nil {
		padding = r.padding.NextPaddingLen()
	}
	size, err := r.sizeParser.Decode(sizeBytes)
	return size, padding, err
}

var errSoft = newError("waiting for more data")

func (r *AuthenticationReader) readInternal(soft bool) (*buf.Buffer, error) {
	if soft && r.reader.BufferedBytes() < r.sizeParser.SizeBytes() {
		return nil, errSoft
	}

	if r.done {
		return nil, io.EOF
	}

	size, padding, err := r.readSize()
	if err != nil {
		return nil, err
	}

	if size == uint16(r.auth.Overhead())+padding {
		r.done = true
		return nil, io.EOF
	}

	if soft && int32(size) > r.reader.BufferedBytes() {
		r.size = size
		r.paddingLen = padding
		r.hasSize = true
		return nil, errSoft
	}

	b := buf.NewSize(int32(size))
	if err := b.Reset(buf.ReadFullFrom(r.reader, int32(size))); err != nil {
		b.Release()
		return nil, err
	}

	size -= padding

	rb, err := r.auth.Open(b.BytesTo(0), b.BytesTo(int32(size)))
	if err != nil {
		b.Release()
		return nil, err
	}
	b.Resize(0, int32(len(rb)))

	return b, nil
}

func (r *AuthenticationReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
	b, err := r.readInternal(false)
	if err != nil {
		return nil, err
	}

	mb := buf.NewMultiBufferCap(32)
	mb.Append(b)

	for {
		b, err := r.readInternal(true)
		if err == errSoft || err == io.EOF {
			break
		}
		if err != nil {
			mb.Release()
			return nil, err
		}
		mb.Append(b)
	}

	return mb, nil
}

type AuthenticationWriter struct {
	auth         Authenticator
	writer       buf.Writer
	sizeParser   ChunkSizeEncoder
	transferType protocol.TransferType
	padding      PaddingLengthGenerator
}

func NewAuthenticationWriter(auth Authenticator, sizeParser ChunkSizeEncoder, writer io.Writer, transferType protocol.TransferType, padding PaddingLengthGenerator) *AuthenticationWriter {
	return &AuthenticationWriter{
		auth:         auth,
		writer:       buf.NewWriter(writer),
		sizeParser:   sizeParser,
		transferType: transferType,
		padding:      padding,
	}
}

func (w *AuthenticationWriter) seal(b *buf.Buffer) (*buf.Buffer, error) {
	encryptedSize := int(b.Len()) + w.auth.Overhead()
	paddingSize := 0
	if w.padding != nil {
		paddingSize = int(w.padding.NextPaddingLen())
	}

	eb := buf.New()
	common.Must(eb.Reset(func(bb []byte) (int, error) {
		w.sizeParser.Encode(uint16(encryptedSize+paddingSize), bb[:0])
		return int(w.sizeParser.SizeBytes()), nil
	}))
	if err := eb.AppendSupplier(func(bb []byte) (int, error) {
		_, err := w.auth.Seal(bb[:0], b.Bytes())
		return encryptedSize, err
	}); err != nil {
		eb.Release()
		return nil, err
	}
	if paddingSize > 0 {
		if err := eb.AppendSupplier(func(bb []byte) (int, error) {
			common.Must2(rand.Read(bb[:paddingSize]))
			return paddingSize, nil
		}); err != nil {
			eb.Release()
			return nil, err
		}
	}

	return eb, nil
}

func (w *AuthenticationWriter) writeStream(mb buf.MultiBuffer) error {
	defer mb.Release()

	var maxPadding int32
	if w.padding != nil {
		maxPadding = int32(w.padding.MaxPaddingLen())
	}

	payloadSize := buf.Size - int32(w.auth.Overhead()) - w.sizeParser.SizeBytes() - maxPadding
	mb2Write := buf.NewMultiBufferCap(int32(len(mb) + 10))

	for {
		b := buf.New()
		common.Must(b.Reset(func(bb []byte) (int, error) {
			return mb.Read(bb[:payloadSize])
		}))
		eb, err := w.seal(b)
		b.Release()

		if err != nil {
			mb2Write.Release()
			return err
		}
		mb2Write.Append(eb)
		if mb.IsEmpty() {
			break
		}
	}

	return w.writer.WriteMultiBuffer(mb2Write)
}

func (w *AuthenticationWriter) writePacket(mb buf.MultiBuffer) error {
	defer mb.Release()

	mb2Write := buf.NewMultiBufferCap(int32(len(mb)) + 1)

	for !mb.IsEmpty() {
		b := mb.SplitFirst()
		if b == nil {
			continue
		}
		eb, err := w.seal(b)
		b.Release()
		if err != nil {
			mb2Write.Release()
			return err
		}
		mb2Write.Append(eb)
	}

	return w.writer.WriteMultiBuffer(mb2Write)
}

func (w *AuthenticationWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
	if mb.IsEmpty() {
		b := buf.New()
		defer b.Release()

		eb, _ := w.seal(b)
		return w.writer.WriteMultiBuffer(buf.NewMultiBufferValue(eb))
	}

	if w.transferType == protocol.TransferTypeStream {
		return w.writeStream(mb)
	}

	return w.writePacket(mb)
}
<|endoftext|>


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

import (
	"errors"
)

type Result struct {
	rowCount int64
}

func (r *Result) LastInsertId() (int64, error) {
	// TODO(brainman): implement (*Resilt).LastInsertId
	return 0, errors.New("not implemented")
}

func (r *Result) RowsAffected() (int64, error) {
	return r.rowCount, nil
}
<commit_msg>result: fix typo<commit_after>// Copyright 2012 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 odbc

import (
	"errors"
)

type Result struct {
	rowCount int64
}

func (r *Result) LastInsertId() (int64, error) {
	// TODO(brainman): implement (*Result).LastInsertId
	return 0, errors.New("not implemented")
}

func (r *Result) RowsAffected() (int64, error) {
	return r.rowCount, nil
}
<|endoftext|>


<commit_before>package main

import (
  "net/http"
  "github.com/pilu/traffic"
  "fmt"
)

func rootHandler(r http.ResponseWriter, req *http.Request) {
  fmt.Fprint(r, "Hello World")
}

func pageHandler(r http.ResponseWriter, req *http.Request) {
  params := req.URL.Query()
  fmt.Fprintf(r, "Category ID: %s\n", params.Get("category_id"))
  fmt.Fprintf(r, "Page ID: %s\n", params.Get("id"))
}

func main() {
  router := traffic.New()
  router.Get("/", rootHandler)
  router.Get("/categories/:category_id/pages/:id", pageHandler)

  http.Handle("/", router)
  http.ListenAndServe(":7000", nil)
}
<commit_msg>more examples on BeforeFilter and NotFoundHandler<commit_after>package main

import (
  "net/http"
  "github.com/pilu/traffic"
  "fmt"
)

func rootHandler(w http.ResponseWriter, r *http.Request) {
  fmt.Fprint(w, "Hello World\n")
}

func pageHandler(w http.ResponseWriter, r *http.Request) {
  params := r.URL.Query()
  fmt.Fprintf(w, "Category ID: %s\n", params.Get("category_id"))
  fmt.Fprintf(w, "Page ID: %s\n", params.Get("id"))
}

func customNotFoundHandler(w http.ResponseWriter, r *http.Request) {
  w.WriteHeader(http.StatusNotFound)
  fmt.Fprintf(w, "Page not found: %s\n", r.URL.Path)
}

func customBeforeFilter(w http.ResponseWriter, r *http.Request) {
  w.Header().Add("X-APP-NAME", "My App")
}

func main() {
  router := traffic.New()
  router.Get("/", rootHandler)
  router.Get("/categories/:category_id/pages/:id", pageHandler)
  router.NotFoundHandler = customNotFoundHandler
  router.BeforeFilter = customBeforeFilter

  http.Handle("/", router)
  http.ListenAndServe(":7000", nil)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/adityashedge/go-verifalia/verifalia"
)

func main() {
	// add a valid account subscription ID and auth token(or sub-account password)
	c := verifalia.NewClient("Account SID", "Auth Token")
	emails := []string{"john.smith@example.com", "foo@example.net"}
	resp, err := c.Validate(emails)
	if err != nil {
		panic(err)
	} else {
		fmt.Printf("Response:\t%+v\n", resp)
		fmt.Printf("Server response:\t%+v\n", resp.Data)
	}
}
<commit_msg>Ref #4 Updated example for API to get the status of an email validation job<commit_after>package main

import (
	"fmt"

	"github.com/adityashedge/go-verifalia/verifalia"
)

func main() {
	// add a valid account subscription ID and auth token(or sub-account password)
	c := verifalia.NewClient("Account SID", "Auth Token")

	emails := []string{"john.smith@example.com", "foo@example.net"}

	fmt.Println("-------------> Validate")
	resp, err := c.Validate(emails)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Response:\t%+v\n", resp)
	fmt.Printf("Server response:\t%+v\n", resp.Data)

	fmt.Println("-------------> Query")
	resp, err := c.Query(resp.UniqueID)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Response:\t%+v\n", resp)
	fmt.Printf("Server response:\t%+v\n", resp.Data)
}
<|endoftext|>


<commit_before>package baja

import (
	"log"

	//"bytes"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/russross/blackfriday"
	"gopkg.in/yaml.v2"
)

//TODO Move theme reference to config with DI
func Compile(source string) error {
	page := buildPage()

	createRSS(page)
	createHome(page)
	createIssues(page)

	CopyDir("themes/yeo/assets", "public/assets")
	CopyDir("static/", "public/")

	return nil
}

func createRSS(page Page) {
	f, err := os.Create("./public/rss.xml")
	if err != nil {
		log.Println("Error creating file", err)
	}

	var publicableIssue Issues
	for i := len(page.Issues) - 1; i >= 0; i-- {
		issue := page.Issues[i]
		if issue.Draft == false {
			publicableIssue = append(publicableIssue, issue)
		}
	}
	page.Issues = publicableIssue

	funcMap := template.FuncMap{
		"attr": func(s string) template.HTMLAttr {
			return template.HTMLAttr(s)
		},
		"safe": func(s string) template.HTML {
			return template.HTML(s)
		},
	}

	t := template.Must(template.New("").Funcs(funcMap).ParseFiles("themes/yeo/rss.tmpl"))
	if err := t.ExecuteTemplate(f, "base", &page); err != nil {
		log.Fatal(err)
	}
}
func createHome(page Page) {
	t, err := template.ParseFiles("themes/yeo/layout.tmpl", "themes/yeo/index.tmpl")
	if err != nil {
		log.Fatal(err)
	}

	f, err := os.Create("./public/index.html")
	if err != nil {
		log.Println("Error creating file", err)
	}

	//var tpl bytes.Buffer
	if err := t.ExecuteTemplate(f, "base", &page); err != nil {
		log.Fatal(err)
	}
}

func createIssue(layout string, issue Issue) {
	t, err := template.ParseFiles("themes/yeo/"+layout+".tmpl", "themes/yeo/issue.tmpl")
	if err != nil {
		log.Fatal(err)
	}

	directory := "./public/issues/" + issue.Name
	if issue.Draft == true {
		directory = "./public/issues/" + issue.Name + "/draft"
	}

	if layout == "email" {
		directory = "./public/issues/" + issue.Name + "/email"
	}
	os.MkdirAll(directory, 0755)

	f, err := os.Create(directory + "/index.html")
	if err != nil {
		log.Fatalf("Error creating file", err)
	}

	page := &Page{
		Time:  time.Now(),
		Issue: issue,
	}
	//var tpl bytes.Buffer
	if err := t.ExecuteTemplate(f, "base", &page); err != nil {
		log.Fatal(err)
	}

}

func buildPage() Page {
	page := Page{
		Time: time.Now(),
	}

	var issues []Issue
	files, _ := ioutil.ReadDir("./content/issues/")
	for _, f := range files {
		if strings.HasSuffix(f.Name(), ".yml") {
			if issue, err := loadIssue(f); err == nil {
				issues = append(issues, issue)
			}
		}
	}

	// Sort Issue
	sort.Sort(Issues(issues))

	page.Issues = issues
	for k := len(page.Issues) - 1; k >= 0; k-- {
		page.Issue = page.Issues[k]
		if page.Issue.Draft == false {
			break
		}
	}
	return page
}

func createIssues(page Page) {
	t, err := template.ParseFiles("themes/yeo/layout.tmpl", "themes/yeo/issues.tmpl")
	if err != nil {
		log.Fatal(err)
	}

	os.Mkdir("./public/issues", 0755)
	f, err := os.Create("./public/issues/index.html")
	if err != nil {
		log.Println("Error creating file", err)
	}

	var publicableIssue Issues
	//for _, issue := range page.Issues {
	for i := len(page.Issues) - 1; i >= 0; i-- {
		issue := page.Issues[i]
		if issue.Draft == false {
			publicableIssue = append(publicableIssue, issue)
		}

		createIssue("layout", issue)
		createIssue("email", issue)
	}

	//var tpl bytes.Buffer
	page.Issues = publicableIssue
	if err := t.ExecuteTemplate(f, "base", &page); err != nil {
		log.Fatal(err)
	}
}

func loadIssue(f os.FileInfo) (Issue, error) {
	name := strings.Split(f.Name(), ".")
	issue := Issue{
		Name: name[0],
	}

	data, err := ioutil.ReadFile("./content/issues/" + f.Name())
	if err != nil {
		log.Fatal("Fail to parse issue", f.Name(), err)
		return issue, err
	}

	err = yaml.Unmarshal([]byte(data), &issue)
	if err != nil {
		log.Println("Error unmarshal yaml of issue", issue.Name, err)
	}

	//Thu, 06 Jul 2017 17:42:26 +0000
	if issue.PubTime, err = time.Parse("Jan 2, 2006 15:04:05 -0700", issue.Time+" 05:19:00 -0700"); err != nil {
		log.Println("Cannot parse time on issue ", name, issue.Name, issue.Time, err)
	}

	issue.Description = template.HTML(string(blackfriday.Run([]byte(issue.Description))))

	if issue.Links != nil {
		for i := range issue.Links {
			issue.Links[i].Description = template.HTML(string(blackfriday.Run([]byte(issue.Links[i].Description))))
		}
	}

	for i := range issue.Tools {
		issue.Tools[i].Description = template.HTML(string(blackfriday.Run([]byte(issue.Tools[i].Description))))
	}

	for i := range issue.Briefs {
		issue.Briefs[i].Description = template.HTML(string(blackfriday.Run([]byte(issue.Briefs[i].Description))))
	}

	for i := range issue.CodeToRead {
		issue.CodeToRead[i].Description = template.HTML(string(blackfriday.Run([]byte(issue.CodeToRead[i].Description))))
	}

	for i := range issue.Videos {
		issue.Videos[i].Description = template.HTML(string(blackfriday.Run([]byte(issue.Videos[i].Description))))
	}

	return issue, nil
}

func CopyFile(src, dst string) (err error) {
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()

	out, err := os.Create(dst)
	if err != nil {
		return
	}
	defer func() {
		if e := out.Close(); e != nil {
			err = e
		}
	}()

	_, err = io.Copy(out, in)
	if err != nil {
		return
	}

	err = out.Sync()
	if err != nil {
		return
	}

	si, err := os.Stat(src)
	if err != nil {
		return
	}
	err = os.Chmod(dst, si.Mode())
	if err != nil {
		return
	}

	return
}

// CopyDir recursively copies a directory tree, attempting to preserve permissions.
// Source directory must exist, destination directory must *not* exist.
// Symlinks are ignored and skipped.
func CopyDir(src string, dst string) (err error) {
	src = filepath.Clean(src)
	dst = filepath.Clean(dst)

	si, err := os.Stat(src)
	if err != nil {
		return err
	}
	if !si.IsDir() {
		return fmt.Errorf("source is not a directory")
	}

	_, err = os.Stat(dst)
	if err != nil && !os.IsNotExist(err) {
		return
	}
	//if err == nil {
	//		return fmt.Errorf("destination already exists")
	//}

	err = os.MkdirAll(dst, si.Mode())
	if err != nil {
		return
	}

	entries, err := ioutil.ReadDir(src)
	if err != nil {
		return
	}

	for _, entry := range entries {
		srcPath := filepath.Join(src, entry.Name())
		dstPath := filepath.Join(dst, entry.Name())

		if entry.IsDir() {
			err = CopyDir(srcPath, dstPath)
			if err != nil {
				return
			}
		} else {
			// Skip symlinks.
			if entry.Mode()&os.ModeSymlink != 0 {
				continue
			}

			err = CopyFile(srcPath, dstPath)
			if err != nil {
				return
			}
		}
	}

	return
}
<commit_msg>Cleanup<commit_after>package baja

import (
	"log"

	//"bytes"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/russross/blackfriday"
	"gopkg.in/yaml.v2"
)

//TODO Move theme reference to config with DI
func Compile(source string) error {
	page := buildPage()

	createRSS(page)
	createHome(page)
	createIssues(page)

	CopyDir("themes/yeo/assets", "public/assets")
	CopyDir("static/", "public/")

	return nil
}

func createRSS(page Page) {
	f, err := os.Create("./public/rss.xml")
	if err != nil {
		log.Println("Error creating file", err)
	}

	var publicableIssue Issues
	for i := len(page.Issues) - 1; i >= 0; i-- {
		issue := page.Issues[i]
		if issue.Draft == false {
			publicableIssue = append(publicableIssue, issue)
		}
	}
	page.Issues = publicableIssue

	funcMap := template.FuncMap{
		"attr": func(s string) template.HTMLAttr {
			return template.HTMLAttr(s)
		},
		"safe": func(s string) template.HTML {
			return template.HTML(s)
		},
	}

	t := template.Must(template.New("").Funcs(funcMap).ParseFiles("themes/yeo/rss.tmpl"))
	if err := t.ExecuteTemplate(f, "base", &page); err != nil {
		log.Fatal(err)
	}
}
func createHome(page Page) {
	t, err := template.ParseFiles("themes/yeo/layout.tmpl", "themes/yeo/index.tmpl")
	if err != nil {
		log.Fatal(err)
	}

	f, err := os.Create("./public/index.html")
	if err != nil {
		log.Println("Error creating file", err)
	}

	//var tpl bytes.Buffer
	if err := t.ExecuteTemplate(f, "base", &page); err != nil {
		log.Fatal(err)
	}
}

func createIssue(layout string, issue Issue) {
	t, err := template.ParseFiles("themes/yeo/"+layout+".tmpl", "themes/yeo/issue.tmpl")
	if err != nil {
		log.Fatal(err)
	}

	directory := "./public/issues/" + issue.Name
	if issue.Draft == true {
		directory = "./public/issues/" + issue.Name + "/draft"
	}

	if layout == "email" {
		directory = "./public/issues/" + issue.Name + "/email"
	}
	os.MkdirAll(directory, 0755)

	f, err := os.Create(directory + "/index.html")
	if err != nil {
		log.Fatalf("Error creating file", err)
	}

	page := &Page{
		Time:  time.Now(),
		Issue: issue,
	}
	//var tpl bytes.Buffer
	if err := t.ExecuteTemplate(f, "base", &page); err != nil {
		log.Fatal(err)
	}

}

func buildPage() Page {
	page := Page{
		Time: time.Now(),
	}

	var issues []Issue
	files, _ := ioutil.ReadDir("./content/issues/")
	for _, f := range files {
		if strings.HasSuffix(f.Name(), ".yml") {
			if issue, err := loadIssue(f); err == nil {
				issues = append(issues, issue)
			}
		}
	}

	// Sort Issue
	sort.Sort(Issues(issues))

	page.Issues = issues
	for k := len(page.Issues) - 1; k >= 0; k-- {
		page.Issue = page.Issues[k]
		if page.Issue.Draft == false {
			break
		}
	}
	return page
}

func createIssues(page Page) {
	t, err := template.ParseFiles("themes/yeo/layout.tmpl", "themes/yeo/issues.tmpl")
	if err != nil {
		log.Fatal(err)
	}

	os.Mkdir("./public/issues", 0755)
	f, err := os.Create("./public/issues/index.html")
	if err != nil {
		log.Println("Error creating file", err)
	}

	var publicableIssue Issues
	for i := len(page.Issues) - 1; i >= 0; i-- {
		issue := page.Issues[i]
		if issue.Draft == false {
			publicableIssue = append(publicableIssue, issue)
		}

		createIssue("layout", issue)
		createIssue("email", issue)
	}

	//var tpl bytes.Buffer
	page.Issues = publicableIssue
	if err := t.ExecuteTemplate(f, "base", &page); err != nil {
		log.Fatal(err)
	}
}

func loadIssue(f os.FileInfo) (Issue, error) {
	name := strings.Split(f.Name(), ".")
	issue := Issue{
		Name: name[0],
	}

	data, err := ioutil.ReadFile("./content/issues/" + f.Name())
	if err != nil {
		log.Fatal("Fail to parse issue", f.Name(), err)
		return issue, err
	}

	err = yaml.Unmarshal([]byte(data), &issue)
	if err != nil {
		log.Println("Error unmarshal yaml of issue", issue.Name, err)
	}

	//Thu, 06 Jul 2017 17:42:26 +0000
	if issue.PubTime, err = time.Parse("Jan 2, 2006 15:04:05 -0700", issue.Time+" 05:19:00 -0700"); err != nil {
		log.Println("Cannot parse time on issue ", name, issue.Name, issue.Time, err)
	}

	issue.Description = template.HTML(string(blackfriday.Run([]byte(issue.Description))))

	if issue.Links != nil {
		for i := range issue.Links {
			issue.Links[i].Description = template.HTML(string(blackfriday.Run([]byte(issue.Links[i].Description))))
		}
	}

	for i := range issue.Tools {
		issue.Tools[i].Description = template.HTML(string(blackfriday.Run([]byte(issue.Tools[i].Description))))
	}

	for i := range issue.Briefs {
		issue.Briefs[i].Description = template.HTML(string(blackfriday.Run([]byte(issue.Briefs[i].Description))))
	}

	for i := range issue.CodeToRead {
		issue.CodeToRead[i].Description = template.HTML(string(blackfriday.Run([]byte(issue.CodeToRead[i].Description))))
	}

	for i := range issue.Videos {
		issue.Videos[i].Description = template.HTML(string(blackfriday.Run([]byte(issue.Videos[i].Description))))
	}

	return issue, nil
}

func CopyFile(src, dst string) (err error) {
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()

	out, err := os.Create(dst)
	if err != nil {
		return
	}
	defer func() {
		if e := out.Close(); e != nil {
			err = e
		}
	}()

	_, err = io.Copy(out, in)
	if err != nil {
		return
	}

	err = out.Sync()
	if err != nil {
		return
	}

	si, err := os.Stat(src)
	if err != nil {
		return
	}
	err = os.Chmod(dst, si.Mode())
	if err != nil {
		return
	}

	return
}

// CopyDir recursively copies a directory tree, attempting to preserve permissions.
// Source directory must exist, destination directory must *not* exist.
// Symlinks are ignored and skipped.
func CopyDir(src string, dst string) (err error) {
	src = filepath.Clean(src)
	dst = filepath.Clean(dst)

	si, err := os.Stat(src)
	if err != nil {
		return err
	}
	if !si.IsDir() {
		return fmt.Errorf("source is not a directory")
	}

	_, err = os.Stat(dst)
	if err != nil && !os.IsNotExist(err) {
		return
	}
	//if err == nil {
	//		return fmt.Errorf("destination already exists")
	//}

	err = os.MkdirAll(dst, si.Mode())
	if err != nil {
		return
	}

	entries, err := ioutil.ReadDir(src)
	if err != nil {
		return
	}

	for _, entry := range entries {
		srcPath := filepath.Join(src, entry.Name())
		dstPath := filepath.Join(dst, entry.Name())

		if entry.IsDir() {
			err = CopyDir(srcPath, dstPath)
			if err != nil {
				return
			}
		} else {
			// Skip symlinks.
			if entry.Mode()&os.ModeSymlink != 0 {
				continue
			}

			err = CopyFile(srcPath, dstPath)
			if err != nil {
				return
			}
		}
	}

	return
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Alcatel-Lucent Inc.
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
// * Neither the name of bambou nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package bambou

import (
	"fmt"
)

const (
	// ErrorCodeJSONCannotDecode is the code that means it is impossible to
	// decode json data.
	ErrorCodeJSONCannotDecode = 10001

	// ErrorCodeJSONCannotEncode is the code that means it is impossible to
	// encode json data.
	ErrorCodeJSONCannotEncode = 10002

	// ErrorCodeSessionAlreadyStarted is the error code that means a session
	// is already stared.
	ErrorCodeSessionAlreadyStarted = 11001

	// ErrorCodeSessionCannotForgetAuthToken is the code that means no password
	// or token has been given to the session.
	ErrorCodeSessionCannotForgeAuthToken = 11002

	// ErrorCodeSessionCannotProcessRequest is the code that means that it was
	// impossible to process a request.
	ErrorCodeSessionCannotProcessRequest = 11003

	// ErrorCodeSessionIDNotSet is the code that means the Identifiable is
	// missing a required ID.
	ErrorCodeSessionIDNotSet = 11004

	// ErrorCodeSessionUsernameNotSet is the code that means the username
	// is missing.
	ErrorCodeSessionUsernameNotSet = 11005
)

type Errorlist struct {
	Errors       []Error `json:"errors"`
	VsdErrorCode int     `json:"internalErrorCode"`
}

// Error represent an connection error.
type Error struct {
	Code         int                `json:"-"`
	Property     string             `json:"property"`
	Descriptions []ErrorDescription `json:"descriptions"`
}

// ErrorDescription represents an entry in an Error.
type ErrorDescription struct {
	// Title       string `json:"title"`
	Description string `json:"description"`
}

// NewError returns a new *Error.
// You can give a message, that will be used, if no additional
// information is given by the server. Otherwhise Message will be
// overwritten.
func NewError(code int, message string) *Error {
	return &Error{
		Code:     code,
		Property: message,
		// Descriptions:
	}
}

// Error returns the string representation of the Error.
func (e *Error) Error() string {

	return fmt.Sprintf("<Error Code: %d, Error Description: %s>", e.Code, e.Descriptions)
}
<commit_msg>Changes to Error format<commit_after>// Copyright (c) 2015, Alcatel-Lucent Inc.
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
// * Neither the name of bambou nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package bambou

import (
	"fmt"
)

const (
	// ErrorCodeJSONCannotDecode is the code that means it is impossible to
	// decode json data.
	ErrorCodeJSONCannotDecode = 10001

	// ErrorCodeJSONCannotEncode is the code that means it is impossible to
	// encode json data.
	ErrorCodeJSONCannotEncode = 10002

	// ErrorCodeSessionAlreadyStarted is the error code that means a session
	// is already stared.
	ErrorCodeSessionAlreadyStarted = 11001

	// ErrorCodeSessionCannotForgetAuthToken is the code that means no password
	// or token has been given to the session.
	ErrorCodeSessionCannotForgeAuthToken = 11002

	// ErrorCodeSessionCannotProcessRequest is the code that means that it was
	// impossible to process a request.
	ErrorCodeSessionCannotProcessRequest = 11003

	// ErrorCodeSessionIDNotSet is the code that means the Identifiable is
	// missing a required ID.
	ErrorCodeSessionIDNotSet = 11004

	// ErrorCodeSessionUsernameNotSet is the code that means the username
	// is missing.
	ErrorCodeSessionUsernameNotSet = 11005
)

type Errorlist struct {
	Errors       []Error `json:"errors"`
	VsdErrorCode int     `json:"internalErrorCode"`
}

// Error represent a connection error.
type Error struct {
	Code         int                `json:"-"`
	Property     string             `json:"property"`
	Descriptions []ErrorDescription `json:"descriptions"`
}

// ErrorDescription represents an entry in an Error.
type ErrorDescription struct {
	Title       string `json:"title"`
	Description string `json:"description"`
}

// NewError returns a new *Error.
// You can give a message, that will be used, if no additional
// information is given by the server. Otherwhise Message will be
// overwritten.
func NewError(code int, message string) *Error {
	return &Error{
		Code:         code,
		Property:     message,
		Descriptions: []ErrorDescription{{Title: "", Description: ""}},
	}
}

// Error returns the string representation of the Error.
func (e *Error) Error() string {

	return fmt.Sprintf("<Error Code: %d, Error Description: %s>", e.Code, e.Descriptions)
}
<|endoftext|>


<commit_before>package assert

import (
	"strings"
	"testing"
)

func Contains(t *testing.T, st string, subs ...string) {
	for _, s := range subs {
		if !strings.Contains(st, s) {
			t.Logf("'%s' string should have 'contained' %s", st, s)
			t.Fail()
		}
	}
}

func Excludes(t *testing.T, st string, subs ...string) {
	for _, s := range subs {
		if strings.Contains(st, s) {
			t.Logf("'%s' should NOT have 'contained' %s", st, s)
			t.Fail()
		}
	}
}

func IsEmptyString(t Exam, a string) {
	if a == "" {
		return
	}
	t.Logf("'%s' == '' (%t)", a, a == "")
	t.Fail()
}

func IsEqStrings(t Exam, a, b string) {
	if a == b {
		return
	}
	t.Logf("'%s' == '%s' (%t)", a, b, a == b)
	t.Fail()
}
<commit_msg>Adding IsNotEqString<commit_after>package assert

import (
	"strings"
	"testing"
)

func Contains(t *testing.T, st string, subs ...string) {
	for _, s := range subs {
		if !strings.Contains(st, s) {
			t.Logf("'%s' string should have 'contained' %s", st, s)
			t.Fail()
		}
	}
}

func Excludes(t *testing.T, st string, subs ...string) {
	for _, s := range subs {
		if strings.Contains(st, s) {
			t.Logf("'%s' should NOT have 'contained' %s", st, s)
			t.Fail()
		}
	}
}

func IsEmptyString(t Exam, a string) {
	if a == "" {
		return
	}
	t.Logf("'%s' == '' (%t)", a, a == "")
	t.Fail()
}

func IsNotEmptyString(t Exam, a string) {
	if a != "" {
		return
	}
	t.Logf("'%s' != '' (%t)", a, a == "")
	t.Fail()
}

func IsEqStrings(t Exam, a, b string) {
	if a == b {
		return
	}
	t.Logf("'%s' == '%s' (%t)", a, b, a == b)
	t.Fail()
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strings"

	"github.com/rainforestapp/rainforest-cli/rainforest"
	"github.com/urfave/cli"
)

type branchAPI interface {
	GetBranches(...string) ([]rainforest.Branch, error)
	CreateBranch(*rainforest.Branch) error
	MergeBranch(int) error
	DeleteBranch(int) error
}

func newBranch(c cliContext, api branchAPI) error {
	name := c.Args().First()
	name = strings.TrimSpace(name)

	if name == "" {
		return cli.NewExitError("Branch name cannot be blank", 1)
	}

	branch := rainforest.Branch{
		Name: name,
	}

	err := api.CreateBranch(&branch)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	fmt.Printf("Created branch %q.\n", name)
	return nil
}

func mergeBranch(c cliContext, api branchAPI) error {
	name := c.Args().First()
	name = strings.TrimSpace(name)

	if name == "" {
		return cli.NewExitError("Branch name cannot be blank", 1)
	}

	branchID, err := getBranchID(name, api)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	err = api.MergeBranch(branchID)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	fmt.Printf("Merged branch %q into main.\n", name)
	return nil
}

func deleteBranch(c cliContext, api branchAPI) error {
	name := c.Args().First()
	name = strings.TrimSpace(name)

	if name == "" {
		return cli.NewExitError("Branch name cannot be blank", 1)
	}

	branchID, err := getBranchID(name, api)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	err = api.DeleteBranch(branchID)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	fmt.Printf("Deleted branch %q.\n", name)
	return nil
}

// getBranchID gets branchID by using the branch name to query the API
func getBranchID(name string, api branchAPI) (int, error) {
	branches, err := api.GetBranches(name)

	if err != nil {
		return 0, err
	}

	if len(branches) == 0 {
		return 0, errors.New("Cannot find branch")
	}

	branch := branches[0]

	return branch.ID, nil
}
<commit_msg>Extract repeated branch name handling into it's own function<commit_after>package main

import (
	"errors"
	"fmt"
	"strings"

	"github.com/rainforestapp/rainforest-cli/rainforest"
	"github.com/urfave/cli"
)

type branchAPI interface {
	GetBranches(...string) ([]rainforest.Branch, error)
	CreateBranch(*rainforest.Branch) error
	MergeBranch(int) error
	DeleteBranch(int) error
}

func newBranch(c cliContext, api branchAPI) error {
	name, err := getBranchName(c)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	branch := rainforest.Branch{
		Name: name,
	}

	err = api.CreateBranch(&branch)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	fmt.Printf("Created branch %q.\n", name)
	return nil
}

func mergeBranch(c cliContext, api branchAPI) error {
	name, err := getBranchName(c)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	branchID, err := getBranchID(name, api)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	err = api.MergeBranch(branchID)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	fmt.Printf("Merged branch %q into main.\n", name)
	return nil
}

func deleteBranch(c cliContext, api branchAPI) error {
	name, err := getBranchName(c)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	branchID, err := getBranchID(name, api)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	err = api.DeleteBranch(branchID)

	if err != nil {
		return cli.NewExitError(err.Error(), 1)
	}

	fmt.Printf("Deleted branch %q.\n", name)
	return nil
}

// getBranchID gets branchID by using the branch name to query the API
func getBranchID(name string, api branchAPI) (int, error) {
	branches, err := api.GetBranches(name)

	if err != nil {
		return 0, err
	}

	if len(branches) == 0 {
		return 0, errors.New("Cannot find branch")
	}

	branch := branches[0]

	return branch.ID, nil
}

// getBranchName gets branchName from the cli
func getBranchName(c cliContext) (string, error) {
	name := c.Args().First()
	name = strings.TrimSpace(name)

	if name == "" {
		return "", errors.New("Branch name cannot be blank")
	}

	return name, nil
}
<|endoftext|>


<commit_before>package data

import (
	cmn "github.com/RxnWeaver/rxnweaver/common"
)

// Ring represents a simple cycle in a molecule.
//
// A ring holds information of the atoms and the bonds it comprises.
// It also knows its neighbouring rings.
//
// Rings are supposed to be immutable: once completed, their
// composition should never change.
type Ring struct {
	mol  *Molecule // Containing molecule of this ring.
	id   uint8     // A unique identifier for this ring.
	rsId uint8     // ID of the ring system to which this ring belongs.

	atoms []uint16 // List of atoms participating in this ring.
	bonds []uint16 // List of bonds participating in this ring.
	nbrs  []uint8  // List of rings neighbouring this ring.

	isAro    bool // Is this ring aromatic?
	isHetAro bool // Is this an aromatic ring with at least one hetero atom?

	isComplete bool // Has this ring been finalised?
}

// newRing creates and initialises a new ring.
func newRing(mol *Molecule) {
	r := new(Ring)
	r.mol = mol

	r.atoms = make([]uint16, 0, cmn.ListSizeSmall)
	r.bonds = make([]uint16, 0, cmn.ListSizeSmall)
	r.nbrs = make([]uint8, 0, cmn.ListSizeSmall)
}

// size answers the size of this ring.  It is equivalently the number
// of atoms or the number of bonds participating in this ring.
func (r *Ring) size() int {
	return len(r.atoms)
}
<commit_msg>Add `github.com/willf/bitset` as a dependency<commit_after>package data

import (
	bits "github.com/willf/bitset"

	cmn "github.com/RxnWeaver/rxnweaver/common"
)

// Ring represents a simple cycle in a molecule.
//
// A ring holds information of the atoms and the bonds it comprises.
// It also knows its neighbouring rings.
//
// Rings are supposed to be immutable: once completed, their
// composition should never change.
type Ring struct {
	mol  *Molecule // Containing molecule of this ring.
	id   uint8     // A unique identifier for this ring.
	rsId uint8     // ID of the ring system to which this ring belongs.

	atoms []uint16 // List of atoms participating in this ring.
	bonds []uint16 // List of bonds participating in this ring.
	nbrs  []uint8  // List of rings neighbouring this ring.

	atomBitSet *bits.BitSet // For faster comparison.
	bondBitSet *bits.BitSet // For faster comparison.

	isAro    bool // Is this ring aromatic?
	isHetAro bool // Is this an aromatic ring with at least one hetero atom?

	isComplete bool // Has this ring been finalised?
}

// newRing creates and initialises a new ring.
func newRing(mol *Molecule) {
	r := new(Ring)
	r.mol = mol

	r.atoms = make([]uint16, 0, cmn.ListSizeSmall)
	r.bonds = make([]uint16, 0, cmn.ListSizeSmall)
	r.nbrs = make([]uint8, 0, cmn.ListSizeSmall)
}

// size answers the size of this ring.  It is equivalently the number
// of atoms or the number of bonds participating in this ring.
func (r *Ring) size() int {
	return len(r.atoms)
}
<|endoftext|>


<commit_before>// Binary attest-tool performs attestation operations on the local system.
package main

import (
	"crypto/rand"
	"encoding/hex"
	"flag"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/google/go-attestation/attest"
	"github.com/google/go-tpm/tpm2"
)

var (
	keyPath     = flag.String("key", "aik.json", "Path to the key file")
	nonceHex    = flag.String("nonce", "", "Hex string to use as nonce when quoting")
	randomNonce = flag.Bool("random-nonce", false, "Generate a random nonce instead of using one provided")
	useSHA256   = flag.Bool("sha256", false, "Use SHA256 for quote operatons")
)

func main() {
	flag.Parse()

	if *randomNonce {
		n := make([]byte, 8)
		rand.Read(n)
		*nonceHex = hex.EncodeToString(n)
	}

	tpm, err := attest.OpenTPM(nil)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error opening the TPM: %v\n", err)
		os.Exit(1)
	}

	err = runCommand(tpm)
	tpm.Close()

	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}
}

func runCommand(tpm *attest.TPM) error {
	switch flag.Arg(0) {
	case "info":
		info, err := tpm.Info()
		if err != nil {
			return err
		}
		fmt.Printf("Version: %d\n", info.Version)
		fmt.Printf("Interface: %d\n", info.Interface)
		fmt.Printf("VendorInfo: %x\n", info.VendorInfo)
		fmt.Printf("Manufactorer: %v\n", info.Manufacturer)

	case "make-aik":
		k, err := tpm.MintAIK(nil)
		if err != nil {
			return fmt.Errorf("MintAIK() failed: %v", err)
		}
		defer k.Close(tpm)
		b, err := k.Marshal()
		if err != nil {
			return err
		}
		return ioutil.WriteFile(*keyPath, b, 0755)

	case "quote":
		b, err := ioutil.ReadFile(*keyPath)
		if err != nil {
			return err
		}
		k, err := tpm.LoadKey(b)
		if err != nil {
			return fmt.Errorf("tpm.LoadKey() failed: %v", err)
		}
		defer k.Close(tpm)

		nonce, err := hex.DecodeString(*nonceHex)
		if err != nil {
			return err
		}
		alg := tpm2.AlgSHA1
		if *useSHA256 {
			alg = tpm2.AlgSHA256
		}

		q, err := k.Quote(tpm, nonce, alg)
		if err != nil {
			return fmt.Errorf("Quote() failed: %v", err)
		}
		fmt.Printf("Quote: %x\n", q.Quote)
		fmt.Printf("Signature: %x\n", q.Signature)

	case "delete-aik":
		b, err := ioutil.ReadFile(*keyPath)
		if err != nil {
			return err
		}
		k, err := tpm.LoadKey(b)
		if err != nil {
			return fmt.Errorf("tpm.LoadKey() failed: %v", err)
		}
		return k.Delete(tpm)

	case "list-eks":
		eks, err := tpm.EKs()
		if err != nil {
			return fmt.Errorf("tpm.EKs() failed: %v", err)
		}
		for _, ek := range eks {
			if ek.Cert != nil {
				fmt.Printf("EK certificate: %x\n", ek.Cert.Raw)
			}
		}

	case "list-pcrs":
		pcrs, alg, err := tpm.PCRs()
		if err != nil {
			return fmt.Errorf("tpm.PCRs() failed: %v", err)
		}
		fmt.Printf("PCR digest: %v\n", alg)
		for _, pcr := range pcrs {
			fmt.Printf("PCR[%d]: %x\n", pcr.Index, pcr.Digest)
		}

	case "measurement-log":
		b, err := tpm.MeasurementLog()
		if err != nil {
			return fmt.Errorf("tpm.MeasurementLog() failed: %v", err)
		}
		fmt.Printf("%x\n", b)

	default:
		return fmt.Errorf("no such command %q", flag.Arg(0))
	}
	return nil
}
<commit_msg>Fix attest-tool (#54)<commit_after>// Binary attest-tool performs attestation operations on the local system.
package main

import (
	"crypto/rand"
	"encoding/hex"
	"flag"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/google/go-attestation/attest"
)

var (
	keyPath     = flag.String("key", "aik.json", "Path to the key file")
	nonceHex    = flag.String("nonce", "", "Hex string to use as nonce when quoting")
	randomNonce = flag.Bool("random-nonce", false, "Generate a random nonce instead of using one provided")
	useSHA256   = flag.Bool("sha256", false, "Use SHA256 for quote operatons")
)

func main() {
	flag.Parse()

	if *randomNonce {
		n := make([]byte, 8)
		rand.Read(n)
		*nonceHex = hex.EncodeToString(n)
	}

	tpm, err := attest.OpenTPM(nil)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error opening the TPM: %v\n", err)
		os.Exit(1)
	}

	err = runCommand(tpm)
	tpm.Close()

	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}
}

func runCommand(tpm *attest.TPM) error {
	switch flag.Arg(0) {
	case "info":
		info, err := tpm.Info()
		if err != nil {
			return err
		}
		fmt.Printf("Version: %d\n", info.Version)
		fmt.Printf("Interface: %d\n", info.Interface)
		fmt.Printf("VendorInfo: %x\n", info.VendorInfo)
		fmt.Printf("Manufactorer: %v\n", info.Manufacturer)

	case "make-aik":
		k, err := tpm.MintAIK(nil)
		if err != nil {
			return fmt.Errorf("MintAIK() failed: %v", err)
		}
		defer k.Close(tpm)
		b, err := k.Marshal()
		if err != nil {
			return err
		}
		return ioutil.WriteFile(*keyPath, b, 0755)

	case "quote":
		b, err := ioutil.ReadFile(*keyPath)
		if err != nil {
			return err
		}
		k, err := tpm.LoadAIK(b)
		if err != nil {
			return fmt.Errorf("tpm.LoadKey() failed: %v", err)
		}
		defer k.Close(tpm)

		nonce, err := hex.DecodeString(*nonceHex)
		if err != nil {
			return err
		}
		alg := attest.HashSHA1
		if *useSHA256 {
			alg = attest.HashSHA256
		}

		q, err := k.Quote(tpm, nonce, alg)
		if err != nil {
			return fmt.Errorf("Quote() failed: %v", err)
		}
		fmt.Printf("Quote: %x\n", q.Quote)
		fmt.Printf("Signature: %x\n", q.Signature)

	case "list-eks":
		eks, err := tpm.EKs()
		if err != nil {
			return fmt.Errorf("tpm.EKs() failed: %v", err)
		}
		for _, ek := range eks {
			if ek.Cert != nil {
				fmt.Printf("EK certificate: %x\n", ek.Cert.Raw)
			}
		}

	case "list-pcrs":
		pcrs, alg, err := tpm.PCRs()
		if err != nil {
			return fmt.Errorf("tpm.PCRs() failed: %v", err)
		}
		fmt.Printf("PCR digest: %v\n", alg)
		for _, pcr := range pcrs {
			fmt.Printf("PCR[%d]: %x\n", pcr.Index, pcr.Digest)
		}

	case "measurement-log":
		b, err := tpm.MeasurementLog()
		if err != nil {
			return fmt.Errorf("tpm.MeasurementLog() failed: %v", err)
		}
		fmt.Printf("%x\n", b)

	default:
		return fmt.Errorf("no such command %q", flag.Arg(0))
	}
	return nil
}
<|endoftext|>


<commit_before>package kontrol

import (
	"database/sql"
	"errors"
	"fmt"
	"net/url"
	"os"
	"strings"
	"time"

	"github.com/hashicorp/go-version"
	sq "github.com/lann/squirrel"
	_ "github.com/lib/pq"

	"github.com/koding/kite"
	kontrolprotocol "github.com/koding/kite/kontrol/protocol"
	"github.com/koding/kite/protocol"
)

// Postgres holds Postgresql database related configuration
type PostgresConfig struct {
	Host     string
	Port     int
	Username string
	Password string
	DBName   string
}

type Postgres struct {
	DB  *sql.DB
	Log kite.Logger
}

func NewPostgres(conf *PostgresConfig, log kite.Logger) *Postgres {
	if conf == nil {
		conf = &PostgresConfig{}
	}

	if conf.Port == 0 {
		conf.Port = 5432
	}

	if conf.Host == "" {
		conf.Host = "localhost"
	}

	if conf.DBName == "" {
		conf.DBName = os.Getenv("KONTROL_POSTGRES_DBNAME")
		if conf.DBName == "" {
			panic("db name is not set for postgres kontrol storage")
		}
	}

	connString := fmt.Sprintf(
		"host=%s port=%d dbname=%s sslmode=disable",
		conf.Host, conf.Port, conf.DBName,
	)

	if conf.Password != "" {
		connString += " password=" + conf.Password
	}

	if conf.Username == "" {
		conf.Username = os.Getenv("KONTROL_POSTGRES_USERNAME")
		if conf.Username == "" {
			panic("username is not set for postgres kontrol storage")
		}
	}

	connString += " user=" + conf.Username

	db, err := sql.Open("postgres", connString)
	if err != nil {
		panic(err)
	}

	p := &Postgres{
		DB:  db,
		Log: log,
	}

	cleanInterval := 30 * time.Second  // clean every 30 second
	expireInterval := 20 * time.Second // clean rows that are 20 second old
	go p.RunCleaner(cleanInterval, expireInterval)

	return p
}

// RunCleaner delets every "interval" duration rows which are older than
// "expire" duration based on the "updated_at" field. For more info check
// CleanExpireRows which is used to delete old rows.
func (p *Postgres) RunCleaner(interval, expire time.Duration) {
	cleanFunc := func() {
		affectedRows, err := p.CleanExpiredRows(expire)
		if err != nil {
			p.Log.Warning("postgres: cleaning old rows failed: %s", err)
		} else if affectedRows != 0 {
			p.Log.Info("postgres: cleaned up %d rows", affectedRows)
		}
	}

	cleanFunc() // run for the first time
	for _ = range time.Tick(interval) {
		cleanFunc()
	}
}

// CleanExpiredRows deletes rows that are at least "expire" duration old. So if
// say an expire duration of 10 second is given, it will delete all rows that
// were updated 10 seconds ago
func (p *Postgres) CleanExpiredRows(expire time.Duration) (int64, error) {
	// See: http://stackoverflow.com/questions/14465727/how-to-insert-things-like-now-interval-2-minutes-into-php-pdo-query
	// basically by passing an integer to INTERVAL is not possible, we need to
	// cast it. However there is a more simpler way, we can multiply INTERVAL
	// with an integer so we just declare a one second INTERVAL and multiply it
	// with the amount we want.
	cleanOldRows := `DELETE FROM kite.kite WHERE updated_at < (now() at time zone 'utc') - ((INTERVAL '1 second') * $1)`

	rows, err := p.DB.Exec(cleanOldRows, int64(expire/time.Second))
	if err != nil {
		return 0, err
	}

	return rows.RowsAffected()
}

func (p *Postgres) Get(query *protocol.KontrolQuery) (Kites, error) {
	// only let query with usernames, otherwise the whole tree will be fetched
	// which is not good for us
	sqlQuery, args, err := selectQuery(query)
	if err != nil {
		return nil, err
	}

	var hasVersionConstraint bool // does query contains a constraint on version?
	var keyRest string            // query key after the version field
	var versionConstraint version.Constraints
	// NewVersion returns an error if it's a constraint, like: ">= 1.0, < 1.4"
	_, err = version.NewVersion(query.Version)
	if err != nil && query.Version != "" {
		// now parse our constraint
		versionConstraint, err = version.NewConstraint(query.Version)
		if err != nil {
			// version is a malformed, just return the error
			return nil, err
		}

		hasVersionConstraint = true
		nameQuery := &protocol.KontrolQuery{
			Username:    query.Username,
			Environment: query.Environment,
			Name:        query.Name,
		}

		// We will make a get request to all nodes under this name
		// and filter the result later.
		sqlQuery, args, err = selectQuery(nameQuery)
		if err != nil {
			return nil, err
		}

		// Rest of the key after version field
		keyRest = "/" + strings.TrimRight(
			query.Region+"/"+query.Hostname+"/"+query.ID, "/")
	}

	rows, err := p.DB.Query(sqlQuery, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var (
		username    string
		environment string
		kitename    string
		version     string
		region      string
		hostname    string
		id          string
		url         string
		updated_at  time.Time
		created_at  time.Time
	)

	kites := make(Kites, 0)

	for rows.Next() {
		err := rows.Scan(
			&username,
			&environment,
			&kitename,
			&version,
			&region,
			&hostname,
			&id,
			&url,
			&updated_at,
			&created_at,
		)
		if err != nil {
			return nil, err
		}

		kites = append(kites, &protocol.KiteWithToken{
			Kite: protocol.Kite{
				Username:    username,
				Environment: environment,
				Name:        kitename,
				Version:     version,
				Region:      region,
				Hostname:    hostname,
				ID:          id,
			},
			URL: url,
		})
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	// if it's just single result there is no need to shuffle or filter
	// according to the version constraint
	if len(kites) == 1 {
		return kites, nil
	}

	// Filter kites by version constraint
	if hasVersionConstraint {
		kites.Filter(versionConstraint, keyRest)
	}

	// randomize the result
	kites.Shuffle()

	return kites, nil
}

func (p *Postgres) Upsert(kiteProt *protocol.Kite, value *kontrolprotocol.RegisterValue) (err error) {
	// check that the incoming URL is valid to prevent malformed input
	_, err = url.Parse(value.URL)
	if err != nil {
		return err
	}

	// we are going to try an UPDATE, if it's not successfull we are going to
	// INSERT the document, all ine one single transaction
	tx, err := p.DB.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			err = tx.Rollback()
		} else {
			// it calls Rollback inside if it fails again :)
			err = tx.Commit()
		}
	}()

	res, err := tx.Exec(`UPDATE kite.kite SET url = $1, updated_at = (now() at time zone 'utc')
	WHERE id = $2`, value.URL, kiteProt.ID)
	if err != nil {
		return err
	}

	rowAffected, err := res.RowsAffected()
	if err != nil {
		return err
	}

	// we got an update! so this was successfull, just return without an error
	if rowAffected != 0 {
		return nil
	}

	insertSQL, args, err := insertQuery(kiteProt, value.URL)
	if err != nil {
		return err
	}

	_, err = tx.Exec(insertSQL, args...)
	return err
}

func (p *Postgres) Add(kiteProt *protocol.Kite, value *kontrolprotocol.RegisterValue) error {
	// check that the incoming URL is valid to prevent malformed input
	_, err := url.Parse(value.URL)
	if err != nil {
		return err
	}

	sqlQuery, args, err := insertQuery(kiteProt, value.URL)
	if err != nil {
		return err
	}

	_, err = p.DB.Exec(sqlQuery, args...)
	return err
}

func (p *Postgres) Update(kiteProt *protocol.Kite, value *kontrolprotocol.RegisterValue) error {
	// check that the incoming url is valid to prevent malformed input
	_, err := url.Parse(value.URL)
	if err != nil {
		return err
	}

	// TODO: also consider just using WHERE id = kiteProt.ID, see how it's
	// performs out
	_, err = p.DB.Exec(`UPDATE kite.kite SET url = $1, updated_at = (now() at time zone 'utc')
	WHERE id = $2`,
		value.URL, kiteProt.ID)

	return err
}

func (p *Postgres) Delete(kiteProt *protocol.Kite) error {
	deleteKite := `DELETE FROM kite.kite WHERE id = $1`
	_, err := p.DB.Exec(deleteKite, kiteProt.ID)
	return err
}

// selectQuery returns a SQL query for the given query
func selectQuery(query *protocol.KontrolQuery) (string, []interface{}, error) {
	psql := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)

	kites := psql.Select("*").From("kite.kite")
	fields := query.Fields()
	andQuery := sq.And{}

	// we stop for the first empty value
	for _, key := range keyOrder {
		v := fields[key]
		if v == "" {
			continue
		}

		// we are using "kitename" as the columname
		if key == "name" {
			key = "kitename"
		}

		andQuery = append(andQuery, sq.Eq{key: v})
	}

	if len(andQuery) == 0 {
		return "", nil, errors.New("all query fields are empty")
	}

	return kites.Where(andQuery).ToSql()
}

// inseryQuery
func insertQuery(kiteProt *protocol.Kite, url string) (string, []interface{}, error) {
	psql := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)

	kiteValues := kiteProt.Values()
	values := make([]interface{}, len(kiteValues))

	for i, kiteVal := range kiteValues {
		values[i] = kiteVal
	}

	values = append(values, url)

	return psql.Insert("kite.kite").Columns(
		"username",
		"environment",
		"kitename",
		"version",
		"region",
		"hostname",
		"id",
		"url",
	).Values(values...).ToSql()
}
<commit_msg>kontrol/postgres: take changes from github<commit_after>package kontrol

import (
	"database/sql"
	"errors"
	"fmt"
	"net/url"
	"strings"
	"time"

	"github.com/hashicorp/go-version"
	sq "github.com/lann/squirrel"
	_ "github.com/lib/pq"

	"github.com/koding/kite"
	kontrolprotocol "github.com/koding/kite/kontrol/protocol"
	"github.com/koding/kite/protocol"
	"github.com/koding/multiconfig"
)

// Postgres holds Postgresql database related configuration
type PostgresConfig struct {
	Host     string `default:"localhost"`
	Port     int    `default:"5432"`
	Username string `required:"true"`
	Password string
	DBName   string `required:"true" `
}

type Postgres struct {
	DB  *sql.DB
	Log kite.Logger
}

func NewPostgres(conf *PostgresConfig, log kite.Logger) *Postgres {
	if conf == nil {
		conf = new(PostgresConfig)

		envLoader := &multiconfig.EnvironmentLoader{Prefix: "kontrol_postgres"}
		configLoader := multiconfig.MultiLoader(
			&multiconfig.TagLoader{}, envLoader,
		)

		if err := configLoader.Load(conf); err != nil {
			fmt.Println("Valid environment variables are: ")
			envLoader.PrintEnvs(conf)
			panic(err)
		}

		err := multiconfig.MultiValidator(&multiconfig.RequiredValidator{}).Validate(conf)
		if err != nil {
			fmt.Println("Valid environment variables are: ")
			envLoader.PrintEnvs(conf)
			panic(err)
		}
	}

	connString := fmt.Sprintf(
		"host=%s port=%d dbname=%s user=%s password=%s sslmode=disable",
		conf.Host, conf.Port, conf.DBName, conf.Username, conf.Password,
	)

	db, err := sql.Open("postgres", connString)
	if err != nil {
		panic(err)
	}

	p := &Postgres{
		DB:  db,
		Log: log,
	}

	cleanInterval := 30 * time.Second  // clean every 30 second
	expireInterval := 20 * time.Second // clean rows that are 20 second old
	go p.RunCleaner(cleanInterval, expireInterval)

	return p
}

// RunCleaner delets every "interval" duration rows which are older than
// "expire" duration based on the "updated_at" field. For more info check
// CleanExpireRows which is used to delete old rows.
func (p *Postgres) RunCleaner(interval, expire time.Duration) {
	cleanFunc := func() {
		affectedRows, err := p.CleanExpiredRows(expire)
		if err != nil {
			p.Log.Warning("postgres: cleaning old rows failed: %s", err)
		} else if affectedRows != 0 {
			p.Log.Info("postgres: cleaned up %d rows", affectedRows)
		}
	}

	cleanFunc() // run for the first time
	for _ = range time.Tick(interval) {
		cleanFunc()
	}
}

// CleanExpiredRows deletes rows that are at least "expire" duration old. So if
// say an expire duration of 10 second is given, it will delete all rows that
// were updated 10 seconds ago
func (p *Postgres) CleanExpiredRows(expire time.Duration) (int64, error) {
	// See: http://stackoverflow.com/questions/14465727/how-to-insert-things-like-now-interval-2-minutes-into-php-pdo-query
	// basically by passing an integer to INTERVAL is not possible, we need to
	// cast it. However there is a more simpler way, we can multiply INTERVAL
	// with an integer so we just declare a one second INTERVAL and multiply it
	// with the amount we want.
	cleanOldRows := `DELETE FROM kite.kite WHERE updated_at < (now() at time zone 'utc') - ((INTERVAL '1 second') * $1)`

	rows, err := p.DB.Exec(cleanOldRows, int64(expire/time.Second))
	if err != nil {
		return 0, err
	}

	return rows.RowsAffected()
}

func (p *Postgres) Get(query *protocol.KontrolQuery) (Kites, error) {
	// only let query with usernames, otherwise the whole tree will be fetched
	// which is not good for us
	sqlQuery, args, err := selectQuery(query)
	if err != nil {
		return nil, err
	}

	var hasVersionConstraint bool // does query contains a constraint on version?
	var keyRest string            // query key after the version field
	var versionConstraint version.Constraints
	// NewVersion returns an error if it's a constraint, like: ">= 1.0, < 1.4"
	_, err = version.NewVersion(query.Version)
	if err != nil && query.Version != "" {
		// now parse our constraint
		versionConstraint, err = version.NewConstraint(query.Version)
		if err != nil {
			// version is a malformed, just return the error
			return nil, err
		}

		hasVersionConstraint = true
		nameQuery := &protocol.KontrolQuery{
			Username:    query.Username,
			Environment: query.Environment,
			Name:        query.Name,
		}

		// We will make a get request to all nodes under this name
		// and filter the result later.
		sqlQuery, args, err = selectQuery(nameQuery)
		if err != nil {
			return nil, err
		}

		// Rest of the key after version field
		keyRest = "/" + strings.TrimRight(
			query.Region+"/"+query.Hostname+"/"+query.ID, "/")
	}

	rows, err := p.DB.Query(sqlQuery, args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var (
		username    string
		environment string
		kitename    string
		version     string
		region      string
		hostname    string
		id          string
		url         string
		updated_at  time.Time
		created_at  time.Time
	)

	kites := make(Kites, 0)

	for rows.Next() {
		err := rows.Scan(
			&username,
			&environment,
			&kitename,
			&version,
			&region,
			&hostname,
			&id,
			&url,
			&updated_at,
			&created_at,
		)
		if err != nil {
			return nil, err
		}

		kites = append(kites, &protocol.KiteWithToken{
			Kite: protocol.Kite{
				Username:    username,
				Environment: environment,
				Name:        kitename,
				Version:     version,
				Region:      region,
				Hostname:    hostname,
				ID:          id,
			},
			URL: url,
		})
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	// if it's just single result there is no need to shuffle or filter
	// according to the version constraint
	if len(kites) == 1 {
		return kites, nil
	}

	// Filter kites by version constraint
	if hasVersionConstraint {
		kites.Filter(versionConstraint, keyRest)
	}

	// randomize the result
	kites.Shuffle()

	return kites, nil
}

func (p *Postgres) Upsert(kiteProt *protocol.Kite, value *kontrolprotocol.RegisterValue) (err error) {
	// check that the incoming URL is valid to prevent malformed input
	_, err = url.Parse(value.URL)
	if err != nil {
		return err
	}

	// we are going to try an UPDATE, if it's not successfull we are going to
	// INSERT the document, all ine one single transaction
	tx, err := p.DB.Begin()
	if err != nil {
		return err
	}

	defer func() {
		if err != nil {
			err = tx.Rollback()
		} else {
			// it calls Rollback inside if it fails again :)
			err = tx.Commit()
		}
	}()

	res, err := tx.Exec(`UPDATE kite.kite SET url = $1, updated_at = (now() at time zone 'utc')
	WHERE id = $2`, value.URL, kiteProt.ID)
	if err != nil {
		return err
	}

	rowAffected, err := res.RowsAffected()
	if err != nil {
		return err
	}

	// we got an update! so this was successfull, just return without an error
	if rowAffected != 0 {
		return nil
	}

	insertSQL, args, err := insertQuery(kiteProt, value.URL)
	if err != nil {
		return err
	}

	_, err = tx.Exec(insertSQL, args...)
	return err
}

func (p *Postgres) Add(kiteProt *protocol.Kite, value *kontrolprotocol.RegisterValue) error {
	// check that the incoming URL is valid to prevent malformed input
	_, err := url.Parse(value.URL)
	if err != nil {
		return err
	}

	sqlQuery, args, err := insertQuery(kiteProt, value.URL)
	if err != nil {
		return err
	}

	_, err = p.DB.Exec(sqlQuery, args...)
	return err
}

func (p *Postgres) Update(kiteProt *protocol.Kite, value *kontrolprotocol.RegisterValue) error {
	// check that the incoming url is valid to prevent malformed input
	_, err := url.Parse(value.URL)
	if err != nil {
		return err
	}

	// TODO: also consider just using WHERE id = kiteProt.ID, see how it's
	// performs out
	_, err = p.DB.Exec(`UPDATE kite.kite SET url = $1, updated_at = (now() at time zone 'utc')
	WHERE id = $2`,
		value.URL, kiteProt.ID)

	return err
}

func (p *Postgres) Delete(kiteProt *protocol.Kite) error {
	deleteKite := `DELETE FROM kite.kite WHERE id = $1`
	_, err := p.DB.Exec(deleteKite, kiteProt.ID)
	return err
}

// selectQuery returns a SQL query for the given query
func selectQuery(query *protocol.KontrolQuery) (string, []interface{}, error) {
	psql := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)

	kites := psql.Select("*").From("kite.kite")
	fields := query.Fields()
	andQuery := sq.And{}

	// we stop for the first empty value
	for _, key := range keyOrder {
		v := fields[key]
		if v == "" {
			continue
		}

		// we are using "kitename" as the columname
		if key == "name" {
			key = "kitename"
		}

		andQuery = append(andQuery, sq.Eq{key: v})
	}

	if len(andQuery) == 0 {
		return "", nil, errors.New("all query fields are empty")
	}

	return kites.Where(andQuery).ToSql()
}

// inseryQuery
func insertQuery(kiteProt *protocol.Kite, url string) (string, []interface{}, error) {
	psql := sq.StatementBuilder.PlaceholderFormat(sq.Dollar)

	kiteValues := kiteProt.Values()
	values := make([]interface{}, len(kiteValues))

	for i, kiteVal := range kiteValues {
		values[i] = kiteVal
	}

	values = append(values, url)

	return psql.Insert("kite.kite").Columns(
		"username",
		"environment",
		"kitename",
		"version",
		"region",
		"hostname",
		"id",
		"url",
	).Values(values...).ToSql()
}
<|endoftext|>


<commit_before>package client

import (
	"net/http"
	"os"
	"time"

	bosherr "github.com/cloudfoundry/bosh-utils/errors"
	boshlog "github.com/cloudfoundry/bosh-utils/logger"

	"bosh-google-cpi/google/config"

	"golang.org/x/oauth2"
	oauthgoogle "golang.org/x/oauth2/google"
	"google.golang.org/api/compute/v1"
	"google.golang.org/api/storage/v1"
)

const (
	computeScope = compute.ComputeScope
	storageScope = storage.DevstorageFullControlScope
	metadataHost = "metadata.google.internal"
	retryMax     = 5
	retryDelay   = 200 * time.Millisecond
)

type GoogleClient struct {
	config         config.Config
	computeService *compute.Service
	storageService *storage.Service
	logger         boshlog.Logger
}

type RetryTransport struct {
	Transport http.RoundTripper
}

func (rt *RetryTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	var resp *http.Response
	var err error
	var try uint64

	for try = 0; try < retryMax; try++ {
		resp, err = rt.Transport.RoundTrip(req)
		if err != nil {
			break
		}
		if resp.StatusCode < 500 || resp.StatusCode > 599 {
			break
		}
		time.Sleep(retryDelay << try)
	}
	return resp, err
}

func NewGoogleClient(
	config config.Config,
	logger boshlog.Logger,
) (GoogleClient, error) {
	var err error
	var computeClient, storageClient *http.Client
	userAgent := "bosh-google-cpi/0.0.1"

	if config.JSONKey != "" {
		computeJwtConf, err := oauthgoogle.JWTConfigFromJSON([]byte(config.JSONKey), computeScope)
		if err != nil {
			return GoogleClient{}, bosherr.WrapError(err, "Reading Google JSON Key")
		}
		computeClient = computeJwtConf.Client(oauth2.NoContext)

		storageJwtConf, err := oauthgoogle.JWTConfigFromJSON([]byte(config.JSONKey), storageScope)
		if err != nil {
			return GoogleClient{}, bosherr.WrapError(err, "Reading Google JSON Key")
		}
		storageClient = storageJwtConf.Client(oauth2.NoContext)
	} else {
		if v := os.Getenv("GCE_METADATA_HOST"); v == "" {
			os.Setenv("GCE_METADATA_HOST", metadataHost)
		}
		computeClient, err = oauthgoogle.DefaultClient(oauth2.NoContext, computeScope)
		if err != nil {
			return GoogleClient{}, bosherr.WrapError(err, "Creating a Google default client")
		}

		storageClient, err = oauthgoogle.DefaultClient(oauth2.NoContext, storageScope)
		if err != nil {
			return GoogleClient{}, bosherr.WrapError(err, "Creating a Google default client")
		}
	}

	// Custom RoundTripper for retries
	computeClient.Transport = &RetryTransport{
		Transport: computeClient.Transport,
	}
	computeService, err := compute.New(computeClient)
	if err != nil {
		return GoogleClient{}, bosherr.WrapError(err, "Creating a Google Compute Service client")
	}
	computeService.UserAgent = userAgent

	// Custom RoundTripper for retries
	storageClient.Transport = &RetryTransport{
		Transport: computeClient.Transport,
	}
	storageService, err := storage.New(storageClient)
	if err != nil {
		return GoogleClient{}, bosherr.WrapError(err, "Creating a Google Storage Service client")
	}
	storageService.UserAgent = userAgent

	return GoogleClient{
		config:         config,
		computeService: computeService,
		storageService: storageService,
		logger:         logger,
	}, nil
}

func (c GoogleClient) Project() string {
	return c.config.Project
}

func (c GoogleClient) DefaultRootDiskSizeGb() int {
	return c.config.DefaultRootDiskSizeGb
}

func (c GoogleClient) DefaultRootDiskType() string {
	return c.config.DefaultRootDiskType
}

func (c GoogleClient) DefaultZone() string {
	return c.config.DefaultZone
}

func (c GoogleClient) ComputeService() *compute.Service {
	return c.computeService
}

func (c GoogleClient) StorageService() *storage.Service {
	return c.storageService
}
<commit_msg>google: Fix retry bug causing GCS flakes<commit_after>package client

import (
	"net/http"
	"os"
	"time"

	bosherr "github.com/cloudfoundry/bosh-utils/errors"
	boshlog "github.com/cloudfoundry/bosh-utils/logger"

	"bosh-google-cpi/google/config"

	"golang.org/x/oauth2"
	oauthgoogle "golang.org/x/oauth2/google"
	"google.golang.org/api/compute/v1"
	"google.golang.org/api/storage/v1"
)

const (
	computeScope = compute.ComputeScope
	storageScope = storage.DevstorageFullControlScope
	metadataHost = "metadata.google.internal"
	retryMax     = 5
	retryDelay   = 200 * time.Millisecond
)

type GoogleClient struct {
	config         config.Config
	computeService *compute.Service
	storageService *storage.Service
	logger         boshlog.Logger
}

type RetryTransport struct {
	Transport http.RoundTripper
}

func (rt *RetryTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	var resp *http.Response
	var err error
	var try uint64

	for try = 0; try < retryMax; try++ {
		resp, err = rt.Transport.RoundTrip(req)
		if err != nil {
			break
		}
		if resp.StatusCode < 500 || resp.StatusCode > 599 {
			break
		}
		time.Sleep(retryDelay << try)
	}
	return resp, err
}

func NewGoogleClient(
	config config.Config,
	logger boshlog.Logger,
) (GoogleClient, error) {
	var err error
	var computeClient, storageClient *http.Client
	userAgent := "bosh-google-cpi/0.0.1"

	if config.JSONKey != "" {
		computeJwtConf, err := oauthgoogle.JWTConfigFromJSON([]byte(config.JSONKey), computeScope)
		if err != nil {
			return GoogleClient{}, bosherr.WrapError(err, "Reading Google JSON Key")
		}
		computeClient = computeJwtConf.Client(oauth2.NoContext)

		storageJwtConf, err := oauthgoogle.JWTConfigFromJSON([]byte(config.JSONKey), storageScope)
		if err != nil {
			return GoogleClient{}, bosherr.WrapError(err, "Reading Google JSON Key")
		}
		storageClient = storageJwtConf.Client(oauth2.NoContext)
	} else {
		if v := os.Getenv("GCE_METADATA_HOST"); v == "" {
			os.Setenv("GCE_METADATA_HOST", metadataHost)
		}
		computeClient, err = oauthgoogle.DefaultClient(oauth2.NoContext, computeScope)
		if err != nil {
			return GoogleClient{}, bosherr.WrapError(err, "Creating a Google default client")
		}

		storageClient, err = oauthgoogle.DefaultClient(oauth2.NoContext, storageScope)
		if err != nil {
			return GoogleClient{}, bosherr.WrapError(err, "Creating a Google default client")
		}
	}

	// Custom RoundTripper for retries
	computeClient.Transport = &RetryTransport{
		Transport: computeClient.Transport,
	}
	computeService, err := compute.New(computeClient)
	if err != nil {
		return GoogleClient{}, bosherr.WrapError(err, "Creating a Google Compute Service client")
	}
	computeService.UserAgent = userAgent

	// Custom RoundTripper for retries
	storageClient.Transport = &RetryTransport{
		Transport: storageClient.Transport,
	}
	storageService, err := storage.New(storageClient)
	if err != nil {
		return GoogleClient{}, bosherr.WrapError(err, "Creating a Google Storage Service client")
	}
	storageService.UserAgent = userAgent

	return GoogleClient{
		config:         config,
		computeService: computeService,
		storageService: storageService,
		logger:         logger,
	}, nil
}

func (c GoogleClient) Project() string {
	return c.config.Project
}

func (c GoogleClient) DefaultRootDiskSizeGb() int {
	return c.config.DefaultRootDiskSizeGb
}

func (c GoogleClient) DefaultRootDiskType() string {
	return c.config.DefaultRootDiskType
}

func (c GoogleClient) DefaultZone() string {
	return c.config.DefaultZone
}

func (c GoogleClient) ComputeService() *compute.Service {
	return c.computeService
}

func (c GoogleClient) StorageService() *storage.Service {
	return c.storageService
}
<|endoftext|>


<commit_before>package modelhelper

import (
	"fmt"
	"koding/db/models"
	"os"
	"testing"
	"time"

	"log"

	"gopkg.in/mgo.v2/bson"
)

func initMongoConn() {
	// i didnt write this
	mongoURL := ""

	if url := os.Getenv("WERCKER_MONGODB_URL"); url != "" {
		mongoURL = url
	} else {
		mongoURL = os.Getenv("MONGODB_URL")
	}

	if mongoURL == "" {
		log.Fatalf("either WERCKER_MONGODB_URL or MONGODB_URL should be set")
	}

	Initialize(mongoURL)
}

func TestBlockUser(t *testing.T) {
	initMongoConn()
	defer Close()

	username, blockedReason := "testuser", "testing"

	user := &models.User{
		Name: username, ObjectId: bson.NewObjectId(), Status: UserStatusBlocked,
	}

	defer func() {
		RemoveUser(username)
	}()

	err := CreateUser(user)
	if err != nil {
		t.Error(err)
	}

	err = BlockUser(username, blockedReason, 1*time.Hour)
	if err != nil {
		t.Error(err)
	}

	user, err = GetUser(username)
	if err != nil {
		t.Error(err)
	}

	if user.Status != UserStatusBlocked {
		t.Errorf("User status is not blocked")
	}

	if user.BlockedReason != blockedReason {
		t.Errorf("User blocked reason is not: %s", blockedReason)
	}

	if user.BlockedUntil.IsZero() {
		t.Errorf("User blocked until date is not set")
	}
}

func TestRemoveUser(t *testing.T) {
	initMongoConn()
	defer Close()

	username := "testuser"
	user := &models.User{
		Name: username, ObjectId: bson.NewObjectId(),
	}

	err := CreateUser(user)
	if err != nil {
		t.Error(err)
	}

	err = RemoveUser(username)
	if err != nil {
		t.Error(err)
	}

	user, err = GetUser(username)
	if err == nil {
		t.Errorf("User should've been deleted, but wasn't")
	}
}

func TestGetAnyUserTokenFromGroup(t *testing.T) {
	initMongoConn()
	defer Close()

	username := "testuser"
	user := &models.User{
		Name: username, ObjectId: bson.NewObjectId(),
	}

	err := CreateUser(user)
	if err != nil {
		t.Error(err)
	}
	groupName := "groupName"
	key := fmt.Sprintf("foreignAuth.slack.%s.token", groupName)
	token := "token-123qwe"
	selector := bson.M{"username": username}
	update := bson.M{key: token}

	if err := UpdateUser(selector, update); err != nil {
		t.Error("Error while updating user")
	}

	username2 := "testuser2"
	user2 := &models.User{
		Name: username2, ObjectId: bson.NewObjectId(),
	}

	err = CreateUser(user2)
	if err != nil {
		t.Error(err)
	}
	groupName2 := "groupName2"
	key2 := fmt.Sprintf("foreignAuth.slack.%s.token", groupName2)
	token2 := "token-123qwe11"
	selector2 := bson.M{"username": username2}
	update2 := bson.M{key2: token2}

	if err := UpdateUser(selector2, update2); err != nil {
		t.Error("Error while updating user")
	}

	users, err := GetAnySlackTokenWithGroup(groupName)
	if err != nil {
		t.Error("Error while getting user token")
	}

	if len(users) != 1 {
		t.Error("Length of user should be 1")
	}

	err = RemoveUser(username)
	if err != nil {
		t.Error(err)
	}
}
<commit_msg>go: fix TestGetAnyUserTokenFromGroup<commit_after>package modelhelper

import (
	"fmt"
	"koding/db/models"
	"os"
	"testing"
	"time"

	"log"

	"gopkg.in/mgo.v2/bson"
)

func initMongoConn() {
	// i didnt write this
	mongoURL := ""

	if url := os.Getenv("WERCKER_MONGODB_URL"); url != "" {
		mongoURL = url
	} else {
		mongoURL = os.Getenv("MONGODB_URL")
	}

	if mongoURL == "" {
		log.Fatalf("either WERCKER_MONGODB_URL or MONGODB_URL should be set")
	}

	Initialize(mongoURL)
}

func TestBlockUser(t *testing.T) {
	initMongoConn()
	defer Close()

	username, blockedReason := "testuser", "testing"

	user := &models.User{
		Name: username, ObjectId: bson.NewObjectId(), Status: UserStatusBlocked,
	}

	defer func() {
		RemoveUser(username)
	}()

	err := CreateUser(user)
	if err != nil {
		t.Error(err)
	}

	err = BlockUser(username, blockedReason, 1*time.Hour)
	if err != nil {
		t.Error(err)
	}

	user, err = GetUser(username)
	if err != nil {
		t.Error(err)
	}

	if user.Status != UserStatusBlocked {
		t.Errorf("User status is not blocked")
	}

	if user.BlockedReason != blockedReason {
		t.Errorf("User blocked reason is not: %s", blockedReason)
	}

	if user.BlockedUntil.IsZero() {
		t.Errorf("User blocked until date is not set")
	}
}

func TestRemoveUser(t *testing.T) {
	initMongoConn()
	defer Close()

	username := "testuser"
	user := &models.User{
		Name: username, ObjectId: bson.NewObjectId(),
	}

	err := CreateUser(user)
	if err != nil {
		t.Error(err)
	}

	err = RemoveUser(username)
	if err != nil {
		t.Error(err)
	}

	user, err = GetUser(username)
	if err == nil {
		t.Errorf("User should've been deleted, but wasn't")
	}
}

func TestGetAnyUserTokenFromGroup(t *testing.T) {
	initMongoConn()
	defer Close()

	id := bson.NewObjectId()
	username := id.Hex()
	user := &models.User{
		ObjectId: id,
		Name:     username,
		Email:    username + "@" + username + ".com",
	}

	err := CreateUser(user)
	if err != nil {
		t.Error(err)
	}

	groupName := bson.NewObjectId().Hex()

	key := fmt.Sprintf("foreignAuth.slack.%s.token", groupName)
	token := "token-123qwe"
	selector := bson.M{"username": username}
	update := bson.M{key: token}

	if err := UpdateUser(selector, update); err != nil {
		t.Error("Error while updating user")
	}

	id2 := bson.NewObjectId()
	username2 := id2.Hex()
	user2 := &models.User{
		ObjectId: id2,
		Name:     username2,
		Email:    username2 + "@" + username2 + ".com",
	}

	err = CreateUser(user2)
	if err != nil {
		t.Error(err)
	}

	groupName2 := bson.NewObjectId().Hex()
	key2 := fmt.Sprintf("foreignAuth.slack.%s.token", groupName2)
	token2 := "token-123qwe11"
	selector2 := bson.M{"username": username2}
	update2 := bson.M{key2: token2}

	if err := UpdateUser(selector2, update2); err != nil {
		t.Error("Error while updating user")
	}

	users, err := GetAnySlackTokenWithGroup(groupName)
	if err != nil {
		t.Error("Error while getting user token")
	}

	if len(users) != 1 {
		t.Error("Length of user should be 1")
	}

	err = RemoveUser(username)
	if err != nil {
		t.Error(err)
	}
}
<|endoftext|>