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

package csv

import (
	"bufio"
	"bytes"
	"io"
	"unicode/utf8"
)

// A Reader reads records from a CSV-encoded file.
//
// Can be created by calling either NewReader or using NewDialectReader.
type Reader struct {
	opts                    Dialect
	r                       *bufio.Reader
	tmpBuf                  bytes.Buffer
	optimizedDelimiter      []byte
	optimizedLineTerminator []byte
}

// Creates a reader that conforms to RFC 4180 and behaves identical as a
// encoding/csv.Reader.
//
// See `Default*` constants for default dialect used.
func NewReader(r io.Reader) *Reader {
	opts := Dialect{}
	opts.setDefaults()
	return NewDialectReader(r, opts)
}

// Create a custom CSV reader.
func NewDialectReader(r io.Reader, opts Dialect) *Reader {
	opts.setDefaults()
	return &Reader{
		opts:                    opts,
		r:                       bufio.NewReader(r),
		optimizedDelimiter:      []byte(string(opts.Delimiter)),
		optimizedLineTerminator: []byte(opts.LineTerminator),
	}
}

// ReadAll reads all the remaining records from r. Each record is a slice of
// fields. A successful call returns err == nil, not err == EOF. Because
// ReadAll is defined to read until EOF, it does not treat end of file as an
// error to be reported.
func (r *Reader) ReadAll() ([][]string, error) {
	allRows := make([][]string, 0, 1)
	for {
		fields, err := r.Read()
		if err == io.EOF {
			return allRows, nil
		}
		if err != nil {
			return nil, err
		}
		allRows = append(allRows, fields)
	}

	// Required by Go 1.0 to compile. Unreachable code.
	return allRows, nil
}

// Read reads one record from r. The record is a slice of strings with each
// string representing one field.
func (r *Reader) Read() ([]string, error) {
	// TODO: Possible optimization; store the maximum number of columns for
	// faster preallocation.
	record := make([]string, 0, 2)

	for {
		field, err := r.readField()
		record = append(record, field)
		if err != nil {
			return record, err
		}

		if nextIsLineTerminator, _ := r.nextIsLineTerminator(); nextIsLineTerminator {
			// Skipping so that next read call is good to go.
			err = r.skipLineTerminator()
			// Error is not expected since it should be in the Unreader buffer, but
			// might as well return it just in case.
			return record, err
		}
		nextIsDelimiter, err := r.nextIsDelimiter()
		if !nextIsDelimiter {
			// Herein lies the devil!
			return record, err
		} else {
			r.skipDelimiter()
		}
	}

	// Required by Go 1.0 to compile. Unreachable code.
	return record, nil
}

func (r *Reader) readField() (string, error) {
	char, _, err := r.r.ReadRune()
	if err != nil {
		return "", err
	}

	// Let the next individual reader functions handle this.
	r.r.UnreadRune()

	if char == r.opts.QuoteChar {
		return r.readQuotedField()
	}
	return r.readUnquotedField()
}

func (r *Reader) nextIsLineTerminator() (bool, error) {
	return r.nextIsBytes(r.optimizedLineTerminator)
}

func (r *Reader) nextIsDelimiter() (bool, error) {
	return r.nextIsBytes(r.optimizedDelimiter)
}

func (r *Reader) nextIsBytes(bs []byte) (bool, error) {
	n := len(bs)
	nextBytes, err := r.r.Peek(n)
	return bytes.Equal(nextBytes, bs), err
}

func (r *Reader) skipLineTerminator() error {
	for _ = range r.opts.LineTerminator {
		_, _, err := r.r.ReadRune()
		if err != nil {
			return err
		}
	}
	return nil
}

func (r *Reader) skipDelimiter() error {
	_, _, err := r.r.ReadRune()
	return err
}

func (r *Reader) readQuotedField() (string, error) {
	char, _, err := r.r.ReadRune()
	if err != nil {
		return "", err
	}
	if char != r.opts.QuoteChar {
		panic("Expected first character to be quote character.")
	}

	s := &r.tmpBuf
	defer r.tmpBuf.Reset() // TODO: Not using defer here is faster.
	for {
		char, _, err := r.r.ReadRune()
		if err != nil {
			return s.String(), err
		}
		if char != r.opts.QuoteChar {
			s.WriteRune(char)
		} else {
			switch r.opts.DoubleQuote {
			case DoDoubleQuote:
				char, _, err = r.r.ReadRune()
				if err != nil {
					return s.String(), err
				}
				if char == r.opts.QuoteChar {
					s.WriteRune(char)
				} else {
					r.r.UnreadRune()
					return s.String(), nil
				}
			case NoDoubleQuote:
				if s.Len() == 0 {
					return s.String(), nil
				}
				lastRune, size := utf8.DecodeLastRuneInString(s.String())
				if lastRune == utf8.RuneError && size == 1 {
					panic("Field contained malformed rune.")
				}
				if lastRune == r.opts.EscapeChar {
					// Replace previous escape character.
					s.Truncate(s.Len() - utf8.RuneLen(char))
					s.WriteRune(char)
				} else {
					return s.String(), nil
				}
			default:
				panic("Unrecognized double quote mode.")
			}
		}
	}

	// Required by Go 1.0 to compile. Unreachable code.
	return s.String(), nil
}

func (r *Reader) readUnquotedField() (string, error) {
	// TODO: Use bytes.Buffer
	s := &r.tmpBuf
	defer r.tmpBuf.Reset() // TODO: Not using defer here is faster.
	for {
		char, _, err := r.r.ReadRune()
		if err != nil || char == r.opts.Delimiter {
			// TODO Can a non quoted string be escaped? In that case, it should be
			// handled here. Should probably have a look at how Python's csv module
			// is handling this.

			// Putting it back for the outer loop to read separators. This makes more
			// compatible with readQuotedField().
			r.r.UnreadRune()

			return s.String(), err
		} else {
			s.WriteRune(char)
		}
		if ok, _ := r.nextIsLineTerminator(); ok {
			return s.String(), nil
		}
	}

	// Required by Go 1.0 to compile. Unreachable code.
	return s.String(), nil
}
<commit_msg>perf(reader): avoid rune to bytes conversion<commit_after>// Copyright 2014 Jens Rantil. All rights reserved.  Use of this source code is
// governed by a BSD-style license that can be found in the LICENSE file.

package csv

import (
	"bufio"
	"bytes"
	"io"
	"unicode/utf8"
)

// A Reader reads records from a CSV-encoded file.
//
// Can be created by calling either NewReader or using NewDialectReader.
type Reader struct {
	opts                    Dialect
	r                       *bufio.Reader
	tmpBuf                  bytes.Buffer
	optimizedDelimiter      []byte
	optimizedLineTerminator []byte
}

// Creates a reader that conforms to RFC 4180 and behaves identical as a
// encoding/csv.Reader.
//
// See `Default*` constants for default dialect used.
func NewReader(r io.Reader) *Reader {
	opts := Dialect{}
	opts.setDefaults()
	return NewDialectReader(r, opts)
}

// Create a custom CSV reader.
func NewDialectReader(r io.Reader, opts Dialect) *Reader {
	opts.setDefaults()
	return &Reader{
		opts:                    opts,
		r:                       bufio.NewReader(r),
		optimizedDelimiter:      []byte(string(opts.Delimiter)),
		optimizedLineTerminator: []byte(opts.LineTerminator),
	}
}

// ReadAll reads all the remaining records from r. Each record is a slice of
// fields. A successful call returns err == nil, not err == EOF. Because
// ReadAll is defined to read until EOF, it does not treat end of file as an
// error to be reported.
func (r *Reader) ReadAll() ([][]string, error) {
	allRows := make([][]string, 0, 1)
	for {
		fields, err := r.Read()
		if err == io.EOF {
			return allRows, nil
		}
		if err != nil {
			return nil, err
		}
		allRows = append(allRows, fields)
	}

	// Required by Go 1.0 to compile. Unreachable code.
	return allRows, nil
}

// Read reads one record from r. The record is a slice of strings with each
// string representing one field.
func (r *Reader) Read() ([]string, error) {
	// TODO: Possible optimization; store the maximum number of columns for
	// faster preallocation.
	record := make([]string, 0, 2)

	for {
		field, err := r.readField()
		record = append(record, field)
		if err != nil {
			return record, err
		}

		if nextIsLineTerminator, _ := r.nextIsLineTerminator(); nextIsLineTerminator {
			// Skipping so that next read call is good to go.
			err = r.skipLineTerminator()
			// Error is not expected since it should be in the Unreader buffer, but
			// might as well return it just in case.
			return record, err
		}
		nextIsDelimiter, err := r.nextIsDelimiter()
		if !nextIsDelimiter {
			// Herein lies the devil!
			return record, err
		} else {
			r.skipDelimiter()
		}
	}

	// Required by Go 1.0 to compile. Unreachable code.
	return record, nil
}

func (r *Reader) readField() (string, error) {
	char, _, err := r.r.ReadRune()
	if err != nil {
		return "", err
	}

	// Let the next individual reader functions handle this.
	r.r.UnreadRune()

	if char == r.opts.QuoteChar {
		return r.readQuotedField()
	}
	return r.readUnquotedField()
}

func (r *Reader) nextIsLineTerminator() (bool, error) {
	return r.nextIsBytes(r.optimizedLineTerminator)
}

func (r *Reader) nextIsDelimiter() (bool, error) {
	return r.nextIsBytes(r.optimizedDelimiter)
}

func (r *Reader) nextIsBytes(bs []byte) (bool, error) {
	n := len(bs)
	nextBytes, err := r.r.Peek(n)
	return bytes.Equal(nextBytes, bs), err
}

func (r *Reader) skipLineTerminator() error {
	_, err := r.r.Discard(len(r.optimizedLineTerminator))
	return err
}

func (r *Reader) skipDelimiter() error {
	_, err := r.r.Discard(len(r.optimizedDelimiter))
	return err
}

func (r *Reader) readQuotedField() (string, error) {
	char, _, err := r.r.ReadRune()
	if err != nil {
		return "", err
	}
	if char != r.opts.QuoteChar {
		panic("Expected first character to be quote character.")
	}

	s := &r.tmpBuf
	defer r.tmpBuf.Reset() // TODO: Not using defer here is faster.
	for {
		char, _, err := r.r.ReadRune()
		if err != nil {
			return s.String(), err
		}
		if char != r.opts.QuoteChar {
			s.WriteRune(char)
		} else {
			switch r.opts.DoubleQuote {
			case DoDoubleQuote:
				char, _, err = r.r.ReadRune()
				if err != nil {
					return s.String(), err
				}
				if char == r.opts.QuoteChar {
					s.WriteRune(char)
				} else {
					r.r.UnreadRune()
					return s.String(), nil
				}
			case NoDoubleQuote:
				if s.Len() == 0 {
					return s.String(), nil
				}
				lastRune, size := utf8.DecodeLastRuneInString(s.String())
				if lastRune == utf8.RuneError && size == 1 {
					panic("Field contained malformed rune.")
				}
				if lastRune == r.opts.EscapeChar {
					// Replace previous escape character.
					s.Truncate(s.Len() - utf8.RuneLen(char))
					s.WriteRune(char)
				} else {
					return s.String(), nil
				}
			default:
				panic("Unrecognized double quote mode.")
			}
		}
	}

	// Required by Go 1.0 to compile. Unreachable code.
	return s.String(), nil
}

func (r *Reader) readUnquotedField() (string, error) {
	// TODO: Use bytes.Buffer
	s := &r.tmpBuf
	defer r.tmpBuf.Reset() // TODO: Not using defer here is faster.
	for {
		char, _, err := r.r.ReadRune()
		if err != nil || char == r.opts.Delimiter {
			// TODO Can a non quoted string be escaped? In that case, it should be
			// handled here. Should probably have a look at how Python's csv module
			// is handling this.

			// Putting it back for the outer loop to read separators. This makes more
			// compatible with readQuotedField().
			r.r.UnreadRune()

			return s.String(), err
		} else {
			s.WriteRune(char)
		}
		if ok, _ := r.nextIsLineTerminator(); ok {
			return s.String(), nil
		}
	}

	// Required by Go 1.0 to compile. Unreachable code.
	return s.String(), nil
}
<|endoftext|>


<commit_before>package rpc

import (
	"reflect"
	"testing"
)

type testUi struct {
	askCalled      bool
	askQuery       string
	errorCalled    bool
	errorMessage   string
	machineCalled  bool
	machineType    string
	machineArgs    []string
	messageCalled  bool
	messageMessage string
	sayCalled      bool
	sayMessage     string
}

func (u *testUi) Ask(query string) (string, error) {
	u.askCalled = true
	u.askQuery = query
	return "foo", nil
}

func (u *testUi) Error(message string) {
	u.errorCalled = true
	u.errorMessage = message
}

func (u *testUi) Machine(t string, args ...string) {
	u.machineCalled = true
	u.machineType = t
	u.machineArgs = args
}

func (u *testUi) Message(message string) {
	u.messageCalled = true
	u.messageMessage = message
}

func (u *testUi) Say(message string) {
	u.sayCalled = true
	u.sayMessage = message
}

