<commit_before>// Copyright (c) 2014, Rob Thornton
// All rights reserved.
// This source code is governed by a Simplied BSD-License. Please see the
// LICENSE included in this distribution for a copy of the full license
// or, if one is not included, you may also find a copy at
// http://opensource.org/licenses/BSD-2-Clause

package ast

import (
	"github.com/rthornton128/calc/token"
)

type Node interface {
	Pos() token.Pos
	End() token.Pos
}

type Expr interface {
	Node
	exprNode()
}

type AssignExpr struct {
	Expression
	Equal token.Pos
	Name  *Ident
	Value Expr
}

type BasicLit struct {
	LitPos token.Pos
	Kind   token.Token
	Lit    string
}

type BinaryExpr struct {
	Expression
	Op    token.Token
	OpPos token.Pos
	List  []Expr
}

type CallExpr struct {
	Expression
	Call token.Pos
	Name *Ident
	Args []Expr
}

type DeclExpr struct {
	Expression
	Decl   token.Pos
	Name   *Ident
	Type   *Ident
	Params []*Ident
	Body   Expr
	Scope  *Scope
}

type Expression struct {
	Opening token.Pos
	Closing token.Pos
}

type ExprList struct {
	Expression
	List []Expr
}

type File struct {
	Scope *Scope
}

type Ident struct {
	NamePos token.Pos
	Name    string
	Object  *Object // may be nil (ie. Name is a type keyword)
}

type IfExpr struct {
	Expression
	If    token.Pos
	Type  *Ident
	Cond  Expr
	Then  Expr
	Else  Expr
	Scope *Scope
}

type Object struct {
	NamePos token.Pos
	Name    string
	Kind    ObKind
	Offset  int
	Type    *Ident // variable type, function return type, etc
	Value   Expr
}

type ObKind int

type Package struct {
	Scope *Scope
	//Files map[string]*File
}

type Scope struct {
	Parent *Scope
	Table  map[string]*Object
}

type VarExpr struct {
	Expression
	Var    token.Pos
	Name   *Ident
	Object *Object
}

func (b *BasicLit) Pos() token.Pos   { return b.LitPos }
func (e *Expression) Pos() token.Pos { return e.Opening }
func (f *File) Pos() token.Pos       { return token.NoPos }
func (i *Ident) Pos() token.Pos      { return i.NamePos }
func (p *Package) Pos() token.Pos    { return token.NoPos }

func (b *BasicLit) End() token.Pos   { return b.LitPos + token.Pos(len(b.Lit)) }
func (e *Expression) End() token.Pos { return e.Closing }
func (f *File) End() token.Pos       { return token.NoPos }
func (i *Ident) End() token.Pos      { return i.NamePos + token.Pos(len(i.Name)) }
func (p *Package) End() token.Pos    { return token.NoPos }

func (b *BasicLit) exprNode()   {}
func (e *Expression) exprNode() {}
func (i *Ident) exprNode()      {}

const (
	Decl ObKind = iota
	Var
)

func NewScope(parent *Scope) *Scope {
	return &Scope{Parent: parent, Table: make(map[string]*Object)}
}

func (s *Scope) Insert(ob *Object) *Object {
	if old, ok := s.Table[ob.Name]; ok {
		return old
	}
	s.Table[ob.Name] = ob
	return nil
}

func (s *Scope) Lookup(ident string) *Object {
	ob, ok := s.Table[ident]
	if ok || s.Parent == nil {
		return ob
	}
	return s.Parent.Lookup(ident)
}

func (s *Scope) Size() int {
	return len(s.Table)
}
<commit_msg>change ast.Package to use file slice and add MergeScope function<commit_after>// Copyright (c) 2014, Rob Thornton
// All rights reserved.
// This source code is governed by a Simplied BSD-License. Please see the
// LICENSE included in this distribution for a copy of the full license
// or, if one is not included, you may also find a copy at
// http://opensource.org/licenses/BSD-2-Clause

package ast

import (
	"github.com/rthornton128/calc/token"
)

type Node interface {
	Pos() token.Pos
	End() token.Pos
}

type Expr interface {
	Node
	exprNode()
}

type AssignExpr struct {
	Expression
	Equal token.Pos
	Name  *Ident
	Value Expr
}

type BasicLit struct {
	LitPos token.Pos
	Kind   token.Token
	Lit    string
}

type BinaryExpr struct {
	Expression
	Op    token.Token
	OpPos token.Pos
	List  []Expr
}

type CallExpr struct {
	Expression
	Call token.Pos
	Name *Ident
	Args []Expr
}

type DeclExpr struct {
	Expression
	Decl   token.Pos
	Name   *Ident
	Type   *Ident
	Params []*Ident
	Body   Expr
	Scope  *Scope
}

type Expression struct {
	Opening token.Pos
	Closing token.Pos
}

type ExprList struct {
	Expression
	List []Expr
}

type File struct {
	Scope *Scope
}

type Ident struct {
	NamePos token.Pos
	Name    string
	Object  *Object // may be nil (ie. Name is a type keyword)
}

type IfExpr struct {
	Expression
	If    token.Pos
	Type  *Ident
	Cond  Expr
	Then  Expr
	Else  Expr
	Scope *Scope
}

type Object struct {
	NamePos token.Pos
	Name    string
	Kind    ObKind
	Offset  int
	Type    *Ident // variable type, function return type, etc
	Value   Expr
}

type ObKind int

type Package struct {
	Scope *Scope
	Files []*File
}

type Scope struct {
	Parent *Scope
	Table  map[string]*Object
}

type VarExpr struct {
	Expression
	Var    token.Pos
	Name   *Ident
	Object *Object
}

func (b *BasicLit) Pos() token.Pos   { return b.LitPos }
func (e *Expression) Pos() token.Pos { return e.Opening }
func (f *File) Pos() token.Pos       { return token.NoPos }
func (i *Ident) Pos() token.Pos      { return i.NamePos }
func (p *Package) Pos() token.Pos    { return token.NoPos }

func (b *BasicLit) End() token.Pos   { return b.LitPos + token.Pos(len(b.Lit)) }
func (e *Expression) End() token.Pos { return e.Closing }
func (f *File) End() token.Pos       { return token.NoPos }
func (i *Ident) End() token.Pos      { return i.NamePos + token.Pos(len(i.Name)) }
func (p *Package) End() token.Pos    { return token.NoPos }

func (b *BasicLit) exprNode()   {}
func (e *Expression) exprNode() {}
func (i *Ident) exprNode()      {}

const (
	Decl ObKind = iota
	Var
)

func NewScope(parent *Scope) *Scope {
	return &Scope{Parent: parent, Table: make(map[string]*Object)}
}

func MergeScopes(files []*File) *Scope {
	table := make(map[string]*Object)
	for _, f := range files {
		for k, v := range f.Scope.Table {
			table[k] = v
		}
	}
	return &Scope{Parent: nil, Table: table}
}

func (s *Scope) Insert(ob *Object) *Object {
	if old, ok := s.Table[ob.Name]; ok {
		return old
	}
	s.Table[ob.Name] = ob
	return nil
}

func (s *Scope) Lookup(ident string) *Object {
	ob, ok := s.Table[ident]
	if ok || s.Parent == nil {
		return ob
	}
	return s.Parent.Lookup(ident)
}

func (s *Scope) Size() int {
	return len(s.Table)
}
<|endoftext|>


<commit_before>// Package client provides a Stripe client for invoking APIs across all resources
package client

import (
	. "github.com/stripe/stripe-go"
	"github.com/stripe/stripe-go/account"
	"github.com/stripe/stripe-go/balance"
	"github.com/stripe/stripe-go/bankaccount"
	"github.com/stripe/stripe-go/bitcoinreceiver"
	"github.com/stripe/stripe-go/bitcointransaction"
	"github.com/stripe/stripe-go/card"
	"github.com/stripe/stripe-go/charge"
	"github.com/stripe/stripe-go/countryspec"
	"github.com/stripe/stripe-go/coupon"
	"github.com/stripe/stripe-go/customer"
	"github.com/stripe/stripe-go/discount"
	"github.com/stripe/stripe-go/dispute"
	"github.com/stripe/stripe-go/event"
	"github.com/stripe/stripe-go/fee"
	"github.com/stripe/stripe-go/feerefund"
	"github.com/stripe/stripe-go/fileupload"
	"github.com/stripe/stripe-go/invoice"
	"github.com/stripe/stripe-go/invoiceitem"
	"github.com/stripe/stripe-go/order"
	"github.com/stripe/stripe-go/orderreturn"
	"github.com/stripe/stripe-go/plan"
	"github.com/stripe/stripe-go/product"
	"github.com/stripe/stripe-go/recipient"
	"github.com/stripe/stripe-go/refund"
	"github.com/stripe/stripe-go/reversal"
	"github.com/stripe/stripe-go/sku"
	"github.com/stripe/stripe-go/source"
	"github.com/stripe/stripe-go/sub"
	"github.com/stripe/stripe-go/token"
	"github.com/stripe/stripe-go/transfer"
	"github.com/stripe/stripe-go/paymentsource"
)

// API is the Stripe client. It contains all the different resources available.
type API struct {
	// Charges is the client used to invoke /charges APIs.
	// For more details see https://stripe.com/docs/api#charges.
	Charges *charge.Client
	// Customers is the client used to invoke /customers APIs.
	// For more details see https://stripe.com/docs/api#customers.
	Customers *customer.Client
	// Cards is the client used to invoke /cards APIs.
	// For more details see https://stripe.com/docs/api#cards.
	Cards *card.Client
	// Subs is the client used to invoke /subscriptions APIs.
	// For more details see https://stripe.com/docs/api#subscriptions.
	Subs *sub.Client
	// Plans is the client used to invoke /plans APIs.
	// For more details see https://stripe.com/docs/api#plans.
	Plans *plan.Client
	// Coupons is the client used to invoke /coupons APIs.
	// For more details see https://stripe.com/docs/api#coupons.
	Coupons *coupon.Client
	// Discounts is the client used to invoke discount-related APIs.
	// For mode details see https://stripe.com/docs/api#discounts.
	Discounts *discount.Client
	// Invoices is the client used to invoke /invoices APIs.
	// For more details see https://stripe.com/docs/api#invoices.
	Invoices *invoice.Client
	// InvoiceItems is the client used to invoke /invoiceitems APIs.
	// For more details see https://stripe.com/docs/api#invoiceitems.
	InvoiceItems *invoiceitem.Client
	// Disputes is the client used to invoke dispute-related APIs.
	// For more details see https://stripe.com/docs/api#disputes.
	Disputes *dispute.Client
	// Transfers is the client used to invoke /transfers APIs.
	// For more details see https://stripe.com/docs/api#transfers.
	Transfers *transfer.Client
	// Recipients is the client used to invoke /recipients APIs.
	// For more details see https://stripe.com/docs/api#recipients.
	Recipients *recipient.Client
	// Refunds is the client used to invoke /refunds APIs.
	// For more details see https://stripe.com/docs/api#refunds.
	Refunds *refund.Client
	// Fees is the client used to invoke /application_fees APIs.
	// For more details see https://stripe.com/docs/api#application_fees.
	Fees *fee.Client
	// FeeRefunds is the client used to invoke /application_fees/refunds APIs.
	// For more details see https://stripe.com/docs/api#fee_refundss.
	FeeRefunds *feerefund.Client
	// Account is the client used to invoke /account APIs.
	// For more details see https://stripe.com/docs/api#account.
	Account *account.Client
	// CountrySpec is the client used to invoke /country_specs APIs.
	// For more details see https://stripe.com/docs/api#country_specs.
	CountrySpec *countryspec.Client
	// Balance is the client used to invoke /balance and transaction-related APIs.
	// For more details see https://stripe.com/docs/api#balance.
	Balance *balance.Client
	// Events is the client used to invoke /events APIs.
	// For more details see https://stripe.com/docs/api#events.
	Events *event.Client
	// Tokens is the client used to invoke /tokens APIs.
	// For more details see https://stripe.com/docs/api#tokens.
	Tokens *token.Client
	// FileUploads is the client used to invoke the uploads /files APIs.
	// For more details see https://stripe.com/docs/api#file_uploads.
	FileUploads *fileupload.Client
	// BitcoinReceivers is the client used to invoke /bitcoin/receivers APIs.
	// For more details see https://stripe.com/docs/api#bitcoin_receivers.
	BitcoinReceivers *bitcoinreceiver.Client
	// BitcoinTransactions is the client used to invoke /bitcoin/transactions APIs.
	// For more details see https://stripe.com/docs/api#bitcoin_receivers.
	BitcoinTransactions *bitcointransaction.Client
	// Reversals is the client used to invoke /transfers/reversals APIs.
	Reversals *reversal.Client
	// BankAccounts is the client used to invoke /accounts/bank_accounts APIs.
	BankAccounts *bankaccount.Client
	// Products is the client used to invoke /products APIs.
	// For more details see https://stripe.com/docs/api#products.
	Products *product.Client
	// Orders is the client used to invoke /orders APIs.
	// For more details see https://stripe.com/docs/api#orders.
	Orders *order.Client
	// OrderReturns is the client used to invoke /order_returns APIs.
	// For more details, see https://stripe.com/docs/api#order_returns.
	OrderReturns *orderreturn.Client
	// Skus is the client used to invoke /skus APIs.
	// For more details see https://stripe.com/docs/api#skus.
	Skus *sku.Client
	// Sources is the client used to invoke /sources APIs.
	// For more details see https://stripe.com/docs/api#sources.
	Sources *source.Client
	// PaymentSource is used to invoke /sources APIs.
	// For more details see https://stripe.com/docs/api.
	PaymentSource *paymentsource.Client
}

