<commit_before>package model

import (
	"encoding/json"
	"fmt"
	"io"
	"strings"
)

type Metadata struct {
	APIVersion          string
	EndpointPrefix      string
	JSONVersion         string
	ServiceAbbreviation string
	ServiceFullName     string
	SignatureVersion    string
	TargetPrefix        string
	Protocol            string
}

type HTTPOptions struct {
	Method     string
	RequestURI string
}

type Operation struct {
	Name          string
	Documentation string
	HTTP          HTTPOptions
	InputRef      *ShapeRef `json:"Input"`
	OutputRef     *ShapeRef `json:"Output"`
}

func (o Operation) Input() *Shape {
	return o.InputRef.Shape()
}

func (o Operation) Output() *Shape {
	return o.OutputRef.Shape()
}

type Error struct {
	Code           string
	HTTPStatusCode int
	SenderFault    bool
}

type ShapeRef struct {
	ShapeName     string `json:"Shape"`
	Documentation string
	Wrapper       bool
	ResultWrapper string
}

func (ref *ShapeRef) Shape() *Shape {
	if ref == nil {
		return nil
	}
	return service.Shapes[ref.ShapeName]
}

type Member struct {
	Name     string
	Shape    *Shape
	Required bool
}

func (m Member) JSONTag() string {
	if !m.Required {
		return fmt.Sprintf("`json:\"%s,omitempty\"`", m.Name)
	}
	return fmt.Sprintf("`json:\"%s\"`", m.Name)
}

func (m Member) XMLTag(wrapper string) string {
	var path []string
	if wrapper != "" {
		path = append(path, wrapper)
	}

	path = append(path, m.Name)

	if m.Shape.ShapeType == "list" {
		// I'm assuming the plural ends with an S otherwise we're hosed
		path = append(path, m.Name[:len(m.Name)-1])
	}

	return fmt.Sprintf("`xml:\"%s\"`", strings.Join(path, ">"))
}

func (m Member) Type() string {
	return m.Shape.Type()
}

type Shape struct {
	Name          string
	ShapeType     string `json:"Type"`
	Required      []string
	MemberRefs    map[string]ShapeRef `json:"Members"`
	MemberRef     *ShapeRef           `json:"Member"`
	KeyRef        *ShapeRef           `json:"Key"`
	ValueRef      *ShapeRef           `json:"Value"`
	Error         Error
	Exception     bool
	Documentation string
	Min           int
	Max           int
	Pattern       string
	Sensitive     bool
	Wrapper       bool
}

func (s *Shape) Message() bool {
	return strings.HasSuffix(s.Name, "Message") && s.ResultWrapper() != ""
}

func (s *Shape) MessageTag() string {
	tag := strings.TrimSuffix(s.ResultWrapper(), "Result") + "Response"
	return fmt.Sprintf("`xml:\"%s\"`", tag)
}

func (s *Shape) Key() *Shape {
	return s.KeyRef.Shape()
}

func (s *Shape) Member() *Shape {
	return s.MemberRef.Shape()
}

func (s *Shape) Members() map[string]Member {
	required := func(v string) bool {
		for _, s := range s.Required {
			if s == v {
				return true
			}
		}
		return false
	}

	members := map[string]Member{}
	for name, ref := range s.MemberRefs {
		members[name] = Member{
			Name:     name,
			Shape:    ref.Shape(),
			Required: required(name),
		}
	}
	return members
}

func (s *Shape) ResultWrapper() string {
	for _, op := range service.Operations {
		if op.OutputRef != nil && op.OutputRef.ShapeName == s.Name {
			return op.OutputRef.ResultWrapper
		}
	}
	return ""
}

func (s *Shape) Value() *Shape {
	return s.ValueRef.Shape()
}

func (s *Shape) Type() string {
	switch s.ShapeType {
	case "structure":
		return exportable(s.Name)
	case "integer", "long":
		return "int"
	case "double":
		return "float64"
	case "string":
		return "string"
	case "map":
		return "map[" + s.Key().Type() + "]" + s.Value().Type()
	case "list":
		return "[]" + s.Member().Type()
	case "boolean":
		return "bool"
	case "blob":
		return "[]byte"
	case "timestamp":
		return "time.Time"
	}

	panic(fmt.Errorf("type %q (%q) not found", s.Name, s.ShapeType))
}

type Service struct {
	Name          string
	FullName      string
	PackageName   string
	Metadata      Metadata
	Documentation string
	Operations    map[string]Operation
	Shapes        map[string]*Shape
}

var service Service

func Load(name string, r io.Reader) error {
	service = Service{}
	if err := json.NewDecoder(r).Decode(&service); err != nil {
		return err
	}

	for name, shape := range service.Shapes {
		shape.Name = name
	}

	service.FullName = service.Metadata.ServiceFullName
	service.PackageName = strings.ToLower(name)
	service.Name = name

	return nil
}
<commit_msg>Fix wrapper paths.<commit_after>package model

import (
	"encoding/json"
	"fmt"
	"io"
	"strings"
)

type Metadata struct {
	APIVersion          string
	EndpointPrefix      string
	JSONVersion         string
	ServiceAbbreviation string
	ServiceFullName     string
	SignatureVersion    string
	TargetPrefix        string
	Protocol            string
}

type HTTPOptions struct {
	Method     string
	RequestURI string
}

type Operation struct {
	Name          string
	Documentation string
	HTTP          HTTPOptions
	InputRef      *ShapeRef `json:"Input"`
	OutputRef     *ShapeRef `json:"Output"`
}

func (o Operation) Input() *Shape {
	return o.InputRef.Shape()
}

func (o Operation) Output() *Shape {
	return o.OutputRef.Shape()
}

type Error struct {
	Code           string
	HTTPStatusCode int
	SenderFault    bool
}

type ShapeRef struct {
	ShapeName     string `json:"Shape"`
	Documentation string
	Wrapper       bool
	ResultWrapper string
}

func (ref *ShapeRef) Shape() *Shape {
	if ref == nil {
		return nil
	}
	return service.Shapes[ref.ShapeName]
}

type Member struct {
	Name     string
	Shape    *Shape
	Required bool
}

func (m Member) JSONTag() string {
	if !m.Required {
		return fmt.Sprintf("`json:\"%s,omitempty\"`", m.Name)
	}
	return fmt.Sprintf("`json:\"%s\"`", m.Name)
}

func (m Member) XMLTag(wrapper string) string {
	var path []string
	if wrapper != "" {
		path = append(path, wrapper)
	}

	path = append(path, m.Name)

	if m.Shape.ShapeType == "list" {
		path = append(path, m.Shape.Member().Name)
	}

	return fmt.Sprintf("`xml:\"%s\"`", strings.Join(path, ">"))
}

func (m Member) Type() string {
	return m.Shape.Type()
}

type Shape struct {
	Name          string
	ShapeType     string `json:"Type"`
	Required      []string
	MemberRefs    map[string]ShapeRef `json:"Members"`
	MemberRef     *ShapeRef           `json:"Member"`
	KeyRef        *ShapeRef           `json:"Key"`
	ValueRef      *ShapeRef           `json:"Value"`
	Error         Error
	Exception     bool
	Documentation string
	Min           int
	Max           int
	Pattern       string
	Sensitive     bool
	Wrapper       bool
}

func (s *Shape) Message() bool {
	return strings.HasSuffix(s.Name, "Message") && s.ResultWrapper() != ""
}

func (s *Shape) MessageTag() string {
	tag := strings.TrimSuffix(s.ResultWrapper(), "Result") + "Response"
	return fmt.Sprintf("`xml:\"%s\"`", tag)
}

func (s *Shape) Key() *Shape {
	return s.KeyRef.Shape()
}

func (s *Shape) Member() *Shape {
	return s.MemberRef.Shape()
}

func (s *Shape) Members() map[string]Member {
	required := func(v string) bool {
		for _, s := range s.Required {
			if s == v {
				return true
			}
		}
		return false
	}

	members := map[string]Member{}
	for name, ref := range s.MemberRefs {
		members[name] = Member{
			Name:     name,
			Shape:    ref.Shape(),
			Required: required(name),
		}
	}
	return members
}

func (s *Shape) ResultWrapper() string {
	for _, op := range service.Operations {
		if op.OutputRef != nil && op.OutputRef.ShapeName == s.Name {
			return op.OutputRef.ResultWrapper
		}
	}
	return ""
}

func (s *Shape) Value() *Shape {
	return s.ValueRef.Shape()
}

func (s *Shape) Type() string {
	switch s.ShapeType {
	case "structure":
		return exportable(s.Name)
	case "integer", "long":
		return "int"
	case "double":
		return "float64"
	case "string":
		return "string"
	case "map":
		return "map[" + s.Key().Type() + "]" + s.Value().Type()
	case "list":
		return "[]" + s.Member().Type()
	case "boolean":
		return "bool"
	case "blob":
		return "[]byte"
	case "timestamp":
		return "time.Time"
	}

	panic(fmt.Errorf("type %q (%q) not found", s.Name, s.ShapeType))
}

type Service struct {
	Name          string
	FullName      string
	PackageName   string
	Metadata      Metadata
	Documentation string
	Operations    map[string]Operation
	Shapes        map[string]*Shape
}

var service Service

func Load(name string, r io.Reader) error {
	service = Service{}
	if err := json.NewDecoder(r).Decode(&service); err != nil {
		return err
	}

	for name, shape := range service.Shapes {
		shape.Name = name
	}

	service.FullName = service.Metadata.ServiceFullName
	service.PackageName = strings.ToLower(name)
	service.Name = name

	return nil
}
<|endoftext|>


<commit_before>package s3

const TypeLineItem = "lineitem"
const IndexPrefixLineItem = "lineitems"

const MappingLineItem = `{
	"properties": {
		"lineItemId": {
			"type": "keyword"
		},
		"timeInterval": {
			"type": "keyword"
		},
		"invoiceId": {
			"type": "keyword"
		},
		"usageAccountId": {
			"type": "keyword"
		},
		"productCode": {
			"type": "keyword"
		},
		"usageType": {
			"type": "keyword"
		},
		"operation": {
			"type": "keyword"
		},
		"availabilityZone": {
			"type": "keyword"
		},
		"resourceId": {
			"type": "keyword"
		},
		"currencyCode": {
			"type": "keyword"
		},
		"unblendedCost": {
			"type": "float",
			"index": false
		},
		"usageStartDate": {
			"type": "date"
		},
		"usageEndDate": {
			"type": "date"
		}
	},
	"_all": {
		"enabled": false
	},
	"numeric_detection": false,
	"date_detection": false
}`
<commit_msg>aws/s3: put ElasticSearch mapping template at startup<commit_after>package s3

import (
	"context"
	"time"

	"github.com/trackit/jsonlog"

	"github.com/trackit/trackit2/es"
)

const TypeLineItem = "lineitem"
const IndexPrefixLineItem = "lineitems"
const TemplateNameLineItem = "lineitems"

// put the ElasticSearch index for *-lineitems indices at startup.
func init() {
	ctx, ctxCancel := context.WithTimeout(context.Background(), 10*time.Second)
	res, err := es.Client.IndexPutTemplate(TemplateNameLineItem).BodyString(TemplateLineItem).Do(ctx)
	if err != nil {
		jsonlog.DefaultLogger.Error("Failed to put ES index lineitems.", err)
	} else {
		jsonlog.DefaultLogger.Info("Put ES index lineitems.", res)
		ctxCancel()
	}
}

const TemplateLineItem = `
{
	"template": "*-lineitems",
	"version": 2,
	"mappings": {
		"lineitem": {
			"properties": {
				"lineItemId": {
					"type": "keyword",
					"norms": false
				},
				"timeInterval": {
					"type": "keyword",
					"norms": false
				},
				"invoiceId": {
					"type": "keyword",
					"norms": false
				},
				"usageAccountId": {
					"type": "keyword",
					"norms": false
				},
				"productCode": {
					"type": "keyword",
					"norms": false
				},
				"usageType": {
					"type": "keyword",
					"norms": false
				},
				"operation": {
					"type": "keyword",
					"norms": false
				},
				"availabilityZone": {
					"type": "keyword",
					"norms": false
				},
				"resourceId": {
					"type": "keyword",
					"norms": false
				},
				"currencyCode": {
					"type": "keyword",
					"norms": false
				},
				"unblendedCost": {
					"type": "float",
					"index": false
				},
				"usageStartDate": {
					"type": "date"
				},
				"usageEndDate": {
					"type": "date"
				}
			},
			"dynamic_templates": [
				{
					"tags": {
						"match_mapping_type": "string",
						"path_match": "tag.*",
						"mapping": {
							"type": "keyword"
						}
					}
				}
			],
			"_all": {
				"enabled": false
			},
			"numeric_detection": false,
			"date_detection": false
		}
	}
}
`
<|endoftext|>