func TestUiRPC(t *testing.T) {
	// Create the UI to test
	ui := new(testUi)

	// Start the RPC server
	client, server := testClientServer(t)
	defer client.Close()
	defer server.Close()
	server.RegisterUi(ui)

	uiClient := client.Ui()

	// Basic error and say tests
	result, err := uiClient.Ask("query")
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if !ui.askCalled {
		t.Fatal("should be called")
	}
	if ui.askQuery != "query" {
		t.Fatalf("bad: %s", ui.askQuery)
	}
	if result != "foo" {
		t.Fatalf("bad: %#v", result)
	}

	uiClient.Error("message")
	if ui.errorMessage != "message" {
		t.Fatalf("bad: %#v", ui.errorMessage)
	}

	uiClient.Message("message")
	if ui.messageMessage != "message" {
		t.Fatalf("bad: %#v", ui.errorMessage)
	}

	uiClient.Say("message")
	if ui.sayMessage != "message" {
		t.Fatalf("bad: %#v", ui.errorMessage)
	}

	uiClient.Machine("foo", "bar", "baz")
	if !ui.machineCalled {
		t.Fatal("machine should be called")
	}

	if ui.machineType != "foo" {
		t.Fatalf("bad type: %#v", ui.machineType)
	}

	expected := []string{"bar", "baz"}
	if !reflect.DeepEqual(ui.machineArgs, expected) {
		t.Fatalf("bad: %#v", ui.machineArgs)
	}
}
<commit_msg>packer/rpc/ui_test.go: test progress bar too<commit_after>package rpc

import (
	"reflect"
	"testing"

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

type testUi struct {
	askCalled         bool
	askQuery          string
	errorCalled       bool
	errorMessage      string
	machineCalled     bool
	machineType       string
	machineArgs       []string
	messageCalled     bool
	messageMessage    string
	sayCalled         bool
	sayMessage        string
	progressBarCalled bool
}

func (u *testUi) Ask(query string) (string, error) {
	u.askCalled = true
	u.askQuery = query
	return "foo", nil
}

func (u *testUi) Error(message string) {
	u.errorCalled = true
	u.errorMessage = message
}

func (u *testUi) Machine(t string, args ...string) {
	u.machineCalled = true
	u.machineType = t
	u.machineArgs = args
}

func (u *testUi) Message(message string) {
	u.messageCalled = true
	u.messageMessage = message
}

func (u *testUi) Say(message string) {
	u.sayCalled = true
	u.sayMessage = message
}

func (u *testUi) ProgressBar() packer.ProgressBar {
	u.progressBarCalled = true
	return new(packer.NoopProgressBar)
}

func TestUiRPC(t *testing.T) {
	// Create the UI to test
	ui := new(testUi)

	// Start the RPC server
	client, server := testClientServer(t)
	defer client.Close()
	defer server.Close()
	server.RegisterUi(ui)

	uiClient := client.Ui()

	// Basic error and say tests
	result, err := uiClient.Ask("query")
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if !ui.askCalled {
		t.Fatal("should be called")
	}
	if ui.askQuery != "query" {
		t.Fatalf("bad: %s", ui.askQuery)
	}
	if result != "foo" {
		t.Fatalf("bad: %#v", result)
	}

	uiClient.Error("message")
	if ui.errorMessage != "message" {
		t.Fatalf("bad: %#v", ui.errorMessage)
	}

	uiClient.Message("message")
	if ui.messageMessage != "message" {
		t.Fatalf("bad: %#v", ui.errorMessage)
	}

	uiClient.Say("message")
	if ui.sayMessage != "message" {
		t.Fatalf("bad: %#v", ui.errorMessage)
	}
	uiClient.ProgressBar()
	if ui.progressBarCalled != true {
		t.Fatalf("ProgressBar not called.")
	}

	uiClient.Machine("foo", "bar", "baz")
	if !ui.machineCalled {
		t.Fatal("machine should be called")
	}

	if ui.machineType != "foo" {
		t.Fatalf("bad type: %#v", ui.machineType)
	}

	expected := []string{"bar", "baz"}
	if !reflect.DeepEqual(ui.machineArgs, expected) {
		t.Fatalf("bad: %#v", ui.machineArgs)
	}
}
<|endoftext|>


<commit_before>package atlas

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
)

// bcWrapper is the API wrapper since the server wraps the resulting object.
type bcWrapper struct {
	BuildConfig *BuildConfig `json:"build_configuration"`
}

// Atlas expects a list of key/value vars
type BuildVar struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}
type BuildVars []BuildVar

// BuildConfig represents a Packer build configuration.
type BuildConfig struct {
	// User is the namespace under which the build config lives
	User string `json:"username"`

	// Name is the actual name of the build config, unique in the scope
	// of the username.
	Name string `json:"name"`
}

// Slug returns the slug format for this BuildConfig (User/Name)
func (b *BuildConfig) Slug() string {
	return fmt.Sprintf("%s/%s", b.User, b.Name)
}

// BuildConfigVersion represents a single uploaded (or uploadable) version
// of a build configuration.
type BuildConfigVersion struct {
	// The fields below are the username/name combo to uniquely identify
	// a build config.
	User string `json:"username"`
	Name string `json:"name"`

	// Builds is the list of builds that this version supports.
	Builds []BuildConfigBuild
}

// Slug returns the slug format for this BuildConfigVersion (User/Name)
func (bv *BuildConfigVersion) Slug() string {
	return fmt.Sprintf("%s/%s", bv.User, bv.Name)
}

// BuildConfigBuild is a single build that is present in an uploaded
// build configuration.
type BuildConfigBuild struct {
	// Name is a unique name for this build
	Name string `json:"name"`

	// Type is the type of builder that this build needs to run on,
	// such as "amazon-ebs" or "qemu".
	Type string `json:"type"`

	// Artifact is true if this build results in one or more artifacts
	// being sent to Atlas
	Artifact bool `json:"artifact"`
}

// BuildConfig gets a single build configuration by user and name.
func (c *Client) BuildConfig(user, name string) (*BuildConfig, error) {
	log.Printf("[INFO] getting build configuration %s/%s", user, name)

	endpoint := fmt.Sprintf("/api/v1/packer/build-configurations/%s/%s", user, name)
	request, err := c.Request("GET", endpoint, nil)
	if err != nil {
		return nil, err
	}

	response, err := checkResp(c.HTTPClient.Do(request))
	if err != nil {
		return nil, err
	}

	var bc BuildConfig
	if err := decodeJSON(response, &bc); err != nil {
		return nil, err
	}

	return &bc, nil
}

// CreateBuildConfig creates a new build configuration.
func (c *Client) CreateBuildConfig(user, name string) (*BuildConfig, error) {
	log.Printf("[INFO] creating build configuration %s/%s", user, name)

	endpoint := "/api/v1/packer/build-configurations"
	body, err := json.Marshal(&bcWrapper{
		BuildConfig: &BuildConfig{
			User: user,
			Name: name,
		},
	})
	if err != nil {
		return nil, err
	}

	request, err := c.Request("POST", endpoint, &RequestOptions{
		Body: bytes.NewReader(body),
		Headers: map[string]string{
			"Content-Type": "application/json",
		},
	})
	if err != nil {
		return nil, err
	}

	response, err := checkResp(c.HTTPClient.Do(request))
	if err != nil {
		return nil, err
	}

	var bc BuildConfig
	if err := decodeJSON(response, &bc); err != nil {
		return nil, err
	}

	return &bc, nil
}

// UploadBuildConfigVersion creates a single build configuration version
// and uploads the template associated with it.
//
// Actual API: "Create Build Config Version"
func (c *Client) UploadBuildConfigVersion(v *BuildConfigVersion, metadata map[string]interface{},
	vars BuildVars, data io.Reader, size int64) error {

	log.Printf("[INFO] uploading build configuration version %s (%d bytes), with metadata %q",
		v.Slug(), size, metadata)

	endpoint := fmt.Sprintf("/api/v1/packer/build-configurations/%s/%s/versions",
		v.User, v.Name)

	var bodyData bcCreateWrapper
	bodyData.Version.Builds = v.Builds
	bodyData.Version.Metadata = metadata
	bodyData.Version.Vars = vars
	body, err := json.Marshal(bodyData)
	if err != nil {
		return err
	}

	request, err := c.Request("POST", endpoint, &RequestOptions{
		Body: bytes.NewReader(body),
		Headers: map[string]string{
			"Content-Type": "application/json",
		},
	})
	if err != nil {
		return err
	}

	response, err := checkResp(c.HTTPClient.Do(request))
	if err != nil {
		return err
	}

	var bv bcCreate
	if err := decodeJSON(response, &bv); err != nil {
		return err
	}

	if err := c.putFile(bv.UploadPath, data, size); err != nil {
		return err
	}

	return nil
}

// bcCreate is the struct returned when creating a build configuration.
type bcCreate struct {
	UploadPath string `json:"upload_path"`
}

// bcCreateWrapper is the wrapper for creating a build config.
type bcCreateWrapper struct {
	Version struct {
		Metadata map[string]interface{} `json:"metadata,omitempty"`
		Builds   []BuildConfigBuild     `json:"builds"`
		Vars     BuildVars              `json:"packer_vars,omitempty"`
	} `json:"version"`
}
<commit_msg>add sensitive to api<commit_after>package atlas

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
)

// bcWrapper is the API wrapper since the server wraps the resulting object.
type bcWrapper struct {
	BuildConfig *BuildConfig `json:"build_configuration"`
}

// Atlas expects a list of key/value vars
type BuildVar struct {
	Key       string `json:"key"`
	Value     string `json:"value"`
	Sensitive bool   `json:"sensitive"`
}
type BuildVars []BuildVar

// BuildConfig represents a Packer build configuration.
type BuildConfig struct {
	// User is the namespace under which the build config lives
	User string `json:"username"`

	// Name is the actual name of the build config, unique in the scope
	// of the username.
	Name string `json:"name"`
}

// Slug returns the slug format for this BuildConfig (User/Name)
func (b *BuildConfig) Slug() string {
	return fmt.Sprintf("%s/%s", b.User, b.Name)
}

// BuildConfigVersion represents a single uploaded (or uploadable) version
// of a build configuration.
type BuildConfigVersion struct {
	// The fields below are the username/name combo to uniquely identify
	// a build config.
	User string `json:"username"`
	Name string `json:"name"`

	// Builds is the list of builds that this version supports.
	Builds []BuildConfigBuild
}

// Slug returns the slug format for this BuildConfigVersion (User/Name)
func (bv *BuildConfigVersion) Slug() string {
	return fmt.Sprintf("%s/%s", bv.User, bv.Name)
}

// BuildConfigBuild is a single build that is present in an uploaded
// build configuration.
type BuildConfigBuild struct {
	// Name is a unique name for this build
	Name string `json:"name"`

	// Type is the type of builder that this build needs to run on,
	// such as "amazon-ebs" or "qemu".
	Type string `json:"type"`

	// Artifact is true if this build results in one or more artifacts
	// being sent to Atlas
	Artifact bool `json:"artifact"`
}

// BuildConfig gets a single build configuration by user and name.
func (c *Client) BuildConfig(user, name string) (*BuildConfig, error) {
	log.Printf("[INFO] getting build configuration %s/%s", user, name)

	endpoint := fmt.Sprintf("/api/v1/packer/build-configurations/%s/%s", user, name)
	request, err := c.Request("GET", endpoint, nil)
	if err != nil {
		return nil, err
	}

	response, err := checkResp(c.HTTPClient.Do(request))
	if err != nil {
		return nil, err
	}

	var bc BuildConfig
	if err := decodeJSON(response, &bc); err != nil {
		return nil, err
	}

	return &bc, nil
}

// CreateBuildConfig creates a new build configuration.
func (c *Client) CreateBuildConfig(user, name string) (*BuildConfig, error) {
	log.Printf("[INFO] creating build configuration %s/%s", user, name)

	endpoint := "/api/v1/packer/build-configurations"
	body, err := json.Marshal(&bcWrapper{
		BuildConfig: &BuildConfig{
			User: user,
			Name: name,
		},
	})
	if err != nil {
		return nil, err
	}

	request, err := c.Request("POST", endpoint, &RequestOptions{
		Body: bytes.NewReader(body),
		Headers: map[string]string{
			"Content-Type": "application/json",
		},
	})
	if err != nil {
		return nil, err
	}

	response, err := checkResp(c.HTTPClient.Do(request))
	if err != nil {
		return nil, err
	}

	var bc BuildConfig
	if err := decodeJSON(response, &bc); err != nil {
		return nil, err
	}

	return &bc, nil
}

// UploadBuildConfigVersion creates a single build configuration version
// and uploads the template associated with it.
//
// Actual API: "Create Build Config Version"
func (c *Client) UploadBuildConfigVersion(v *BuildConfigVersion, metadata map[string]interface{},
	vars BuildVars, data io.Reader, size int64) error {

	log.Printf("[INFO] uploading build configuration version %s (%d bytes), with metadata %q",
		v.Slug(), size, metadata)

	endpoint := fmt.Sprintf("/api/v1/packer/build-configurations/%s/%s/versions",
		v.User, v.Name)

	var bodyData bcCreateWrapper
	bodyData.Version.Builds = v.Builds
	bodyData.Version.Metadata = metadata
	bodyData.Version.Vars = vars
	body, err := json.Marshal(bodyData)
	if err != nil {
		return err
	}

	request, err := c.Request("POST", endpoint, &RequestOptions{
		Body: bytes.NewReader(body),
		Headers: map[string]string{
			"Content-Type": "application/json",
		},
	})
	if err != nil {
		return err
	}

	response, err := checkResp(c.HTTPClient.Do(request))
	if err != nil {
		return err
	}

	var bv bcCreate
	if err := decodeJSON(response, &bv); err != nil {
		return err
	}

	if err := c.putFile(bv.UploadPath, data, size); err != nil {
		return err
	}

	return nil
}

