<commit_before>package main

import (
	"io/ioutil"
	"os"
	"strings"

	"github.com/urfave/cli"
)

func main() {
	fakeImagePlugin := cli.NewApp()
	fakeImagePlugin.Name = "fakeImagePlugin"
	fakeImagePlugin.Usage = "I am FakeImagePlugin!"

	fakeImagePlugin.Flags = []cli.Flag{
		cli.BoolFlag{
			Name: "debug",
		},
		cli.StringFlag{
			Name: "log",
		},
		cli.StringFlag{
			Name: "newuidmap",
		},
		cli.StringFlag{
			Name: "newgidmap",
		},
	}

	fakeImagePlugin.Commands = []cli.Command{
		CreateCommand,
	}

	_ = fakeImagePlugin.Run(os.Args)
}

var CreateCommand = cli.Command{
	Name: "create",
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name: "no-new-keyring",
		},
		cli.StringFlag{
			Name: "bundle",
		},
		cli.StringFlag{
			Name: "pid-file",
		},
	},

	Action: func(ctx *cli.Context) error {
		err := ioutil.WriteFile("/tmp/args", []byte(strings.Join(os.Args, " ")), 0777)
		if err != nil {
			panic(err)
		}

		return nil
	},
}
<commit_msg>Rename erroneous fakeImagePlugin to fakeRuntimePlugin<commit_after>package main

import (
	"io/ioutil"
	"os"
	"strings"

	"github.com/urfave/cli"
)

func main() {
	fakeRuntimePlugin := cli.NewApp()
	fakeRuntimePlugin.Name = "fakeRuntimePlugin"
	fakeRuntimePlugin.Usage = "I am FakeRuntimePlugin!"

	fakeRuntimePlugin.Flags = []cli.Flag{
		cli.BoolFlag{
			Name: "debug",
		},
		cli.StringFlag{
			Name: "log",
		},
		cli.StringFlag{
			Name: "newuidmap",
		},
		cli.StringFlag{
			Name: "newgidmap",
		},
	}

	fakeRuntimePlugin.Commands = []cli.Command{
		CreateCommand,
	}

	_ = fakeRuntimePlugin.Run(os.Args)
}

var CreateCommand = cli.Command{
	Name: "create",
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name: "no-new-keyring",
		},
		cli.StringFlag{
			Name: "bundle",
		},
		cli.StringFlag{
			Name: "pid-file",
		},
	},

	Action: func(ctx *cli.Context) error {
		err := ioutil.WriteFile("/tmp/args", []byte(strings.Join(os.Args, " ")), 0777)
		if err != nil {
			panic(err)
		}

		return nil
	},
}
<|endoftext|>


<commit_before>package kallax

// AfterLoader must be implemented by those entities listening the AfterLoad event
type AfterLoader interface {
	// AfterLoad runs after the entitie has been loaded from DB
	AfterLoad()
}

// AfterLoader must be implemented by those entities listening the BeforeSave event
type BeforeSaver interface {
	// BeforeSave runs before the entitie has being Saved in the DB.
	// It will return an error if the Saveing process will be interrupted
	BeforeSave() error
}

// AfterLoader must be implemented by those entities listening the AfterSave event
type AfterSaver interface {
	// AfterSave runs after the entitie has being Saved in the DB.
	// If an error is returned, the transaction will be rollbacked.
	AfterSave() error
}

// AfterLoader must be implemented by those entities listening the BeforeUpdate event
type BeforeUpdater interface {
	// BeforeUpdate runs before the entitie has been updated in the DB
	// It will return an error if the update process will be interrupted
	BeforeUpdate() error
}

// AfterLoader must be implemented by those entities listening the AfterUpdate event
type AfterUpdater interface {
	// AfterUpdate runs after the entitie has been updated in the DB
	// If an error is returned, the transaction will be rollbacked.
	AfterUpdate() error
}

// AfterLoader must be implemented by those entities listening the BeforeInsert event
type BeforeInserter interface {
	// BeforeInsert runs before the entitie has been inserted in the DB
	// It will return an error if the insertion process will be interrupted
	BeforeInsert() error
}

// AfterLoader must be implemented by those entities listening the AfterInsert event
type AfterInserter interface {
	// AfterInsert runs after the entitie has been inserted in the DB
	// If an error is returned, the transaction will be rollbacked.
	AfterInsert() error
}

// AfterLoader must be implemented by those entities listening the BeforeDelete event
type BeforeDeleter interface {
	// BeforeDelete runs before the entitie has been deleted from DB
	// It will return an error if the deletion process will be interrupted
	BeforeDelete() error
}

// AfterLoader must be implemented by those entities listening the AfterDelete event
type AfterDeleter interface {
	// AfterDelete runs after the entitie has been deleted from DB
	// If an error is returned, the transaction will be rollbacked.
	AfterDelete() error
}
<commit_msg>Remove hook interfaces<commit_after><|endoftext|>


<commit_before>package parsesearch

import (
	"fmt"
	"log"
	"os"
	"path"
	"strings"

	"github.com/tmc/parse"
)

func squelchAlreadyExists(err error) error {
	if err, ok := err.(*parse.Error); ok {
		if strings.Contains(err.Message, "already exists") {
			return nil
		}
	}
	return err
}

// RegisterHooks auto-registers the search service with a Parse Application.
func (i *Indexer) RegisterHooks(className string) error {
	c, err := parse.NewClient(i.appID, "")
	c.TraceOn(log.New(os.Stderr, "[parse api] ", log.LstdFlags))
	if err != nil {
		return err
	}
	c = c.WithMasterKey(i.masterKey)
	urlPrefix := os.Getenv("URL")
	if urlPrefix == "" {
		return fmt.Errorf("Skipping registering Webhooks as the 'URL' environment variable is empty.")
	}
	err = squelchAlreadyExists(c.CreateHookFunction(&parse.HookFunction{
		FunctionName: "search",
		URL:          path.Join(urlPrefix, "search"),
	}))
	if err != nil {
		return err
	}
	err = squelchAlreadyExists(c.CreateTriggerFunction(&parse.TriggerFunction{
		ClassName:   className,
		TriggerName: "afterSave",
		URL:         path.Join(urlPrefix, "index"),
	}))
	if err != nil {
		return err
	}
	err = squelchAlreadyExists(c.CreateTriggerFunction(&parse.TriggerFunction{
		ClassName:   className,
		TriggerName: "afterDelete",
		URL:         path.Join(urlPrefix, "unindex"),
	}))
	return err
}
<commit_msg>fix joining<commit_after>package parsesearch

import (
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/tmc/parse"
)

func squelchAlreadyExists(err error) error {
	if err, ok := err.(*parse.Error); ok {
		if strings.Contains(err.Message, "already exists") {
			return nil
		}
	}
	return err
}

func pathJoin(a, b string) string {
	if !strings.HasSuffix(a, "/") {
		a = a + "/"
	}
	return a + b
}

// RegisterHooks auto-registers the search service with a Parse Application.
func (i *Indexer) RegisterHooks(className string) error {
	c, err := parse.NewClient(i.appID, "")
	c.TraceOn(log.New(os.Stderr, "[parse api] ", log.LstdFlags))
	if err != nil {
		return err
	}
	c = c.WithMasterKey(i.masterKey)
	urlPrefix := os.Getenv("URL")
	if urlPrefix == "" {
		return fmt.Errorf("Skipping registering Webhooks as the 'URL' environment variable is empty.")
	}
	err = squelchAlreadyExists(c.CreateHookFunction(&parse.HookFunction{
		FunctionName: "search",
		URL:          pathJoin(urlPrefix, "search"),
	}))
	if err != nil {
		return err
	}
	err = squelchAlreadyExists(c.CreateTriggerFunction(&parse.TriggerFunction{
		ClassName:   className,
		TriggerName: "afterSave",
		URL:         pathJoin(urlPrefix, "index"),
	}))
	if err != nil {
		return err
	}
	err = squelchAlreadyExists(c.CreateTriggerFunction(&parse.TriggerFunction{
		ClassName:   className,
		TriggerName: "afterDelete",
		URL:         pathJoin(urlPrefix, "unindex"),
	}))
	return err
}
<|endoftext|>


<commit_before>package calendar

import (
	"database/sql"
	"math"
	"time"

	"github.com/MyHomeworkSpace/api-server/data"
)

// A ViewDay represents a day in a View.
type ViewDay struct {
	DayString     string                     `json:"day"`
	Announcements []data.PlannerAnnouncement `json:"announcements"`
	Events        []data.Event               `json:"events"`
}

// A View represents a view of a user's calendar over a certain period of time.
type View struct {
	Providers []ProviderInfo `json:"providers"`
	Days      []ViewDay      `json:"days"`
}

// A ProviderInfo struct represents information about an active calendar providers.
type ProviderInfo struct {
	Name string `json:"name"`
}

// GetView retrieves a CalendarView for the given user with the given parameters.
func GetView(db *sql.DB, user *data.User, location *time.Location, startTime time.Time, endTime time.Time) (View, error) {
	view := View{
		Providers: []ProviderInfo{},
		Days:      []ViewDay{},
	}

	providers, err := data.GetProvidersForUser(user)
	if err != nil {
		return View{}, err
	}

	// create days in array
	dayCount := int((endTime.Sub(startTime).Hours() / 24) + 0.5)
	currentDay := startTime
	for i := 0; i < dayCount; i++ {
		view.Days = append(view.Days, ViewDay{
			DayString:     currentDay.Format("2006-01-02"),
			Announcements: []data.PlannerAnnouncement{},
			Events:        []data.Event{},
		})

		currentDay = currentDay.AddDate(0, 0, 1)
	}

	// get plain events
	plainEventRows, err := db.Query(
		"SELECT calendar_events.id, calendar_events.name, calendar_events.`start`, calendar_events.`end`, calendar_events.`desc`, calendar_events.userId, calendar_event_rules.id, calendar_event_rules.eventId, calendar_event_rules.frequency, calendar_event_rules.interval, calendar_event_rules.byDay, calendar_event_rules.byMonthDay, calendar_event_rules.byMonth, calendar_event_rules.until FROM calendar_events "+
			"LEFT JOIN calendar_event_rules ON calendar_events.id = calendar_event_rules.eventId "+
			"WHERE calendar_events.userId = ? AND ((calendar_events.`end` >= ? AND calendar_events.`start` <= ?) OR calendar_event_rules.frequency IS NOT NULL)",
		user.ID, startTime.Unix(), endTime.Unix(),
	)
	if err != nil {
		return View{}, err
	}
	defer plainEventRows.Close()

	for plainEventRows.Next() {
		event := data.Event{
			Tags:   map[data.EventTagType]interface{}{},
			Source: -1,
		}
		desc := ""
		recurRule := data.RecurRule{
			ID: -1,
		}
		plainEventRows.Scan(
			&event.ID, &event.Name, &event.Start, &event.End, &desc, &event.UserID,
			&recurRule.ID, &recurRule.EventID, &recurRule.Frequency, &recurRule.Interval, &recurRule.ByDayString, &recurRule.ByMonthDay, &recurRule.ByMonth, &recurRule.UntilString,
		)
		event.Tags[data.EventTagDescription] = desc
		if recurRule.ID != -1 {
			event.RecurRule = &recurRule

			if event.RecurRule.UntilString == "2099-12-12" {
				// just a placeholder value for mysql, ignore it
				event.RecurRule.UntilString = ""
			} else {
				event.RecurRule.Until, err = time.Parse("2006-01-02", event.RecurRule.UntilString)
				if err != nil {
					return View{}, err
				}
			}
		}

		eventTimes := event.CalculateTimes(endTime)

		for _, eventTime := range eventTimes {
			dayOffset := int(math.Floor(eventTime.Sub(startTime).Hours() / 24))

			if dayOffset < 0 || dayOffset > len(view.Days)-1 {
				continue
			}

			view.Days[dayOffset].Events = append(view.Days[dayOffset].Events, event)
		}
	}

	// get homework events
	hwEventRows, err := db.Query("SELECT calendar_hwevents.id, homework.id, homework.name, homework.`due`, homework.`desc`, homework.`complete`, homework.classId, homework.userId, calendar_hwevents.`start`, calendar_hwevents.`end`, calendar_hwevents.userId FROM calendar_hwevents INNER JOIN homework ON calendar_hwevents.homeworkId = homework.id WHERE calendar_hwevents.userId = ? AND (calendar_hwevents.`end` >= ? AND calendar_hwevents.`start` <= ?)", user.ID, startTime.Unix(), endTime.Unix())
	if err != nil {
		return View{}, err
	}
	defer hwEventRows.Close()

	for hwEventRows.Next() {
		event := data.Event{
			Tags:   map[data.EventTagType]interface{}{},
			Source: -1,
		}
		homework := data.Homework{}
		hwEventRows.Scan(&event.ID, &homework.ID, &homework.Name, &homework.Due, &homework.Desc, &homework.Complete, &homework.ClassID, &homework.UserID, &event.Start, &event.End, &event.UserID)
		event.Tags[data.EventTagHomework] = homework
		event.Name = homework.Name

		eventStartTime := time.Unix(int64(event.Start), 0)
		dayOffset := int(math.Floor(eventStartTime.Sub(startTime).Hours() / 24))

		if dayOffset < 0 || dayOffset > len(view.Days)-1 {
			continue
		}

		view.Days[dayOffset].Events = append(view.Days[dayOffset].Events, event)
	}

	// handle calendar providers
	for providerIndex, provider := range providers {
		// add them to the list
		view.Providers = append(view.Providers, ProviderInfo{
			Name: provider.Name(),
		})

		// get data
		providerData, err := provider.GetData(db, user, location, startTime, endTime, data.ProviderDataAll)
		if err != nil {
			return View{}, err
		}

		// add announcements
		for _, announcement := range providerData.Announcements {
			announcementDate, err := time.Parse("2006-01-02", announcement.Date)
			if err != nil {
				return View{}, err
			}
			dayOffset := int(math.Ceil(announcementDate.Sub(startTime).Hours() / 24))

			if dayOffset < 0 || dayOffset > len(view.Days)-1 {
				continue
			}

			view.Days[dayOffset].Announcements = append(view.Days[dayOffset].Announcements, announcement)
		}

		// add events
		for _, event := range providerData.Events {
			eventDate := time.Unix(int64(event.Start), 0)
			dayOffset := int(math.Floor(eventDate.Sub(startTime).Hours() / 24))

			if dayOffset < 0 || dayOffset > len(view.Days)-1 {
				continue
			}

			event.Source = providerIndex

			view.Days[dayOffset].Events = append(view.Days[dayOffset].Events, event)
		}
	}

	return view, nil
}
<commit_msg>report schools that need updates in calendar view<commit_after>package calendar