<commit_before>package s3

import (
	"bufio"
	"bytes"
	"context"
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/signer/v4"
	"github.com/aws/aws-sdk-go/private/protocol/rest"
)

// dumbS3Manager implements custom request and signing code in order to
// circumvent a limitation of the AWS SDK described here:
//   https://stackoverflow.com/questions/48285381/how-to-use-getobject-when-key-has-leading-slashes
type dumbS3Manager struct {
	creds  *credentials.Credentials
	signer *v4.Signer
}

// readToWriter reads everything from a reader and writes it to a writer.
func readToWriter(reader io.Reader, writer io.Writer) error {
	var bufReader = bufio.NewReader(reader)
	var bufWriter = bufio.NewWriter(writer)
	_, err := bufWriter.ReadFrom(bufReader)
	return err
}

// init initializes the dumbS3Manager's signer from a set of credentials.
func (dm *dumbS3Manager) init(creds *credentials.Credentials) {
	dm.signer = v4.NewSigner(creds)
}

// rawS3GetObjectToBuffer reads an S3 object to a buffer.
func (dm dumbS3Manager) rawS3GetObjectToBuffer(
	ctx context.Context, client *http.Client, region, bucket, key string,
) ([]byte, error) {
	body, err := dm.rawS3GetObjectToReader(ctx, client, region, bucket, key)
	if err != nil {
		return nil, err
	}
	bufWrapper := bytes.NewBuffer(make([]byte, 0, 0x8000))
	err = readToWriter(body, bufWrapper)
	if err != nil {
		return nil, err
	}
	return bufWrapper.Bytes(), nil
}

// rawS3GetObjectToReader returns the reader for an S3 object.
func (dm dumbS3Manager) rawS3GetObjectToReader(ctx context.Context, client *http.Client, region, bucket, key string) (io.ReadCloser, error) {
	req, err := dm.rawS3GetObject(region, bucket, key)
	if err != nil {
		return nil, err
	}
	res, err := client.Do(req.WithContext(ctx))
	if err != nil {
		return nil, err
	}
	return res.Body, nil
}

// rawS3GetObject returns the signed requests which will request the given S3
// object.
func (dm dumbS3Manager) rawS3GetObject(region, bucket, key string) (*http.Request, error) {
	url := fmt.Sprintf(
		"https://%s.s3.%s.amazonaws.com/%s",
		bucket,
		region,
		rest.EscapePath(key, false),
	)
	request, err := http.NewRequest(
		http.MethodGet,
		url,
		nil,
	)
	if err != nil {
		return nil, err
	}
	_, err = dm.signer.Sign(request, nil, "s3", region, time.Now())
	if err != nil {
		return nil, err
	}
	return request, nil
}
<commit_msg>Changed S3 URL to accept bucket name with period.<commit_after>package s3

import (
	"bufio"
	"bytes"
	"context"
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/signer/v4"
	"github.com/aws/aws-sdk-go/private/protocol/rest"
)

// dumbS3Manager implements custom request and signing code in order to
// circumvent a limitation of the AWS SDK described here:
//   https://stackoverflow.com/questions/48285381/how-to-use-getobject-when-key-has-leading-slashes
type dumbS3Manager struct {
	creds  *credentials.Credentials
	signer *v4.Signer
}

// readToWriter reads everything from a reader and writes it to a writer.
func readToWriter(reader io.Reader, writer io.Writer) error {
	var bufReader = bufio.NewReader(reader)
	var bufWriter = bufio.NewWriter(writer)
	_, err := bufWriter.ReadFrom(bufReader)
	return err
}

// init initializes the dumbS3Manager's signer from a set of credentials.
func (dm *dumbS3Manager) init(creds *credentials.Credentials) {
	dm.signer = v4.NewSigner(creds)
}

// rawS3GetObjectToBuffer reads an S3 object to a buffer.
func (dm dumbS3Manager) rawS3GetObjectToBuffer(
	ctx context.Context, client *http.Client, region, bucket, key string,
) ([]byte, error) {
	body, err := dm.rawS3GetObjectToReader(ctx, client, region, bucket, key)
	if err != nil {
		return nil, err
	}
	bufWrapper := bytes.NewBuffer(make([]byte, 0, 0x8000))
	err = readToWriter(body, bufWrapper)
	if err != nil {
		return nil, err
	}
	return bufWrapper.Bytes(), nil
}

// rawS3GetObjectToReader returns the reader for an S3 object.
func (dm dumbS3Manager) rawS3GetObjectToReader(ctx context.Context, client *http.Client, region, bucket, key string) (io.ReadCloser, error) {
	req, err := dm.rawS3GetObject(region, bucket, key)
	if err != nil {
		return nil, err
	}
	res, err := client.Do(req.WithContext(ctx))
	if err != nil {
		return nil, err
	}
	return res.Body, nil
}

// rawS3GetObject returns the signed requests which will request the given S3
// object.
func (dm dumbS3Manager) rawS3GetObject(region, bucket, key string) (*http.Request, error) {
	url := fmt.Sprintf(
		"https://s3.%s.amazonaws.com/%s/%s",
		region,
		bucket,
		rest.EscapePath(key, false),
	)
	request, err := http.NewRequest(
		http.MethodGet,
		url,
		nil,
	)
	if err != nil {
		return nil, err
	}
	_, err = dm.signer.Sign(request, nil, "s3", region, time.Now())
	if err != nil {
		return nil, err
	}
	return request, nil
}
<|endoftext|>


<commit_before>package backend

import (
	"context"
	"errors"
	"fmt"

	"git.timschuster.info/rls.moe/catgi/backend/types"
)

// Backend Type Alias for easier importing
type Backend types.Backend
type KVBackend types.KVBackend
type ContentBackend types.ContentBackend

type driverCreator func(map[string]interface{}, context.Context) (types.Backend, error)

var backendDrivers = map[string]driverCreator{}

type noDriverError struct {
	drvName string
}

func (n noDriverError) Error() string {
	return fmt.Sprintf("Driver '%s' not installed", n.drvName)
}

func newNoDriverError(drv string) error {
	return noDriverError{drvName: drv}
}

func NewBackend(
	driver string, params map[string]interface{}, ctx context.Context) (types.Backend, error) {
	if f, ok := backendDrivers[driver]; ok {
		return f(params, ctx)
	}
	return nil, newNoDriverError(driver)
}

func InstalledDrivers() []string {
	var list = []string{}
	for v := range backendDrivers {
		list = append(list, v)
	}
	return list
}

func NewDriver(driver string, dfunc interface{}) error {
	switch v := dfunc.(type) {
	case func(map[string]interface{}, context.Context) (types.Backend, error):
		backendDrivers[driver] = v
		return nil
	default:
		return errors.New("Not a known driver type")
	}
}
<commit_msg>Cleaned code<commit_after>package backend

import (
	"context"
	"errors"
	"fmt"

	"git.timschuster.info/rls.moe/catgi/backend/types"
)

// Backend Type Alias for easier importing
type Backend types.Backend

type driverCreator func(map[string]interface{}, context.Context) (types.Backend, error)

var backendDrivers = map[string]driverCreator{}

type noDriverError struct {
	drvName string
}

func (n noDriverError) Error() string {
	return fmt.Sprintf("Driver '%s' not installed", n.drvName)
}

func newNoDriverError(drv string) error {
	return noDriverError{drvName: drv}
}

func NewBackend(
	driver string, params map[string]interface{}, ctx context.Context) (types.Backend, error) {
	if f, ok := backendDrivers[driver]; ok {
		return f(params, ctx)
	}
	return nil, newNoDriverError(driver)
}

func InstalledDrivers() []string {
	var list = []string{}
	for v := range backendDrivers {
		list = append(list, v)
	}
	return list
}

func NewDriver(driver string, dfunc interface{}) error {
	switch v := dfunc.(type) {
	case func(map[string]interface{}, context.Context) (types.Backend, error):
		backendDrivers[driver] = v
		return nil
	default:
		return errors.New("Not a known driver type")
	}
}
<|endoftext|>


<commit_before>package backend

import (
	"fmt"
	"math/rand"
)

type Random struct {
	Items []Item
}

func (r Random) Name() string {
	return "Backend-Random"
}

func (r *Random) Open() {
	r.Items = make([]Item, 0)

	seeds := []map[string]string{
		map[string]string{"type": "node", "group_id": "cpu/usage_rate", "units": "cpu", "issue": "42"},
		map[string]string{"type": "node", "group_id": "memory/usage_rate", "units": "byte"},
		map[string]string{"type": "node", "group_id": "cpu/usage_rate", "units": "cpu", "issue": "42"},
		map[string]string{"type": "node", "group_id": "memory/usage_rate", "units": "byte"},
		map[string]string{"type": "node", "group_id": "cpu/limit", "units": "cpu", "issue": "442"},
		map[string]string{"type": "node", "group_id": "memory/limit", "units": "byte", "issue": "442"},
		map[string]string{"type": "node", "group_id": "filesystem/usage_rate", "units": "byte"},
	}

	for i := 0; i < 120; i++ {
		seed := seeds[rand.Intn(len(seeds))]
		tags := map[string]string{
			"type":     seed["type"],
			"group_id": seed["group_id"],
			"units":    seed["units"],
			"issue":    seed["issue"],
			"hostname": fmt.Sprintf("example.%03d.com", i/4),
		}
		r.Items = append(r.Items, Item{
			Id:   fmt.Sprintf("hello_kitty_%3d", i),
			Type: "gauge",
			Tags: tags,
		})
	}
}

func (r Random) GetItemList(tags map[string]string) []Item {
	res := r.Items

	if len(tags) > 0 {
		for key, value := range tags {
			res = FilterItems(res, func(i Item) bool { return i.Tags[key] == value })
		}
	}

	return res
}

func (r Random) GetRawData(id string, end int64, start int64, limit int64, order string) []DataItem {
	res := make([]DataItem, 0)

	delta := int64(5 * 60 * 1000)

	for i := limit; i > 0; i-- {
		res = append(res, DataItem{
			Timestamp: end - i*delta,
			Value:     float64(50 + rand.Intn(50)),
		})
	}

	return res
}

func (r Random) GetStatData(id string, end int64, start int64, limit int64, order string, bucketDuration int64) []StatItem {
	res := make([]StatItem, 0)

	delta := int64(5 * 60 * 1000)

	for i := limit; i > 0; i-- {
		value := float64(50 + rand.Intn(50))
		res = append(res, StatItem{
			Start:   end - i*delta,
			End:     end - (i-1)*delta,
			Empty:   false,
			Samples: 1,
			Min:     value,
			Max:     value,
			Avg:     value,
			Median:  value,
			Sum:     value,
		})
	}

	return res
}

func (r Random) PostRawData(id string, t int64, v float64) bool {
	return false
}

func (r Random) PutTags(id string, tags map[string]string) bool {
	return false
}
<commit_msg>sort random answers<commit_after>package backend

import (
	"fmt"
	"math/rand"
)

type Random struct {
	Items []Item
}

func (r Random) Name() string {
	return "Backend-Random"
}

func (r *Random) Open() {
	r.Items = make([]Item, 0)

	seeds := []map[string]string{
		map[string]string{"type": "node", "group_id": "cpu/usage_rate", "units": "cpu", "issue": "42"},
		map[string]string{"type": "node", "group_id": "memory/usage_rate", "units": "byte"},
		map[string]string{"type": "node", "group_id": "cpu/usage_rate", "units": "cpu", "issue": "42"},
		map[string]string{"type": "node", "group_id": "memory/usage_rate", "units": "byte"},
		map[string]string{"type": "node", "group_id": "cpu/limit", "units": "cpu", "issue": "442"},
		map[string]string{"type": "node", "group_id": "memory/limit", "units": "byte", "issue": "442"},
		map[string]string{"type": "node", "group_id": "filesystem/usage_rate", "units": "byte"},
	}

	for i := 0; i < 120; i++ {
		seed := seeds[rand.Intn(len(seeds))]
		tags := map[string]string{
			"type":     seed["type"],
			"group_id": seed["group_id"],
			"units":    seed["units"],
			"issue":    seed["issue"],
			"hostname": fmt.Sprintf("example.%03d.com", i/4),
		}
		r.Items = append(r.Items, Item{
			Id:   fmt.Sprintf("hello_kitty_%3d", i),
			Type: "gauge",
			Tags: tags,
		})
	}
}

