<commit_before>package s3

import (
	"context.Context"

	"github.com/aws/aws-sdk-go/service/s3"
)

type BillLocation struct {
	Region string
	Bucket string
	Key    string
}

type bucketLocation struct {
}

func LocateBills(ctx context.Context, ss *s3.S3, cbk func(context.Context, BillLocation) bool) error {
	buckets, error := listBuckets(ctx, ss)
	for b := range listBills(ctx, ss, buckets) {
		if !cbk(ctx, b) {
			break
		}
	}
}

func listBuckets(ctx context.Context, ss *s3.S3) ([]string, error) {
	input := s3.ListBucketsInput{}
	output, err := ss.ListBucketsWithContext(ctx, &input)
	if err == nil {
		buckets := make([]string, len(output.Buckets))
		for i := range buckets {
			buckets[i] = *output.Buckets[i]
		}
		return buckets, nil
	} else {
		return nil, err
	}
}

// mergecBillLocation implements the fan-in pattern by merging to the out
// channel the input from the channels read on cs.
func mergecBillLocation(out chan<- BillLocation, cs <-chan <-chan BillLocation) {
	var wg sync.WaitGroup
	for c := range cs {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for u := range c {
				out <- u
			}
		}()
	}
	go func() {
		wg.Wait()
		close(out)
	}()
}

func listBills(ctx context.Context, ss *s3.S3, buckets []string) <-chan BillLocation {
	c := make(chan BillLocation)
	cc := make(chan (<-chan BillLocation))
	defer close(cc)
	go mergecBillLocations(c, cc)
	for _, b := range buckets {
		cc <- listBillsFromBucket(ctx, ss, b)
	}
	return c
}

func listBillsFromBucket(ctx context.Context, ss *s3.S3, b string) {

}
<commit_msg>aws/s3: get billing keys for a single region<commit_after>package s3

import (
	"context"
	"regexp"
	"sync"

	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/trackit/jsonlog"
)

type BillLocation struct {
	Region string
	Bucket string
	Key    string
}

type bucketLocation struct {
}

func LocateBills(ctx context.Context, ss *s3.S3, cbk func(context.Context, BillLocation) bool) error {
	buckets, err := listBuckets(ctx, ss)
	if err == nil {
		for b := range listBills(ctx, ss, buckets) {
			if !cbk(ctx, b) {
				break
			}
		}
	}
	return err
}

func listBuckets(ctx context.Context, ss *s3.S3) ([]string, error) {
	input := s3.ListBucketsInput{}
	output, err := ss.ListBucketsWithContext(ctx, &input)
	if err == nil {
		buckets := make([]string, len(output.Buckets))
		for i := range buckets {
			buckets[i] = *output.Buckets[i].Name
		}
		return buckets, nil
	} else {
		return nil, err
	}
}

// mergecBillLocation implements the fan-in pattern by merging to the out
// channel the input from the channels read on cs.
func mergecBillLocation(out chan<- BillLocation, cs <-chan <-chan BillLocation) {
	var wg sync.WaitGroup
	for c := range cs {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for u := range c {
				out <- u
			}
		}()
	}
	go func() {
		wg.Wait()
		close(out)
	}()
}

func listBills(ctx context.Context, ss *s3.S3, buckets []string) <-chan BillLocation {
	c := make(chan BillLocation)
	cc := make(chan (<-chan BillLocation))
	defer close(cc)
	go mergecBillLocation(c, cc)
	for _, b := range buckets {
		cc <- listBillsFromBucket(ctx, ss, b)
	}
	return c
}

func filterBillsByKey(in <-chan BillLocation) <-chan BillLocation {
	out := make(chan BillLocation)
	go func() {
		defer close(out)
		for b := range in {
			if isBillKey(b) {
				out <- b
			}
		}
	}()
	return out
}

var billKey = regexp.MustCompile(`\d+-aws-billing-detailed-line-items-with-resources-and-tags-\d{4}-\d{2}.csv.zip$`)

func isBillKey(b BillLocation) bool {
	return billKey.MatchString(b.Key)
}

func listBillsFromBucket(ctx context.Context, ss *s3.S3, b string) <-chan BillLocation {
	c := make(chan BillLocation)
	go func() {
		defer close(c)
		input := s3.ListObjectsV2Input{
			Bucket: &b,
		}
		err := ss.ListObjectsV2PagesWithContext(ctx, &input, func(page *s3.ListObjectsV2Output, last bool) bool {
			for _, o := range page.Contents {
				c <- BillLocation{
					Key:    *o.Key,
					Bucket: b,
					Region: "",
				}
			}
			return !last
		})
		if err != nil {
			jsonlog.LoggerFromContextOrDefault(ctx).Error("Failed to list objects from bucket.", err.Error())
		}
	}()
	return c
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"os"

	"fmt"
	"strconv"
	"time"

	"github.com/Financial-Times/base-ft-rw-app-go"
	"github.com/Financial-Times/go-fthealth/v1a"
	"github.com/Financial-Times/http-handlers-go"
	"github.com/Financial-Times/public-people-api/people"
	log "github.com/Sirupsen/logrus"
	"github.com/getsentry/raven-go"
	"github.com/gorilla/mux"
	"github.com/jawher/mow.cli"
	"github.com/jmcvetta/neoism"
	"github.com/rcrowley/go-metrics"
)

var env *string

func main() {
	log.Infof("Application starting with args %s", os.Args)
	app := cli.App("public-people-api-neo4j", "A public RESTful API for accessing People in neo4j")
	neoURL := app.StringOpt("neo-url", "http://localhost:7474/db/data", "neo4j endpoint URL")
	// neoURL := app.StringOpt("neo-url", "http://ftper60304-law1a-eu-t:8080/db/data", "neo4j endpoint URL")
	sentryLogon := app.StringOpt("sentry-info", "", "Sentry logon info")
	port := app.StringOpt("port", "8080", "Port to listen on")
	env = app.StringOpt("env", "local", "environment this app is running in")
	graphiteTCPAddress := app.StringOpt("graphiteTCPAddress", "",
		"Graphite TCP address, e.g. graphite.ft.com:2003. Leave as default if you do NOT want to output to graphite (e.g. if running locally)")
	graphitePrefix := app.StringOpt("graphitePrefix", "",
		"Prefix to use. Should start with content, include the environment, and the host name. e.g. content.test.public.people.api.ftaps59382-law1a-eu-t")
	logMetrics := app.BoolOpt("logMetrics", false, "Whether to log metrics. Set to true if running locally and you want metrics output")
	cacheDuration := app.StringOpt("cache-duration", "1h", "Duration Get requests should be cached for. e.g. 2h45m would set the max-age value to '7440' seconds")

	app.Action = func() {
		baseftrwapp.OutputMetricsIfRequired(*graphiteTCPAddress, *graphitePrefix, *logMetrics)
		setupSentry(*sentryLogon)

		if *env != "local" {
			f, err := os.OpenFile("/var/log/apps/public-people-api-go-app.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0755)
			if err == nil {
				log.SetOutput(f)
				log.SetFormatter(&log.TextFormatter{})
			} else {
				log.Fatalf("Failed to initialise log file, %v", err)
			}

			defer f.Close()
		}

		log.Infof("public-people-api will listen on port: %s, connecting to: %s", *port, *neoURL)
		runServer(*neoURL, *port, *cacheDuration, *env)
	}
	log.SetLevel(log.InfoLevel)
	log.Infof("Application started with args %s", os.Args)
	app.Run(os.Args)
}

func runServer(neoURL string, port string, cacheDuration string, env string) {

	if duration, durationErr := time.ParseDuration(cacheDuration); durationErr != nil {
		log.Fatalf("Failed to parse cache duration string, %v", durationErr)
	} else {
		people.CacheControlHeader = fmt.Sprintf("max-age=%s, public", strconv.FormatFloat(duration.Seconds(), 'f', 0, 64))
	}

	db, err := neoism.Connect(neoURL)
	db.Session.Client = &http.Client{Transport: &http.Transport{MaxIdleConnsPerHost: 100}}
	if err != nil {
		log.Fatalf("Error connecting to neo4j %s", err)
		raven.CaptureError(err, nil)
	}

	people.PeopleDriver = people.NewCypherDriver(db, env)

	servicesRouter := mux.NewRouter()

	// Healthchecks and standards first
	servicesRouter.HandleFunc("/__health", v1a.Handler("PeopleReadWriteNeo4j Healthchecks",
		"Checks for accessing neo4j", people.HealthCheck()))
	servicesRouter.HandleFunc("/ping", people.Ping)
	servicesRouter.HandleFunc("/__ping", people.Ping)

	// Then API specific ones:
	servicesRouter.HandleFunc("/people/{uuid}", people.GetPerson).Methods("GET")
	servicesRouter.HandleFunc("/people/{uuid}", people.MethodNotAllowedHandler)

	var monitoringRouter http.Handler = servicesRouter
	monitoringRouter = httphandlers.TransactionAwareRequestLoggingHandler(log.StandardLogger(), monitoringRouter)
	monitoringRouter = httphandlers.HTTPMetricsHandler(metrics.DefaultRegistry, monitoringRouter)

	// The top one of these feels more correct, but the lower one matches what we have in Dropwizard,
	// so it's what apps expect currently same as ping, the content of build-info needs more definition
	http.HandleFunc("/__build-info", people.BuildInfoHandler)
	http.HandleFunc("/build-info", people.BuildInfoHandler)
	http.Handle("/", monitoringRouter)

	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatalf("Unable to start server: %v", err)
	}
}

func setupSentry(logon string) {
	if logon != "" {
		raven.SetDSN(logon)
	}
}
<commit_msg>Sentry details now located in external file. Not in hieradata<commit_after>package main

import (
	"bufio"
	"net/http"
	"os"

	"fmt"
	"strconv"
	"time"

	"github.com/Financial-Times/base-ft-rw-app-go"
	"github.com/Financial-Times/go-fthealth/v1a"
	"github.com/Financial-Times/http-handlers-go"
	"github.com/Financial-Times/public-people-api/people"
	log "github.com/Sirupsen/logrus"
	"github.com/getsentry/raven-go"
	"github.com/gorilla/mux"
	"github.com/jawher/mow.cli"
	"github.com/jmcvetta/neoism"
	"github.com/rcrowley/go-metrics"
)

func main() {
	log.Infof("Application starting with args %s", os.Args)
	app := cli.App("public-people-api-neo4j", "A public RESTful API for accessing People in neo4j")
	neoURL := app.StringOpt("neo-url", "http://localhost:7474/db/data", "neo4j endpoint URL")
	// neoURL := app.StringOpt("neo-url", "http://ftper60304-law1a-eu-t:8080/db/data", "neo4j endpoint URL")
	port := app.StringOpt("port", "8080", "Port to listen on")
	env := app.StringOpt("env", "local", "environment this app is running in")
	graphiteTCPAddress := app.StringOpt("graphiteTCPAddress", "",
		"Graphite TCP address, e.g. graphite.ft.com:2003. Leave as default if you do NOT want to output to graphite (e.g. if running locally)")
	graphitePrefix := app.StringOpt("graphitePrefix", "",
		"Prefix to use. Should start with content, include the environment, and the host name. e.g. content.test.public.people.api.ftaps59382-law1a-eu-t")
	logMetrics := app.BoolOpt("logMetrics", false, "Whether to log metrics. Set to true if running locally and you want metrics output")
	cacheDuration := app.StringOpt("cache-duration", "1h", "Duration Get requests should be cached for. e.g. 2h45m would set the max-age value to '7440' seconds")

	app.Action = func() {
		baseftrwapp.OutputMetricsIfRequired(*graphiteTCPAddress, *graphitePrefix, *logMetrics)
		setupSentry()

		if *env != "local" {
			f, err := os.OpenFile("/var/log/apps/public-people-api-go-app.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0755)
			if err == nil {
				log.SetOutput(f)
				log.SetFormatter(&log.TextFormatter{})
			} else {
				log.Fatalf("Failed to initialise log file, %v", err)
			}

			defer f.Close()
		}

		log.Infof("public-people-api will listen on port: %s, connecting to: %s", *port, *neoURL)
		runServer(*neoURL, *port, *cacheDuration, *env)
	}
	log.SetLevel(log.InfoLevel)
	log.Infof("Application started with args %s", os.Args)
	app.Run(os.Args)
}

func runServer(neoURL string, port string, cacheDuration string, env string) {

	if duration, durationErr := time.ParseDuration(cacheDuration); durationErr != nil {
		log.Fatalf("Failed to parse cache duration string, %v", durationErr)
	} else {
		people.CacheControlHeader = fmt.Sprintf("max-age=%s, public", strconv.FormatFloat(duration.Seconds(), 'f', 0, 64))
	}

	db, err := neoism.Connect(neoURL)
	db.Session.Client = &http.Client{Transport: &http.Transport{MaxIdleConnsPerHost: 100}}
	if err != nil {
		log.Fatalf("Error connecting to neo4j %s", err)
		raven.CaptureError(err, nil)
	}

	people.PeopleDriver = people.NewCypherDriver(db, env)

	servicesRouter := mux.NewRouter()

	// Healthchecks and standards first
	servicesRouter.HandleFunc("/__health", v1a.Handler("PeopleReadWriteNeo4j Healthchecks",
		"Checks for accessing neo4j", people.HealthCheck()))
	servicesRouter.HandleFunc("/ping", people.Ping)
	servicesRouter.HandleFunc("/__ping", people.Ping)

	// Then API specific ones:
	servicesRouter.HandleFunc("/people/{uuid}", people.GetPerson).Methods("GET")
	servicesRouter.HandleFunc("/people/{uuid}", people.MethodNotAllowedHandler)

	var monitoringRouter http.Handler = servicesRouter
	monitoringRouter = httphandlers.TransactionAwareRequestLoggingHandler(log.StandardLogger(), monitoringRouter)
	monitoringRouter = httphandlers.HTTPMetricsHandler(metrics.DefaultRegistry, monitoringRouter)

	// The top one of these feels more correct, but the lower one matches what we have in Dropwizard,
	// so it's what apps expect currently same as ping, the content of build-info needs more definition
	http.HandleFunc("/__build-info", people.BuildInfoHandler)
	http.HandleFunc("/build-info", people.BuildInfoHandler)
	http.Handle("/", monitoringRouter)

	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatalf("Unable to start server: %v", err)
	}
}