// Init initializes the Stripe client with the appropriate secret key
// as well as providing the ability to override the backend as needed.
func (a *API) Init(key string, backends *Backends) {
	if backends == nil {
		backends = &Backends{GetBackend(APIBackend), GetBackend(UploadsBackend)}
	}

	a.Charges = &charge.Client{B: backends.API, Key: key}
	a.Customers = &customer.Client{B: backends.API, Key: key}
	a.Cards = &card.Client{B: backends.API, Key: key}
	a.Subs = &sub.Client{B: backends.API, Key: key}
	a.Plans = &plan.Client{B: backends.API, Key: key}
	a.Coupons = &coupon.Client{B: backends.API, Key: key}
	a.Discounts = &discount.Client{B: backends.API, Key: key}
	a.Invoices = &invoice.Client{B: backends.API, Key: key}
	a.InvoiceItems = &invoiceitem.Client{B: backends.API, Key: key}
	a.Disputes = &dispute.Client{B: backends.API, Key: key}
	a.Transfers = &transfer.Client{B: backends.API, Key: key}
	a.Recipients = &recipient.Client{B: backends.API, Key: key}
	a.Refunds = &refund.Client{B: backends.API, Key: key}
	a.Fees = &fee.Client{B: backends.API, Key: key}
	a.FeeRefunds = &feerefund.Client{B: backends.API, Key: key}
	a.Account = &account.Client{B: backends.API, Key: key}
	a.CountrySpec = &countryspec.Client{B: backends.API, Key: key}
	a.Balance = &balance.Client{B: backends.API, Key: key}
	a.Events = &event.Client{B: backends.API, Key: key}
	a.Tokens = &token.Client{B: backends.API, Key: key}
	a.FileUploads = &fileupload.Client{B: backends.Uploads, Key: key}
	a.BitcoinReceivers = &bitcoinreceiver.Client{B: backends.API, Key: key}
	a.BitcoinTransactions = &bitcointransaction.Client{B: backends.API, Key: key}
	a.Reversals = &reversal.Client{B: backends.API, Key: key}
	a.BankAccounts = &bankaccount.Client{B: backends.API, Key: key}
	a.Products = &product.Client{B: backends.API, Key: key}
	a.Orders = &order.Client{B: backends.API, Key: key}
	a.OrderReturns = &orderreturn.Client{B: backends.API, Key: key}
	a.Skus = &sku.Client{B: backends.API, Key: key}
	a.Sources = &source.Client{B: backends.API, Key: key}
	a.PaymentSource = &paymentsource.Client{B: backends.API, Key: key}
}

// New creates a new Stripe client with the appropriate secret key
// as well as providing the ability to override the backends as needed.
func New(key string, backends *Backends) *API {
	api := API{}
	api.Init(key, backends)
	return &api
}
<commit_msg>ran gofmt on api.go<commit_after>// Package client provides a Stripe client for invoking APIs across all resources
package client

import (
	. "github.com/stripe/stripe-go"
	"github.com/stripe/stripe-go/account"
	"github.com/stripe/stripe-go/balance"
	"github.com/stripe/stripe-go/bankaccount"
	"github.com/stripe/stripe-go/bitcoinreceiver"
	"github.com/stripe/stripe-go/bitcointransaction"
	"github.com/stripe/stripe-go/card"
	"github.com/stripe/stripe-go/charge"
	"github.com/stripe/stripe-go/countryspec"
	"github.com/stripe/stripe-go/coupon"
	"github.com/stripe/stripe-go/customer"
	"github.com/stripe/stripe-go/discount"
	"github.com/stripe/stripe-go/dispute"
	"github.com/stripe/stripe-go/event"
	"github.com/stripe/stripe-go/fee"
	"github.com/stripe/stripe-go/feerefund"
	"github.com/stripe/stripe-go/fileupload"
	"github.com/stripe/stripe-go/invoice"
	"github.com/stripe/stripe-go/invoiceitem"
	"github.com/stripe/stripe-go/order"
	"github.com/stripe/stripe-go/orderreturn"
	"github.com/stripe/stripe-go/paymentsource"
	"github.com/stripe/stripe-go/plan"
	"github.com/stripe/stripe-go/product"
	"github.com/stripe/stripe-go/recipient"
	"github.com/stripe/stripe-go/refund"
	"github.com/stripe/stripe-go/reversal"
	"github.com/stripe/stripe-go/sku"
	"github.com/stripe/stripe-go/source"
	"github.com/stripe/stripe-go/sub"
	"github.com/stripe/stripe-go/token"
	"github.com/stripe/stripe-go/transfer"
)

// API is the Stripe client. It contains all the different resources available.
type API struct {
	// Charges is the client used to invoke /charges APIs.
	// For more details see https://stripe.com/docs/api#charges.
	Charges *charge.Client
	// Customers is the client used to invoke /customers APIs.
	// For more details see https://stripe.com/docs/api#customers.
	Customers *customer.Client
	// Cards is the client used to invoke /cards APIs.
	// For more details see https://stripe.com/docs/api#cards.
	Cards *card.Client
	// Subs is the client used to invoke /subscriptions APIs.
	// For more details see https://stripe.com/docs/api#subscriptions.
	Subs *sub.Client
	// Plans is the client used to invoke /plans APIs.
	// For more details see https://stripe.com/docs/api#plans.
	Plans *plan.Client
	// Coupons is the client used to invoke /coupons APIs.
	// For more details see https://stripe.com/docs/api#coupons.
	Coupons *coupon.Client
	// Discounts is the client used to invoke discount-related APIs.
	// For mode details see https://stripe.com/docs/api#discounts.
	Discounts *discount.Client
	// Invoices is the client used to invoke /invoices APIs.
	// For more details see https://stripe.com/docs/api#invoices.
	Invoices *invoice.Client
	// InvoiceItems is the client used to invoke /invoiceitems APIs.
	// For more details see https://stripe.com/docs/api#invoiceitems.
	InvoiceItems *invoiceitem.Client
	// Disputes is the client used to invoke dispute-related APIs.
	// For more details see https://stripe.com/docs/api#disputes.
	Disputes *dispute.Client
	// Transfers is the client used to invoke /transfers APIs.
	// For more details see https://stripe.com/docs/api#transfers.
	Transfers *transfer.Client
	// Recipients is the client used to invoke /recipients APIs.
	// For more details see https://stripe.com/docs/api#recipients.
	Recipients *recipient.Client
	// Refunds is the client used to invoke /refunds APIs.
	// For more details see https://stripe.com/docs/api#refunds.
	Refunds *refund.Client
	// Fees is the client used to invoke /application_fees APIs.
	// For more details see https://stripe.com/docs/api#application_fees.
	Fees *fee.Client
	// FeeRefunds is the client used to invoke /application_fees/refunds APIs.
	// For more details see https://stripe.com/docs/api#fee_refundss.
	FeeRefunds *feerefund.Client
	// Account is the client used to invoke /account APIs.
	// For more details see https://stripe.com/docs/api#account.
	Account *account.Client
	// CountrySpec is the client used to invoke /country_specs APIs.
	// For more details see https://stripe.com/docs/api#country_specs.
	CountrySpec *countryspec.Client
	// Balance is the client used to invoke /balance and transaction-related APIs.
	// For more details see https://stripe.com/docs/api#balance.
	Balance *balance.Client
	// Events is the client used to invoke /events APIs.
	// For more details see https://stripe.com/docs/api#events.
	Events *event.Client
	// Tokens is the client used to invoke /tokens APIs.
	// For more details see https://stripe.com/docs/api#tokens.
	Tokens *token.Client
	// FileUploads is the client used to invoke the uploads /files APIs.
	// For more details see https://stripe.com/docs/api#file_uploads.
	FileUploads *fileupload.Client
	// BitcoinReceivers is the client used to invoke /bitcoin/receivers APIs.
	// For more details see https://stripe.com/docs/api#bitcoin_receivers.
	BitcoinReceivers *bitcoinreceiver.Client
	// BitcoinTransactions is the client used to invoke /bitcoin/transactions APIs.
	// For more details see https://stripe.com/docs/api#bitcoin_receivers.
	BitcoinTransactions *bitcointransaction.Client
	// Reversals is the client used to invoke /transfers/reversals APIs.
	Reversals *reversal.Client
	// BankAccounts is the client used to invoke /accounts/bank_accounts APIs.
	BankAccounts *bankaccount.Client
	// Products is the client used to invoke /products APIs.
	// For more details see https://stripe.com/docs/api#products.
	Products *product.Client
	// Orders is the client used to invoke /orders APIs.
	// For more details see https://stripe.com/docs/api#orders.
	Orders *order.Client
	// OrderReturns is the client used to invoke /order_returns APIs.
	// For more details, see https://stripe.com/docs/api#order_returns.
	OrderReturns *orderreturn.Client
	// Skus is the client used to invoke /skus APIs.
	// For more details see https://stripe.com/docs/api#skus.
	Skus *sku.Client
	// Sources is the client used to invoke /sources APIs.
	// For more details see https://stripe.com/docs/api#sources.
	Sources *source.Client
	// PaymentSource is used to invoke /sources APIs.
	// For more details see https://stripe.com/docs/api.
	PaymentSource *paymentsource.Client
}

// Init initializes the Stripe client with the appropriate secret key
// as well as providing the ability to override the backend as needed.
func (a *API) Init(key string, backends *Backends) {
	if backends == nil {
		backends = &Backends{GetBackend(APIBackend), GetBackend(UploadsBackend)}
	}

	a.Charges = &charge.Client{B: backends.API, Key: key}
	a.Customers = &customer.Client{B: backends.API, Key: key}
	a.Cards = &card.Client{B: backends.API, Key: key}
	a.Subs = &sub.Client{B: backends.API, Key: key}
	a.Plans = &plan.Client{B: backends.API, Key: key}
	a.Coupons = &coupon.Client{B: backends.API, Key: key}
	a.Discounts = &discount.Client{B: backends.API, Key: key}
	a.Invoices = &invoice.Client{B: backends.API, Key: key}
	a.InvoiceItems = &invoiceitem.Client{B: backends.API, Key: key}
	a.Disputes = &dispute.Client{B: backends.API, Key: key}
	a.Transfers = &transfer.Client{B: backends.API, Key: key}
	a.Recipients = &recipient.Client{B: backends.API, Key: key}
	a.Refunds = &refund.Client{B: backends.API, Key: key}
	a.Fees = &fee.Client{B: backends.API, Key: key}
	a.FeeRefunds = &feerefund.Client{B: backends.API, Key: key}
	a.Account = &account.Client{B: backends.API, Key: key}
	a.CountrySpec = &countryspec.Client{B: backends.API, Key: key}
	a.Balance = &balance.Client{B: backends.API, Key: key}
	a.Events = &event.Client{B: backends.API, Key: key}
	a.Tokens = &token.Client{B: backends.API, Key: key}
	a.FileUploads = &fileupload.Client{B: backends.Uploads, Key: key}
	a.BitcoinReceivers = &bitcoinreceiver.Client{B: backends.API, Key: key}
	a.BitcoinTransactions = &bitcointransaction.Client{B: backends.API, Key: key}
	a.Reversals = &reversal.Client{B: backends.API, Key: key}
	a.BankAccounts = &bankaccount.Client{B: backends.API, Key: key}
	a.Products = &product.Client{B: backends.API, Key: key}
	a.Orders = &order.Client{B: backends.API, Key: key}
	a.OrderReturns = &orderreturn.Client{B: backends.API, Key: key}
	a.Skus = &sku.Client{B: backends.API, Key: key}
	a.Sources = &source.Client{B: backends.API, Key: key}
	a.PaymentSource = &paymentsource.Client{B: backends.API, Key: key}
}

// New creates a new Stripe client with the appropriate secret key
// as well as providing the ability to override the backends as needed.
func New(key string, backends *Backends) *API {
	api := API{}
	api.Init(key, backends)
	return &api
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"strconv"
	"strings"

	"github.com/monnand/dhkx"
)

var commonKey []byte
var connection net.Conn
var publicKeyCode string

func setup() {
	publicKeyCode = "ssd990=+?¡][ªs)(sdª]ßð=S)]"
}

func clear() {
	cmd := exec.Command("clear")
	cmd.Stdout = os.Stdout
	cmd.Run()
}

func welcome() (string, string) {
	clear()

	fmt.Println("Welcome to GoChat!\n")
	fmt.Println("1 Direct connection")
	fmt.Println("2 Choose from stored servers")
	fmt.Println("3 Add new server\n")

	reader := bufio.NewReader(os.Stdin)
	text, _ := reader.ReadString('\n')

	var address string
	var port string

	switch string(text[0]) {
	case "1":
		address, port = chooseServer()
	case "2":
		address, port = chooseStoredServer()
	case "3":
		address, port = chooseServer()
		fmt.Print("Server name: ")

		reader := bufio.NewReader(os.Stdin)
		text, _ := reader.ReadString('\n')
		name := text[0 : len(text)-1]

		storeNewServer(address, port, name)
	}

	return address, port
}