func (r Random) GetItemList(tags map[string]string) []Item {
	res := r.Items

	if len(tags) > 0 {
		for key, value := range tags {
			res = FilterItems(res, func(i Item) bool { return i.Tags[key] == value })
		}
	}

	return res
}

func (r Random) GetRawData(id string, end int64, start int64, limit int64, order string) []DataItem {
	res := make([]DataItem, 0)

	delta := int64(5 * 60 * 1000)

	for i := limit; i > 0; i-- {
		res = append(res, DataItem{
			Timestamp: end - i*delta,
			Value:     float64(50 + rand.Intn(50)),
		})
	}

	if order == "DESC" {
		for i, j := 0, len(res)-1; i < j; i, j = i+1, j-1 {
			res[i], res[j] = res[j], res[i]
		}
	}

	return res
}

func (r Random) GetStatData(id string, end int64, start int64, limit int64, order string, bucketDuration int64) []StatItem {
	res := make([]StatItem, 0)

	delta := int64(5 * 60 * 1000)

	for i := limit; i > 0; i-- {
		value := float64(50 + rand.Intn(50))
		res = append(res, StatItem{
			Start:   end - i*delta,
			End:     end - (i-1)*delta,
			Empty:   false,
			Samples: 1,
			Min:     value,
			Max:     value,
			Avg:     value,
			Median:  value,
			Sum:     value,
		})
	}

	if order == "DESC" {
		for i, j := 0, len(res)-1; i < j; i, j = i+1, j-1 {
			res[i], res[j] = res[j], res[i]
		}
	}

	return res
}

func (r Random) PostRawData(id string, t int64, v float64) bool {
	return false
}

func (r Random) PutTags(id string, tags map[string]string) bool {
	return false
}
<|endoftext|>


<commit_before>package backupservice

import (
	"log"
	"os"

	"fmt"

	"path/filepath"

	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/mleonard87/frosty/config"
)

const (
	BUCKET_NAME                            string = "frosty.backups"
	ERROR_CODE_INVALID_BUCKET_NAME         string = "InvalidBucketName"
	ERROR_CODE_BUCKET_ALREADY_OWNED_BY_YOU string = "BucketAlreadyOwnedByYou"
)

type AmazonS3BackupService struct {
	AccessKeyId     string
	SecretAccessKey string
	Region          string
	AccountId       string
	BucketName      string
	S3Service       *s3.S3
}

// Return the backup service type this must match the string as used as the JSON property in the frosty backup config.
func (agss *AmazonS3BackupService) Name() string {
	return config.BACKUP_SERVICE_AMAZON_S3
}

// Initialise any variable needed for backups.
func (asbs *AmazonS3BackupService) SetConfig(backupConfig *config.BackupConfig) {
	asbs.AccessKeyId = backupConfig.BackupConfig["accessKeyId"].(string)
	asbs.SecretAccessKey = backupConfig.BackupConfig["secretAccessKey"].(string)
	asbs.Region = backupConfig.BackupConfig["region"].(string)
	asbs.AccountId = backupConfig.BackupConfig["accountId"].(string)
	asbs.BucketName = BUCKET_NAME
}

// Initialise anything in the backup service that needs to be created prior to uploading files. In this instance we need
// to create a bucket to store the backups if one does not already exist. This always uses a bucket
// called "frosty.backups".
func (asbs *AmazonS3BackupService) Init() error {
	asbs.setEnvvars()
	asbs.S3Service = s3.New(session.New(), &aws.Config{})

	err := asbs.createBucket(asbs.BucketName)
	if err != nil {
		fmt.Println("error creating bucket")
		fmt.Println(err)
		return err
	}

	return nil
}

// Store the file in pathToFile in the bucket in S3.
func (asbs *AmazonS3BackupService) StoreFile(pathToFile string) error {
	_, fileName := filepath.Split(pathToFile)

	key := getObjectKey(fileName)

	f, err := os.Open(pathToFile)
	if err != nil {
		log.Printf("Failed to open file to store: %s", pathToFile)
		log.Println(err)
		return err
	}

	params := &s3.PutObjectInput{
		Body:   f,
		Bucket: &asbs.BucketName,
		Key:    &key,
	}

	_, err = asbs.S3Service.PutObject(params)
	if err != nil {
		log.Printf("Failed to put object %s into bucket %s with a key of %s\n", pathToFile, asbs.BucketName, fileName)
		log.Println(err)
		return err
	}

	return nil
}

// Get the name to be used for the .zip archive without the .zip extension.
func (asbs *AmazonS3BackupService) ArtifactFilename(jobName string) string {
	return jobName
}

// Get a friendly name for the email template of where this backup was stored. In this case, the name of the S3 bucket.
func (asbs *AmazonS3BackupService) BackupLocation() string {
	return fmt.Sprintf("S3 Bucket: %s", asbs.BucketName)
}

// Create the S3 bucket.
func (asbs *AmazonS3BackupService) createBucket(bucketName string) error {
	asbs.setEnvvars()
	params := &s3.CreateBucketInput{
		Bucket: aws.String(bucketName),
	}

	_, err := asbs.S3Service.CreateBucket(params)
	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			if aerr.Code() == ERROR_CODE_INVALID_BUCKET_NAME {
				log.Printf("The specified bucket is not valid. Bucket name: %s\n", bucketName)
				log.Println(err)
				return err
			}
			// If the BucketAlreadyOwnedByYou error is raised then this bucket already exists.
			if aerr.Code() == ERROR_CODE_BUCKET_ALREADY_OWNED_BY_YOU {
				return nil
			}

		}
		return err
	}

	if err = asbs.S3Service.WaitUntilBucketExists(&s3.HeadBucketInput{Bucket: &bucketName}); err != nil {
		log.Printf("Failed to wait for bucket to exist %s, %s\n", bucketName, err)
		return err
	}

	return nil
}

// Set the required AWS environment variables.
func (asbs *AmazonS3BackupService) setEnvvars() {
	os.Setenv(ENVVAR_AWS_ACCESS_KEY_ID, asbs.AccessKeyId)
	os.Setenv(ENVVAR_AWS_SECRET_ACCESS_KEY, asbs.SecretAccessKey)
	os.Setenv(ENVVAR_AWS_REGION, asbs.Region)
}

// Get the name to use for the file being stored in S3.
func getObjectKey(fileName string) string {
	hostname, err := os.Hostname()
	if err != nil {
		log.Fatal("Could not determine hostname.", err)
		return ""
	}

	return fmt.Sprintf("%s_%s_%s", hostname, time.Now().Format("20060102T15:04:05"), fileName)
}
<commit_msg>Organise the objects into folders in the S3 bucket.<commit_after>package backupservice

import (
	"log"
	"os"

	"fmt"

	"path/filepath"

	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/mleonard87/frosty/config"
)

const (
	BUCKET_NAME                            string = "frosty.backups"
	ERROR_CODE_INVALID_BUCKET_NAME         string = "InvalidBucketName"
	ERROR_CODE_BUCKET_ALREADY_OWNED_BY_YOU string = "BucketAlreadyOwnedByYou"
)

type AmazonS3BackupService struct {
	AccessKeyId     string
	SecretAccessKey string
	Region          string
	AccountId       string
	BucketName      string
	S3Service       *s3.S3
}

// Return the backup service type this must match the string as used as the JSON property in the frosty backup config.
func (agss *AmazonS3BackupService) Name() string {
	return config.BACKUP_SERVICE_AMAZON_S3
}

// Initialise any variable needed for backups.
func (asbs *AmazonS3BackupService) SetConfig(backupConfig *config.BackupConfig) {
	asbs.AccessKeyId = backupConfig.BackupConfig["accessKeyId"].(string)
	asbs.SecretAccessKey = backupConfig.BackupConfig["secretAccessKey"].(string)
	asbs.Region = backupConfig.BackupConfig["region"].(string)
	asbs.AccountId = backupConfig.BackupConfig["accountId"].(string)
	asbs.BucketName = BUCKET_NAME
}

// Initialise anything in the backup service that needs to be created prior to uploading files. In this instance we need
// to create a bucket to store the backups if one does not already exist. This always uses a bucket
// called "frosty.backups".
func (asbs *AmazonS3BackupService) Init() error {
	asbs.setEnvvars()
	asbs.S3Service = s3.New(session.New(), &aws.Config{})

	err := asbs.createBucket(asbs.BucketName)
	if err != nil {
		fmt.Println("error creating bucket")
		fmt.Println(err)
		return err
	}

	return nil
}

// Store the file in pathToFile in the bucket in S3.
func (asbs *AmazonS3BackupService) StoreFile(pathToFile string) error {
	_, fileName := filepath.Split(pathToFile)

	key := getObjectKey(fileName)

	f, err := os.Open(pathToFile)
	if err != nil {
		log.Printf("Failed to open file to store: %s", pathToFile)
		log.Println(err)
		return err
	}

	params := &s3.PutObjectInput{
		Body:   f,
		Bucket: &asbs.BucketName,
		Key:    &key,
	}

	_, err = asbs.S3Service.PutObject(params)
	if err != nil {
		log.Printf("Failed to put object %s into bucket %s with a key of %s\n", pathToFile, asbs.BucketName, fileName)
		log.Println(err)
		return err
	}

	return nil
}

// Get the name to be used for the .zip archive without the .zip extension.
func (asbs *AmazonS3BackupService) ArtifactFilename(jobName string) string {
	return jobName
}

// Get a friendly name for the email template of where this backup was stored. In this case, the name of the S3 bucket.
func (asbs *AmazonS3BackupService) BackupLocation() string {
	return fmt.Sprintf("S3 Bucket: %s", asbs.BucketName)
}

// Create the S3 bucket.
func (asbs *AmazonS3BackupService) createBucket(bucketName string) error {
	asbs.setEnvvars()
	params := &s3.CreateBucketInput{
		Bucket: aws.String(bucketName),
	}

	_, err := asbs.S3Service.CreateBucket(params)
	if err != nil {
		if aerr, ok := err.(awserr.Error); ok {
			if aerr.Code() == ERROR_CODE_INVALID_BUCKET_NAME {
				log.Printf("The specified bucket is not valid. Bucket name: %s\n", bucketName)
				log.Println(err)
				return err
			}
			// If the BucketAlreadyOwnedByYou error is raised then this bucket already exists.
			if aerr.Code() == ERROR_CODE_BUCKET_ALREADY_OWNED_BY_YOU {
				return nil
			}

		}
		return err
	}

	if err = asbs.S3Service.WaitUntilBucketExists(&s3.HeadBucketInput{Bucket: &bucketName}); err != nil {
		log.Printf("Failed to wait for bucket to exist %s, %s\n", bucketName, err)
		return err
	}

	return nil
}

// Set the required AWS environment variables.
func (asbs *AmazonS3BackupService) setEnvvars() {
	os.Setenv(ENVVAR_AWS_ACCESS_KEY_ID, asbs.AccessKeyId)
	os.Setenv(ENVVAR_AWS_SECRET_ACCESS_KEY, asbs.SecretAccessKey)
	os.Setenv(ENVVAR_AWS_REGION, asbs.Region)
}

// Get the name to use for the file being stored in S3.
func getObjectKey(fileName string) string {
	hostname, err := os.Hostname()
	if err != nil {
		log.Fatal("Could not determine hostname.", err)
		return ""
	}

	return fmt.Sprintf("%s/%s/%s_%s", hostname, time.Now().Format("20060102"), time.Now().Format("15:04:05"), fileName)
}
<|endoftext|>


<commit_before>package bitbucket

import (
	"fmt"
	"net/url"
)

// Use the ssh-keys resource to manipulate the ssh-keys associated
// with a repository
//
// https://confluence.atlassian.com/display/BITBUCKET/deploy-keys+Resource
type RepoKeyResource struct {
	client *Client
}

// Gets a list of the keys associated with a repository.
func (r *RepoKeyResource) List(owner, slug string) ([]*Key, error) {
	keys := []*Key{}
	path := fmt.Sprintf("/repositories/%s/%s/deploy-keys", owner, slug)

	if err := r.client.do("GET", path, nil, nil, &keys); err != nil {
		return nil, err
	}

	return keys, nil
}