// bcCreate is the struct returned when creating a build configuration.
type bcCreate struct {
	UploadPath string `json:"upload_path"`
}

// bcCreateWrapper is the wrapper for creating a build config.
type bcCreateWrapper struct {
	Version struct {
		Metadata map[string]interface{} `json:"metadata,omitempty"`
		Builds   []BuildConfigBuild     `json:"builds"`
		Vars     BuildVars              `json:"packer_vars,omitempty"`
	} `json:"version"`
}
<|endoftext|>


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

// Package statsgod - this library manages the different socket listeners
// that we use to collect metrics.
package statsgod

import (
	"fmt"
	"net"
	"os"
	"strings"
)

// Enumeration of the socket types.
const (
	SocketTypeUdp = iota
	SocketTypeTcp
	SocketTypeUnix
)

// Socket is the interface for all of our socket types.
type Socket interface {
	Listen(parseChannel chan string, logger Logger)
}

// CreateSocket is a factory to create Socket structs.
func CreateSocket(socketType int) Socket {
	switch socketType {
	case SocketTypeUdp:
		return new(SocketUdp)
	case SocketTypeTcp:
		return new(SocketTcp)
	case SocketTypeUnix:
		return new(SocketUnix)
	default:
		panic("Unknown socket type requested.")
	}
}

// SocketTcp contains the required fields to start a TCP socket.
type SocketTcp struct {
	Host string
	Port int
}

// Listen conforms to the Structure.Listen() interface.
func (l SocketTcp) Listen(parseChannel chan string, logger Logger) {
	if l.Host == "" || l.Port == 0 {
		panic("Could not establish a TCP socket. Host and port must be specified.")
	}
	addr := fmt.Sprintf("%s:%d", l.Host, l.Port)
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		panic(fmt.Sprintf("Could not establish a TCP socket. %s", err))
	}

	logger.Info.Printf("TCP socket opened on %s", addr)
	for {
		conn, err := listener.Accept()
		if err != nil {
			logger.Error.Println("Could not accept connection", err)
			return
		}
		go readInput(conn, parseChannel, logger)
	}
}

// SocketUdp contains the fields required to start a UDP socket.
type SocketUdp struct {
	Host string
	Port int
}

// Listen conforms to the Structure.Listen() interface.
func (l SocketUdp) Listen(parseChannel chan string, logger Logger) {
	if l.Host == "" || l.Port == 0 {
		panic("Could not establish a UDP socket. Host and port must be specified.")
	}
	addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%d", l.Host, l.Port))
	listener, err := net.ListenUDP("udp", addr)
	if err != nil {
		panic(fmt.Sprintf("Could not establish a UDP socket. %s", err))
	}

	logger.Info.Printf("UDP socket opened on %s", addr)
	for {
		readInputUdp(*listener, parseChannel, logger)
	}
}

// SocketUnix contains the fields required to start a Unix socket.
type SocketUnix struct {
	Sock string
}

// Listen conforms to the Structure.Listen() interface.
func (l SocketUnix) Listen(parseChannel chan string, logger Logger) {
	if l.Sock == "" {
		panic("Could not establish a Unix socket. No sock file specified.")
	}
	listener, err := net.Listen("unix", l.Sock)
	defer os.Remove(l.Sock)
	if err != nil {
		panic(fmt.Sprintf("Could not establish a Unix socket. %s", err))
	}
	logger.Info.Printf("Unix socket opened at %s", l.Sock)
	for {
		conn, err := listener.Accept()
		if err != nil {
			logger.Error.Println("Could not accept connection", err)
			return
		}
		go readInput(conn, parseChannel, logger)
	}
}

// readInput parses the buffer for TCP and Unix sockets.
func readInput(conn net.Conn, parseChannel chan string, logger Logger) {
	defer conn.Close()
	// Read the data from the connection.
	buf := make([]byte, 512)
	_, err := conn.Read(buf)
	if err != nil {
		logger.Error.Println("Could not read stream.", err)
		return
	}
	if len(string(buf)) != 0 {
		parseChannel <- strings.TrimSpace(strings.Trim(string(buf), "\x00"))
	}
}

// readInputUdp parses the buffer for UDP sockets.
func readInputUdp(conn net.UDPConn, parseChannel chan string, logger Logger) {
	buf := make([]byte, 512)
	_, _, err := conn.ReadFromUDP(buf[0:])
	if err != nil {
		logger.Error.Println("Could not read stream.", err)
		return
	}
	parseChannel <- strings.TrimSpace(strings.Trim(string(buf), "\x00"))
}
<commit_msg>Issue #3 fixing comments.<commit_after>/**
 * Copyright 2014 Acquia, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Package statsgod - this library manages the different socket listeners
// that we use to collect metrics.
package statsgod

import (
	"fmt"
	"net"
	"os"
	"strings"
)

// Enumeration of the socket types.
const (
	SocketTypeUdp = iota
	SocketTypeTcp
	SocketTypeUnix
)

// Socket is the interface for all of our socket types.
type Socket interface {
	Listen(parseChannel chan string, logger Logger)
}

// CreateSocket is a factory to create Socket structs.
func CreateSocket(socketType int) Socket {
	switch socketType {
	case SocketTypeUdp:
		return new(SocketUdp)
	case SocketTypeTcp:
		return new(SocketTcp)
	case SocketTypeUnix:
		return new(SocketUnix)
	default:
		panic("Unknown socket type requested.")
	}
}

// SocketTcp contains the required fields to start a TCP socket.
type SocketTcp struct {
	Host string
	Port int
}

// Listen conforms to the Socket.Listen() interface.
func (l SocketTcp) Listen(parseChannel chan string, logger Logger) {
	if l.Host == "" || l.Port == 0 {
		panic("Could not establish a TCP socket. Host and port must be specified.")
	}
	addr := fmt.Sprintf("%s:%d", l.Host, l.Port)
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		panic(fmt.Sprintf("Could not establish a TCP socket. %s", err))
	}

	logger.Info.Printf("TCP socket opened on %s", addr)
	for {
		conn, err := listener.Accept()
		if err != nil {
			logger.Error.Println("Could not accept connection", err)
			return
		}
		go readInput(conn, parseChannel, logger)
	}
}

// SocketUdp contains the fields required to start a UDP socket.
type SocketUdp struct {
	Host string
	Port int
}

// Listen conforms to the Socket.Listen() interface.
func (l SocketUdp) Listen(parseChannel chan string, logger Logger) {
	if l.Host == "" || l.Port == 0 {
		panic("Could not establish a UDP socket. Host and port must be specified.")
	}
	addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%d", l.Host, l.Port))
	listener, err := net.ListenUDP("udp", addr)
	if err != nil {
		panic(fmt.Sprintf("Could not establish a UDP socket. %s", err))
	}

	logger.Info.Printf("UDP socket opened on %s", addr)
	for {
		readInputUdp(*listener, parseChannel, logger)
	}
}

// SocketUnix contains the fields required to start a Unix socket.
type SocketUnix struct {
	Sock string
}

// Listen conforms to the Socket.Listen() interface.
func (l SocketUnix) Listen(parseChannel chan string, logger Logger) {
	if l.Sock == "" {
		panic("Could not establish a Unix socket. No sock file specified.")
	}
	listener, err := net.Listen("unix", l.Sock)
	defer os.Remove(l.Sock)
	if err != nil {
		panic(fmt.Sprintf("Could not establish a Unix socket. %s", err))
	}
	logger.Info.Printf("Unix socket opened at %s", l.Sock)
	for {
		conn, err := listener.Accept()
		if err != nil {
			logger.Error.Println("Could not accept connection", err)
			return
		}
		go readInput(conn, parseChannel, logger)
	}
}

// readInput parses the buffer for TCP and Unix sockets.
func readInput(conn net.Conn, parseChannel chan string, logger Logger) {
	defer conn.Close()
	// Read the data from the connection.
	buf := make([]byte, 512)
	_, err := conn.Read(buf)
	if err != nil {
		logger.Error.Println("Could not read stream.", err)
		return
	}
	if len(string(buf)) != 0 {
		parseChannel <- strings.TrimSpace(strings.Trim(string(buf), "\x00"))
	}
}

// readInputUdp parses the buffer for UDP sockets.
func readInputUdp(conn net.UDPConn, parseChannel chan string, logger Logger) {
	buf := make([]byte, 512)
	_, _, err := conn.ReadFromUDP(buf[0:])
	if err != nil {
		logger.Error.Println("Could not read stream.", err)
		return
	}
	parseChannel <- strings.TrimSpace(strings.Trim(string(buf), "\x00"))
}
<|endoftext|>


<commit_before>package disruptor

import "time"

type Reader struct {
	read     *Cursor
	written  *Cursor
	upstream Barrier
	consumer Consumer
	ready    bool
} // TODO: padding???

func NewReader(read, written *Cursor, upstream Barrier, consumer Consumer) *Reader {
	return &Reader{
		read:     read,
		written:  written,
		upstream: upstream,
		consumer: consumer,
		ready:    false,
	}
}

func (this *Reader) Start() {
	this.ready = true
	go this.receive()
}
func (this *Reader) Stop() {
	this.ready = false
}

func (this *Reader) receive() {
	previous := this.read.Sequence // TODO: this.read.Load()
	idling, gating := 0, 0

	for {
		lower := previous + 1
		upper := this.upstream.Read(lower)

		if lower <= upper {
			this.consumer.Consume(lower, upper)
			this.read.Sequence = upper // TODO: this.read.Commit()
			previous = upper
		} else if upper = this.written.Load(); lower <= upper {
			// Gating--TODO: wait strategy (provide gating count to wait strategy for phased backoff)
			gating++
			idling = 0
		} else if this.ready {
			// Idling--TODO: wait strategy (provide idling count to wait strategy for phased backoff)
			idling++
			gating = 0
		} else {
			break
		}

		// sleeping increases the batch size which reduces the number of read commits
		// which drastically reduces the cost; longer sleeps = larger batches = less expensive commits
		time.Sleep(time.Microsecond)
	}
}
<commit_msg>Removed reader comments.<commit_after>package disruptor

import "time"

type Reader struct {
	read     *Cursor
	written  *Cursor
	upstream Barrier
	consumer Consumer
	ready    bool
} // TODO: padding???

func NewReader(read, written *Cursor, upstream Barrier, consumer Consumer) *Reader {
	return &Reader{
		read:     read,
		written:  written,
		upstream: upstream,
		consumer: consumer,
		ready:    false,
	}
}

func (this *Reader) Start() {
	this.ready = true
	go this.receive()
}
func (this *Reader) Stop() {
	this.ready = false
}

func (this *Reader) receive() {
	previous := this.read.Load()
	idling, gating := 0, 0

	for {
		lower := previous + 1
		upper := this.upstream.Read(lower)

		if lower <= upper {
			this.consumer.Consume(lower, upper)
			this.read.Store(upper)
			previous = upper
		} else if upper = this.written.Load(); lower <= upper {
			// Gating--TODO: wait strategy (provide gating count to wait strategy for phased backoff)
			gating++
			idling = 0
		} else if this.ready {
			// Idling--TODO: wait strategy (provide idling count to wait strategy for phased backoff)
			idling++
			gating = 0
		} else {
			break
		}

		// sleeping increases the batch size which reduces number of writes required to store the sequence
		// reducing the number of writes allows the CPU to optimize the pipeline without prediction failures
		time.Sleep(time.Microsecond)
	}
}
<|endoftext|>


<commit_before>package dedup

import (
	"bufio"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"math"
)

// A reader will decode a deduplicated stream and
// return the data as it was encoded.
// Use Close when done to release resources.
type Reader interface {
	io.ReadCloser

	// MaxMem returns the *maximum* memory required to decode the stream.
	MaxMem() int
}

//
type fixedMemReader struct {
	blocks       []*rblock
	in           io.Reader
	stream       *bufio.Reader
	size         int
	maxLength    uint64 // Maxmimum backreference count
	curBlock     int
	curData      []byte
	ready        chan *rblock
	closeReader  chan struct{}
	readerClosed chan struct{}
}

// rblock contains read information about a single block
type rblock struct {
	data     []byte
	readData int
	first    int   // Index of first occurrence
	last     int   // Index of last occurrence
	err      error // Read error?
}

func (r *rblock) String() string {
	if r == nil {
		return "<nil>"
	}
	return fmt.Sprintf("{Read:%d; [%d:%d]}", r.readData, r.first, r.last)
}

var ErrUnknownFormat = errors.New("unknown index format")

// NewReader returns a reader that will decode the supplied index and data stream.
//
// This is compatible content from the NewWriter function.
//
// When you are done with the Reader, use Close to release resources.
func NewReader(index io.Reader, blocks io.Reader) (Reader, error) {
	f := &fixedMemReader{
		in:           blocks,
		ready:        make(chan *rblock, 8), // Read up to 8 blocks ahead
		closeReader:  make(chan struct{}, 0),
		readerClosed: make(chan struct{}, 0),
		curBlock:     0,
	}
	idx := bufio.NewReader(index)
	format, err := binary.ReadUvarint(idx)
	if err != nil {
		return nil, err
	}

	switch format {
	case 1:
		err = f.readFormat1(idx)
	default:
		err = ErrUnknownFormat
	}
	go f.blockReader()

	//fmt.Println(f.blocks)
	return f, err
}