import (
	"database/sql"
	"math"
	"time"

	"github.com/MyHomeworkSpace/api-server/data"
)

// A ViewDay represents a day in a View.
type ViewDay struct {
	DayString     string                     `json:"day"`
	Announcements []data.PlannerAnnouncement `json:"announcements"`
	Events        []data.Event               `json:"events"`
}

// A View represents a view of a user's calendar over a certain period of time.
type View struct {
	Providers       []ProviderInfo    `json:"providers"`
	SchoolsToUpdate []data.SchoolInfo `json:"schoolsToUpdate"`
	Days            []ViewDay         `json:"days"`
}

// A ProviderInfo struct represents information about an active calendar providers.
type ProviderInfo struct {
	Name string `json:"name"`
}

// GetView retrieves a CalendarView for the given user with the given parameters.
func GetView(db *sql.DB, user *data.User, location *time.Location, startTime time.Time, endTime time.Time) (View, error) {
	view := View{
		Providers:       []ProviderInfo{},
		SchoolsToUpdate: []data.SchoolInfo{},
		Days:            []ViewDay{},
	}

	providers, err := data.GetProvidersForUser(user)
	if err != nil {
		return View{}, err
	}

	for _, schoolInfo := range user.Schools {
		needsUpdate, err := schoolInfo.School.NeedsUpdate(db)
		if err != nil {
			return View{}, err
		}

		if needsUpdate {
			view.SchoolsToUpdate = append(view.SchoolsToUpdate, schoolInfo)
		}
	}

	// create days in array
	dayCount := int((endTime.Sub(startTime).Hours() / 24) + 0.5)
	currentDay := startTime
	for i := 0; i < dayCount; i++ {
		view.Days = append(view.Days, ViewDay{
			DayString:     currentDay.Format("2006-01-02"),
			Announcements: []data.PlannerAnnouncement{},
			Events:        []data.Event{},
		})

		currentDay = currentDay.AddDate(0, 0, 1)
	}

	// get plain events
	plainEventRows, err := db.Query(
		"SELECT calendar_events.id, calendar_events.name, calendar_events.`start`, calendar_events.`end`, calendar_events.`desc`, calendar_events.userId, calendar_event_rules.id, calendar_event_rules.eventId, calendar_event_rules.frequency, calendar_event_rules.interval, calendar_event_rules.byDay, calendar_event_rules.byMonthDay, calendar_event_rules.byMonth, calendar_event_rules.until FROM calendar_events "+
			"LEFT JOIN calendar_event_rules ON calendar_events.id = calendar_event_rules.eventId "+
			"WHERE calendar_events.userId = ? AND ((calendar_events.`end` >= ? AND calendar_events.`start` <= ?) OR calendar_event_rules.frequency IS NOT NULL)",
		user.ID, startTime.Unix(), endTime.Unix(),
	)
	if err != nil {
		return View{}, err
	}
	defer plainEventRows.Close()

	for plainEventRows.Next() {
		event := data.Event{
			Tags:   map[data.EventTagType]interface{}{},
			Source: -1,
		}
		desc := ""
		recurRule := data.RecurRule{
			ID: -1,
		}
		plainEventRows.Scan(
			&event.ID, &event.Name, &event.Start, &event.End, &desc, &event.UserID,
			&recurRule.ID, &recurRule.EventID, &recurRule.Frequency, &recurRule.Interval, &recurRule.ByDayString, &recurRule.ByMonthDay, &recurRule.ByMonth, &recurRule.UntilString,
		)
		event.Tags[data.EventTagDescription] = desc
		if recurRule.ID != -1 {
			event.RecurRule = &recurRule

			if event.RecurRule.UntilString == "2099-12-12" {
				// just a placeholder value for mysql, ignore it
				event.RecurRule.UntilString = ""
			} else {
				event.RecurRule.Until, err = time.Parse("2006-01-02", event.RecurRule.UntilString)
				if err != nil {
					return View{}, err
				}
			}
		}

		eventTimes := event.CalculateTimes(endTime)

		for _, eventTime := range eventTimes {
			dayOffset := int(math.Floor(eventTime.Sub(startTime).Hours() / 24))

			if dayOffset < 0 || dayOffset > len(view.Days)-1 {
				continue
			}

			view.Days[dayOffset].Events = append(view.Days[dayOffset].Events, event)
		}
	}

	// get homework events
	hwEventRows, err := db.Query("SELECT calendar_hwevents.id, homework.id, homework.name, homework.`due`, homework.`desc`, homework.`complete`, homework.classId, homework.userId, calendar_hwevents.`start`, calendar_hwevents.`end`, calendar_hwevents.userId FROM calendar_hwevents INNER JOIN homework ON calendar_hwevents.homeworkId = homework.id WHERE calendar_hwevents.userId = ? AND (calendar_hwevents.`end` >= ? AND calendar_hwevents.`start` <= ?)", user.ID, startTime.Unix(), endTime.Unix())
	if err != nil {
		return View{}, err
	}
	defer hwEventRows.Close()

	for hwEventRows.Next() {
		event := data.Event{
			Tags:   map[data.EventTagType]interface{}{},
			Source: -1,
		}
		homework := data.Homework{}
		hwEventRows.Scan(&event.ID, &homework.ID, &homework.Name, &homework.Due, &homework.Desc, &homework.Complete, &homework.ClassID, &homework.UserID, &event.Start, &event.End, &event.UserID)
		event.Tags[data.EventTagHomework] = homework
		event.Name = homework.Name

		eventStartTime := time.Unix(int64(event.Start), 0)
		dayOffset := int(math.Floor(eventStartTime.Sub(startTime).Hours() / 24))

		if dayOffset < 0 || dayOffset > len(view.Days)-1 {
			continue
		}

		view.Days[dayOffset].Events = append(view.Days[dayOffset].Events, event)
	}

	// handle calendar providers
	for providerIndex, provider := range providers {
		// add them to the list
		view.Providers = append(view.Providers, ProviderInfo{
			Name: provider.Name(),
		})

		// get data
		providerData, err := provider.GetData(db, user, location, startTime, endTime, data.ProviderDataAll)
		if err != nil {
			return View{}, err
		}

		// add announcements
		for _, announcement := range providerData.Announcements {
			announcementDate, err := time.Parse("2006-01-02", announcement.Date)
			if err != nil {
				return View{}, err
			}
			dayOffset := int(math.Ceil(announcementDate.Sub(startTime).Hours() / 24))

			if dayOffset < 0 || dayOffset > len(view.Days)-1 {
				continue
			}

			view.Days[dayOffset].Announcements = append(view.Days[dayOffset].Announcements, announcement)
		}

		// add events
		for _, event := range providerData.Events {
			eventDate := time.Unix(int64(event.Start), 0)
			dayOffset := int(math.Floor(eventDate.Sub(startTime).Hours() / 24))

			if dayOffset < 0 || dayOffset > len(view.Days)-1 {
				continue
			}

			event.Source = providerIndex

			view.Days[dayOffset].Events = append(view.Days[dayOffset].Events, event)
		}
	}

	return view, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"database/sql"
	"errors"
	"fmt"
	"github.com/cactus/go-statsd-client/statsd"
	"github.com/go-sql-driver/mysql"
	"github.com/stvp/go-toml-config"
	"io"
	"net"
	"os"
	"strings"
	"sync"
	"time"
)

func dieIfError(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
		os.Exit(1)
	}
}

type metricSpec struct {
	metric_id string
	tags      map[string]string
}

type Stats struct {
	mu                           sync.Mutex
	in_conns_current             int
	in_conns_broken_total        int64
	in_metrics_proto2_bad_total  int64
	in_metrics_proto2_good_total int64
	in_metrics_proto1_total      int64
	already_tracked              map[string]bool
}

func NewStats() *Stats {
	return &Stats{already_tracked: make(map[string]bool)}
}

func main() {
	var (
		mysql_user            = config.String("mysql.user", "carbon_tagger")
		mysql_password        = config.String("mysql.password", "carbon_tagger_pw")
		mysql_address         = config.String("mysql.address", "undefined")
		mysql_dbname          = config.String("mysql.dbname", "carbon_tagger")
		mysql_max_pending     = config.Int("mysql.max_pending", 1000000)
		in_port               = config.Int("in.port", 2005)
		out_host              = config.String("out.host", "localhost")
		out_port              = config.Int("out.port", 2003)
		statsd_address        = config.String("statsd.address", "localhost:8125")
		statsd_id             = config.String("statsd.id", "myhost")
		statsd_flush_interval = config.Int("statsd.flush_interval", 2003)
	)
	err := config.Parse("carbon-tagger.conf")
	dieIfError(err)
	dsn := fmt.Sprintf("%s:%s@%s/%s?charset=utf8", *mysql_user, *mysql_password, *mysql_address, *mysql_dbname)

	// connect to database to store tags
	db, err := sql.Open("mysql", dsn)
	dieIfError(err)
	defer db.Close()
	// Open doesn't open a connection. Validate DSN data:
	err = db.Ping()
	db.SetMaxIdleConns(80)
	dieIfError(err)

	// listen for incoming metrics
	addr, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf(":%d", *in_port))
	dieIfError(err)
	listener, err := net.ListenTCP("tcp", addr)
	dieIfError(err)
	defer listener.Close()

	// connect to outgoing carbon daemon (carbon-relay, carbon-cache, ..)
	// TODO implement fwd'ing, toggle on/off
	conn_out, err := net.Dial("tcp", fmt.Sprintf("%s:%d", *out_host, *out_port))
	dieIfError(err)

	// we can queue up to max_pending: if more than that are pending flush to mysql, start blocking..
	metrics_to_track := make(chan metricSpec, *mysql_max_pending)

	// statsd client
	s, err := statsd.Dial(*statsd_address, fmt.Sprintf("carbon-tagger.%s", *statsd_id))
	dieIfError(err)
	defer s.Close()

	stats := NewStats()

	submitStats := func(stats *Stats, s *statsd.Client) {
		for {
			stats.mu.Lock()
			s.Gauge("in.conns.current", int64(stats.in_conns_current), 1)
			s.Gauge("in.conns.broken.total", stats.in_conns_broken_total, 1)
			s.Gauge("in.metrics.proto2.bad.total", stats.in_metrics_proto2_bad_total, 1)
			s.Gauge("in.metrics.proto2.good.total", stats.in_metrics_proto2_good_total, 1)
			s.Gauge("in.metrics.proto1.total", stats.in_metrics_proto1_total, 1)
			s.Gauge("metrics.proto2.count-pending-tracking", int64(len(metrics_to_track)), 1)
			s.Gauge("metrics.proto2.count-already-tracked", int64(len(stats.already_tracked)), 1)
			stats.mu.Unlock()
			time.Sleep(time.Duration(*statsd_flush_interval) * time.Second) // todo: run the stats submissions exactly every X seconds
		}
	}
	go submitStats(stats, s)

	lines_to_forward := make(chan []byte)
	// 1 forwarding worker should suffice?
	go forwardLines(conn_out, lines_to_forward, stats, s)

	// for now, only 1 sql persist worker...
	go trackMetrics(db, metrics_to_track, stats)

	fmt.Printf("carbon-tagger %s ready to serve on %d\n", *statsd_id, *in_port)
	for {
		// would be nice to have a metric showing highest amount of connections seen per interval
		conn_in, err := listener.Accept()
		dieIfError(err)
		go handleClient(conn_in, metrics_to_track, lines_to_forward, stats)
	}
}