func setupSentry() {
	file, _ := os.Open("/usr/local/public-people-api/sentryLogon.txt")
	scanner := bufio.NewScanner(file)
	dsn := ""
	for scanner.Scan() {
		dsn = scanner.Text()
	}
	if dsn != "" {
		raven.SetDSN(dsn)
	}
}
<|endoftext|>


<commit_before>// This library implements a cron spec parser and runner.  See the README for
// more details.
package cron

import (
	"log"
	"runtime"
	"sort"
	"time"
)

// Cron keeps track of any number of entries, invoking the associated func as
// specified by the schedule. It may be started, stopped, and the entries may
// be inspected while running.
type Cron struct {
	entries  []*Entry
	stop     chan struct{}
	add      chan *Entry
	snapshot chan []*Entry
	running  bool
	ErrorLog *log.Logger
	location *time.Location
}

// Job is an interface for submitted cron jobs.
type Job interface {
	Run()
}

// The Schedule describes a job's duty cycle.
type Schedule interface {
	// Return the next activation time, later than the given time.
	// Next is invoked initially, and then each time the job is run.
	Next(time.Time) time.Time
}

// Entry consists of a schedule and the func to execute on that schedule.
type Entry struct {
	// The schedule on which this job should be run.
	Schedule Schedule

	// The next time the job will run. This is the zero time if Cron has not been
	// started or this entry's schedule is unsatisfiable
	Next time.Time

	// The last time this job was run. This is the zero time if the job has never
	// been run.
	Prev time.Time

	// The Job to run.
	Job Job
}

// byTime is a wrapper for sorting the entry array by time
// (with zero time at the end).
type byTime []*Entry

func (s byTime) Len() int      { return len(s) }
func (s byTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s byTime) Less(i, j int) bool {
	// Two zero times should return false.
	// Otherwise, zero is "greater" than any other time.
	// (To sort it at the end of the list.)
	if s[i].Next.IsZero() {
		return false
	}
	if s[j].Next.IsZero() {
		return true
	}
	return s[i].Next.Before(s[j].Next)
}

// New returns a new Cron job runner.
func New() *Cron {
	return &Cron{
		entries:  nil,
		add:      make(chan *Entry),
		stop:     make(chan struct{}),
		snapshot: make(chan []*Entry),
		running:  false,
		ErrorLog: nil,
		location: time.Now().Location(),
	}
}

// A wrapper that turns a func() into a cron.Job
type FuncJob func()

func (f FuncJob) Run() { f() }

// AddFunc adds a func to the Cron to be run on the given schedule.
func (c *Cron) AddFunc(spec string, cmd func()) error {
	return c.AddJob(spec, FuncJob(cmd))
}

// AddJob adds a Job to the Cron to be run on the given schedule.
func (c *Cron) AddJob(spec string, cmd Job) error {
	schedule, err := Parse(spec)
	if err != nil {
		return err
	}
	c.Schedule(schedule, cmd)
	return nil
}

// Schedule adds a Job to the Cron to be run on the given schedule.
func (c *Cron) Schedule(schedule Schedule, cmd Job) {
	entry := &Entry{
		Schedule: schedule,
		Job:      cmd,
	}
	if !c.running {
		c.entries = append(c.entries, entry)
		return
	}

	c.add <- entry
}

// Entries returns a snapshot of the cron entries.
func (c *Cron) Entries() []*Entry {
	if c.running {
		c.snapshot <- nil
		x := <-c.snapshot
		return x
	}
	return c.entrySnapshot()
}

// SetLocations sets the time zone location
func (c *Cron) SetLocation(location *time.Location) {
	c.location = location
}

// Start the cron scheduler in its own go-routine.
func (c *Cron) Start() {
	c.running = true
	go c.run()
}

func (c *Cron) runWithRecovery(j Job) {
	defer func() {
		if r := recover(); r != nil {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			c.logf("cron: panic running job: %v\n%s", r, buf)
		}
	}()
	j.Run()
}

// Run the scheduler.. this is private just due to the need to synchronize
// access to the 'running' state variable.
func (c *Cron) run() {
	// Figure out the next activation times for each entry.
	now := time.Now().In(c.location)
	for _, entry := range c.entries {
		entry.Next = entry.Schedule.Next(now)
	}

	for {
		// Determine the next entry to run.
		sort.Sort(byTime(c.entries))

		var effective time.Time
		if len(c.entries) == 0 || c.entries[0].Next.IsZero() {
			// If there are no entries yet, just sleep - it still handles new entries
			// and stop requests.
			effective = now.AddDate(10, 0, 0)
		} else {
			effective = c.entries[0].Next
		}

		select {
		case now = <-time.After(effective.Sub(now)):
			// Run every entry whose next time was this effective time.
			for _, e := range c.entries {
				if e.Next != effective {
					break
				}
				go c.runWithRecovery(e.Job)
				e.Prev = e.Next
				e.Next = e.Schedule.Next(now)
			}
			continue

		case newEntry := <-c.add:
			c.entries = append(c.entries, newEntry)
			newEntry.Next = newEntry.Schedule.Next(time.Now().Local())

		case <-c.snapshot:
			c.snapshot <- c.entrySnapshot()

		case <-c.stop:
			return
		}

		// 'now' should be updated after newEntry and snapshot cases.
		now = time.Now().Local()
	}
}

// Logs an error to stderr or to the configured error log
func (c *Cron) logf(format string, args ...interface{}) {
	if c.ErrorLog != nil {
		c.ErrorLog.Printf(format, args...)
	} else {
		log.Printf(format, args...)
	}
}

// Stop stops the cron scheduler if it is running; otherwise it does nothing.
func (c *Cron) Stop() {
	if !c.running {
		return
	}
	c.stop <- struct{}{}
	c.running = false
}

// entrySnapshot returns a copy of the current cron entry list.
func (c *Cron) entrySnapshot() []*Entry {
	entries := []*Entry{}
	for _, e := range c.entries {
		entries = append(entries, &Entry{
			Schedule: e.Schedule,
			Next:     e.Next,
			Prev:     e.Prev,
			Job:      e.Job,
		})
	}
	return entries
}
<commit_msg>Add location support v2<commit_after>// This library implements a cron spec parser and runner.  See the README for
// more details.
package cron

import (
	"log"
	"runtime"
	"sort"
	"time"
)

// Cron keeps track of any number of entries, invoking the associated func as
// specified by the schedule. It may be started, stopped, and the entries may
// be inspected while running.
type Cron struct {
	entries  []*Entry
	stop     chan struct{}
	add      chan *Entry
	snapshot chan []*Entry
	running  bool
	ErrorLog *log.Logger
	location *time.Location
}

// Job is an interface for submitted cron jobs.
type Job interface {
	Run()
}

// The Schedule describes a job's duty cycle.
type Schedule interface {
	// Return the next activation time, later than the given time.
	// Next is invoked initially, and then each time the job is run.
	Next(time.Time) time.Time
}

// Entry consists of a schedule and the func to execute on that schedule.
type Entry struct {
	// The schedule on which this job should be run.
	Schedule Schedule

	// The next time the job will run. This is the zero time if Cron has not been
	// started or this entry's schedule is unsatisfiable
	Next time.Time

	// The last time this job was run. This is the zero time if the job has never
	// been run.
	Prev time.Time

	// The Job to run.
	Job Job
}

// byTime is a wrapper for sorting the entry array by time
// (with zero time at the end).
type byTime []*Entry

func (s byTime) Len() int      { return len(s) }
func (s byTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s byTime) Less(i, j int) bool {
	// Two zero times should return false.
	// Otherwise, zero is "greater" than any other time.
	// (To sort it at the end of the list.)
	if s[i].Next.IsZero() {
		return false
	}
	if s[j].Next.IsZero() {
		return true
	}
	return s[i].Next.Before(s[j].Next)
}

// New returns a new Cron job runner.
func New() *Cron {
	return &Cron{
		entries:  nil,
		add:      make(chan *Entry),
		stop:     make(chan struct{}),
		snapshot: make(chan []*Entry),
		running:  false,
		ErrorLog: nil,
		location: time.Now().Location(),
	}
}

// A wrapper that turns a func() into a cron.Job
type FuncJob func()

func (f FuncJob) Run() { f() }

// AddFunc adds a func to the Cron to be run on the given schedule.
func (c *Cron) AddFunc(spec string, cmd func()) error {
	return c.AddJob(spec, FuncJob(cmd))
}

// AddJob adds a Job to the Cron to be run on the given schedule.
func (c *Cron) AddJob(spec string, cmd Job) error {
	schedule, err := Parse(spec)
	if err != nil {
		return err
	}
	c.Schedule(schedule, cmd)
	return nil
}

// Schedule adds a Job to the Cron to be run on the given schedule.
func (c *Cron) Schedule(schedule Schedule, cmd Job) {
	entry := &Entry{
		Schedule: schedule,
		Job:      cmd,
	}
	if !c.running {
		c.entries = append(c.entries, entry)
		return
	}

	c.add <- entry
}

// Entries returns a snapshot of the cron entries.
func (c *Cron) Entries() []*Entry {
	if c.running {
		c.snapshot <- nil
		x := <-c.snapshot
		return x
	}
	return c.entrySnapshot()
}

// SetLocations sets the time zone location
func (c *Cron) SetLocation(location *time.Location) {
	c.location = location
}

// Start the cron scheduler in its own go-routine.
func (c *Cron) Start() {
	c.running = true
	go c.run()
}

func (c *Cron) runWithRecovery(j Job) {
	defer func() {
		if r := recover(); r != nil {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			c.logf("cron: panic running job: %v\n%s", r, buf)
		}
	}()
	j.Run()
}

// Run the scheduler.. this is private just due to the need to synchronize
// access to the 'running' state variable.
func (c *Cron) run() {
	// Figure out the next activation times for each entry.
	now := time.Now().In(c.location)
	for _, entry := range c.entries {
		entry.Next = entry.Schedule.Next(now)
	}

	for {
		// Determine the next entry to run.
		sort.Sort(byTime(c.entries))

		var effective time.Time
		if len(c.entries) == 0 || c.entries[0].Next.IsZero() {
			// If there are no entries yet, just sleep - it still handles new entries
			// and stop requests.
			effective = now.AddDate(10, 0, 0)
		} else {
			effective = c.entries[0].Next
		}

		select {
		case now = <-time.After(effective.Sub(now)):
			// Run every entry whose next time was this effective time.
			for _, e := range c.entries {
				if e.Next != effective {
					break
				}
				go c.runWithRecovery(e.Job)
				e.Prev = e.Next
				e.Next = e.Schedule.Next(now)
			}
			continue

		case newEntry := <-c.add:
			c.entries = append(c.entries, newEntry)
			newEntry.Next = newEntry.Schedule.Next(time.Now().Local())

		case <-c.snapshot:
			c.snapshot <- c.entrySnapshot()

		case <-c.stop:
			return
		}

		// 'now' should be updated after newEntry and snapshot cases.
		now = time.Now().In(c.location)
	}
}