// NewStreamReader returns a reader that will decode the supplied data stream.
//
// This is compatible content from the NewStreamWriter function.
//
// When you are done with the Reader, use Close to release resources.
func NewStreamReader(in io.Reader) (Reader, error) {
	f := &fixedMemReader{
		ready:        make(chan *rblock, 8), // Read up to 8 blocks ahead
		closeReader:  make(chan struct{}, 0),
		readerClosed: make(chan struct{}, 0),
		curBlock:     0,
	}
	br := bufio.NewReader(in)
	format, err := binary.ReadUvarint(br)
	if err != nil {
		return nil, err
	}

	switch format {
	case 2:
		err = f.readFormat2(br)
		if err != nil {
			return nil, err
		}
	default:
		return nil, ErrUnknownFormat
	}

	f.stream = br
	go f.streamReader()

	return f, nil
}

// NewSeekRead returns a reader that will decode the supplied index and data stream.
//
// This is compatible content from the NewWriter function.
//
// No blocks will be kept in memory, but the block data input must be seekable.
//
// When you are done with the Reader, use Close to release resources.
func NewSeekReader(index io.Reader, blocks io.ReadSeeker) (Reader, error) {
	f := &fixedMemReader{
		in:           blocks,
		ready:        make(chan *rblock, 8), // Read up to 8 blocks ahead
		closeReader:  make(chan struct{}, 0),
		readerClosed: make(chan struct{}, 0),
		curBlock:     0,
	}
	idx := bufio.NewReader(index)
	format, err := binary.ReadUvarint(idx)
	if err != nil {
		return nil, err
	}

	switch format {
	case 1:
		err = f.readFormat1(idx)
	default:
		err = ErrUnknownFormat
	}
	go f.blockReader()

	//fmt.Println(f.blocks)
	return f, err
}

// NewStreamReader returns a reader that will decode the supplied data stream.
//
// This is compatible content from the NewStreamWriter function.
//
// No blocks will be kept in memory, but the block data input must be seekable.
//
// When you are done with the Reader, use Close to release resources.
func NewSeekStreamReader(in io.ReadSeeker) (Reader, error) {
	f := &fixedMemReader{
		ready:        make(chan *rblock, 8), // Read up to 8 blocks ahead
		closeReader:  make(chan struct{}, 0),
		readerClosed: make(chan struct{}, 0),
		curBlock:     0,
	}
	br := bufio.NewReader(in)
	format, err := binary.ReadUvarint(br)
	if err != nil {
		return nil, err
	}

	switch format {
	case 2:
		err = f.readFormat2(br)
		if err != nil {
			return nil, err
		}
	default:
		return nil, ErrUnknownFormat
	}

	f.stream = br
	go f.streamReader()

	return f, nil
}

// readFormat1 will read the index of format 1
// and prepare decoding
func (f *fixedMemReader) readFormat1(idx io.ByteReader) error {
	size, err := binary.ReadUvarint(idx)
	if err != nil {
		return err
	}
	f.size = int(size)

	// Insert empty block 0
	f.blocks = append(f.blocks, nil)
	i := 0
	// Read blocks
	for {
		i++
		offset, err := binary.ReadUvarint(idx)
		if err != nil {
			return err
		}
		switch offset {
		// new block
		case 0:
			r, err := binary.ReadUvarint(idx)
			if err != nil {
				return err
			}
			f.blocks = append(f.blocks, &rblock{first: i, last: i, readData: int(size - r)})

		// Last block
		case math.MaxUint64:
			r, err := binary.ReadUvarint(idx)
			if err != nil {
				return err
			}
			f.blocks = append(f.blocks, &rblock{readData: int(size - r)})
			return nil
		// Deduplicated block
		default:
			pos := len(f.blocks) - int(offset)
			if pos <= 0 || pos >= len(f.blocks) {
				return fmt.Errorf("invalid offset encountered at block %d, offset was %d", len(f.blocks), offset)
			}
			// Update last position.
			org := f.blocks[pos]
			org.last = i
			f.blocks = append(f.blocks, org)
		}
	}
	return nil
}

// readFormat2 will read the header data of format 2
// and stop at the first block.
func (f *fixedMemReader) readFormat2(rd io.ByteReader) error {
	size, err := binary.ReadUvarint(rd)
	if err != nil {
		return err
	}
	if size < MinBlockSize {
		return ErrSizeTooSmall
	}
	f.size = int(size)

	maxLength, err := binary.ReadUvarint(rd)
	if err != nil {
		return err
	}
	if maxLength < 1 {
		return ErrMaxBlocksTooSmall
	}
	f.maxLength = maxLength
	return nil
}

// Read will read from the input stream and return the
// deduplicated data.
func (f *fixedMemReader) Read(b []byte) (int, error) {
	read := 0
	for len(b) > 0 {
		// Read next
		if len(f.curData) == 0 {
			f.curBlock++
			next, ok := <-f.ready
			if !ok {
				return read, io.EOF
			}
			if next.err != nil {
				return read, next.err
			}
			f.curData = next.data
			// We don't want to keep it, if this is the last block
			if f.curBlock == next.last {
				next.data = nil
			}
			if len(f.curData) == 0 {
				continue
			}
		}
		n := copy(b, f.curData)
		read += n
		b = b[n:]
		f.curData = f.curData[n:]
	}
	return read, nil
}

// MaxMem returns the estimated maximum RAM usage needed to
// unpack this content.
func (f *fixedMemReader) MaxMem() int {
	if f.maxLength > 0 {
		return int(f.maxLength) * f.size
	}
	i := 1 // Current block
	curUse := 0
	maxUse := 0
	for {
		b := f.blocks[i]
		if b.first == i {
			curUse += b.readData
		}
		if curUse > maxUse {
			maxUse = curUse
		}

		if b.last == i {
			curUse -= b.readData
		}

		i++
		// We read them all
		if i == len(f.blocks) {
			break
		}
	}
	return maxUse
}

// blockReader will read format 1 blocks and deliver them
// to the ready channel.
// The function will return if the stream is finished,
// or an error occurs
func (f *fixedMemReader) blockReader() {
	defer close(f.readerClosed)
	defer close(f.ready)

	i := 1 // Current block
	totalRead := 0
	for {
		b := f.blocks[i]
		// Read it?
		if len(b.data) != b.readData {
			b.data = make([]byte, b.readData)
			n, err := io.ReadFull(f.in, b.data)
			if err != nil {
				b.err = err
			} else if n != b.readData {
				b.err = io.ErrUnexpectedEOF
			}
			totalRead += n
		}
		// Send or close
		select {
		case <-f.closeReader:
			return
		case f.ready <- b:
		}
		// Exit because of an error
		if b.err != nil {
			return
		}
		i++
		// We read them all
		if i == len(f.blocks) {
			return
		}
	}
	return
}

// streamReader will read blocks from a single stream
// and deliver them to the "ready" channel.
// The function will return if an error occurs or
// the stream is finished.
func (f *fixedMemReader) streamReader() {
	defer close(f.readerClosed)
	defer close(f.ready)

	totalRead := 0

	// Create backreference buffers
	blocks := make([][]byte, f.maxLength)
	for i := range blocks {
		blocks[i] = make([]byte, f.size)
	}

	i := uint64(1) // Current block
	for {
		b := &rblock{}
		lastBlock := false

		b.err = func() error {
			offset, err := binary.ReadUvarint(f.stream)
			if err != nil {
				return err
			}
			// Read it?
			if offset == 0 || offset == math.MaxUint64 {
				s, err := binary.ReadUvarint(f.stream)
				if err != nil {
					return err
				}
				size := f.size - int(s)
				if size > f.size || size <= 0 {
					return fmt.Errorf("invalid size encountered at block %d, size was %d", i, size)
				}
				b.data = make([]byte, size)
				n, err := io.ReadFull(f.stream, b.data)
				if err != nil {
					return err
				} else if n != len(b.data) {
					return io.ErrUnexpectedEOF
				}
				totalRead += n
				if offset == math.MaxUint64 {
					lastBlock = true
				}
			} else {
				if offset > f.maxLength {
					return fmt.Errorf("invalid offset encountered at block %d, offset was %d", i, offset)
				}
				pos := i - offset
				if pos <= 0 {
					return fmt.Errorf("invalid offset encountered at block %d, offset was %d", i, offset)
				}
				src := blocks[pos%f.maxLength]
				b.data = src
			}

			blocks[i%f.maxLength] = b.data
			return nil
		}()
		// Send or close
		select {
		case <-f.closeReader:
			return
		case f.ready <- b:
		}
		// Exit because of an error
		if b.err != nil || lastBlock {
			return
		}
		i++
	}
	return
}

// Close the reader and shut down the running goroutines.
func (f *fixedMemReader) Close() error {
	select {
	case <-f.readerClosed:
	case f.closeReader <- struct{}{}:
		<-f.readerClosed
	}
	return nil
}
<commit_msg>Remove unreachable returns.<commit_after>package dedup

import (
	"bufio"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"math"
)

// A reader will decode a deduplicated stream and
// return the data as it was encoded.
// Use Close when done to release resources.
type Reader interface {
	io.ReadCloser

	// MaxMem returns the *maximum* memory required to decode the stream.
	MaxMem() int
}

//
type fixedMemReader struct {
	blocks       []*rblock
	in           io.Reader
	stream       *bufio.Reader
	size         int
	maxLength    uint64 // Maxmimum backreference count
	curBlock     int
	curData      []byte
	ready        chan *rblock
	closeReader  chan struct{}
	readerClosed chan struct{}
}

// rblock contains read information about a single block
type rblock struct {
	data     []byte
	readData int
	first    int   // Index of first occurrence
	last     int   // Index of last occurrence
	err      error // Read error?
}

func (r *rblock) String() string {
	if r == nil {
		return "<nil>"
	}
	return fmt.Sprintf("{Read:%d; [%d:%d]}", r.readData, r.first, r.last)
}

var ErrUnknownFormat = errors.New("unknown index format")

// NewReader returns a reader that will decode the supplied index and data stream.
//
// This is compatible content from the NewWriter function.
//
// When you are done with the Reader, use Close to release resources.
func NewReader(index io.Reader, blocks io.Reader) (Reader, error) {
	f := &fixedMemReader{
		in:           blocks,
		ready:        make(chan *rblock, 8), // Read up to 8 blocks ahead
		closeReader:  make(chan struct{}, 0),
		readerClosed: make(chan struct{}, 0),
		curBlock:     0,
	}
	idx := bufio.NewReader(index)
	format, err := binary.ReadUvarint(idx)
	if err != nil {
		return nil, err
	}

	switch format {
	case 1:
		err = f.readFormat1(idx)
	default:
		err = ErrUnknownFormat
	}
	go f.blockReader()

	//fmt.Println(f.blocks)
	return f, err
}

// NewStreamReader returns a reader that will decode the supplied data stream.
//
// This is compatible content from the NewStreamWriter function.
//
// When you are done with the Reader, use Close to release resources.
func NewStreamReader(in io.Reader) (Reader, error) {
	f := &fixedMemReader{
		ready:        make(chan *rblock, 8), // Read up to 8 blocks ahead
		closeReader:  make(chan struct{}, 0),
		readerClosed: make(chan struct{}, 0),
		curBlock:     0,
	}
	br := bufio.NewReader(in)
	format, err := binary.ReadUvarint(br)
	if err != nil {
		return nil, err
	}

	switch format {
	case 2:
		err = f.readFormat2(br)
		if err != nil {
			return nil, err
		}
	default:
		return nil, ErrUnknownFormat
	}

	f.stream = br
	go f.streamReader()

	return f, nil
}

// NewSeekRead returns a reader that will decode the supplied index and data stream.
//
// This is compatible content from the NewWriter function.
//
// No blocks will be kept in memory, but the block data input must be seekable.
//
// When you are done with the Reader, use Close to release resources.
func NewSeekReader(index io.Reader, blocks io.ReadSeeker) (Reader, error) {
	f := &fixedMemReader{
		in:           blocks,
		ready:        make(chan *rblock, 8), // Read up to 8 blocks ahead
		closeReader:  make(chan struct{}, 0),
		readerClosed: make(chan struct{}, 0),
		curBlock:     0,
	}
	idx := bufio.NewReader(index)
	format, err := binary.ReadUvarint(idx)
	if err != nil {
		return nil, err
	}

	switch format {
	case 1:
		err = f.readFormat1(idx)
	default:
		err = ErrUnknownFormat
	}
	go f.blockReader()

	//fmt.Println(f.blocks)
	return f, err
}

// NewStreamReader returns a reader that will decode the supplied data stream.
//
// This is compatible content from the NewStreamWriter function.
//
// No blocks will be kept in memory, but the block data input must be seekable.
//
// When you are done with the Reader, use Close to release resources.
func NewSeekStreamReader(in io.ReadSeeker) (Reader, error) {
	f := &fixedMemReader{
		ready:        make(chan *rblock, 8), // Read up to 8 blocks ahead
		closeReader:  make(chan struct{}, 0),
		readerClosed: make(chan struct{}, 0),
		curBlock:     0,
	}
	br := bufio.NewReader(in)
	format, err := binary.ReadUvarint(br)
	if err != nil {
		return nil, err
	}

	switch format {
	case 2:
		err = f.readFormat2(br)
		if err != nil {
			return nil, err
		}
	default:
		return nil, ErrUnknownFormat
	}

	f.stream = br
	go f.streamReader()

	return f, nil
}