func chooseStoredServer() (string, string) {
	var address string
	var port string

	clear()

	dat, err := ioutil.ReadFile("servers.txt")
	if err != nil {
		panic(err)
	}

	servers := strings.Split(string(dat), "|")
	var serverArray []Server

	fmt.Println("Servers:\n")
	for i, e := range servers {
		if len(e) > 1 {
			data := strings.Split(e, "-")
			s := Server{address: data[0], port: data[1], name: data[2]}
			fmt.Println(i, s.address+":"+s.port+" "+s.name)
			serverArray = append(serverArray, s)
		}
	}

	fmt.Print("\nChoose server: ")
	reader := bufio.NewReader(os.Stdin)
	text, _ := reader.ReadString('\n')
	chosen := text[0 : len(text)-1]
	i, _ := strconv.ParseInt(chosen, 10, 64)

	if int(i) < len(serverArray) {
		address = serverArray[i].address
		port = serverArray[i].port
	}

	return address, port
}

func storeNewServer(address string, port string, name string) {
	dat, err := ioutil.ReadFile("servers.txt")
	if err != nil {
		panic(err)
	}

	text := string(dat)
	newServer := address + "-" + port + "-" + name + "|"
	text += newServer

	err2 := ioutil.WriteFile("servers.txt", []byte(text), 0644)
	if err2 != nil {
		panic(err2)
	}
}

func chooseServer() (string, string) {
	var address string
	var port string

	clear()

	fmt.Print("Server address: ")
	reader := bufio.NewReader(os.Stdin)
	text, _ := reader.ReadString('\n')
	address = text[0 : len(text)-1]

	fmt.Print("Server port: ")
	reader2 := bufio.NewReader(os.Stdin)
	text2, _ := reader2.ReadString('\n')
	port = text2[0 : len(text2)-1]

	return address, port
}

func dialServer(address string, port string) bool {
	conn, err := net.Dial("tcp", address+":"+port)
	if err != nil {
		fmt.Println("Can't connect to server")
		return false
	}

	connection = conn
	return true
}

func contains(s []byte, e byte) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func exchangeKeys() {
	var serverPublicKey []byte

	// generate private key
	g, _ := dhkx.GetGroup(0)
	clientPrivateKey, _ := g.GeneratePrivateKey(nil)

	// make sure the key does not contain '\n' or '%'
	for {
		if contains(clientPrivateKey.Bytes(), byte('\n')) || contains(clientPrivateKey.Bytes(), byte('%')) {
			newKey, _ := g.GeneratePrivateKey(nil)
			clientPrivateKey = newKey
		} else {
			break
		}
	}

	// generate public key
	clientPublicKey := clientPrivateKey.Bytes()

	// sending client public key
	msg := publicKeyCode + string(clientPublicKey) + "\n"
	fmt.Fprintf(connection, msg)

	// listening for server public key
	for {
		message, _ := bufio.NewReader(connection).ReadString('\n')
		if len(message) > len(publicKeyCode) {
			if message[0:len(publicKeyCode)] == publicKeyCode {
				serverPublicKey = []byte(message[len(publicKeyCode) : len(message)-1])
				break
			}
		}
	}

	// finding common key
	pubKey := dhkx.NewPublicKey(serverPublicKey)
	k, _ := g.ComputeKey(pubKey, clientPrivateKey)
	commonKey = k.Bytes()[0:32]
}

func startClient() {
	setup()
	address, port := welcome()

	clear()

	if dialServer(address, port) {
		exchangeKeys()
		fmt.Println("Connected to: " + address + ":" + port)
		go listener(connection, commonKey)

		for {
			reader := bufio.NewReader(os.Stdin)
			text, _ := reader.ReadString('\n')
			if !checkForCmd(connection, text) {
				cryptText := encrypt(commonKey, text)

				fmt.Fprintf(connection, cryptText+"\n")
			}
		}
	}
}

func main() {
	startClient()
}

func listener(conn net.Conn, key []byte) {
	for {
		message, _ := bufio.NewReader(conn).ReadString('\n')
		msg := decrypt(key, message)
		fmt.Print(msg)
	}
}

func quit(conn net.Conn) {
	conn.Close()
	os.Exit(1)
}

func checkForCmd(conn net.Conn, msg string) bool {
	if len(msg) > 1 {
		words := strings.Split(msg[0:len(msg)-1], " ")
		switch words[0] {
		case "!quit":
			quit(conn)
			return true
		}
	}
	return false
}

func encrypt(key []byte, text string) string {
	plaintext := []byte(text)

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	stream := cipher.NewCFBEncrypter(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

	return base64.URLEncoding.EncodeToString(ciphertext)
}

func decrypt(key []byte, cryptoText string) string {
	ciphertext, _ := base64.URLEncoding.DecodeString(cryptoText)

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}
	if len(ciphertext) < aes.BlockSize {
		panic("Ciphertext too short")
	}

	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]

	stream := cipher.NewCFBDecrypter(block, iv)

	stream.XORKeyStream(ciphertext, ciphertext)

	return fmt.Sprintf("%s", ciphertext)
}
<commit_msg>support for clearin terminal window on linux and windows<commit_after>package main

import (
	"bufio"
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"strings"

	"github.com/monnand/dhkx"
)

var commonKey []byte
var connection net.Conn
var publicKeyCode string

func setup() {
	publicKeyCode = "ssd990=+?¡][ªs)(sdª]ßð=S)]"
}

func clear() {

	switch runtime.GOOS {
	case "Linux":
		cmd := exec.Command("clear")
		cmd.Stdout = os.Stdout
		cmd.Run()
	case "Windows":
		cmd := exec.Command("cmd", "/c", "cls")
		cmd.Stdout = os.Stdout
		cmd.Run()
	default:
		fmt.Println("Attempted to clear terminal, but OS is not supported.")
	}
}

func welcome() (string, string) {
	clear()

	fmt.Println("Welcome to GoChat!\n")
	fmt.Println("1 Direct connection")
	fmt.Println("2 Choose from stored servers")
	fmt.Println("3 Add new server\n")

	reader := bufio.NewReader(os.Stdin)
	text, _ := reader.ReadString('\n')

	var address string
	var port string

	switch string(text[0]) {
	case "1":
		address, port = chooseServer()
	case "2":
		address, port = chooseStoredServer()
	case "3":
		address, port = chooseServer()
		fmt.Print("Server name: ")

		reader := bufio.NewReader(os.Stdin)
		text, _ := reader.ReadString('\n')
		name := text[0 : len(text)-1]

		storeNewServer(address, port, name)
	}

	return address, port
}

func chooseStoredServer() (string, string) {
	var address string
	var port string

	clear()

	dat, err := ioutil.ReadFile("servers.txt")
	if err != nil {
		panic(err)
	}

	servers := strings.Split(string(dat), "|")
	var serverArray []Server

	fmt.Println("Servers:\n")
	for i, e := range servers {
		if len(e) > 1 {
			data := strings.Split(e, "-")
			s := Server{address: data[0], port: data[1], name: data[2]}
			fmt.Println(i, s.address+":"+s.port+" "+s.name)
			serverArray = append(serverArray, s)
		}
	}

	fmt.Print("\nChoose server: ")
	reader := bufio.NewReader(os.Stdin)
	text, _ := reader.ReadString('\n')
	chosen := text[0 : len(text)-1]
	i, _ := strconv.ParseInt(chosen, 10, 64)

	if int(i) < len(serverArray) {
		address = serverArray[i].address
		port = serverArray[i].port
	}

	return address, port
}

func storeNewServer(address string, port string, name string) {
	dat, err := ioutil.ReadFile("servers.txt")
	if err != nil {
		panic(err)
	}

	text := string(dat)
	newServer := address + "-" + port + "-" + name + "|"
	text += newServer

	err2 := ioutil.WriteFile("servers.txt", []byte(text), 0644)
	if err2 != nil {
		panic(err2)
	}
}

func chooseServer() (string, string) {
	var address string
	var port string

	clear()

	fmt.Print("Server address: ")
	reader := bufio.NewReader(os.Stdin)
	text, _ := reader.ReadString('\n')
	address = text[0 : len(text)-1]

	fmt.Print("Server port: ")
	reader2 := bufio.NewReader(os.Stdin)
	text2, _ := reader2.ReadString('\n')
	port = text2[0 : len(text2)-1]

	return address, port
}

func dialServer(address string, port string) bool {
	conn, err := net.Dial("tcp", address+":"+port)
	if err != nil {
		fmt.Println("Can't connect to server")
		return false
	}

	connection = conn
	return true
}

func contains(s []byte, e byte) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}

func exchangeKeys() {
	var serverPublicKey []byte

	// generate private key
	g, _ := dhkx.GetGroup(0)
	clientPrivateKey, _ := g.GeneratePrivateKey(nil)

	// make sure the key does not contain '\n' or '%'
	for {
		if contains(clientPrivateKey.Bytes(), byte('\n')) || contains(clientPrivateKey.Bytes(), byte('%')) {
			newKey, _ := g.GeneratePrivateKey(nil)
			clientPrivateKey = newKey
		} else {
			break
		}
	}

	// generate public key
	clientPublicKey := clientPrivateKey.Bytes()

	// sending client public key
	msg := publicKeyCode + string(clientPublicKey) + "\n"
	fmt.Fprintf(connection, msg)

	// listening for server public key
	for {
		message, _ := bufio.NewReader(connection).ReadString('\n')
		if len(message) > len(publicKeyCode) {
			if message[0:len(publicKeyCode)] == publicKeyCode {
				serverPublicKey = []byte(message[len(publicKeyCode) : len(message)-1])
				break
			}
		}
	}

	// finding common key
	pubKey := dhkx.NewPublicKey(serverPublicKey)
	k, _ := g.ComputeKey(pubKey, clientPrivateKey)
	commonKey = k.Bytes()[0:32]
}

func startClient() {
	setup()
	address, port := welcome()

	clear()

	if dialServer(address, port) {
		exchangeKeys()
		fmt.Println("Connected to: " + address + ":" + port)
		go listener(connection, commonKey)

		for {
			reader := bufio.NewReader(os.Stdin)
			text, _ := reader.ReadString('\n')
			if !checkForCmd(connection, text) {
				cryptText := encrypt(commonKey, text)

				fmt.Fprintf(connection, cryptText+"\n")
			}
		}
	}
}

func main() {
	startClient()
}

func listener(conn net.Conn, key []byte) {
	for {
		message, _ := bufio.NewReader(conn).ReadString('\n')
		msg := decrypt(key, message)
		fmt.Print(msg)
	}
}

func quit(conn net.Conn) {
	conn.Close()
	os.Exit(1)
}

func checkForCmd(conn net.Conn, msg string) bool {
	if len(msg) > 1 {
		words := strings.Split(msg[0:len(msg)-1], " ")
		switch words[0] {
		case "!quit":
			quit(conn)
			return true
		}
	}
	return false
}

func encrypt(key []byte, text string) string {
	plaintext := []byte(text)

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	stream := cipher.NewCFBEncrypter(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

	return base64.URLEncoding.EncodeToString(ciphertext)
}

func decrypt(key []byte, cryptoText string) string {
	ciphertext, _ := base64.URLEncoding.DecodeString(cryptoText)

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}
	if len(ciphertext) < aes.BlockSize {
		panic("Ciphertext too short")
	}

	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]

	stream := cipher.NewCFBDecrypter(block, iv)

	stream.XORKeyStream(ciphertext, ciphertext)

	return fmt.Sprintf("%s", ciphertext)
}
<|endoftext|>


<commit_before>package client

import (
	"fmt"
	"github.com/coreos/fleet/schema"
	"github.com/juju/errgo"
	execPkg "os/exec"
	"strings"
)

const (
	FLEETCTL            = "fleetctl"
	ENDPOINT_OPTION     = "--endpoint"
	ENDPOINT_VALUE      = "http://172.17.42.1:4001"
	ETCD_PREFIX_OPTION  = "--etcd-key-prefix"
	DEFAULT_ETCD_PREFIX = "/_coreos.com/fleet/"
)

type ClientCLI struct {
	etcdPeer   string
	driver     string
	etcdPrefix string
}

func NewClientCLI() FleetClient {
	return NewClientCLIWithPeer(ENDPOINT_VALUE)
}

func NewClientCLIWithPeer(etcdPeer string) FleetClient {
	return &ClientCLI{
		etcdPeer:   etcdPeer,
		driver:     "--driver=etcd",
		etcdPrefix: DEFAULT_ETCD_PREFIX,
	}
}

func NewClientCLIWithPeerAndPrefix(etcdPeer, etcdPrefix string) FleetClient {
	client := NewClientCLIWithPeer(etcdPeer)
	if etcdPrefix == "" {
		etcdPrefix = DEFAULT_ETCD_PREFIX
	}
	return &ClientCLI{
		etcdPeer:   etcdPeer,
		driver:     getDriver(),
		etcdPrefix: etcdPrefix,
	}

	return client
}

func args(extras []string, required ...string) []string {
	return append(required, extras...)
}

func (this *ClientCLI) Submit(filePath ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(filePath, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "submit")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(filePath, ENDPOINT_OPTION, this.etcdPeer, "submit")...)
	}
	output, err := exec(cmd)
	if err != nil {
		fmt.Printf("Error in submit: %s %s\n", err, output)
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Unit(name string) (*schema.Unit, error) {
	return nil, fmt.Errorf("Method not implemented: ClientCLI.Unit")
}

func (this *ClientCLI) Start(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "start", "--no-block=true")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "start", "--no-block=true")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Stop(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "stop", "--no-block=true")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "stop", "--no-block=true")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Load(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "load", "--no-block=true")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "load", "--no-block=true")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Destroy(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "destroy")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "destroy")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}
<commit_msg>fixed bug<commit_after>package client