// Logs an error to stderr or to the configured error log
func (c *Cron) logf(format string, args ...interface{}) {
	if c.ErrorLog != nil {
		c.ErrorLog.Printf(format, args...)
	} else {
		log.Printf(format, args...)
	}
}

// Stop stops the cron scheduler if it is running; otherwise it does nothing.
func (c *Cron) Stop() {
	if !c.running {
		return
	}
	c.stop <- struct{}{}
	c.running = false
}

// entrySnapshot returns a copy of the current cron entry list.
func (c *Cron) entrySnapshot() []*Entry {
	entries := []*Entry{}
	for _, e := range c.entries {
		entries = append(entries, &Entry{
			Schedule: e.Schedule,
			Next:     e.Next,
			Prev:     e.Prev,
			Job:      e.Job,
		})
	}
	return entries
}
<|endoftext|>


<commit_before>package http

import (
	"net/http"

	"github.com/go-chi/chi"
	"github.com/influxdata/influxdb"
	"github.com/influxdata/influxdb/authorizer"
	"github.com/influxdata/influxdb/chronograf/server"
	"github.com/influxdata/influxdb/http/metric"
	"github.com/influxdata/influxdb/kit/prom"
	kithttp "github.com/influxdata/influxdb/kit/transport/http"
	"github.com/influxdata/influxdb/query"
	"github.com/influxdata/influxdb/storage"
	"github.com/prometheus/client_golang/prometheus"
	"go.uber.org/zap"
)

// APIHandler is a collection of all the service handlers.
type APIHandler struct {
	chi.Router
}

// APIBackend is all services and associated parameters required to construct
// an APIHandler.
type APIBackend struct {
	AssetsPath string // if empty then assets are served from bindata.
	Logger     *zap.Logger
	influxdb.HTTPErrorHandler
	SessionRenewDisabled bool
	// MaxBatchSizeBytes is the maximum number of bytes which can be written
	// in a single points batch
	MaxBatchSizeBytes int64

	// WriteParserMaxBytes specifies the maximum number of bytes that may be allocated when processing a single
	// write request. A value of zero specifies there is no limit.
	WriteParserMaxBytes int

	// WriteParserMaxLines specifies the maximum number of lines that may be parsed when processing a single
	// write request. A value of zero specifies there is no limit.
	WriteParserMaxLines int

	// WriteParserMaxValues specifies the maximum number of values that may be parsed when processing a single
	// write request. A value of zero specifies there is no limit.
	WriteParserMaxValues int

	NewBucketService func(*influxdb.Source) (influxdb.BucketService, error)
	NewQueryService  func(*influxdb.Source) (query.ProxyQueryService, error)

	WriteEventRecorder metric.EventRecorder
	QueryEventRecorder metric.EventRecorder

	PointsWriter                    storage.PointsWriter
	DeleteService                   influxdb.DeleteService
	BackupService                   influxdb.BackupService
	KVBackupService                 influxdb.KVBackupService
	AuthorizationService            influxdb.AuthorizationService
	BucketService                   influxdb.BucketService
	SessionService                  influxdb.SessionService
	UserService                     influxdb.UserService
	OrganizationService             influxdb.OrganizationService
	UserResourceMappingService      influxdb.UserResourceMappingService
	LabelService                    influxdb.LabelService
	DashboardService                influxdb.DashboardService
	DashboardOperationLogService    influxdb.DashboardOperationLogService
	BucketOperationLogService       influxdb.BucketOperationLogService
	UserOperationLogService         influxdb.UserOperationLogService
	OrganizationOperationLogService influxdb.OrganizationOperationLogService
	SourceService                   influxdb.SourceService
	VariableService                 influxdb.VariableService
	PasswordsService                influxdb.PasswordsService
	OnboardingService               influxdb.OnboardingService
	InfluxQLService                 query.ProxyQueryService
	FluxService                     query.ProxyQueryService
	TaskService                     influxdb.TaskService
	CheckService                    influxdb.CheckService
	TelegrafService                 influxdb.TelegrafConfigStore
	ScraperTargetStoreService       influxdb.ScraperTargetStoreService
	SecretService                   influxdb.SecretService
	LookupService                   influxdb.LookupService
	ChronografService               *server.Service
	OrgLookupService                authorizer.OrganizationService
	DocumentService                 influxdb.DocumentService
	NotificationRuleStore           influxdb.NotificationRuleStore
	NotificationEndpointService     influxdb.NotificationEndpointService
}

// PrometheusCollectors exposes the prometheus collectors associated with an APIBackend.
func (b *APIBackend) PrometheusCollectors() []prometheus.Collector {
	var cs []prometheus.Collector

	if pc, ok := b.WriteEventRecorder.(prom.PrometheusCollector); ok {
		cs = append(cs, pc.PrometheusCollectors()...)
	}

	if pc, ok := b.QueryEventRecorder.(prom.PrometheusCollector); ok {
		cs = append(cs, pc.PrometheusCollectors()...)
	}

	return cs
}

// APIHandlerOptFn is a functional input param to set parameters on
// the APIHandler.
type APIHandlerOptFn func(chi.Router)

// WithResourceHandler registers a resource handler on the APIHandler.
func WithResourceHandler(resHandler kithttp.ResourceHandler) APIHandlerOptFn {
	return func(h chi.Router) {
		h.Mount(resHandler.Prefix(), resHandler)
	}
}

// NewAPIHandler constructs all api handlers beneath it and returns an APIHandler
func NewAPIHandler(b *APIBackend, opts ...APIHandlerOptFn) *APIHandler {
	h := &APIHandler{
		Router: newBaseChiRouter(b.HTTPErrorHandler),
	}

	internalURM := b.UserResourceMappingService
	b.UserResourceMappingService = authorizer.NewURMService(b.OrgLookupService, b.UserResourceMappingService)

	h.Mount("/api/v2", serveLinksHandler(b.HTTPErrorHandler))

	authorizationBackend := NewAuthorizationBackend(b.Logger.With(zap.String("handler", "authorization")), b)
	authorizationBackend.AuthorizationService = authorizer.NewAuthorizationService(b.AuthorizationService)
	h.Mount(prefixAuthorization, NewAuthorizationHandler(b.Logger, authorizationBackend))

	bucketBackend := NewBucketBackend(b.Logger.With(zap.String("handler", "bucket")), b)
	bucketBackend.BucketService = authorizer.NewBucketService(b.BucketService)
	h.Mount(prefixBuckets, NewBucketHandler(b.Logger, bucketBackend))

	checkBackend := NewCheckBackend(b.Logger.With(zap.String("handler", "check")), b)
	checkBackend.CheckService = authorizer.NewCheckService(b.CheckService,
		b.UserResourceMappingService, b.OrganizationService)
	h.Mount(prefixChecks, NewCheckHandler(b.Logger, checkBackend))

	h.Mount(prefixChronograf, NewChronografHandler(b.ChronografService, b.HTTPErrorHandler))

	dashboardBackend := NewDashboardBackend(b.Logger.With(zap.String("handler", "dashboard")), b)
	dashboardBackend.DashboardService = authorizer.NewDashboardService(b.DashboardService)
	h.Mount(prefixDashboards, NewDashboardHandler(b.Logger, dashboardBackend))

	deleteBackend := NewDeleteBackend(b.Logger.With(zap.String("handler", "delete")), b)
	h.Mount(prefixDelete, NewDeleteHandler(b.Logger, deleteBackend))

	documentBackend := NewDocumentBackend(b.Logger.With(zap.String("handler", "document")), b)
	h.Mount(prefixDocuments, NewDocumentHandler(documentBackend))

	fluxBackend := NewFluxBackend(b.Logger.With(zap.String("handler", "query")), b)
	h.Mount(prefixQuery, NewFluxHandler(b.Logger, fluxBackend))

	h.Mount(prefixLabels, NewLabelHandler(b.Logger, authorizer.NewLabelService(b.LabelService), b.HTTPErrorHandler))

	notificationEndpointBackend := NewNotificationEndpointBackend(b.Logger.With(zap.String("handler", "notificationEndpoint")), b)
	notificationEndpointBackend.NotificationEndpointService = authorizer.NewNotificationEndpointService(b.NotificationEndpointService,
		b.UserResourceMappingService, b.OrganizationService)
	h.Mount(prefixNotificationEndpoints, NewNotificationEndpointHandler(notificationEndpointBackend.Logger(), notificationEndpointBackend))

	notificationRuleBackend := NewNotificationRuleBackend(b.Logger.With(zap.String("handler", "notification_rule")), b)
	notificationRuleBackend.NotificationRuleStore = authorizer.NewNotificationRuleStore(b.NotificationRuleStore,
		b.UserResourceMappingService, b.OrganizationService)
	h.Mount(prefixNotificationRules, NewNotificationRuleHandler(b.Logger, notificationRuleBackend))

	orgBackend := NewOrgBackend(b.Logger.With(zap.String("handler", "org")), b)
	orgBackend.OrganizationService = authorizer.NewOrgService(b.OrganizationService)
	h.Mount(prefixOrganizations, NewOrgHandler(b.Logger, orgBackend))

	scraperBackend := NewScraperBackend(b.Logger.With(zap.String("handler", "scraper")), b)
	scraperBackend.ScraperStorageService = authorizer.NewScraperTargetStoreService(b.ScraperTargetStoreService,
		b.UserResourceMappingService,
		b.OrganizationService)
	h.Mount(prefixTargets, NewScraperHandler(b.Logger, scraperBackend))

	sessionBackend := newSessionBackend(b.Logger.With(zap.String("handler", "session")), b)
	sessionHandler := NewSessionHandler(b.Logger, sessionBackend)
	h.Mount(prefixSignIn, sessionHandler)
	h.Mount(prefixSignOut, sessionHandler)

	setupBackend := NewSetupBackend(b.Logger.With(zap.String("handler", "setup")), b)
	h.Mount(prefixSetup, NewSetupHandler(b.Logger, setupBackend))

	sourceBackend := NewSourceBackend(b.Logger.With(zap.String("handler", "source")), b)
	sourceBackend.SourceService = authorizer.NewSourceService(b.SourceService)
	sourceBackend.BucketService = authorizer.NewBucketService(b.BucketService)
	h.Mount(prefixSources, NewSourceHandler(b.Logger, sourceBackend))

	h.Mount("/api/v2/swagger.json", newSwaggerLoader(b.Logger.With(zap.String("service", "swagger-loader")), b.HTTPErrorHandler))

	taskBackend := NewTaskBackend(b.Logger.With(zap.String("handler", "task")), b)
	taskHandler := NewTaskHandler(b.Logger, taskBackend)
	taskHandler.UserResourceMappingService = internalURM
	h.Mount(prefixTasks, taskHandler)

	telegrafBackend := NewTelegrafBackend(b.Logger.With(zap.String("handler", "telegraf")), b)
	telegrafBackend.TelegrafService = authorizer.NewTelegrafConfigService(b.TelegrafService, b.UserResourceMappingService)
	h.Mount(prefixTelegrafPlugins, NewTelegrafHandler(b.Logger, telegrafBackend))
	h.Mount(prefixTelegraf, NewTelegrafHandler(b.Logger, telegrafBackend))

	userBackend := NewUserBackend(b.Logger.With(zap.String("handler", "user")), b)
	userBackend.UserService = authorizer.NewUserService(b.UserService)
	userBackend.PasswordsService = authorizer.NewPasswordService(b.PasswordsService)
	userHandler := NewUserHandler(b.Logger, userBackend)
	h.Mount(prefixMe, userHandler)
	h.Mount(prefixUsers, userHandler)

	variableBackend := NewVariableBackend(b.Logger.With(zap.String("handler", "variable")), b)
	variableBackend.VariableService = authorizer.NewVariableService(b.VariableService)
	h.Mount(prefixVariables, NewVariableHandler(b.Logger, variableBackend))

	backupBackend := NewBackupBackend(b)
	backupBackend.BackupService = authorizer.NewBackupService(backupBackend.BackupService)
	h.Mount(prefixBackup, NewBackupHandler(backupBackend))

	writeBackend := NewWriteBackend(b.Logger.With(zap.String("handler", "write")), b)
	h.Mount(prefixWrite, NewWriteHandler(b.Logger, writeBackend,
		WithMaxBatchSizeBytes(b.MaxBatchSizeBytes),
		WithParserMaxBytes(b.WriteParserMaxBytes),
		WithParserMaxLines(b.WriteParserMaxLines),
		WithParserMaxValues(b.WriteParserMaxValues),
	))

	for _, o := range opts {
		o(h)
	}
	return h
}