// Gets the content of the specified key_id.
// This call requires authentication.
func (r *RepoKeyResource) Find(owner, slug string, id int) (*Key, error) {
	key := Key{}
	path := fmt.Sprintf("/repositories/%s/%s/deploy-keys/%v", owner, slug, id)
	if err := r.client.do("GET", path, nil, nil, &key); err != nil {
		return nil, err
	}

	return &key, nil
}

// Gets the content of the specified key with the
// given label.
func (r *RepoKeyResource) FindName(owner, slug, label string) (*Key, error) {
	keys, err := r.List(owner, slug)
	if err != nil {
		return nil, err
	}

	for _, key := range keys {
		if key.Label == label {
			return key, nil
		}
	}

	return nil, ErrNotFound
}

// Creates a key on the specified repo. You must supply a valid key
// that is unique across the Bitbucket service.
func (r *RepoKeyResource) Create(owner, slug, key, label string) (*Key, error) {

	values := url.Values{}
	values.Add("key", key)
	values.Add("label", label)

	k := Key{}
	path := fmt.Sprintf("/repositories/%s/%s/deploy-keys", owner, slug)
	if err := r.client.do("POST", path, nil, values, &k); err != nil {
		return nil, err
	}

	return &k, nil
}

// Creates a key on the specified account. You must supply a valid key
// that is unique across the Bitbucket service.
func (r *RepoKeyResource) Update(owner, slug, key, label string, id int) (*Key, error) {

	values := url.Values{}
	values.Add("key", key)
	values.Add("label", label)

	k := Key{}
	path := fmt.Sprintf("/repositories/%s/%s/deploy-keys/%v", owner, slug, id)
	if err := r.client.do("PUT", path, nil, values, &k); err != nil {
		return nil, err
	}

	return &k, nil
}

func (r *RepoKeyResource) CreateUpdate(owner, slug, key, label string) (*Key, error) {
	if found, err := r.FindName(owner, slug, label); err == nil {
		// if the public keys are different we should update
		if found.Key != key {
			return r.Update(owner, slug, key, label, found.Id)
		}

		// otherwise we should just return the key, since there
		// is nothing to update
		return found, nil
	}

	return r.Create(owner, slug, key, label)
}

// Deletes the key specified by the key_id value.
// This call requires authentication
func (r *RepoKeyResource) Delete(owner, slug string, id int) error {
	path := fmt.Sprintf("/repositories/%s/%s/deploy-keys/%v", owner, slug, id)
	return r.client.do("DELETE", path, nil, nil, nil)
}

// Deletes the named key.
// This call requires authentication
func (r *RepoKeyResource) DeleteName(owner, slug, label string) error {
	key, err := r.FindName(owner, slug, label)
	if err != nil {
		return err
	}

	return r.Delete(owner, slug, key.Id)
}
<commit_msg>Fix updating of deploy-keys<commit_after>package bitbucket

import (
	"fmt"
	"net/url"
)

// Use the ssh-keys resource to manipulate the ssh-keys associated
// with a repository
//
// https://confluence.atlassian.com/display/BITBUCKET/deploy-keys+Resource
type RepoKeyResource struct {
	client *Client
}

// Gets a list of the keys associated with a repository.
func (r *RepoKeyResource) List(owner, slug string) ([]*Key, error) {
	keys := []*Key{}
	path := fmt.Sprintf("/repositories/%s/%s/deploy-keys", owner, slug)

	if err := r.client.do("GET", path, nil, nil, &keys); err != nil {
		return nil, err
	}

	return keys, nil
}

// Gets the content of the specified key_id.
// This call requires authentication.
func (r *RepoKeyResource) Find(owner, slug string, id int) (*Key, error) {
	key := Key{}
	path := fmt.Sprintf("/repositories/%s/%s/deploy-keys/%v", owner, slug, id)
	if err := r.client.do("GET", path, nil, nil, &key); err != nil {
		return nil, err
	}

	return &key, nil
}

// Gets the content of the specified key with the
// given label.
func (r *RepoKeyResource) FindName(owner, slug, label string) (*Key, error) {
	keys, err := r.List(owner, slug)
	if err != nil {
		return nil, err
	}

	for _, key := range keys {
		if key.Label == label {
			return key, nil
		}
	}

	return nil, ErrNotFound
}

// Creates a key on the specified repo. You must supply a valid key
// that is unique across the Bitbucket service.
func (r *RepoKeyResource) Create(owner, slug, key, label string) (*Key, error) {

	values := url.Values{}
	values.Add("key", key)
	values.Add("label", label)

	k := Key{}
	path := fmt.Sprintf("/repositories/%s/%s/deploy-keys", owner, slug)
	if err := r.client.do("POST", path, nil, values, &k); err != nil {
		return nil, err
	}

	return &k, nil
}

// Creates a key on the specified account. You must supply a valid key
// that is unique across the Bitbucket service.
func (r *RepoKeyResource) Update(owner, slug, key, label string, id int) (*Key, error) {
	// There is actually no API to update an existing key
	r.Delete(owner, slug, id)
	return r.Create(owner, slug, key, label)
}

func (r *RepoKeyResource) CreateUpdate(owner, slug, key, label string) (*Key, error) {
	if found, err := r.FindName(owner, slug, label); err == nil {
		// if the public keys are different we should update
		if found.Key != key {
			return r.Update(owner, slug, key, label, found.Id)
		}

		// otherwise we should just return the key, since there
		// is nothing to update
		return found, nil
	}

	return r.Create(owner, slug, key, label)
}

// Deletes the key specified by the key_id value.
// This call requires authentication
func (r *RepoKeyResource) Delete(owner, slug string, id int) error {
	path := fmt.Sprintf("/repositories/%s/%s/deploy-keys/%v", owner, slug, id)
	return r.client.do("DELETE", path, nil, nil, nil)
}

// Deletes the named key.
// This call requires authentication
func (r *RepoKeyResource) DeleteName(owner, slug, label string) error {
	key, err := r.FindName(owner, slug, label)
	if err != nil {
		return err
	}

	return r.Delete(owner, slug, key.Id)
}
<|endoftext|>


<commit_before>// Copyright 2013 Alexandre Fiori
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Diameter message, header with multiple AVPs.  Part of go-diameter.

package base

import (
	"encoding/binary"
	"fmt"
	"io"

	"github.com/fiorix/go-diameter/dict"
)

// ReadHeader reads one diameter header from the connection and return it.
func ReadHeader(r io.Reader) (*Header, error) {
	var hdr Header
	if err := binary.Read(r, binary.BigEndian, &hdr); err != nil {
		return nil, err
	}
	// Only supports diameter version 1.
	if hdr.Version != byte(1) {
		return nil, fmt.Errorf(
			"Unsupported diameter version %d", hdr.Version)
	}
	return &hdr, nil
}

// ReadMessage reads an entire diameter message from the connection with
// Header and AVPs and return it.
func ReadMessage(r io.Reader, d *dict.Parser) (*Message, error) {
	var (
		err   error
		avp   *AVP
		extra uint32
	)
	m := &Message{Dict: d}
	if m.Header, err = ReadHeader(r); err != nil {
		return nil, err
	}
	// n is how many bytes are left in this message.
	n := int32(m.Header.MessageLength() - hdrSize)
	// Read all AVPs in this message.
	for n != 0 {
		if extra, avp, err = ReadAVP(r, m); err != nil {
			return nil, err
		} else {
			n = n - int32(avp.Length+extra)
			if n < 0 {
				return nil, fmt.Errorf(
					"Malformed AVP: %s", avp.String())
			}
		}
		m.AVP = append(m.AVP, avp)
	}
	return m, nil
}
<commit_msg>Improvements<commit_after>// Copyright 2013 Alexandre Fiori
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Diameter message, header with multiple AVPs.  Part of go-diameter.

package base

import (
	"encoding/binary"
	"fmt"
	"io"

	"github.com/fiorix/go-diameter/dict"
)

// ReadMessage reads an entire diameter message from the connection with
// Header and AVPs and return it.
func ReadMessage(r io.Reader, d *dict.Parser) (*Message, error) {
	var (
		err   error
		avp   *AVP
		extra uint32
	)
	m := &Message{Dict: d}
	if m.Header, err = readHeader(r); err != nil {
		return nil, err
	}
	// n is how many bytes are left in this message.
	n := int32(m.Header.MessageLength() - hdrSize)
	// Read all AVPs in this message.
	for n != 0 {
		if extra, avp, err = ReadAVP(r, m); err != nil {
			return nil, err
		} else {
			n = n - int32(avp.Length+extra)
			if n < 0 {
				return nil, fmt.Errorf(
					"Malformed AVP: %s", avp.String())
			}
		}
		m.AVP = append(m.AVP, avp)
	}
	return m, nil
}

// readHeader reads one diameter header from the connection and return it.
func readHeader(r io.Reader) (*Header, error) {
	var hdr Header
	if err := binary.Read(r, binary.BigEndian, &hdr); err != nil {
		return nil, err
	}
	// Only supports diameter version 1.
	if hdr.Version != byte(1) {
		return nil, fmt.Errorf(
			"Unsupported diameter version %d", hdr.Version)
	}
	return &hdr, nil
}
<|endoftext|>


<commit_before>package gsnake

import (
	"github.com/golang/glog"
	"io"
	"os"
)

type TextFileReader interface {
	LoadFile(filepath string, fp *os.File) error
	ReadLine() ([]byte, error)
}

type TextFileTailReader struct {
	path   string
	offset int
	fp     *os.File
	r      TextFileReader
	dr     *DirReader
}

func NewTextFileTailReader(dr *DirReader) *TextFileTailReader {
	r := &TextFileTailReader{
		path:   "",
		offset: 0,
		fp:     nil,
		dr:     dr,
	}

	if *reader_type == "PTailReader" {
		r.r = NewPTailFileReader()
	} else if *reader_type == "GzipReader" {
		r.r = NewGzipFileReader()
	} else {
		glog.Fatal("Error reader_type %v", *reader_type)
	}

	return r
}

func (r *TextFileTailReader) ReadFile(file string, offset int) (err error) {
	if r.fp != nil {
		r.fp.Close()
		r.fp = nil
	}

	r.path = file
	r.fp, err = os.OpenFile(file, os.O_RDONLY, 0644)
	if err != nil {
		glog.Errorf("OpenFile <%s> failed : %v\n", file, err.Error())
		return err
	}
	glog.Infof("OpenFile %v OK", file)

	if offset > 0 {
		r.fp.Seek(int64(offset), os.SEEK_SET)
	}

	r.r.LoadFile(file, r.fp)

	r.readTextFile()

	return nil
}

func (r *TextFileTailReader) readTextFile() {
	var lastLine []byte
	for {
		line, err := r.r.ReadLine()
		//glog.Infof("ReadLine: lastLine=<%s> current-read=<%s> <%v>", string(lastLine), string(line), err)
		if len(lastLine) > 0 {
			line = append(lastLine, line...)
		}

		if err == io.EOF {
			if len(line) > 0 {
				lastLine = line
			}

			// there are still files which are ready to be processed
			if r.dr.GetPendingFileCount() > 0 {
				if len(line) > 0 {
					// The last line of the file
					dispatcher.textModule.OnRecord(line)
				}
				break
			}

			// no more files. we wait this file to be updated or wait new file created
			glog.Infof("no more files, we wait this file <%v> to be updated. Waiting ...", r.path)
			r.dr.Wait()
			continue
		} else if err != nil {
			glog.Errorf("Read data from <%s> failed : %v", r.path, err.Error())
			break
		} else {
			lastLine = []byte{}
		}

		dispatcher.textModule.OnRecord(line)
	}
}
<commit_msg>Fix fd leak bug<commit_after>package gsnake

import (
	"github.com/golang/glog"
	"io"
	"os"
)

type TextFileReader interface {
	LoadFile(filepath string, fp *os.File) error
	ReadLine() ([]byte, error)
}

type TextFileTailReader struct {
	path   string
	offset int
	fp     *os.File
	r      TextFileReader
	dr     *DirReader
}

func NewTextFileTailReader(dr *DirReader) *TextFileTailReader {
	r := &TextFileTailReader{
		path:   "",
		offset: 0,
		fp:     nil,
		dr:     dr,
	}

	if *reader_type == "PTailReader" {
		r.r = NewPTailFileReader()
	} else if *reader_type == "GzipReader" {
		r.r = NewGzipFileReader()
	} else {
		glog.Fatal("Error reader_type %v", *reader_type)
	}

	return r
}