import (
	"fmt"
	"github.com/coreos/fleet/schema"
	"github.com/juju/errgo"
	execPkg "os/exec"
)

const (
	FLEETCTL            = "fleetctl"
	ENDPOINT_OPTION     = "--endpoint"
	ENDPOINT_VALUE      = "http://172.17.42.1:4001"
	ETCD_PREFIX_OPTION  = "--etcd-key-prefix"
	DEFAULT_ETCD_PREFIX = "/_coreos.com/fleet/"
)

type ClientCLI struct {
	etcdPeer   string
	driver     string
	etcdPrefix string
}

func NewClientCLI() FleetClient {
	return NewClientCLIWithPeer(ENDPOINT_VALUE)
}

func NewClientCLIWithPeer(etcdPeer string) FleetClient {
	return &ClientCLI{
		etcdPeer:   etcdPeer,
		driver:     "--driver=etcd",
		etcdPrefix: DEFAULT_ETCD_PREFIX,
	}
}

func NewClientCLIWithPeerAndPrefix(etcdPeer, etcdPrefix string) FleetClient {
	client := NewClientCLIWithPeer(etcdPeer)
	if etcdPrefix == "" {
		etcdPrefix = DEFAULT_ETCD_PREFIX
	}
	return &ClientCLI{
		etcdPeer:   etcdPeer,
		driver:     "--driver=etcd",
		etcdPrefix: etcdPrefix,
	}

	return client
}

func args(extras []string, required ...string) []string {
	return append(required, extras...)
}

func (this *ClientCLI) Submit(filePath ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(filePath, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "submit")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(filePath, ENDPOINT_OPTION, this.etcdPeer, "submit")...)
	}
	output, err := exec(cmd)
	if err != nil {
		fmt.Printf("Error in submit: %s %s\n", err, output)
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Unit(name string) (*schema.Unit, error) {
	return nil, fmt.Errorf("Method not implemented: ClientCLI.Unit")
}

func (this *ClientCLI) Start(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "start", "--no-block=true")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "start", "--no-block=true")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Stop(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "stop", "--no-block=true")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "stop", "--no-block=true")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Load(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "load", "--no-block=true")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "load", "--no-block=true")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}

func (this *ClientCLI) Destroy(name ...string) error {
	var cmd *execPkg.Cmd

	if this.driver != "" {
		cmd = execPkg.Command(FLEETCTL, args(name, this.driver, ENDPOINT_OPTION, this.etcdPeer, ETCD_PREFIX_OPTION, this.etcdPrefix, "destroy")...)
	} else {
		cmd = execPkg.Command(FLEETCTL, args(name, ENDPOINT_OPTION, this.etcdPeer, "destroy")...)
	}
	_, err := exec(cmd)

	if err != nil {
		return errgo.Mask(err)
	}

	return nil
}
<|endoftext|>


<commit_before>package backend

import (
    "log"
)
<commit_msg>working on the backend over here<commit_after>package main

import (
    "log"
    "flag"
    "net/http"
    "strings"
    "code.google.com/p/gorest"
    "nowac/kegg"
)

func main () {

    var ip = flag.String("ip", "localhost", "ip to run on")
    var port = flag.String("port", ":8080" ,"port to run on")

    flag.Parse()
    address := *ip+*port

    gorest.RegisterService(new(NOWACService))
    http.Handle("/", gorest.Handle())

    log.Println("Starting server on", address)
    err := http.ListenAndServe(address, nil)
    if err != nil{
        log.Panic("Could not start rest-service:", err)
    }

}

type NOWACService struct {
    gorest.RestService `root:"/"
                        consumes:"application/json"
                        produces:"application/json"`

    newPathwayGraph gorest.EndPoint `method:"GET"
                                    path:"/new/graph/pathway/{Pathways:string}"
                                    output:"string"`

}

func (serv NOWACService) NewPathwayGraph(Pathways string) string {
    addAccessControlAllowOriginHeader(serv)
    log.Print("Pathways:", parsePathwayInput(Pathways));
    pws := parsePathwayInput(Pathways);
    handler := kegg.PathwayGraphFrom(pws[0])

    return handler

}

func addAccessControlAllowOriginHeader (serv NOWACService) {
    // Allowing access control stuff
    rb := serv.ResponseBuilder()
    rb.AddHeader("Access-Control-Allow-Origin","*")
}

func parsePathwayInput(input string) ([] string) {
        // Remove any unwanted characters
	a := strings.Replace(input, "%3A", ":", -1)
	a = strings.Replace(a, "&", "", -1)
	a = strings.Replace(a, "=", "", -1)

	// Split into separate hsa:... strings
	b := strings.Split(a, "pathwaySelect")

	// Clear out first empty item
	b = b[1:len(b)]

    return b

}
<|endoftext|>


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

package gc

// auto generated by go tool dist
var opnames = []string{
	OXXX:             "XXX",
	ONAME:            "NAME",
	ONONAME:          "NONAME",
	OTYPE:            "TYPE",
	OPACK:            "PACK",
	OLITERAL:         "LITERAL",
	OADD:             "ADD",
	OSUB:             "SUB",
	OOR:              "OR",
	OXOR:             "XOR",
	OADDSTR:          "ADDSTR",
	OADDR:            "ADDR",
	OANDAND:          "ANDAND",
	OAPPEND:          "APPEND",
	OARRAYBYTESTR:    "ARRAYBYTESTR",
	OARRAYBYTESTRTMP: "ARRAYBYTESTRTMP",
	OARRAYRUNESTR:    "ARRAYRUNESTR",
	OSTRARRAYBYTE:    "STRARRAYBYTE",
	OSTRARRAYBYTETMP: "STRARRAYBYTETMP",
	OSTRARRAYRUNE:    "STRARRAYRUNE",
	OAS:              "AS",
	OAS2:             "AS2",
	OAS2FUNC:         "AS2FUNC",
	OAS2RECV:         "AS2RECV",
	OAS2MAPR:         "AS2MAPR",
	OAS2DOTTYPE:      "AS2DOTTYPE",
	OASOP:            "ASOP",
	OASWB:            "ASWB",
	OCALL:            "CALL",
	OCALLFUNC:        "CALLFUNC",
	OCALLMETH:        "CALLMETH",
	OCALLINTER:       "CALLINTER",
	OCALLPART:        "CALLPART",
	OCAP:             "CAP",
	OCLOSE:           "CLOSE",
	OCLOSURE:         "CLOSURE",
	OCMPIFACE:        "CMPIFACE",
	OCMPSTR:          "CMPSTR",
	OCOMPLIT:         "COMPLIT",
	OMAPLIT:          "MAPLIT",
	OSTRUCTLIT:       "STRUCTLIT",
	OARRAYLIT:        "ARRAYLIT",
	OPTRLIT:          "PTRLIT",
	OCONV:            "CONV",
	OCONVIFACE:       "CONVIFACE",
	OCONVNOP:         "CONVNOP",
	OCOPY:            "COPY",
	ODCL:             "DCL",
	ODCLFUNC:         "DCLFUNC",
	ODCLFIELD:        "DCLFIELD",
	ODCLCONST:        "DCLCONST",
	ODCLTYPE:         "DCLTYPE",
	ODELETE:          "DELETE",
	ODOT:             "DOT",
	ODOTPTR:          "DOTPTR",
	ODOTMETH:         "DOTMETH",
	ODOTINTER:        "DOTINTER",
	OXDOT:            "XDOT",
	ODOTTYPE:         "DOTTYPE",
	ODOTTYPE2:        "DOTTYPE2",
	OEQ:              "EQ",
	ONE:              "NE",
	OLT:              "LT",
	OLE:              "LE",
	OGE:              "GE",
	OGT:              "GT",
	OIND:             "IND",
	OINDEX:           "INDEX",
	OINDEXMAP:        "INDEXMAP",
	OKEY:             "KEY",
	OPARAM:           "PARAM",
	OLEN:             "LEN",
	OMAKE:            "MAKE",
	OMAKECHAN:        "MAKECHAN",
	OMAKEMAP:         "MAKEMAP",
	OMAKESLICE:       "MAKESLICE",
	OMUL:             "MUL",
	ODIV:             "DIV",
	OMOD:             "MOD",
	OLSH:             "LSH",
	ORSH:             "RSH",
	OAND:             "AND",
	OANDNOT:          "ANDNOT",
	ONEW:             "NEW",
	ONOT:             "NOT",
	OCOM:             "COM",
	OPLUS:            "PLUS",
	OMINUS:           "MINUS",
	OOROR:            "OROR",
	OPANIC:           "PANIC",
	OPRINT:           "PRINT",
	OPRINTN:          "PRINTN",
	OPAREN:           "PAREN",
	OSEND:            "SEND",
	OSLICE:           "SLICE",
	OSLICEARR:        "SLICEARR",
	OSLICESTR:        "SLICESTR",
	OSLICE3:          "SLICE3",
	OSLICE3ARR:       "SLICE3ARR",
	ORECOVER:         "RECOVER",
	ORECV:            "RECV",
	ORUNESTR:         "RUNESTR",
	OSELRECV:         "SELRECV",
	OSELRECV2:        "SELRECV2",
	OIOTA:            "IOTA",
	OREAL:            "REAL",
	OIMAG:            "IMAG",
	OCOMPLEX:         "COMPLEX",
	OBLOCK:           "BLOCK",
	OBREAK:           "BREAK",
	OCASE:            "CASE",
	OXCASE:           "XCASE",
	OCONTINUE:        "CONTINUE",
	ODEFER:           "DEFER",
	OEMPTY:           "EMPTY",
	OFALL:            "FALL",
	OXFALL:           "XFALL",
	OFOR:             "FOR",
	OGOTO:            "GOTO",
	OIF:              "IF",
	OLABEL:           "LABEL",
	OPROC:            "PROC",
	ORANGE:           "RANGE",
	ORETURN:          "RETURN",
	OSELECT:          "SELECT",
	OSWITCH:          "SWITCH",
	OTYPESW:          "TYPESW",
	OTCHAN:           "TCHAN",
	OTMAP:            "TMAP",
	OTSTRUCT:         "TSTRUCT",
	OTINTER:          "TINTER",
	OTFUNC:           "TFUNC",
	OTARRAY:          "TARRAY",
	ODDD:             "DDD",
	ODDDARG:          "DDDARG",
	OINLCALL:         "INLCALL",
	OEFACE:           "EFACE",
	OITAB:            "ITAB",
	OSPTR:            "SPTR",
	OCLOSUREVAR:      "CLOSUREVAR",
	OCFUNC:           "CFUNC",
	OCHECKNIL:        "CHECKNIL",
	OVARKILL:         "VARKILL",
	OREGISTER:        "REGISTER",
	OINDREG:          "INDREG",
	OCMP:             "CMP",
	ODEC:             "DEC",
	OINC:             "INC",
	OEXTEND:          "EXTEND",
	OHMUL:            "HMUL",
	OLROT:            "LROT",
	ORROTC:           "RROTC",
	ORETJMP:          "RETJMP",
	OEND:             "END",
}
<commit_msg>cmd/compile: add VARLIVE to opnames list<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gc