func parseTagBasedMetric(metric_line string) (metric metricSpec, err error) {
	// metric_spec value unix_timestamp
	elements := strings.Split(metric_line, " ")
	metric_id := ""
	if len(elements) != 3 {
		return metricSpec{metric_id, nil}, errors.New(fmt.Sprintf("metric doesn't contain exactly 3 nodes: %s", metric_line))
	}
	metric_id = elements[0]
	nodes := strings.Split(metric_id, ".")
	tags := make(map[string]string)
	// TODO make sure incoming tags are sorted
	for _, node := range nodes {
		tag := strings.Split(node, "=")
		if len(tag) != 2 {
			return metricSpec{metric_id, nil}, errors.New("bad metric spec: each node must be a 'tag_k=tag_v' pair")
		}
		if tag[0] == "" || tag[1] == "" {
			return metricSpec{metric_id, nil}, errors.New("bad metric spec: tag_k and tag_v must be non-empty strings")
		}

		tags[tag[0]] = tag[1]
	}
	if _, ok := tags["unit"]; !ok {
		return metricSpec{metric_id, nil}, errors.New("bad metric spec: unit tag (mandatory) not specified")
	}
	if len(tags) < 2 {
		return metricSpec{metric_id, nil}, errors.New("bad metric spec: must have at least one tag_k/tag_v pair beyond unit")
	}
	return metricSpec{metric_id, tags}, nil
}

func trackMetrics(db *sql.DB, metrics_to_track chan metricSpec, stats *Stats) {
	statement_insert_tag, err := db.Prepare("INSERT INTO tags (tag_key, tag_val) VALUES( ?, ? )")
	dieIfError(err)
	statement_select_tag, err := db.Prepare("SELECT tag_id FROM tags WHERE tag_key=? AND tag_val=?")
	dieIfError(err)
	statement_insert_metric, err := db.Prepare("INSERT INTO metrics VALUES( ? )")
	dieIfError(err)
	statement_insert_link, err := db.Prepare("INSERT INTO metrics_tags VALUES( ?, ? )")
	dieIfError(err)
	for {
		metric := <-metrics_to_track
		// this is racey but that's not so bad, processing the same metric and sending it to mysql twice is not so bad.
		stats.mu.Lock()
		_, ok := stats.already_tracked[metric.metric_id]
		stats.mu.Unlock()
		if ok {
			continue
		}
		// TODO this should go in a transaction. for now we first store all tag_k=tag_v pairs (if they are orphans, it's not so bad)
		// then add the metric, than the coupling between metric and tags. <-- all this should def. be in a transaction
		tag_ids := make([]int64, 0) //maybe set cap to len(tags) or so
		for tag_k, tag_v := range metric.tags {
			res, err := statement_insert_tag.Exec(tag_k, tag_v)
			if err != nil {
				if err.(*mysql.MySQLError).Number == 1062 { // Error 1062: Duplicate entry
					var id int64
					err := statement_select_tag.QueryRow(tag_k, tag_v).Scan(&id)
					if err != nil {
						fmt.Fprintf(os.Stderr, "Can't lookup the id of tag %s=%s: %s\n", tag_k, tag_v, err.Error())
						return
					}
					tag_ids = append(tag_ids, id)
				} else {
					fmt.Fprintf(os.Stderr, "can't store tag %s=%s: %s\n", tag_k, tag_v, err.Error())
					return
				}
			} else {
				id, err := res.LastInsertId()
				if err != nil {
					fmt.Fprintf(os.Stderr, "can't get id for just inserted tag %s=%s: %s\n", tag_k, tag_v, err.Error())
					return
				} else {
					tag_ids = append(tag_ids, id)
				}
			}
		}
		_, err = statement_insert_metric.Exec(metric.metric_id)
		if err != nil {
			if err.(*mysql.MySQLError).Number != 1062 { // Error 1062: Duplicate entry 'unit=f.b=aeu' for key 'PRIMARY'
				fmt.Fprintf(os.Stderr, "can't store metric %s:%s\n", metric.metric_id, err.Error())
				return
			}
		} else {
			// the metric is newly inserted.. we still have to couple it to the tags.
			// so we assume if the metric already existed, we don't need to do this anymore. which is not very accurate since we don't use transactions yet
			for _, tag_id := range tag_ids {
				_, err = statement_insert_link.Exec(metric.metric_id, tag_id)
				if err != nil {
					fmt.Fprintf(os.Stderr, "can't link metric %s to tag:%s\n", metric.metric_id, err.Error())
					return
				}
			}
		}
		stats.mu.Lock()
		stats.already_tracked[metric.metric_id] = true
		stats.mu.Unlock()
	}
}

func forwardLines(conn_out net.Conn, lines_to_forward chan []byte, stats *Stats, s *statsd.Client) {
	out_lines_error := int64(0)
	out_lines_ok := int64(0)
	for {
		line := <-lines_to_forward
		_, err := conn_out.Write(line)
		if err != nil {
			out_lines_error += 1
			s.Gauge("out.lines.error", out_lines_error, 1)
		} else {
			out_lines_ok += 1
			s.Gauge("out.lines.ok", out_lines_ok, 1)
		}
	}
}

func handleClient(conn_in net.Conn, metrics_to_track chan metricSpec, lines_to_forward chan []byte, stats *Stats) {
	stats.mu.Lock()
	stats.in_conns_current += 1
	stats.mu.Unlock()
	defer conn_in.Close()
	reader := bufio.NewReader(conn_in)
	for {
		// TODO handle isPrefix cases (means we should merge this read with the next one in a different packet, i think)
		buf, err := reader.ReadBytes('\n')
		if err != nil {
			str := strings.TrimSpace(string(buf))
			if err != io.EOF {
				fmt.Printf("connection closed uncleanly/broken: %s  -- line read: '%s'\n", err.Error(), str)
				stats.mu.Lock()
				stats.in_conns_broken_total += 1
				stats.mu.Unlock()
			} else {
				fmt.Printf("reached EOF. line read: '%s'\n", str)
			}
			// todo handle incomplete eads
			fmt.Printf("WARN incomplete read, possible neglected metric. line read: '%s'\n", str)
			stats.mu.Lock()
			stats.in_conns_current -= 1
			stats.mu.Unlock()
			return
		}
		str := string(buf)
		if strings.ContainsAny(str, "=") {
			str = strings.TrimSpace(str)
			metric, err := parseTagBasedMetric(str)
			if err != nil {
				stats.mu.Lock()
				stats.in_metrics_proto2_bad_total += 1
				stats.mu.Unlock()
			} else {
				stats.mu.Lock()
				stats.in_metrics_proto2_good_total += 1
				stats.mu.Unlock()
				metrics_to_track <- metric
				lines_to_forward <- buf
			}
		} else {
			stats.mu.Lock()
			stats.in_metrics_proto1_total += 1
			stats.mu.Unlock()
			lines_to_forward <- buf
		}
	}
	stats.mu.Lock()
	stats.in_conns_current -= 1
	stats.mu.Unlock()
}
<commit_msg>only warn when non-zero strings are dropped, ignore regular EOF's<commit_after>package main

import (
	"bufio"
	"database/sql"
	"errors"
	"fmt"
	"github.com/cactus/go-statsd-client/statsd"
	"github.com/go-sql-driver/mysql"
	"github.com/stvp/go-toml-config"
	"io"
	"net"
	"os"
	"strings"
	"sync"
	"time"
)

func dieIfError(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
		os.Exit(1)
	}
}

type metricSpec struct {
	metric_id string
	tags      map[string]string
}

type Stats struct {
	mu                           sync.Mutex
	in_conns_current             int
	in_conns_broken_total        int64
	in_metrics_proto2_bad_total  int64
	in_metrics_proto2_good_total int64
	in_metrics_proto1_total      int64
	already_tracked              map[string]bool
}

func NewStats() *Stats {
	return &Stats{already_tracked: make(map[string]bool)}
}

func main() {
	var (
		mysql_user            = config.String("mysql.user", "carbon_tagger")
		mysql_password        = config.String("mysql.password", "carbon_tagger_pw")
		mysql_address         = config.String("mysql.address", "undefined")
		mysql_dbname          = config.String("mysql.dbname", "carbon_tagger")
		mysql_max_pending     = config.Int("mysql.max_pending", 1000000)
		in_port               = config.Int("in.port", 2005)
		out_host              = config.String("out.host", "localhost")
		out_port              = config.Int("out.port", 2003)
		statsd_address        = config.String("statsd.address", "localhost:8125")
		statsd_id             = config.String("statsd.id", "myhost")
		statsd_flush_interval = config.Int("statsd.flush_interval", 2003)
	)
	err := config.Parse("carbon-tagger.conf")
	dieIfError(err)
	dsn := fmt.Sprintf("%s:%s@%s/%s?charset=utf8", *mysql_user, *mysql_password, *mysql_address, *mysql_dbname)

	// connect to database to store tags
	db, err := sql.Open("mysql", dsn)
	dieIfError(err)
	defer db.Close()
	// Open doesn't open a connection. Validate DSN data:
	err = db.Ping()
	db.SetMaxIdleConns(80)
	dieIfError(err)

	// listen for incoming metrics
	addr, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf(":%d", *in_port))
	dieIfError(err)
	listener, err := net.ListenTCP("tcp", addr)
	dieIfError(err)
	defer listener.Close()

	// connect to outgoing carbon daemon (carbon-relay, carbon-cache, ..)
	// TODO implement fwd'ing, toggle on/off
	conn_out, err := net.Dial("tcp", fmt.Sprintf("%s:%d", *out_host, *out_port))
	dieIfError(err)

	// we can queue up to max_pending: if more than that are pending flush to mysql, start blocking..
	metrics_to_track := make(chan metricSpec, *mysql_max_pending)

	// statsd client
	s, err := statsd.Dial(*statsd_address, fmt.Sprintf("carbon-tagger.%s", *statsd_id))
	dieIfError(err)
	defer s.Close()

	stats := NewStats()

	submitStats := func(stats *Stats, s *statsd.Client) {
		for {
			stats.mu.Lock()
			s.Gauge("in.conns.current", int64(stats.in_conns_current), 1)
			s.Gauge("in.conns.broken.total", stats.in_conns_broken_total, 1)
			s.Gauge("in.metrics.proto2.bad.total", stats.in_metrics_proto2_bad_total, 1)
			s.Gauge("in.metrics.proto2.good.total", stats.in_metrics_proto2_good_total, 1)
			s.Gauge("in.metrics.proto1.total", stats.in_metrics_proto1_total, 1)
			s.Gauge("metrics.proto2.count-pending-tracking", int64(len(metrics_to_track)), 1)
			s.Gauge("metrics.proto2.count-already-tracked", int64(len(stats.already_tracked)), 1)
			stats.mu.Unlock()
			time.Sleep(time.Duration(*statsd_flush_interval) * time.Second) // todo: run the stats submissions exactly every X seconds
		}
	}
	go submitStats(stats, s)

	lines_to_forward := make(chan []byte)
	// 1 forwarding worker should suffice?
	go forwardLines(conn_out, lines_to_forward, stats, s)

	// for now, only 1 sql persist worker...
	go trackMetrics(db, metrics_to_track, stats)

	fmt.Printf("carbon-tagger %s ready to serve on %d\n", *statsd_id, *in_port)
	for {
		// would be nice to have a metric showing highest amount of connections seen per interval
		conn_in, err := listener.Accept()
		dieIfError(err)
		go handleClient(conn_in, metrics_to_track, lines_to_forward, stats)
	}
}

func parseTagBasedMetric(metric_line string) (metric metricSpec, err error) {
	// metric_spec value unix_timestamp
	elements := strings.Split(metric_line, " ")
	metric_id := ""
	if len(elements) != 3 {
		return metricSpec{metric_id, nil}, errors.New(fmt.Sprintf("metric doesn't contain exactly 3 nodes: %s", metric_line))
	}
	metric_id = elements[0]
	nodes := strings.Split(metric_id, ".")
	tags := make(map[string]string)
	// TODO make sure incoming tags are sorted
	for _, node := range nodes {
		tag := strings.Split(node, "=")
		if len(tag) != 2 {
			return metricSpec{metric_id, nil}, errors.New("bad metric spec: each node must be a 'tag_k=tag_v' pair")
		}
		if tag[0] == "" || tag[1] == "" {
			return metricSpec{metric_id, nil}, errors.New("bad metric spec: tag_k and tag_v must be non-empty strings")
		}

		tags[tag[0]] = tag[1]
	}
	if _, ok := tags["unit"]; !ok {
		return metricSpec{metric_id, nil}, errors.New("bad metric spec: unit tag (mandatory) not specified")
	}
	if len(tags) < 2 {
		return metricSpec{metric_id, nil}, errors.New("bad metric spec: must have at least one tag_k/tag_v pair beyond unit")
	}
	return metricSpec{metric_id, tags}, nil
}