func (r *TextFileTailReader) ReadFile(file string, offset int) (err error) {
	if r.fp != nil {
		r.fp.Close()
		r.fp = nil
	}

	r.path = file
	r.fp, err = os.OpenFile(file, os.O_RDONLY, 0644)
	if err != nil {
		glog.Errorf("OpenFile <%s> failed : %v\n", file, err.Error())
		return err
	}
	glog.Infof("OpenFile %v OK", file)
	defer r.fp.Close()

	if offset > 0 {
		r.fp.Seek(int64(offset), os.SEEK_SET)
	}

	r.r.LoadFile(file, r.fp)

	r.readTextFile()

	return nil
}

func (r *TextFileTailReader) readTextFile() {
	var lastLine []byte
	for {
		line, err := r.r.ReadLine()
		//glog.Infof("ReadLine: lastLine=<%s> current-read=<%s> <%v>", string(lastLine), string(line), err)
		if len(lastLine) > 0 {
			line = append(lastLine, line...)
		}

		if err == io.EOF {
			if len(line) > 0 {
				lastLine = line
			}

			// there are still files which are ready to be processed
			if r.dr.GetPendingFileCount() > 0 {
				if len(line) > 0 {
					// The last line of the file
					dispatcher.textModule.OnRecord(line)
				}
				break
			}

			// no more files. we wait this file to be updated or wait new file created
			glog.Infof("no more files, we wait this file <%v> to be updated. Waiting ...", r.path)
			r.dr.Wait()
			continue
		} else if err != nil {
			glog.Errorf("Read data from <%s> failed : %v", r.path, err.Error())
			break
		} else {
			lastLine = []byte{}
		}

		dispatcher.textModule.OnRecord(line)
	}
}
<|endoftext|>


<commit_before>package filters

import (
	"fmt"
	"log"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	aw "github.com/deanishe/awgo"
	"github.com/rkoval/alfred-aws-console-services-workflow/core"
)

func GetInstanceStateEmoji(instanceState string) string {
	if instanceState == ec2.InstanceStateNamePending {
		return "⚪"
	} else if instanceState == ec2.InstanceStateNameRunning {
		return "🟢"
	} else if instanceState == ec2.InstanceStateNameShuttingDown || instanceState == ec2.InstanceStateNameStopping {
		return "🟡"
	} else if instanceState == ec2.InstanceStateNameTerminated || instanceState == ec2.InstanceStateNameStopped {
		return "🔴"
	}
	return "❔"
}

func SearchEC2Instances(wf *aw.Workflow, query string) error {
	sess, cfg := core.LoadAWSConfig()
	svc := ec2.New(sess, cfg)

	values := []*string{
		aws.String(strings.Join([]string{"*", query, "*"}, "")),
	}

	var name string
	if strings.HasPrefix(query, "i-") {
		// assume we're querying by instance ID here
		name = "instance-id"
	} else {
		name = "tag:Name"
	}
	params := &ec2.DescribeInstancesInput{
		Filters: []*ec2.Filter{
			{
				Name:   aws.String(name),
				Values: values,
			},
		},
	}

	resp, err := svc.DescribeInstances(params)
	if err != nil {
		wf.NewItem(err.Error()).
			Icon(aw.IconError)
		return err
	}
	log.Printf("%+v\n", *resp)

	for _, reservation := range resp.Reservations {
		for _, instance := range reservation.Instances {
			var title string
			subtitle := GetInstanceStateEmoji(*instance.State.Name)
			name := GetTagValue(instance.Tags, "Name")
			if name != "" {
				title = name
				subtitle += " " + *instance.InstanceId
			} else {
				title = *instance.InstanceId
			}
			wf.NewItem(title).
				Subtitle(subtitle).
				Arg(fmt.Sprintf("https://%s.console.aws.amazon.com/ec2/v2/home?region=%s#Instances:search=%s", *cfg.Region, *cfg.Region, *instance.InstanceId)).
				Icon(core.GetImageIcon("ec2")).
				Valid(true)
		}
	}

	return nil
}

func GetTagValue(tags []*ec2.Tag, key string) string {
	for _, tag := range tags {
		if *tag.Key == key {
			return *tag.Value
		}
	}
	return ""
}
<commit_msg>added instance type to ec2<commit_after>package filters

import (
	"fmt"
	"log"
	"strings"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ec2"
	aw "github.com/deanishe/awgo"
	"github.com/rkoval/alfred-aws-console-services-workflow/core"
)

func GetInstanceStateEmoji(instanceState string) string {
	if instanceState == ec2.InstanceStateNamePending {
		return "⚪"
	} else if instanceState == ec2.InstanceStateNameRunning {
		return "🟢"
	} else if instanceState == ec2.InstanceStateNameShuttingDown || instanceState == ec2.InstanceStateNameStopping {
		return "🟡"
	} else if instanceState == ec2.InstanceStateNameTerminated || instanceState == ec2.InstanceStateNameStopped {
		return "🔴"
	}
	return "❔"
}

func SearchEC2Instances(wf *aw.Workflow, query string) error {
	sess, cfg := core.LoadAWSConfig()
	svc := ec2.New(sess, cfg)

	values := []*string{
		aws.String(strings.Join([]string{"*", query, "*"}, "")),
	}

	var name string
	if strings.HasPrefix(query, "i-") {
		// assume we're querying by instance ID here
		name = "instance-id"
	} else {
		name = "tag:Name"
	}
	params := &ec2.DescribeInstancesInput{
		Filters: []*ec2.Filter{
			{
				Name:   aws.String(name),
				Values: values,
			},
		},
	}

	resp, err := svc.DescribeInstances(params)
	if err != nil {
		wf.NewItem(err.Error()).
			Icon(aw.IconError)
		return err
	}
	log.Printf("%+v\n", *resp)

	for _, reservation := range resp.Reservations {
		for _, instance := range reservation.Instances {
			var title string
			subtitle := GetInstanceStateEmoji(*instance.State.Name)
			name := GetTagValue(instance.Tags, "Name")
			if name != "" {
				title = name
				subtitle += "  " + *instance.InstanceId
			} else {
				title = *instance.InstanceId
			}
			subtitle += "  " + *instance.InstanceType

			wf.NewItem(title).
				Subtitle(subtitle).
				Arg(fmt.Sprintf("https://%s.console.aws.amazon.com/ec2/v2/home?region=%s#Instances:search=%s", *cfg.Region, *cfg.Region, *instance.InstanceId)).
				Icon(core.GetImageIcon("ec2")).
				Valid(true)
		}
	}

	return nil
}

func GetTagValue(tags []*ec2.Tag, key string) string {
	for _, tag := range tags {
		if *tag.Key == key {
			return *tag.Value
		}
	}
	return ""
}
<|endoftext|>


<commit_before>package benchdb

import (
	"bytes"
	"database/sql"
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"
	"time"

	_ "github.com/lib/pq"

	"golang.org/x/tools/benchmark/parse"
)

// A BenchDB manges the execution of benchmark tests using go test and
// writing a parse.Set to a database.
//
// Implementations of BenchDB for different databases are allowed by way
// of the WriteSet method.
type BenchDB interface {
	// Run executes go test bench for benchmarks matching regex in the current
	// directory. By default it does not run unit tests by way of setting test.run
	// to XXX in the call to go test. It also parses the benchSet and calls WriteSet
	// to write the benchmark data to a database. It returns any error encountered.
	Run(regex string) error

	// WriteSet is responsible for opening a postgres database connection and writing
	// a parsed benchSet to a db table. It closes the connection, returns the number of
	// benchmark tests written, and any error encountered.
	WriteSet(parse.Set) (int, error)
}

// BenchPSQL represents a BenchDB that writes benchmarks to a postgres
// database.
type BenchPSQL struct {
	Driver    string // database driver name
	ConnStr   string // sql connection string
	TableName string // database table name

	dbConn *sql.DB
}

// Run runs go test benchmarks matching regex in the current directory and writes
// benchmark data to a PSQL database by calling WriteSet. It returns any error
// encountered.
func (benchdb *BenchPSQL) Run(regex string) error {
	// Exec a subprocess for go test bench and write
	// to both stdout and a byte buffer.
	cmd := exec.Command("go", "test", "-bench", regex,
		"-test.run", "XXX", "-benchmem")
	var out bytes.Buffer
	var stderr bytes.Buffer
	cmd.Stdout = io.MultiWriter(os.Stdout, &out)
	cmd.Stderr = io.Writer(&stderr)
	err := cmd.Run()
	if err != nil {
		fmt.Printf("%s", out.String())
		fmt.Printf("%s", stderr.String())
		return fmt.Errorf("command failed: %v", err)
	}

	benchSet, err := parse.ParseSet(&out)
	if err != nil {
		return fmt.Errorf("failed to parse benchmark data: %v", err)
	}

	// Writes parse set to sql database.
	_, err = benchdb.WriteSet(benchSet)
	if err != nil {
		return fmt.Errorf("failed to write benchSet to db: %v", err)
	}
	return nil
}

// WriteSet is responsible for opening a postgres database connection and writing
// a parsed benchSet to a db table. It closes the connection, returns the number of
// benchmark tests written, and any error encountered.
//
// A new sql transaction is created and committed per Benchmark in benchSet. This way if a
// db failure occurs all data from the benchSet is not lost.
func (benchdb *BenchPSQL) WriteSet(benchSet parse.Set) (int, error) {
	sqlDB, err := sql.Open(benchdb.Driver, benchdb.ConnStr)
	if err != nil {
		return 0, fmt.Errorf("could not connect to db: %v", err)
	}
	defer sqlDB.Close()
	benchdb.dbConn = sqlDB

	cnt := 0
	for _, b := range benchSet {
		n := len(b)
		for i := 0; i < n; i++ {
			val := b[i]
			err := saveBenchmark(benchdb.dbConn, benchdb.TableName, *val)
			if err != nil {
				return 0, fmt.Errorf("failed to save benchmark: %v", err)
			}
			cnt++
		}
	}
	return cnt, nil
}

func saveBenchmark(dbConn *sql.DB, table string, b parse.Benchmark) error {
	// Create a transaction per Benchmark.
	tx, err := dbConn.Begin()
	if err != nil {
		return err
	}
	defer tx.Rollback()

	q := fmt.Sprintf(`
        INSERT INTO %s
        (datetime, name, n, ns_op, allocated_bytes_op, allocs_op)
        VALUES
        ($1, $2, $3, $4, $5, $6)
        `, table)

	// Strips of leading Benchmark string in Benchmark.Name
	name := strings.TrimPrefix(strings.TrimSpace(b.Name), "Benchmark")
	ts := time.Now().UTC()

	_, err = tx.Exec(q,
		ts, name, b.N, b.NsPerOp, b.AllocedBytesPerOp, b.AllocsPerOp)
	if err != nil {
		return err
	}
	return tx.Commit()
}
<commit_msg>adding latest git sha and a batch id<commit_after>package benchdb

import (
	"bytes"
	"crypto/rand"
	"database/sql"
	"encoding/hex"
	"fmt"
	"io"
	"os"
	"os/exec"
	"strings"
	"time"

	_ "github.com/lib/pq"

	"golang.org/x/tools/benchmark/parse"
)

// A BenchDB manges the execution of benchmark tests using go test and
// writing a parse.Set to a database.
//
// Implementations of BenchDB for different databases are allowed by way
// of the WriteSet method.
type BenchDB interface {
	// Run executes go test bench for benchmarks matching regex in the current
	// directory. By default it does not run unit tests by way of setting test.run
	// to XXX in the call to go test. It also parses the benchSet and calls WriteSet
	// to write the benchmark data to a database. It returns any error encountered.
	Run(regex string) error

	// WriteSet is responsible for opening a postgres database connection and writing
	// a parsed benchSet to a db table. It closes the connection, returns the number of
	// benchmark tests written, and any error encountered.
	WriteSet(parse.Set) (int, error)
}

// BenchPSQL represents a BenchDB that writes benchmarks to a postgres
// database.
type BenchPSQL struct {
	Driver    string // database driver name
	ConnStr   string // sql connection string
	TableName string // database table name

	dbConn *sql.DB
}