// auto generated by go tool dist
var opnames = []string{
	OXXX:             "XXX",
	ONAME:            "NAME",
	ONONAME:          "NONAME",
	OTYPE:            "TYPE",
	OPACK:            "PACK",
	OLITERAL:         "LITERAL",
	OADD:             "ADD",
	OSUB:             "SUB",
	OOR:              "OR",
	OXOR:             "XOR",
	OADDSTR:          "ADDSTR",
	OADDR:            "ADDR",
	OANDAND:          "ANDAND",
	OAPPEND:          "APPEND",
	OARRAYBYTESTR:    "ARRAYBYTESTR",
	OARRAYBYTESTRTMP: "ARRAYBYTESTRTMP",
	OARRAYRUNESTR:    "ARRAYRUNESTR",
	OSTRARRAYBYTE:    "STRARRAYBYTE",
	OSTRARRAYBYTETMP: "STRARRAYBYTETMP",
	OSTRARRAYRUNE:    "STRARRAYRUNE",
	OAS:              "AS",
	OAS2:             "AS2",
	OAS2FUNC:         "AS2FUNC",
	OAS2RECV:         "AS2RECV",
	OAS2MAPR:         "AS2MAPR",
	OAS2DOTTYPE:      "AS2DOTTYPE",
	OASOP:            "ASOP",
	OASWB:            "ASWB",
	OCALL:            "CALL",
	OCALLFUNC:        "CALLFUNC",
	OCALLMETH:        "CALLMETH",
	OCALLINTER:       "CALLINTER",
	OCALLPART:        "CALLPART",
	OCAP:             "CAP",
	OCLOSE:           "CLOSE",
	OCLOSURE:         "CLOSURE",
	OCMPIFACE:        "CMPIFACE",
	OCMPSTR:          "CMPSTR",
	OCOMPLIT:         "COMPLIT",
	OMAPLIT:          "MAPLIT",
	OSTRUCTLIT:       "STRUCTLIT",
	OARRAYLIT:        "ARRAYLIT",
	OPTRLIT:          "PTRLIT",
	OCONV:            "CONV",
	OCONVIFACE:       "CONVIFACE",
	OCONVNOP:         "CONVNOP",
	OCOPY:            "COPY",
	ODCL:             "DCL",
	ODCLFUNC:         "DCLFUNC",
	ODCLFIELD:        "DCLFIELD",
	ODCLCONST:        "DCLCONST",
	ODCLTYPE:         "DCLTYPE",
	ODELETE:          "DELETE",
	ODOT:             "DOT",
	ODOTPTR:          "DOTPTR",
	ODOTMETH:         "DOTMETH",
	ODOTINTER:        "DOTINTER",
	OXDOT:            "XDOT",
	ODOTTYPE:         "DOTTYPE",
	ODOTTYPE2:        "DOTTYPE2",
	OEQ:              "EQ",
	ONE:              "NE",
	OLT:              "LT",
	OLE:              "LE",
	OGE:              "GE",
	OGT:              "GT",
	OIND:             "IND",
	OINDEX:           "INDEX",
	OINDEXMAP:        "INDEXMAP",
	OKEY:             "KEY",
	OPARAM:           "PARAM",
	OLEN:             "LEN",
	OMAKE:            "MAKE",
	OMAKECHAN:        "MAKECHAN",
	OMAKEMAP:         "MAKEMAP",
	OMAKESLICE:       "MAKESLICE",
	OMUL:             "MUL",
	ODIV:             "DIV",
	OMOD:             "MOD",
	OLSH:             "LSH",
	ORSH:             "RSH",
	OAND:             "AND",
	OANDNOT:          "ANDNOT",
	ONEW:             "NEW",
	ONOT:             "NOT",
	OCOM:             "COM",
	OPLUS:            "PLUS",
	OMINUS:           "MINUS",
	OOROR:            "OROR",
	OPANIC:           "PANIC",
	OPRINT:           "PRINT",
	OPRINTN:          "PRINTN",
	OPAREN:           "PAREN",
	OSEND:            "SEND",
	OSLICE:           "SLICE",
	OSLICEARR:        "SLICEARR",
	OSLICESTR:        "SLICESTR",
	OSLICE3:          "SLICE3",
	OSLICE3ARR:       "SLICE3ARR",
	ORECOVER:         "RECOVER",
	ORECV:            "RECV",
	ORUNESTR:         "RUNESTR",
	OSELRECV:         "SELRECV",
	OSELRECV2:        "SELRECV2",
	OIOTA:            "IOTA",
	OREAL:            "REAL",
	OIMAG:            "IMAG",
	OCOMPLEX:         "COMPLEX",
	OBLOCK:           "BLOCK",
	OBREAK:           "BREAK",
	OCASE:            "CASE",
	OXCASE:           "XCASE",
	OCONTINUE:        "CONTINUE",
	ODEFER:           "DEFER",
	OEMPTY:           "EMPTY",
	OFALL:            "FALL",
	OXFALL:           "XFALL",
	OFOR:             "FOR",
	OGOTO:            "GOTO",
	OIF:              "IF",
	OLABEL:           "LABEL",
	OPROC:            "PROC",
	ORANGE:           "RANGE",
	ORETURN:          "RETURN",
	OSELECT:          "SELECT",
	OSWITCH:          "SWITCH",
	OTYPESW:          "TYPESW",
	OTCHAN:           "TCHAN",
	OTMAP:            "TMAP",
	OTSTRUCT:         "TSTRUCT",
	OTINTER:          "TINTER",
	OTFUNC:           "TFUNC",
	OTARRAY:          "TARRAY",
	ODDD:             "DDD",
	ODDDARG:          "DDDARG",
	OINLCALL:         "INLCALL",
	OEFACE:           "EFACE",
	OITAB:            "ITAB",
	OSPTR:            "SPTR",
	OCLOSUREVAR:      "CLOSUREVAR",
	OCFUNC:           "CFUNC",
	OCHECKNIL:        "CHECKNIL",
	OVARKILL:         "VARKILL",
	OVARLIVE:         "VARLIVE",
	OREGISTER:        "REGISTER",
	OINDREG:          "INDREG",
	OCMP:             "CMP",
	ODEC:             "DEC",
	OINC:             "INC",
	OEXTEND:          "EXTEND",
	OHMUL:            "HMUL",
	OLROT:            "LROT",
	ORROTC:           "RROTC",
	ORETJMP:          "RETJMP",
	OEND:             "END",
}
<|endoftext|>


<commit_before>package archetype