func trackMetrics(db *sql.DB, metrics_to_track chan metricSpec, stats *Stats) {
	statement_insert_tag, err := db.Prepare("INSERT INTO tags (tag_key, tag_val) VALUES( ?, ? )")
	dieIfError(err)
	statement_select_tag, err := db.Prepare("SELECT tag_id FROM tags WHERE tag_key=? AND tag_val=?")
	dieIfError(err)
	statement_insert_metric, err := db.Prepare("INSERT INTO metrics VALUES( ? )")
	dieIfError(err)
	statement_insert_link, err := db.Prepare("INSERT INTO metrics_tags VALUES( ?, ? )")
	dieIfError(err)
	for {
		metric := <-metrics_to_track
		// this is racey but that's not so bad, processing the same metric and sending it to mysql twice is not so bad.
		stats.mu.Lock()
		_, ok := stats.already_tracked[metric.metric_id]
		stats.mu.Unlock()
		if ok {
			continue
		}
		// TODO this should go in a transaction. for now we first store all tag_k=tag_v pairs (if they are orphans, it's not so bad)
		// then add the metric, than the coupling between metric and tags. <-- all this should def. be in a transaction
		tag_ids := make([]int64, 0) //maybe set cap to len(tags) or so
		for tag_k, tag_v := range metric.tags {
			res, err := statement_insert_tag.Exec(tag_k, tag_v)
			if err != nil {
				if err.(*mysql.MySQLError).Number == 1062 { // Error 1062: Duplicate entry
					var id int64
					err := statement_select_tag.QueryRow(tag_k, tag_v).Scan(&id)
					if err != nil {
						fmt.Fprintf(os.Stderr, "Can't lookup the id of tag %s=%s: %s\n", tag_k, tag_v, err.Error())
						return
					}
					tag_ids = append(tag_ids, id)
				} else {
					fmt.Fprintf(os.Stderr, "can't store tag %s=%s: %s\n", tag_k, tag_v, err.Error())
					return
				}
			} else {
				id, err := res.LastInsertId()
				if err != nil {
					fmt.Fprintf(os.Stderr, "can't get id for just inserted tag %s=%s: %s\n", tag_k, tag_v, err.Error())
					return
				} else {
					tag_ids = append(tag_ids, id)
				}
			}
		}
		_, err = statement_insert_metric.Exec(metric.metric_id)
		if err != nil {
			if err.(*mysql.MySQLError).Number != 1062 { // Error 1062: Duplicate entry 'unit=f.b=aeu' for key 'PRIMARY'
				fmt.Fprintf(os.Stderr, "can't store metric %s:%s\n", metric.metric_id, err.Error())
				return
			}
		} else {
			// the metric is newly inserted.. we still have to couple it to the tags.
			// so we assume if the metric already existed, we don't need to do this anymore. which is not very accurate since we don't use transactions yet
			for _, tag_id := range tag_ids {
				_, err = statement_insert_link.Exec(metric.metric_id, tag_id)
				if err != nil {
					fmt.Fprintf(os.Stderr, "can't link metric %s to tag:%s\n", metric.metric_id, err.Error())
					return
				}
			}
		}
		stats.mu.Lock()
		stats.already_tracked[metric.metric_id] = true
		stats.mu.Unlock()
	}
}

func forwardLines(conn_out net.Conn, lines_to_forward chan []byte, stats *Stats, s *statsd.Client) {
	out_lines_error := int64(0)
	out_lines_ok := int64(0)
	for {
		line := <-lines_to_forward
		_, err := conn_out.Write(line)
		if err != nil {
			out_lines_error += 1
			s.Gauge("out.lines.error", out_lines_error, 1)
		} else {
			out_lines_ok += 1
			s.Gauge("out.lines.ok", out_lines_ok, 1)
		}
	}
}

func handleClient(conn_in net.Conn, metrics_to_track chan metricSpec, lines_to_forward chan []byte, stats *Stats) {
	stats.mu.Lock()
	stats.in_conns_current += 1
	stats.mu.Unlock()
	defer conn_in.Close()
	reader := bufio.NewReader(conn_in)
	for {
		// TODO handle isPrefix cases (means we should merge this read with the next one in a different packet, i think)
		buf, err := reader.ReadBytes('\n')
		if err != nil {
			str := strings.TrimSpace(string(buf))
			if err != io.EOF {
				fmt.Printf("WARN connection closed uncleanly/broken: %s\n", err.Error())
				stats.mu.Lock()
				stats.in_conns_broken_total += 1
				stats.mu.Unlock()
			}
			if len(str) > 0 {
				// todo handle incomplete reads
				fmt.Printf("WARN incomplete read, line read: '%s'. neglecting line because connection closed because of %s\n", str, err.Error())
			}
			stats.mu.Lock()
			stats.in_conns_current -= 1
			stats.mu.Unlock()
			return
		}
		str := string(buf)
		if strings.ContainsAny(str, "=") {
			str = strings.TrimSpace(str)
			metric, err := parseTagBasedMetric(str)
			if err != nil {
				stats.mu.Lock()
				stats.in_metrics_proto2_bad_total += 1
				stats.mu.Unlock()
			} else {
				stats.mu.Lock()
				stats.in_metrics_proto2_good_total += 1
				stats.mu.Unlock()
				metrics_to_track <- metric
				lines_to_forward <- buf
			}
		} else {
			stats.mu.Lock()
			stats.in_metrics_proto1_total += 1
			stats.mu.Unlock()
			lines_to_forward <- buf
		}
	}
	stats.mu.Lock()
	stats.in_conns_current -= 1
	stats.mu.Unlock()
}
<|endoftext|>


<commit_before>package cli

import (
	"encoding/json"
	"fmt"
	"os"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/go-utils/colorstring"
	"github.com/bitrise-io/stepman/models"
	"github.com/bitrise-io/stepman/stepman"
	"github.com/codegangsta/cli"
)

func registerFatal(errorMsg, format string) {
	msg := map[string]string{
		"error": errorMsg,
	}

	if format == OutputFormatRaw {
		log.Fatal(msg["error"])
	} else {
		bytes, err := json.Marshal(msg)
		if err != nil {
			log.Fatalf("Faild to parse error model, err: %s", err)
		}

		fmt.Println(string(bytes))
		os.Exit(1)
	}
}

func collections(c *cli.Context) {
	format := c.String(FormatKey)
	if format == "" {
		format = OutputFormatRaw
	} else if !(format == OutputFormatRaw || format == OutputFormatJSON) {
		registerFatal(fmt.Sprintf("Invalid format: %s", format), OutputFormatJSON)
	}

	stepLibURIs := stepman.GetAllStepCollectionPath()

	switch format {
	case OutputFormatRaw:
		for _, stepLibURI := range stepLibURIs {
			fmt.Println(colorstring.Blue(stepLibURI))
		}
		break
	case OutputFormatJSON:
		stepLibs := models.StepLibURIsModel{}
		for _, stepLibURI := range stepLibURIs {
			stepLibs.StepLibURIs = append(stepLibs.StepLibURIs, models.StepLibURIModel{URI: stepLibURI})
		}
		bytes, err := json.Marshal(stepLibs)
		if err != nil {
			registerFatal(err.Error(), format)
		}
		fmt.Println(string(bytes))
		break
	default:
		registerFatal(fmt.Sprintf("Invalid format: %s", format), OutputFormatJSON)
	}
}
<commit_msg>FIX: typo Faild<commit_after>package cli

import (
	"encoding/json"
	"fmt"
	"os"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/go-utils/colorstring"
	"github.com/bitrise-io/stepman/models"
	"github.com/bitrise-io/stepman/stepman"
	"github.com/codegangsta/cli"
)

func registerFatal(errorMsg, format string) {
	msg := map[string]string{
		"error": errorMsg,
	}

	if format == OutputFormatRaw {
		log.Fatal(msg["error"])
	} else {
		bytes, err := json.Marshal(msg)
		if err != nil {
			log.Fatalf("Failed to parse error model, err: %s", err)
		}

		fmt.Println(string(bytes))
		os.Exit(1)
	}
}

func collections(c *cli.Context) {
	format := c.String(FormatKey)
	if format == "" {
		format = OutputFormatRaw
	} else if !(format == OutputFormatRaw || format == OutputFormatJSON) {
		registerFatal(fmt.Sprintf("Invalid format: %s", format), OutputFormatJSON)
	}

	stepLibURIs := stepman.GetAllStepCollectionPath()

	switch format {
	case OutputFormatRaw:
		for _, stepLibURI := range stepLibURIs {
			fmt.Println(colorstring.Blue(stepLibURI))
		}
		break
	case OutputFormatJSON:
		stepLibs := models.StepLibURIsModel{}
		for _, stepLibURI := range stepLibURIs {
			stepLibs.StepLibURIs = append(stepLibs.StepLibURIs, models.StepLibURIModel{URI: stepLibURI})
		}
		bytes, err := json.Marshal(stepLibs)
		if err != nil {
			registerFatal(err.Error(), format)
		}
		fmt.Println(string(bytes))
		break
	default:
		registerFatal(fmt.Sprintf("Invalid format: %s", format), OutputFormatJSON)
	}
}
<|endoftext|>


<commit_before>package koding