// readFormat1 will read the index of format 1
// and prepare decoding
func (f *fixedMemReader) readFormat1(idx io.ByteReader) error {
	size, err := binary.ReadUvarint(idx)
	if err != nil {
		return err
	}
	f.size = int(size)

	// Insert empty block 0
	f.blocks = append(f.blocks, nil)
	i := 0
	// Read blocks
	for {
		i++
		offset, err := binary.ReadUvarint(idx)
		if err != nil {
			return err
		}
		switch offset {
		// new block
		case 0:
			r, err := binary.ReadUvarint(idx)
			if err != nil {
				return err
			}
			f.blocks = append(f.blocks, &rblock{first: i, last: i, readData: int(size - r)})

		// Last block
		case math.MaxUint64:
			r, err := binary.ReadUvarint(idx)
			if err != nil {
				return err
			}
			f.blocks = append(f.blocks, &rblock{readData: int(size - r)})
			return nil
		// Deduplicated block
		default:
			pos := len(f.blocks) - int(offset)
			if pos <= 0 || pos >= len(f.blocks) {
				return fmt.Errorf("invalid offset encountered at block %d, offset was %d", len(f.blocks), offset)
			}
			// Update last position.
			org := f.blocks[pos]
			org.last = i
			f.blocks = append(f.blocks, org)
		}
	}
}

// readFormat2 will read the header data of format 2
// and stop at the first block.
func (f *fixedMemReader) readFormat2(rd io.ByteReader) error {
	size, err := binary.ReadUvarint(rd)
	if err != nil {
		return err
	}
	if size < MinBlockSize {
		return ErrSizeTooSmall
	}
	f.size = int(size)

	maxLength, err := binary.ReadUvarint(rd)
	if err != nil {
		return err
	}
	if maxLength < 1 {
		return ErrMaxBlocksTooSmall
	}
	f.maxLength = maxLength
	return nil
}

// Read will read from the input stream and return the
// deduplicated data.
func (f *fixedMemReader) Read(b []byte) (int, error) {
	read := 0
	for len(b) > 0 {
		// Read next
		if len(f.curData) == 0 {
			f.curBlock++
			next, ok := <-f.ready
			if !ok {
				return read, io.EOF
			}
			if next.err != nil {
				return read, next.err
			}
			f.curData = next.data
			// We don't want to keep it, if this is the last block
			if f.curBlock == next.last {
				next.data = nil
			}
			if len(f.curData) == 0 {
				continue
			}
		}
		n := copy(b, f.curData)
		read += n
		b = b[n:]
		f.curData = f.curData[n:]
	}
	return read, nil
}

// MaxMem returns the estimated maximum RAM usage needed to
// unpack this content.
func (f *fixedMemReader) MaxMem() int {
	if f.maxLength > 0 {
		return int(f.maxLength) * f.size
	}
	i := 1 // Current block
	curUse := 0
	maxUse := 0
	for {
		b := f.blocks[i]
		if b.first == i {
			curUse += b.readData
		}
		if curUse > maxUse {
			maxUse = curUse
		}

		if b.last == i {
			curUse -= b.readData
		}

		i++
		// We read them all
		if i == len(f.blocks) {
			break
		}
	}
	return maxUse
}

// blockReader will read format 1 blocks and deliver them
// to the ready channel.
// The function will return if the stream is finished,
// or an error occurs
func (f *fixedMemReader) blockReader() {
	defer close(f.readerClosed)
	defer close(f.ready)

	i := 1 // Current block
	totalRead := 0
	for {
		b := f.blocks[i]
		// Read it?
		if len(b.data) != b.readData {
			b.data = make([]byte, b.readData)
			n, err := io.ReadFull(f.in, b.data)
			if err != nil {
				b.err = err
			} else if n != b.readData {
				b.err = io.ErrUnexpectedEOF
			}
			totalRead += n
		}
		// Send or close
		select {
		case <-f.closeReader:
			return
		case f.ready <- b:
		}
		// Exit because of an error
		if b.err != nil {
			return
		}
		i++
		// We read them all
		if i == len(f.blocks) {
			return
		}
	}
}

// streamReader will read blocks from a single stream
// and deliver them to the "ready" channel.
// The function will return if an error occurs or
// the stream is finished.
func (f *fixedMemReader) streamReader() {
	defer close(f.readerClosed)
	defer close(f.ready)

	totalRead := 0

	// Create backreference buffers
	blocks := make([][]byte, f.maxLength)
	for i := range blocks {
		blocks[i] = make([]byte, f.size)
	}

	i := uint64(1) // Current block
	for {
		b := &rblock{}
		lastBlock := false

		b.err = func() error {
			offset, err := binary.ReadUvarint(f.stream)
			if err != nil {
				return err
			}
			// Read it?
			if offset == 0 || offset == math.MaxUint64 {
				s, err := binary.ReadUvarint(f.stream)
				if err != nil {
					return err
				}
				size := f.size - int(s)
				if size > f.size || size <= 0 {
					return fmt.Errorf("invalid size encountered at block %d, size was %d", i, size)
				}
				b.data = make([]byte, size)
				n, err := io.ReadFull(f.stream, b.data)
				if err != nil {
					return err
				} else if n != len(b.data) {
					return io.ErrUnexpectedEOF
				}
				totalRead += n
				if offset == math.MaxUint64 {
					lastBlock = true
				}
			} else {
				if offset > f.maxLength {
					return fmt.Errorf("invalid offset encountered at block %d, offset was %d", i, offset)
				}
				pos := i - offset
				if pos <= 0 {
					return fmt.Errorf("invalid offset encountered at block %d, offset was %d", i, offset)
				}
				src := blocks[pos%f.maxLength]
				b.data = src
			}

			blocks[i%f.maxLength] = b.data
			return nil
		}()
		// Send or close
		select {
		case <-f.closeReader:
			return
		case f.ready <- b:
		}
		// Exit because of an error
		if b.err != nil || lastBlock {
			return
		}
		i++
	}
}

// Close the reader and shut down the running goroutines.
func (f *fixedMemReader) Close() error {
	select {
	case <-f.readerClosed:
	case f.closeReader <- struct{}{}:
		<-f.readerClosed
	}
	return nil
}
<|endoftext|>


<commit_before>// Command apidiff determines whether two versions of a package are compatible
package main

import (
	"flag"
	"fmt"
	"go/token"
	"go/types"
	"os"

	"golang.org/x/exp/apidiff"
	"golang.org/x/tools/go/gcexportdata"
	"golang.org/x/tools/go/packages"
)

var (
	exportDataOutfile = flag.String("w", "", "file for export data")
	incompatibleOnly  = flag.Bool("incompatible", false, "display only incompatible changes")
)

func main() {
	flag.Usage = func() {
		w := flag.CommandLine.Output()
		fmt.Fprintf(w, "usage:\n")
		fmt.Fprintf(w, "apidiff OLD NEW\n")
		fmt.Fprintf(w, "   compares OLD and NEW package APIs\n")
		fmt.Fprintf(w, "   where OLD and NEW are either import paths or files of export data\n")
		fmt.Fprintf(w, "apidiff -w FILE IMPORT_PATH\n")
		fmt.Fprintf(w, "   writes export data of the package at IMPORT_PATH to FILE\n")
		flag.PrintDefaults()
	}

	flag.Parse()
	if *exportDataOutfile != "" {
		if len(flag.Args()) != 1 {
			flag.Usage()
		}
		pkg := mustLoadPackage(flag.Arg(0))
		if err := writeExportData(pkg, *exportDataOutfile); err != nil {
			die("writing export data: %v", err)
		}
	} else {
		if len(flag.Args()) != 2 {
			flag.Usage()
		}
		oldpkg := mustLoadOrRead(flag.Arg(0))
		newpkg := mustLoadOrRead(flag.Arg(1))

		report := apidiff.Changes(oldpkg, newpkg)
		var err error
		if *incompatibleOnly {
			err = report.TextIncompatible(os.Stdout)
		} else {
			err = report.Text(os.Stdout)
		}
		if err != nil {
			die("writing report: %v", err)
		}
	}
}

func mustLoadOrRead(importPathOrFile string) *types.Package {
	fileInfo, err := os.Stat(importPathOrFile)
	if err == nil && fileInfo.Mode().IsRegular() {
		pkg, err := readExportData(importPathOrFile)
		if err != nil {
			die("reading export data from %s: %v", importPathOrFile, err)
		}
		return pkg
	} else {
		return mustLoadPackage(importPathOrFile).Types
	}
}

func mustLoadPackage(importPath string) *packages.Package {
	pkg, err := loadPackage(importPath)
	if err != nil {
		die("loading %s: %v", importPath, err)
	}
	return pkg
}

func loadPackage(importPath string) (*packages.Package, error) {
	cfg := &packages.Config{Mode: packages.LoadTypes}
	pkgs, err := packages.Load(cfg, importPath)
	if err != nil {
		return nil, err
	}
	if len(pkgs[0].Errors) > 0 {
		return nil, pkgs[0].Errors[0]
	}
	return pkgs[0], nil
}

func readExportData(filename string) (*types.Package, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return gcexportdata.Read(f, token.NewFileSet(), map[string]*types.Package{}, filename)
}

func writeExportData(pkg *packages.Package, filename string) error {
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	err1 := gcexportdata.Write(f, pkg.Fset, pkg.Types)
	err2 := f.Close()
	if err1 != nil {
		return err1
	}
	return err2
}

func die(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, format+"\n", args...)
	os.Exit(1)
}
<commit_msg>cmd/apidiff: add additional documentation module cache behavior<commit_after>// Command apidiff determines whether two versions of a package are compatible
package main

import (
	"flag"
	"fmt"
	"go/token"
	"go/types"
	"os"

	"golang.org/x/exp/apidiff"
	"golang.org/x/tools/go/gcexportdata"
	"golang.org/x/tools/go/packages"
)

var (
	exportDataOutfile = flag.String("w", "", "file for export data")
	incompatibleOnly  = flag.Bool("incompatible", false, "display only incompatible changes")
)

func main() {
	flag.Usage = func() {
		w := flag.CommandLine.Output()
		fmt.Fprintf(w, "usage:\n")
		fmt.Fprintf(w, "apidiff OLD NEW\n")
		fmt.Fprintf(w, "   compares OLD and NEW package APIs\n")
		fmt.Fprintf(w, "   where OLD and NEW are either import paths or files of export data\n")
		fmt.Fprintf(w, "apidiff -w FILE IMPORT_PATH\n")
		fmt.Fprintf(w, "   writes export data of the package at IMPORT_PATH to FILE\n")
		fmt.Fprintf(w, "   NOTE: In a GOPATH-less environment, this option consults the\n")
		fmt.Fprintf(w, "   module cache by default, unless used in the directory that\n")
		fmt.Fprintf(w, "   contains the go.mod module definition that IMPORT_PATH belongs\n")
		fmt.Fprintf(w, "   to. In most cases users want the latter behavior, so be sure\n")
		fmt.Fprintf(w, "   to cd to the exact directory which contains the module\n")
		fmt.Fprintf(w, "   definition of IMPORT_PATH.\n")
		flag.PrintDefaults()
	}

	flag.Parse()
	if *exportDataOutfile != "" {
		if len(flag.Args()) != 1 {
			flag.Usage()
		}
		pkg := mustLoadPackage(flag.Arg(0))
		if err := writeExportData(pkg, *exportDataOutfile); err != nil {
			die("writing export data: %v", err)
		}
	} else {
		if len(flag.Args()) != 2 {
			flag.Usage()
		}
		oldpkg := mustLoadOrRead(flag.Arg(0))
		newpkg := mustLoadOrRead(flag.Arg(1))

		report := apidiff.Changes(oldpkg, newpkg)
		var err error
		if *incompatibleOnly {
			err = report.TextIncompatible(os.Stdout)
		} else {
			err = report.Text(os.Stdout)
		}
		if err != nil {
			die("writing report: %v", err)
		}
	}
}

func mustLoadOrRead(importPathOrFile string) *types.Package {
	fileInfo, err := os.Stat(importPathOrFile)
	if err == nil && fileInfo.Mode().IsRegular() {
		pkg, err := readExportData(importPathOrFile)
		if err != nil {
			die("reading export data from %s: %v", importPathOrFile, err)
		}
		return pkg
	} else {
		return mustLoadPackage(importPathOrFile).Types
	}
}

func mustLoadPackage(importPath string) *packages.Package {
	pkg, err := loadPackage(importPath)
	if err != nil {
		die("loading %s: %v", importPath, err)
	}
	return pkg
}

func loadPackage(importPath string) (*packages.Package, error) {
	cfg := &packages.Config{Mode: packages.LoadTypes}
	pkgs, err := packages.Load(cfg, importPath)
	if err != nil {
		return nil, err
	}
	if len(pkgs[0].Errors) > 0 {
		return nil, pkgs[0].Errors[0]
	}
	return pkgs[0], nil
}

func readExportData(filename string) (*types.Package, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return gcexportdata.Read(f, token.NewFileSet(), map[string]*types.Package{}, filename)
}

func writeExportData(pkg *packages.Package, filename string) error {
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	err1 := gcexportdata.Write(f, pkg.Fset, pkg.Types)
	err2 := f.Close()
	if err1 != nil {
		return err1
	}
	return err2
}