import (
	"archive/zip"
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"
	"text/template"
	"time"

	"github.com/Masterminds/sprig"
	awsEvents "github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-sdk-go/aws/session"
	sparta "github.com/mweagle/Sparta"
	"github.com/mweagle/Sparta/archetype/xformer"
	gocf "github.com/mweagle/go-cloudformation"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

func dropError() error {
	return errors.New("KinesisFirehoseDrop")
}

// TemplateFileName is the name of the file in the ZIP archive
const TemplateFileName = "xform.template"
const xformResourcePrefix = "firehosexform_"
const envVarKinesisFirehoseTransformName = "SPARTA_KINESIS_FIREHOSE_TRANSFORM"

// KinesisFirehoseReactor represents a lambda function that responds to Dynamo  messages
type KinesisFirehoseReactor interface {
	// OnKinesisFirehoseRecord when an Kinesis reocrd occurs.
	OnKinesisFirehoseRecord(ctx context.Context,
		record *awsEvents.KinesisFirehoseEventRecord) (*awsEvents.KinesisFirehoseResponseRecord, error)
}

// KinesisFirehoseReactorFunc is a free function that adapts a KinesisFirehoseReactor
// compliant signature into a function that exposes an OnEvent
// function
type KinesisFirehoseReactorFunc func(ctx context.Context,
	kinesisRecord *awsEvents.KinesisFirehoseEventRecord) (*awsEvents.KinesisFirehoseResponseRecord, error)

// OnKinesisFirehoseRecord satisfies the KinesisFirehoseReactor interface
func (reactorFunc KinesisFirehoseReactorFunc) OnKinesisFirehoseRecord(ctx context.Context,
	kinesisRecord *awsEvents.KinesisFirehoseEventRecord) (*awsEvents.KinesisFirehoseResponseRecord, error) {
	return reactorFunc(ctx, kinesisRecord)
}

// ReactorName provides the name of the reactor func
func (reactorFunc KinesisFirehoseReactorFunc) ReactorName() string {
	return runtime.FuncForPC(reflect.ValueOf(reactorFunc).Pointer()).Name()
}

// NewKinesisFirehoseLambdaTransformer returns a new firehose proocessor that supports
// transforming records.
func NewKinesisFirehoseLambdaTransformer(reactor KinesisFirehoseReactor,
	timeout time.Duration) (*sparta.LambdaAWSInfo, error) {

	reactorLambda := func(ctx context.Context,
		kinesisFirehoseEvent awsEvents.KinesisFirehoseEvent) (interface{}, error) {
		// Apply the transform to each record and see
		// what it says

		response := &awsEvents.KinesisFirehoseResponse{
			Records: make([]awsEvents.KinesisFirehoseResponseRecord,
				len(kinesisFirehoseEvent.Records)),
		}

		var responseRecord *awsEvents.KinesisFirehoseResponseRecord
		var responseRecordErr error
		for eachIndex, eachRecord := range kinesisFirehoseEvent.Records {
			responseRecord, responseRecordErr = reactor.OnKinesisFirehoseRecord(ctx, &eachRecord)
			if responseRecordErr != nil {
				return nil, errors.Wrapf(responseRecordErr, "Failed to transform record")
			}
			if responseRecord == nil {
				responseRecord = &awsEvents.KinesisFirehoseResponseRecord{
					RecordID: eachRecord.RecordID,
					Result:   awsEvents.KinesisFirehoseTransformedStateDropped,
					Data:     eachRecord.Data,
				}
			}
			response.Records[eachIndex] = *responseRecord
		}
		return response, nil
	}

	lambdaFn, lambdaFnErr := sparta.NewAWSLambda(reactorName(reactor),
		reactorLambda,
		sparta.IAMRoleDefinition{})
	return lambdaFn, lambdaFnErr
}

// NewKinesisFirehoseTransformer returns a new firehose proocessor that supports
// transforming records.
func NewKinesisFirehoseTransformer(xformFilePath string,
	timeout time.Duration,
	hooks *sparta.WorkflowHooks) (*sparta.LambdaAWSInfo, error) {

	baseName := filepath.Base(xformFilePath)
	archiveEntryName := sparta.CloudFormationResourceName(xformResourcePrefix, xformFilePath)
	lambdaName := fmt.Sprintf("Firehose%s", baseName)

	// Return a lambda function that applies the XForm transformation
	reactorLambda := func(ctx context.Context,
		kinesisEvent awsEvents.KinesisFirehoseEvent) (*awsEvents.KinesisFirehoseResponse, error) {
		return lambdaXForm(ctx, kinesisEvent)
	}
	lambdaFn, lambdaFnErr := sparta.NewAWSLambda(lambdaName,
		reactorLambda,
		sparta.IAMRoleDefinition{})
	if lambdaFnErr != nil {
		return nil, errors.Wrapf(lambdaFnErr, "attempting to create Kinesis Firehose reactor")
	}

	// Borrow the resource name creator to get a name for the archive
	lambdaFn.Options.Environment[envVarKinesisFirehoseTransformName] = gocf.String(archiveEntryName)
	lambdaFn.Options.Timeout = (timeout.Milliseconds() / 1000)

	// Create the decorator that adds the file to the ZIP archive using
	// the transform name...
	archiveDecorator := func(context map[string]interface{},
		serviceName string,
		zipWriter *zip.Writer,
		awsSession *session.Session,
		noop bool,
		logger *logrus.Logger) error {
		fileInfo, fileInfoErr := os.Stat(xformFilePath)
		if fileInfoErr != nil {
			return errors.Wrapf(fileInfoErr, "Failed to get fileInfo for Kinesis Firehose transform")
		}
		// G304: Potential file inclusion via variable
		/* #nosec */
		fileReader, fileReaderErr := os.Open(xformFilePath)
		if fileReaderErr != nil {
			return errors.Wrapf(fileReaderErr, "Failed to open Kinesis Firehose transform file")
		}
		defer func() {
			closeErr := fileReader.Close()

			if closeErr != nil {
				logger.WithFields(logrus.Fields{
					"error": closeErr,
				}).Warn("Failed to close file reader")
			}
		}()

		fileHeader, fileHeaderErr := zip.FileInfoHeader(fileInfo)
		if fileHeaderErr != nil {
			return errors.Wrapf(fileHeaderErr, "Failed to detect ZIP header for Kinesis Firehose transform")
		}

		fileHeader.Name = archiveEntryName
		fileHeader.Method = zip.Deflate

		// Copy it...
		writer, writerErr := zipWriter.CreateHeader(fileHeader)
		if writerErr != nil {
			return errors.Wrapf(fileHeaderErr, "Failed to create ZIP header for Kinesis Firehose transform")
		}
		_, copyErr := io.Copy(writer, fileReader)
		return copyErr
	}
	// Done...
	hooks.Archives = append(hooks.Archives, sparta.ArchiveHookFunc(archiveDecorator))
	return lambdaFn, nil
}

// ApplyTransformToKinesisFirehoseEvent is the generic transformation function that applies
// a template.Template transformation to each
func ApplyTransformToKinesisFirehoseEvent(ctx context.Context,
	templateBytes []byte,
	kinesisEvent awsEvents.KinesisFirehoseEvent) (*awsEvents.KinesisFirehoseResponse, error) {

	logger, loggerOk := ctx.Value(sparta.ContextKeyLogger).(*logrus.Logger)
	if loggerOk {
		logger.Info("Hello world structured log message")
	}

	funcMap := sprig.TxtFuncMap()
	funcMap["KinesisFirehoseDrop"] = interface{}(func() (string, error) {
		return "", dropError()
	})

	// Setup the function map that knows how to do the JMESPath
	// given the map...
	transform, transformErr := template.
		New("xformer").
		Funcs(funcMap).
		Parse(string(templateBytes))
	if transformErr != nil {
		return nil, errors.Wrapf(transformErr, "Attempting to create template")
	}

	response := &awsEvents.KinesisFirehoseResponse{
		Records: make([]awsEvents.KinesisFirehoseResponseRecord, len(kinesisEvent.Records)),
	}
	headerInfo := &xformer.KinesisEventHeaderInfo{
		InvocationID: kinesisEvent.InvocationID,

		DeliveryStreamArn:      kinesisEvent.DeliveryStreamArn,
		SourceKinesisStreamArn: kinesisEvent.SourceKinesisStreamArn,
		Region:                 kinesisEvent.Region,
	}

	for eachIndex, eachRecord := range kinesisEvent.Records {
		xformedRecord := awsEvents.KinesisFirehoseResponseRecord{
			RecordID: eachRecord.RecordID,
			Result:   awsEvents.KinesisFirehoseTransformedStateDropped,
			Data:     eachRecord.Data,
		}
		xform, xformErr := xformer.NewKinesisFirehoseEventXFormer(headerInfo, &eachRecord)
		if xformErr == nil {
			dataMap := map[string]interface{}{
				"Record": xform,
			}
			var outputBuffer bytes.Buffer
			templateErr := transform.Execute(&outputBuffer, dataMap)
			if templateErr != nil {
				// Is the fail value "KinesisFirehoseDrop" ?
				if !strings.Contains(templateErr.Error(), dropError().Error()) {
					xformedRecord.Result = awsEvents.KinesisFirehoseTransformedStateProcessingFailed
				}
			} else if xform.Error() != nil {
				xformedRecord.Result = awsEvents.KinesisFirehoseTransformedStateProcessingFailed
			} else {
				if loggerOk && logger.IsLevelEnabled(logrus.DebugLevel) {
					logger.WithFields(logrus.Fields{
						"input":  eachRecord.Data,
						"output": outputBuffer.Bytes(),
					}).Debug("Transformation result")
				}

				xformedRecord.Data = outputBuffer.Bytes()
				xformedRecord.Result = awsEvents.KinesisFirehoseTransformedStateOk
			}
		}
		// Save it...
		response.Records[eachIndex] = xformedRecord
	}
	return response, nil
}
<commit_msg>Update to new signature<commit_after>package archetype

import (
	"archive/zip"
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"reflect"
	"runtime"
	"strings"
	"text/template"
	"time"

	"github.com/Masterminds/sprig"
	awsEvents "github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-sdk-go/aws/session"
	sparta "github.com/mweagle/Sparta"
	"github.com/mweagle/Sparta/archetype/xformer"
	gocf "github.com/mweagle/go-cloudformation"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

func dropError() error {
	return errors.New("KinesisFirehoseDrop")
}

// TemplateFileName is the name of the file in the ZIP archive
const TemplateFileName = "xform.template"
const xformResourcePrefix = "firehosexform_"
const envVarKinesisFirehoseTransformName = "SPARTA_KINESIS_FIREHOSE_TRANSFORM"

// KinesisFirehoseReactor represents a lambda function that responds to Dynamo  messages
type KinesisFirehoseReactor interface {
	// OnKinesisFirehoseRecord when an Kinesis reocrd occurs.
	OnKinesisFirehoseRecord(ctx context.Context,
		record *awsEvents.KinesisFirehoseEventRecord) (*awsEvents.KinesisFirehoseResponseRecord, error)
}

// KinesisFirehoseReactorFunc is a free function that adapts a KinesisFirehoseReactor
// compliant signature into a function that exposes an OnEvent
// function
type KinesisFirehoseReactorFunc func(ctx context.Context,
	kinesisRecord *awsEvents.KinesisFirehoseEventRecord) (*awsEvents.KinesisFirehoseResponseRecord, error)

// OnKinesisFirehoseRecord satisfies the KinesisFirehoseReactor interface
func (reactorFunc KinesisFirehoseReactorFunc) OnKinesisFirehoseRecord(ctx context.Context,
	kinesisRecord *awsEvents.KinesisFirehoseEventRecord) (*awsEvents.KinesisFirehoseResponseRecord, error) {
	return reactorFunc(ctx, kinesisRecord)
}

// ReactorName provides the name of the reactor func
func (reactorFunc KinesisFirehoseReactorFunc) ReactorName() string {
	return runtime.FuncForPC(reflect.ValueOf(reactorFunc).Pointer()).Name()
}

// NewKinesisFirehoseLambdaTransformer returns a new firehose proocessor that supports
// transforming records.
func NewKinesisFirehoseLambdaTransformer(reactor KinesisFirehoseReactor,
	timeout time.Duration) (*sparta.LambdaAWSInfo, error) {

	reactorLambda := func(ctx context.Context,
		kinesisFirehoseEvent awsEvents.KinesisFirehoseEvent) (interface{}, error) {
		// Apply the transform to each record and see
		// what it says

		response := &awsEvents.KinesisFirehoseResponse{
			Records: make([]awsEvents.KinesisFirehoseResponseRecord,
				len(kinesisFirehoseEvent.Records)),
		}

		var responseRecord *awsEvents.KinesisFirehoseResponseRecord
		var responseRecordErr error
		for eachIndex, eachRecord := range kinesisFirehoseEvent.Records {
			responseRecord, responseRecordErr = reactor.OnKinesisFirehoseRecord(ctx, &eachRecord)
			if responseRecordErr != nil {
				return nil, errors.Wrapf(responseRecordErr, "Failed to transform record")
			}
			if responseRecord == nil {
				responseRecord = &awsEvents.KinesisFirehoseResponseRecord{
					RecordID: eachRecord.RecordID,
					Result:   awsEvents.KinesisFirehoseTransformedStateDropped,
					Data:     eachRecord.Data,
				}
			}
			response.Records[eachIndex] = *responseRecord
		}
		return response, nil
	}

	lambdaFn, lambdaFnErr := sparta.NewAWSLambda(reactorName(reactor),
		reactorLambda,
		sparta.IAMRoleDefinition{})
	return lambdaFn, lambdaFnErr
}

// NewKinesisFirehoseTransformer returns a new firehose proocessor that supports
// transforming records.
func NewKinesisFirehoseTransformer(xformFilePath string,
	timeout time.Duration,
	hooks *sparta.WorkflowHooks) (*sparta.LambdaAWSInfo, error) {

	baseName := filepath.Base(xformFilePath)
	archiveEntryName := sparta.CloudFormationResourceName(xformResourcePrefix, xformFilePath)
	lambdaName := fmt.Sprintf("Firehose%s", baseName)

	// Return a lambda function that applies the XForm transformation
	reactorLambda := func(ctx context.Context,
		kinesisEvent awsEvents.KinesisFirehoseEvent) (*awsEvents.KinesisFirehoseResponse, error) {
		return lambdaXForm(ctx, kinesisEvent)
	}
	lambdaFn, lambdaFnErr := sparta.NewAWSLambda(lambdaName,
		reactorLambda,
		sparta.IAMRoleDefinition{})
	if lambdaFnErr != nil {
		return nil, errors.Wrapf(lambdaFnErr, "attempting to create Kinesis Firehose reactor")
	}

	// Borrow the resource name creator to get a name for the archive
	lambdaFn.Options.Environment[envVarKinesisFirehoseTransformName] = gocf.String(archiveEntryName)
	lambdaFn.Options.Timeout = (timeout.Milliseconds() / 1000)

	// Create the decorator that adds the file to the ZIP archive using
	// the transform name...
	archiveDecorator := func(ctx context.Context,
		serviceName string,
		zipWriter *zip.Writer,
		awsSession *session.Session,
		noop bool,
		logger *logrus.Logger) (context.Context, error) {
		fileInfo, fileInfoErr := os.Stat(xformFilePath)
		if fileInfoErr != nil {
			return ctx, errors.Wrapf(fileInfoErr, "Failed to get fileInfo for Kinesis Firehose transform")
		}
		// G304: Potential file inclusion via variable
		/* #nosec */
		fileReader, fileReaderErr := os.Open(xformFilePath)
		if fileReaderErr != nil {
			return ctx, errors.Wrapf(fileReaderErr, "Failed to open Kinesis Firehose transform file")
		}
		defer func() {
			closeErr := fileReader.Close()

			if closeErr != nil {
				logger.WithFields(logrus.Fields{
					"error": closeErr,
				}).Warn("Failed to close file reader")
			}
		}()

		fileHeader, fileHeaderErr := zip.FileInfoHeader(fileInfo)
		if fileHeaderErr != nil {
			return ctx, errors.Wrapf(fileHeaderErr, "Failed to detect ZIP header for Kinesis Firehose transform")
		}

		fileHeader.Name = archiveEntryName
		fileHeader.Method = zip.Deflate

		// Copy it...
		writer, writerErr := zipWriter.CreateHeader(fileHeader)
		if writerErr != nil {
			return ctx, errors.Wrapf(fileHeaderErr, "Failed to create ZIP header for Kinesis Firehose transform")
		}
		_, copyErr := io.Copy(writer, fileReader)
		return ctx, copyErr
	}
	// Done...
	hooks.Archives = append(hooks.Archives, sparta.ArchiveHookFunc(archiveDecorator))
	return lambdaFn, nil
}

// ApplyTransformToKinesisFirehoseEvent is the generic transformation function that applies
// a template.Template transformation to each
func ApplyTransformToKinesisFirehoseEvent(ctx context.Context,
	templateBytes []byte,
	kinesisEvent awsEvents.KinesisFirehoseEvent) (*awsEvents.KinesisFirehoseResponse, error) {

	logger, loggerOk := ctx.Value(sparta.ContextKeyLogger).(*logrus.Logger)
	if loggerOk {
		logger.Info("Hello world structured log message")
	}

	funcMap := sprig.TxtFuncMap()
	funcMap["KinesisFirehoseDrop"] = interface{}(func() (string, error) {
		return "", dropError()
	})

	// Setup the function map that knows how to do the JMESPath
	// given the map...
	transform, transformErr := template.
		New("xformer").
		Funcs(funcMap).
		Parse(string(templateBytes))
	if transformErr != nil {
		return nil, errors.Wrapf(transformErr, "Attempting to create template")
	}

	response := &awsEvents.KinesisFirehoseResponse{
		Records: make([]awsEvents.KinesisFirehoseResponseRecord, len(kinesisEvent.Records)),
	}
	headerInfo := &xformer.KinesisEventHeaderInfo{
		InvocationID: kinesisEvent.InvocationID,

		DeliveryStreamArn:      kinesisEvent.DeliveryStreamArn,
		SourceKinesisStreamArn: kinesisEvent.SourceKinesisStreamArn,
		Region:                 kinesisEvent.Region,
	}

	for eachIndex, eachRecord := range kinesisEvent.Records {
		xformedRecord := awsEvents.KinesisFirehoseResponseRecord{
			RecordID: eachRecord.RecordID,
			Result:   awsEvents.KinesisFirehoseTransformedStateDropped,
			Data:     eachRecord.Data,
		}
		xform, xformErr := xformer.NewKinesisFirehoseEventXFormer(headerInfo, &eachRecord)
		if xformErr == nil {
			dataMap := map[string]interface{}{
				"Record": xform,
			}
			var outputBuffer bytes.Buffer
			templateErr := transform.Execute(&outputBuffer, dataMap)
			if templateErr != nil {
				// Is the fail value "KinesisFirehoseDrop" ?
				if !strings.Contains(templateErr.Error(), dropError().Error()) {
					xformedRecord.Result = awsEvents.KinesisFirehoseTransformedStateProcessingFailed
				}
			} else if xform.Error() != nil {
				xformedRecord.Result = awsEvents.KinesisFirehoseTransformedStateProcessingFailed
			} else {
				if loggerOk && logger.IsLevelEnabled(logrus.DebugLevel) {
					logger.WithFields(logrus.Fields{
						"input":  eachRecord.Data,
						"output": outputBuffer.Bytes(),
					}).Debug("Transformation result")
				}

				xformedRecord.Data = outputBuffer.Bytes()
				xformedRecord.Result = awsEvents.KinesisFirehoseTransformedStateOk
			}
		}
		// Save it...
		response.Records[eachIndex] = xformedRecord
	}
	return response, nil
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"strconv"

	"github.com/asaskevich/govalidator"
	"github.com/mebiusashan/beaker/cli"
	"github.com/mebiusashan/beaker/common"
	"github.com/mitchellh/go-homedir"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

type websiteConfig struct {
	Alias string
	HOST  string
	Key   string
}

type config struct {
	DefaultWebsite string
	Editor         string
	Websites       []websiteConfig
}

var (
	localConfig         config
	addWebSiteAlias     string
	addWebSiteUser      string
	addWebSitePassword  string
	addWebSiteIsDefault bool

	configCmd = &cobra.Command{
		Use:   "config",
		Short: "Configure blog information",
		Long: `The configuration command can
set your blog background address`,
		Run: func(cmd *cobra.Command, args []string) {
			editor := common.DefaultEditor
			if localConfig.Editor != "" {
				editor = localConfig.Editor
			}
			fmt.Println("Editor:", editor)
			l := len(localConfig.Websites)
			fmt.Println("Total number of sites:", l)
			if l == 0 {
				return
			}
			fmt.Println("Default Website:", localConfig.DefaultWebsite)
			fmt.Println("-----------------------------")
			max := 0
			for _, d := range localConfig.Websites {
				if len(d.Alias) > max {
					max = len(d.Alias)
				}
			}
			for _, d := range localConfig.Websites {
				fmt.Printf("%-"+strconv.Itoa(max)+"s %s\n", d.Alias, d.HOST)
			}
		},
	}

	addWebSiteCmd = &cobra.Command{
		Use:   "addw",
		Short: "Add blog site information",
		Long: `To add a blog server information,
you need to specify the blog address,
user name and password, and it will be
verified after adding`,
		Args: cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			url := args[0]
			if !govalidator.IsURL(url) && !govalidator.IsIP(url) {
				common.Err("Blog address format error")
			}

			if addWebSiteAlias == "" {
				common.Err("Alias cannot be empty")
			}

			//check current config , has duplicate config
			for _, website := range localConfig.Websites {
				if website.Alias == addWebSiteAlias {
					common.Err("Duplicate alias")
				}
				if website.HOST == url {
					common.Err("Duplicate host")
				}
			}
			login(url, addWebSiteUser, addWebSitePassword)
		},
	}

	rmWebsiteCmd = &cobra.Command{
		Use:   "rmw",
		Short: "Remove a website information",
		Long: `Remove a website information in
the local record, if the website is the default
website, set the first one of the remaining
website information as the default website`,
		Args: cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			alias := args[0]
			isDefault := localConfig.DefaultWebsite == alias
			for i := 0; i < len(localConfig.Websites); i++ {
				if isDefault && localConfig.Websites[i].Alias != alias {
					localConfig.DefaultWebsite = localConfig.Websites[i].Alias
					isDefault = false
				}
				if localConfig.Websites[i].Alias == alias {
					localConfig.Websites = append(localConfig.Websites[:i], localConfig.Websites[i+1:]...)
					writeConfig()
					return
				}
			}
		},
	}

	loginCmd = &cobra.Command{
		Use:   "login",
		Short: "Log in to the website",
		Long: `When the website login expires,
use the login command to log in again and obtain
operation permissions`,
		Args: cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			alias := args[0]
			info := getWebsiteInfoWithAlias(alias)
			login(info.HOST, addWebSiteUser, addWebSitePassword)
		},
	}
)