var apiLinks = map[string]interface{}{
	// when adding new links, please take care to keep this list alphabetical
	// as this makes it easier to verify values against the swagger document.
	"authorizations": "/api/v2/authorizations",
	"backup":         "/api/v2/backup",
	"buckets":        "/api/v2/buckets",
	"dashboards":     "/api/v2/dashboards",
	"external": map[string]string{
		"statusFeed": "https://www.influxdata.com/feed/json",
	},
	"labels":                "/api/v2/labels",
	"variables":             "/api/v2/variables",
	"me":                    "/api/v2/me",
	"notificationRules":     "/api/v2/notificationRules",
	"notificationEndpoints": "/api/v2/notificationEndpoints",
	"orgs":                  "/api/v2/orgs",
	"query": map[string]string{
		"self":        "/api/v2/query",
		"ast":         "/api/v2/query/ast",
		"analyze":     "/api/v2/query/analyze",
		"suggestions": "/api/v2/query/suggestions",
	},
	"setup":    "/api/v2/setup",
	"signin":   "/api/v2/signin",
	"signout":  "/api/v2/signout",
	"sources":  "/api/v2/sources",
	"scrapers": "/api/v2/scrapers",
	"swagger":  "/api/v2/swagger.json",
	"system": map[string]string{
		"metrics": "/metrics",
		"debug":   "/debug/pprof",
		"health":  "/health",
	},
	"tasks":     "/api/v2/tasks",
	"checks":    "/api/v2/checks",
	"telegrafs": "/api/v2/telegrafs",
	"plugins":   "/api/v2/telegraf/plugins",
	"users":     "/api/v2/users",
	"write":     "/api/v2/write",
	"delete":    "/api/v2/delete",
}

func serveLinksHandler(errorHandler influxdb.HTTPErrorHandler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()
		if err := encodeResponse(ctx, w, http.StatusOK, apiLinks); err != nil {
			errorHandler.HandleHTTPError(ctx, err, w)
		}
	}
	return http.HandlerFunc(fn)
}
<commit_msg>fix(tasks): update tasks authorization (#16994)<commit_after>package http

import (
	"net/http"

	"github.com/go-chi/chi"
	"github.com/influxdata/influxdb"
	"github.com/influxdata/influxdb/authorizer"
	"github.com/influxdata/influxdb/chronograf/server"
	"github.com/influxdata/influxdb/http/metric"
	"github.com/influxdata/influxdb/kit/prom"
	kithttp "github.com/influxdata/influxdb/kit/transport/http"
	"github.com/influxdata/influxdb/query"
	"github.com/influxdata/influxdb/storage"
	"github.com/prometheus/client_golang/prometheus"
	"go.uber.org/zap"
)

// APIHandler is a collection of all the service handlers.
type APIHandler struct {
	chi.Router
}

// APIBackend is all services and associated parameters required to construct
// an APIHandler.
type APIBackend struct {
	AssetsPath string // if empty then assets are served from bindata.
	Logger     *zap.Logger
	influxdb.HTTPErrorHandler
	SessionRenewDisabled bool
	// MaxBatchSizeBytes is the maximum number of bytes which can be written
	// in a single points batch
	MaxBatchSizeBytes int64

	// WriteParserMaxBytes specifies the maximum number of bytes that may be allocated when processing a single
	// write request. A value of zero specifies there is no limit.
	WriteParserMaxBytes int

	// WriteParserMaxLines specifies the maximum number of lines that may be parsed when processing a single
	// write request. A value of zero specifies there is no limit.
	WriteParserMaxLines int

	// WriteParserMaxValues specifies the maximum number of values that may be parsed when processing a single
	// write request. A value of zero specifies there is no limit.
	WriteParserMaxValues int

	NewBucketService func(*influxdb.Source) (influxdb.BucketService, error)
	NewQueryService  func(*influxdb.Source) (query.ProxyQueryService, error)

	WriteEventRecorder metric.EventRecorder
	QueryEventRecorder metric.EventRecorder

	PointsWriter                    storage.PointsWriter
	DeleteService                   influxdb.DeleteService
	BackupService                   influxdb.BackupService
	KVBackupService                 influxdb.KVBackupService
	AuthorizationService            influxdb.AuthorizationService
	BucketService                   influxdb.BucketService
	SessionService                  influxdb.SessionService
	UserService                     influxdb.UserService
	OrganizationService             influxdb.OrganizationService
	UserResourceMappingService      influxdb.UserResourceMappingService
	LabelService                    influxdb.LabelService
	DashboardService                influxdb.DashboardService
	DashboardOperationLogService    influxdb.DashboardOperationLogService
	BucketOperationLogService       influxdb.BucketOperationLogService
	UserOperationLogService         influxdb.UserOperationLogService
	OrganizationOperationLogService influxdb.OrganizationOperationLogService
	SourceService                   influxdb.SourceService
	VariableService                 influxdb.VariableService
	PasswordsService                influxdb.PasswordsService
	OnboardingService               influxdb.OnboardingService
	InfluxQLService                 query.ProxyQueryService
	FluxService                     query.ProxyQueryService
	TaskService                     influxdb.TaskService
	CheckService                    influxdb.CheckService
	TelegrafService                 influxdb.TelegrafConfigStore
	ScraperTargetStoreService       influxdb.ScraperTargetStoreService
	SecretService                   influxdb.SecretService
	LookupService                   influxdb.LookupService
	ChronografService               *server.Service
	OrgLookupService                authorizer.OrganizationService
	DocumentService                 influxdb.DocumentService
	NotificationRuleStore           influxdb.NotificationRuleStore
	NotificationEndpointService     influxdb.NotificationEndpointService
}

// PrometheusCollectors exposes the prometheus collectors associated with an APIBackend.
func (b *APIBackend) PrometheusCollectors() []prometheus.Collector {
	var cs []prometheus.Collector

	if pc, ok := b.WriteEventRecorder.(prom.PrometheusCollector); ok {
		cs = append(cs, pc.PrometheusCollectors()...)
	}

	if pc, ok := b.QueryEventRecorder.(prom.PrometheusCollector); ok {
		cs = append(cs, pc.PrometheusCollectors()...)
	}

	return cs
}

// APIHandlerOptFn is a functional input param to set parameters on
// the APIHandler.
type APIHandlerOptFn func(chi.Router)

// WithResourceHandler registers a resource handler on the APIHandler.
func WithResourceHandler(resHandler kithttp.ResourceHandler) APIHandlerOptFn {
	return func(h chi.Router) {
		h.Mount(resHandler.Prefix(), resHandler)
	}
}

// NewAPIHandler constructs all api handlers beneath it and returns an APIHandler
func NewAPIHandler(b *APIBackend, opts ...APIHandlerOptFn) *APIHandler {
	h := &APIHandler{
		Router: newBaseChiRouter(b.HTTPErrorHandler),
	}

	b.UserResourceMappingService = authorizer.NewURMService(b.OrgLookupService, b.UserResourceMappingService)

	h.Mount("/api/v2", serveLinksHandler(b.HTTPErrorHandler))

	authorizationBackend := NewAuthorizationBackend(b.Logger.With(zap.String("handler", "authorization")), b)
	authorizationBackend.AuthorizationService = authorizer.NewAuthorizationService(b.AuthorizationService)
	h.Mount(prefixAuthorization, NewAuthorizationHandler(b.Logger, authorizationBackend))

	bucketBackend := NewBucketBackend(b.Logger.With(zap.String("handler", "bucket")), b)
	bucketBackend.BucketService = authorizer.NewBucketService(b.BucketService)
	h.Mount(prefixBuckets, NewBucketHandler(b.Logger, bucketBackend))

	checkBackend := NewCheckBackend(b.Logger.With(zap.String("handler", "check")), b)
	checkBackend.CheckService = authorizer.NewCheckService(b.CheckService,
		b.UserResourceMappingService, b.OrganizationService)
	h.Mount(prefixChecks, NewCheckHandler(b.Logger, checkBackend))

	h.Mount(prefixChronograf, NewChronografHandler(b.ChronografService, b.HTTPErrorHandler))

	dashboardBackend := NewDashboardBackend(b.Logger.With(zap.String("handler", "dashboard")), b)
	dashboardBackend.DashboardService = authorizer.NewDashboardService(b.DashboardService)
	h.Mount(prefixDashboards, NewDashboardHandler(b.Logger, dashboardBackend))

	deleteBackend := NewDeleteBackend(b.Logger.With(zap.String("handler", "delete")), b)
	h.Mount(prefixDelete, NewDeleteHandler(b.Logger, deleteBackend))

	documentBackend := NewDocumentBackend(b.Logger.With(zap.String("handler", "document")), b)
	h.Mount(prefixDocuments, NewDocumentHandler(documentBackend))

	fluxBackend := NewFluxBackend(b.Logger.With(zap.String("handler", "query")), b)
	h.Mount(prefixQuery, NewFluxHandler(b.Logger, fluxBackend))

	h.Mount(prefixLabels, NewLabelHandler(b.Logger, authorizer.NewLabelService(b.LabelService), b.HTTPErrorHandler))

	notificationEndpointBackend := NewNotificationEndpointBackend(b.Logger.With(zap.String("handler", "notificationEndpoint")), b)
	notificationEndpointBackend.NotificationEndpointService = authorizer.NewNotificationEndpointService(b.NotificationEndpointService,
		b.UserResourceMappingService, b.OrganizationService)
	h.Mount(prefixNotificationEndpoints, NewNotificationEndpointHandler(notificationEndpointBackend.Logger(), notificationEndpointBackend))

	notificationRuleBackend := NewNotificationRuleBackend(b.Logger.With(zap.String("handler", "notification_rule")), b)
	notificationRuleBackend.NotificationRuleStore = authorizer.NewNotificationRuleStore(b.NotificationRuleStore,
		b.UserResourceMappingService, b.OrganizationService)
	h.Mount(prefixNotificationRules, NewNotificationRuleHandler(b.Logger, notificationRuleBackend))

	orgBackend := NewOrgBackend(b.Logger.With(zap.String("handler", "org")), b)
	orgBackend.OrganizationService = authorizer.NewOrgService(b.OrganizationService)
	h.Mount(prefixOrganizations, NewOrgHandler(b.Logger, orgBackend))

	scraperBackend := NewScraperBackend(b.Logger.With(zap.String("handler", "scraper")), b)
	scraperBackend.ScraperStorageService = authorizer.NewScraperTargetStoreService(b.ScraperTargetStoreService,
		b.UserResourceMappingService,
		b.OrganizationService)
	h.Mount(prefixTargets, NewScraperHandler(b.Logger, scraperBackend))

	sessionBackend := newSessionBackend(b.Logger.With(zap.String("handler", "session")), b)
	sessionHandler := NewSessionHandler(b.Logger, sessionBackend)
	h.Mount(prefixSignIn, sessionHandler)
	h.Mount(prefixSignOut, sessionHandler)

	setupBackend := NewSetupBackend(b.Logger.With(zap.String("handler", "setup")), b)
	h.Mount(prefixSetup, NewSetupHandler(b.Logger, setupBackend))

	sourceBackend := NewSourceBackend(b.Logger.With(zap.String("handler", "source")), b)
	sourceBackend.SourceService = authorizer.NewSourceService(b.SourceService)
	sourceBackend.BucketService = authorizer.NewBucketService(b.BucketService)
	h.Mount(prefixSources, NewSourceHandler(b.Logger, sourceBackend))

	h.Mount("/api/v2/swagger.json", newSwaggerLoader(b.Logger.With(zap.String("service", "swagger-loader")), b.HTTPErrorHandler))

	taskLogger := b.Logger.With(zap.String("handler", "bucket"))
	taskBackend := NewTaskBackend(taskLogger, b)
	taskBackend.TaskService = authorizer.NewTaskService(taskLogger, b.TaskService)
	taskHandler := NewTaskHandler(b.Logger, taskBackend)
	h.Mount(prefixTasks, taskHandler)

	telegrafBackend := NewTelegrafBackend(b.Logger.With(zap.String("handler", "telegraf")), b)
	telegrafBackend.TelegrafService = authorizer.NewTelegrafConfigService(b.TelegrafService, b.UserResourceMappingService)
	h.Mount(prefixTelegrafPlugins, NewTelegrafHandler(b.Logger, telegrafBackend))
	h.Mount(prefixTelegraf, NewTelegrafHandler(b.Logger, telegrafBackend))

	userBackend := NewUserBackend(b.Logger.With(zap.String("handler", "user")), b)
	userBackend.UserService = authorizer.NewUserService(b.UserService)
	userBackend.PasswordsService = authorizer.NewPasswordService(b.PasswordsService)
	userHandler := NewUserHandler(b.Logger, userBackend)
	h.Mount(prefixMe, userHandler)
	h.Mount(prefixUsers, userHandler)

	variableBackend := NewVariableBackend(b.Logger.With(zap.String("handler", "variable")), b)
	variableBackend.VariableService = authorizer.NewVariableService(b.VariableService)
	h.Mount(prefixVariables, NewVariableHandler(b.Logger, variableBackend))

	backupBackend := NewBackupBackend(b)
	backupBackend.BackupService = authorizer.NewBackupService(backupBackend.BackupService)
	h.Mount(prefixBackup, NewBackupHandler(backupBackend))

	writeBackend := NewWriteBackend(b.Logger.With(zap.String("handler", "write")), b)
	h.Mount(prefixWrite, NewWriteHandler(b.Logger, writeBackend,
		WithMaxBatchSizeBytes(b.MaxBatchSizeBytes),
		WithParserMaxBytes(b.WriteParserMaxBytes),
		WithParserMaxLines(b.WriteParserMaxLines),
		WithParserMaxValues(b.WriteParserMaxValues),
	))

	for _, o := range opts {
		o(h)
	}
	return h
}

var apiLinks = map[string]interface{}{
	// when adding new links, please take care to keep this list alphabetical
	// as this makes it easier to verify values against the swagger document.
	"authorizations": "/api/v2/authorizations",
	"backup":         "/api/v2/backup",
	"buckets":        "/api/v2/buckets",
	"dashboards":     "/api/v2/dashboards",
	"external": map[string]string{
		"statusFeed": "https://www.influxdata.com/feed/json",
	},
	"labels":                "/api/v2/labels",
	"variables":             "/api/v2/variables",
	"me":                    "/api/v2/me",
	"notificationRules":     "/api/v2/notificationRules",
	"notificationEndpoints": "/api/v2/notificationEndpoints",
	"orgs":                  "/api/v2/orgs",
	"query": map[string]string{
		"self":        "/api/v2/query",
		"ast":         "/api/v2/query/ast",
		"analyze":     "/api/v2/query/analyze",
		"suggestions": "/api/v2/query/suggestions",
	},
	"setup":    "/api/v2/setup",
	"signin":   "/api/v2/signin",
	"signout":  "/api/v2/signout",
	"sources":  "/api/v2/sources",
	"scrapers": "/api/v2/scrapers",
	"swagger":  "/api/v2/swagger.json",
	"system": map[string]string{
		"metrics": "/metrics",
		"debug":   "/debug/pprof",
		"health":  "/health",
	},
	"tasks":     "/api/v2/tasks",
	"checks":    "/api/v2/checks",
	"telegrafs": "/api/v2/telegrafs",
	"plugins":   "/api/v2/telegraf/plugins",
	"users":     "/api/v2/users",
	"write":     "/api/v2/write",
	"delete":    "/api/v2/delete",
}

func serveLinksHandler(errorHandler influxdb.HTTPErrorHandler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		ctx := r.Context()
		if err := encodeResponse(ctx, w, http.StatusOK, apiLinks); err != nil {
			errorHandler.HandleHTTPError(ctx, err, w)
		}
	}
	return http.HandlerFunc(fn)
}
<|endoftext|>