func die(format string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, format+"\n", args...)
	os.Exit(1)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/ActiveState/log"
	"github.com/alecthomas/gozmq"
	"logyard"
	"logyard/drain"
	"os"
	"os/signal"
	"stackato/server"
	"syscall"
)

func main() {
	major, minor, patch := gozmq.Version()
	log.Infof("Starting logyard (zeromq %d.%d.%d)", major, minor, patch)

	m := drain.NewDrainManager()
	log.Info("Starting drain manager")
	go m.Run()
	// SIGTERM handle for stopping running drains.
	go func() {
		sigchan := make(chan os.Signal)
		signal.Notify(sigchan, syscall.SIGTERM)
		<-sigchan
		log.Info("Stopping all drains before exiting")
		m.Stop()
		log.Info("Exiting now.")
		os.Exit(0)
	}()

	server.MarkRunning("logyard")

	log.Info("Running pubsub broker")
	log.Fatal(logyard.Broker.Run())
}
<commit_msg>display Go version in logyard.log<commit_after>package main

import (
	"github.com/ActiveState/log"
	"github.com/alecthomas/gozmq"
	"logyard"
	"logyard/drain"
	"os"
	"os/signal"
	"runtime"
	"stackato/server"
	"syscall"
)

func main() {
	major, minor, patch := gozmq.Version()
	log.Infof("Starting logyard (Go %s; ZeroMQ %d.%d.%d)",
		runtime.Version(), major, minor, patch)

	m := drain.NewDrainManager()
	log.Info("Starting drain manager")
	go m.Run()
	// SIGTERM handle for stopping running drains.
	go func() {
		sigchan := make(chan os.Signal)
		signal.Notify(sigchan, syscall.SIGTERM)
		<-sigchan
		log.Info("Stopping all drains before exiting")
		m.Stop()
		log.Info("Exiting now.")
		os.Exit(0)
	}()

	server.MarkRunning("logyard")

	log.Info("Running pubsub broker")
	log.Fatal(logyard.Broker.Run())
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"io/ioutil"
	"net/http"
	"os"
	"os/signal"
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/feedhenry/mcp-standalone/pkg/data"
	"github.com/feedhenry/mcp-standalone/pkg/httpclient"
	"github.com/feedhenry/mcp-standalone/pkg/k8s"
	"github.com/feedhenry/mcp-standalone/pkg/mobile"
	"github.com/feedhenry/mcp-standalone/pkg/mobile/app"
	"github.com/feedhenry/mcp-standalone/pkg/mobile/integration"
	"github.com/feedhenry/mcp-standalone/pkg/mobile/metrics"
	"github.com/feedhenry/mcp-standalone/pkg/openshift"
	"github.com/feedhenry/mcp-standalone/pkg/web"
	"github.com/feedhenry/mcp-standalone/pkg/web/middleware"
	"github.com/pkg/errors"
)

func main() {
	var (
		router          = web.NewRouter()
		port            = flag.String("port", ":3001", "set the port to listen on")
		insecure        = flag.String("insecure", "false", "allow insecure requests")
		cert            = flag.String("cert", "server.crt", "SSL/TLS Certificate to HTTPS")
		key             = flag.String("key", "server.key", "SSL/TLS Private Key for the Certificate")
		namespace       = flag.String("namespace", os.Getenv("NAMESPACE"), "the namespace to target")
		logLevel        = flag.String("log-level", "error", "the level to log at")
		saTokenPath     = flag.String("satoken-path", "var/run/secrets/kubernetes.io/serviceaccount/token", "where on disk the service account token to use is ")
		staticDirectory = flag.String("web-dir", "./web/app", "Location of static content to serve at /console. index.html will be used as a fallback for requested files that don't exist")
		k8host          string
	)
	flag.StringVar(&k8host, "k8-host", "", "kubernetes target")
	flag.Parse()

	switch *logLevel {
	case "debug":
		logrus.SetLevel(logrus.DebugLevel)
	case "info":
		logrus.SetLevel(logrus.InfoLevel)
	case "error":
		logrus.SetLevel(logrus.ErrorLevel)
	default:
		logrus.SetLevel(logrus.ErrorLevel)
	}
	logger := logrus.StandardLogger()

	logger.Info("insecure request set to ", *insecure)

	if *namespace == "" {
		logger.Fatal("-namespace is a required flag or it can be set via NAMESPACE env var")
	}

	token, err := readSAToken(*saTokenPath)
	if err != nil {
		panic(err)
	}

	if k8host == "" {
		k8host = "https://" + os.Getenv("KUBERNETES_SERVICE_HOST") + ":" + os.Getenv("KUBERNETES_SERVICE_PORT")
	}

	var (
		insecureRequests = *insecure == "true"
		incluster        = os.Getenv("KUBERNETES_SERVICE_HOST") != ""
		//setup out builders
		k8ClientBuilder    = k8s.NewClientBuilder(*namespace, k8host, insecureRequests)
		mounterBuilder     = k8s.NewMounterBuilder(k8ClientBuilder, *namespace, token)
		appRepoBuilder     = data.NewMobileAppRepoBuilder(k8ClientBuilder, *namespace, token)
		svcRepoBuilder     = data.NewServiceRepoBuilder(k8ClientBuilder, *namespace, token)
		authCheckerBuilder = openshift.NewAuthCheckerBuilder(k8host)
		userRepoBuilder    = openshift.NewUserRepoBuilder(k8host, insecureRequests).WithClient(&openshift.UserAccess{})
		httpClientBuilder  = httpclient.NewClientBuilder()
		defaultHTTPClient  = httpClientBuilder.Insecure(insecureRequests).Build()
		ocClientBuilder    = openshift.NewClientBuilder(k8host, *namespace, incluster, insecureRequests)
		buildRepoBuilder   = data.NewBuildsRepoBuilder(k8ClientBuilder, ocClientBuilder, *namespace, token)
		openshiftUser      = openshift.UserAccess{}
		mwAccess           = middleware.NewAccess(logger, k8host, openshiftUser.ReadUserFromToken)
		// these channels control when background proccess should stop
		stop = make(chan struct{})
		s    = make(chan os.Signal, 1)
	)

	// send a message to the signal channel for any interrupt type signals (ctl+c etc)
	signal.Notify(s, os.Interrupt)
	appService := &app.Service{}

	k8sMetadata, err := k8s.GetMetadata(k8host, defaultHTTPClient)
	if err != nil {
		panic(err)
	}

	// Ensure that the apiKey map exists
	{
		err := createAppAPIKeyMap(appRepoBuilder, token)
		if err != nil {
			panic(err)
		}
	}

	//kick off metrics scheduler
	{
		//TODO move time interval to config
		interval := time.NewTicker(5 * time.Second)
		gatherer := metrics.NewGathererScheduler(interval, stop, logger)

		// add metrics gatherers
		kcMetrics := metrics.NewKeycloak(httpClientBuilder, svcRepoBuilder, logger)
		gatherer.Add(kcMetrics.ServiceName, kcMetrics.Gather)

		// add fh-sync-server gatherers
		syncMetrics := metrics.NewFhSyncServer(httpClientBuilder, svcRepoBuilder, logger)
		gatherer.Add(syncMetrics.ServiceName, syncMetrics.Gather)

		// start collecting metrics
		go gatherer.Run()
	}

	//mobileapp handler
	{
		appHandler := web.NewMobileAppHandler(logger, appRepoBuilder, appService)
		web.MobileAppRoute(router, appHandler)
	}

	//mobileservice handler
	{
		integrationSvc := integration.NewMobileSevice(*namespace)
		metricSvc := &metrics.MetricsService{}
		svcHandler := web.NewMobileServiceHandler(logger, integrationSvc, mounterBuilder, metricSvc, svcRepoBuilder, userRepoBuilder, authCheckerBuilder)
		web.MobileServiceRoute(router, svcHandler)
	}

	//sdk handler
	{
		sdkService := &integration.SDKService{}
		sdkHandler := web.NewSDKConfigHandler(logger, sdkService, svcRepoBuilder, appRepoBuilder)
		web.SDKConfigRoute(router, sdkHandler)
	}
	//sys handler
	{
		sysHandler := web.NewSysHandler(logger)
		web.SysRoute(router, sysHandler)
	}

	//build handler
	{
		buildSvc := app.NewBuild()
		buildHandler := web.NewBuildHandler(buildRepoBuilder, buildSvc, logger)
		web.MobileBuildRoute(router, buildHandler)
	}

	//console config handler
	var consoleMountPath = ""
	{
		k8MetaHost, err := k8sMetadata.GetK8IssuerHost()
		if err != nil {
			panic(err)
		}
		consoleConfigHandler := web.NewConsoleConfigHandler(logger, k8MetaHost, k8sMetadata.AuthorizationEndpoint, *namespace)
		web.ConsoleConfigRoute(router, consoleConfigHandler)
	}

	//static handler
	{
		staticHandler := web.NewStaticHandler(logger, *staticDirectory, consoleMountPath, "index.html")
		web.StaticRoute(staticHandler)
	}
	handler := web.BuildHTTPHandler(router, mwAccess)
	server := http.Server{
		Addr:              *port,
		IdleTimeout:       time.Second * 60,
		ReadHeaderTimeout: time.Second * 5,
		WriteTimeout:      time.Second * 15,
		Handler:           handler,
	}

	logger.Info("starting server on port "+*port, " using key ", *key, " and cert ", *cert, "target namespace is ", *namespace)
	go func() {
		if err := server.ListenAndServeTLS(*cert, *key); err != nil {
			panic(err)
		}
	}()
	<-s //wait for interrupt
	close(stop)
}

func readSAToken(path string) (string, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return "", errors.Wrap(err, "failed to read service account token ")
	}
	return string(data), nil
}