import (
	"fmt"
	"time"

	"koding/kites/kloud/kloud"
	"koding/kites/kloud/machinestate"
	"koding/kites/kloud/protocol"

	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

// Get returns the meta of the associated credential with the given machine id.
func (p *Provider) Get(id string) (*protocol.Machine, error) {
	if !bson.IsObjectIdHex(id) {
		return nil, fmt.Errorf("Invalid machine id: %q", id)
	}

	// let's first check if the id exists, because we are going to use
	// findAndModify() and it would be difficult to distinguish if the id
	// really doesn't exist or if there is an assignee which is a different
	// thing. (Because findAndModify() also returns "not found" for the case
	// where the id exist but someone else is the assignee).
	machine := &MachineDocument{}
	if err := p.Session.Run("jMachines", func(c *mgo.Collection) error {
		return c.FindId(bson.ObjectIdHex(id)).One(&machine)
	}); err == mgo.ErrNotFound {
		return nil, kloud.NewError(kloud.ErrMachineNotFound)
	}

	// as a koding provider, the credential is just the username so we can use
	// it directly, otherwise we need to make an additional lookup via
	// jAccounts with machine.Users.Id..
	username := machine.Credential

	// do not check for admin users, or if test mode is enabled
	if !IsAdmin(username) {
		// check for user permissions
		if err := p.checkUser(username, machine.Users); err != nil && !p.Test {
			return nil, err
		}
	}

	credential := p.GetCredential(machine.Credential)

	m := &protocol.Machine{
		Id:          id,
		Username:    machine.Credential, // contains the username for koding provider
		Provider:    machine.Provider,
		Builder:     machine.Meta,
		Credential:  credential.Meta,
		State:       machine.State(),
		IpAddress:   machine.IpAddress,
		QueryString: machine.QueryString,
	}
	m.Domain.Name = machine.Domain

	return m, nil
}

func (p *Provider) GetCredential(publicKey string) *Credential {
	credential := &Credential{}
	// we neglect errors because credential is optional
	p.Session.Run("jCredentialDatas", func(c *mgo.Collection) error {
		return c.Find(bson.M{"publicKey": publicKey}).One(credential)
	})

	return credential
}

func (p *Provider) Update(id string, s *kloud.StorageData) error {
	p.Log.Debug("[%s] storage update request of type '%s' data: %v", id, s.Type, s.Data)

	data := map[string]interface{}{}

	switch s.Type {
	case "build":
		data["queryString"] = s.Data["queryString"]
		data["ipAddress"] = s.Data["ipAddress"]
		data["domain"] = s.Data["domainName"]
		data["meta.instanceId"] = s.Data["instanceId"]
		data["meta.instanceName"] = s.Data["instanceName"]
	case "reinit":
		data["queryString"] = s.Data["queryString"]
		data["ipAddress"] = s.Data["ipAddress"]
		data["domain"] = s.Data["domainName"]
		data["meta.instanceId"] = s.Data["instanceId"]
		data["meta.instanceName"] = s.Data["instanceName"]
	case "info":
		data["meta.instanceName"] = s.Data["instanceName"]
	case "start":
		data["ipAddress"] = s.Data["ipAddress"]
		data["domain"] = s.Data["domainName"]
		data["meta.instanceId"] = s.Data["instanceId"]
	case "stop":
		data["ipAddress"] = s.Data["ipAddress"]
	case "domain":
		data["domain"] = s.Data["domainName"]
	case "resize":
		data["ipAddress"] = s.Data["ipAddress"]
	default:
		return fmt.Errorf("Storage type unknown: '%s'", s.Type)
	}

	return p.Session.Run("jMachines", func(c *mgo.Collection) error {
		return c.UpdateId(
			bson.ObjectIdHex(id),
			bson.M{"$set": data},
		)
	})
}

func (p *Provider) UpdateState(id string, state machinestate.State) error {
	p.Log.Info("[%s] updating state to '%v'", id, state)
	return p.Session.Run("jMachines", func(c *mgo.Collection) error {
		return c.Update(
			bson.M{
				"_id": bson.ObjectIdHex(id),
			},
			bson.M{
				"$set": bson.M{
					"status.state":      state.String(),
					"status.modifiedAt": time.Now().UTC(),
				},
			},
		)
	})
}
<commit_msg>kloud: Remove code duplication in switch case block.<commit_after>package koding

import (
	"fmt"
	"time"

	"koding/kites/kloud/kloud"
	"koding/kites/kloud/machinestate"
	"koding/kites/kloud/protocol"

	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

// Get returns the meta of the associated credential with the given machine id.
func (p *Provider) Get(id string) (*protocol.Machine, error) {
	if !bson.IsObjectIdHex(id) {
		return nil, fmt.Errorf("Invalid machine id: %q", id)
	}

	// let's first check if the id exists, because we are going to use
	// findAndModify() and it would be difficult to distinguish if the id
	// really doesn't exist or if there is an assignee which is a different
	// thing. (Because findAndModify() also returns "not found" for the case
	// where the id exist but someone else is the assignee).
	machine := &MachineDocument{}
	if err := p.Session.Run("jMachines", func(c *mgo.Collection) error {
		return c.FindId(bson.ObjectIdHex(id)).One(&machine)
	}); err == mgo.ErrNotFound {
		return nil, kloud.NewError(kloud.ErrMachineNotFound)
	}

	// as a koding provider, the credential is just the username so we can use
	// it directly, otherwise we need to make an additional lookup via
	// jAccounts with machine.Users.Id..
	username := machine.Credential

	// do not check for admin users, or if test mode is enabled
	if !IsAdmin(username) {
		// check for user permissions
		if err := p.checkUser(username, machine.Users); err != nil && !p.Test {
			return nil, err
		}
	}

	credential := p.GetCredential(machine.Credential)

	m := &protocol.Machine{
		Id:          id,
		Username:    machine.Credential, // contains the username for koding provider
		Provider:    machine.Provider,
		Builder:     machine.Meta,
		Credential:  credential.Meta,
		State:       machine.State(),
		IpAddress:   machine.IpAddress,
		QueryString: machine.QueryString,
	}
	m.Domain.Name = machine.Domain

	return m, nil
}

func (p *Provider) GetCredential(publicKey string) *Credential {
	credential := &Credential{}
	// we neglect errors because credential is optional
	p.Session.Run("jCredentialDatas", func(c *mgo.Collection) error {
		return c.Find(bson.M{"publicKey": publicKey}).One(credential)
	})

	return credential
}

func (p *Provider) Update(id string, s *kloud.StorageData) error {
	p.Log.Debug("[%s] storage update request of type '%s' data: %v", id, s.Type, s.Data)

	data := map[string]interface{}{}

	switch s.Type {
	case "build", "reinit":
		data["queryString"] = s.Data["queryString"]
		data["ipAddress"] = s.Data["ipAddress"]
		data["domain"] = s.Data["domainName"]
		data["meta.instanceId"] = s.Data["instanceId"]
		data["meta.instanceName"] = s.Data["instanceName"]
	case "info":
		data["meta.instanceName"] = s.Data["instanceName"]
	case "start":
		data["ipAddress"] = s.Data["ipAddress"]
		data["domain"] = s.Data["domainName"]
		data["meta.instanceId"] = s.Data["instanceId"]
	case "stop":
		data["ipAddress"] = s.Data["ipAddress"]
	case "domain":
		data["domain"] = s.Data["domainName"]
	case "resize":
		data["ipAddress"] = s.Data["ipAddress"]
	default:
		return fmt.Errorf("Storage type unknown: '%s'", s.Type)
	}

	return p.Session.Run("jMachines", func(c *mgo.Collection) error {
		return c.UpdateId(
			bson.ObjectIdHex(id),
			bson.M{"$set": data},
		)
	})
}

func (p *Provider) UpdateState(id string, state machinestate.State) error {
	p.Log.Info("[%s] updating state to '%v'", id, state)
	return p.Session.Run("jMachines", func(c *mgo.Collection) error {
		return c.Update(
			bson.M{
				"_id": bson.ObjectIdHex(id),
			},
			bson.M{
				"$set": bson.M{
					"status.state":      state.String(),
					"status.modifiedAt": time.Now().UTC(),
				},
			},
		)
	})
}
<|endoftext|>


<commit_before>package userService

import (
	"errors"
	"github.com/NyaaPantsu/nyaa/db"
	"github.com/NyaaPantsu/nyaa/model"
	formStruct "github.com/NyaaPantsu/nyaa/service/user/form"
	msg "github.com/NyaaPantsu/nyaa/util/messages"
	"github.com/NyaaPantsu/nyaa/util/modelHelper"
	"github.com/NyaaPantsu/nyaa/util/timeHelper"
	"github.com/gorilla/context"
	"github.com/gorilla/securecookie"
	"golang.org/x/crypto/bcrypt"
	"fmt"
	"net/http"
	"strconv"
	"time"
)

const (
	CookieName = "session"
	UserContextKey = "user"
	)

// If you want to keep login cookies between restarts you need to make these permanent
var cookieHandler = securecookie.New(
	securecookie.GenerateRandomKey(64),
	securecookie.GenerateRandomKey(32))

// Encoding & Decoding of the cookie value
func DecodeCookie(cookie_value string) (uint, error) {
	value := make(map[string]string)
	err := cookieHandler.Decode(CookieName, cookie_value, &value)
	if err != nil {
		return 0, err
	}
	time_int, _ := strconv.ParseInt(value["t"], 10, 0)
	if timeHelper.IsExpired(time.Unix(time_int, 0)) {
		return 0, errors.New("Cookie is expired")
	}
	ret, err := strconv.ParseUint(value["u"], 10, 0)
	return uint(ret), err
}

func EncodeCookie(user_id uint) (string, error) {
	validUntil := timeHelper.FewDaysLater(7) // 1 week
	value := map[string]string{
		"u": strconv.FormatUint(uint64(user_id), 10),
		"t": strconv.FormatInt(validUntil.Unix(), 10),
	}
	return cookieHandler.Encode(CookieName, value)
}

func ClearCookie(w http.ResponseWriter) (int, error) {
	cookie := &http.Cookie{
		Name:     CookieName,
		Value:    "",
		Path:     "/",
		HttpOnly: true,
		MaxAge:   -1,
	}
	http.SetCookie(w, cookie)
	return http.StatusOK, nil
}

// SetCookieHandler sets the authentication cookie
func SetCookieHandler(w http.ResponseWriter, r *http.Request, email string, pass string) (int, error) {
	if email == "" || pass == "" {
		return http.StatusNotFound, errors.New("No username/password entered")
	}

	var user model.User
	messages := msg.GetMessages(r)
	// search by email or username
	isValidEmail := formStruct.EmailValidation(email, messages)
	if isValidEmail {
		if db.ORM.Where("email = ?", email).First(&user).RecordNotFound() {
			return http.StatusNotFound, errors.New("User not found")
		}
	} else {
		if db.ORM.Where("username = ?", email).First(&user).RecordNotFound() {
			return http.StatusNotFound, errors.New("User not found")
		}
	}
	err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(pass))
	if err != nil {
		return http.StatusUnauthorized, errors.New("Password incorrect")
	}
	if user.IsBanned() {
		return http.StatusUnauthorized, errors.New("Account banned")
	}

	encoded, err := EncodeCookie(user.ID)
	if err != nil {
		return http.StatusInternalServerError, err
	}
	cookie := &http.Cookie{
		Name:     CookieName,
		Value:    encoded,
		Path:     "/",
		HttpOnly: true,
	}
	http.SetCookie(w, cookie)
	// also set response header for convenience
	w.Header().Set("X-Auth-Token", encoded)
	return http.StatusOK, nil
}

// RegisterHanderFromForm sets cookie from a RegistrationForm.
func RegisterHanderFromForm(w http.ResponseWriter, r *http.Request, registrationForm formStruct.RegistrationForm) (int, error) {
	username := registrationForm.Username // email isn't set at this point
	pass := registrationForm.Password
	return SetCookieHandler(w, r, username, pass)
}

// RegisterHandler sets a cookie when user registered.
func RegisterHandler(w http.ResponseWriter, r *http.Request) (int, error) {
	var registrationForm formStruct.RegistrationForm
	modelHelper.BindValueForm(&registrationForm, r)
	return RegisterHanderFromForm(w, r, registrationForm)
}

// CurrentUser determines the current user from the request or context
func CurrentUser(r *http.Request) (model.User, error) {
	var user model.User
	var encoded string
	if r == nil {
		fmt.Println("ERROR r is terminated")
	}
	encoded = r.Header.Get("X-Auth-Token")
	if len(encoded) == 0 {
		// check cookie instead
		cookie, err := r.Cookie(CookieName)
		if err != nil {
			return user, err
		}
		encoded = cookie.Value
	}
	user_id, err := DecodeCookie(encoded)
	if err != nil {
		return user, err
	}

	userFromContext := getUserFromContext(r)

	if userFromContext.ID > 0 && user_id == userFromContext.ID {
		user = userFromContext
	} else {
		if db.ORM.Preload("Notifications").Where("user_id = ?", user_id).First(&user).RecordNotFound() { // We only load unread notifications
			return user, errors.New("User not found")
		} else {
			setUserToContext(r, user)
		}
	}

	if user.IsBanned() {
		// recheck as user might've been banned in the meantime
		return user, errors.New("Account banned")
	}
	return user, nil
}

func getUserFromContext(r *http.Request) model.User {
	if rv := context.Get(r, UserContextKey); rv != nil {
        return rv.(model.User)
    }
    return model.User{}
}
func setUserToContext(r *http.Request, val model.User) {
    context.Set(r, UserContextKey, val)
}<commit_msg>Removing debug fmt<commit_after>package userService

import (
	"errors"
	"github.com/NyaaPantsu/nyaa/db"
	"github.com/NyaaPantsu/nyaa/model"
	formStruct "github.com/NyaaPantsu/nyaa/service/user/form"
	msg "github.com/NyaaPantsu/nyaa/util/messages"
	"github.com/NyaaPantsu/nyaa/util/modelHelper"
	"github.com/NyaaPantsu/nyaa/util/timeHelper"
	"github.com/gorilla/context"
	"github.com/gorilla/securecookie"
	"golang.org/x/crypto/bcrypt"
	"net/http"
	"strconv"
	"time"
)

const (
	CookieName = "session"
	UserContextKey = "user"
	)

// If you want to keep login cookies between restarts you need to make these permanent
var cookieHandler = securecookie.New(
	securecookie.GenerateRandomKey(64),
	securecookie.GenerateRandomKey(32))

// Encoding & Decoding of the cookie value
func DecodeCookie(cookie_value string) (uint, error) {
	value := make(map[string]string)
	err := cookieHandler.Decode(CookieName, cookie_value, &value)
	if err != nil {
		return 0, err
	}
	time_int, _ := strconv.ParseInt(value["t"], 10, 0)
	if timeHelper.IsExpired(time.Unix(time_int, 0)) {
		return 0, errors.New("Cookie is expired")
	}
	ret, err := strconv.ParseUint(value["u"], 10, 0)
	return uint(ret), err
}

func EncodeCookie(user_id uint) (string, error) {
	validUntil := timeHelper.FewDaysLater(7) // 1 week
	value := map[string]string{
		"u": strconv.FormatUint(uint64(user_id), 10),
		"t": strconv.FormatInt(validUntil.Unix(), 10),
	}
	return cookieHandler.Encode(CookieName, value)
}

func ClearCookie(w http.ResponseWriter) (int, error) {
	cookie := &http.Cookie{
		Name:     CookieName,
		Value:    "",
		Path:     "/",
		HttpOnly: true,
		MaxAge:   -1,
	}
	http.SetCookie(w, cookie)
	return http.StatusOK, nil
}

// SetCookieHandler sets the authentication cookie
func SetCookieHandler(w http.ResponseWriter, r *http.Request, email string, pass string) (int, error) {
	if email == "" || pass == "" {
		return http.StatusNotFound, errors.New("No username/password entered")
	}

	var user model.User
	messages := msg.GetMessages(r)
	// search by email or username
	isValidEmail := formStruct.EmailValidation(email, messages)
	if isValidEmail {
		if db.ORM.Where("email = ?", email).First(&user).RecordNotFound() {
			return http.StatusNotFound, errors.New("User not found")
		}
	} else {
		if db.ORM.Where("username = ?", email).First(&user).RecordNotFound() {
			return http.StatusNotFound, errors.New("User not found")
		}
	}
	err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(pass))
	if err != nil {
		return http.StatusUnauthorized, errors.New("Password incorrect")
	}
	if user.IsBanned() {
		return http.StatusUnauthorized, errors.New("Account banned")
	}

	encoded, err := EncodeCookie(user.ID)
	if err != nil {
		return http.StatusInternalServerError, err
	}
	cookie := &http.Cookie{
		Name:     CookieName,
		Value:    encoded,
		Path:     "/",
		HttpOnly: true,
	}
	http.SetCookie(w, cookie)
	// also set response header for convenience
	w.Header().Set("X-Auth-Token", encoded)
	return http.StatusOK, nil
}