<commit_before>package storage

import (
	"fmt"

	"github.com/docker/distribution"
	"github.com/docker/distribution/context"
	"github.com/docker/distribution/digest"
	"github.com/docker/distribution/manifest/schema1"
	"github.com/docker/libtrust"
)

type manifestStore struct {
	repository                 *repository
	revisionStore              *revisionStore
	tagStore                   *tagStore
	ctx                        context.Context
	skipDependencyVerification bool
}

var _ distribution.ManifestService = &manifestStore{}

func (ms *manifestStore) Exists(dgst digest.Digest) (bool, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Exists")

	_, err := ms.revisionStore.blobStore.Stat(ms.ctx, dgst)
	if err != nil {
		if err == distribution.ErrBlobUnknown {
			return false, nil
		}

		return false, err
	}

	return true, nil
}

func (ms *manifestStore) Get(dgst digest.Digest) (*schema1.SignedManifest, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Get")
	return ms.revisionStore.get(ms.ctx, dgst)
}

// SkipLayerVerification allows a manifest to be Put before it's
// layers are on the filesystem
func SkipLayerVerification(ms distribution.ManifestService) error {
	if ms, ok := ms.(*manifestStore); ok {
		ms.skipDependencyVerification = true
		return nil
	}
	return fmt.Errorf("skip layer verification only valid for manifeststore")
}

func (ms *manifestStore) Put(manifest *schema1.SignedManifest) error {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Put")

	if err := ms.verifyManifest(ms.ctx, manifest); err != nil {
		return err
	}

	// Store the revision of the manifest
	revision, err := ms.revisionStore.put(ms.ctx, manifest)
	if err != nil {
		return err
	}

	// Now, tag the manifest
	return ms.tagStore.tag(manifest.Tag, revision.Digest)
}

// Delete removes the revision of the specified manfiest.
func (ms *manifestStore) Delete(dgst digest.Digest) error {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Delete")
	return ms.revisionStore.delete(ms.ctx, dgst)
}

func (ms *manifestStore) Tags() ([]string, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Tags")
	return ms.tagStore.tags()
}

func (ms *manifestStore) ExistsByTag(tag string) (bool, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).ExistsByTag")
	return ms.tagStore.exists(tag)
}

func (ms *manifestStore) GetByTag(tag string, options ...distribution.ManifestServiceOption) (*schema1.SignedManifest, error) {
	for _, option := range options {
		err := option(ms)
		if err != nil {
			return nil, err
		}
	}

	context.GetLogger(ms.ctx).Debug("(*manifestStore).GetByTag")
	dgst, err := ms.tagStore.resolve(tag)
	if err != nil {
		return nil, err
	}

	return ms.revisionStore.get(ms.ctx, dgst)
}

// verifyManifest ensures that the manifest content is valid from the
// perspective of the registry. It ensures that the signature is valid for the
// enclosed payload. As a policy, the registry only tries to store valid
// content, leaving trust policies of that content up to consumers.
func (ms *manifestStore) verifyManifest(ctx context.Context, mnfst *schema1.SignedManifest) error {
	var errs distribution.ErrManifestVerification
	if mnfst.Name != ms.repository.Name() {
		errs = append(errs, fmt.Errorf("repository name does not match manifest name"))
	}

	if len(mnfst.History) != len(mnfst.FSLayers) {
		errs = append(errs, fmt.Errorf("mismatched history and fslayer cardinality %d != %d",
			len(mnfst.History), len(mnfst.FSLayers)))
	}

	if _, err := schema1.Verify(mnfst); err != nil {
		switch err {
		case libtrust.ErrMissingSignatureKey, libtrust.ErrInvalidJSONContent, libtrust.ErrMissingSignatureKey:
			errs = append(errs, distribution.ErrManifestUnverified{})
		default:
			if err.Error() == "invalid signature" { // TODO(stevvooe): This should be exported by libtrust
				errs = append(errs, distribution.ErrManifestUnverified{})
			} else {
				errs = append(errs, err)
			}
		}
	}

	if !ms.skipDependencyVerification {
		for _, fsLayer := range mnfst.FSLayers {
			_, err := ms.repository.Blobs(ctx).Stat(ctx, fsLayer.BlobSum)
			if err != nil {
				if err != distribution.ErrBlobUnknown {
					errs = append(errs, err)
				}

				// On error here, we always append unknown blob errors.
				errs = append(errs, distribution.ErrManifestBlobUnknown{Digest: fsLayer.BlobSum})
			}
		}
	}
	if len(errs) != 0 {
		return errs
	}

	return nil
}
<commit_msg>Use case of type name<commit_after>package storage

import (
	"fmt"

	"github.com/docker/distribution"
	"github.com/docker/distribution/context"
	"github.com/docker/distribution/digest"
	"github.com/docker/distribution/manifest/schema1"
	"github.com/docker/libtrust"
)

type manifestStore struct {
	repository                 *repository
	revisionStore              *revisionStore
	tagStore                   *tagStore
	ctx                        context.Context
	skipDependencyVerification bool
}

var _ distribution.ManifestService = &manifestStore{}

func (ms *manifestStore) Exists(dgst digest.Digest) (bool, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Exists")

	_, err := ms.revisionStore.blobStore.Stat(ms.ctx, dgst)
	if err != nil {
		if err == distribution.ErrBlobUnknown {
			return false, nil
		}

		return false, err
	}

	return true, nil
}

func (ms *manifestStore) Get(dgst digest.Digest) (*schema1.SignedManifest, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Get")
	return ms.revisionStore.get(ms.ctx, dgst)
}

// SkipLayerVerification allows a manifest to be Put before it's
// layers are on the filesystem
func SkipLayerVerification(ms distribution.ManifestService) error {
	if ms, ok := ms.(*manifestStore); ok {
		ms.skipDependencyVerification = true
		return nil
	}
	return fmt.Errorf("skip layer verification only valid for manifestStore")
}

func (ms *manifestStore) Put(manifest *schema1.SignedManifest) error {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Put")

	if err := ms.verifyManifest(ms.ctx, manifest); err != nil {
		return err
	}

	// Store the revision of the manifest
	revision, err := ms.revisionStore.put(ms.ctx, manifest)
	if err != nil {
		return err
	}

	// Now, tag the manifest
	return ms.tagStore.tag(manifest.Tag, revision.Digest)
}

// Delete removes the revision of the specified manfiest.
func (ms *manifestStore) Delete(dgst digest.Digest) error {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Delete")
	return ms.revisionStore.delete(ms.ctx, dgst)
}

func (ms *manifestStore) Tags() ([]string, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).Tags")
	return ms.tagStore.tags()
}

func (ms *manifestStore) ExistsByTag(tag string) (bool, error) {
	context.GetLogger(ms.ctx).Debug("(*manifestStore).ExistsByTag")
	return ms.tagStore.exists(tag)
}

func (ms *manifestStore) GetByTag(tag string, options ...distribution.ManifestServiceOption) (*schema1.SignedManifest, error) {
	for _, option := range options {
		err := option(ms)
		if err != nil {
			return nil, err
		}
	}

	context.GetLogger(ms.ctx).Debug("(*manifestStore).GetByTag")
	dgst, err := ms.tagStore.resolve(tag)
	if err != nil {
		return nil, err
	}

	return ms.revisionStore.get(ms.ctx, dgst)
}

// verifyManifest ensures that the manifest content is valid from the
// perspective of the registry. It ensures that the signature is valid for the
// enclosed payload. As a policy, the registry only tries to store valid
// content, leaving trust policies of that content up to consumers.
func (ms *manifestStore) verifyManifest(ctx context.Context, mnfst *schema1.SignedManifest) error {
	var errs distribution.ErrManifestVerification
	if mnfst.Name != ms.repository.Name() {
		errs = append(errs, fmt.Errorf("repository name does not match manifest name"))
	}

	if len(mnfst.History) != len(mnfst.FSLayers) {
		errs = append(errs, fmt.Errorf("mismatched history and fslayer cardinality %d != %d",
			len(mnfst.History), len(mnfst.FSLayers)))
	}

	if _, err := schema1.Verify(mnfst); err != nil {
		switch err {
		case libtrust.ErrMissingSignatureKey, libtrust.ErrInvalidJSONContent, libtrust.ErrMissingSignatureKey:
			errs = append(errs, distribution.ErrManifestUnverified{})
		default:
			if err.Error() == "invalid signature" { // TODO(stevvooe): This should be exported by libtrust
				errs = append(errs, distribution.ErrManifestUnverified{})
			} else {
				errs = append(errs, err)
			}
		}
	}

	if !ms.skipDependencyVerification {
		for _, fsLayer := range mnfst.FSLayers {
			_, err := ms.repository.Blobs(ctx).Stat(ctx, fsLayer.BlobSum)
			if err != nil {
				if err != distribution.ErrBlobUnknown {
					errs = append(errs, err)
				}

				// On error here, we always append unknown blob errors.
				errs = append(errs, distribution.ErrManifestBlobUnknown{Digest: fsLayer.BlobSum})
			}
		}
	}
	if len(errs) != 0 {
		return errs
	}

	return nil
}
<|endoftext|>