func init() {
	addWebSiteCmd.PersistentFlags().StringVarP(&addWebSiteAlias, "alias", "a", "", "blog alias")
	addWebSiteCmd.PersistentFlags().StringVarP(&addWebSiteUser, "user", "u", "", "blog administrator account name")
	addWebSiteCmd.PersistentFlags().StringVarP(&addWebSitePassword, "password", "p", "", "blog administrator account password")
	addWebSiteCmd.PersistentFlags().BoolVarP(&addWebSiteIsDefault, "defalut", "d", false, "set as default blog")

	loginCmd.PersistentFlags().StringVarP(&addWebSiteUser, "user", "u", "", "blog administrator account name")
	loginCmd.PersistentFlags().StringVarP(&addWebSitePassword, "password", "p", "", "blog administrator account password")

	configCmd.AddCommand(addWebSiteCmd)
	configCmd.AddCommand(rmWebsiteCmd)
	configCmd.AddCommand(loginCmd)
}

func initConfig() {
	home, err := homedir.Dir()
	common.Assert(err)

	viper.AddConfigPath(home)
	viper.SetConfigType("yaml")
	viper.SetConfigName(".beaker")
	viper.SafeWriteConfig()

	err = viper.ReadInConfig()
	common.Assert(err)

	err = viper.UnmarshalKey("config", &localConfig)
	common.Assert(err)
}

func checkWebsite() {
	if len(localConfig.Websites) == 0 {
		common.Err("No website information is configured")
	}
	info := getWebsiteInfo()
	rel := cli.Check(info.HOST, []byte(info.Key))
	if !rel {
		fmt.Println("Login invalid, please login again")
	}
}

func getWebsiteInfo() *websiteConfig {
	return getWebsiteInfoWithAlias(actionWebsite)
}

func getWebsiteInfoWithAlias(alias string) *websiteConfig {
	if alias == "" || alias == "default" {
		alias = localConfig.DefaultWebsite
	}

	for _, d := range localConfig.Websites {
		if d.Alias == alias {
			return &d
		}
	}

	common.Err(actionWebsite + " website information does not exist")
	return nil
}

func login(url string, username string, password string) {
	//need login with current website
	//if success login, set info and server key to config file
	//if it's default website, need reset all website config
	pubKey := cli.Ping(url)
	serverPubKey := cli.Login(url, pubKey, username, password)
	if cli.Check(url, serverPubKey) {
		if len(localConfig.Websites) == 0 || localConfig.Websites == nil {
			localConfig.Websites = make([]websiteConfig, 0)
			addWebSiteIsDefault = true
		}
		if addWebSiteIsDefault {
			localConfig.DefaultWebsite = addWebSiteAlias
		}

		for _, v := range localConfig.Websites {
			if v.HOST == url {
				v.Key = string(serverPubKey)
				writeConfig()
				return
			}
		}

		d := websiteConfig{Alias: addWebSiteAlias, HOST: url, Key: string(serverPubKey)}
		localConfig.Websites = append(localConfig.Websites, d)
		writeConfig()
	} else {
		fmt.Println("login fail")
	}
}

func writeConfig() {
	viper.Set("config", localConfig)
	err := viper.WriteConfig()
	common.Assert(err)
}
<commit_msg>add set editor command<commit_after>package cmd

import (
	"fmt"
	"strconv"

	"github.com/asaskevich/govalidator"
	"github.com/mebiusashan/beaker/cli"
	"github.com/mebiusashan/beaker/common"
	"github.com/mitchellh/go-homedir"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

type websiteConfig struct {
	Alias string
	HOST  string
	Key   string
}

type config struct {
	DefaultWebsite string
	Editor         string
	Websites       []websiteConfig
}

var (
	localConfig         config
	addWebSiteAlias     string
	addWebSiteUser      string
	addWebSitePassword  string
	addWebSiteIsDefault bool

	configCmd = &cobra.Command{
		Use:   "config",
		Short: "Configure blog information",
		Long: `The configuration command can
set your blog background address`,
		Run: func(cmd *cobra.Command, args []string) {
			editor := common.DefaultEditor
			if localConfig.Editor != "" {
				editor = localConfig.Editor
			}
			fmt.Println("Editor:", editor)
			l := len(localConfig.Websites)
			fmt.Println("Total number of sites:", l)
			if l == 0 {
				return
			}
			fmt.Println("Default Website:", localConfig.DefaultWebsite)
			fmt.Println("-----------------------------")
			max := 0
			for _, d := range localConfig.Websites {
				if len(d.Alias) > max {
					max = len(d.Alias)
				}
			}
			for _, d := range localConfig.Websites {
				fmt.Printf("%-"+strconv.Itoa(max)+"s %s\n", d.Alias, d.HOST)
			}
		},
	}

	addWebSiteCmd = &cobra.Command{
		Use:   "addw",
		Short: "Add blog site information",
		Long: `To add a blog server information,
you need to specify the blog address,
user name and password, and it will be
verified after adding`,
		Args: cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			url := args[0]
			if !govalidator.IsURL(url) && !govalidator.IsIP(url) {
				common.Err("Blog address format error")
			}

			if addWebSiteAlias == "" {
				common.Err("Alias cannot be empty")
			}

			//check current config , has duplicate config
			for _, website := range localConfig.Websites {
				if website.Alias == addWebSiteAlias {
					common.Err("Duplicate alias")
				}
				if website.HOST == url {
					common.Err("Duplicate host")
				}
			}
			login(url, addWebSiteUser, addWebSitePassword)
		},
	}

	rmWebsiteCmd = &cobra.Command{
		Use:   "rmw",
		Short: "Remove a website information",
		Long: `Remove a website information in
the local record, if the website is the default
website, set the first one of the remaining
website information as the default website`,
		Args: cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			alias := args[0]
			isDefault := localConfig.DefaultWebsite == alias
			for i := 0; i < len(localConfig.Websites); i++ {
				if isDefault && localConfig.Websites[i].Alias != alias {
					localConfig.DefaultWebsite = localConfig.Websites[i].Alias
					isDefault = false
				}
				if localConfig.Websites[i].Alias == alias {
					localConfig.Websites = append(localConfig.Websites[:i], localConfig.Websites[i+1:]...)
					writeConfig()
					return
				}
			}
		},
	}

	loginCmd = &cobra.Command{
		Use:   "login",
		Short: "Log in to the website",
		Long: `When the website login expires,
use the login command to log in again and obtain
operation permissions`,
		Args: cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			alias := args[0]
			info := getWebsiteInfoWithAlias(alias)
			login(info.HOST, addWebSiteUser, addWebSitePassword)
		},
	}

	setEditorCmd = &cobra.Command{
		Use:   "editor",
		Short: "",
		Long:  ``,
		Args:  cobra.ExactArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			editor := args[0]
			localConfig.Editor = editor
			writeConfig()
		},
	}
)

func init() {
	addWebSiteCmd.PersistentFlags().StringVarP(&addWebSiteAlias, "alias", "a", "", "blog alias")
	addWebSiteCmd.PersistentFlags().StringVarP(&addWebSiteUser, "user", "u", "", "blog administrator account name")
	addWebSiteCmd.PersistentFlags().StringVarP(&addWebSitePassword, "password", "p", "", "blog administrator account password")
	addWebSiteCmd.PersistentFlags().BoolVarP(&addWebSiteIsDefault, "defalut", "d", false, "set as default blog")

	loginCmd.PersistentFlags().StringVarP(&addWebSiteUser, "user", "u", "", "blog administrator account name")
	loginCmd.PersistentFlags().StringVarP(&addWebSitePassword, "password", "p", "", "blog administrator account password")

	configCmd.AddCommand(addWebSiteCmd)
	configCmd.AddCommand(rmWebsiteCmd)
	configCmd.AddCommand(loginCmd)
	configCmd.AddCommand(setEditorCmd)
}

func initConfig() {
	home, err := homedir.Dir()
	common.Assert(err)

	viper.AddConfigPath(home)
	viper.SetConfigType("yaml")
	viper.SetConfigName(".beaker")
	viper.SafeWriteConfig()

	err = viper.ReadInConfig()
	common.Assert(err)

	err = viper.UnmarshalKey("config", &localConfig)
	common.Assert(err)
}

func checkWebsite() {
	if len(localConfig.Websites) == 0 {
		common.Err("No website information is configured")
	}
	info := getWebsiteInfo()
	rel := cli.Check(info.HOST, []byte(info.Key))
	if !rel {
		fmt.Println("Login invalid, please login again")
	}
}

func getWebsiteInfo() *websiteConfig {
	return getWebsiteInfoWithAlias(actionWebsite)
}

func getWebsiteInfoWithAlias(alias string) *websiteConfig {
	if alias == "" || alias == "default" {
		alias = localConfig.DefaultWebsite
	}

	for _, d := range localConfig.Websites {
		if d.Alias == alias {
			return &d
		}
	}

	common.Err(actionWebsite + " website information does not exist")
	return nil
}

func login(url string, username string, password string) {
	//need login with current website
	//if success login, set info and server key to config file
	//if it's default website, need reset all website config
	pubKey := cli.Ping(url)
	serverPubKey := cli.Login(url, pubKey, username, password)
	if cli.Check(url, serverPubKey) {
		if len(localConfig.Websites) == 0 || localConfig.Websites == nil {
			localConfig.Websites = make([]websiteConfig, 0)
			addWebSiteIsDefault = true
		}
		if addWebSiteIsDefault {
			localConfig.DefaultWebsite = addWebSiteAlias
		}

		for _, v := range localConfig.Websites {
			if v.HOST == url {
				v.Key = string(serverPubKey)
				writeConfig()
				return
			}
		}

		d := websiteConfig{Alias: addWebSiteAlias, HOST: url, Key: string(serverPubKey)}
		localConfig.Websites = append(localConfig.Websites, d)
		writeConfig()
	} else {
		fmt.Println("login fail")
	}
}

func writeConfig() {
	viper.Set("config", localConfig)
	err := viper.WriteConfig()
	common.Assert(err)
}
<|endoftext|>


<commit_before>package collector

import (
	"fullerite/config"
	"fullerite/metric"

	"strings"
	"time"

	l "github.com/Sirupsen/logrus"

	"github.com/fsouza/go-dockerclient"
)

const (
	mesosTaskID         = "MESOS_TASK_ID"
	endpoint            = "unix:///var/run/docker.sock"
	defaultStatsTimeout = 7
)

// DockerStats collector type.
// previousCPUValues contains the last cpu-usage values per container.
// dockerClient is the client for the Docker remote API.
type DockerStats struct {
	baseCollector
	previousCPUValues map[string]*CPUValues
	dockerClient      *docker.Client
	statsTimeout      int
}

// CPUValues struct contains the last cpu-usage values in order to compute properly the current values.
// (see calculateCPUPercent() for more details)
type CPUValues struct {
	totCPU, systemCPU uint64
}

// NewDockerStats creates a new DockerStats collector.
func NewDockerStats(channel chan metric.Metric, initialInterval int, log *l.Entry) *DockerStats {
	d := new(DockerStats)

	d.log = log
	d.channel = channel
	d.interval = initialInterval

	d.name = "DockerStats"
	d.previousCPUValues = make(map[string]*CPUValues)
	d.dockerClient, _ = docker.NewClient(endpoint)
	d.statsTimeout = defaultStatsTimeout

	return d
}

// Configure takes a dictionary of values with which the handler can configure itself.
func (d *DockerStats) Configure(configMap map[string]interface{}) {
	if timeout, exists := configMap["dockerStatsTimeout"]; exists {
		d.statsTimeout = config.GetAsInt(timeout, defaultStatsTimeout)
	}
	d.configureCommonParams(configMap)
}

// Collect iterates on all the docker containers alive and, if possible, collects the correspondent
// memory and cpu statistics.
// For each container a gorutine is started to spin up the collection process.
func (d *DockerStats) Collect() {
	if d.dockerClient == nil {
		d.log.Error("Invalid endpoint: ", docker.ErrInvalidEndpoint)
		return
	}
	containers, err := d.dockerClient.ListContainers(docker.ListContainersOptions{All: false})
	if err != nil {
		d.log.Error("ListContainers() failed: ", err)
		return
	}
	for _, apiContainer := range containers {
		container, err := d.dockerClient.InspectContainer(apiContainer.ID)
		if err != nil {
			d.log.Error("InspectContainer() failed: ", err)
			continue
		}
		if _, ok := d.previousCPUValues[container.ID]; !ok {
			d.previousCPUValues[container.ID] = new(CPUValues)
		}
		go d.getDockerContainerInfo(container)
	}
}