// Run runs go test benchmarks matching regex in the current directory and writes
// benchmark data to a PSQL database by calling WriteSet. It returns any error
// encountered.
func (benchdb *BenchPSQL) Run(regex string) error {
	// Exec a subprocess for go test bench and write
	// to both stdout and a byte buffer.
	cmd := exec.Command("go", "test", "-bench", regex,
		"-test.run", "XXX", "-benchmem")
	var out bytes.Buffer
	var stderr bytes.Buffer
	cmd.Stdout = io.MultiWriter(os.Stdout, &out)
	cmd.Stderr = io.Writer(&stderr)
	err := cmd.Run()
	if err != nil {
		fmt.Printf("%s", out.String())
		fmt.Printf("%s", stderr.String())
		return fmt.Errorf("command failed: %v", err)
	}

	benchSet, err := parse.ParseSet(&out)
	if err != nil {
		return fmt.Errorf("failed to parse benchmark data: %v", err)
	}

	// Writes parse set to sql database.
	_, err = benchdb.WriteSet(benchSet)
	if err != nil {
		return fmt.Errorf("failed to write benchSet to db: %v", err)
	}
	return nil
}

func latestGitSha() (string, error) {
	out, err := exec.Command("git", "rev-parse", "HEAD").Output()
	if err != nil {
		return "", fmt.Errorf("failed to get latest git sha: %v\n", err)
	}
	return string(out), nil
}

func uuid() (string, error) {
	b := make([]byte, 16)
	if _, err := io.ReadFull(rand.Reader, b); err != nil {
		return "", err
	}
	return hex.EncodeToString(b), nil
}

// WriteSet is responsible for opening a postgres database connection and writing
// a parsed benchSet to a db table. It closes the connection, returns the number of
// benchmark tests written, and any error encountered.
//
// A new sql transaction is created and committed per Benchmark in benchSet. This way if a
// db failure occurs all data from the benchSet is not lost.
func (benchdb *BenchPSQL) WriteSet(benchSet parse.Set) (int, error) {
	sqlDB, err := sql.Open(benchdb.Driver, benchdb.ConnStr)
	if err != nil {
		return 0, fmt.Errorf("could not connect to db: %v", err)
	}
	defer sqlDB.Close()
	benchdb.dbConn = sqlDB

	batchId, err := uuid()
	if err != nil {
		return 0, fmt.Errorf("could not generate batch id: %v\n", err)
	}

	cnt := 0
	for _, b := range benchSet {
		n := len(b)
		for i := 0; i < n; i++ {
			val := b[i]
			err := saveBenchmark(benchdb.dbConn, benchdb.TableName, batchId, *val)
			if err != nil {
				return 0, fmt.Errorf("failed to save benchmark: %v", err)
			}
			cnt++
		}
	}
	return cnt, nil
}

func saveBenchmark(dbConn *sql.DB, table, batchId string, b parse.Benchmark) error {
	// Create a transaction per Benchmark.
	tx, err := dbConn.Begin()
	if err != nil {
		return err
	}
	defer tx.Rollback()

	sha, err := latestGitSha()
	if err != nil {
		return err
	}

	q := fmt.Sprintf(`
        INSERT INTO %s
        (batch_id, latest_sha, datetime, name, n, ns_op, allocated_bytes_op, allocs_op)
        VALUES
        ($1, $2, $3, $4, $5, $6, $7, $8)
        `, table)

	// Strips of leading Benchmark string in Benchmark.Name
	name := strings.TrimPrefix(strings.TrimSpace(b.Name), "Benchmark")
	ts := time.Now().UTC()

	_, err = tx.Exec(q,
		batchId, sha, ts, name, b.N, b.NsPerOp, b.AllocedBytesPerOp, b.AllocsPerOp)
	if err != nil {
		return err
	}
	return tx.Commit()
}
<|endoftext|>


<commit_before>// +build integration

/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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

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

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

package integration

import (
	"context"
	"fmt"
	"os"
	"strings"
	"testing"
	"time"

	"net/http"

	"github.com/elazarl/goproxy"
	"github.com/phayes/freeport"
	"github.com/pkg/errors"
)

// setUpProxy runs a local http proxy and sets the env vars for it.
func setUpProxy(t *testing.T) (*http.Server, error) {
	port, err := freeport.GetFreePort()
	if err != nil {
		return nil, errors.Wrap(err, "Failed to get an open port")
	}

	addr := fmt.Sprintf("localhost:%d", port)
	err = os.Setenv("NO_PROXY", "")
	if err != nil {
		return nil, errors.Wrap(err, "Failed to set no proxy env")
	}
	err = os.Setenv("HTTP_PROXY", addr)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to set http proxy env")
	}

	proxy := goproxy.NewProxyHttpServer()
	srv := &http.Server{Addr: addr, Handler: proxy}
	go func(s *http.Server, t *testing.T) {
		if err := s.ListenAndServe(); err != http.ErrServerClosed {
			t.Errorf("Failed to start http server for proxy mock")
		}
	}(srv, t)
	return srv, nil
}

func TestProxy(t *testing.T) {
	origHP := os.Getenv("HTTP_PROXY")
	origNP := os.Getenv("NO_PROXY")
	srv, err := setUpProxy(t)
	if err != nil {
		t.Fatalf("Failed to set up the test proxy: %s", err)
	}

	// making sure there is no running miniukube to avoid https://github.com/kubernetes/minikube/issues/4132
	r := NewMinikubeRunner(t)
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
	defer cancel()
	_, _, err = r.RunWithContext(ctx, "delete")
	if err != nil {
		t.Logf("Error deleting minikube before test setup %s : ", err)
	}

	// Clean up after setting up proxy
	defer func(t *testing.T) {
		err = os.Setenv("HTTP_PROXY", origHP)
		if err != nil {
			t.Errorf("Error reverting the HTTP_PROXY env")
		}
		err = os.Setenv("NO_PROXY", origNP)
		if err != nil {
			t.Errorf("Error reverting the NO_PROXY env")
		}

		err := srv.Shutdown(context.TODO()) // shutting down the http proxy after tests
		if err != nil {
			t.Errorf("Error shutting down the http proxy")
		}

		_, _, err = r.RunWithContext(ctx, "delete")
		if err != nil {
			t.Logf("Error deleting minikube when cleaning up proxy setup: %s", err)
		}
	}(t)

	t.Run("Proxy Console Warnning", testProxyWarning)
	t.Run("Proxy Dashboard", testProxyDashboard)

}

// testProxyWarning checks user is warned correctly about the proxy related env vars
func testProxyWarning(t *testing.T) {
	r := NewMinikubeRunner(t)
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
	defer cancel()
	startCmd := fmt.Sprintf("start %s %s %s", r.StartArgs, r.Args, "--alsologtostderr --v=5")
	stdout, stderr, err := r.RunWithContext(ctx, startCmd)
	if err != nil {
		t.Fatalf("start: %v\nstdout: %s\nstderr: %s", err, stdout, stderr)
	}

	msg := "Found network options:"
	if !strings.Contains(stdout, msg) {
		t.Errorf("Proxy wranning (%s) is missing from the output: %s", msg, stderr)
	}

	msg = "You appear to be using a proxy"
	if !strings.Contains(stderr, msg) {
		t.Errorf("Proxy wranning (%s) is missing from the output: %s", msg, stderr)
	}
}
<commit_msg>Adding non-parallel dashboard test for proxy<commit_after>// +build integration