// RegisterHanderFromForm sets cookie from a RegistrationForm.
func RegisterHanderFromForm(w http.ResponseWriter, r *http.Request, registrationForm formStruct.RegistrationForm) (int, error) {
	username := registrationForm.Username // email isn't set at this point
	pass := registrationForm.Password
	return SetCookieHandler(w, r, username, pass)
}

// RegisterHandler sets a cookie when user registered.
func RegisterHandler(w http.ResponseWriter, r *http.Request) (int, error) {
	var registrationForm formStruct.RegistrationForm
	modelHelper.BindValueForm(&registrationForm, r)
	return RegisterHanderFromForm(w, r, registrationForm)
}

// CurrentUser determines the current user from the request or context
func CurrentUser(r *http.Request) (model.User, error) {
	var user model.User
	var encoded string

	encoded = r.Header.Get("X-Auth-Token")
	if len(encoded) == 0 {
		// check cookie instead
		cookie, err := r.Cookie(CookieName)
		if err != nil {
			return user, err
		}
		encoded = cookie.Value
	}
	user_id, err := DecodeCookie(encoded)
	if err != nil {
		return user, err
	}

	userFromContext := getUserFromContext(r)

	if userFromContext.ID > 0 && user_id == userFromContext.ID {
		user = userFromContext
	} else {
		if db.ORM.Preload("Notifications").Where("user_id = ?", user_id).First(&user).RecordNotFound() { // We only load unread notifications
			return user, errors.New("User not found")
		} else {
			setUserToContext(r, user)
		}
	}

	if user.IsBanned() {
		// recheck as user might've been banned in the meantime
		return user, errors.New("Account banned")
	}
	return user, nil
}

func getUserFromContext(r *http.Request) model.User {
	if rv := context.Get(r, UserContextKey); rv != nil {
        return rv.(model.User)
    }
    return model.User{}
}
func setUserToContext(r *http.Request, val model.User) {
    context.Set(r, UserContextKey, val)
}
<|endoftext|>


<commit_before>package main

import (
	"image"
	"image/color"
	"image/gif"
	"io"
	"math"
	"math/rand"
	"os"
)

var palette = []color.Color{color.Black, color.RGBA{0x00, 0xff, 0x00, 0xff}}

const (
	blackIndex = 0
	greenIndex = 1
)

func main() {
	lissajous(os.Stdout)
}

func lissajous(out io.Writer) {
	const (
		cycles  = 5
		res     = 0.001
		size    = 100
		nframes = 64
		delay   = 8
	)
	freq := rand.Float64() * 3.0
	anim := gif.GIF{LoopCount: nframes}
	phase := 0.0
	for i := 0; i < nframes; i++ {
		rect := image.Rect(0, 0, 2*size+1, 2*size+1)
		img := image.NewPaletted(rect, palette)
		for t := 0.0; t < cycles*2*math.Pi; t += res {
			x := math.Sin(t)
			y := math.Sin(t*freq + phase)
			img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), greenIndex)
		}
		phase += 0.1
		anim.Delay = append(anim.Delay, delay)
		anim.Image = append(anim.Image, img)
	}
	gif.EncodeAll(out, &anim)
}
<commit_msg>multicolor GIFs, FTW ex 1.6<commit_after>package main

import (
	"image"
	cp "image/color/palette"
	"image/gif"
	"io"
	"math"
	"math/rand"
	"os"
)

var palette = cp.WebSafe

const (
	blackIndex = 0
)

func main() {
	lissajous(os.Stdout)
}

func lissajous(out io.Writer) {
	const (
		cycles  = 5
		res     = 0.001
		size    = 100
		nframes = 64
		delay   = 8
	)
	freq := rand.Float64() * 3.0
	anim := gif.GIF{LoopCount: nframes}
	phase := 0.0
	for i := 0; i < nframes; i++ {
		rect := image.Rect(0, 0, 2*size+1, 2*size+1)
		img := image.NewPaletted(rect, palette)
		color := rand.Intn(216)
		for t := 0.0; t < cycles*2*math.Pi; t += res {
			x := math.Sin(t)
			y := math.Sin(t*freq + phase)
			img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), uint8(color))
		}
		phase += 0.1
		anim.Delay = append(anim.Delay, delay)
		anim.Image = append(anim.Image, img)
	}
	gif.EncodeAll(out, &anim)
}
<|endoftext|>


<commit_before>package marathon

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"sort"
	"strconv"
	"strings"

	"github.com/QubitProducts/bamboo/configuration"
)

// Describes an app process running
type Task struct {
	Frontend string
	Server   string
	Host     string
	Port     int
	Ports    []int
	Version  string
	Weight   int
}

// A health check on the application
type HealthCheck struct {
	// One of TCP, HTTP or COMMAND
	Protocol string
	// The path (if Protocol is HTTP)
	Path string
	// The position of the port targeted in the ports array
	PortIndex int
}

type Endpoint struct {
	Protocol string
	Bind     int
}

// An app may have multiple processes
type App struct {
	Id              string
	Frontend        string
	HealthCheckPath string
	HealthChecks    []HealthCheck
	Tasks           []Task
	ServicePort     int
	ServicePorts    []int
	Env             map[string]string
	Labels          map[string]string
	Endpoints       []Endpoint
	CurVsn          string
}

type AppList []App

func (slice AppList) Len() int {
	return len(slice)
}

func (slice AppList) Less(i, j int) bool {
	return slice[i].Id < slice[j].Id
}

func (slice AppList) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

type marathonTaskList []marathonTask

type marathonTasks struct {
	Tasks marathonTaskList `json:"tasks"`
}

type marathonTask struct {
	AppId        string
	Id           string
	Host         string
	Ports        []int
	ServicePorts []int
	StartedAt    string
	StagedAt     string
	Version      string
}

func (slice marathonTaskList) Len() int {
	return len(slice)
}

func (slice marathonTaskList) Less(i, j int) bool {
	return slice[i].Id < slice[j].Id
}

func (slice marathonTaskList) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

type marathonApps struct {
	Apps []marathonApp `json:"apps"`
}

type marathonApp struct {
	Id           string                `json:"id"`
	HealthChecks []marathonHealthCheck `json:"healthChecks"`
	Ports        []int                 `json:"ports"`
	Env          map[string]string     `json:"env"`
	Labels       map[string]string     `json:"labels"`
}

type marathonHealthCheck struct {
	Path      string `json:"path"`
	Protocol  string `json:"protocol"`
	PortIndex int    `json:"portIndex"`
}

func fetchMarathonApps(endpoint string, conf *configuration.Configuration) (map[string]marathonApp, error) {
	client := &http.Client{}
	req, _ := http.NewRequest("GET", endpoint+"/v2/apps", nil)
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Content-Type", "application/json")
	if len(conf.Marathon.User) > 0 && len(conf.Marathon.Password) > 0 {
		req.SetBasicAuth(conf.Marathon.User, conf.Marathon.Password)
	}
	response, err := client.Do(req)

	if err != nil {
		return nil, err
	}

	defer response.Body.Close()
	var appResponse marathonApps

	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(contents, &appResponse)
	if err != nil {
		return nil, err
	}

	dataById := map[string]marathonApp{}

	for _, appConfig := range appResponse.Apps {
		dataById[appConfig.Id] = appConfig
	}

	return dataById, nil
}

func fetchTasks(endpoint string, conf *configuration.Configuration) (map[string]marathonTaskList, error) {
	client := &http.Client{}
	req, _ := http.NewRequest("GET", endpoint+"/v2/tasks", nil)
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Content-Type", "application/json")
	if len(conf.Marathon.User) > 0 && len(conf.Marathon.Password) > 0 {
		req.SetBasicAuth(conf.Marathon.User, conf.Marathon.Password)
	}
	response, err := client.Do(req)

	var tasks marathonTasks

	if err != nil {
		return nil, err
	}

	contents, err := ioutil.ReadAll(response.Body)
	defer response.Body.Close()
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(contents, &tasks)
	if err != nil {
		return nil, err
	}

	taskList := tasks.Tasks
	sort.Sort(taskList)

	tasksById := map[string]marathonTaskList{}
	for _, task := range taskList {
		if tasksById[task.AppId] == nil {
			tasksById[task.AppId] = marathonTaskList{}
		}
		tasksById[task.AppId] = append(tasksById[task.AppId], task)
	}

	for _, task_list := range tasksById {
		sort.Sort(task_list)
	}

	return tasksById, nil
}

func createApps(tasksById map[string]marathonTaskList, marathonApps map[string]marathonApp) AppList {
	appMap := map[string]*App{}
	for _, mApp := range marathonApps {
		mappJson, _ := json.Marshal(mApp)
		log.Println("mapp", string(mappJson))
		appPath := formPath(mApp)
		log.Println("appPath", string(appPath))
		app, ok := appMap[appPath]
		if !ok {
			newApp := formApp(mApp, appPath)

			if endpointStr, ok := mApp.Env["BB_DM_ENDPOINTS"]; ok {
				endpoints := formEndpoints(endpointStr)
				newApp.Endpoints = endpoints
				app = &newApp
				appMap[appPath] = app
			}
		}
		//compare and select min version
		if mApp.Env["SRY_APP_VSN"] < app.CurVsn {
			app.CurVsn = mApp.Env["SRY_APP_VSN"]
			if endpointStr, ok := mApp.Env["BB_DM_ENDPOINTS"]; ok {
				endpoints := formEndpoints(endpointStr)
				app.Endpoints = endpoints
			}
		}
		tasks := formTasks(mApp, *app, tasksById)
		tasksJson, _ := json.Marshal(tasks)
		log.Println("tasks", string(tasksJson))
		app.Tasks = append(app.Tasks, tasks...)
		appJson, _ := json.Marshal(app)
		log.Println("app", string(appJson))
	}
	appMapJson, _ := json.Marshal(appMap)
	log.Println("app", string(appMapJson))

	apps := AppList{}
	for _, app := range appMap {
		apps = append(apps, *app)
	}
	return apps
}

func formTasks(mApp marathonApp, app App, tasksById map[string]marathonTaskList) []Task {
	tasks := []Task{}
	for _, mTask := range tasksById[mApp.Id] {
		if len(mTask.Ports) > 0 {
			server := fmt.Sprintf("%s-%s", app.Frontend, mTask.Host)
			t := Task{
				Frontend: app.Frontend,
				Server:   server,
				Host:     mTask.Host,
				Port:     mTask.Ports[0],
				Ports:    mTask.Ports,
				Version:  mApp.Env["SRY_APP_VSN"],
				Weight:   1,
			}
			tasks = append(tasks, t)
		}
	}
	return tasks
}

func formEndpoints(str string) []Endpoint {
	//{{ range $tcpIdx, $endpoint := Split $app.Env.BB_DM_ENDPOINTS "," }}
	//{{ $endpointSlices := Split $endpoint ":" }}
	//{{ $svcType := index $endpointSlices 0 }}
	//{{ $protocol := index $endpointSlices 1 }}
	//{{ $uri := index $endpointSlices 2 }}
	//{{ $port := index $endpointSlices 3 }}
	//# len {{ len $end
	//BB_DM_ENDPOINTS=pub:http:nil:9800,pub:tcp:nil:9801

	epStrSlices := strings.Split(str, ",")
	endpoints := []Endpoint{}
	for _, epStr := range epStrSlices {
		epParts := strings.Split(epStr, ":")
		if len(epParts) < 4 {
			continue
		}
		bind, err := strconv.Atoi(epParts[3])
		if err != nil {
			log.Panicln("bad bind value", err.Error())
		}
		endpoint := Endpoint{
			Protocol: epParts[1],
			Bind:     bind,
		}

		endpoints = append(endpoints, endpoint)
	}

	return endpoints
}