<commit_before>package evaluator

import "monkey/ast"
import "monkey/object"

var (
	NULL  = &object.Null{}
	TRUE  = &object.Boolean{Value: true}
	FALSE = &object.Boolean{Value: false}
)

func Eval(node ast.Node) object.Object {
	switch node := node.(type) {
	// Statements
	case *ast.Program:
		return evalStatements(node.Statements)
	case *ast.ExpressionStatement:
		return Eval(node.Expression)
	// Expressions
	case *ast.IntegerLiteral:
		return &object.Integer{Value: node.Value}
	case *ast.Boolean:
		return nativeBoolToBooleanObject(node.Value)
	case *ast.PrefixExpression:
		right := Eval(node.Right)
		return evalPrefixExpression(node.Operator, right)
	}

	return nil
}

func evalStatements(stmts []ast.Statement) object.Object {
	var result object.Object

	for _, statement := range stmts {
		result = Eval(statement)
	}

	return result
}

func nativeBoolToBooleanObject(input bool) *object.Boolean {
	if input {
		return TRUE
	}
	return FALSE
}

func evalPrefixExpression(operator string, right object.Object) object.Object {
	switch operator {
	case "!":
		return evalBangOperatorExpression(right)
	case "-":
		return evalMinusPrefixOperatorExpression(right)
	default:
		return NULL
	}
}

func evalBangOperatorExpression(right object.Object) object.Object {
	switch right {
	case TRUE:
		return FALSE
	case FALSE:
		return TRUE
	case NULL:
		return TRUE
	default:
		return FALSE
	}
}

func evalMinusPrefixOperatorExpression(right object.Object) object.Object {
	if right.Type() != object.INTEGER_OBJ {
		return NULL
	}

	value := right.(*object.Integer).Value
	return &object.Integer{Value: -value}
}
<commit_msg>add doc comments<commit_after>// Package evaluator : Prcesses an AST node by node to execute the program
package evaluator

import "monkey/ast"
import "monkey/object"

// Single reference Objects
var (
	NULL  = &object.Null{}
	TRUE  = &object.Boolean{Value: true}
	FALSE = &object.Boolean{Value: false}
)

// Eval : Takes a Node and evaluates it into its corresponding Object
func Eval(node ast.Node) object.Object {
	switch node := node.(type) {
	// Statements
	case *ast.Program:
		return evalStatements(node.Statements)
	case *ast.ExpressionStatement:
		return Eval(node.Expression)
	// Expressions
	case *ast.IntegerLiteral:
		return &object.Integer{Value: node.Value}
	case *ast.Boolean:
		return nativeBoolToBooleanObject(node.Value)
	case *ast.PrefixExpression:
		right := Eval(node.Right)
		return evalPrefixExpression(node.Operator, right)
	}

	return nil
}

func evalStatements(stmts []ast.Statement) object.Object {
	var result object.Object

	for _, statement := range stmts {
		result = Eval(statement)
	}

	return result
}

func nativeBoolToBooleanObject(input bool) *object.Boolean {
	if input {
		return TRUE
	}
	return FALSE
}

func evalPrefixExpression(operator string, right object.Object) object.Object {
	switch operator {
	case "!":
		return evalBangOperatorExpression(right)
	case "-":
		return evalMinusPrefixOperatorExpression(right)
	default:
		return NULL
	}
}

func evalBangOperatorExpression(right object.Object) object.Object {
	switch right {
	case TRUE:
		return FALSE
	case FALSE:
		return TRUE
	case NULL:
		return TRUE
	default:
		return FALSE
	}
}

func evalMinusPrefixOperatorExpression(right object.Object) object.Object {
	if right.Type() != object.INTEGER_OBJ {
		return NULL
	}

	value := right.(*object.Integer).Value
	return &object.Integer{Value: -value}
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"io"
	"log"
	"net/url"
	"os"
	"path/filepath"
	"time"
)

func SpitSlurp() {
	var connStr = fmt.Sprintf("%s:%s@%s/%s?charset=utf8mb4,utf8&allowOldPasswords=1&parseTime=true", Config.Evh1.DbUser, Config.Evh1.DbPass, Config.Evh1.DbHost, Config.Evh1.DbName)

	if Config.Evh1.Timezone != "" {
		connStr = connStr + "&loc=" + url.QueryEscape(Config.Evh1.Timezone)
	}

	db, err := sql.Open("mysql", connStr)
	if err != nil {
		log.Println("ERROR: sql.Open:", err.Error())
		return
	}
	defer db.Close()

	// Open doesn't open a connection. Validate DSN data:
	err = db.Ping()
	if err != nil {
		log.Println("ERROR: db.Ping:", err.Error())
		return
	}

	// Prepare statement for inserting data
	rows, err := db.Query("SELECT id, sessionid, name from Files where 1 order by id")
	if err != nil {
		log.Println("ERROR: query error:", err.Error())
		return
	}

	// Loop over files in EVH
	for rows.Next() {
		var id int
		var sessionid, name string

		err := rows.Scan(&id, &sessionid, &name)
		if err != nil {
			log.Println("ERROR: row error:", err.Error())
			return
		}

		// Fetch the rest of the information for the session
		var fileid, size int
		var avail, dnldcode, modcode, srcemail, destemail, description string
		var indate, outdate time.Time
		sessinfo, sesserr := db.Prepare("select Sessions.id, dnldcode, modcode, indate, outdate, avail, srcemail, destemail, size, description, Files.id from Sessions,Files where Sessions.id = ? and Files.sessionid=Sessions.id")
		if sesserr != nil {
			log.Println("ERROR: query error:", sesserr.Error())
			return
		}
		defer sessinfo.Close()

		sessinfoerr := sessinfo.QueryRow(sessionid).Scan(&sessionid, &dnldcode, &modcode, &indate, &outdate, &avail, &srcemail, &destemail, &size, &description, &fileid)
		if sessinfoerr != nil {
			log.Println("ERROR: row error:", sessinfoerr.Error())
			return
		}

		// Does this already exist (skip if it does)
		var trackerfile = filepath.Join(Config.Server.Assets, dnldcode, TrackerFileName)
		tracker, loaderr := LoadTrackerFromFile(trackerfile)
		if loaderr != nil {
			log.Println("Found new file to migrate:", dnldcode)
		} else {
			log.Println("Skipping file, already migrated: ", dnldcode)
			continue
		}

		// New Tracker, lets get this file migrated!
		tracker = NewTracker(dnldcode)
		tracker.Description = description
		tracker.Vercode = dnldcode
		tracker.When = indate
		tracker.ExpirationDate = outdate
		tracker.Expiration = avail
		tracker.ExpirationStr = tracker.ExpirationDate.Format(TimeLayout)
		tracker.SrcEmail = srcemail
		tracker.DstEmail = destemail
		tracker.Size = float64(size)
		tracker.SizeMB = tracker.Size / 1024 / 1024

		var file = NewFile(name, tracker.BaseDir)
		file.Size = tracker.Size
		file.SizeMB = tracker.SizeMB
		file.Saved = true
		file.WhenSaved = tracker.When.Format(TimeLayout)

		tracker.Files = append(tracker.Files, file)

		// Create new asset dir
		mkdirerr := os.MkdirAll(tracker.BaseDir, 0700)
		if mkdirerr != nil {
			log.Println(dnldcode, "ERROR: Could not create tracker dir:", mkdirerr.Error())
			return
		}

		// Write tracker
		saveerr := tracker.Save()
		if saveerr != nil {
			log.Println(dnldcode, "ERROR: Could not save tracker:", saveerr.Error())
			return
		}

		// Copy (or move) file to new location
		var oldfile = filepath.Join(Config.Evh1.Assets, tracker.Dnldcode, name)
		var newfile = filepath.Join(Config.Server.Assets, tracker.Dnldcode, file.Base64Name)

		// Move
		if Config.Evh1.Move {
			moveerr := os.Rename(oldfile, newfile)
			if moveerr != nil {
				log.Println(dnldcode, "ERROR: Could not move file:", moveerr.Error())
			} else {
				log.Println(dnldcode, "Move successful")
			}
		} else { // Copy
			// Create destination file
			dst, dsterr := os.Create(newfile)
			if dsterr != nil {
				log.Println(fmt.Sprintf("%s ERROR: could create empty file: %s", dnldcode, dsterr.Error()))
				return
			}

			// Open old file for copying
			fhandle, tmpferr := os.Open(oldfile)
			if tmpferr != nil {
				log.Println(fmt.Sprintf("%s ERROR: could not open old file for copy: %s", dnldcode, tmpferr.Error()))
				return
			}

			// Copy the uploaded file to the destination file
			bytes, cpyerr := io.Copy(dst, fhandle)
			if cpyerr != nil {
				log.Println(fmt.Sprintf("%s ERROR: could not write file contents: %s", dnldcode, cpyerr.Error()))
				return
			}
			fhandle.Close()
			dst.Close()

			log.Println(fmt.Sprintf("%s Copied %.2f MB", dnldcode, float64(bytes)/1024/1024))
		}
	}
}
<commit_msg>Make evh21import more resilient to errors<commit_after>package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"io"
	"log"
	"net/url"
	"os"
	"path/filepath"
	"time"
)

func SpitSlurp() {
	var connStr = fmt.Sprintf("%s:%s@%s/%s?charset=utf8mb4,utf8&allowOldPasswords=1&parseTime=true", Config.Evh1.DbUser, Config.Evh1.DbPass, Config.Evh1.DbHost, Config.Evh1.DbName)

	if Config.Evh1.Timezone != "" {
		connStr = connStr + "&loc=" + url.QueryEscape(Config.Evh1.Timezone)
	}

	db, err := sql.Open("mysql", connStr)
	if err != nil {
		log.Println("ERROR: sql.Open:", err.Error())
		return
	}
	defer db.Close()

	// Open doesn't open a connection. Validate DSN data:
	err = db.Ping()
	if err != nil {
		log.Println("ERROR: db.Ping:", err.Error())
		return
	}

	// Prepare statement for inserting data
	rows, err := db.Query("SELECT id, sessionid, name from Files where 1 order by id")
	if err != nil {
		log.Println("ERROR: query error:", err.Error())
		return
	}

	// Loop over files in EVH
	for rows.Next() {
		var id int
		var sessionid, name string

		err := rows.Scan(&id, &sessionid, &name)
		if err != nil {
			log.Println("ERROR: row error:", err.Error())
			return
		}

		// Fetch the rest of the information for the session
		var fileid, size int
		var avail, dnldcode, modcode, srcemail, destemail, description string
		var indate, outdate time.Time
		sessinfo, sesserr := db.Prepare("select Sessions.id, dnldcode, modcode, indate, outdate, avail, srcemail, destemail, size, description, Files.id from Sessions,Files where Sessions.id = ? and Files.sessionid=Sessions.id")
		if sesserr != nil {
			log.Println("ERROR: query error:", sesserr.Error())
			return
		}
		defer sessinfo.Close()

		sessinfoerr := sessinfo.QueryRow(sessionid).Scan(&sessionid, &dnldcode, &modcode, &indate, &outdate, &avail, &srcemail, &destemail, &size, &description, &fileid)
		if sessinfoerr != nil {
			log.Println("ERROR: row error:", sessinfoerr.Error())
			return
		}

		// Does this already exist (skip if it does)
		var trackerfile = filepath.Join(Config.Server.Assets, dnldcode, TrackerFileName)
		tracker, loaderr := LoadTrackerFromFile(trackerfile)
		if loaderr != nil {
			log.Println("Found new file to migrate:", dnldcode)
		} else {
			log.Println("Skipping file, already migrated: ", dnldcode)
			continue
		}

		// New Tracker, lets get this file migrated!
		tracker = NewTracker(dnldcode)
		tracker.Description = description
		tracker.Vercode = dnldcode
		tracker.When = indate
		tracker.ExpirationDate = outdate
		tracker.Expiration = avail
		tracker.ExpirationStr = tracker.ExpirationDate.Format(TimeLayout)
		tracker.SrcEmail = srcemail
		tracker.DstEmail = destemail
		tracker.Size = float64(size)
		tracker.SizeMB = tracker.Size / 1024 / 1024

		var file = NewFile(name, tracker.BaseDir)
		file.Size = tracker.Size
		file.SizeMB = tracker.SizeMB
		file.Saved = true
		file.WhenSaved = tracker.When.Format(TimeLayout)

		tracker.Files = append(tracker.Files, file)

		// Create new asset dir
		mkdirerr := os.MkdirAll(tracker.BaseDir, 0700)
		if mkdirerr != nil {
			log.Println(dnldcode, "ERROR: Could not create tracker dir:", mkdirerr.Error())
			return
		}

		// Write tracker
		saveerr := tracker.Save()
		if saveerr != nil {
			log.Println(dnldcode, "ERROR: Could not save tracker:", saveerr.Error())
			return
		}

		// Copy (or move) file to new location
		var oldfile = filepath.Join(Config.Evh1.Assets, tracker.Dnldcode, name)
		var newfile = filepath.Join(Config.Server.Assets, tracker.Dnldcode, file.Base64Name)

		// Move
		if Config.Evh1.Move {
			moveerr := os.Rename(oldfile, newfile)
			if moveerr != nil {
				log.Println(dnldcode, "ERROR: Could not move file:", moveerr.Error())
				RemoveDir(tracker.BaseDir)
				continue
			} else {
				log.Println(dnldcode, "Move successful")
			}
		} else { // Copy
			// Create destination file
			dst, dsterr := os.Create(newfile)
			if dsterr != nil {
				log.Println(fmt.Sprintf("%s ERROR: could create empty file: %s", dnldcode, dsterr.Error()))
				RemoveDir(tracker.BaseDir)
				continue
			}

			// Open old file for copying
			fhandle, tmpferr := os.Open(oldfile)
			if tmpferr != nil {
				log.Println(fmt.Sprintf("%s ERROR: could not open old file for copy: %s", dnldcode, tmpferr.Error()))
				RemoveDir(tracker.BaseDir)
				continue
			}

			// Copy the uploaded file to the destination file
			bytes, cpyerr := io.Copy(dst, fhandle)
			if cpyerr != nil {
				log.Println(fmt.Sprintf("%s ERROR: could not write file contents: %s", dnldcode, cpyerr.Error()))
				RemoveDir(tracker.BaseDir)
				continue
			}
			fhandle.Close()
			dst.Close()

			log.Println(fmt.Sprintf("%s Copied %.2f MB", dnldcode, float64(bytes)/1024/1024))
		}
	}
}
<|endoftext|>