func createAppAPIKeyMap(appRepoBuilder mobile.AppRepoBuilder, token string) error {
	appRepo, err := appRepoBuilder.WithToken(token).Build()
	if err != nil {
		return err
	}
	err = appRepo.CreateAPIKeyMap()
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>add sigterm to signals<commit_after>package main

import (
	"flag"
	"io/ioutil"
	"net/http"
	"os"
	"os/signal"
	"time"

	"syscall"

	"github.com/Sirupsen/logrus"
	"github.com/feedhenry/mcp-standalone/pkg/data"
	"github.com/feedhenry/mcp-standalone/pkg/httpclient"
	"github.com/feedhenry/mcp-standalone/pkg/k8s"
	"github.com/feedhenry/mcp-standalone/pkg/mobile"
	"github.com/feedhenry/mcp-standalone/pkg/mobile/app"
	"github.com/feedhenry/mcp-standalone/pkg/mobile/integration"
	"github.com/feedhenry/mcp-standalone/pkg/mobile/metrics"
	"github.com/feedhenry/mcp-standalone/pkg/openshift"
	"github.com/feedhenry/mcp-standalone/pkg/web"
	"github.com/feedhenry/mcp-standalone/pkg/web/middleware"
	"github.com/pkg/errors"
)

func main() {
	var (
		router          = web.NewRouter()
		port            = flag.String("port", ":3001", "set the port to listen on")
		insecure        = flag.String("insecure", "false", "allow insecure requests")
		cert            = flag.String("cert", "server.crt", "SSL/TLS Certificate to HTTPS")
		key             = flag.String("key", "server.key", "SSL/TLS Private Key for the Certificate")
		namespace       = flag.String("namespace", os.Getenv("NAMESPACE"), "the namespace to target")
		logLevel        = flag.String("log-level", "error", "the level to log at")
		saTokenPath     = flag.String("satoken-path", "var/run/secrets/kubernetes.io/serviceaccount/token", "where on disk the service account token to use is ")
		staticDirectory = flag.String("web-dir", "./web/app", "Location of static content to serve at /console. index.html will be used as a fallback for requested files that don't exist")
		k8host          string
	)
	flag.StringVar(&k8host, "k8-host", "", "kubernetes target")
	flag.Parse()

	switch *logLevel {
	case "debug":
		logrus.SetLevel(logrus.DebugLevel)
	case "info":
		logrus.SetLevel(logrus.InfoLevel)
	case "error":
		logrus.SetLevel(logrus.ErrorLevel)
	default:
		logrus.SetLevel(logrus.ErrorLevel)
	}
	logger := logrus.StandardLogger()

	logger.Info("insecure request set to ", *insecure)

	if *namespace == "" {
		logger.Fatal("-namespace is a required flag or it can be set via NAMESPACE env var")
	}

	token, err := readSAToken(*saTokenPath)
	if err != nil {
		panic(err)
	}

	if k8host == "" {
		k8host = "https://" + os.Getenv("KUBERNETES_SERVICE_HOST") + ":" + os.Getenv("KUBERNETES_SERVICE_PORT")
	}

	var (
		insecureRequests = *insecure == "true"
		incluster        = os.Getenv("KUBERNETES_SERVICE_HOST") != ""
		//setup out builders
		k8ClientBuilder    = k8s.NewClientBuilder(*namespace, k8host, insecureRequests)
		mounterBuilder     = k8s.NewMounterBuilder(k8ClientBuilder, *namespace, token)
		appRepoBuilder     = data.NewMobileAppRepoBuilder(k8ClientBuilder, *namespace, token)
		svcRepoBuilder     = data.NewServiceRepoBuilder(k8ClientBuilder, *namespace, token)
		authCheckerBuilder = openshift.NewAuthCheckerBuilder(k8host)
		userRepoBuilder    = openshift.NewUserRepoBuilder(k8host, insecureRequests).WithClient(&openshift.UserAccess{})
		httpClientBuilder  = httpclient.NewClientBuilder()
		defaultHTTPClient  = httpClientBuilder.Insecure(insecureRequests).Build()
		ocClientBuilder    = openshift.NewClientBuilder(k8host, *namespace, incluster, insecureRequests)
		buildRepoBuilder   = data.NewBuildsRepoBuilder(k8ClientBuilder, ocClientBuilder, *namespace, token)
		openshiftUser      = openshift.UserAccess{}
		mwAccess           = middleware.NewAccess(logger, k8host, openshiftUser.ReadUserFromToken)
		// these channels control when background proccess should stop
		stop = make(chan struct{})
		s    = make(chan os.Signal, 1)
	)

	// send a message to the signal channel for any interrupt type signals (ctl+c etc)
	signal.Notify(s, os.Interrupt, syscall.SIGTERM)
	appService := &app.Service{}

	k8sMetadata, err := k8s.GetMetadata(k8host, defaultHTTPClient)
	if err != nil {
		panic(err)
	}

	// Ensure that the apiKey map exists
	{
		err := createAppAPIKeyMap(appRepoBuilder, token)
		if err != nil {
			panic(err)
		}
	}

	//kick off metrics scheduler
	{
		//TODO move time interval to config
		interval := time.NewTicker(5 * time.Second)
		gatherer := metrics.NewGathererScheduler(interval, stop, logger)

		// add metrics gatherers
		kcMetrics := metrics.NewKeycloak(httpClientBuilder, svcRepoBuilder, logger)
		gatherer.Add(kcMetrics.ServiceName, kcMetrics.Gather)

		// add fh-sync-server gatherers
		syncMetrics := metrics.NewFhSyncServer(httpClientBuilder, svcRepoBuilder, logger)
		gatherer.Add(syncMetrics.ServiceName, syncMetrics.Gather)

		// start collecting metrics
		go gatherer.Run()
	}

	//mobileapp handler
	{
		appHandler := web.NewMobileAppHandler(logger, appRepoBuilder, appService)
		web.MobileAppRoute(router, appHandler)
	}

	//mobileservice handler
	{
		integrationSvc := integration.NewMobileSevice(*namespace)
		metricSvc := &metrics.MetricsService{}
		svcHandler := web.NewMobileServiceHandler(logger, integrationSvc, mounterBuilder, metricSvc, svcRepoBuilder, userRepoBuilder, authCheckerBuilder)
		web.MobileServiceRoute(router, svcHandler)
	}

	//sdk handler
	{
		sdkService := &integration.SDKService{}
		sdkHandler := web.NewSDKConfigHandler(logger, sdkService, svcRepoBuilder, appRepoBuilder)
		web.SDKConfigRoute(router, sdkHandler)
	}
	//sys handler
	{
		sysHandler := web.NewSysHandler(logger)
		web.SysRoute(router, sysHandler)
	}

	//build handler
	{
		buildSvc := app.NewBuild()
		buildHandler := web.NewBuildHandler(buildRepoBuilder, buildSvc, logger)
		web.MobileBuildRoute(router, buildHandler)
	}

	//console config handler
	var consoleMountPath = ""
	{
		k8MetaHost, err := k8sMetadata.GetK8IssuerHost()
		if err != nil {
			panic(err)
		}
		consoleConfigHandler := web.NewConsoleConfigHandler(logger, k8MetaHost, k8sMetadata.AuthorizationEndpoint, *namespace)
		web.ConsoleConfigRoute(router, consoleConfigHandler)
	}

	//static handler
	{
		staticHandler := web.NewStaticHandler(logger, *staticDirectory, consoleMountPath, "index.html")
		web.StaticRoute(staticHandler)
	}
	handler := web.BuildHTTPHandler(router, mwAccess)
	server := http.Server{
		Addr:              *port,
		IdleTimeout:       time.Second * 60,
		ReadHeaderTimeout: time.Second * 5,
		WriteTimeout:      time.Second * 15,
		Handler:           handler,
	}

	logger.Info("starting server on port "+*port, " using key ", *key, " and cert ", *cert, "target namespace is ", *namespace)
	go func() {
		if err := server.ListenAndServeTLS(*cert, *key); err != nil {
			panic(err)
		}
	}()
	<-s //wait for interrupt
	close(stop)
}

func readSAToken(path string) (string, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return "", errors.Wrap(err, "failed to read service account token ")
	}
	return string(data), nil
}