/*
Copyright 2019 The Kubernetes Authors All rights reserved.

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

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

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

package integration

import (
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"testing"
	"time"

	"net/http"
	"net/url"

	"github.com/elazarl/goproxy"
	"github.com/phayes/freeport"
	"github.com/pkg/errors"
)

// setUpProxy runs a local http proxy and sets the env vars for it.
func setUpProxy(t *testing.T) (*http.Server, error) {
	port, err := freeport.GetFreePort()
	if err != nil {
		return nil, errors.Wrap(err, "Failed to get an open port")
	}

	addr := fmt.Sprintf("localhost:%d", port)
	err = os.Setenv("NO_PROXY", "")
	if err != nil {
		return nil, errors.Wrap(err, "Failed to set no proxy env")
	}
	err = os.Setenv("HTTP_PROXY", addr)
	if err != nil {
		return nil, errors.Wrap(err, "Failed to set http proxy env")
	}

	proxy := goproxy.NewProxyHttpServer()
	srv := &http.Server{Addr: addr, Handler: proxy}
	go func(s *http.Server, t *testing.T) {
		if err := s.ListenAndServe(); err != http.ErrServerClosed {
			t.Errorf("Failed to start http server for proxy mock")
		}
	}(srv, t)
	return srv, nil
}

func TestProxy(t *testing.T) {
	origHP := os.Getenv("HTTP_PROXY")
	origNP := os.Getenv("NO_PROXY")
	srv, err := setUpProxy(t)
	if err != nil {
		t.Fatalf("Failed to set up the test proxy: %s", err)
	}

	// making sure there is no running miniukube to avoid https://github.com/kubernetes/minikube/issues/4132
	r := NewMinikubeRunner(t)
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
	defer cancel()
	_, _, err = r.RunWithContext(ctx, "delete")
	if err != nil {
		t.Logf("Error deleting minikube before test setup %s : ", err)
	}

	// Clean up after setting up proxy
	defer func(t *testing.T) {
		err = os.Setenv("HTTP_PROXY", origHP)
		if err != nil {
			t.Errorf("Error reverting the HTTP_PROXY env")
		}
		err = os.Setenv("NO_PROXY", origNP)
		if err != nil {
			t.Errorf("Error reverting the NO_PROXY env")
		}

		err := srv.Shutdown(context.TODO()) // shutting down the http proxy after tests
		if err != nil {
			t.Errorf("Error shutting down the http proxy")
		}

		_, _, err = r.RunWithContext(ctx, "delete")
		if err != nil {
			t.Logf("Error deleting minikube when cleaning up proxy setup: %s", err)
		}
	}(t)

	t.Run("Proxy Console Warnning", testProxyWarning)
	t.Run("Proxy Dashboard", testProxyDashboard)

}

// testProxyWarning checks user is warned correctly about the proxy related env vars
func testProxyWarning(t *testing.T) {
	r := NewMinikubeRunner(t)
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
	defer cancel()
	startCmd := fmt.Sprintf("start %s %s %s", r.StartArgs, r.Args, "--alsologtostderr --v=5")
	stdout, stderr, err := r.RunWithContext(ctx, startCmd)
	if err != nil {
		t.Fatalf("start: %v\nstdout: %s\nstderr: %s", err, stdout, stderr)
	}

	msg := "Found network options:"
	if !strings.Contains(stdout, msg) {
		t.Errorf("Proxy wranning (%s) is missing from the output: %s", msg, stderr)
	}

	msg = "You appear to be using a proxy"
	if !strings.Contains(stderr, msg) {
		t.Errorf("Proxy wranning (%s) is missing from the output: %s", msg, stderr)
	}
}

// testProxyDashboard checks if dashboard URL is accessible if proxy is set
func testProxyDashboard(t *testing.T) {
	minikubeRunner := NewMinikubeRunner(t)
	cmd, out := minikubeRunner.RunDaemon("dashboard --url")
	defer func() {
		err := cmd.Process.Kill()
		if err != nil {
			t.Logf("Failed to kill dashboard command: %v", err)
		}
	}()

	s, err := readLineWithTimeout(out, 180*time.Second)
	if err != nil {
		t.Fatalf("failed to read url: %v", err)
	}

	u, err := url.Parse(strings.TrimSpace(s))
	if err != nil {
		t.Fatalf("failed to parse %q: %v", s, err)
	}
	resp, err := http.Get(u.String())
	if err != nil {
		t.Fatalf("failed get: %v", err)
	}
	if resp.StatusCode != http.StatusOK {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			t.Fatalf("Unable to read http response body: %v", err)
		}
		t.Errorf("%s returned status code %d, expected %d.\nbody:\n%s", u, resp.StatusCode, http.StatusOK, body)
	}
}
<|endoftext|>


<commit_before>package engine

import (
	"crypto/tls"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/imdario/mergo"
	"github.com/influx6/flux"
	"github.com/influx6/relay"
	"gopkg.in/yaml.v2"
)

// DefaultConfig provides a default configuration for the app
var DefaultConfig = Config{
	Addr:    ":8080",
	Env:     "dev",
	Folders: Folders{},
}

//TLSConfig provides a base config for tls configuration
type TLSConfig struct {
	Certs *tls.Config
	Key   string `yaml:"key"`
	Cert  string `yaml:"cert"`
}

type tlsconf struct {
	Key  string `yaml:"key"`
	Cert string `yaml:"cert"`
}

// UnmarshalYAML unmarshalls the incoming data for use
func (t *TLSConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
	toc := tlsconf{}

	if err := unmarshal(&toc); err != nil {
		return err
	}

	if toc.Cert == "" || toc.Key == "" {
		return nil
	}

	co, err := relay.LoadTLS(toc.Cert, toc.Key)

	if err != nil {
		return err
	}

	t.Certs = co
	return nil
}

// Folders provide a configuration for app-used folders
type Folders struct {
	Assets string `yaml:"assets"`
	Models string `yaml:"models"`
	Views  string `yaml:"views"`
}

// Config provides configuration for Afro
type Config struct {
	Addr    string    `yaml:"addr"`
	Env     string    `yaml:"env"`
	C       TLSConfig `yaml:"tls"`
	Folders Folders   `yaml:"folders"`
}

// NewConfig returns a new configuration file
func NewConfig() *Config {
	c := DefaultConfig
	return &c
}

// Load loads the configuration from a yaml file
func (c *Config) Load(file string) error {
	data, err := ioutil.ReadFile(file)

	if err != nil {
		return err
	}

	conf := Config{}
	err = yaml.Unmarshal(data, &conf)

	if err != nil {
		return err
	}

	return mergo.MergeWithOverwrite(c, conf)
}

//Engine provides a base luncher for a service
type Engine struct {
	*relay.Routes
	*Config
	li net.Listener
}

//NewEngine returns a new app configuration
func NewEngine(c *Config) *Engine {
	return &Engine{
		Config: c,
		Routes: relay.NewRoutes(""),
	}
}

func (a *Engine) loadup() error {
	//is the asset folder not empty?, if so load it up
	if a.Folders.Assets != "" {

		if _, err := os.Stat(a.Folders.Assets); err != nil {
			return err
		}

		a.ServeDir("/assets", a.Folders.Assets, "/assets/")
	}

	return nil
}

// Serve serves the app and configuration and loads the routes and serivices settings
func (a *Engine) Serve() error {
	var err error
	var li net.Listener

	if a.C.Certs != nil {
		_, li, err = relay.CreateTLS(a.Addr, a.C.Certs, a)
	} else {
		_, li, err = relay.CreateHTTP(a.Addr, a)
	}

	if err != nil {
		log.Fatalf("Server failed to start: %+s", err.Error())
		return err
	}

	a.li = li

	//load up configurations
	return a.loadup()
}

// EngineAddr returns the address of the app
func (a *Engine) EngineAddr() net.Addr {
	return a.li.Addr()
}

// Close closes and returns an error of the internal listener
func (a *Engine) Close() error {
	return a.li.Close()
}

// AppSignalInit provides a wrap function thats starts up the server and loads up,awaiting for a signal to kill
func AppSignalInit(ms time.Duration, app *Engine, cb func(*Engine)) {

	//start up the app server calling the .Serve()
	go flux.RecoveryHandlerCallback("App.Engine.Serve", app.Serve, func(ex interface{}) {
		//if we are in dev mode then panic,we should know when things go wrong
		if app.Env == "dev" {
			panic(ex)
		}
	})

	//setup the signal block and listen for the interrup
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGQUIT)
	signal.Notify(ch, os.Interrupt)

	//setup a for loop and begin calling
	for {
		select {
		case <-time.After(ms):
			//TODO: make app return info,health status and
			//useful info
			if cb != nil {
				cb(app)
			}
		case <-ch:
			app.Close()
		}
	}
}
<commit_msg>added comments for asset dir<commit_after>package engine

import (
	"crypto/tls"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/imdario/mergo"
	"github.com/influx6/flux"
	"github.com/influx6/relay"
	"gopkg.in/yaml.v2"
)

// DefaultConfig provides a default configuration for the app
var DefaultConfig = Config{
	Addr:    ":8080",
	Env:     "dev",
	Folders: Folders{},
}

//TLSConfig provides a base config for tls configuration
type TLSConfig struct {
	Certs *tls.Config
	Key   string `yaml:"key"`
	Cert  string `yaml:"cert"`
}

type tlsconf struct {
	Key  string `yaml:"key"`
	Cert string `yaml:"cert"`
}

// UnmarshalYAML unmarshalls the incoming data for use
func (t *TLSConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
	toc := tlsconf{}

	if err := unmarshal(&toc); err != nil {
		return err
	}

	if toc.Cert == "" || toc.Key == "" {
		return nil
	}

	co, err := relay.LoadTLS(toc.Cert, toc.Key)

	if err != nil {
		return err
	}

	t.Certs = co
	return nil
}

// Folders provide a configuration for app-used folders
type Folders struct {
	Assets string `yaml:"assets"`
	Models string `yaml:"models"`
	Views  string `yaml:"views"`
}

// Config provides configuration for Afro
type Config struct {
	Addr    string    `yaml:"addr"`
	Env     string    `yaml:"env"`
	C       TLSConfig `yaml:"tls"`
	Folders Folders   `yaml:"folders"`
}

// NewConfig returns a new configuration file
func NewConfig() *Config {
	c := DefaultConfig
	return &c
}

// Load loads the configuration from a yaml file
func (c *Config) Load(file string) error {
	data, err := ioutil.ReadFile(file)

	if err != nil {
		return err
	}

	conf := Config{}
	err = yaml.Unmarshal(data, &conf)

	if err != nil {
		return err
	}

	return mergo.MergeWithOverwrite(c, conf)
}

//Engine provides a base luncher for a service
type Engine struct {
	*relay.Routes
	*Config
	li net.Listener
}

//NewEngine returns a new app configuration
func NewEngine(c *Config) *Engine {
	return &Engine{
		Config: c,
		Routes: relay.NewRoutes(""),
	}
}

func (a *Engine) loadup() error {
	//is the asset folder not empty?, if so load it up
	if a.Folders.Assets != "" {

		if _, err := os.Stat(a.Folders.Assets); err != nil {
			return err
		}

		log.Printf("Setting up assets dir: %s", a.Folders.Assets)
		a.ServeDir("/assets", a.Folders.Assets, "/assets/")
		log.Printf("Done loading assets dir: %s", a.Folders.Assets)
	}

	return nil
}

// Serve serves the app and configuration and loads the routes and serivices settings
func (a *Engine) Serve() error {
	var err error
	var li net.Listener

	if a.C.Certs != nil {
		_, li, err = relay.CreateTLS(a.Addr, a.C.Certs, a)
	} else {
		_, li, err = relay.CreateHTTP(a.Addr, a)
	}

	if err != nil {
		log.Fatalf("Server failed to start: %+s", err.Error())
		return err
	}

	a.li = li

	//load up configurations
	return a.loadup()
}

// EngineAddr returns the address of the app
func (a *Engine) EngineAddr() net.Addr {
	return a.li.Addr()
}

// Close closes and returns an error of the internal listener
func (a *Engine) Close() error {
	return a.li.Close()
}

// AppSignalInit provides a wrap function thats starts up the server and loads up,awaiting for a signal to kill
func AppSignalInit(ms time.Duration, app *Engine, cb func(*Engine)) {

	//start up the app server calling the .Serve()
	go flux.RecoveryHandlerCallback("App.Engine.Serve", app.Serve, func(ex interface{}) {
		//if we are in dev mode then panic,we should know when things go wrong
		if app.Env == "dev" {
			panic(ex)
		}
	})

	//setup the signal block and listen for the interrup
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGQUIT)
	signal.Notify(ch, os.Interrupt)

	//setup a for loop and begin calling
	for {
		select {
		case <-time.After(ms):
			//TODO: make app return info,health status and
			//useful info
			if cb != nil {
				cb(app)
			}
		case <-ch:
			app.Close()
		}
	}
}
<|endoftext|>


<commit_before>package engine

import (
	"fmt"
	"io"
	"os"

	"github.com/drone/drone/shared/docker"
	"github.com/samalba/dockerclient"
)

var (
	// name of the build agent container.
	// TODO(xiaods):  drone/drone#1527 is fixed to support customizable location
	DefaultAgent = "catalog.shurenyun.com/library/drone-exec:latest"

	// default name of the build agent executable
	DefaultEntrypoint = []string{"/bin/drone-exec"}

	// default argument to invoke build steps
	DefaultBuildArgs = []string{"--pull", "--cache", "--clone", "--build", "--deploy"}

	// default argument to invoke build steps
	DefaultPullRequestArgs = []string{"--pull", "--cache", "--clone", "--build"}

	// default arguments to invoke notify steps
	DefaultNotifyArgs = []string{"--pull", "--notify"}
)

type worker struct {
	client dockerclient.Client
	build  *dockerclient.ContainerInfo
	notify *dockerclient.ContainerInfo
}

func newWorker(client dockerclient.Client) *worker {
	return &worker{client: client}
}

//GetAgent get build agent image uri from env
func GetAgent() string {
	if uri := os.Getenv("AGENT_URI"); len(uri) > 0 {
		return uri
	} else {
		return DefaultAgent
	}
}

// Build executes the clone, build and deploy steps.
func (w *worker) Build(name string, stdin []byte, pr bool) (_ int, err error) {
	// the command line arguments passed into the
	// build agent container.
	args := DefaultBuildArgs
	if pr {
		args = DefaultPullRequestArgs
	}
	args = append(args, "--")
	args = append(args, string(stdin))

	conf := &dockerclient.ContainerConfig{
		Image:      GetAgent(),
		Entrypoint: DefaultEntrypoint,
		Cmd:        args,
		HostConfig: dockerclient.HostConfig{
			Binds:      []string{"/var/run/docker.sock:/var/run/docker.sock"},
			Privileged: true,
			ExtraHosts: GetExtraHosts(),
		},
		Volumes: map[string]struct{}{
			"/var/run/docker.sock": struct{}{},
		},
	}

	// TEMPORARY: always try to pull the new image for now
	// since we'll be frequently updating the build image
	// for the next few weeks
	w.client.PullImage(conf.Image, nil)

	w.build, err = docker.Run(w.client, conf, name)
	if err != nil {
		return 1, err
	}
	if w.build.State.OOMKilled {
		return 1, fmt.Errorf("OOMKill received")
	}
	return w.build.State.ExitCode, err
}

// Notify executes the notification steps.
func (w *worker) Notify(stdin []byte) error {

	args := DefaultNotifyArgs
	args = append(args, "--")
	args = append(args, string(stdin))

	conf := &dockerclient.ContainerConfig{
		Image:      GetAgent(),
		Entrypoint: DefaultEntrypoint,
		Cmd:        args,
		HostConfig: dockerclient.HostConfig{
			ExtraHosts: GetExtraHosts(),
		},
	}

	var err error
	w.notify, err = docker.Run(w.client, conf, "")
	return err
}

// Logs returns a multi-reader that fetches the logs
// from the build and deploy agents.
func (w *worker) Logs() (io.ReadCloser, error) {
	if w.build == nil {
		return nil, errLogging
	}
	return w.client.ContainerLogs(w.build.Id, logOpts)
}

// Remove stops and removes the build, deploy and
// notification agents created for the build task.
func (w *worker) Remove() {
	if w.notify != nil {
		w.client.KillContainer(w.notify.Id, "9")
		w.client.RemoveContainer(w.notify.Id, true, true)
	}
	if w.build != nil {
		w.client.KillContainer(w.build.Id, "9")
		w.client.RemoveContainer(w.build.Id, true, true)
	}
}
<commit_msg>remove cache step for workflow<commit_after>package engine

import (
	"fmt"
	"io"
	"os"

	"github.com/drone/drone/shared/docker"
	"github.com/samalba/dockerclient"
)

var (
	// name of the build agent container.
	// TODO(xiaods):  drone/drone#1527 is fixed to support customizable location
	DefaultAgent = "catalog.shurenyun.com/library/drone-exec:latest"

	// default name of the build agent executable
	DefaultEntrypoint = []string{"/bin/drone-exec"}

	// default argument to invoke build steps
	DefaultBuildArgs = []string{"--pull", "--clone", "--build", "--deploy"}

	// default argument to invoke build steps
	DefaultPullRequestArgs = []string{"--pull", "--clone", "--build"}

	// default arguments to invoke notify steps
	DefaultNotifyArgs = []string{"--pull", "--notify"}
)

type worker struct {
	client dockerclient.Client
	build  *dockerclient.ContainerInfo
	notify *dockerclient.ContainerInfo
}

func newWorker(client dockerclient.Client) *worker {
	return &worker{client: client}
}

//GetAgent get build agent image uri from env
func GetAgent() string {
	if uri := os.Getenv("AGENT_URI"); len(uri) > 0 {
		return uri
	} else {
		return DefaultAgent
	}
}

// Build executes the clone, build and deploy steps.
func (w *worker) Build(name string, stdin []byte, pr bool) (_ int, err error) {
	// the command line arguments passed into the
	// build agent container.
	args := DefaultBuildArgs
	if pr {
		args = DefaultPullRequestArgs
	}
	args = append(args, "--")
	args = append(args, string(stdin))

	conf := &dockerclient.ContainerConfig{
		Image:      GetAgent(),
		Entrypoint: DefaultEntrypoint,
		Cmd:        args,
		HostConfig: dockerclient.HostConfig{
			Binds:      []string{"/var/run/docker.sock:/var/run/docker.sock"},
			Privileged: true,
			ExtraHosts: GetExtraHosts(),
		},
		Volumes: map[string]struct{}{
			"/var/run/docker.sock": struct{}{},
		},
	}

	// TEMPORARY: always try to pull the new image for now
	// since we'll be frequently updating the build image
	// for the next few weeks
	w.client.PullImage(conf.Image, nil)

	w.build, err = docker.Run(w.client, conf, name)
	if err != nil {
		return 1, err
	}
	if w.build.State.OOMKilled {
		return 1, fmt.Errorf("OOMKill received")
	}
	return w.build.State.ExitCode, err
}

// Notify executes the notification steps.
func (w *worker) Notify(stdin []byte) error {

	args := DefaultNotifyArgs
	args = append(args, "--")
	args = append(args, string(stdin))

	conf := &dockerclient.ContainerConfig{
		Image:      GetAgent(),
		Entrypoint: DefaultEntrypoint,
		Cmd:        args,
		HostConfig: dockerclient.HostConfig{
			ExtraHosts: GetExtraHosts(),
		},
	}

	var err error
	w.notify, err = docker.Run(w.client, conf, "")
	return err
}

// Logs returns a multi-reader that fetches the logs
// from the build and deploy agents.
func (w *worker) Logs() (io.ReadCloser, error) {
	if w.build == nil {
		return nil, errLogging
	}
	return w.client.ContainerLogs(w.build.Id, logOpts)
}

// Remove stops and removes the build, deploy and
// notification agents created for the build task.
func (w *worker) Remove() {
	if w.notify != nil {
		w.client.KillContainer(w.notify.Id, "9")
		w.client.RemoveContainer(w.notify.Id, true, true)
	}
	if w.build != nil {
		w.client.KillContainer(w.build.Id, "9")
		w.client.RemoveContainer(w.build.Id, true, true)
	}
}
<|endoftext|>


<commit_before>package errors

// Error represents all errors which can be passed between services
type Error interface {
	Code() string
	Error() string
	Type() ErrorType
}

// ErrorType is an enumerated type of error
type ErrorType string

const (
	// ErrUnknown indicates an unknown type of error
	// @todo should this just be mapped to an internal server error?
	ErrUnknown = ErrorType("UnknownError")

	ErrBadRequest     = ErrorType("BadRequestError")
	ErrBadResponse    = ErrorType("BadResponseError")
	ErrForbidden      = ErrorType("ForbiddenError")
	ErrInternalServer = ErrorType("InternalServerError")
	ErrNotFound       = ErrorType("NotFoundError")
	ErrTimeout        = ErrorType("TimeoutError")
)

// platformError implements the Error interface, and is the internal type we
// use to pass errors between services. The error cannot be directly instantiated,
// and one of the helper methods should be used to construct a specific type of error
type platformError struct {
	errorType   ErrorType
	code        string
	description string
}

// Code defines a clearly defined inter-service error code
func (p *platformError) Code() string {
	if p != nil {
		return p.code
	}

	return ""
}

// Error returns a string description of the error
func (p *platformError) Error() string {
	if p != nil {
		return p.description
	}

	return ""
}

// Type of error that this error represents
func (p *platformError) Type() ErrorType {
	if p != nil {
		return p.errorType
	}

	return ErrUnknown
}

// InternalServerError creates a new error that represents an error originating within a service
func InternalServerError(code, description string, context ...string) Error {
	return &platformError{
		errorType:   ErrInternalServer,
		code:        code,
		description: description,
	}
}

// BadRequest creates a new error to represent an error caused by the client sending
// an invalid request. This is non-retryable unless the request is modified.
func BadRequest(code, description string, context ...string) Error {
	return &platformError{
		errorType:   ErrBadRequest,
		code:        code,
		description: description,
	}
}

// BadResponse creates a new error representing a failure to response with a valid response
// Examples of this would be a handler returning an invalid message format
func BadResponse(code, description string, context ...string) Error {
	return &platformError{
		errorType:   ErrBadResponse,
		code:        code,
		description: description,
	}
}

// Timeout creates a new error representing a timeout from client to server
func Timeout(code, description string, context ...string) Error {
	return &platformError{
		errorType:   ErrTimeout,
		code:        code,
		description: description,
	}
}

// NotFound creates a new error representing a resource that cannot be found. In some
// cases this is not an error, and would be better represented by a zero length slice of elements
func NotFound(code, description string, context ...string) Error {
	return &platformError{
		errorType:   ErrNotFound,
		code:        code,
		description: description,
	}
}

// Forbidden creates a new error representing a resource that cannot be accessed with
// the current authorisation credentials. The user may need authorising, or if authorised,
// may not be permitted to perform this action
func Forbidden(code, description string, context ...string) Error {
	return &platformError{
		errorType:   ErrForbidden,
		code:        code,
		description: description,
	}
}
<commit_msg>Update err consts to match error types<commit_after>package errors

// Error represents all errors which can be passed between services
type Error interface {
	Code() string
	Error() string
	Type() ErrorType
}

// ErrorType is an enumerated type of error
type ErrorType string

const (
	// ErrUnknown indicates an unknown type of error
	// @todo should this just be mapped to an internal server error?
	ErrUnknown = ErrorType("UnknownError")

	ErrBadRequest     = ErrorType("ErrBadRequest")
	ErrBadResponse    = ErrorType("ErrBadResponse")
	ErrForbidden      = ErrorType("ErrForbidden")
	ErrInternalServer = ErrorType("ErrInternalServer")
	ErrNotFound       = ErrorType("ErrNotFound")
	ErrTimeout        = ErrorType("ErrTimeout")
)

// platformError implements the Error interface, and is the internal type we
// use to pass errors between services. The error cannot be directly instantiated,
// and one of the helper methods should be used to construct a specific type of error
type platformError struct {
	errorType   ErrorType
	code        string
	description string
}

// Code defines a clearly defined inter-service error code
func (p *platformError) Code() string {
	if p != nil {
		return p.code
	}

	return ""
}

// Error returns a string description of the error
func (p *platformError) Error() string {
	if p != nil {
		return p.description
	}

	return ""
}

// Type of error that this error represents
func (p *platformError) Type() ErrorType {
	if p != nil {
		return p.errorType
	}

	return ErrUnknown
}

// InternalServerError creates a new error that represents an error originating within a service
func InternalServerError(code, description string, context ...string) Error {
	return &platformError{
		errorType:   ErrInternalServer,
		code:        code,
		description: description,
	}
}

// BadRequest creates a new error to represent an error caused by the client sending
// an invalid request. This is non-retryable unless the request is modified.
func BadRequest(code, description string, context ...string) Error {
	return &platformError{
		errorType:   ErrBadRequest,
		code:        code,
		description: description,
	}
}

// BadResponse creates a new error representing a failure to response with a valid response
// Examples of this would be a handler returning an invalid message format
func BadResponse(code, description string, context ...string) Error {
	return &platformError{
		errorType:   ErrBadResponse,
		code:        code,
		description: description,
	}
}

// Timeout creates a new error representing a timeout from client to server
func Timeout(code, description string, context ...string) Error {
	return &platformError{
		errorType:   ErrTimeout,
		code:        code,
		description: description,
	}
}

// NotFound creates a new error representing a resource that cannot be found. In some
// cases this is not an error, and would be better represented by a zero length slice of elements
func NotFound(code, description string, context ...string) Error {
	return &platformError{
		errorType:   ErrNotFound,
		code:        code,
		description: description,
	}
}

// Forbidden creates a new error representing a resource that cannot be accessed with
// the current authorisation credentials. The user may need authorising, or if authorised,
// may not be permitted to perform this action
func Forbidden(code, description string, context ...string) Error {
	return &platformError{
		errorType:   ErrForbidden,
		code:        code,
		description: description,
	}
}
<|endoftext|>


<commit_before>package loadbalancer

import (
	"context"
	"fmt"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/giantswarm/microerror"
	"github.com/giantswarm/operatorkit/framework"
)

func (r *Resource) ApplyDeleteChange(ctx context.Context, obj, deleteChange interface{}) error {
	deleteInput, err := toLoadBalancerState(deleteChange)
	if err != nil {
		return microerror.Mask(err)
	}

	if deleteInput != nil && len(deleteInput.LoadBalancerNames) > 0 {
		for _, lbName := range deleteInput.LoadBalancerNames {
			if _, err := r.clients.ELB.DeleteLoadBalancer(&elb.DeleteLoadBalancerInput{
				LoadBalancerName: aws.String(lbName),
			}); err != nil {
				return microerror.Mask(err)
			}
		}
	}

	r.logger.LogCtx(ctx, "debug", fmt.Sprintf("deleted %d load balancers", len(deleteInput.LoadBalancerNames)))

	return nil
}

func (r *Resource) NewDeletePatch(ctx context.Context, obj, currentState, desiredState interface{}) (*framework.Patch, error) {
	delete, err := r.newDeleteChange(ctx, obj, currentState, desiredState)
	if err != nil {
		return nil, microerror.Mask(err)
	}

	patch := framework.NewPatch()
	patch.SetDeleteChange(delete)

	return patch, nil
}

func (r *Resource) newDeleteChange(ctx context.Context, obj, currentState, desiredState interface{}) (interface{}, error) {
	currentLBState, err := toLoadBalancerState(currentState)
	if err != nil {
		return nil, microerror.Mask(err)
	}
	desiredLBState, err := toLoadBalancerState(desiredState)
	if err != nil {
		return nil, microerror.Mask(err)
	}

	var lbStateToDelete *LoadBalancerState
	if desiredLBState == nil && currentLBState != nil && len(currentLBState.LoadBalancerNames) > 0 {
		lbStateToDelete = currentLBState
	}

	return lbStateToDelete, nil
}
<commit_msg>Split delete logic for elbs (#762)<commit_after>package loadbalancer

import (
	"context"
	"fmt"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/elb"
	"github.com/giantswarm/microerror"
	"github.com/giantswarm/operatorkit/framework"
)

func (r *Resource) ApplyDeleteChange(ctx context.Context, obj, deleteChange interface{}) error {
	deleteInput, err := toLoadBalancerState(deleteChange)
	if err != nil {
		return microerror.Mask(err)
	}

	if deleteInput != nil && len(deleteInput.LoadBalancerNames) > 0 {
		for _, lbName := range deleteInput.LoadBalancerNames {
			_, err := r.clients.ELB.DeleteLoadBalancer(&elb.DeleteLoadBalancerInput{
				LoadBalancerName: aws.String(lbName),
			})
			if err != nil {
				return microerror.Mask(err)
			}
		}
	}

	r.logger.LogCtx(ctx, "debug", fmt.Sprintf("deleted %d load balancers", len(deleteInput.LoadBalancerNames)))

	return nil
}

func (r *Resource) NewDeletePatch(ctx context.Context, obj, currentState, desiredState interface{}) (*framework.Patch, error) {
	delete, err := r.newDeleteChange(ctx, obj, currentState, desiredState)
	if err != nil {
		return nil, microerror.Mask(err)
	}

	patch := framework.NewPatch()
	patch.SetDeleteChange(delete)

	return patch, nil
}

func (r *Resource) newDeleteChange(ctx context.Context, obj, currentState, desiredState interface{}) (interface{}, error) {
	currentLBState, err := toLoadBalancerState(currentState)
	if err != nil {
		return nil, microerror.Mask(err)
	}
	desiredLBState, err := toLoadBalancerState(desiredState)
	if err != nil {
		return nil, microerror.Mask(err)
	}

	var lbStateToDelete *LoadBalancerState
	if desiredLBState == nil && currentLBState != nil && len(currentLBState.LoadBalancerNames) > 0 {
		lbStateToDelete = currentLBState
	}

	return lbStateToDelete, nil
}
<|endoftext|>