func formPath(mApp marathonApp) string {
	// Try to handle old app id format without slashes
	var appPath string
	if envAppId, ok := mApp.Env["SRY_APP_ID"]; ok {
		appPath = envAppId
	} else {
		appPath = mApp.Id
	}
	return strings.TrimPrefix(appPath, "/")
}

//formApp build App from marathonApp
func formApp(mApp marathonApp, appPath string) App {
	app := App{
		Id:              appPath,
		Frontend:        strings.Replace(appPath, "/", "::", -1),
		HealthCheckPath: parseHealthCheckPath(mApp.HealthChecks),
		Env:             mApp.Env,
		Labels:          mApp.Labels,
		CurVsn:          mApp.Env["SRY_APP_VSN"],
	}
	app.HealthChecks = make([]HealthCheck, 0, len(mApp.HealthChecks))
	for _, marathonCheck := range mApp.HealthChecks {
		check := HealthCheck{
			Protocol:  marathonCheck.Protocol,
			Path:      marathonCheck.Path,
			PortIndex: marathonCheck.PortIndex,
		}
		app.HealthChecks = append(app.HealthChecks, check)
	}

	if len(mApp.Ports) > 0 {
		app.ServicePort = mApp.Ports[0]
		app.ServicePorts = mApp.Ports
	}

	return app
}

func parseHealthCheckPath(checks []marathonHealthCheck) string {
	for _, check := range checks {
		if check.Protocol != "HTTP" {
			continue
		}
		return check.Path
	}
	return ""
}

/*
	Apps returns a struct that describes Marathon current app and their
	sub tasks information.

	Parameters:
		endpoint: Marathon HTTP endpoint, e.g. http://localhost:8080
*/
func FetchApps(maraconf configuration.Marathon, conf *configuration.Configuration) (AppList, error) {

	var applist AppList
	var err error

	// try all configured endpoints until one succeeds
	for _, url := range maraconf.Endpoints() {
		applist, err = _fetchApps(url, conf)
		if err == nil {
			return applist, err
		}
	}
	// return last error
	return nil, err
}

func _fetchApps(url string, conf *configuration.Configuration) (AppList, error) {
	tasks, err := fetchTasks(url, conf)
	if err != nil {
		return nil, err
	}

	marathonApps, err := fetchMarathonApps(url, conf)
	if err != nil {
		return nil, err
	}
	log.Println("got mapps", len(marathonApps))
	log.Println("got mtasks", len(tasks))
	apps := createApps(tasks, marathonApps)
	sort.Sort(apps)
	return apps, nil
}
<commit_msg>fix bug get app version panic<commit_after>package marathon

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"sort"
	"strconv"
	"strings"

	"github.com/QubitProducts/bamboo/configuration"
)

// Describes an app process running
type Task struct {
	Frontend string
	Server   string
	Host     string
	Port     int
	Ports    []int
	Version  string
	Weight   int
}

// A health check on the application
type HealthCheck struct {
	// One of TCP, HTTP or COMMAND
	Protocol string
	// The path (if Protocol is HTTP)
	Path string
	// The position of the port targeted in the ports array
	PortIndex int
}

type Endpoint struct {
	Protocol string
	Bind     int
}

// An app may have multiple processes
type App struct {
	Id              string
	Frontend        string
	HealthCheckPath string
	HealthChecks    []HealthCheck
	Tasks           []Task
	ServicePort     int
	ServicePorts    []int
	Env             map[string]string
	Labels          map[string]string
	Endpoints       []Endpoint
	CurVsn          string
}

type AppList []App

func (slice AppList) Len() int {
	return len(slice)
}

func (slice AppList) Less(i, j int) bool {
	return slice[i].Id < slice[j].Id
}

func (slice AppList) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

type marathonTaskList []marathonTask

type marathonTasks struct {
	Tasks marathonTaskList `json:"tasks"`
}

type marathonTask struct {
	AppId        string
	Id           string
	Host         string
	Ports        []int
	ServicePorts []int
	StartedAt    string
	StagedAt     string
	Version      string
}

func (slice marathonTaskList) Len() int {
	return len(slice)
}

func (slice marathonTaskList) Less(i, j int) bool {
	return slice[i].Id < slice[j].Id
}

func (slice marathonTaskList) Swap(i, j int) {
	slice[i], slice[j] = slice[j], slice[i]
}

type marathonApps struct {
	Apps []marathonApp `json:"apps"`
}

type marathonApp struct {
	Id           string                `json:"id"`
	HealthChecks []marathonHealthCheck `json:"healthChecks"`
	Ports        []int                 `json:"ports"`
	Env          map[string]string     `json:"env"`
	Labels       map[string]string     `json:"labels"`
}

type marathonHealthCheck struct {
	Path      string `json:"path"`
	Protocol  string `json:"protocol"`
	PortIndex int    `json:"portIndex"`
}

func fetchMarathonApps(endpoint string, conf *configuration.Configuration) (map[string]marathonApp, error) {
	client := &http.Client{}
	req, _ := http.NewRequest("GET", endpoint+"/v2/apps", nil)
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Content-Type", "application/json")
	if len(conf.Marathon.User) > 0 && len(conf.Marathon.Password) > 0 {
		req.SetBasicAuth(conf.Marathon.User, conf.Marathon.Password)
	}
	response, err := client.Do(req)

	if err != nil {
		return nil, err
	}

	defer response.Body.Close()
	var appResponse marathonApps

	contents, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(contents, &appResponse)
	if err != nil {
		return nil, err
	}

	dataById := map[string]marathonApp{}

	for _, appConfig := range appResponse.Apps {
		dataById[appConfig.Id] = appConfig
	}

	return dataById, nil
}

func fetchTasks(endpoint string, conf *configuration.Configuration) (map[string]marathonTaskList, error) {
	client := &http.Client{}
	req, _ := http.NewRequest("GET", endpoint+"/v2/tasks", nil)
	req.Header.Add("Accept", "application/json")
	req.Header.Add("Content-Type", "application/json")
	if len(conf.Marathon.User) > 0 && len(conf.Marathon.Password) > 0 {
		req.SetBasicAuth(conf.Marathon.User, conf.Marathon.Password)
	}
	response, err := client.Do(req)

	var tasks marathonTasks

	if err != nil {
		return nil, err
	}

	contents, err := ioutil.ReadAll(response.Body)
	defer response.Body.Close()
	if err != nil {
		return nil, err
	}

	err = json.Unmarshal(contents, &tasks)
	if err != nil {
		return nil, err
	}

	taskList := tasks.Tasks
	sort.Sort(taskList)

	tasksById := map[string]marathonTaskList{}
	for _, task := range taskList {
		if tasksById[task.AppId] == nil {
			tasksById[task.AppId] = marathonTaskList{}
		}
		tasksById[task.AppId] = append(tasksById[task.AppId], task)
	}

	for _, task_list := range tasksById {
		sort.Sort(task_list)
	}

	return tasksById, nil
}

func createApps(tasksById map[string]marathonTaskList, marathonApps map[string]marathonApp) AppList {
	appMap := map[string]*App{}
	for _, mApp := range marathonApps {
		mappJson, _ := json.Marshal(mApp)
		log.Println("mapp", string(mappJson))
		appPath := formPath(mApp)
		log.Println("appPath", string(appPath))
		app, ok := appMap[appPath]
		if !ok {
			newApp := formApp(mApp, appPath)

			if endpointStr, ok := mApp.Env["BB_DM_ENDPOINTS"]; ok {
				endpoints := formEndpoints(endpointStr)
				newApp.Endpoints = endpoints
				app = &newApp
				appMap[appPath] = app
			}
		}

		//compare and select min version
		if appVersionStr, ok := mApp.Env["SRY_APP_VSN"]; ok && appVersionStr < app.CurVsn {
			app.CurVsn = appVersionStr
			if endpointStr, ok := mApp.Env["BB_DM_ENDPOINTS"]; ok {
				endpoints := formEndpoints(endpointStr)
				app.Endpoints = endpoints
			}
		}

		tasks := formTasks(mApp, *app, tasksById)
		tasksJson, _ := json.Marshal(tasks)
		log.Println("tasks", string(tasksJson))
		app.Tasks = append(app.Tasks, tasks...)
		appJson, _ := json.Marshal(app)
		log.Println("app", string(appJson))
	}
	appMapJson, _ := json.Marshal(appMap)
	log.Println("app", string(appMapJson))

	apps := AppList{}
	for _, app := range appMap {
		apps = append(apps, *app)
	}
	return apps
}

func formTasks(mApp marathonApp, app App, tasksById map[string]marathonTaskList) []Task {
	tasks := []Task{}
	for _, mTask := range tasksById[mApp.Id] {
		if len(mTask.Ports) > 0 {
			server := fmt.Sprintf("%s-%s", app.Frontend, mTask.Host)
			t := Task{
				Frontend: app.Frontend,
				Server:   server,
				Host:     mTask.Host,
				Port:     mTask.Ports[0],
				Ports:    mTask.Ports,
				Version:  mApp.Env["SRY_APP_VSN"],
				Weight:   1,
			}
			tasks = append(tasks, t)
		}
	}
	return tasks
}

func formEndpoints(str string) []Endpoint {
	//{{ range $tcpIdx, $endpoint := Split $app.Env.BB_DM_ENDPOINTS "," }}
	//{{ $endpointSlices := Split $endpoint ":" }}
	//{{ $svcType := index $endpointSlices 0 }}
	//{{ $protocol := index $endpointSlices 1 }}
	//{{ $uri := index $endpointSlices 2 }}
	//{{ $port := index $endpointSlices 3 }}
	//# len {{ len $end
	//BB_DM_ENDPOINTS=pub:http:nil:9800,pub:tcp:nil:9801

	epStrSlices := strings.Split(str, ",")
	endpoints := []Endpoint{}
	for _, epStr := range epStrSlices {
		epParts := strings.Split(epStr, ":")
		if len(epParts) < 4 {
			continue
		}
		bind, err := strconv.Atoi(epParts[3])
		if err != nil {
			log.Panicln("bad bind value", err.Error())
		}
		endpoint := Endpoint{
			Protocol: epParts[1],
			Bind:     bind,
		}

		endpoints = append(endpoints, endpoint)
	}

	return endpoints
}

func formPath(mApp marathonApp) string {
	// Try to handle old app id format without slashes
	var appPath string
	if envAppId, ok := mApp.Env["SRY_APP_ID"]; ok {
		appPath = envAppId
	} else {
		appPath = mApp.Id
	}
	return strings.TrimPrefix(appPath, "/")
}

//formApp build App from marathonApp
func formApp(mApp marathonApp, appPath string) App {
	app := App{
		Id:              appPath,
		Frontend:        strings.Replace(appPath, "/", "::", -1),
		HealthCheckPath: parseHealthCheckPath(mApp.HealthChecks),
		Env:             mApp.Env,
		Labels:          mApp.Labels,
		CurVsn:          mApp.Env["SRY_APP_VSN"],
	}
	app.HealthChecks = make([]HealthCheck, 0, len(mApp.HealthChecks))
	for _, marathonCheck := range mApp.HealthChecks {
		check := HealthCheck{
			Protocol:  marathonCheck.Protocol,
			Path:      marathonCheck.Path,
			PortIndex: marathonCheck.PortIndex,
		}
		app.HealthChecks = append(app.HealthChecks, check)
	}

	if len(mApp.Ports) > 0 {
		app.ServicePort = mApp.Ports[0]
		app.ServicePorts = mApp.Ports
	}

	return app
}

func parseHealthCheckPath(checks []marathonHealthCheck) string {
	for _, check := range checks {
		if check.Protocol != "HTTP" {
			continue
		}
		return check.Path
	}
	return ""
}

/*
	Apps returns a struct that describes Marathon current app and their
	sub tasks information.

	Parameters:
		endpoint: Marathon HTTP endpoint, e.g. http://localhost:8080
*/
func FetchApps(maraconf configuration.Marathon, conf *configuration.Configuration) (AppList, error) {

	var applist AppList
	var err error

	// try all configured endpoints until one succeeds
	for _, url := range maraconf.Endpoints() {
		applist, err = _fetchApps(url, conf)
		if err == nil {
			return applist, err
		}
	}
	// return last error
	return nil, err
}

func _fetchApps(url string, conf *configuration.Configuration) (AppList, error) {
	tasks, err := fetchTasks(url, conf)
	if err != nil {
		return nil, err
	}

	marathonApps, err := fetchMarathonApps(url, conf)
	if err != nil {
		return nil, err
	}
	log.Println("got mapps", len(marathonApps))
	log.Println("got mtasks", len(tasks))
	apps := createApps(tasks, marathonApps)
	sort.Sort(apps)
	return apps, nil
}
<|endoftext|>


<commit_before>package services

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"

	datatypes "github.com/maximilien/softlayer-go/data_types"
	softlayer "github.com/maximilien/softlayer-go/softlayer"
)

const NAME = "SoftLayer_Account"

type softLayer_Account struct {
	client softlayer.Client
}