func createAppAPIKeyMap(appRepoBuilder mobile.AppRepoBuilder, token string) error {
	appRepo, err := appRepoBuilder.WithToken(token).Build()
	if err != nil {
		return err
	}
	err = appRepo.CreateAPIKeyMap()
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2016 The nvim-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.

// nvim-go: a Go language development plugin for Neovim written in pure Go.
package main

import (
	"context"
	"flag"
	logpkg "log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"runtime"
	"syscall"

	"github.com/google/gops/agent"
	"github.com/neovim/go-client/nvim/plugin"
	"github.com/pkg/errors"
	"go.uber.org/zap"
	"golang.org/x/sync/errgroup"

	"github.com/zchee/nvim-go/pkg/autocmd"
	"github.com/zchee/nvim-go/pkg/buildctx"
	"github.com/zchee/nvim-go/pkg/command"
	"github.com/zchee/nvim-go/pkg/logger"
	"github.com/zchee/nvim-go/pkg/server"
)

var (
	pluginHost  = flag.String("manifest", "", "Write plugin manifest for `host` to stdout")
	vimFilePath = flag.String("location", "", "Manifest is automatically written to `.vim file`")
)

func main() {
	flag.Parse()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	zapLogger, undo := logger.NewRedirectZapLogger()
	defer undo()
	ctx = logger.NewContext(ctx, zapLogger)

	if *pluginHost != "" {
		fn := func(p *plugin.Plugin) error {
			return Main(ctx, p)
		}
		Plugin(fn)
		return
	}

	var eg = &errgroup.Group{}
	eg, ctx = errgroup.WithContext(ctx)
	eg.Go(func() error {
		fn := func(p *plugin.Plugin) error {
			return Main(ctx, p)
		}
		Plugin(fn)
		return nil
	})
	eg.Go(func() error {
		return Child(ctx)
	})
	go func() {
		if err := eg.Wait(); err != nil {
			logger.FromContext(ctx).Fatal("eg.Wait", zap.Error(err))
		}
	}()

	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
	select {
	case sig := <-sigc:
		switch sig {
		case syscall.SIGINT, syscall.SIGTERM:
			logger.FromContext(ctx).Info("catch signal", zap.String("name", sig.String()))
			cancel() // avoid goroutine leak
			return
		}
	}
}

func Main(ctx context.Context, p *plugin.Plugin) error {
	debug := os.Getenv("NVIM_GO_DEBUG") != ""
	pprof := os.Getenv("NVIM_GO_PPROF") != ""

	log := logger.FromContext(ctx).Named("main")
	ctx = logger.NewContext(ctx, log)

	buildctxt := buildctx.NewContext()
	c := command.Register(ctx, p, buildctxt)
	autocmd.Register(ctx, p, buildctxt, c)

	if debug {
		// starts the gops agent
		if err := agent.Listen(agent.Options{ShutdownCleanup: true}); err != nil {
			return err
		}

		if pprof {
			const addr = ":14715" // (n: 14)vim-(g: 7)(o: 15)
			log.Debug("start the pprof debugging", zap.String("listen at", addr))

			// enable the report of goroutine blocking events
			runtime.SetBlockProfileRate(1)
			go logpkg.Println(http.ListenAndServe(addr, nil))
		}
	}

	return nil
}

func Child(ctx context.Context) error {
	log := logger.FromContext(ctx).Named("child")
	ctx = logger.NewContext(ctx, log)

	s, err := server.NewServer(ctx)
	if err != nil {
		return errors.Wrap(err, "failed to create NewServer")
	}
	go s.Serve()
	defer func() {
		if err := s.Close(); err != nil {
			log.Fatal("Close", zap.Error(err))
		}
	}()

	bufs, err := s.Buffers()
	if err != nil {
		return errors.Wrap(err, "failed to get buffers")
	}
	// Get the names using a single atomic call to Nvim.
	names := make([]string, len(bufs))
	b := s.NewBatch()
	for i, buf := range bufs {
		b.BufferName(buf, &names[i])
	}

	if err := b.Execute(); err != nil {
		return errors.Wrap(err, "failed to execute batch")
	}

	for _, name := range names {
		log.Info("buffer", zap.String("name", name))
	}

	return nil
}
<commit_msg>cmd/nvim-go: remove gops/agent debug<commit_after>// Copyright 2016 The nvim-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.

// nvim-go: a Go language development plugin for Neovim written in pure Go.
package main

import (
	"context"
	"flag"
	logpkg "log"
	"net/http"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"runtime"
	"syscall"

	"github.com/neovim/go-client/nvim/plugin"
	"github.com/pkg/errors"
	"go.uber.org/zap"
	"golang.org/x/sync/errgroup"

	"github.com/zchee/nvim-go/pkg/autocmd"
	"github.com/zchee/nvim-go/pkg/buildctx"
	"github.com/zchee/nvim-go/pkg/command"
	"github.com/zchee/nvim-go/pkg/logger"
	"github.com/zchee/nvim-go/pkg/server"
)

var (
	pluginHost  = flag.String("manifest", "", "Write plugin manifest for `host` to stdout")
	vimFilePath = flag.String("location", "", "Manifest is automatically written to `.vim file`")
)

func main() {
	flag.Parse()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	zapLogger, undo := logger.NewRedirectZapLogger()
	defer undo()
	ctx = logger.NewContext(ctx, zapLogger)

	if *pluginHost != "" {
		fn := func(p *plugin.Plugin) error {
			return Main(ctx, p)
		}
		Plugin(fn)
		return
	}

	var eg = &errgroup.Group{}
	eg, ctx = errgroup.WithContext(ctx)
	eg.Go(func() error {
		fn := func(p *plugin.Plugin) error {
			return Main(ctx, p)
		}
		Plugin(fn)
		return nil
	})
	eg.Go(func() error {
		return Child(ctx)
	})
	go func() {
		if err := eg.Wait(); err != nil {
			logger.FromContext(ctx).Fatal("eg.Wait", zap.Error(err))
		}
	}()

	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
	select {
	case sig := <-sigc:
		switch sig {
		case syscall.SIGINT, syscall.SIGTERM:
			logger.FromContext(ctx).Info("catch signal", zap.String("name", sig.String()))
			cancel() // avoid goroutine leak
			return
		}
	}
}

func Main(ctx context.Context, p *plugin.Plugin) error {
	debug := os.Getenv("NVIM_GO_DEBUG") != ""

	log := logger.FromContext(ctx).Named("main")
	ctx = logger.NewContext(ctx, log)

	buildctxt := buildctx.NewContext()
	c := command.Register(ctx, p, buildctxt)
	autocmd.Register(ctx, p, buildctxt, c)

	if debug {
		const addr = ":14715" // (n: 14)vim-(g: 7)(o: 15)
		log.Debug("start the pprof debugging", zap.String("listen at", addr))

		// enable the report of goroutine blocking events
		runtime.SetBlockProfileRate(1)
		go logpkg.Println(http.ListenAndServe(addr, nil))
	}

	return nil
}

func Child(ctx context.Context) error {
	log := logger.FromContext(ctx).Named("child")
	ctx = logger.NewContext(ctx, log)

	s, err := server.NewServer(ctx)
	if err != nil {
		return errors.Wrap(err, "failed to create NewServer")
	}
	go s.Serve()
	defer func() {
		if err := s.Close(); err != nil {
			log.Fatal("Close", zap.Error(err))
		}
	}()

	bufs, err := s.Buffers()
	if err != nil {
		return errors.Wrap(err, "failed to get buffers")
	}
	// Get the names using a single atomic call to Nvim.
	names := make([]string, len(bufs))
	b := s.NewBatch()
	for i, buf := range bufs {
		b.BufferName(buf, &names[i])
	}

	if err := b.Execute(); err != nil {
		return errors.Wrap(err, "failed to execute batch")
	}

	for _, name := range names {
		log.Info("buffer", zap.String("name", name))
	}

	return nil
}
<|endoftext|>


<commit_before>package web

import (
	"encoding/json"
	"net/http"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/demisto/alfred/conf"
	"github.com/demisto/alfred/domain"
	"github.com/demisto/alfred/util"
	"github.com/demisto/slack"
	"github.com/gorilla/context"
	"github.com/wayn3h0/go-uuid/random"
	"golang.org/x/oauth2"
)

type simpleUser struct {
	Name     string `json:"name"`
	Email    string `json:"email"`
	RealName string `json:"real_name"`
	TeamName string `json:"team_name"`
}

type credentials struct {
	User     string `json:"user"`
	Password string `json:"password"`
}

const (
	slackOAuthEndpoint = "https://slack.com/oauth/authorize"
	slackOAuthExchange = "https://slack.com/api/oauth.access"
)

func (ac *AppContext) initiateOAuth(w http.ResponseWriter, r *http.Request) {
	// First - check that you are not from a banned country
	if isBanned(r.RemoteAddr) {
		http.Redirect(w, r, "/banned", http.StatusFound)
		return
	}
	// Now, generate a random state
	uuid, err := random.New()
	if err != nil {
		panic(err)
	}
	conf := &oauth2.Config{
		ClientID:     conf.Options.Slack.ClientID,
		ClientSecret: conf.Options.Slack.ClientSecret,
		Scopes:       []string{"client"},
		Endpoint: oauth2.Endpoint{
			AuthURL:  slackOAuthEndpoint,
			TokenURL: slackOAuthExchange,
		},
	}
	// Store state
	ac.r.SetOAuthState(&domain.OAuthState{State: uuid.String(), Timestamp: time.Now()})
	url := conf.AuthCodeURL(uuid.String())
	http.Redirect(w, r, url, http.StatusFound)
}

func (ac *AppContext) loginOAuth(w http.ResponseWriter, r *http.Request) {
	state := r.FormValue("state")
	code := r.FormValue("code")
	errStr := r.FormValue("error")
	if errStr != "" {
		WriteError(w, &Error{"oauth_err", 401, "Slack OAuth Error", errStr})
		return
	}
	if state == "" || code == "" {
		WriteError(w, ErrBadContentRequest)
		return
	}
	savedState, err := ac.r.OAuthState(state)
	if err != nil {
		WriteError(w, ErrBadContentRequest)
		return
	}
	// We allow only 5 min between requests
	if time.Since(savedState.Timestamp) > 5*time.Minute {
		WriteError(w, ErrBadRequest)
	}
	token, err := slack.OAuthAccess(conf.Options.Slack.ClientID,
		conf.Options.Slack.ClientSecret, code, "")
	if err != nil {
		WriteError(w, &Error{"oauth_err", 401, "Slack OAuth Error", err.Error()})
		return
	}
	log.Debugln("OAuth successful, creating Slack client")
	s, err := slack.New(slack.SetToken(token.AccessToken))
	if err != nil {
		panic(err)
	}
	log.Debugln("Slack client created")
	// Get our own user id
	test, err := s.AuthTest()
	if err != nil {
		panic(err)
	}
	team, err := s.TeamInfo()
	if err != nil {
		panic(err)
	}
	user, err := s.UserInfo(test.UserID)
	if err != nil {
		panic(err)
	}
	log.Debugln("Got all details about myself from Slack")
	ourTeam, err := ac.r.TeamByExternalID(team.Team.ID)
	if err != nil {
		log.Debugf("Got a new team registered - %s", team.Team.Name)
		teamID, err := random.New()
		if err != nil {
			panic(err)
		}
		ourTeam = &domain.Team{
			ID:          "T" + teamID.String(),
			Name:        team.Team.Name,
			EmailDomain: team.Team.EmailDomain,
			Domain:      team.Team.Domain,
			Plan:        team.Team.Plan,
			ExternalID:  team.Team.ID,
			Created:     time.Now(),
		}
	} else {
		log.Debugf("Got an existing team - %s", team.Team.Name)
		ourTeam.Name, ourTeam.EmailDomain, ourTeam.Domain, ourTeam.Plan =
			team.Team.Name, team.Team.EmailDomain, team.Team.Domain, team.Team.Plan
	}
	newUser := false
	log.Debugln("Finding the user...")
	ourUser, err := ac.r.UserByExternalID(user.User.ID)
	if err != nil {
		log.Debugf("Got a new user registered - %s", user.User.Name)
		userID, err := random.New()
		if err != nil {
			panic(err)
		}
		ourUser = &domain.User{
			ID:                "U" + userID.String(),
			Team:              ourTeam.ID,
			Name:              user.User.Name,
			Type:              domain.UserTypeSlack,
			Status:            domain.UserStatusActive,
			RealName:          user.User.RealName,
			Email:             user.User.Profile.Email,
			IsBot:             user.User.IsBot,
			IsAdmin:           user.User.IsAdmin,
			IsOwner:           user.User.IsOwner,
			IsPrimaryOwner:    user.User.IsPrimaryOwner,
			IsRestricted:      user.User.IsRestricted,
			IsUltraRestricted: user.User.IsUltraRestricted,
			ExternalID:        user.User.ID,
			Token:             token.AccessToken,
			Created:           time.Now(),
		}
		newUser = true
	} else {
		ourUser.Name, ourUser.RealName, ourUser.Email, ourUser.Token =
			user.User.Name, user.User.RealName, user.User.Profile.Email, token.AccessToken
	}
	log.Debugln("Saving to the DB...")
	err = ac.r.SetTeamAndUser(ourTeam, ourUser)
	if err != nil {
		panic(err)
	}
	log.Infof("User %v logged in\n", ourUser.Name)
	if newUser {
		newConf := &domain.Configuration{All: true}
		err = ac.r.SetChannelsAndGroups(ourUser.ID, newConf)
		if err != nil {
			// If we got here, allow empty configuration
			log.Warnf("Unable to store initial configuration for user %s - %v\n", ourUser.ID, err)
		}
	}
	sess := session{ourUser.Name, ourUser.ID, time.Now()}
	secure := conf.Options.SSL.Key != ""
	val, _ := util.EncryptJSON(&sess, conf.Options.Security.SessionKey)
	// Set the cookie for the user
	http.SetCookie(w, &http.Cookie{Name: sessionCookie, Value: val, Path: "/", Expires: time.Now().Add(time.Duration(conf.Options.Security.Timeout) * time.Minute), MaxAge: conf.Options.Security.Timeout * 60, Secure: secure, HttpOnly: true})
	http.Redirect(w, r, "/conf", http.StatusFound)
}

func (ac *AppContext) logout(w http.ResponseWriter, r *http.Request) {
	secure := conf.Options.SSL.Key != ""
	http.SetCookie(w, &http.Cookie{Name: sessionCookie, Value: "", Path: "/", Expires: time.Now(), MaxAge: -1, Secure: secure, HttpOnly: true})
	w.WriteHeader(http.StatusNoContent)
	w.Write([]byte("\n"))
}

func (ac *AppContext) currUser(w http.ResponseWriter, r *http.Request) {
	u := context.Get(r, "user").(*domain.User)
	t, err := ac.r.Team(u.Team)
	if err != nil {
		panic(err)
	}
	externalUser := simpleUser{u.Name, u.Email, u.RealName, t.Name}
	json.NewEncoder(w).Encode(externalUser)
}
<commit_msg>Changed debug message to info for new user<commit_after>package web

import (
	"encoding/json"
	"net/http"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/demisto/alfred/conf"
	"github.com/demisto/alfred/domain"
	"github.com/demisto/alfred/util"
	"github.com/demisto/slack"
	"github.com/gorilla/context"
	"github.com/wayn3h0/go-uuid/random"
	"golang.org/x/oauth2"
)

type simpleUser struct {
	Name     string `json:"name"`
	Email    string `json:"email"`
	RealName string `json:"real_name"`
	TeamName string `json:"team_name"`
}

type credentials struct {
	User     string `json:"user"`
	Password string `json:"password"`
}

const (
	slackOAuthEndpoint = "https://slack.com/oauth/authorize"
	slackOAuthExchange = "https://slack.com/api/oauth.access"
)

func (ac *AppContext) initiateOAuth(w http.ResponseWriter, r *http.Request) {
	// First - check that you are not from a banned country
	if isBanned(r.RemoteAddr) {
		http.Redirect(w, r, "/banned", http.StatusFound)
		return
	}
	// Now, generate a random state
	uuid, err := random.New()
	if err != nil {
		panic(err)
	}
	conf := &oauth2.Config{
		ClientID:     conf.Options.Slack.ClientID,
		ClientSecret: conf.Options.Slack.ClientSecret,
		Scopes:       []string{"client"},
		Endpoint: oauth2.Endpoint{
			AuthURL:  slackOAuthEndpoint,
			TokenURL: slackOAuthExchange,
		},
	}
	// Store state
	ac.r.SetOAuthState(&domain.OAuthState{State: uuid.String(), Timestamp: time.Now()})
	url := conf.AuthCodeURL(uuid.String())
	http.Redirect(w, r, url, http.StatusFound)
}

func (ac *AppContext) loginOAuth(w http.ResponseWriter, r *http.Request) {
	state := r.FormValue("state")
	code := r.FormValue("code")
	errStr := r.FormValue("error")
	if errStr != "" {
		WriteError(w, &Error{"oauth_err", 401, "Slack OAuth Error", errStr})
		return
	}
	if state == "" || code == "" {
		WriteError(w, ErrBadContentRequest)
		return
	}
	savedState, err := ac.r.OAuthState(state)
	if err != nil {
		WriteError(w, ErrBadContentRequest)
		return
	}
	// We allow only 5 min between requests
	if time.Since(savedState.Timestamp) > 5*time.Minute {
		WriteError(w, ErrBadRequest)
	}
	token, err := slack.OAuthAccess(conf.Options.Slack.ClientID,
		conf.Options.Slack.ClientSecret, code, "")
	if err != nil {
		WriteError(w, &Error{"oauth_err", 401, "Slack OAuth Error", err.Error()})
		return
	}
	log.Debugln("OAuth successful, creating Slack client")
	s, err := slack.New(slack.SetToken(token.AccessToken))
	if err != nil {
		panic(err)
	}
	log.Debugln("Slack client created")
	// Get our own user id
	test, err := s.AuthTest()
	if err != nil {
		panic(err)
	}
	team, err := s.TeamInfo()
	if err != nil {
		panic(err)
	}
	user, err := s.UserInfo(test.UserID)
	if err != nil {
		panic(err)
	}
	log.Debugln("Got all details about myself from Slack")
	ourTeam, err := ac.r.TeamByExternalID(team.Team.ID)
	if err != nil {
		log.Debugf("Got a new team registered - %s", team.Team.Name)
		teamID, err := random.New()
		if err != nil {
			panic(err)
		}
		ourTeam = &domain.Team{
			ID:          "T" + teamID.String(),
			Name:        team.Team.Name,
			EmailDomain: team.Team.EmailDomain,
			Domain:      team.Team.Domain,
			Plan:        team.Team.Plan,
			ExternalID:  team.Team.ID,
			Created:     time.Now(),
		}
	} else {
		log.Debugf("Got an existing team - %s", team.Team.Name)
		ourTeam.Name, ourTeam.EmailDomain, ourTeam.Domain, ourTeam.Plan =
			team.Team.Name, team.Team.EmailDomain, team.Team.Domain, team.Team.Plan
	}
	newUser := false
	log.Debugln("Finding the user...")
	ourUser, err := ac.r.UserByExternalID(user.User.ID)
	if err != nil {
		log.Infof("Got a new user registered - %s", user.User.Name)
		userID, err := random.New()
		if err != nil {
			panic(err)
		}
		ourUser = &domain.User{
			ID:                "U" + userID.String(),
			Team:              ourTeam.ID,
			Name:              user.User.Name,
			Type:              domain.UserTypeSlack,
			Status:            domain.UserStatusActive,
			RealName:          user.User.RealName,
			Email:             user.User.Profile.Email,
			IsBot:             user.User.IsBot,
			IsAdmin:           user.User.IsAdmin,
			IsOwner:           user.User.IsOwner,
			IsPrimaryOwner:    user.User.IsPrimaryOwner,
			IsRestricted:      user.User.IsRestricted,
			IsUltraRestricted: user.User.IsUltraRestricted,
			ExternalID:        user.User.ID,
			Token:             token.AccessToken,
			Created:           time.Now(),
		}
		newUser = true
	} else {
		ourUser.Name, ourUser.RealName, ourUser.Email, ourUser.Token =
			user.User.Name, user.User.RealName, user.User.Profile.Email, token.AccessToken
	}
	log.Debugln("Saving to the DB...")
	err = ac.r.SetTeamAndUser(ourTeam, ourUser)
	if err != nil {
		panic(err)
	}
	log.Infof("User %v logged in\n", ourUser.Name)
	if newUser {
		newConf := &domain.Configuration{All: true}
		err = ac.r.SetChannelsAndGroups(ourUser.ID, newConf)
		if err != nil {
			// If we got here, allow empty configuration
			log.Warnf("Unable to store initial configuration for user %s - %v\n", ourUser.ID, err)
		}
	}
	sess := session{ourUser.Name, ourUser.ID, time.Now()}
	secure := conf.Options.SSL.Key != ""
	val, _ := util.EncryptJSON(&sess, conf.Options.Security.SessionKey)
	// Set the cookie for the user
	http.SetCookie(w, &http.Cookie{Name: sessionCookie, Value: val, Path: "/", Expires: time.Now().Add(time.Duration(conf.Options.Security.Timeout) * time.Minute), MaxAge: conf.Options.Security.Timeout * 60, Secure: secure, HttpOnly: true})
	http.Redirect(w, r, "/conf", http.StatusFound)
}

func (ac *AppContext) logout(w http.ResponseWriter, r *http.Request) {
	secure := conf.Options.SSL.Key != ""
	http.SetCookie(w, &http.Cookie{Name: sessionCookie, Value: "", Path: "/", Expires: time.Now(), MaxAge: -1, Secure: secure, HttpOnly: true})
	w.WriteHeader(http.StatusNoContent)
	w.Write([]byte("\n"))
}

func (ac *AppContext) currUser(w http.ResponseWriter, r *http.Request) {
	u := context.Get(r, "user").(*domain.User)
	t, err := ac.r.Team(u.Team)
	if err != nil {
		panic(err)
	}
	externalUser := simpleUser{u.Name, u.Email, u.RealName, t.Name}
	json.NewEncoder(w).Encode(externalUser)
}
<|endoftext|>