<commit_before>package httpclientprovider

import (
	"net/http"

	sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
	"github.com/grafana/grafana/pkg/infra/httpclient"
	"github.com/grafana/grafana/pkg/infra/metrics/metricutil"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	datasourceRequestCounter = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: "grafana",
			Name:      "datasource_request_total",
			Help:      "A counter for outgoing requests for a data source",
		},
		[]string{"datasource", "code", "method"},
	)

	datasourceRequestHistogram = promauto.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: "grafana",
			Name:      "datasource_request_duration_seconds",
			Help:      "summary of outgoing data source requests sent from Grafana",
			Buckets:   []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 25, 50, 100},
		}, []string{"datasource", "code", "method"},
	)

	datasourceResponseHistogram = promauto.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: "grafana",
			Name:      "datasource_response_size_bytes",
			Help:      "summary of data source response sizes returned to Grafana",
			Buckets:   []float64{128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576},
		}, []string{"datasource"},
	)

	datasourceRequestsInFlight = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: "grafana",
			Name:      "datasource_request_in_flight",
			Help:      "A gauge of outgoing data source requests currently being sent by Grafana",
		},
		[]string{"datasource"},
	)
)

const DataSourceMetricsMiddlewareName = "metrics"

var executeMiddlewareFunc = executeMiddleware

func DataSourceMetricsMiddleware() sdkhttpclient.Middleware {
	return sdkhttpclient.NamedMiddlewareFunc(DataSourceMetricsMiddlewareName, func(opts sdkhttpclient.Options, next http.RoundTripper) http.RoundTripper {
		if opts.Labels == nil {
			return next
		}

		datasourceName, exists := opts.Labels["datasource_name"]
		if !exists {
			return next
		}

		datasourceLabelName, err := metricutil.SanitizeLabelName(datasourceName)
		// if the datasource named cannot be turned into a prometheus
		// label we will skip instrumenting these metrics.
		if err != nil {
			return next
		}

		datasourceLabel := prometheus.Labels{"datasource": datasourceLabelName}

		return executeMiddlewareFunc(next, datasourceLabel)
	})
}

func executeMiddleware(next http.RoundTripper, datasourceLabel prometheus.Labels) http.RoundTripper {
	return sdkhttpclient.RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
		requestCounter := datasourceRequestCounter.MustCurryWith(datasourceLabel)
		requestHistogram := datasourceRequestHistogram.MustCurryWith(datasourceLabel)
		requestInFlight := datasourceRequestsInFlight.With(datasourceLabel)
		responseSizeHistogram := datasourceResponseHistogram.With(datasourceLabel)

		res, err := promhttp.InstrumentRoundTripperDuration(requestHistogram,
			promhttp.InstrumentRoundTripperCounter(requestCounter,
				promhttp.InstrumentRoundTripperInFlight(requestInFlight, next))).
			RoundTrip(r)
		if err != nil {
			return nil, err
		}

		if res != nil && res.StatusCode != http.StatusSwitchingProtocols {
			res.Body = httpclient.CountBytesReader(res.Body, func(bytesRead int64) {
				responseSizeHistogram.Observe(float64(bytesRead))
			})
		}

		return res, nil
	})
}
<commit_msg>datasource metrics: Correct help text for histograms (#50942)<commit_after>package httpclientprovider

import (
	"net/http"

	sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
	"github.com/grafana/grafana/pkg/infra/httpclient"
	"github.com/grafana/grafana/pkg/infra/metrics/metricutil"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	datasourceRequestCounter = promauto.NewCounterVec(
		prometheus.CounterOpts{
			Namespace: "grafana",
			Name:      "datasource_request_total",
			Help:      "A counter for outgoing requests for a data source",
		},
		[]string{"datasource", "code", "method"},
	)

	datasourceRequestHistogram = promauto.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: "grafana",
			Name:      "datasource_request_duration_seconds",
			Help:      "histogram of durations of outgoing data source requests sent from Grafana",
			Buckets:   []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 25, 50, 100},
		}, []string{"datasource", "code", "method"},
	)

	datasourceResponseHistogram = promauto.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: "grafana",
			Name:      "datasource_response_size_bytes",
			Help:      "histogram of data source response sizes returned to Grafana",
			Buckets:   []float64{128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576},
		}, []string{"datasource"},
	)

	datasourceRequestsInFlight = promauto.NewGaugeVec(
		prometheus.GaugeOpts{
			Namespace: "grafana",
			Name:      "datasource_request_in_flight",
			Help:      "A gauge of outgoing data source requests currently being sent by Grafana",
		},
		[]string{"datasource"},
	)
)

const DataSourceMetricsMiddlewareName = "metrics"

var executeMiddlewareFunc = executeMiddleware

func DataSourceMetricsMiddleware() sdkhttpclient.Middleware {
	return sdkhttpclient.NamedMiddlewareFunc(DataSourceMetricsMiddlewareName, func(opts sdkhttpclient.Options, next http.RoundTripper) http.RoundTripper {
		if opts.Labels == nil {
			return next
		}

		datasourceName, exists := opts.Labels["datasource_name"]
		if !exists {
			return next
		}

		datasourceLabelName, err := metricutil.SanitizeLabelName(datasourceName)
		// if the datasource named cannot be turned into a prometheus
		// label we will skip instrumenting these metrics.
		if err != nil {
			return next
		}

		datasourceLabel := prometheus.Labels{"datasource": datasourceLabelName}

		return executeMiddlewareFunc(next, datasourceLabel)
	})
}

func executeMiddleware(next http.RoundTripper, datasourceLabel prometheus.Labels) http.RoundTripper {
	return sdkhttpclient.RoundTripperFunc(func(r *http.Request) (*http.Response, error) {
		requestCounter := datasourceRequestCounter.MustCurryWith(datasourceLabel)
		requestHistogram := datasourceRequestHistogram.MustCurryWith(datasourceLabel)
		requestInFlight := datasourceRequestsInFlight.With(datasourceLabel)
		responseSizeHistogram := datasourceResponseHistogram.With(datasourceLabel)

		res, err := promhttp.InstrumentRoundTripperDuration(requestHistogram,
			promhttp.InstrumentRoundTripperCounter(requestCounter,
				promhttp.InstrumentRoundTripperInFlight(requestInFlight, next))).
			RoundTrip(r)
		if err != nil {
			return nil, err
		}

		if res != nil && res.StatusCode != http.StatusSwitchingProtocols {
			res.Body = httpclient.CountBytesReader(res.Body, func(bytesRead int64) {
				responseSizeHistogram.Observe(float64(bytesRead))
			})
		}

		return res, nil
	})
}
<|endoftext|>


<commit_before>package sqlpaxos

import "testing"
import "runtime"
import "strconv"
import "os"
import "time"
import "fmt"
import "math/rand"

func check(t *testing.T, ck *Clerk, key string, value string) {
  v := ck.Get(key)
  if v != value {
    t.Fatalf("Get(%v) -> %v, expected %v", key, v, value)
  }
}

func cleanup(kva []*TSimpleServer) {
  for i := 0; i < len(kva); i++ {
    if kva[i] != nil {
      //kva[i].kill()
      // kill the SQLPaxos server
    }
  }
}

func StartServer(servers []string, me int) {
  protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
  transportFactory := thrift.NewTTransportFactory()
  transport, err := thrift.NewTServerSocket(servers[me])

  if err != nil {
    fmt.Println("Error: ", err)
    return
  }

  handler := NewBaristaHandler()
  processor := barista.NewBaristaProcessor(handler)
  server := thrift.NewTSimpleServer4(processor, transport, transportFactory, protocolFactory)

  fmt.Println("Starting the Barista server on ", servers[me])
  server.Serve()
}

func TestBasic(t *testing.T) {
  const nservers = 5

  // store the addresses of the servers
  var kvh []string = make([]string, nservers)
  // initialize the addresses

  var kva []*TSimpleServer = make([]*TSimpleServer, nservers)

  defer cleanup(kva)

  for i := 0; i < nservers; i++ {
  	// start servers on the various machines
    kva[i] = StartServer(kvh, i)
  }

  ck := MakeClerk(kvh)
  var cka [nservers]*Clerk
  for i := 0; i < nservers; i++ {
    cka[i] = MakeClerk([]string{kvh[i]})
  }

  fmt.Printf("Test: Basic open/execute/close ...\n")

  con, err := ck.OpenConnection()
  if err != nil {
  	t.Fatalf("Error opening connection:", err)
  } else if con == nil {
  	t.Fatalf("Error nil connection returned by open:", err)
  }

  // create a table
  rs, err := ck.ExecuteSQL(con,
  	"create table sqlpaxos_test (key varchar(40), value varchar(40))", nil)
  if err != nil {
  	t.Fatalf("Error creatint table:", err)
  }

  // count number of rows in the table
  res, err := ck.ExecuteSQL(con,
  	"select count(*) from sqlpaxos_test", nil)
  if err != nil || res == nil {
  	t.Fatalf("Error querying table:", err)
  }

  for _, tuple := range *(res.Tuples) {
    for _, cell := range *(tuple.Cells) {
      if "0" != cell {
      	t.Fatalf("Table should be empty: %s", cell)
      }
    }
  }

  // insert item into table
  key := "a"
  val := "100"
  res, err := ck.ExecuteSQL(con,
  	"insert into sqlpaxos_test values (\'"+ key +"\', \'" +
  		value +"\')", nil)
  if err != nil || res == nil {
  	t.Fatalf("Error querying table:", err)
  }

  // retrieve old item from table
  res, err := ck.ExecuteSQL(con,
  	"select value from sqlpaxos_test where key=\'" + key
  	  + "\'", nil)
  if err != nil || res == nil {
  	t.Fatalf("Error querying table:", err)
  }

  for _, tuple := range *(res.Tuples) {
    for _, cell := range *(tuple.Cells) {
      if val != cell {
      	t.Fatalf("Table should be empty: %s", cell)
      }
    }
  }

  err := ck.CloseConnection()
	if err != nil {
  	t.Fatalf("Error closing connection:", err)
  }

  fmt.Printf("  ... Passed\n")
  return

  fmt.Printf("Test: Concurrent clients ...\n")

  for iters := 0; iters < 20; iters++ {
    const npara = 15
    var ca [npara]chan bool
    for nth := 0; nth < npara; nth++ {
      ca[nth] = make(chan bool)
      go func(me int) {
        defer func() { ca[me] <- true }()
        ci := (rand.Int() % nservers)
        myck := MakeClerk([]string{kvh[ci]})
        con, err := ck.OpenConnection()
		if err != nil {
		  t.Fatalf("Error opening connection:", err)
		} else if con == nil {
		  t.Fatalf("Error nil connection returned by open:", err)
		}
        if (rand.Int() % 1000) < 500 {
          // insert
          res, err := ck.ExecuteSQL(con,
  			"insert into sqlpaxos_test values (\'"+ key +"\', \'" +
  		    strconv.Itoa(rand.Int())) +"\')", nil)
		  if err != nil || res == nil {
		  	t.Fatalf("Error querying table:", err)
		  }
  		} else {
          // retrieve old item from table
		  res, err := ck.ExecuteSQL(con,
		  	"select value from sqlpaxos_test where key=\'" + key
		  	  + "\'", nil)
		  if err != nil || res == nil {
		  	t.Fatalf("Error querying table:", err)
		  }
        }
        err := ck.CloseConnection()
		if err != nil {
  		  t.Fatalf("Error closing connection:", err)
  		}
      }(nth)
    }

    for nth := 0; nth < npara; nth++ {
      <- ca[nth]
    }

    var va [nservers]string
    for i := 0; i < nservers; i++ {
	  res, err := ck.ExecuteSQL(con,
	  	"select value from sqlpaxos_test where key=\'" + key
	  	  + "\'", nil)
	  if err != nil || res == nil {
	  	t.Fatalf("Error querying table:", err)
	  }
	  for _, tuple := range *(res.Tuples) {
        for _, cell := range *(tuple.Cells) {
          va[i] = cell
    	}
      }

      if va[i] != va[0] {
        t.Fatalf("mismatch")
      }
    }
  }

  fmt.Printf("  ... Passed\n")

  time.Sleep(1 * time.Second)
}

<commit_msg>package change<commit_after>package main

import "testing"
import "runtime"
import "strconv"
import "os"
import "time"
import "fmt"
import "math/rand"

func check(t *testing.T, ck *Clerk, key string, value string) {
  v := ck.Get(key)
  if v != value {
    t.Fatalf("Get(%v) -> %v, expected %v", key, v, value)
  }
}

func cleanup(kva []*TSimpleServer) {
  for i := 0; i < len(kva); i++ {
    if kva[i] != nil {
      //kva[i].kill()
      // kill the SQLPaxos server
    }
  }
}

func StartServer(servers []string, me int) {
  protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
  transportFactory := thrift.NewTTransportFactory()
  transport, err := thrift.NewTServerSocket(servers[me])

  if err != nil {
    fmt.Println("Error: ", err)
    return
  }

  handler := NewBaristaHandler()
  processor := barista.NewBaristaProcessor(handler)
  server := thrift.NewTSimpleServer4(processor, transport, transportFactory, protocolFactory)

  fmt.Println("Starting the Barista server on ", servers[me])
  server.Serve()
}