<commit_before>// This file is used only when compiled with GAE support.
// GAE-based backend serves only templates.

// +build appengine

package main

import (
	"net/http"
	"strings"
	"time"

	"golang.org/x/net/context"

	"google.golang.org/appengine"
	"google.golang.org/appengine/log"
	"google.golang.org/appengine/urlfetch"
	"google.golang.org/appengine/user"
)

func init() {
	if err := initConfig("server.config", ""); err != nil {
		panic("initConfig: " + err.Error())
	}

	// use built-in memcache service
	cache = &gaeMemcache{}
	// apps hosted on GAE use a different HTTP transport
	httpTransport = func(c context.Context) http.RoundTripper {
		return &urlfetch.Transport{
			Context:  c,
			Deadline: 10 * time.Second,
		}
	}
	// staging instance is accessed only by whitelisted people/domains
	if len(config.Whitelist) > 0 {
		wrapHandler = checkWhitelist
	}
	rootHandleFn = serveTemplate
	registerHandlers()
}

// allowPassthrough returns true if the request r can be handled w/o whitelist check.
// Currently, only GAE Cron and Task Queue jobs are allowed.
func allowPassthrough(r *http.Request) bool {
	return strings.HasPrefix(r.URL.Path, "/sync/") ||
		r.Header.Get("x-appengine-cron") == "true" ||
		r.Header.Get("x-appengine-taskname") != ""
}

// checkWhitelist checks whether the current user is allowed to access
// handler h using isWhitelisted() func before handing over in-flight request.
// It redirects to GAE login URL if no user found or responds with 403
// (Forbidden) HTTP error code if the current user is not whitelisted.
func checkWhitelist(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if allowPassthrough(r) {
			h.ServeHTTP(w, r)
			return
		}
		c := appengine.NewContext(r)
		u := user.Current(c)
		switch {
		case u != nil && isWhitelisted(u.Email):
			h.ServeHTTP(w, r)
		case u != nil:
			errorf(c, "%s is not whitelisted", u.Email)
			http.Error(w, "Access denied, sorry. Try with a different account.", http.StatusForbidden)
		default:
			url, err := user.LoginURL(c, r.URL.Path)
			if err != nil {
				errorf(c, "user.LoginURL(%q): %v", r.URL.Path, err)
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			http.Redirect(w, r, url, http.StatusFound)
		}
	})
}

// newContext returns a context of the in-flight request r.
func newContext(r *http.Request) context.Context {
	return appengine.NewContext(r)
}

// logf logs an info message using appengine's context.
func logf(c context.Context, format string, args ...interface{}) {
	log.Infof(c, format, args...)
}

// errorf logs an error message using appengine's context.
func errorf(c context.Context, format string, args ...interface{}) {
	log.Errorf(c, format, args...)
}
<commit_msg>Compute correct passthrou prefix for /sync/ tasks<commit_after>// This file is used only when compiled with GAE support.
// GAE-based backend serves only templates.

// +build appengine

package main

import (
	"net/http"
	"path"
	"strings"
	"time"

	"golang.org/x/net/context"

	"google.golang.org/appengine"
	"google.golang.org/appengine/log"
	"google.golang.org/appengine/urlfetch"
	"google.golang.org/appengine/user"
)

// allow requests prefixed with passthruPrefix to bypass checkWhitelist
var passthruPrefix string

func init() {
	if err := initConfig("server.config", ""); err != nil {
		panic("initConfig: " + err.Error())
	}
	passthruPrefix = path.Join(config.Prefix, "/sync") + "/"
	// use built-in memcache service
	cache = &gaeMemcache{}
	// apps hosted on GAE use a different HTTP transport
	httpTransport = func(c context.Context) http.RoundTripper {
		return &urlfetch.Transport{
			Context:  c,
			Deadline: 10 * time.Second,
		}
	}
	// staging instance is accessed only by whitelisted people/domains
	if len(config.Whitelist) > 0 {
		wrapHandler = checkWhitelist
	}
	rootHandleFn = serveTemplate
	registerHandlers()
}

// allowPassthrough returns true if the request r can be handled w/o whitelist check.
// Currently, only GAE Cron and Task Queue jobs are allowed.
func allowPassthrough(r *http.Request) bool {
	return strings.HasPrefix(r.URL.Path, passthruPrefix) ||
		r.Header.Get("x-appengine-cron") == "true" ||
		r.Header.Get("x-appengine-taskname") != ""
}

// checkWhitelist checks whether the current user is allowed to access
// handler h using isWhitelisted() func before handing over in-flight request.
// It redirects to GAE login URL if no user found or responds with 403
// (Forbidden) HTTP error code if the current user is not whitelisted.
func checkWhitelist(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if allowPassthrough(r) {
			h.ServeHTTP(w, r)
			return
		}
		c := appengine.NewContext(r)
		u := user.Current(c)
		switch {
		case u != nil && isWhitelisted(u.Email):
			h.ServeHTTP(w, r)
		case u != nil:
			errorf(c, "%s is not whitelisted", u.Email)
			http.Error(w, "Access denied, sorry. Try with a different account.", http.StatusForbidden)
		default:
			url, err := user.LoginURL(c, r.URL.Path)
			if err != nil {
				errorf(c, "user.LoginURL(%q): %v", r.URL.Path, err)
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			http.Redirect(w, r, url, http.StatusFound)
		}
	})
}

// newContext returns a context of the in-flight request r.
func newContext(r *http.Request) context.Context {
	return appengine.NewContext(r)
}

// logf logs an info message using appengine's context.
func logf(c context.Context, format string, args ...interface{}) {
	log.Infof(c, format, args...)
}

// errorf logs an error message using appengine's context.
func errorf(c context.Context, format string, args ...interface{}) {
	log.Errorf(c, format, args...)
}
<|endoftext|>


<commit_before>package backends

import (
	"encoding/json"
	"fmt"
	"github.com/docker/libswarm/beam"
	"github.com/dotcloud/docker/api"
	"github.com/dotcloud/docker/pkg/version"
	"github.com/gorilla/mux"
	"net"
	"net/http"
)

func ApiServer() beam.Sender {
	backend := beam.NewServer()
	backend.OnSpawn(beam.Handler(func(ctx *beam.Message) error {
		instance := beam.Task(func(in beam.Receiver, out beam.Sender) {
			err := listenAndServe("tcp", "0.0.0.0:4243", out)
			if err != nil {
				fmt.Printf("listenAndServe: %v", err)
			}
		})
		_, err := ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: instance})
		return err
	}))
	return backend
}

type HttpApiFunc func(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error

func listenAndServe(proto, addr string, out beam.Sender) error {
	fmt.Println("Starting API server...")
	r, err := createRouter(out)
	if err != nil {
		return err
	}
	l, err := net.Listen(proto, addr)
	if err != nil {
		return err
	}
	httpSrv := http.Server{Addr: addr, Handler: r}
	return httpSrv.Serve(l)
}

func ping(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	_, err := w.Write([]byte{'O', 'K'})
	return err
}

func getContainersJSON(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if err := r.ParseForm(); err != nil {
		return err
	}

	o := beam.Obj(out)
	names, err := o.Ls()
	if err != nil {
		return err
	}

	return writeJSON(w, 200, names)
}

func createRouter(out beam.Sender) (*mux.Router, error) {
	r := mux.NewRouter()
	m := map[string]map[string]HttpApiFunc{
		"GET": {
			"/_ping":           ping,
			"/containers/json": getContainersJSON,
		},
		"POST":    {},
		"DELETE":  {},
		"OPTIONS": {},
	}

	for method, routes := range m {
		for route, fct := range routes {
			localRoute := route
			localFct := fct
			localMethod := method

			f := makeHttpHandler(out, localMethod, localRoute, localFct, version.Version("0.11.0"))

			// add the new route
			if localRoute == "" {
				r.Methods(localMethod).HandlerFunc(f)
			} else {
				r.Path("/v{version:[0-9.]+}" + localRoute).Methods(localMethod).HandlerFunc(f)
				r.Path(localRoute).Methods(localMethod).HandlerFunc(f)
			}
		}
	}

	return r, nil
}

func makeHttpHandler(out beam.Sender, localMethod string, localRoute string, handlerFunc HttpApiFunc, dockerVersion version.Version) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// log the request
		fmt.Printf("Calling %s %s\n", localMethod, localRoute)

		version := version.Version(mux.Vars(r)["version"])
		if version == "" {
			version = api.APIVERSION
		}

		if err := handlerFunc(out, version, w, r, mux.Vars(r)); err != nil {
			fmt.Printf("Error: %s", err)
		}
	}
}

func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(code)
	enc := json.NewEncoder(w)
	return enc.Encode(v)
}
<commit_msg>Use http.StatusOK instead of int<commit_after>package backends

import (
	"encoding/json"
	"fmt"
	"github.com/docker/libswarm/beam"
	"github.com/dotcloud/docker/api"
	"github.com/dotcloud/docker/pkg/version"
	"github.com/gorilla/mux"
	"net"
	"net/http"
)

func ApiServer() beam.Sender {
	backend := beam.NewServer()
	backend.OnSpawn(beam.Handler(func(ctx *beam.Message) error {
		instance := beam.Task(func(in beam.Receiver, out beam.Sender) {
			err := listenAndServe("tcp", "0.0.0.0:4243", out)
			if err != nil {
				fmt.Printf("listenAndServe: %v", err)
			}
		})
		_, err := ctx.Ret.Send(&beam.Message{Verb: beam.Ack, Ret: instance})
		return err
	}))
	return backend
}