func NewSoftLayer_Account(client softlayer.Client) *softLayer_Account {
	return &softLayer_Account{
		client: client,
	}
}

func (sla *softLayer_Account) GetName() string {
	return NAME
}

func (sla *softLayer_Account) GetAccountStatus() (datatypes.SoftLayer_Account_Status, error) {
	path := fmt.Sprintf("%s/%s", sla.GetName(), "getAccountStatus.json")
	responseBytes, err := sla.client.DoRawHttpRequest(path, "GET", &bytes.Buffer{})
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: could not SoftLayer_Account#getAccountStatus, error message '%s'", err.Error())
		return datatypes.SoftLayer_Account_Status{}, errors.New(errorMessage)
	}

	accountStatus := datatypes.SoftLayer_Account_Status{}
	err = json.Unmarshal(responseBytes, &accountStatus)
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: failed to decode JSON response, err message '%s'", err.Error())
		err := errors.New(errorMessage)
		return datatypes.SoftLayer_Account_Status{}, err
	}

	return accountStatus, nil
}

func (sla *softLayer_Account) GetVirtualGuests() ([]datatypes.SoftLayer_Virtual_Guest, error) {
	path := fmt.Sprintf("%s/%s", sla.GetName(), "getVirtualGuests.json")
	responseBytes, err := sla.client.DoRawHttpRequest(path, "GET", &bytes.Buffer{})
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: could not SoftLayer_Account#getVirtualGuests, error message '%s'", err.Error())
		return []datatypes.SoftLayer_Virtual_Guest{}, errors.New(errorMessage)
	}

	virtualGuests := []datatypes.SoftLayer_Virtual_Guest{}
	err = json.Unmarshal(responseBytes, &virtualGuests)
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: failed to decode JSON response, err message '%s'", err.Error())
		err := errors.New(errorMessage)
		return []datatypes.SoftLayer_Virtual_Guest{}, err
	}

	return virtualGuests, nil
}

func (sla *softLayer_Account) GetNetworkStorage() ([]datatypes.SoftLayer_Network_Storage, error) {
	path := fmt.Sprintf("%s/%s", sla.GetName(), "getNetworkStorage.json")
	responseBytes, err := sla.client.DoRawHttpRequest(path, "GET", &bytes.Buffer{})
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: could not SoftLayer_Account#getNetworkStorage, error message '%s'", err.Error())
		return []datatypes.SoftLayer_Network_Storage{}, errors.New(errorMessage)
	}

	networkStorage := []datatypes.SoftLayer_Network_Storage{}
	err = json.Unmarshal(responseBytes, &networkStorage)
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: failed to decode JSON response, err message '%s'", err.Error())
		err := errors.New(errorMessage)
		return []datatypes.SoftLayer_Network_Storage{}, err
	}

	return networkStorage, nil
}

func (sla *softLayer_Account) GetVirtualDiskImages() ([]datatypes.SoftLayer_Virtual_Disk_Image, error) {
	path := fmt.Sprintf("%s/%s", sla.GetName(), "getVirtualDiskImages.json")
	responseBytes, err := sla.client.DoRawHttpRequest(path, "GET", &bytes.Buffer{})
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: could not SoftLayer_Account#getVirtualDiskImages, error message '%s'", err.Error())
		return []datatypes.SoftLayer_Virtual_Disk_Image{}, errors.New(errorMessage)
	}

	virtualDiskImages := []datatypes.SoftLayer_Virtual_Disk_Image{}
	err = json.Unmarshal(responseBytes, &virtualDiskImages)
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: failed to decode JSON response, err message '%s'", err.Error())
		err := errors.New(errorMessage)
		return []datatypes.SoftLayer_Virtual_Disk_Image{}, err
	}

	return virtualDiskImages, nil
}
<commit_msg>remove NAME constant since will clash with others<commit_after>package services

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"

	datatypes "github.com/maximilien/softlayer-go/data_types"
	softlayer "github.com/maximilien/softlayer-go/softlayer"
)

type softLayer_Account struct {
	client softlayer.Client
}

func NewSoftLayer_Account(client softlayer.Client) *softLayer_Account {
	return &softLayer_Account{
		client: client,
	}
}

func (sla *softLayer_Account) GetName() string {
	return "SoftLayer_Account"
}

func (sla *softLayer_Account) GetAccountStatus() (datatypes.SoftLayer_Account_Status, error) {
	path := fmt.Sprintf("%s/%s", sla.GetName(), "getAccountStatus.json")
	responseBytes, err := sla.client.DoRawHttpRequest(path, "GET", &bytes.Buffer{})
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: could not SoftLayer_Account#getAccountStatus, error message '%s'", err.Error())
		return datatypes.SoftLayer_Account_Status{}, errors.New(errorMessage)
	}

	accountStatus := datatypes.SoftLayer_Account_Status{}
	err = json.Unmarshal(responseBytes, &accountStatus)
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: failed to decode JSON response, err message '%s'", err.Error())
		err := errors.New(errorMessage)
		return datatypes.SoftLayer_Account_Status{}, err
	}

	return accountStatus, nil
}

func (sla *softLayer_Account) GetVirtualGuests() ([]datatypes.SoftLayer_Virtual_Guest, error) {
	path := fmt.Sprintf("%s/%s", sla.GetName(), "getVirtualGuests.json")
	responseBytes, err := sla.client.DoRawHttpRequest(path, "GET", &bytes.Buffer{})
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: could not SoftLayer_Account#getVirtualGuests, error message '%s'", err.Error())
		return []datatypes.SoftLayer_Virtual_Guest{}, errors.New(errorMessage)
	}

	virtualGuests := []datatypes.SoftLayer_Virtual_Guest{}
	err = json.Unmarshal(responseBytes, &virtualGuests)
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: failed to decode JSON response, err message '%s'", err.Error())
		err := errors.New(errorMessage)
		return []datatypes.SoftLayer_Virtual_Guest{}, err
	}

	return virtualGuests, nil
}

func (sla *softLayer_Account) GetNetworkStorage() ([]datatypes.SoftLayer_Network_Storage, error) {
	path := fmt.Sprintf("%s/%s", sla.GetName(), "getNetworkStorage.json")
	responseBytes, err := sla.client.DoRawHttpRequest(path, "GET", &bytes.Buffer{})
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: could not SoftLayer_Account#getNetworkStorage, error message '%s'", err.Error())
		return []datatypes.SoftLayer_Network_Storage{}, errors.New(errorMessage)
	}

	networkStorage := []datatypes.SoftLayer_Network_Storage{}
	err = json.Unmarshal(responseBytes, &networkStorage)
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: failed to decode JSON response, err message '%s'", err.Error())
		err := errors.New(errorMessage)
		return []datatypes.SoftLayer_Network_Storage{}, err
	}

	return networkStorage, nil
}

func (sla *softLayer_Account) GetVirtualDiskImages() ([]datatypes.SoftLayer_Virtual_Disk_Image, error) {
	path := fmt.Sprintf("%s/%s", sla.GetName(), "getVirtualDiskImages.json")
	responseBytes, err := sla.client.DoRawHttpRequest(path, "GET", &bytes.Buffer{})
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: could not SoftLayer_Account#getVirtualDiskImages, error message '%s'", err.Error())
		return []datatypes.SoftLayer_Virtual_Disk_Image{}, errors.New(errorMessage)
	}

	virtualDiskImages := []datatypes.SoftLayer_Virtual_Disk_Image{}
	err = json.Unmarshal(responseBytes, &virtualDiskImages)
	if err != nil {
		errorMessage := fmt.Sprintf("softlayer-go: failed to decode JSON response, err message '%s'", err.Error())
		err := errors.New(errorMessage)
		return []datatypes.SoftLayer_Virtual_Disk_Image{}, err
	}

	return virtualDiskImages, nil
}
<|endoftext|>


<commit_before>package base

import (
	"gopkg.in/mgo.v2/bson"
	"encoding/json"

	"mr/app/models"
)

func NewCaterer(account_id, token string, jsonStr []byte) (string, int) {

	/* Función que recibe los valores de nickname como string, y como JSON del proveedor nuevo que se insertará en la BD */

	session, err := Connect() // Conecta a la base de datos
	if err != nil {
		return "No se ha conectado a la base de datos", 500
    }
    defer session.Close()

	if CheckToken(token, session) == false {
		return "token no válido", 401   // Verifica que sea un token válido
	} else if UserExists("_id", account_id) == false{
		return "Usuario no encontrado", 403		//Verifica que el account_id exista en la base de datos
	}

	caterer := &models.Proveedor{}
	json.Unmarshal(jsonStr, caterer)

	if CatererExists(caterer.Name){
		return "El nombre del proveedor ya existe", 409
	}

    con := session.DB(NameDB).C("proveedores")

    err = con.Insert(caterer)

	if err != nil {
		return "No se ha insertado", 500
	}

	return "Nuevo proveedor agregado", 201

}

func CatererExists(name string) bool {

	/* Función que verifica si existe el número de serial del proveedor en la base de datos */

	session, err := Connect()
	if err != nil {
		return false
    }
    defer session.Close()
    con := session.DB(NameDB).C("proveedores")

    result := &models.Proveedor{}
    err = con.Find(bson.M{"name": name}).One(&result)

    if err != nil{
    	return false
    } else{
    	return true
    }
}

func UpdateCaterer(account_id, token string, jsonStr []byte) (string, int){

	/* Función que actualiza un proveedor en la base de datos
		Se reciben el id de usuario y el id de la BD del proveedkr */

	session, err := Connect()
	if err != nil {
		return "No se ha conectado a la base de datos", 500
    }
    defer session.Close()

	if CheckToken(token, session) == false {
		return "token no válido", 401   // Verifica que sea un token válido
	} else if UserExists("_id", account_id) == false{
		return "Usuario no encontrado", 403		//Verifica que el account_id exista en la base de datos
	}

	caterer := &models.Proveedor{}
	json.Unmarshal(jsonStr, caterer)

    con := session.DB(NameDB).C("proveedores")

    colQuerier := bson.M{"_id": caterer.Id }  // Busca el documento por ACCOUNT_ID
	change := bson.M{"$set": caterer } // Inserta en el array de proveedores
	err = con.Update(colQuerier, change)

	if err != nil {

		return "Proveedor no encontrado", 400
	}

	return "Datos de proveedor cambiados", 200

}

<commit_msg>Optimizacion: Recibe mongo.session al verificar nombre de proveedor<commit_after>package base

import (
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"encoding/json"

	"mr/app/models"
)

func NewCaterer(account_id, token string, jsonStr []byte) (string, int) {

	/* Función que recibe los valores de nickname como string, y como JSON del proveedor nuevo que se insertará en la BD */

	session, err := Connect() // Conecta a la base de datos
	if err != nil {
		return "No se ha conectado a la base de datos", 500
    }
    defer session.Close()

	if CheckToken(token, session) == false {
		return "token no válido", 401   // Verifica que sea un token válido
	} else if UserExists("_id", account_id) == false{
		return "Usuario no encontrado", 403		//Verifica que el account_id exista en la base de datos
	}

	caterer := &models.Proveedor{}
	json.Unmarshal(jsonStr, caterer)

	if CatererExists(caterer.Name, session){
		return "El nombre del proveedor ya existe", 409
	}

    con := session.DB(NameDB).C("proveedores")

    err = con.Insert(caterer)

	if err != nil {
		return "No se ha insertado", 500
	}

	return "Nuevo proveedor agregado", 201

}

func CatererExists(name string, session *mgo.Session) bool {

	/* Función que verifica si existe el número de serial del proveedor en la base de datos */

    con := session.DB(NameDB).C("proveedores")

    result := &models.Proveedor{}
    err := con.Find(bson.M{"name": name}).One(&result)

    if err != nil{
    	return false
    } else{
    	return true
    }
}

func UpdateCaterer(account_id, token string, jsonStr []byte) (string, int){

	/* Función que actualiza un proveedor en la base de datos
		Se reciben el id de usuario y el id de la BD del proveedkr */

	session, err := Connect()
	if err != nil {
		return "No se ha conectado a la base de datos", 500
    }
    defer session.Close()

	if CheckToken(token, session) == false {
		return "token no válido", 401   // Verifica que sea un token válido
	} else if UserExists("_id", account_id) == false{
		return "Usuario no encontrado", 403		//Verifica que el account_id exista en la base de datos
	}

	caterer := &models.Proveedor{}
	json.Unmarshal(jsonStr, caterer)

    con := session.DB(NameDB).C("proveedores")

    colQuerier := bson.M{"_id": caterer.Id }  // Busca el documento por ACCOUNT_ID
	change := bson.M{"$set": caterer } // Inserta en el array de proveedores
	err = con.Update(colQuerier, change)

	if err != nil {

		return "Proveedor no encontrado", 400
	}

	return "Datos de proveedor cambiados", 200

}

<|endoftext|>