func TestBasic(t *testing.T) {
  const nservers = 5

  // store the addresses of the servers
  var kvh []string = make([]string, nservers)
  // initialize the addresses

  var kva []*TSimpleServer = make([]*TSimpleServer, nservers)

  defer cleanup(kva)

  for i := 0; i < nservers; i++ {
  	// start servers on the various machines
    kva[i] = StartServer(kvh, i)
  }

  ck := MakeClerk(kvh)
  var cka [nservers]*Clerk
  for i := 0; i < nservers; i++ {
    cka[i] = MakeClerk([]string{kvh[i]})
  }

  fmt.Printf("Test: Basic open/execute/close ...\n")

  con, err := ck.OpenConnection()
  if err != nil {
  	t.Fatalf("Error opening connection:", err)
  } else if con == nil {
  	t.Fatalf("Error nil connection returned by open:", err)
  }

  // create a table
  rs, err := ck.ExecuteSQL(con,
  	"create table sqlpaxos_test (key varchar(40), value varchar(40))", nil)
  if err != nil {
  	t.Fatalf("Error creatint table:", err)
  }

  // count number of rows in the table
  res, err := ck.ExecuteSQL(con,
  	"select count(*) from sqlpaxos_test", nil)
  if err != nil || res == nil {
  	t.Fatalf("Error querying table:", err)
  }

  for _, tuple := range *(res.Tuples) {
    for _, cell := range *(tuple.Cells) {
      if "0" != cell {
      	t.Fatalf("Table should be empty: %s", cell)
      }
    }
  }

  // insert item into table
  key := "a"
  val := "100"
  res, err := ck.ExecuteSQL(con,
  	"insert into sqlpaxos_test values (\'"+ key +"\', \'" +
  		value +"\')", nil)
  if err != nil || res == nil {
  	t.Fatalf("Error querying table:", err)
  }

  // retrieve old item from table
  res, err := ck.ExecuteSQL(con,
  	"select value from sqlpaxos_test where key=\'" + key
  	  + "\'", nil)
  if err != nil || res == nil {
  	t.Fatalf("Error querying table:", err)
  }

  for _, tuple := range *(res.Tuples) {
    for _, cell := range *(tuple.Cells) {
      if val != cell {
      	t.Fatalf("Table should be empty: %s", cell)
      }
    }
  }

  err := ck.CloseConnection()
	if err != nil {
  	t.Fatalf("Error closing connection:", err)
  }

  fmt.Printf("  ... Passed\n")
  return

  fmt.Printf("Test: Concurrent clients ...\n")

  for iters := 0; iters < 20; iters++ {
    const npara = 15
    var ca [npara]chan bool
    for nth := 0; nth < npara; nth++ {
      ca[nth] = make(chan bool)
      go func(me int) {
        defer func() { ca[me] <- true }()
        ci := (rand.Int() % nservers)
        myck := MakeClerk([]string{kvh[ci]})
        con, err := ck.OpenConnection()
		if err != nil {
		  t.Fatalf("Error opening connection:", err)
		} else if con == nil {
		  t.Fatalf("Error nil connection returned by open:", err)
		}
        if (rand.Int() % 1000) < 500 {
          // insert
          res, err := ck.ExecuteSQL(con,
  			"insert into sqlpaxos_test values (\'"+ key +"\', \'" +
  		    strconv.Itoa(rand.Int())) +"\')", nil)
		  if err != nil || res == nil {
		  	t.Fatalf("Error querying table:", err)
		  }
  		} else {
          // retrieve old item from table
		  res, err := ck.ExecuteSQL(con,
		  	"select value from sqlpaxos_test where key=\'" + key
		  	  + "\'", nil)
		  if err != nil || res == nil {
		  	t.Fatalf("Error querying table:", err)
		  }
        }
        err := ck.CloseConnection()
		if err != nil {
  		  t.Fatalf("Error closing connection:", err)
  		}
      }(nth)
    }

    for nth := 0; nth < npara; nth++ {
      <- ca[nth]
    }

    var va [nservers]string
    for i := 0; i < nservers; i++ {
	  res, err := ck.ExecuteSQL(con,
	  	"select value from sqlpaxos_test where key=\'" + key
	  	  + "\'", nil)
	  if err != nil || res == nil {
	  	t.Fatalf("Error querying table:", err)
	  }
	  for _, tuple := range *(res.Tuples) {
        for _, cell := range *(tuple.Cells) {
          va[i] = cell
    	}
      }

      if va[i] != va[0] {
        t.Fatalf("mismatch")
      }
    }
  }

  fmt.Printf("  ... Passed\n")

  time.Sleep(1 * time.Second)
}

<|endoftext|>


<commit_before>package sentrylib

import (
	"errors"
	"io"
	"log"
	"time"
)

type Sentry interface {
	Serve() error
}

type sentry struct {
	config Config
}

func NewSentry(config Config) Sentry {
	return &sentry{
		config: config,
	}
}

func (server *sentry) Serve() error {
	log.SetFlags(log.Flags() | log.Llongfile)
	client := NewAprsClient(server.config.AprsServer, server.config.AprsUser, server.config.AprsPasscode, server.config.AprsFilter)

	store, err := NewBoltStore("sentry.db")
	if err != nil {
		return err
	}

	mail := NewMailgunServer(server.config)

	// runs in background
	NewWebServer(store)

	duration := 25 * time.Hour
	if server.config.Cutoff != "" {
		duration, err = time.ParseDuration(server.config.Cutoff)
		if err != nil {
			return errors.New("Unable to parse Cutoff in config")
		}
	}

	worker := NewSentryWorker(store, duration, mail)

	go RunReaper(worker, duration)

	for {
		err = client.Dial()
		if err != nil {
			return err
		}
		for client.Next() {
			frame, err := client.Frame()
			if err != nil {
				log.Println(err)
			}
			err = worker.HandleMessage(frame)
			if err != nil {
				if !(err == FrameNotValidError || err.Error() == "no positions found") {
					log.Println(err)
				}
			}
		}
		err = client.Error()
		if err != io.EOF {
			log.Fatalln(err)
			return err
		} else {
			client.Dial()
		}
	}
}

func RunReaper(sentryWorker SentryWorker, duration time.Duration) {
	for {
		nodes, err := sentryWorker.ReapLiveNodes()
		if err != nil {
			log.Println(err)
			continue
		}
		for _, v := range nodes {
			go sentryWorker.Email(v.Callsign, v.LastSeen)
		}
		time.Sleep(1 * time.Second)
	}
}
<commit_msg>Readding starting pause<commit_after>package sentrylib

import (
	"errors"
	"io"
	"log"
	"time"
)

type Sentry interface {
	Serve() error
}

type sentry struct {
	config Config
}

func NewSentry(config Config) Sentry {
	return &sentry{
		config: config,
	}
}

func (server *sentry) Serve() error {
	log.SetFlags(log.Flags() | log.Llongfile)
	client := NewAprsClient(server.config.AprsServer, server.config.AprsUser, server.config.AprsPasscode, server.config.AprsFilter)

	store, err := NewBoltStore("sentry.db")
	if err != nil {
		return err
	}

	mail := NewMailgunServer(server.config)

	// runs in background
	NewWebServer(store)

	duration := 25 * time.Hour
	if server.config.Cutoff != "" {
		duration, err = time.ParseDuration(server.config.Cutoff)
		if err != nil {
			return errors.New("Unable to parse Cutoff in config")
		}
	}

	worker := NewSentryWorker(store, duration, mail)

	go RunReaper(worker, duration)

	for {
		err = client.Dial()
		if err != nil {
			return err
		}
		for client.Next() {
			frame, err := client.Frame()
			if err != nil {
				log.Println(err)
			}
			err = worker.HandleMessage(frame)
			if err != nil {
				if !(err == FrameNotValidError || err.Error() == "no positions found") {
					log.Println(err)
				}
			}
		}
		err = client.Error()
		if err != io.EOF {
			log.Fatalln(err)
			return err
		} else {
			client.Dial()
		}
	}
}