type HttpApiFunc func(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error

func listenAndServe(proto, addr string, out beam.Sender) error {
	fmt.Println("Starting API server...")
	r, err := createRouter(out)
	if err != nil {
		return err
	}
	l, err := net.Listen(proto, addr)
	if err != nil {
		return err
	}
	httpSrv := http.Server{Addr: addr, Handler: r}
	return httpSrv.Serve(l)
}

func ping(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	_, err := w.Write([]byte{'O', 'K'})
	return err
}

func getContainersJSON(out beam.Sender, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
	if err := r.ParseForm(); err != nil {
		return err
	}

	o := beam.Obj(out)
	names, err := o.Ls()
	if err != nil {
		return err
	}

	return writeJSON(w, http.StatusOK, names)
}

func createRouter(out beam.Sender) (*mux.Router, error) {
	r := mux.NewRouter()
	m := map[string]map[string]HttpApiFunc{
		"GET": {
			"/_ping":           ping,
			"/containers/json": getContainersJSON,
		},
		"POST":    {},
		"DELETE":  {},
		"OPTIONS": {},
	}

	for method, routes := range m {
		for route, fct := range routes {
			localRoute := route
			localFct := fct
			localMethod := method

			f := makeHttpHandler(out, localMethod, localRoute, localFct, version.Version("0.11.0"))

			// add the new route
			if localRoute == "" {
				r.Methods(localMethod).HandlerFunc(f)
			} else {
				r.Path("/v{version:[0-9.]+}" + localRoute).Methods(localMethod).HandlerFunc(f)
				r.Path(localRoute).Methods(localMethod).HandlerFunc(f)
			}
		}
	}

	return r, nil
}

func makeHttpHandler(out beam.Sender, localMethod string, localRoute string, handlerFunc HttpApiFunc, dockerVersion version.Version) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// log the request
		fmt.Printf("Calling %s %s\n", localMethod, localRoute)

		version := version.Version(mux.Vars(r)["version"])
		if version == "" {
			version = api.APIVERSION
		}

		if err := handlerFunc(out, version, w, r, mux.Vars(r)); err != nil {
			fmt.Printf("Error: %s", err)
		}
	}
}

func writeJSON(w http.ResponseWriter, code int, v interface{}) error {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(code)
	enc := json.NewEncoder(w)
	return enc.Encode(v)
}
<|endoftext|>


<commit_before>package yaml

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strings"

	"github.com/qor/i18n"
	"gopkg.in/yaml.v2"
)

// New new YAML backend for I18n
func New(paths ...string) i18n.Backend {
	backend := &Backend{}

	var files []string
	for _, p := range paths {
		if file, err := os.Open(p); err == nil {
			defer file.Close()
			if fileInfo, err := file.Stat(); err == nil {
				if fileInfo.IsDir() {
					yamlFiles, _ := filepath.Glob(path.Join(p, "*.yaml"))
					files = append(files, yamlFiles...)

					ymlFiles, _ := filepath.Glob(path.Join(p, "*.yml"))
					files = append(files, ymlFiles...)
				} else if fileInfo.Mode().IsRegular() {
					files = append(files, p)
				}
			}
		}
	}
	for _, file := range files {
		if content, err := ioutil.ReadFile(file); err == nil {
			backend.contents = append(backend.contents, content)
		}
	}
	return backend
}

// NewWithWalk has the same functionality as New but uses filepath.Walk to find all the translation files recursively.
func NewWithWalk(paths ...string) i18n.Backend {
	backend := &Backend{}

	var files []string
	for _, p := range paths {
		filepath.Walk(p, func(path string, fileInfo os.FileInfo, err error) error {
			if isYamlFile(fileInfo) {
				files = append(files, path)
			}
			return nil
		})
	}
	for _, file := range files {
		if content, err := ioutil.ReadFile(file); err == nil {
			backend.contents = append(backend.contents, content)
		}
	}

	return backend
}

func isYamlFile(fileInfo os.FileInfo) bool {
	if fileInfo == nil {
		return false
	}
	return fileInfo.Mode().IsRegular() && (strings.HasSuffix(fileInfo.Name(), ".yml") || strings.HasSuffix(fileInfo.Name(), ".yaml"))
}

func walkFilesystem(fs http.FileSystem, entry http.File, prefix string) [][]byte {
	var (
		contents [][]byte
		err      error
		isRoot   bool
	)
	if entry == nil {
		if entry, err = fs.Open("/"); err != nil {
			return nil
		}
		isRoot = true
		defer entry.Close()
	}
	fileInfo, err := entry.Stat()
	if err != nil {
		return nil
	}
	if !isRoot {
		prefix = prefix + fileInfo.Name() + "/"
	}
	if fileInfo.IsDir() {
		if entries, err := entry.Readdir(-1); err == nil {
			for _, e := range entries {
				if file, err := fs.Open(prefix + e.Name()); err == nil {
					defer file.Close()
					contents = append(contents, walkFilesystem(fs, file, prefix)...)
				}
			}
		}
	} else if isYamlFile(fileInfo) {
		if content, err := ioutil.ReadAll(entry); err == nil {
			contents = append(contents, content)
		}
	}
	return contents
}

// NewWithFilesystem initializes a backend that reads translation files from an http.FileSystem.
func NewWithFilesystem(fss ...http.FileSystem) i18n.Backend {
	backend := &Backend{}

	for _, fs := range fss {
		backend.contents = append(backend.contents, walkFilesystem(fs, nil, "/")...)
	}
	return backend
}

// Backend YAML backend
type Backend struct {
	contents [][]byte
}

func loadTranslationsFromYaml(locale string, value interface{}, scopes []string) (translations []*i18n.Translation) {
	switch v := value.(type) {
	case yaml.MapSlice:
		for _, s := range v {
			results := loadTranslationsFromYaml(locale, s.Value, append(scopes, fmt.Sprint(s.Key)))
			translations = append(translations, results...)
		}
	default:
		var translation = &i18n.Translation{
			Locale: locale,
			Key:    strings.Join(scopes, "."),
			Value:  fmt.Sprint(v),
		}
		translations = append(translations, translation)
	}
	return
}

// LoadTranslations load translations from YAML backend
func (backend *Backend) LoadTranslations() (translations []*i18n.Translation) {
	for _, content := range backend.contents {
		var slice yaml.MapSlice
		if err := yaml.Unmarshal(content, &slice); err == nil {
			for _, item := range slice {
				translations = append(translations, loadTranslationsFromYaml(item.Key.(string) /* locale */, item.Value, []string{})...)
			}
		} else {
			panic(err)
		}
	}
	return translations
}

// SaveTranslation save translation into YAML backend, not implemented
func (backend *Backend) SaveTranslation(t *i18n.Translation) error {
	return errors.New("not implemented")
}

// DeleteTranslation delete translation into YAML backend, not implemented
func (backend *Backend) DeleteTranslation(t *i18n.Translation) error {
	return errors.New("not implemented")
}
<commit_msg>Load from YAML content<commit_after>package yaml

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strings"

	"github.com/qor/i18n"
	"gopkg.in/yaml.v2"
)

// New new YAML backend for I18n
func New(paths ...string) i18n.Backend {
	backend := &Backend{}

	var files []string
	for _, p := range paths {
		if file, err := os.Open(p); err == nil {
			defer file.Close()
			if fileInfo, err := file.Stat(); err == nil {
				if fileInfo.IsDir() {
					yamlFiles, _ := filepath.Glob(path.Join(p, "*.yaml"))
					files = append(files, yamlFiles...)

					ymlFiles, _ := filepath.Glob(path.Join(p, "*.yml"))
					files = append(files, ymlFiles...)
				} else if fileInfo.Mode().IsRegular() {
					files = append(files, p)
				}
			}
		}
	}
	for _, file := range files {
		if content, err := ioutil.ReadFile(file); err == nil {
			backend.contents = append(backend.contents, content)
		}
	}
	return backend
}

// NewWithWalk has the same functionality as New but uses filepath.Walk to find all the translation files recursively.
func NewWithWalk(paths ...string) i18n.Backend {
	backend := &Backend{}

	var files []string
	for _, p := range paths {
		filepath.Walk(p, func(path string, fileInfo os.FileInfo, err error) error {
			if isYamlFile(fileInfo) {
				files = append(files, path)
			}
			return nil
		})
	}
	for _, file := range files {
		if content, err := ioutil.ReadFile(file); err == nil {
			backend.contents = append(backend.contents, content)
		}
	}

	return backend
}

func isYamlFile(fileInfo os.FileInfo) bool {
	if fileInfo == nil {
		return false
	}
	return fileInfo.Mode().IsRegular() && (strings.HasSuffix(fileInfo.Name(), ".yml") || strings.HasSuffix(fileInfo.Name(), ".yaml"))
}

func walkFilesystem(fs http.FileSystem, entry http.File, prefix string) [][]byte {
	var (
		contents [][]byte
		err      error
		isRoot   bool
	)
	if entry == nil {
		if entry, err = fs.Open("/"); err != nil {
			return nil
		}
		isRoot = true
		defer entry.Close()
	}
	fileInfo, err := entry.Stat()
	if err != nil {
		return nil
	}
	if !isRoot {
		prefix = prefix + fileInfo.Name() + "/"
	}
	if fileInfo.IsDir() {
		if entries, err := entry.Readdir(-1); err == nil {
			for _, e := range entries {
				if file, err := fs.Open(prefix + e.Name()); err == nil {
					defer file.Close()
					contents = append(contents, walkFilesystem(fs, file, prefix)...)
				}
			}
		}
	} else if isYamlFile(fileInfo) {
		if content, err := ioutil.ReadAll(entry); err == nil {
			contents = append(contents, content)
		}
	}
	return contents
}

// NewWithFilesystem initializes a backend that reads translation files from an http.FileSystem.
func NewWithFilesystem(fss ...http.FileSystem) i18n.Backend {
	backend := &Backend{}

	for _, fs := range fss {
		backend.contents = append(backend.contents, walkFilesystem(fs, nil, "/")...)
	}
	return backend
}

// Backend YAML backend
type Backend struct {
	contents [][]byte
}

func loadTranslationsFromYaml(locale string, value interface{}, scopes []string) (translations []*i18n.Translation) {
	switch v := value.(type) {
	case yaml.MapSlice:
		for _, s := range v {
			results := loadTranslationsFromYaml(locale, s.Value, append(scopes, fmt.Sprint(s.Key)))
			translations = append(translations, results...)
		}
	default:
		var translation = &i18n.Translation{
			Locale: locale,
			Key:    strings.Join(scopes, "."),
			Value:  fmt.Sprint(v),
		}
		translations = append(translations, translation)
	}
	return
}

// LoadYAMLContent load YAML content
func (backend *Backend) LoadYAMLContent(content []byte) (translations []*i18n.Translation, err error) {
	var slice yaml.MapSlice

	if err = yaml.Unmarshal(content, &slice); err == nil {
		for _, item := range slice {
			translations = append(translations, loadTranslationsFromYaml(item.Key.(string) /* locale */, item.Value, []string{})...)
		}
	}

	return translations, err
}

// LoadTranslations load translations from YAML backend
func (backend *Backend) LoadTranslations() (translations []*i18n.Translation) {
	for _, content := range backend.contents {
		if results, err := backend.LoadYAMLContent(content); err == nil {
			translations = append(translations, results...)
		} else {
			panic(err)
		}
	}
	return translations
}

// SaveTranslation save translation into YAML backend, not implemented
func (backend *Backend) SaveTranslation(t *i18n.Translation) error {
	return errors.New("not implemented")
}

// DeleteTranslation delete translation into YAML backend, not implemented
func (backend *Backend) DeleteTranslation(t *i18n.Translation) error {
	return errors.New("not implemented")
}
<|endoftext|>


<commit_before>package commandclass

const (
	CommandVersionGet                byte = 0x11
	CommandVersionReport                  = 0x12
	CommandVersionCommandClassGet         = 0x13
	CommandVersionCommandClassReport      = 0x14
)

func NewVersionGet() []byte {
	return []byte{
		CommandClassVersion,
		CommandVersionGet,
	}
}
<commit_msg>Parser for VersionCommandClassReport commands<commit_after>package commandclass

const (
	CommandVersionGet                byte = 0x11
	CommandVersionReport                  = 0x12
	CommandVersionCommandClassGet         = 0x13
	CommandVersionCommandClassReport      = 0x14
)

type VersionCommandClassReport struct {
	CommandClass byte
	Version      byte
}

func NewVersionGet() []byte {
	return []byte{
		CommandClassVersion,
		CommandVersionGet,
	}
}

func ParseVersionCommandClassReport(payload []byte) VersionCommandClassReport {
	return VersionCommandClassReport{
		CommandClass: payload[2],
		Version:      payload[3],
	}
}
<|endoftext|>