// getDockerContainerInfo gets container statistics for the given container.
// results is a channel to make possible the synchronization between the main process and the gorutines (wait-notify pattern).
func (d DockerStats) getDockerContainerInfo(container *docker.Container) {
	errC := make(chan error, 1)
	statsC := make(chan *docker.Stats, 1)
	done := make(chan bool)

	go func() {
		errC <- d.dockerClient.Stats(docker.StatsOptions{container.ID, statsC, false, done, 0})
	}()
	select {
	case stats, ok := <-statsC:
		if !ok {
			err := <-errC
			d.log.Error("Failed to collect docker container stats: ", err)
			break
		}
		done <- true

		ret := d.buildMetrics(container, float64(stats.MemoryStats.Usage), float64(stats.MemoryStats.Limit), calculateCPUPercent(d.previousCPUValues[container.ID].totCPU, d.previousCPUValues[container.ID].systemCPU, stats))

		d.sendMetrics(ret)

		d.previousCPUValues[container.ID].totCPU = stats.CPUStats.CPUUsage.TotalUsage
		d.previousCPUValues[container.ID].systemCPU = stats.CPUStats.SystemCPUUsage

		break
	case <-time.After(time.Duration(d.statsTimeout) * time.Second):
		d.log.Error("Timed out collecting stats for container ", container.ID)
		done <- true
		break
	}
}

// buildMetrics creates the actual metrics for the given container.
func (d DockerStats) buildMetrics(container *docker.Container, memUsed, memLimit, cpuPercentage float64) []metric.Metric {
	ret := []metric.Metric{
		buildDockerMetric("DockerMemoryUsed", memUsed),
		buildDockerMetric("DockerMemoryLimit", memLimit),
		buildDockerMetric("DockerCpuPercentage", cpuPercentage),
	}
	additionalDimensions := map[string]string{
		"container_id":   container.ID,
		"container_name": strings.TrimPrefix(container.Name, "/"),
	}
	metric.AddToAll(&ret, additionalDimensions)
	metric.AddToAll(&ret, getServiceDimensions(container))

	return ret
}

// sendMetrics writes all the metrics received to the collector channel.
func (d DockerStats) sendMetrics(metrics []metric.Metric) {
	for _, m := range metrics {
		d.Channel() <- m
	}
}

// Function that extracts the service and instance name from mesos id in order to add them as dimensions
// in these metrics.
func getServiceDimensions(container *docker.Container) map[string]string {
	envVars := container.Config.Env

	tmp := make(map[string]string)
	for _, envVariable := range envVars {
		envArray := strings.Split(envVariable, "=")
		if envArray[0] == mesosTaskID {
			serviceName, instance := getInfoFromMesosTaskID(envArray[1])
			tmp["service_name"] = serviceName
			tmp["instance_name"] = instance
			break
		}
	}
	return tmp
}

func getInfoFromMesosTaskID(taskID string) (serviceName, instance string) {
	varArray := strings.Split(taskID, ".")
	return strings.Replace(varArray[0], "--", "_", -1), strings.Replace(varArray[1], "--", "_", -1)
}

func buildDockerMetric(name string, value float64) (m metric.Metric) {
	m = metric.New(name)
	m.Value = value
	m.AddDimension("collector", "DockerStats")
	return m
}

// Function that compute the current cpu usage percentage combining current and last values.
func calculateCPUPercent(previousCPU, previousSystem uint64, stats *docker.Stats) float64 {
	var (
		cpuPercent = 0.0
		// calculate the change for the cpu usage of the container in between readings
		cpuDelta = float64(stats.CPUStats.CPUUsage.TotalUsage - previousCPU)
		// calculate the change for the entire system between readings
		systemDelta = float64(stats.CPUStats.SystemCPUUsage - previousSystem)
	)

	if systemDelta > 0.0 && cpuDelta > 0.0 {
		cpuPercent = (cpuDelta / systemDelta) * float64(len(stats.CPUStats.CPUUsage.PercpuUsage)) * 100.0
	}
	return cpuPercent
}
<commit_msg>Fix socket closure bug<commit_after>package collector

import (
	"fullerite/config"
	"fullerite/metric"

	"strings"
	"time"

	l "github.com/Sirupsen/logrus"

	"github.com/fsouza/go-dockerclient"
)

const (
	mesosTaskID = "MESOS_TASK_ID"
	endpoint    = "unix:///var/run/docker.sock"
)

// DockerStats collector type.
// previousCPUValues contains the last cpu-usage values per container.
// dockerClient is the client for the Docker remote API.
type DockerStats struct {
	baseCollector
	previousCPUValues map[string]*CPUValues
	dockerClient      *docker.Client
	statsTimeout      int
}

// CPUValues struct contains the last cpu-usage values in order to compute properly the current values.
// (see calculateCPUPercent() for more details)
type CPUValues struct {
	totCPU, systemCPU uint64
}

// NewDockerStats creates a new DockerStats collector.
func NewDockerStats(channel chan metric.Metric, initialInterval int, log *l.Entry) *DockerStats {
	d := new(DockerStats)

	d.log = log
	d.channel = channel
	d.interval = initialInterval

	d.name = "DockerStats"
	d.previousCPUValues = make(map[string]*CPUValues)
	d.dockerClient, _ = docker.NewClient(endpoint)

	return d
}

// Configure takes a dictionary of values with which the handler can configure itself.
func (d *DockerStats) Configure(configMap map[string]interface{}) {
	d.configureCommonParams(configMap)
	if timeout, exists := configMap["dockerStatsTimeout"]; exists {
		d.statsTimeout = min(config.GetAsInt(timeout, d.interval), d.interval)
	} else {
		d.statsTimeout = d.interval
	}
}

// Collect iterates on all the docker containers alive and, if possible, collects the correspondent
// memory and cpu statistics.
// For each container a gorutine is started to spin up the collection process.
func (d *DockerStats) Collect() {
	if d.dockerClient == nil {
		d.log.Error("Invalid endpoint: ", docker.ErrInvalidEndpoint)
		return
	}
	containers, err := d.dockerClient.ListContainers(docker.ListContainersOptions{All: false})
	if err != nil {
		d.log.Error("ListContainers() failed: ", err)
		return
	}
	for _, apiContainer := range containers {
		container, err := d.dockerClient.InspectContainer(apiContainer.ID)
		if err != nil {
			d.log.Error("InspectContainer() failed: ", err)
			continue
		}
		if _, ok := d.previousCPUValues[container.ID]; !ok {
			d.previousCPUValues[container.ID] = new(CPUValues)
		}
		go d.getDockerContainerInfo(container)
	}
}

// getDockerContainerInfo gets container statistics for the given container.
// results is a channel to make possible the synchronization between the main process and the gorutines (wait-notify pattern).
func (d DockerStats) getDockerContainerInfo(container *docker.Container) {
	errC := make(chan error, 1)
	statsC := make(chan *docker.Stats, 1)
	done := make(chan bool)

	go func() {
		errC <- d.dockerClient.Stats(docker.StatsOptions{container.ID, statsC, false, done, time.Second * time.Duration(d.interval)})
	}()
	select {
	case stats, ok := <-statsC:
		if !ok {
			err := <-errC
			d.log.Error("Failed to collect docker container stats: ", err)
			break
		}
		done <- true

		ret := d.buildMetrics(container, float64(stats.MemoryStats.Usage), float64(stats.MemoryStats.Limit), calculateCPUPercent(d.previousCPUValues[container.ID].totCPU, d.previousCPUValues[container.ID].systemCPU, stats))

		d.sendMetrics(ret)

		d.previousCPUValues[container.ID].totCPU = stats.CPUStats.CPUUsage.TotalUsage
		d.previousCPUValues[container.ID].systemCPU = stats.CPUStats.SystemCPUUsage

		break
	case <-time.After(time.Duration(d.statsTimeout) * time.Second):
		d.log.Error("Timed out collecting stats for container ", container.ID)
		done <- true
		break
	}
}

// buildMetrics creates the actual metrics for the given container.
func (d DockerStats) buildMetrics(container *docker.Container, memUsed, memLimit, cpuPercentage float64) []metric.Metric {
	ret := []metric.Metric{
		buildDockerMetric("DockerMemoryUsed", memUsed),
		buildDockerMetric("DockerMemoryLimit", memLimit),
		buildDockerMetric("DockerCpuPercentage", cpuPercentage),
	}
	additionalDimensions := map[string]string{
		"container_id":   container.ID,
		"container_name": strings.TrimPrefix(container.Name, "/"),
	}
	metric.AddToAll(&ret, additionalDimensions)
	metric.AddToAll(&ret, getServiceDimensions(container))

	return ret
}

// sendMetrics writes all the metrics received to the collector channel.
func (d DockerStats) sendMetrics(metrics []metric.Metric) {
	for _, m := range metrics {
		d.Channel() <- m
	}
}

// Function that extracts the service and instance name from mesos id in order to add them as dimensions
// in these metrics.
func getServiceDimensions(container *docker.Container) map[string]string {
	envVars := container.Config.Env

	tmp := make(map[string]string)
	for _, envVariable := range envVars {
		envArray := strings.Split(envVariable, "=")
		if envArray[0] == mesosTaskID {
			serviceName, instance := getInfoFromMesosTaskID(envArray[1])
			tmp["service_name"] = serviceName
			tmp["instance_name"] = instance
			break
		}
	}
	return tmp
}

func getInfoFromMesosTaskID(taskID string) (serviceName, instance string) {
	varArray := strings.Split(taskID, ".")
	return strings.Replace(varArray[0], "--", "_", -1), strings.Replace(varArray[1], "--", "_", -1)
}

func buildDockerMetric(name string, value float64) (m metric.Metric) {
	m = metric.New(name)
	m.Value = value
	m.AddDimension("collector", "DockerStats")
	return m
}

// Function that compute the current cpu usage percentage combining current and last values.
func calculateCPUPercent(previousCPU, previousSystem uint64, stats *docker.Stats) float64 {
	var (
		cpuPercent = 0.0
		// calculate the change for the cpu usage of the container in between readings
		cpuDelta = float64(stats.CPUStats.CPUUsage.TotalUsage - previousCPU)
		// calculate the change for the entire system between readings
		systemDelta = float64(stats.CPUStats.SystemCPUUsage - previousSystem)
	)

	if systemDelta > 0.0 && cpuDelta > 0.0 {
		cpuPercent = (cpuDelta / systemDelta) * float64(len(stats.CPUStats.CPUUsage.PercpuUsage)) * 100.0
	}
	return cpuPercent
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
<|endoftext|>


<commit_before>package inputs

import "github.com/influxdata/telegraf"

// Deprecations lists the deprecated plugins
var Deprecations = map[string]telegraf.DeprecationInfo{
	"cassandra": {
		Since:  "1.7.0",
		Notice: "use 'inputs.jolokia2' with the 'cassandra.conf' example configuration instead",
	},
	"http_listener": {
		Since:  "1.9.0",
		Notice: "has been renamed to 'influxdb_listener', use 'inputs.influxdb_listener' or 'inputs.http_listener_v2' instead",
	},
	"httpjson": {
		Since:  "1.6.0",
		Notice: "use 'inputs.http' instead",
	},
	"io": {
		Since:     "0.10.0",
		RemovalIn: "2.0.0",
		Notice:    "use 'inputs.diskio' instead",
	},
	"jolokia": {
		Since:  "1.5.0",
		Notice: "use 'inputs.jolokia2' instead",
	},
	"kafka_consumer_legacy": {
		Since:  "1.4.0",
		Notice: "use 'inputs.kafka_consumer' instead, NOTE: 'kafka_consumer' only supports Kafka v0.8+",
	},
	"logparser": {
		Since:  "1.15.0",
		Notice: "use 'inputs.tail' with 'grok' data format instead",
	},
	"snmp_legacy": {
		Since:  "1.0.0",
		Notice: "use 'inputs.snmp' instead",
	},
	"tcp_listener": {
		Since:  "1.3.0",
		Notice: "use 'inputs.socket_listener' instead",
	},
	"udp_listener": {
		Since:  "1.3.0",
		Notice: "use 'inputs.socket_listener' instead",
	},
}
<commit_msg>style: Add deprecation notice to renamed plugins (#10867)<commit_after>package inputs

import "github.com/influxdata/telegraf"

// Deprecations lists the deprecated plugins
var Deprecations = map[string]telegraf.DeprecationInfo{
	"cassandra": {
		Since:  "1.7.0",
		Notice: "use 'inputs.jolokia2' with the 'cassandra.conf' example configuration instead",
	},
	"cisco_telemetry_gnmi": {
		Since:  "1.15.0",
		Notice: "has been renamed to 'gnmi'",
	},
	"http_listener": {
		Since:  "1.9.0",
		Notice: "has been renamed to 'influxdb_listener', use 'inputs.influxdb_listener' or 'inputs.http_listener_v2' instead",
	},
	"httpjson": {
		Since:  "1.6.0",
		Notice: "use 'inputs.http' instead",
	},
	"io": {
		Since:     "0.10.0",
		RemovalIn: "2.0.0",
		Notice:    "use 'inputs.diskio' instead",
	},
	"jolokia": {
		Since:  "1.5.0",
		Notice: "use 'inputs.jolokia2' instead",
	},
	"kafka_consumer_legacy": {
		Since:  "1.4.0",
		Notice: "use 'inputs.kafka_consumer' instead, NOTE: 'kafka_consumer' only supports Kafka v0.8+",
	},
	"KNXListener": {
		Since:  "1.20.1",
		Notice: "has been renamed to 'knx_listener'",
	},
	"logparser": {
		Since:  "1.15.0",
		Notice: "use 'inputs.tail' with 'grok' data format instead",
	},
	"snmp_legacy": {
		Since:  "1.0.0",
		Notice: "use 'inputs.snmp' instead",
	},
	"tcp_listener": {
		Since:  "1.3.0",
		Notice: "use 'inputs.socket_listener' instead",
	},
	"udp_listener": {
		Since:  "1.3.0",
		Notice: "use 'inputs.socket_listener' instead",
	},
}
<|endoftext|>