func RunReaper(sentryWorker SentryWorker, duration time.Duration) {
	time.Sleep(duration)
	for {
		nodes, err := sentryWorker.ReapLiveNodes()
		if err != nil {
			log.Println(err)
			continue
		}
		for _, v := range nodes {
			go sentryWorker.Email(v.Callsign, v.LastSeen)
		}
		time.Sleep(1 * time.Second)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Timo Savola. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package runtime

import (
	"context"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"syscall"

	"github.com/tsavola/gate/internal/error/badprogram"
	"github.com/tsavola/gate/internal/file"
	"github.com/tsavola/gate/packet"
	"github.com/tsavola/gate/snapshot"
)

const (
	packetReservedOffset = 7
)

func popServiceBuffers(frozen *snapshot.Buffers) (services []snapshot.Service) {
	if frozen == nil {
		return
	}

	services = frozen.Services
	frozen.Services = nil
	return
}

func popInputBuffer(frozen *snapshot.Buffers) (input []byte) {
	if frozen == nil {
		return
	}

	input = frozen.Input
	frozen.Input = nil
	return
}

func popOutputBuffer(frozen *snapshot.Buffers) (output []byte) {
	if frozen == nil {
		return
	}

	output = frozen.Output
	frozen.Output = nil
	return
}

type read struct {
	buf packet.Buf
	err error
}

// ioLoop mutates Process and IOState (if any).
func ioLoop(ctx context.Context, services ServiceRegistry, subject *Process, frozen *snapshot.Buffers,
) (err error) {
	if frozen == nil {
		subject.writerOut.Close()
		subject.writerOut = nil
	}

	var (
		suspended = subject.suspended
		done      = ctx.Done()
	)

	var (
		messageInput  = make(chan packet.Buf)
		messageOutput = make(chan packet.Buf)
	)
	discoverer, initialServiceState, err := services.StartServing(ctx, ServiceConfig{maxPacketSize}, popServiceBuffers(frozen), messageInput, messageOutput)
	if err != nil {
		return
	}
	defer func() {
		close(messageOutput)
		if frozen != nil {
			frozen.Services = discoverer.Suspend()
		} else {
			discoverer.Shutdown()
		}
	}()

	pendingMsg, initialRead, err := splitBufferedPackets(popOutputBuffer(frozen), discoverer)
	if err != nil {
		return
	}

	var pendingEvs []packet.Buf
	if ev := popInputBuffer(frozen); len(ev) > 0 {
		pendingEvs = []packet.Buf{ev} // No need to split packets.
	}

	if len(initialServiceState) > 0 {
		pendingEvs = append(pendingEvs, makeServicesPacket(packet.DomainInfo, initialServiceState))
	}
	initialServiceState = nil

	subjectInput := subjectReadLoop(subject.reader, initialRead)
	defer func() {
		if subjectInput != nil {
			for range subjectInput {
			}
		}
	}()

	subjectOutput := subjectWriteLoop(subject.writer)
	subject.writer = nil
	defer func() {
		if subjectOutput != nil {
			close(subjectOutput)
		}
	}()

	doSuspend := func() {
		suspended = nil
		done = nil

		subject.killSuspend()

		close(subjectOutput)
		subjectOutput = nil
	}

	for subjectInput != nil || pendingMsg != nil {
		var (
			doEv            packet.Buf
			doMessageInput  <-chan packet.Buf
			doMessageOutput chan<- packet.Buf
			doSubjectInput  <-chan read
			doSubjectOutput chan<- packet.Buf
		)

		if len(pendingEvs) > 0 {
			doEv = pendingEvs[0]
		}

		if pendingMsg != nil {
			doMessageOutput = messageOutput
		}

		if doEv == nil {
			doMessageInput = messageInput
			if pendingMsg == nil {
				doSubjectInput = subjectInput
			}
		} else {
			doSubjectOutput = subjectOutput
		}

		select {
		case p := <-doMessageInput:
			pendingEvs = append(pendingEvs, initMessagePacket(p))

		case read, ok := <-doSubjectInput:
			if !ok {
				err = errors.New("read loop terminated unexpectedly")
				return
			}

			switch {
			case read.err == nil:
				msg, ev, opErr := handlePacket(ctx, read.buf, discoverer)
				if opErr != nil {
					err = opErr
					return
				}

				if msg != nil {
					pendingMsg = msg
				}
				if ev != nil {
					pendingEvs = append(pendingEvs, ev)
				}

			case read.err == io.EOF:
				subjectInput = nil

				if subjectOutput != nil {
					close(subjectOutput)
					subjectOutput = nil
				}

				if frozen != nil {
					if len(read.buf) == 0 {
						frozen.Output = pendingMsg
					} else {
						// pendingMsg might be part of the original
						// Buffers.Output, so don't mutate it.
						frozen.Output = append(append([]byte{}, pendingMsg...), read.buf...)
					}
					pendingMsg = nil

					frozen.Input, err = ioutil.ReadAll(subject.writerOut)
					if err != nil {
						return
					}

					var pendingLen int
					for _, ev := range pendingEvs {
						pendingLen += len(ev)
					}

					if n := len(frozen.Input) + pendingLen; cap(frozen.Input) < n {
						frozen.Input = append(make([]byte, 0, n), frozen.Input...)
					}

					for _, ev := range pendingEvs {
						frozen.Input = append(frozen.Input, ev...)
					}

					subject.writerOut.Close()
					subject.writerOut = nil
				}

			case read.err != nil:
				err = read.err
				return
			}

		case doMessageOutput <- pendingMsg:
			pendingMsg = nil

		case doSubjectOutput <- doEv:
			if len(pendingEvs) > 0 {
				pendingEvs = pendingEvs[1:]
			}

		case <-suspended:
			doSuspend()

		case <-done:
			doSuspend()
		}
	}

	return
}

func subjectReadLoop(r *os.File, partial []byte) <-chan read {
	reads := make(chan read)

	go func() {
		defer close(reads)

		header := make([]byte, packet.HeaderSize)

		for {
			offset := copy(header, partial)
			partial = partial[offset:]

			if n, err := io.ReadFull(r, header[offset:]); err != nil {
				if err != io.EOF {
					err = fmt.Errorf("subject read: %v", err)
				}
				reads <- read{buf: header[:offset+n], err: err}
				return
			}

			size := binary.LittleEndian.Uint32(header)
			if size < packet.HeaderSize || size > maxPacketSize {
				reads <- read{err: badprogram.Errorf("runtime: invalid op packet size: %d", size)}
				return
			}

			buf := make([]byte, packet.Align(int(size)))
			offset = copy(buf, header)
			offset += copy(buf[offset:], partial)
			partial = nil

			if n, err := io.ReadFull(r, buf[offset:]); err != nil {
				if err != io.EOF {
					err = fmt.Errorf("subject read: %v", err)
				}
				reads <- read{buf: buf[:offset+n], err: err}
				return
			}

			reads <- read{buf: buf[:size]}
		}
	}()

	return reads
}

func subjectWriteLoop(w *file.File) chan<- packet.Buf {
	writes := make(chan packet.Buf)

	go func() {
		defer w.Close()

		iov := make([]syscall.Iovec, 2)
		pad := make([]byte, packet.Alignment-1)

		for buf := range writes {
			iov[0].Base = &buf[0]
			iov[0].Len = uint64(len(buf))

			iov[1].Base = &pad[0]
			iov[1].Len = (packet.Alignment - (uint64(len(buf)) & (packet.Alignment - 1))) &^ packet.Alignment

			if err := w.WriteVec(iov); err != nil {
				return
			}
		}
	}()

	return writes
}

func initMessagePacket(p packet.Buf) packet.Buf {
	if len(p) < packet.HeaderSize || len(p) > maxPacketSize {
		panic(errors.New("invalid outgoing message packet buffer length"))
	}

	if p[packetReservedOffset] != 0 {
		panic(errors.New("reserved byte is nonzero in outgoing message packet header"))
	}

	if p.Code() < 0 {
		panic(errors.New("negative service code in outgoing message packet header"))
	}

	if p.Domain() > packet.DomainData {
		panic(errors.New("invalid domain in outgoing message packet header"))
	}

	// Service implementations only need to initialize code and domain fields.
	// But if the size field has been initialized correctly, treat the buffer
	// as read-only.
	if binary.LittleEndian.Uint32(p[packet.OffsetSize:]) != uint32(len(p)) {
		binary.LittleEndian.PutUint32(p[packet.OffsetSize:], uint32(len(p)))
	}

	return p
}

func handlePacket(ctx context.Context, p packet.Buf, discoverer ServiceDiscoverer) (msg, reply packet.Buf, err error) {
	switch code := p.Code(); {
	case code >= 0:
		msg, err = checkServicePacket(p, discoverer)
		if err != nil {
			return
		}

	case code == packet.CodeServices:
		reply, err = handleServicesPacket(ctx, p, discoverer)
		if err != nil {
			return
		}

	default:
		err = badprogram.Errorf("invalid code in incoming packet: %d", code)
		return
	}

	return
}

func splitBufferedPackets(buf []byte, discoverer ServiceDiscoverer,
) (msg packet.Buf, tail []byte, err error) {
	if len(buf) < packet.HeaderSize {
		tail = buf
		return
	}

	size := binary.LittleEndian.Uint32(buf[packet.OffsetSize:])
	if size < packet.HeaderSize || size > maxPacketSize {
		err = badprogram.Errorf("buffered packet has invalid size: %d", size)
		return
	}

	if uint32(len(buf)) < size {
		tail = buf
		return
	}

	p := packet.Buf(buf[:size])

	switch code := p.Code(); {
	case code >= 0:
		msg, err = checkServicePacket(p, discoverer)
		if err != nil {
			return
		}

	default:
		err = badprogram.Errorf("invalid code in buffered packet: %d", code)
		return
	}

	tail = buf[size:]
	return
}

func checkServicePacket(p packet.Buf, discoverer ServiceDiscoverer) (msg packet.Buf, err error) {
	if x := p[packetReservedOffset]; x != 0 {
		err = badprogram.Errorf("reserved byte has value 0x%02x in buffered packet header", x)
		return
	}

	if int(p.Code()) >= discoverer.NumServices() {
		err = badprogram.Errorf("invalid service code in packet: %d", p.Code())
		return
	}

	switch p.Domain() {
	case packet.DomainCall, packet.DomainFlow:

	case packet.DomainData:
		if n := len(p); n < packet.DataHeaderSize {
			err = badprogram.Errorf("data packet is too short: %d bytes", n)
			return
		}

	default:
		err = badprogram.Errorf("invalid domain in packet: %d", p.Domain())
		return
	}

	msg = p
	return
}
<commit_msg>runtime: fix service shutdown on interactive suspend<commit_after>// Copyright (c) 2016 Timo Savola. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package runtime

import (
	"context"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"syscall"

	"github.com/tsavola/gate/internal/error/badprogram"
	"github.com/tsavola/gate/internal/file"
	"github.com/tsavola/gate/packet"
	"github.com/tsavola/gate/snapshot"
)

const (
	packetReservedOffset = 7
)

func popServiceBuffers(frozen *snapshot.Buffers) (services []snapshot.Service) {
	if frozen == nil {
		return
	}

	services = frozen.Services
	frozen.Services = nil
	return
}

func popInputBuffer(frozen *snapshot.Buffers) (input []byte) {
	if frozen == nil {
		return
	}

	input = frozen.Input
	frozen.Input = nil
	return
}

func popOutputBuffer(frozen *snapshot.Buffers) (output []byte) {
	if frozen == nil {
		return
	}

	output = frozen.Output
	frozen.Output = nil
	return
}

type read struct {
	buf packet.Buf
	err error
}

// ioLoop mutates Process and IOState (if any).
func ioLoop(ctx context.Context, services ServiceRegistry, subject *Process, frozen *snapshot.Buffers,
) (err error) {
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()

	if frozen == nil {
		subject.writerOut.Close()
		subject.writerOut = nil
	}

	var (
		suspended = subject.suspended
		done      = ctx.Done()
	)

	var (
		messageInput  = make(chan packet.Buf)
		messageOutput = make(chan packet.Buf)
	)
	discoverer, initialServiceState, err := services.StartServing(ctx, ServiceConfig{maxPacketSize}, popServiceBuffers(frozen), messageInput, messageOutput)
	if err != nil {
		return
	}
	defer func() {
		cancel()
		close(messageOutput)
		if frozen != nil {
			frozen.Services = discoverer.Suspend()
		} else {
			discoverer.Shutdown()
		}
	}()

	pendingMsg, initialRead, err := splitBufferedPackets(popOutputBuffer(frozen), discoverer)
	if err != nil {
		return
	}

	var pendingEvs []packet.Buf
	if ev := popInputBuffer(frozen); len(ev) > 0 {
		pendingEvs = []packet.Buf{ev} // No need to split packets.
	}

	if len(initialServiceState) > 0 {
		pendingEvs = append(pendingEvs, makeServicesPacket(packet.DomainInfo, initialServiceState))
	}
	initialServiceState = nil

	subjectInput := subjectReadLoop(subject.reader, initialRead)
	defer func() {
		if subjectInput != nil {
			for range subjectInput {
			}
		}
	}()

	subjectOutput := subjectWriteLoop(subject.writer)
	subject.writer = nil
	defer func() {
		if subjectOutput != nil {
			close(subjectOutput)
		}
	}()

	doSuspend := func() {
		suspended = nil
		done = nil

		subject.killSuspend()

		close(subjectOutput)
		subjectOutput = nil
	}

	for (subjectInput != nil || pendingMsg != nil) && subjectOutput != nil {
		var (
			doEv            packet.Buf
			doMessageInput  <-chan packet.Buf
			doMessageOutput chan<- packet.Buf
			doSubjectInput  <-chan read
			doSubjectOutput chan<- packet.Buf
		)

		if len(pendingEvs) > 0 {
			doEv = pendingEvs[0]
		}

		if pendingMsg != nil {
			doMessageOutput = messageOutput
		}

		if doEv == nil {
			doMessageInput = messageInput
			if pendingMsg == nil {
				doSubjectInput = subjectInput
			}
		} else {
			doSubjectOutput = subjectOutput
		}

		select {
		case p := <-doMessageInput:
			pendingEvs = append(pendingEvs, initMessagePacket(p))

		case read, ok := <-doSubjectInput:
			if !ok {
				err = errors.New("read loop terminated unexpectedly")
				return
			}

			switch {
			case read.err == nil:
				msg, ev, opErr := handlePacket(ctx, read.buf, discoverer)
				if opErr != nil {
					err = opErr
					return
				}

				if msg != nil {
					pendingMsg = msg
				}
				if ev != nil {
					pendingEvs = append(pendingEvs, ev)
				}

			case read.err == io.EOF:
				subjectInput = nil

				if subjectOutput != nil {
					close(subjectOutput)
					subjectOutput = nil
				}

				if frozen != nil {
					if len(read.buf) == 0 {
						frozen.Output = pendingMsg
					} else {
						// pendingMsg might be part of the original
						// Buffers.Output, so don't mutate it.
						frozen.Output = append(append([]byte{}, pendingMsg...), read.buf...)
					}
					pendingMsg = nil

					frozen.Input, err = ioutil.ReadAll(subject.writerOut)
					if err != nil {
						return
					}

					var pendingLen int
					for _, ev := range pendingEvs {
						pendingLen += len(ev)
					}

					if n := len(frozen.Input) + pendingLen; cap(frozen.Input) < n {
						frozen.Input = append(make([]byte, 0, n), frozen.Input...)
					}

					for _, ev := range pendingEvs {
						frozen.Input = append(frozen.Input, ev...)
					}

					subject.writerOut.Close()
					subject.writerOut = nil
				}

			case read.err != nil:
				err = read.err
				return
			}

		case doMessageOutput <- pendingMsg:
			pendingMsg = nil

		case doSubjectOutput <- doEv:
			if len(pendingEvs) > 0 {
				pendingEvs = pendingEvs[1:]
			}

		case <-suspended:
			doSuspend()

		case <-done:
			doSuspend()
		}
	}

	return
}

func subjectReadLoop(r *os.File, partial []byte) <-chan read {
	reads := make(chan read)

	go func() {
		defer close(reads)

		header := make([]byte, packet.HeaderSize)

		for {
			offset := copy(header, partial)
			partial = partial[offset:]

			if n, err := io.ReadFull(r, header[offset:]); err != nil {
				if err != io.EOF {
					err = fmt.Errorf("subject read: %v", err)
				}
				reads <- read{buf: header[:offset+n], err: err}
				return
			}

			size := binary.LittleEndian.Uint32(header)
			if size < packet.HeaderSize || size > maxPacketSize {
				reads <- read{err: badprogram.Errorf("runtime: invalid op packet size: %d", size)}
				return
			}

			buf := make([]byte, packet.Align(int(size)))
			offset = copy(buf, header)
			offset += copy(buf[offset:], partial)
			partial = nil

			if n, err := io.ReadFull(r, buf[offset:]); err != nil {
				if err != io.EOF {
					err = fmt.Errorf("subject read: %v", err)
				}
				reads <- read{buf: buf[:offset+n], err: err}
				return
			}

			reads <- read{buf: buf[:size]}
		}
	}()

	return reads
}

func subjectWriteLoop(w *file.File) chan<- packet.Buf {
	writes := make(chan packet.Buf)

	go func() {
		defer w.Close()

		iov := make([]syscall.Iovec, 2)
		pad := make([]byte, packet.Alignment-1)

		for buf := range writes {
			iov[0].Base = &buf[0]
			iov[0].Len = uint64(len(buf))

			iov[1].Base = &pad[0]
			iov[1].Len = (packet.Alignment - (uint64(len(buf)) & (packet.Alignment - 1))) &^ packet.Alignment

			if err := w.WriteVec(iov); err != nil {
				return
			}
		}
	}()

	return writes
}

func initMessagePacket(p packet.Buf) packet.Buf {
	if len(p) < packet.HeaderSize || len(p) > maxPacketSize {
		panic(errors.New("invalid outgoing message packet buffer length"))
	}

	if p[packetReservedOffset] != 0 {
		panic(errors.New("reserved byte is nonzero in outgoing message packet header"))
	}

	if p.Code() < 0 {
		panic(errors.New("negative service code in outgoing message packet header"))
	}

	if p.Domain() > packet.DomainData {
		panic(errors.New("invalid domain in outgoing message packet header"))
	}

	// Service implementations only need to initialize code and domain fields.
	// But if the size field has been initialized correctly, treat the buffer
	// as read-only.
	if binary.LittleEndian.Uint32(p[packet.OffsetSize:]) != uint32(len(p)) {
		binary.LittleEndian.PutUint32(p[packet.OffsetSize:], uint32(len(p)))
	}

	return p
}

func handlePacket(ctx context.Context, p packet.Buf, discoverer ServiceDiscoverer) (msg, reply packet.Buf, err error) {
	switch code := p.Code(); {
	case code >= 0:
		msg, err = checkServicePacket(p, discoverer)
		if err != nil {
			return
		}

	case code == packet.CodeServices:
		reply, err = handleServicesPacket(ctx, p, discoverer)
		if err != nil {
			return
		}

	default:
		err = badprogram.Errorf("invalid code in incoming packet: %d", code)
		return
	}

	return
}

func splitBufferedPackets(buf []byte, discoverer ServiceDiscoverer,
) (msg packet.Buf, tail []byte, err error) {
	if len(buf) < packet.HeaderSize {
		tail = buf
		return
	}

	size := binary.LittleEndian.Uint32(buf[packet.OffsetSize:])
	if size < packet.HeaderSize || size > maxPacketSize {
		err = badprogram.Errorf("buffered packet has invalid size: %d", size)
		return
	}

	if uint32(len(buf)) < size {
		tail = buf
		return
	}

	p := packet.Buf(buf[:size])

	switch code := p.Code(); {
	case code >= 0:
		msg, err = checkServicePacket(p, discoverer)
		if err != nil {
			return
		}

	default:
		err = badprogram.Errorf("invalid code in buffered packet: %d", code)
		return
	}

	tail = buf[size:]
	return
}

func checkServicePacket(p packet.Buf, discoverer ServiceDiscoverer) (msg packet.Buf, err error) {
	if x := p[packetReservedOffset]; x != 0 {
		err = badprogram.Errorf("reserved byte has value 0x%02x in buffered packet header", x)
		return
	}

	if int(p.Code()) >= discoverer.NumServices() {
		err = badprogram.Errorf("invalid service code in packet: %d", p.Code())
		return
	}

	switch p.Domain() {
	case packet.DomainCall, packet.DomainFlow:

	case packet.DomainData:
		if n := len(p); n < packet.DataHeaderSize {
			err = badprogram.Errorf("data packet is too short: %d bytes", n)
			return
		}

	default:
		err = badprogram.Errorf("invalid domain in packet: %d", p.Domain())
		return
	}

	msg = p
	return
}
<|endoftext|>


<commit_before>package controller

import (
	"bytes"
	"errors"
	"fmt"
	"time"

	"github.com/appscode/log"
	"github.com/ghodss/yaml"
	"github.com/graymeta/stow"
	_ "github.com/graymeta/stow/google"
	_ "github.com/graymeta/stow/s3"
	tapi "github.com/k8sdb/apimachinery/api"
	kapi "k8s.io/kubernetes/pkg/api"
	k8serr "k8s.io/kubernetes/pkg/api/errors"
	kapps "k8s.io/kubernetes/pkg/apis/apps"
	"k8s.io/kubernetes/pkg/labels"
)

func (c *Controller) ValidateStorageSpec(spec *tapi.StorageSpec) (*tapi.StorageSpec, error) {
	if spec == nil {
		return nil, nil
	}

	if spec.Class == "" {
		return nil, fmt.Errorf(`Object 'Class' is missing in '%v'`, *spec)
	}

	if _, err := c.Client.Storage().StorageClasses().Get(spec.Class); err != nil {
		if k8serr.IsNotFound(err) {
			return nil, fmt.Errorf(`Spec.Storage.Class "%v" not found`, spec.Class)
		}
		return nil, err
	}

	if len(spec.AccessModes) == 0 {
		spec.AccessModes = []kapi.PersistentVolumeAccessMode{
			kapi.ReadWriteOnce,
		}
		log.Infof(`Using "%v" as AccessModes in "%v"`, kapi.ReadWriteOnce, *spec)
	}

	if val, found := spec.Resources.Requests[kapi.ResourceStorage]; found {
		if val.Value() <= 0 {
			return nil, errors.New("Invalid ResourceStorage request")
		}
	} else {
		return nil, errors.New("Missing ResourceStorage request")
	}

	return spec, nil
}

func (c *Controller) ValidateBackupSchedule(spec *tapi.BackupScheduleSpec) error {
	if spec == nil {
		return nil
	}
	// CronExpression can't be empty
	if spec.CronExpression == "" {
		return errors.New("Invalid cron expression")
	}

	return c.ValidateSnapshotSpec(spec.SnapshotSpec)
}

func (c *Controller) ValidateSnapshotSpec(spec tapi.SnapshotSpec) error {
	// BucketName can't be empty
	bucketName := spec.BucketName
	if bucketName == "" {
		return fmt.Errorf(`Object 'BucketName' is missing in '%v'`, spec)
	}

	// Need to provide Storage credential secret
	storageSecret := spec.StorageSecret
	if storageSecret == nil {
		return fmt.Errorf(`Object 'StorageSecret' is missing in '%v'`, spec)
	}

	// Credential SecretName  can't be empty
	storageSecretName := storageSecret.SecretName
	if storageSecretName == "" {
		return fmt.Errorf(`Object 'SecretName' is missing in '%v'`, *spec.StorageSecret)
	}
	return nil
}

const (
	keyProvider = "provider"
	keyConfig   = "config"
)

func (c *Controller) CheckBucketAccess(bucketName string, secretSource *kapi.SecretVolumeSource, namespace string) error {
	secret, err := c.Client.Core().Secrets(namespace).Get(secretSource.SecretName)
	if err != nil {
		return err
	}

	provider := secret.Data[keyProvider]
	if provider == nil {
		return errors.New("Missing provider key")
	}
	configData := secret.Data[keyConfig]
	if configData == nil {
		return errors.New("Missing config key")
	}

	var config stow.ConfigMap
	if err := yaml.Unmarshal(configData, &config); err != nil {
		return err
	}

	loc, err := stow.Dial(string(provider), config)
	if err != nil {
		return err
	}

	container, err := loc.Container(bucketName)
	if err != nil {
		return err
	}

	r := bytes.NewReader([]byte("CheckBucketAccess"))
	item, err := container.Put(".k8sdb", r, r.Size(), nil)
	if err != nil {
		return err
	}

	if err := container.RemoveItem(item.ID()); err != nil {
		return err
	}
	return nil
}

func (c *Controller) CreateGoverningServiceAccount(name, namespace string) error {
	var err error
	if _, err = c.Client.Core().ServiceAccounts(namespace).Get(name); err == nil {
		return nil
	}
	if !k8serr.IsNotFound(err) {
		return err
	}

	serviceAccount := &kapi.ServiceAccount{
		ObjectMeta: kapi.ObjectMeta{
			Name: name,
		},
	}
	_, err = c.Client.Core().ServiceAccounts(namespace).Create(serviceAccount)
	return err
}

func (c *Controller) CheckStatefulSetPodStatus(statefulSet *kapps.StatefulSet, checkDuration time.Duration) error {
	podName := fmt.Sprintf("%v-%v", statefulSet.Name, 0)

	podReady := false
	then := time.Now()
	now := time.Now()
	for now.Sub(then) < checkDuration {
		pod, err := c.Client.Core().Pods(statefulSet.Namespace).Get(podName)
		if err != nil {
			if k8serr.IsNotFound(err) {
				_, err := c.Client.Apps().StatefulSets(statefulSet.Namespace).Get(statefulSet.Name)
				if k8serr.IsNotFound(err) {
					break
				}

				time.Sleep(time.Second * 10)
				now = time.Now()
				continue
			} else {
				return err
			}
		}
		log.Debugf("Pod Phase: %v", pod.Status.Phase)

		// If job is success
		if pod.Status.Phase == kapi.PodRunning {
			podReady = true
			break
		}

		time.Sleep(time.Minute)
		now = time.Now()
	}
	if !podReady {
		return errors.New("Database fails to be Ready")
	}
	return nil
}

func (c *Controller) DeletePersistentVolumeClaims(namespace string, selector labels.Selector) error {
	pvcList, err := c.Client.Core().PersistentVolumeClaims(namespace).List(
		kapi.ListOptions{
			LabelSelector: selector,
		},
	)
	if err != nil {
		return err
	}

	for _, pvc := range pvcList.Items {
		if err := c.Client.Core().PersistentVolumeClaims(pvc.Namespace).Delete(pvc.Name, nil); err != nil {
			return err
		}
	}
	return nil
}

func (c *Controller) DeleteSnapshotData(
	bucketName, folderName, snapshotName string,
	secretSource *kapi.SecretVolumeSource,
	namespace string) error {

	secret, err := c.Client.Core().Secrets(namespace).Get(secretSource.SecretName)
	if err != nil {
		return err
	}

	provider := secret.Data[keyProvider]
	if provider == nil {
		return errors.New("Missing provider key")
	}
	configData := secret.Data[keyConfig]
	if configData == nil {
		return errors.New("Missing config key")
	}

	var config stow.ConfigMap
	if err := yaml.Unmarshal(configData, &config); err != nil {
		return err
	}

	loc, err := stow.Dial(string(provider), config)
	if err != nil {
		return err
	}

	container, err := loc.Container(bucketName)
	if err != nil {
		return err
	}

	prefix := fmt.Sprintf("%v/%v", folderName, snapshotName)
	cursor := stow.CursorStart
	for {
		items, next, err := container.Items(prefix, cursor, 50)
		if err != nil {
			return err
		}
		for _, item := range items {
			if err := container.RemoveItem(item.ID()); err != nil {
				return err
			}
		}
		cursor = next
		if stow.IsCursorEnd(cursor) {
			break
		}
	}

	return nil
}

func (c *Controller) DeleteDatabaseSnapshots(namespace string, selector labels.Selector) error {
	dbSnapshotList, err := c.ExtClient.DatabaseSnapshots(namespace).List(
		kapi.ListOptions{
			LabelSelector: selector,
		},
	)
	if err != nil {
		return err
	}

	for _, dbsnapshot := range dbSnapshotList.Items {
		if err := c.ExtClient.DatabaseSnapshots(dbsnapshot.Namespace).Delete(dbsnapshot.Name); err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>Pass *tapi.DatabaseSnapshot to remove SnapshotData from cloud<commit_after>package controller

import (
	"bytes"
	"errors"
	"fmt"
	"time"

	"github.com/appscode/log"
	"github.com/ghodss/yaml"
	"github.com/graymeta/stow"
	_ "github.com/graymeta/stow/google"
	_ "github.com/graymeta/stow/s3"
	tapi "github.com/k8sdb/apimachinery/api"
	kapi "k8s.io/kubernetes/pkg/api"
	k8serr "k8s.io/kubernetes/pkg/api/errors"
	kapps "k8s.io/kubernetes/pkg/apis/apps"
	"k8s.io/kubernetes/pkg/labels"
)

func (c *Controller) ValidateStorageSpec(spec *tapi.StorageSpec) (*tapi.StorageSpec, error) {
	if spec == nil {
		return nil, nil
	}

	if spec.Class == "" {
		return nil, fmt.Errorf(`Object 'Class' is missing in '%v'`, *spec)
	}

	if _, err := c.Client.Storage().StorageClasses().Get(spec.Class); err != nil {
		if k8serr.IsNotFound(err) {
			return nil, fmt.Errorf(`Spec.Storage.Class "%v" not found`, spec.Class)
		}
		return nil, err
	}

	if len(spec.AccessModes) == 0 {
		spec.AccessModes = []kapi.PersistentVolumeAccessMode{
			kapi.ReadWriteOnce,
		}
		log.Infof(`Using "%v" as AccessModes in "%v"`, kapi.ReadWriteOnce, *spec)
	}

	if val, found := spec.Resources.Requests[kapi.ResourceStorage]; found {
		if val.Value() <= 0 {
			return nil, errors.New("Invalid ResourceStorage request")
		}
	} else {
		return nil, errors.New("Missing ResourceStorage request")
	}

	return spec, nil
}

func (c *Controller) ValidateBackupSchedule(spec *tapi.BackupScheduleSpec) error {
	if spec == nil {
		return nil
	}
	// CronExpression can't be empty
	if spec.CronExpression == "" {
		return errors.New("Invalid cron expression")
	}

	return c.ValidateSnapshotSpec(spec.SnapshotSpec)
}

func (c *Controller) ValidateSnapshotSpec(spec tapi.SnapshotSpec) error {
	// BucketName can't be empty
	bucketName := spec.BucketName
	if bucketName == "" {
		return fmt.Errorf(`Object 'BucketName' is missing in '%v'`, spec)
	}

	// Need to provide Storage credential secret
	storageSecret := spec.StorageSecret
	if storageSecret == nil {
		return fmt.Errorf(`Object 'StorageSecret' is missing in '%v'`, spec)
	}

	// Credential SecretName  can't be empty
	storageSecretName := storageSecret.SecretName
	if storageSecretName == "" {
		return fmt.Errorf(`Object 'SecretName' is missing in '%v'`, *spec.StorageSecret)
	}
	return nil
}

const (
	keyProvider = "provider"
	keyConfig   = "config"
)

func (c *Controller) CheckBucketAccess(bucketName string, secretSource *kapi.SecretVolumeSource, namespace string) error {
	secret, err := c.Client.Core().Secrets(namespace).Get(secretSource.SecretName)
	if err != nil {
		return err
	}

	provider := secret.Data[keyProvider]
	if provider == nil {
		return errors.New("Missing provider key")
	}
	configData := secret.Data[keyConfig]
	if configData == nil {
		return errors.New("Missing config key")
	}

	var config stow.ConfigMap
	if err := yaml.Unmarshal(configData, &config); err != nil {
		return err
	}

	loc, err := stow.Dial(string(provider), config)
	if err != nil {
		return err
	}

	container, err := loc.Container(bucketName)
	if err != nil {
		return err
	}

	r := bytes.NewReader([]byte("CheckBucketAccess"))
	item, err := container.Put(".k8sdb", r, r.Size(), nil)
	if err != nil {
		return err
	}

	if err := container.RemoveItem(item.ID()); err != nil {
		return err
	}
	return nil
}

func (c *Controller) CreateGoverningServiceAccount(name, namespace string) error {
	var err error
	if _, err = c.Client.Core().ServiceAccounts(namespace).Get(name); err == nil {
		return nil
	}
	if !k8serr.IsNotFound(err) {
		return err
	}

	serviceAccount := &kapi.ServiceAccount{
		ObjectMeta: kapi.ObjectMeta{
			Name: name,
		},
	}
	_, err = c.Client.Core().ServiceAccounts(namespace).Create(serviceAccount)
	return err
}

func (c *Controller) CheckStatefulSetPodStatus(statefulSet *kapps.StatefulSet, checkDuration time.Duration) error {
	podName := fmt.Sprintf("%v-%v", statefulSet.Name, 0)

	podReady := false
	then := time.Now()
	now := time.Now()
	for now.Sub(then) < checkDuration {
		pod, err := c.Client.Core().Pods(statefulSet.Namespace).Get(podName)
		if err != nil {
			if k8serr.IsNotFound(err) {
				_, err := c.Client.Apps().StatefulSets(statefulSet.Namespace).Get(statefulSet.Name)
				if k8serr.IsNotFound(err) {
					break
				}

				time.Sleep(time.Second * 10)
				now = time.Now()
				continue
			} else {
				return err
			}
		}
		log.Debugf("Pod Phase: %v", pod.Status.Phase)

		// If job is success
		if pod.Status.Phase == kapi.PodRunning {
			podReady = true
			break
		}

		time.Sleep(time.Minute)
		now = time.Now()
	}
	if !podReady {
		return errors.New("Database fails to be Ready")
	}
	return nil
}

func (c *Controller) DeletePersistentVolumeClaims(namespace string, selector labels.Selector) error {
	pvcList, err := c.Client.Core().PersistentVolumeClaims(namespace).List(
		kapi.ListOptions{
			LabelSelector: selector,
		},
	)
	if err != nil {
		return err
	}

	for _, pvc := range pvcList.Items {
		if err := c.Client.Core().PersistentVolumeClaims(pvc.Namespace).Delete(pvc.Name, nil); err != nil {
			return err
		}
	}
	return nil
}

func (c *Controller) DeleteSnapshotData(dbSnapshot *tapi.DatabaseSnapshot) error {
	secret, err := c.Client.Core().Secrets(dbSnapshot.Namespace).Get(dbSnapshot.Spec.StorageSecret.SecretName)
	if err != nil {
		return err
	}

	provider := secret.Data[keyProvider]
	if provider == nil {
		return errors.New("Missing provider key")
	}
	configData := secret.Data[keyConfig]
	if configData == nil {
		return errors.New("Missing config key")
	}

	var config stow.ConfigMap
	if err := yaml.Unmarshal(configData, &config); err != nil {
		return err
	}

	loc, err := stow.Dial(string(provider), config)
	if err != nil {
		return err
	}

	container, err := loc.Container(dbSnapshot.Spec.BucketName)
	if err != nil {
		return err
	}

	folderName := dbSnapshot.Labels[LabelDatabaseType] + "-" + dbSnapshot.Spec.DatabaseName
	prefix := fmt.Sprintf("%v/%v", folderName, dbSnapshot.Name)
	cursor := stow.CursorStart
	for {
		items, next, err := container.Items(prefix, cursor, 50)
		if err != nil {
			return err
		}
		for _, item := range items {
			if err := container.RemoveItem(item.ID()); err != nil {
				return err
			}
		}
		cursor = next
		if stow.IsCursorEnd(cursor) {
			break
		}
	}

	return nil
}

func (c *Controller) DeleteDatabaseSnapshots(namespace string, selector labels.Selector) error {
	dbSnapshotList, err := c.ExtClient.DatabaseSnapshots(namespace).List(
		kapi.ListOptions{
			LabelSelector: selector,
		},
	)
	if err != nil {
		return err
	}

	for _, dbsnapshot := range dbSnapshotList.Items {
		if err := c.ExtClient.DatabaseSnapshots(dbsnapshot.Namespace).Delete(dbsnapshot.Name); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"time"
)

const (
	DefaultDockerHost    = "tcp://localhost:2375"
	DefaultEtcdEndpoint  = "http://localhost:2379"
	DefaultRepositoryDir = "/repos"
)

func registerApplicationMetadata(commitMetadata *CommitMetadata, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + commitMetadata.Username

	if etcd.HasKey(userDirectoryKey) {
		_ = etcd.Mkdir(userDirectoryKey)
	}

	appDirectoryKey := userDirectoryKey + "/" + commitMetadata.AppName

	if etcd.HasKey(appDirectoryKey) {
		_ = etcd.Mkdir(appDirectoryKey)
		_ = etcd.Mkdir(appDirectoryKey + "/envs")
		_ = etcd.Mkdir(appDirectoryKey + "/revisions")
	}

	if err := etcd.Set(appDirectoryKey+"/revisions/"+commitMetadata.Revision, strconv.FormatInt(time.Now().Unix(), 10)); err != nil {
		return err
	}

	return nil
}

func unpackReceivedFiles(repositoryDir, username, projectName string, stdin io.Reader) (string, error) {
	repositoryPath := filepath.Join(repositoryDir, username, projectName)

	if err := os.MkdirAll(repositoryPath, 0777); err != nil {
		return "", err
	}

	reader := tar.NewReader(stdin)

	for {
		header, err := reader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			return "", err
		}

		buffer := new(bytes.Buffer)
		outPath := filepath.Join(repositoryPath, header.Name)

		switch header.Typeflag {
		case tar.TypeDir:
			if _, err = os.Stat(outPath); err != nil {
				os.MkdirAll(outPath, 0755)
			}

		case tar.TypeReg, tar.TypeRegA:
			if _, err = io.Copy(buffer, reader); err != nil {
				return "", err
			}

			if err = ioutil.WriteFile(outPath, buffer.Bytes(), os.FileMode(header.Mode)); err != nil {
				return "", err
			}
		}
	}

	return repositoryPath, nil
}

func main() {
	dockerHost := os.Getenv("DOCKER_HOST")

	if dockerHost == "" {
		dockerHost = DefaultDockerHost
	}

	etcdEndpoint := os.Getenv("ETCD_ENDPOINT")

	if etcdEndpoint == "" {
		etcdEndpoint = DefaultEtcdEndpoint
	}

	repositoryDir := os.Getenv("REPOSITORY_DIR")

	if repositoryDir == "" {
		repositoryDir = DefaultRepositoryDir
	}

	commitMetadata := NewCommitMetadataFromArgs(os.Args[1:])

	fmt.Println(commitMetadata.Repository)
	fmt.Println(commitMetadata.Revision)
	fmt.Println(commitMetadata.Username)
	fmt.Println(commitMetadata.AppName)
	fmt.Println(commitMetadata.ProjectName)

	repositoryPath, err := unpackReceivedFiles(repositoryDir, commitMetadata.Username, commitMetadata.AppName, os.Stdin)

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println(repositoryPath)

	if err = os.Chdir(repositoryPath); err != nil {
		fmt.Fprintln(os.Stderr, err)
	}

	composeFilePath := filepath.Join(repositoryPath, "docker-compose.yml")

	if _, err := os.Stat(composeFilePath); err != nil {
		fmt.Fprintln(os.Stderr, "=====> docker-compose.yml was NOT found!")
		os.Exit(1)
	}

	fmt.Println("=====> docker-compose.yml was found")
	compose := NewCompose(composeFilePath, commitMetadata.ProjectName)

	fmt.Println("=====> Building ...")

	if err = compose.Build(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println("=====> Pulling ...")

	if err = compose.Pull(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println("=====> Deploying ...")

	if err = compose.Up(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	webContainerId, err := compose.GetContainerId("web")

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println(webContainerId)

	webContainer, err := NewContainer(dockerHost, webContainerId)

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	webContainerHostIp := webContainer.HostIP()
	webContainerHostPort := webContainer.HostPort()

	fmt.Println(webContainerHostIp)
	fmt.Println(webContainerHostPort)

	etcd, err := NewEtcd(etcdEndpoint)

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	if err = registerApplicationMetadata(commitMetadata, etcd); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<commit_msg>Extract deploy process to deploy function<commit_after>package main

import (
	"archive/tar"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"time"
)

const (
	DefaultDockerHost    = "tcp://localhost:2375"
	DefaultEtcdEndpoint  = "http://localhost:2379"
	DefaultRepositoryDir = "/repos"
)

func deploy(commitMetadata *CommitMetadata, composeFilePath string) (string, error) {
	var err error

	compose := NewCompose(composeFilePath, commitMetadata.ProjectName)

	fmt.Println("=====> Building ...")

	if err = compose.Build(); err != nil {
		return "", err
	}

	fmt.Println("=====> Pulling ...")

	if err = compose.Pull(); err != nil {
		return "", err
	}

	fmt.Println("=====> Deploying ...")

	if err = compose.Up(); err != nil {
		return "", err
	}

	webContainerId, err := compose.GetContainerId("web")

	if err != nil {
		return "", err
	}

	return webContainerId, nil
}

func registerApplicationMetadata(commitMetadata *CommitMetadata, etcd *Etcd) error {
	userDirectoryKey := "/paus/users/" + commitMetadata.Username

	if etcd.HasKey(userDirectoryKey) {
		_ = etcd.Mkdir(userDirectoryKey)
	}

	appDirectoryKey := userDirectoryKey + "/" + commitMetadata.AppName

	if etcd.HasKey(appDirectoryKey) {
		_ = etcd.Mkdir(appDirectoryKey)
		_ = etcd.Mkdir(appDirectoryKey + "/envs")
		_ = etcd.Mkdir(appDirectoryKey + "/revisions")
	}

	if err := etcd.Set(appDirectoryKey+"/revisions/"+commitMetadata.Revision, strconv.FormatInt(time.Now().Unix(), 10)); err != nil {
		return err
	}

	return nil
}

func unpackReceivedFiles(repositoryDir, username, projectName string, stdin io.Reader) (string, error) {
	repositoryPath := filepath.Join(repositoryDir, username, projectName)

	if err := os.MkdirAll(repositoryPath, 0777); err != nil {
		return "", err
	}

	reader := tar.NewReader(stdin)

	for {
		header, err := reader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			return "", err
		}

		buffer := new(bytes.Buffer)
		outPath := filepath.Join(repositoryPath, header.Name)

		switch header.Typeflag {
		case tar.TypeDir:
			if _, err = os.Stat(outPath); err != nil {
				os.MkdirAll(outPath, 0755)
			}

		case tar.TypeReg, tar.TypeRegA:
			if _, err = io.Copy(buffer, reader); err != nil {
				return "", err
			}

			if err = ioutil.WriteFile(outPath, buffer.Bytes(), os.FileMode(header.Mode)); err != nil {
				return "", err
			}
		}
	}

	return repositoryPath, nil
}

func main() {
	dockerHost := os.Getenv("DOCKER_HOST")

	if dockerHost == "" {
		dockerHost = DefaultDockerHost
	}

	etcdEndpoint := os.Getenv("ETCD_ENDPOINT")

	if etcdEndpoint == "" {
		etcdEndpoint = DefaultEtcdEndpoint
	}

	repositoryDir := os.Getenv("REPOSITORY_DIR")

	if repositoryDir == "" {
		repositoryDir = DefaultRepositoryDir
	}

	commitMetadata := NewCommitMetadataFromArgs(os.Args[1:])

	fmt.Println(commitMetadata.Repository)
	fmt.Println(commitMetadata.Revision)
	fmt.Println(commitMetadata.Username)
	fmt.Println(commitMetadata.AppName)
	fmt.Println(commitMetadata.ProjectName)

	repositoryPath, err := unpackReceivedFiles(repositoryDir, commitMetadata.Username, commitMetadata.AppName, os.Stdin)

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Println(repositoryPath)

	if err = os.Chdir(repositoryPath); err != nil {
		fmt.Fprintln(os.Stderr, err)
	}

	composeFilePath := filepath.Join(repositoryPath, "docker-compose.yml")

	if _, err := os.Stat(composeFilePath); err != nil {
		fmt.Fprintln(os.Stderr, "=====> docker-compose.yml was NOT found!")
		os.Exit(1)
	}

	fmt.Println("=====> docker-compose.yml was found")
	webContainerId, err := deploy(commitMetadata, composeFilePath)

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	webContainer, err := NewContainer(dockerHost, webContainerId)

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	webContainerHostIp := webContainer.HostIP()
	webContainerHostPort := webContainer.HostPort()

	fmt.Println(webContainerHostIp)
	fmt.Println(webContainerHostPort)

	etcd, err := NewEtcd(etcdEndpoint)

	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	if err = registerApplicationMetadata(commitMetadata, etcd); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package log

import (
	"errors"
	"os"
)

// File logs to a local file for all messages at or above Level.
type File struct {
	Default // File embeds default
	Path    string
}

const (
	// FileFlags serts the flags for OpenFile on the log file
	FileFlags = os.O_WRONLY | os.O_APPEND | os.O_CREATE

	// FilePermissions serts the perms for OpenFile on the log file
	FilePermissions = 0640
)

// NewFile creates a new file logger for the given path at Level Info.
func NewFile(path string) (*File, error) {
	if path == "" {
		return nil, errors.New("log: null file path for file log")
	}

	f := &File{
		Default: Default{
			Prefix: "",
			Level:  LevelInfo,
			Writer: nil,
			Color:  false,
		},
	}

	// Set the writer to the given file
	logFile, err := os.OpenFile(path, FileFlags, FilePermissions)
	if err != nil {
		return nil, err
	}

	f.Writer = logFile

	return f, nil
}
<commit_msg>Added date/time prefix to file logger<commit_after>package log

import (
	"errors"
	"os"
)

// File logs to a local file for all messages at or above Level.
type File struct {
	Default // File embeds default
	Path    string
}

const (
	// FileFlags serts the flags for OpenFile on the log file
	FileFlags = os.O_WRONLY | os.O_APPEND | os.O_CREATE

	// FilePermissions serts the perms for OpenFile on the log file
	FilePermissions = 0640
)

// NewFile creates a new file logger for the given path at Level Info.
func NewFile(path string) (*File, error) {
	if path == "" {
		return nil, errors.New("log: null file path for file log")
	}

	f := &File{
		Default: Default{
			Prefix: PrefixDateTime,
			Level:  LevelInfo,
			Writer: nil,
			Color:  false,
		},
	}

	// Set the writer to the given file
	logFile, err := os.OpenFile(path, FileFlags, FilePermissions)
	if err != nil {
		return nil, err
	}

	f.Writer = logFile

	return f, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"socialapi/models"
	"socialapi/rest"

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

var (
	PARTICIPANT_COUNT = 4
)

func testFrontpageOperations() {

	var accounts []int64
	for i := 0; i < 2; i++ {
		account := models.NewAccount()
		account.OldId = bson.NewObjectId().Hex()
		account, _ = rest.CreateAccount(account)
		accounts = append(accounts, account.Id)
	}

	for i := 0; i < len(accounts); i++ {
		_, err := populateChannelwithAccount(accounts[i])
		if err != nil {
			fmt.Println(err)
			return
		}
	}

	for i := 0; i < len(accounts); i++ {
		channels, err := rest.FetchChannels(accounts[i])
		if err != nil {
			fmt.Println(err)
			return
		}
		for j := 0; j < len(channels); j++ {
			fetchHistoryAndCheckMessages(channels[j].Id, accounts[i])
		}
	}
}
func fetchHistoryAndCheckMessages(channelId, accountId int64) {
	history, err := rest.GetHistory(channelId, accountId)
	if err != nil {
		fmt.Println(err)
		return
	}

	if len(history.MessageList) != PARTICIPANT_COUNT {
		fmt.Println("history should have 4 messages", len(history.MessageList))
		return
	}

	for i := 0; i < len(history.MessageList); i++ {
		if len(history.MessageList[i].Replies) != PARTICIPANT_COUNT {
			fmt.Println("replies count should be PARTICIPANT_COUNT", len(history.MessageList[i].Replies))
		}
		if len(history.MessageList[i].Interactions) != 1 {
			fmt.Println("interaction count should be PARTICIPANT_COUNT", len(history.MessageList[i].Interactions))
		}
	}

	// fmt.Println(history.UnreadCount)
}

func populateChannelwithAccount(accountId int64) (*models.Channel, error) {
	channel, err := rest.CreateChannel(accountId)
	if err != nil {
		return nil, err
	}

	_, err = rest.AddChannelParticipant(channel.Id, accountId, accountId)
	if err != nil {
		return nil, err
	}

	participants, err := rest.CreateChannelParticipants(channel.Id, PARTICIPANT_COUNT)
	if err != nil {
		return nil, err
	}

	//everyone will post status update
	for i := 0; i < len(participants); i++ {
		_, err := populatePost(channel.Id, participants[i].AccountId)
		if err != nil {
			return nil, err
		}
	}

	return channel, nil

}

func populatePost(channelId, accountId int64) (*models.ChannelMessage, error) {
	post, err := rest.CreatePost(channelId, accountId)
	if err != nil {
		return nil, err
	}

	participants, err := rest.CreateChannelParticipants(channelId, PARTICIPANT_COUNT)
	if err != nil {
		return nil, err
	}

	for i := 0; i < len(participants); i++ {
		reply, err := rest.AddReply(post.Id, participants[i].AccountId, post.InitialChannelId)
		if err != nil {
			return nil, err
		}

		// add likes to replies
		err = rest.AddInteraction("like", reply.Id, participants[i].AccountId)
		if err != nil {
			return nil, err
		}

		// like every comment
		err = rest.AddInteraction("like", reply.Id, accountId)
		if err != nil {
			return nil, err
		}

		// add likes to post
		err = rest.AddInteraction("like", post.Id, participants[i].AccountId)
		if err != nil {
			return nil, err
		}

	}

	// like your post
	err = rest.AddInteraction("like", post.Id, accountId)
	if err != nil {
		return nil, err
	}

	return post, nil
}
<commit_msg>Social: inject request param into GetHistory function<commit_after>package main

import (
	"fmt"
	"socialapi/models"
	"socialapi/request"
	"socialapi/rest"

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

var (
	PARTICIPANT_COUNT = 4
)

func testFrontpageOperations() {

	var accounts []int64
	for i := 0; i < 2; i++ {
		account := models.NewAccount()
		account.OldId = bson.NewObjectId().Hex()
		account, _ = rest.CreateAccount(account)
		accounts = append(accounts, account.Id)
	}

	for i := 0; i < len(accounts); i++ {
		_, err := populateChannelwithAccount(accounts[i])
		if err != nil {
			fmt.Println(err)
			return
		}
	}

	for i := 0; i < len(accounts); i++ {
		channels, err := rest.FetchChannels(accounts[i])
		if err != nil {
			fmt.Println(err)
			return
		}
		for j := 0; j < len(channels); j++ {
			fetchHistoryAndCheckMessages(channels[j].Id, accounts[i])
		}
	}
}

func fetchHistoryAndCheckMessages(channelId, accountId int64) {
	history, err := rest.GetHistory(channelId, &request.Query{AccountId: accountId})
	if err != nil {
		fmt.Println(err)
		return
	}

	if len(history.MessageList) != PARTICIPANT_COUNT {
		fmt.Println("history should have 4 messages", len(history.MessageList))
		return
	}

	for i := 0; i < len(history.MessageList); i++ {
		if len(history.MessageList[i].Replies) != PARTICIPANT_COUNT {
			fmt.Println("replies count should be PARTICIPANT_COUNT", len(history.MessageList[i].Replies))
		}
		if len(history.MessageList[i].Interactions) != 1 {
			fmt.Println("interaction count should be PARTICIPANT_COUNT", len(history.MessageList[i].Interactions))
		}
	}

	// fmt.Println(history.UnreadCount)
}

func populateChannelwithAccount(accountId int64) (*models.Channel, error) {
	channel, err := rest.CreateChannel(accountId)
	if err != nil {
		return nil, err
	}

	_, err = rest.AddChannelParticipant(channel.Id, accountId, accountId)
	if err != nil {
		return nil, err
	}

	participants, err := rest.CreateChannelParticipants(channel.Id, PARTICIPANT_COUNT)
	if err != nil {
		return nil, err
	}

	//everyone will post status update
	for i := 0; i < len(participants); i++ {
		_, err := populatePost(channel.Id, participants[i].AccountId)
		if err != nil {
			return nil, err
		}
	}

	return channel, nil

}

func populatePost(channelId, accountId int64) (*models.ChannelMessage, error) {
	post, err := rest.CreatePost(channelId, accountId)
	if err != nil {
		return nil, err
	}

	participants, err := rest.CreateChannelParticipants(channelId, PARTICIPANT_COUNT)
	if err != nil {
		return nil, err
	}

	for i := 0; i < len(participants); i++ {
		reply, err := rest.AddReply(post.Id, participants[i].AccountId, post.InitialChannelId)
		if err != nil {
			return nil, err
		}

		// add likes to replies
		err = rest.AddInteraction("like", reply.Id, participants[i].AccountId)
		if err != nil {
			return nil, err
		}

		// like every comment
		err = rest.AddInteraction("like", reply.Id, accountId)
		if err != nil {
			return nil, err
		}

		// add likes to post
		err = rest.AddInteraction("like", post.Id, participants[i].AccountId)
		if err != nil {
			return nil, err
		}

	}

	// like your post
	err = rest.AddInteraction("like", post.Id, accountId)
	if err != nil {
		return nil, err
	}

	return post, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"
)

type APRSPacket struct {
	Callsign      string
	PacketType    string
	Latitude      string
	Longitude     string
	Altitude      string
	GPSTime       string
	RawData       string
	Symbol        string
	Heading       string
	PHG           string
	Speed         string
	Destination   string
	Status        string
	WindDirection string
	WindSpeed     string
	WindGust      string
	WeatherTemp   string
	RainHour      string
	RainDay       string
	RainMidnight  string
	Humidity      string
	Pressure      string
	Luminosity    string
	Snowfall      string
	Raincounter   string
	Error         string
}

func ParseAPRSPacket(input string) (p APRSPacket, e error) {
	if input == "" {
		e = fmt.Errorf("Could not parse the packet because the packet line is blank")
		return p, e
	}

	if !strings.HasPrefix(input, ">") {
		e = fmt.Errorf("This libary does not support this kind of packet.")
		return p, e
	}
	return p, e
}
<commit_msg>Remove error from the struct, since its uneeded.<commit_after>package main

import (
	"fmt"
	"strings"
)

type APRSPacket struct {
	Callsign      string
	PacketType    string
	Latitude      string
	Longitude     string
	Altitude      string
	GPSTime       string
	RawData       string
	Symbol        string
	Heading       string
	PHG           string
	Speed         string
	Destination   string
	Status        string
	WindDirection string
	WindSpeed     string
	WindGust      string
	WeatherTemp   string
	RainHour      string
	RainDay       string
	RainMidnight  string
	Humidity      string
	Pressure      string
	Luminosity    string
	Snowfall      string
	Raincounter   string
}

func ParseAPRSPacket(input string) (p APRSPacket, e error) {
	if input == "" {
		e = fmt.Errorf("Could not parse the packet because the packet line is blank")
		return p, e
	}

	if !strings.HasPrefix(input, ">") {
		e = fmt.Errorf("This libary does not support this kind of packet.")
		return p, e
	}
	return p, e
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"io"

	kcmd "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
	cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
	"github.com/spf13/cobra"

	"github.com/openshift/origin/pkg/cmd/util/clientcmd"
)

const (
	exposeLong = `Expose containers internally as services or externally via routes.

There is also the ability to expose a deployment configuration, replication controller, service, or pod
as a new service on a specified port. If no labels are specified, the new object will re-use the
labels from the object it exposes.`

	exposeExample = `// Create a route based on service nginx. The new route will re-use nginx's labels
$ %[1]s expose service nginx

// Create a route and specify your own label and route name
$ %[1]s expose service nginx --labels name=myroute --name=fromdowntown

// Expose a deployment configuration as a service and use the specified port
$ %[1]s expose dc ruby-hello-world --port=8080 --generator=services/v1`
)

// NewCmdExpose is a wrapper for the Kubernetes cli expose command
func NewCmdExpose(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command {
	cmd := kcmd.NewCmdExposeService(f.Factory, out)
	cmd.Long = exposeLong
	cmd.Example = fmt.Sprintf(exposeExample, fullName)
	cmd.Flags().Set("generator", "route/v1")
	cmd.Run = func(cmd *cobra.Command, args []string) {
		err := validate(cmd, f, args)
		cmdutil.CheckErr(err)
		err = kcmd.RunExpose(f.Factory, out, cmd, args)
		cmdutil.CheckErr(err)
	}
	return cmd
}

// validate adds one layer of validation prior to calling the upstream
// expose command. Used only for validating services that are about
// to be exposed as routes.
func validate(cmd *cobra.Command, f *clientcmd.Factory, args []string) error {
	if cmdutil.GetFlagString(cmd, "generator") != "route/v1" {
		return nil
	}
	namespace, err := f.DefaultNamespace()
	if err != nil {
		return err
	}

	_, kc, err := f.Clients()
	if err != nil {
		return err
	}

	mapper, typer := f.Object()
	r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
		ContinueOnError().
		NamespaceParam(namespace).DefaultNamespace().
		ResourceTypeOrNameArgs(false, args...).
		Flatten().
		Do()
	err = r.Err()
	if err != nil {
		return err
	}
	mapping, err := r.ResourceMapping()
	if err != nil {
		return err
	}
	infos, err := r.Infos()
	if err != nil {
		return err
	}
	if len(infos) > 1 {
		return fmt.Errorf("multiple resources provided: %v", args)
	}
	info := infos[0]

	switch mapping.Kind {
	case "Service":
		svc, err := kc.Services(info.Namespace).Get(info.Name)
		if err != nil {
			return err
		}

		supportsTCP := false
		for _, port := range svc.Spec.Ports {
			if port.Protocol == "TCP" {
				supportsTCP = true
				break
			}
		}
		if !supportsTCP {
			return fmt.Errorf("service %s doesn't support TCP", info.Name)
		}
	default:
		return fmt.Errorf("cannot expose a %s as a route", mapping.Kind)
	}

	return nil
}
<commit_msg>expose: Fix service validation and help message<commit_after>package cmd

import (
	"fmt"
	"io"
	"strings"

	kcmd "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
	cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
	"github.com/spf13/cobra"

	"github.com/openshift/origin/pkg/cmd/util/clientcmd"
)

const (
	exposeLong = `Expose containers internally as services or externally via routes.

There is also the ability to expose a deployment configuration, replication controller, service, or pod
as a new service on a specified port. If no labels are specified, the new object will re-use the
labels from the object it exposes.`

	exposeExample = `// Create a route based on service nginx. The new route will re-use nginx's labels
$ %[1]s expose service nginx

// Create a route and specify your own label and route name
$ %[1]s expose service nginx -l name=myroute --name=fromdowntown

// Expose a deployment configuration as a service and use the specified port
$ %[1]s expose dc ruby-hello-world --port=8080 --generator=services/v1`
)

// NewCmdExpose is a wrapper for the Kubernetes cli expose command
func NewCmdExpose(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command {
	cmd := kcmd.NewCmdExposeService(f.Factory, out)
	cmd.Long = exposeLong
	cmd.Example = fmt.Sprintf(exposeExample, fullName)
	cmd.Flags().Set("generator", "route/v1")
	cmd.Run = func(cmd *cobra.Command, args []string) {
		err := validate(cmd, f, args)
		cmdutil.CheckErr(err)
		err = kcmd.RunExpose(f.Factory, out, cmd, args)
		cmdutil.CheckErr(err)
	}
	return cmd
}

// validate adds one layer of validation prior to calling the upstream
// expose command. Used only for validating services that are about
// to be exposed as routes.
func validate(cmd *cobra.Command, f *clientcmd.Factory, args []string) error {
	if cmdutil.GetFlagString(cmd, "generator") != "route/v1" {
		return nil
	}
	namespace, err := f.DefaultNamespace()
	if err != nil {
		return err
	}

	_, kc, err := f.Clients()
	if err != nil {
		return err
	}

	mapper, typer := f.Object()
	r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
		ContinueOnError().
		NamespaceParam(namespace).DefaultNamespace().
		ResourceTypeOrNameArgs(false, args...).
		Flatten().
		Do()
	err = r.Err()
	if err != nil {
		return err
	}
	mapping, err := r.ResourceMapping()
	if err != nil {
		return err
	}
	infos, err := r.Infos()
	if err != nil {
		return err
	}
	if len(infos) > 1 {
		return fmt.Errorf("multiple resources provided: %v", args)
	}
	info := infos[0]

	switch mapping.Kind {
	case "Service":
		svc, err := kc.Services(info.Namespace).Get(info.Name)
		if err != nil {
			return err
		}

		supportsTCP := false
		for _, port := range svc.Spec.Ports {
			if strings.ToUpper(string(port.Protocol)) == "TCP" {
				supportsTCP = true
				break
			}
		}
		if !supportsTCP {
			return fmt.Errorf("service %s doesn't support TCP", info.Name)
		}
	default:
		return fmt.Errorf("cannot expose a %s as a route", mapping.Kind)
	}

	return nil
}
<|endoftext|>


<commit_before>package api

// import (
// 	"../transaction"
// 	"crypto/rand"
// 	"encoding/base64"
// 	"encoding/json"
// 	"error"
// 	"fmt"
// 	"github.com/ant0ine/go-json-rest/rest"
// 	"github.com/gorilla/sessions"
// 	"golang.org/x/oauth2"
// 	"log"
// 	"net/http"
// 	"strings"
// )

// // "github.com/google/google-api-go-client/plus/v1"

// const (
// 	SESSION_NAME = "sessionName"
// )

// var ErrFetchingSession error = errors.New("Error fetching session.")

// // config is the configuration specification supplied to the OAuth package.
// var oauthConfig oauth2.Config

// // store initializes the Gorilla session store.
// var store = sessions.NewCookieStore([]byte(randomString(32)))

// // Token represents an OAuth token response.
// type Token struct {
// 	AccessToken string `json:"access_token"`
// 	TokenType   string `json:"token_type"`
// 	ExpiresIn   int    `json:"expires_in"`
// 	IdToken     string `json:"id_token"`
// }

// // ClaimSet represents an IdToken response.
// type ClaimSet struct {
// 	Sub string
// }

// type UserInfo struct {
// 	Email string `json:"email"`
// }

// // exchange takes an authentication code and exchanges it with the OAuth
// // endpoint for a Google API bearer token and a Google+ ID
// func exchange(code string) (accessToken string, idToken string, err error) {
// 	tok, err := oauthConfig.Exchange(oauth2.NoContext, code)
// 	if err != nil {
// 		return "", "", fmt.Errorf("Error while exchanging code: %v", err)
// 	}

// 	// TODO: return ID token in second parameter from updated oauth2 interface
// 	return tok.AccessToken, tok.Extra("id_token").(string), nil
// }

// // decodeIdToken takes an ID Token and decodes it to fetch the Google+ ID within
// func decodeIdToken(idToken string) (gplusID string, err error) {
// 	// An ID token is a cryptographically-signed JSON object encoded in base 64.
// 	// Normally, it is critical that you validate an ID token before you use it,
// 	// but since you are communicating directly with Google over an
// 	// intermediary-free HTTPS channel and using your Client Secret to
// 	// authenticate yourself to Google, you can be confident that the token you
// 	// receive really comes from Google and is valid. If your server passes the ID
// 	// token to other components of your app, it is extremely important that the
// 	// other components validate the token before using it.
// 	var set ClaimSet
// 	if idToken != "" {
// 		// Check that the padding is correct for a base64decode
// 		parts := strings.Split(idToken, ".")
// 		if len(parts) < 2 {
// 			return "", fmt.Errorf("Malformed ID token")
// 		}
// 		// Decode the ID token
// 		b, err := base64Decode(parts[1])
// 		if err != nil {
// 			return "", fmt.Errorf("Malformed ID token: %v", err)
// 		}
// 		err = json.Unmarshal(b, &set)
// 		if err != nil {
// 			return "", fmt.Errorf("Malformed ID token: %v", err)
// 		}
// 	}
// 	return set.Sub, nil
// }

// // randomString returns a random string with the specified length
// func randomString(length int) (str string) {
// 	b := make([]byte, length)
// 	rand.Read(b)
// 	return base64.StdEncoding.EncodeToString(b)
// }

// func base64Decode(s string) ([]byte, error) {
// 	// add back missing padding
// 	switch len(s) % 4 {
// 	case 2:
// 		s += "=="
// 	case 3:
// 		s += "="
// 	}
// 	return base64.URLEncoding.DecodeString(s)
// }

// func getUserInfo(accessToken string) (*UserInfo, error) {
// 	response, err := http.Get("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + accessToken)
// 	if err != nil {
// 		return nil, err
// 	}
// 	defer response.Body.Close()

// 	var userInfo UserInfo
// 	err = json.NewDecoder(response.Body).Decode(&userInfo)
// 	if err != nil {
// 		return nil, err
// 	}
// 	return &userInfo, nil
// }

// // connect exchanges the one-time authorization code for a token and stores the
// // token in the session
// func Login(w rest.ResponseWriter, req *rest.Request) {
// 	type RequestBody struct {
// 		Code *string `json:"code"`
// 	}
// 	type ResponseBody struct {
// 		Username *string `json:"username"`
// 	}

// 	// Ensure that the request is not a forgery and that the user sending this
// 	// connect request is the expected user
// 	session, err := store.Get(req, SESSION_NAME)
// 	if err != nil {
// 		rest.Error(w, "Error fetching session", http.StatusBadRequest)
// 		return
// 	}
// 	if r.FormValue("state") != session.Values["state"].(string) {
// 		rest.Error(w, "Invalid state parameter", http.StatusBadRequest)
// 		return
// 	}

// 	defer r.Body.Close()
// 	var requestBody RequestBody
// 	err = json.NewDecoder(r.Body).Decode(&requestBody)
// 	if err != nil {
// 		rest.Error(w, "Error parsing request body", http.StatusBadRequest)
// 		return
// 	}

// 	fmt.Println(requestBody.Code)

// 	if requestBody.Code == nil && session.Values["acessToken"] != nil {
// 		if session.Values["username"] != nil {
// 			username := session.Values["username"].(string)
// 			json.NewEncoder(w).Encode(ResponseBody{&username})
// 		} else {
// 			json.NewEncoder(w).Encode(ResponseBody{nil})
// 		}
// 		return
// 	} else if requestBody.Code == nil {
// 		json.NewEncoder(w).Encode(ResponseBody{nil})
// 		return
// 	}

// 	accessToken, idToken, err := exchange(*requestBody.Code)
// 	if err != nil {
// 		rest.Error(w, "Error exchanging code for access token", http.StatusBadRequest)
// 		return
// 	}
// 	gplusID, err := decodeIdToken(idToken)
// 	if err != nil {
// 		rest.Error(w, "Error decoding ID token", http.StatusBadRequest)
// 		return
// 	}

// 	// Check if the user is already connected
// 	storedToken := session.Values["accessToken"]
// 	storedGPlusID := session.Values["gplusID"]
// 	if storedToken != nil && storedGPlusID == gplusID {
// 		if session.Values["username"] != nil {
// 			username := session.Values["username"].(string)
// 			w.WriteJson(ResponseBody{&username})
// 		} else {
// 			w.WriteJson(ResponseBody{nil})
// 		}
// 		w.WriteHeader(http.StatusOK)
// 		return
// 	}
// 	session.Values["accessToken"] = accessToken
// 	session.Values["gplusID"] = gplusID

// 	userInfo, err := getUserInfo(accessToken)
// 	if err != nil {
// 		rest.Error(w, "Internal server error", http.StatusBadRequest)
// 		return
// 	}
// 	session.Values["email"] = userInfo.Email

// 	username, err := transaction.GetUsername(userInfo.Email)
// 	if err != nil {
// 		rest.Error(w, "Internal server error", http.StatusBadRequest)
// 		return
// 	} else if username != nil {
// 		session.Values["username"] = username
// 	}

// 	err = session.Save(req, w)
// 	if err != nil {
// 		rest.Error(w, "Internal server error", http.StatusBadRequest)
// 		return
// 	}
// 	w.WriteHeader(http.StatusOK)
// 	w.WriteJson(ResponseBody{username})
// }

// func Logout(w rest.ResponseWriter, req *rest.Request) {
// 	// Only disconnect a connected user
// 	session, err := store.Get(req, SESSION_NAME)
// 	if err != nil {
// 		rest.Error(w, "Error fetching session", http.StatusBadRequest)
// 		return
// 	}

// 	// Reset the user's session
// 	session.Values["accessToken"] = nil
// 	err = session.Save(req, w)
// 	if err != nil {
// 		rest.Error(w, "Error saving session", http.StatusBadRequest)
// 		return
// 	}
// 	w.WriteHeader(http.StatusOK)
// }

// // Disconnect revokes the current user's token and resets their session
// func Disconnect(w http.ResponseWriter, r *http.Request) {
// 	// Only disconnect a connected user
// 	session, err := store.Get(r, SESSION_NAME)
// 	if err != nil {
// 		rest.Error(w, "Error fetching session", http.StatusBadRequest)
// 		return
// 	}
// 	token := session.Values["accessToken"]
// 	if token == nil {
// 		rest.Error(w, "Current user not connected", http.StatusBadRequest)
// 		return
// 	}

// 	// Execute HTTP GET request to revoke current token
// 	url := "https://accounts.google.com/o/oauth2/revoke?token=" + token.(string)
// 	_, err = http.Get(url)
// 	if err != nil {
// 		rest.Error(w, "Failed to revoke token for a given user", http.StatusBadRequest)
// 		return
// 	}

// 	// Reset the user's session
// 	session.Values["accessToken"] = nil
// 	err = session.Save(r, w)
// 	if err != nil {
// 		rest.Error(w, "Error saving session", http.StatusBadRequest)
// 		return
// 	}
// 	w.WriteHeader(http.StatusOK)
// }
<commit_msg>Make login.go compile<commit_after>package api

import (
	"../transaction"
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/ant0ine/go-json-rest/rest"
	"github.com/gorilla/sessions"
	"golang.org/x/oauth2"
	"net/http"
	"strings"
)

// "github.com/google/google-api-go-client/plus/v1"

const (
	SESSION_NAME = "sessionName"
)

var ErrFetchingSession error = errors.New("Error fetching session.")

// config is the configuration specification supplied to the OAuth package.
var oauthConfig oauth2.Config

// store initializes the Gorilla session store.
var store = sessions.NewCookieStore([]byte(randomString(32)))

// Token represents an OAuth token response.
type Token struct {
	AccessToken string `json:"access_token"`
	TokenType   string `json:"token_type"`
	ExpiresIn   int    `json:"expires_in"`
	IdToken     string `json:"id_token"`
}

// ClaimSet represents an IdToken response.
type ClaimSet struct {
	Sub string
}

type UserInfo struct {
	Email string `json:"email"`
}

// exchange takes an authentication code and exchanges it with the OAuth
// endpoint for a Google API bearer token and a Google+ ID
func exchange(code string) (accessToken string, idToken string, err error) {
	tok, err := oauthConfig.Exchange(oauth2.NoContext, code)
	if err != nil {
		return "", "", fmt.Errorf("Error while exchanging code: %v", err)
	}

	// TODO: return ID token in second parameter from updated oauth2 interface
	return tok.AccessToken, tok.Extra("id_token").(string), nil
}

// decodeIdToken takes an ID Token and decodes it to fetch the Google+ ID within
func decodeIdToken(idToken string) (gplusID string, err error) {
	// An ID token is a cryptographically-signed JSON object encoded in base 64.
	// Normally, it is critical that you validate an ID token before you use it,
	// but since you are communicating directly with Google over an
	// intermediary-free HTTPS channel and using your Client Secret to
	// authenticate yourself to Google, you can be confident that the token you
	// receive really comes from Google and is valid. If your server passes the ID
	// token to other components of your app, it is extremely important that the
	// other components validate the token before using it.
	var set ClaimSet
	if idToken != "" {
		// Check that the padding is correct for a base64decode
		parts := strings.Split(idToken, ".")
		if len(parts) < 2 {
			return "", fmt.Errorf("Malformed ID token")
		}
		// Decode the ID token
		b, err := base64Decode(parts[1])
		if err != nil {
			return "", fmt.Errorf("Malformed ID token: %v", err)
		}
		err = json.Unmarshal(b, &set)
		if err != nil {
			return "", fmt.Errorf("Malformed ID token: %v", err)
		}
	}
	return set.Sub, nil
}

// randomString returns a random string with the specified length
func randomString(length int) (str string) {
	b := make([]byte, length)
	rand.Read(b)
	return base64.StdEncoding.EncodeToString(b)
}

func base64Decode(s string) ([]byte, error) {
	// add back missing padding
	switch len(s) % 4 {
	case 2:
		s += "=="
	case 3:
		s += "="
	}
	return base64.URLEncoding.DecodeString(s)
}

func getUserInfo(accessToken string) (*UserInfo, error) {
	response, err := http.Get("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + accessToken)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	var userInfo UserInfo
	err = json.NewDecoder(response.Body).Decode(&userInfo)
	if err != nil {
		return nil, err
	}
	return &userInfo, nil
}

// connect exchanges the one-time authorization code for a token and stores the
// token in the session
func Login(w rest.ResponseWriter, req *rest.Request) {
	type RequestBody struct {
		Code *string `json:"code"`
	}
	type ResponseBody struct {
		Username *string `json:"username"`
	}

	// Ensure that the request is not a forgery and that the user sending this
	// connect request is the expected user
	session, err := store.Get(req.Request, SESSION_NAME)
	if err != nil {
		rest.Error(w, "Error fetching session", http.StatusBadRequest)
		return
	}
	if req.FormValue("state") != session.Values["state"].(string) {
		rest.Error(w, "Invalid state parameter", http.StatusBadRequest)
		return
	}

	defer req.Body.Close()
	var requestBody RequestBody
	err = req.DecodeJsonPayload(&requestBody)
	if err != nil {
		rest.Error(w, "Error parsing request body", http.StatusBadRequest)
		return
	}

	fmt.Println(requestBody.Code)

	if requestBody.Code == nil && session.Values["acessToken"] != nil {
		if session.Values["username"] != nil {
			username := session.Values["username"].(string)
			w.WriteJson(ResponseBody{&username})
			w.WriteHeader(http.StatusOK)
		} else {
			w.WriteJson(ResponseBody{nil})
			w.WriteHeader(http.StatusOK)
		}
		return
	} else if requestBody.Code == nil {
		w.WriteJson(ResponseBody{nil})
		w.WriteHeader(http.StatusOK)
		return
	}

	accessToken, idToken, err := exchange(*requestBody.Code)
	if err != nil {
		rest.Error(w, "Error exchanging code for access token", http.StatusBadRequest)
		return
	}
	gplusID, err := decodeIdToken(idToken)
	if err != nil {
		rest.Error(w, "Error decoding ID token", http.StatusBadRequest)
		return
	}

	// Check if the user is already connected
	storedToken := session.Values["accessToken"]
	storedGPlusID := session.Values["gplusID"]
	if storedToken != nil && storedGPlusID == gplusID {
		if session.Values["username"] != nil {
			username := session.Values["username"].(string)
			w.WriteJson(ResponseBody{&username})
		} else {
			w.WriteJson(ResponseBody{nil})
		}
		w.WriteHeader(http.StatusOK)
		return
	}
	session.Values["accessToken"] = accessToken
	session.Values["gplusID"] = gplusID

	userInfo, err := getUserInfo(accessToken)
	if err != nil {
		rest.Error(w, "Internal server error", http.StatusBadRequest)
		return
	}
	session.Values["email"] = userInfo.Email

	username, err := transaction.GetUsername(userInfo.Email)
	if err != nil {
		rest.Error(w, "Internal server error", http.StatusBadRequest)
		return
	} else if username != nil {
		session.Values["username"] = username
	}

	err = session.Save(req.Request, w.(http.ResponseWriter))
	if err != nil {
		rest.Error(w, "Internal server error", http.StatusBadRequest)
		return
	}
	w.WriteHeader(http.StatusOK)
	w.WriteJson(ResponseBody{username})
}

func Logout(w rest.ResponseWriter, req *rest.Request) {
	// Only disconnect a connected user
	session, err := store.Get(req.Request, SESSION_NAME)
	if err != nil {
		rest.Error(w, "Error fetching session", http.StatusBadRequest)
		return
	}

	// Reset the user's session
	session.Values["accessToken"] = nil
	err = session.Save(req.Request, w.(http.ResponseWriter))
	if err != nil {
		rest.Error(w, "Error saving session", http.StatusBadRequest)
		return
	}
	w.WriteHeader(http.StatusOK)
}

// Disconnect revokes the current user's token and resets their session
func Disconnect(w rest.ResponseWriter, req *rest.Request) {
	// Only disconnect a connected user
	session, err := store.Get(req.Request, SESSION_NAME)
	if err != nil {
		rest.Error(w, "Error fetching session", http.StatusBadRequest)
		return
	}
	token := session.Values["accessToken"]
	if token == nil {
		rest.Error(w, "Current user not connected", http.StatusBadRequest)
		return
	}

	// Execute HTTP GET request to revoke current token
	url := "https://accounts.google.com/o/oauth2/revoke?token=" + token.(string)
	_, err = http.Get(url)
	if err != nil {
		rest.Error(w, "Failed to revoke token for a given user", http.StatusBadRequest)
		return
	}

	// Reset the user's session
	session.Values["accessToken"] = nil
	err = session.Save(req.Request, w.(http.ResponseWriter))
	if err != nil {
		rest.Error(w, "Error saving session", http.StatusBadRequest)
		return
	}
	w.WriteHeader(http.StatusOK)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	fclient "flunky/client"
)

var help bool
var fileDir string

func init() {
	flag.BoolVar(&help, "h", false, "Print help message")
}

func prettyPrint(data string) {
     prettyData := strings.Split(data, ",")
     for _, pretty := range(prettyData){
        fmt.Println(pretty)
     }
     return

}

func main() {
	flag.Parse()

	if help {
	        fmt.Println(fmt.Sprintf("Command syntax -- %s daemon1 daemon2 ...daemonN", os.Args[0]))
		fclient.Usage()
		os.Exit(0)
	}

	if len(os.Args) <= 1 {
		fclient.PrintError("No arguments provided", os.NewError("no args"))
		fmt.Println(fmt.Sprintf("Command syntax -- %s daemon1 daemon2 ...daemonN", os.Args[0]))
		fclient.Usage()
		os.Exit(1)
	} else {
		comm, err := fclient.NewClient()
		if err != nil {
			fclient.PrintError("Failed to setup communication", err)
			os.Exit(1)
		}

		for _, name := range flag.Args() {
			client, err := comm.SetupClient(name)
			if err != nil {
				fclient.PrintError(fmt.Sprintf("Failed to lookup component %s", name), err)
				os.Exit(1)
			}
			resp, err := client.Get("dump")
			if err != nil {
				fclient.PrintError(fmt.Sprintf("Failed to contact component %s", name), err)
			        os.Exit(1)
			}
			//prettyPrint(string(resp))
			fmt.Println(string(resp))
		}
	}
}
<commit_msg>MASTER: Added log lookup ability in comstat.go<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"io/ioutil"
	fclient "flunky/client"
)

var help bool
var fileDir string
var error bool
var log bool

func init() {
	flag.BoolVar(&help, "h", false, "Print help message")
	flag.BoolVar(&error, "e", false, "Print error logs")
	flag.BoolVar(&log, "l", false, "Print log file for specified host")
}

func prettyPrint(data string) {
     prettyData := strings.Split(data, ",")
     for _, pretty := range(prettyData){
        fmt.Println(pretty)
     }
     return

}

func logs(name string) string {
   var errorLog string
   logName := "/var/log/" + name + ".log"
   _,err :=  os.Stat(logName)
   if err != nil{
       fclient.PrintError(err.String(), err)
       os.Exit(1)
   }
   file, err := ioutil.ReadFile(logName)
   if log{
      return string(file)
   }
   if error {
      contents := strings.Split(string(file), "\n")
      for _, data := range(contents){
      	   dex := strings.Index(data, "ERROR")
       	   if dex > 0{
              errorLog = errorLog + data + "\n"
       	    }
       }
   return(errorLog)
   }
   return ""
}

func main() {
	flag.Parse()

	if help {
	        fmt.Println(fmt.Sprintf("Command syntax -- %s daemon1 daemon2 ...daemonN", os.Args[0]))
		fclient.Usage()
		os.Exit(0)
	}

	if len(os.Args) <= 1 {
		fclient.PrintError("No arguments provided", os.NewError("no args"))
		fmt.Println(fmt.Sprintf("Command syntax -- %s daemon1 daemon2 ...daemonN", os.Args[0]))
		fclient.Usage()
		os.Exit(1)
	} else {
	        if log{
		   for _, name := range(flag.Args()){
		       logging := logs(name)
		       fmt.Println(logging)
                   }
		   os.Exit(0)
                 }

                 if error {
		    for _, name := range(flag.Args()){
		        errorLogging := logs(name)
			if len(errorLogging) <=0{
	                     fmt.Println(fmt.Sprintf("No errors exsist in the logs for %s", name))
                        }else{
				fmt.Println(errorLogging)
                        }
                     }
		     os.Exit(0)
                  }

		comm, err := fclient.NewClient()
		if err != nil {
			fclient.PrintError("Failed to setup communication", err)
			os.Exit(1)
		}

		for _, name := range flag.Args() {
			client, err := comm.SetupClient(name)
			if err != nil {
				fclient.PrintError(fmt.Sprintf("Failed to lookup component %s", name), err)
				os.Exit(1)
			}
			resp, err := client.Get("dump")
			if err != nil {
				fclient.PrintError(fmt.Sprintf("Failed to contact component %s", name), err)
			        os.Exit(1)
			}
			//prettyPrint(string(resp))
			fmt.Println(string(resp))
		}
	}
}
<|endoftext|>