<commit_before>package bbs

import (
	"github.com/cloudfoundry/gosteno"
	"github.com/cloudfoundry/gunk/timeprovider"
	"time"

	"github.com/cloudfoundry-incubator/runtime-schema/models"
	"github.com/cloudfoundry/storeadapter"
)

type executorBBS struct {
	store        storeadapter.StoreAdapter
	timeProvider timeprovider.TimeProvider
}

func (self *executorBBS) MaintainExecutorPresence(heartbeatInterval time.Duration, executorId string) (PresenceInterface, <-chan bool, error) {
	presence := NewPresence(self.store, executorSchemaPath(executorId), []byte{})
	lostLock, err := presence.Maintain(heartbeatInterval)
	return presence, lostLock, err
}

func (self *executorBBS) WatchForDesiredRunOnce() (<-chan *models.RunOnce, chan<- bool, <-chan error) {
	return watchForRunOnceModificationsOnState(self.store, models.RunOnceStatePending)
}

// The executor calls this when it wants to claim a runonce
// stagerBBS will retry this repeatedly if it gets a StoreTimeout error (up to N seconds?)
// If this fails, the executor should assume that someone else is handling the claim and should bail
func (self *executorBBS) ClaimRunOnce(runOnce *models.RunOnce, executorID string) error {
	originalValue := runOnce.ToJSON()

	runOnce.UpdatedAt = self.timeProvider.Time().UnixNano()

	runOnce.State = models.RunOnceStateClaimed
	runOnce.ExecutorID = executorID

	return retryIndefinitelyOnStoreTimeout(func() error {
		return self.store.CompareAndSwap(storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: originalValue,
		}, storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: runOnce.ToJSON(),
		})
	})
}

// The executor calls this when it is about to run the runonce in the claimed container
// stagerBBS will retry this repeatedly if it gets a StoreTimeout error (up to N seconds?)
// If this fails, the executor should assume that someone else is running and should clean up and bail
func (self *executorBBS) StartRunOnce(runOnce *models.RunOnce, containerHandle string) error {
	originalValue := runOnce.ToJSON()

	runOnce.UpdatedAt = self.timeProvider.Time().UnixNano()

	runOnce.State = models.RunOnceStateRunning
	runOnce.ContainerHandle = containerHandle

	return retryIndefinitelyOnStoreTimeout(func() error {
		return self.store.CompareAndSwap(storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: originalValue,
		}, storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: runOnce.ToJSON(),
		})
	})
}

// The executor calls this when it has finished running the runonce (be it success or failure)
// stagerBBS will retry this repeatedly if it gets a StoreTimeout error (up to N seconds?)
// This really really shouldn't fail.  If it does, blog about it and walk away. If it failed in a
// consistent way (i.e. key already exists), there's probably a flaw in our design.
func (self *executorBBS) CompleteRunOnce(runOnce *models.RunOnce, failed bool, failureReason string, result string) error {
	originalValue := runOnce.ToJSON()

	runOnce.UpdatedAt = self.timeProvider.Time().UnixNano()

	runOnce.State = models.RunOnceStateCompleted
	runOnce.Failed = failed
	runOnce.FailureReason = failureReason
	runOnce.Result = result

	return retryIndefinitelyOnStoreTimeout(func() error {
		return self.store.CompareAndSwap(storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: originalValue,
		}, storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: runOnce.ToJSON(),
		})
	})
}

// ConvergeRunOnce is run by *one* executor every X seconds (doesn't really matter what X is.. pick something performant)
// Converge will:
// 1. Kick (by setting) any run-onces that are still pending
// 2. Kick (by setting) any run-onces that are completed
// 3. Demote to pending any claimed run-onces that have been claimed for > 30s
// 4. Demote to completed any resolving run-onces that have been resolving for > 30s
// 5. Mark as failed any run-onces that have been in the pending state for > timeToClaim
// 6. Mark as failed any claimed or running run-onces whose executor has stopped maintaining presence
func (self *executorBBS) ConvergeRunOnce(timeToClaim time.Duration) {
	runOnceState, err := self.store.ListRecursively(RunOnceSchemaRoot)
	if err != nil {
		return
	}

	executorState, err := self.store.ListRecursively(ExecutorSchemaRoot)
	if err == storeadapter.ErrorKeyNotFound {
		executorState = storeadapter.StoreNode{}
	} else if err != nil {
		return
	}

	logger := gosteno.NewLogger("bbs")
	logError := func(runOnce models.RunOnce, message string) {
		logger.Errord(map[string]interface{}{
			"runonce": runOnce,
		}, message)
	}

	runOncesToSet := []models.RunOnce{}
	keysToDelete := []string{}
	unclaimedTimeoutBoundary := self.timeProvider.Time().Add(-timeToClaim).UnixNano()

	for _, node := range runOnceState.ChildNodes {
		runOnce, err := models.NewRunOnceFromJSON(node.Value)
		if err != nil {
			logger.Errord(map[string]interface{}{
				"key":   node.Key,
				"value": string(node.Value),
			}, "runonce.converge.json-parse-failure")
			keysToDelete = append(keysToDelete, node.Key)
			continue
		}

		switch runOnce.State {
		case models.RunOnceStatePending:
			if runOnce.CreatedAt <= unclaimedTimeoutBoundary {
				logError(runOnce, "runonce.converge.failed-to-claim")
				runOnce = markRunOnceFailed(runOnce, "not claimed within time limit")
			}
			runOncesToSet = append(runOncesToSet, runOnce)
		case models.RunOnceStateClaimed:
			claimedTooLong := self.timeProvider.Time().Sub(time.Unix(0, runOnce.UpdatedAt)) >= 30*time.Second
			_, executorIsAlive := executorState.Lookup(runOnce.ExecutorID)

			if !executorIsAlive {
				logError(runOnce, "runonce.converge.executor-disappeared")
				runOncesToSet = append(runOncesToSet, markRunOnceFailed(runOnce, "executor disappeared before completion"))
			} else if claimedTooLong {
				logError(runOnce, "runonce.converge.failed-to-start")
				runOncesToSet = append(runOncesToSet, demoteToPending(runOnce))
			}
		case models.RunOnceStateRunning:
			_, executorIsAlive := executorState.Lookup(runOnce.ExecutorID)

			if !executorIsAlive {
				logError(runOnce, "runonce.converge.executor-disappeared")
				runOncesToSet = append(runOncesToSet, markRunOnceFailed(runOnce, "executor disappeared before completion"))
			}
		case models.RunOnceStateCompleted:
			runOncesToSet = append(runOncesToSet, runOnce)
		case models.RunOnceStateResolving:
			resolvingTooLong := self.timeProvider.Time().Sub(time.Unix(0, runOnce.UpdatedAt)) >= 30*time.Second

			if resolvingTooLong {
				logError(runOnce, "runonce.converge.failed-to-resolve")
				runOncesToSet = append(runOncesToSet, demoteToCompleted(runOnce))
			}
		}
	}

	storeNodesToSet := make([]storeadapter.StoreNode, len(runOncesToSet))
	for i, runOnce := range runOncesToSet {
		runOnce.UpdatedAt = self.timeProvider.Time().UnixNano()
		storeNodesToSet[i] = storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: runOnce.ToJSON(),
		}
	}

	self.store.SetMulti(storeNodesToSet)
	self.store.Delete(keysToDelete...)
}

func markRunOnceFailed(runOnce models.RunOnce, reason string) models.RunOnce {
	runOnce.State = models.RunOnceStateCompleted
	runOnce.Failed = true
	runOnce.FailureReason = reason
	return runOnce
}

func demoteToPending(runOnce models.RunOnce) models.RunOnce {
	runOnce.State = models.RunOnceStatePending
	runOnce.ExecutorID = ""
	runOnce.ContainerHandle = ""
	return runOnce
}

func demoteToCompleted(runOnce models.RunOnce) models.RunOnce {
	runOnce.State = models.RunOnceStateCompleted
	return runOnce
}

func (self *executorBBS) MaintainConvergeLock(interval time.Duration, executorID string) (<-chan bool, chan<- chan bool, error) {
	return self.store.MaintainNode(storeadapter.StoreNode{
		Key:   runOnceSchemaPath("converge_lock"),
		Value: []byte(executorID),
		TTL:   uint64(interval.Seconds()),
	})
}
<commit_msg>converge uses CAS instead of set to plug up any potential holes....<commit_after>package bbs

import (
	"github.com/cloudfoundry/gosteno"
	"github.com/cloudfoundry/gunk/timeprovider"
	"time"

	"github.com/cloudfoundry-incubator/runtime-schema/models"
	"github.com/cloudfoundry/storeadapter"
)

type executorBBS struct {
	store        storeadapter.StoreAdapter
	timeProvider timeprovider.TimeProvider
}

func (self *executorBBS) MaintainExecutorPresence(heartbeatInterval time.Duration, executorId string) (PresenceInterface, <-chan bool, error) {
	presence := NewPresence(self.store, executorSchemaPath(executorId), []byte{})
	lostLock, err := presence.Maintain(heartbeatInterval)
	return presence, lostLock, err
}

func (self *executorBBS) WatchForDesiredRunOnce() (<-chan *models.RunOnce, chan<- bool, <-chan error) {
	return watchForRunOnceModificationsOnState(self.store, models.RunOnceStatePending)
}

// The executor calls this when it wants to claim a runonce
// stagerBBS will retry this repeatedly if it gets a StoreTimeout error (up to N seconds?)
// If this fails, the executor should assume that someone else is handling the claim and should bail
func (self *executorBBS) ClaimRunOnce(runOnce *models.RunOnce, executorID string) error {
	originalValue := runOnce.ToJSON()

	runOnce.UpdatedAt = self.timeProvider.Time().UnixNano()

	runOnce.State = models.RunOnceStateClaimed
	runOnce.ExecutorID = executorID

	return retryIndefinitelyOnStoreTimeout(func() error {
		return self.store.CompareAndSwap(storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: originalValue,
		}, storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: runOnce.ToJSON(),
		})
	})
}

// The executor calls this when it is about to run the runonce in the claimed container
// stagerBBS will retry this repeatedly if it gets a StoreTimeout error (up to N seconds?)
// If this fails, the executor should assume that someone else is running and should clean up and bail
func (self *executorBBS) StartRunOnce(runOnce *models.RunOnce, containerHandle string) error {
	originalValue := runOnce.ToJSON()

	runOnce.UpdatedAt = self.timeProvider.Time().UnixNano()

	runOnce.State = models.RunOnceStateRunning
	runOnce.ContainerHandle = containerHandle

	return retryIndefinitelyOnStoreTimeout(func() error {
		return self.store.CompareAndSwap(storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: originalValue,
		}, storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: runOnce.ToJSON(),
		})
	})
}

// The executor calls this when it has finished running the runonce (be it success or failure)
// stagerBBS will retry this repeatedly if it gets a StoreTimeout error (up to N seconds?)
// This really really shouldn't fail.  If it does, blog about it and walk away. If it failed in a
// consistent way (i.e. key already exists), there's probably a flaw in our design.
func (self *executorBBS) CompleteRunOnce(runOnce *models.RunOnce, failed bool, failureReason string, result string) error {
	originalValue := runOnce.ToJSON()

	runOnce.UpdatedAt = self.timeProvider.Time().UnixNano()

	runOnce.State = models.RunOnceStateCompleted
	runOnce.Failed = failed
	runOnce.FailureReason = failureReason
	runOnce.Result = result

	return retryIndefinitelyOnStoreTimeout(func() error {
		return self.store.CompareAndSwap(storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: originalValue,
		}, storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOnce.Guid),
			Value: runOnce.ToJSON(),
		})
	})
}

// ConvergeRunOnce is run by *one* executor every X seconds (doesn't really matter what X is.. pick something performant)
// Converge will:
// 1. Kick (by setting) any run-onces that are still pending
// 2. Kick (by setting) any run-onces that are completed
// 3. Demote to pending any claimed run-onces that have been claimed for > 30s
// 4. Demote to completed any resolving run-onces that have been resolving for > 30s
// 5. Mark as failed any run-onces that have been in the pending state for > timeToClaim
// 6. Mark as failed any claimed or running run-onces whose executor has stopped maintaining presence
func (self *executorBBS) ConvergeRunOnce(timeToClaim time.Duration) {
	runOnceState, err := self.store.ListRecursively(RunOnceSchemaRoot)
	if err != nil {
		return
	}

	executorState, err := self.store.ListRecursively(ExecutorSchemaRoot)
	if err == storeadapter.ErrorKeyNotFound {
		executorState = storeadapter.StoreNode{}
	} else if err != nil {
		return
	}

	logger := gosteno.NewLogger("bbs")
	logError := func(runOnce models.RunOnce, message string) {
		logger.Errord(map[string]interface{}{
			"runonce": runOnce,
		}, message)
	}

	keysToDelete := []string{}
	unclaimedTimeoutBoundary := self.timeProvider.Time().Add(-timeToClaim).UnixNano()

	runOncesToCAS := [][]models.RunOnce{}
	scheduleForCAS := func(oldRunOnce, newRunOnce models.RunOnce) {
		runOncesToCAS = append(runOncesToCAS, []models.RunOnce{
			oldRunOnce,
			newRunOnce,
		})
	}

	for _, node := range runOnceState.ChildNodes {
		runOnce, err := models.NewRunOnceFromJSON(node.Value)
		if err != nil {
			logger.Errord(map[string]interface{}{
				"key":   node.Key,
				"value": string(node.Value),
			}, "runonce.converge.json-parse-failure")
			keysToDelete = append(keysToDelete, node.Key)
			continue
		}

		switch runOnce.State {
		case models.RunOnceStatePending:
			if runOnce.CreatedAt <= unclaimedTimeoutBoundary {
				logError(runOnce, "runonce.converge.failed-to-claim")
				scheduleForCAS(runOnce, markRunOnceFailed(runOnce, "not claimed within time limit"))
			} else {
				scheduleForCAS(runOnce, runOnce)
			}
		case models.RunOnceStateClaimed:
			claimedTooLong := self.timeProvider.Time().Sub(time.Unix(0, runOnce.UpdatedAt)) >= 30*time.Second
			_, executorIsAlive := executorState.Lookup(runOnce.ExecutorID)

			if !executorIsAlive {
				logError(runOnce, "runonce.converge.executor-disappeared")
				scheduleForCAS(runOnce, markRunOnceFailed(runOnce, "executor disappeared before completion"))
			} else if claimedTooLong {
				logError(runOnce, "runonce.converge.failed-to-start")
				scheduleForCAS(runOnce, demoteToPending(runOnce))
			}
		case models.RunOnceStateRunning:
			_, executorIsAlive := executorState.Lookup(runOnce.ExecutorID)

			if !executorIsAlive {
				logError(runOnce, "runonce.converge.executor-disappeared")
				scheduleForCAS(runOnce, markRunOnceFailed(runOnce, "executor disappeared before completion"))
			}
		case models.RunOnceStateCompleted:
			scheduleForCAS(runOnce, runOnce)
		case models.RunOnceStateResolving:
			resolvingTooLong := self.timeProvider.Time().Sub(time.Unix(0, runOnce.UpdatedAt)) >= 30*time.Second

			if resolvingTooLong {
				logError(runOnce, "runonce.converge.failed-to-resolve")
				scheduleForCAS(runOnce, demoteToCompleted(runOnce))
			}
		}
	}

	self.batchCompareAndSwapRunOnces(runOncesToCAS, logger)
	self.store.Delete(keysToDelete...)
}

func (self *executorBBS) batchCompareAndSwapRunOnces(runOncesToCAS [][]models.RunOnce, logger *gosteno.Logger) {
	done := make(chan struct{}, len(runOncesToCAS))

	for _, runOncePair := range runOncesToCAS {
		originalStoreNode := storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOncePair[0].Guid),
			Value: runOncePair[0].ToJSON(),
		}

		runOncePair[1].UpdatedAt = self.timeProvider.Time().UnixNano()
		newStoreNode := storeadapter.StoreNode{
			Key:   runOnceSchemaPath(runOncePair[1].Guid),
			Value: runOncePair[1].ToJSON(),
		}

		go func() {
			err := self.store.CompareAndSwap(originalStoreNode, newStoreNode)
			if err != nil {
				logger.Errord(map[string]interface{}{
					"error": err.Error(),
				}, "runonce.converge.failed-to-compare-and-swap")
			}
			done <- struct{}{}
		}()
	}

	for _ = range runOncesToCAS {
		<-done
	}
}

func markRunOnceFailed(runOnce models.RunOnce, reason string) models.RunOnce {
	runOnce.State = models.RunOnceStateCompleted
	runOnce.Failed = true
	runOnce.FailureReason = reason
	return runOnce
}

func demoteToPending(runOnce models.RunOnce) models.RunOnce {
	runOnce.State = models.RunOnceStatePending
	runOnce.ExecutorID = ""
	runOnce.ContainerHandle = ""
	return runOnce
}

func demoteToCompleted(runOnce models.RunOnce) models.RunOnce {
	runOnce.State = models.RunOnceStateCompleted
	return runOnce
}

func (self *executorBBS) MaintainConvergeLock(interval time.Duration, executorID string) (<-chan bool, chan<- chan bool, error) {
	return self.store.MaintainNode(storeadapter.StoreNode{
		Key:   runOnceSchemaPath("converge_lock"),
		Value: []byte(executorID),
		TTL:   uint64(interval.Seconds()),
	})
}
<|endoftext|>


<commit_before>/*
** Observer.go
** Author: Marin Alcaraz
** Mail   <marin.alcaraz@gmail.com>
** Started on  Mon Feb 09 14:36:00 2015 Marin Alcaraz
** Last update Thu Feb 12 14:16:31 2015 Marin Alcaraz
 */

package UDPush

import (
	"fmt"
	"net"
)

// Constants

// MAX NUMBER PER WATCHER ENGINE

const maxClients = 10

type update struct {
	status  bool
	ownerID int
}

// NotificationEngine interface for the notification system
// Defines the requirements to create a gobox
type NotificationEngine interface {
	Initialize(id string)
	Attach(Watcher) error
	Detach(Watcher) bool
	Notify()
}

// WatcherEngine Interface for watcher (Observer) system
// Defines the requirements to create a gobox
// notification watcher.
type WatcherEngine interface {
	Update()
}

//Pusher struct that satisfies the NotificationEngine interface
type Pusher struct {
	ServerID string
	BindedTo uint
	Watchers map[int]*Watcher
	Pending  bool
}

// Watcher Struct that satisfies the WatcherEngine
// This type requires an auth mecanism in order
// to work in a safe way
type Watcher struct {
	OwnerID    int
	ClientID   int
	SessionKey int
	Action     bool
}

// Methods for struct to satisfy the notificationEngine interface

//Initialize is a 'constructor' for the pusher struct
func (e *Pusher) Initialize(id string) {
	e.ServerID = id
	e.Watchers = make(map[int]*Watcher, maxClients)
}

//Attach Add a new Watcher to the notification slice
func (e *Pusher) Attach(w *Watcher) (err error) {
	//Check if Watchers is full
	if len(e.Watchers) == maxClients {
		return fmt.Errorf("[!] Error: Not enough space for new client")
	}
	//Check if element already exists
	if e.Watchers[w.ClientID] != nil {
		return fmt.Errorf("[!] Warning: client already monitored, skipping addition")
	}
	e.Watchers[w.ClientID] = w
	return nil
}

//Detach Remove a watcher from the notification slice
func (e *Pusher) Detach(w Watcher) (err error) {
	//Check if element already exists
	if e.Watchers[w.ClientID] != nil {
		e.Watchers[w.ClientID] = nil
		return nil
	}
	return fmt.Errorf("[!] Error: client doesn't exist")
}

//Notify Tell the watcher {clientID} to update
func (e *Pusher) Notify(owner int) {
	for _, k := range e.Watchers {
		//Is there a better way to do this? Dictionary and list inside?
		if k.OwnerID == owner {
			k.Action = true
			k.Update()
		}
	}
}

//Utilities for pusher

//ShowWatchers Print current watchers in pusher
func (e *Pusher) ShowWatchers() {
	fmt.Printf("Current watchers in %s:\n", e.ServerID)
	for _, k := range e.Watchers {
		fmt.Println("Watcher: ", k)
	}
}

// Methods for satisfiying the interface

// Update Get update from pusher... Golint forces me to do this
// http://tinyurl.com/lhzjvmm
func (w *Watcher) Update() {
	w.Action = true
}

//Network related methods

func getPendingUpdates() update {
	return update{status: true,
		ownerID: 1}
}

//HandleConnection keeps alive the UDP notification service between
//client and server
func handleConnection(conn net.Conn) error {
	for {
		//Check if there is something to update...
		//TODO: This function needs pairing
		out := getPendingUpdates()
		if out.status {
			//Write to client

			//Create an slice of bytes to contain the ownerID
			//Since we can only send []bytes we must to this
			notification := make([]byte, 1)
			notification[0] = byte(out.ownerID)

			//Send the notification and check the error
			_, err := conn.Write(notification)
			if err != nil {
				return fmt.Errorf("Error handleConnection: %s", err)
			}
		}
	}
	return nil
}

//InitUDPush 'constructs' the UDP notification engine
//The e on the reciever stands for event
func (e *Pusher) InitUDPush() error {
	connectionString := fmt.Sprintf("%s:%s", e.ServerID, e.BindedTo)
	ln, err := net.Listen("tcp", connectionString)
	if err != nil {
		return fmt.Errorf("Error at initUDPush: %s", err)
	}
	for {
		conn, err := ln.Accept()
		defer conn.Close()
		fmt.Println("Host connected: ", ln.Addr())
		if err != nil {
			return fmt.Errorf("Error at initUDPush: %s", err)
		}
		go handleConnection(conn)
	}
}
<commit_msg>bug fix<commit_after>/*
** Observer.go
** Author: Marin Alcaraz
** Mail   <marin.alcaraz@gmail.com>
** Started on  Mon Feb 09 14:36:00 2015 Marin Alcaraz
** Last update Tue Feb 17 16:50:50 2015 Marin Alcaraz
 */

package UDPush

import (
	"fmt"
	"net"
)

// Constants

// MAX NUMBER PER WATCHER ENGINE

const maxClients = 10

type update struct {
	status  bool
	ownerID int
}

// NotificationEngine interface for the notification system
// Defines the requirements to create a gobox
type NotificationEngine interface {
	Initialize(id string)
	Attach(Watcher) error
	Detach(Watcher) bool
	Notify()
}

// WatcherEngine Interface for watcher (Observer) system
// Defines the requirements to create a gobox
// notification watcher.
type WatcherEngine interface {
	Update()
}

//Pusher struct that satisfies the NotificationEngine interface
type Pusher struct {
	ServerID string
	BindedTo uint
	Watchers map[int]*Watcher
	Pending  bool
}

// Watcher Struct that satisfies the WatcherEngine
// This type requires an auth mecanism in order
// to work in a safe way
type Watcher struct {
	OwnerID    int
	ClientID   int
	SessionKey int
	Action     bool
}

// Methods for struct to satisfy the notificationEngine interface

//Initialize is a 'constructor' for the pusher struct
func (e *Pusher) Initialize(id string) {
	e.ServerID = id
	e.Watchers = make(map[int]*Watcher, maxClients)
}

//Attach Add a new Watcher to the notification slice
func (e *Pusher) Attach(w *Watcher) (err error) {
	//Check if Watchers is full
	if len(e.Watchers) == maxClients {
		return fmt.Errorf("[!] Error: Not enough space for new client")
	}
	//Check if element already exists
	if e.Watchers[w.ClientID] != nil {
		return fmt.Errorf("[!] Warning: client already monitored, skipping addition")
	}
	e.Watchers[w.ClientID] = w
	return nil
}

//Detach Remove a watcher from the notification slice
func (e *Pusher) Detach(w Watcher) (err error) {
	//Check if element already exists
	if e.Watchers[w.ClientID] != nil {
		e.Watchers[w.ClientID] = nil
		return nil
	}
	return fmt.Errorf("[!] Error: client doesn't exist")
}

//Notify Tell the watcher {clientID} to update
func (e *Pusher) Notify(owner int) {
	for _, k := range e.Watchers {
		//Is there a better way to do this? Dictionary and list inside?
		if k.OwnerID == owner {
			k.Action = true
			k.Update()
		}
	}
}

//Utilities for pusher

//ShowWatchers Print current watchers in pusher
func (e *Pusher) ShowWatchers() {
	fmt.Printf("Current watchers in %s:\n", e.ServerID)
	for _, k := range e.Watchers {
		fmt.Println("Watcher: ", k)
	}
}

// Methods for satisfiying the interface

// Update Get update from pusher... Golint forces me to do this
// http://tinyurl.com/lhzjvmm
func (w *Watcher) Update() {
	w.Action = true
}

//Network related methods

func getPendingUpdates() update {
	return update{status: true,
		ownerID: 1}
}

//HandleConnection keeps alive the UDP notification service between
//client and server
func handleConnection(conn net.Conn) error {
	for {
		//Check if there is something to update...
		//TODO: This function needs pairing
		out := getPendingUpdates()
		if out.status {
			//Write to client

			//Create an slice of bytes to contain the ownerID
			//Since we can only send []bytes we must to this
			notification := make([]byte, 1)
			notification[0] = byte(out.ownerID)

			//Send the notification and check the error
			_, err := conn.Write(notification)
			if err != nil {
				return fmt.Errorf("Error handleConnection: %s", err)
			}
		}
	}
	return nil
}

//InitUDPush 'constructs' the UDP notification engine
//The e on the reciever stands for event
func (e *Pusher) InitUDPush() error {
	connectionString := fmt.Sprintf("%s:%d", e.ServerID, e.BindedTo)
	ln, err := net.Listen("tcp", connectionString)
	if err != nil {
		return fmt.Errorf("Error at initUDPush: %s", err)
	}
	fmt.Println("[+] UDP Listening on:", connectionString)
	for {
		conn, err := ln.Accept()
		defer conn.Close()
		fmt.Println("Host connected: ", ln.Addr())
		if err != nil {
			return fmt.Errorf("Error at initUDPush: %s", err)
		}
		go handleConnection(conn)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Circonus, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package checkmgr

import (
	"github.com/circonus-labs/circonus-gometrics/api"
)

// IsMetricActive checks whether a given metric name is currently active(enabled)
func (cm *CheckManager) IsMetricActive(name string) bool {
	active, _ := cm.availableMetrics[name]
	return active
}

// ActivateMetric determines if a given metric should be activated
func (cm *CheckManager) ActivateMetric(name string) bool {
	active, exists := cm.availableMetrics[name]

	if !exists {
		return true
	}

	if !active && cm.forceMetricActivation {
		return true
	}

	return false
}

// AddNewMetrics updates a check bundle with new metrics
func (cm *CheckManager) AddNewMetrics(newMetrics map[string]*api.CheckBundleMetric) {
	// only if check manager is enabled
	if !cm.enabled {
		return
	}

	// only if checkBundle has been populated
	if cm.checkBundle == nil {
		return
	}

	newCheckBundle := cm.checkBundle
	numCurrMetrics := len(newCheckBundle.Metrics)
	numNewMetrics := len(newMetrics)

	if numCurrMetrics+numNewMetrics >= cap(newCheckBundle.Metrics) {
		nm := make([]api.CheckBundleMetric, numCurrMetrics+numNewMetrics)
		copy(nm, newCheckBundle.Metrics)
		newCheckBundle.Metrics = nm
	}

	newCheckBundle.Metrics = newCheckBundle.Metrics[0 : numCurrMetrics+numNewMetrics]

	i := 0
	for _, metric := range newMetrics {
		newCheckBundle.Metrics[numCurrMetrics+i] = *metric
		i++
	}

	checkBundle, err := cm.apih.UpdateCheckBundle(newCheckBundle)
	if err != nil {
		cm.Log.Printf("[ERROR] updating check bundle with new metrics %v", err)
		return
	}

	cm.checkBundle = checkBundle
	cm.inventoryMetrics()
}

// inventoryMetrics creates list of active metrics in check bundle
func (cm *CheckManager) inventoryMetrics() {
	availableMetrics := make(map[string]bool)
	for _, metric := range cm.checkBundle.Metrics {
		availableMetrics[metric.Name] = metric.Status == "active"
	}
	cm.availableMetrics = availableMetrics
}
<commit_msg>new: add support for metric tagging<commit_after>// Copyright 2016 Circonus, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package checkmgr

import (
	"github.com/circonus-labs/circonus-gometrics/api"
)

// IsMetricActive checks whether a given metric name is currently active(enabled)
func (cm *CheckManager) IsMetricActive(name string) bool {
	active, _ := cm.availableMetrics[name]
	return active
}

// ActivateMetric determines if a given metric should be activated
func (cm *CheckManager) ActivateMetric(name string) bool {
	active, exists := cm.availableMetrics[name]

	if !exists {
		return true
	}

	if !active && cm.forceMetricActivation {
		return true
	}

	return false
}

// AddMetricTags updates check bundle metrics with tags
func (cm *CheckManager) AddMetricTags(metricName string, tags []string, appendTags bool) bool {
	tagsUpdated := false

	if len(tags) == 0 {
		return tagsUpdated
	}

	metricFound := false

	for metricIdx, metric := range cm.checkBundle.Metrics {
		if metric.Name == metricName {
			metricFound = true
			numNewTags := countNewTags(metric.Tags, tags)

			if numNewTags == 0 {
				if appendTags {
					break // no new tags to add
				} else if len(metric.Tags) == len(tags) {
					break // no new tags and old/new same length
				}
			}

			cm.cbmu.Lock()

			if appendTags {
				metric.Tags = append(metric.Tags, tags...)
			} else {
				metric.Tags = tags
			}

			cm.checkBundle.Metrics[metricIdx] = metric
			tagsUpdated = true

			cm.cbmu.Unlock()
		}
	}

	if tagsUpdated {
		if cm.Debug {
			action := "Set"
			if appendTags {
				action = "Added"
			}
			cm.Log.Printf("[DEBUG] %s metric tag(s) %s %v\n", action, metricName, tags)
		}
		cm.cbmu.Lock()
		cm.forceCheckUpdate = true
		cm.cbmu.Unlock()
	} else {
		if !metricFound {
			if _, exists := cm.metricTags[metricName]; !exists {
				if cm.Debug {
					cm.Log.Printf("[DEBUG] Queing metric tag(s) %s %v\n", metricName, tags)
				}
				// queue the tags, the metric is new (e.g. not in the check yet)
				cm.mtmu.Lock()
				cm.metricTags[metricName] = append(cm.metricTags[metricName], tags...)
				cm.mtmu.Unlock()
			}
		}
	}

	return tagsUpdated
}

// addNewMetrics updates a check bundle with new metrics
func (cm *CheckManager) addNewMetrics(newMetrics map[string]*api.CheckBundleMetric) bool {
	updatedCheckBundle := false

	if cm.checkBundle == nil || len(newMetrics) == 0 {
		return updatedCheckBundle
	}

	cm.cbmu.Lock()

	numCurrMetrics := len(cm.checkBundle.Metrics)
	numNewMetrics := len(newMetrics)

	if numCurrMetrics+numNewMetrics >= cap(cm.checkBundle.Metrics) {
		nm := make([]api.CheckBundleMetric, numCurrMetrics+numNewMetrics)
		copy(nm, cm.checkBundle.Metrics)
		cm.checkBundle.Metrics = nm
	}

	cm.checkBundle.Metrics = cm.checkBundle.Metrics[0 : numCurrMetrics+numNewMetrics]

	i := 0
	for _, metric := range newMetrics {
		cm.checkBundle.Metrics[numCurrMetrics+i] = *metric
		i++
		updatedCheckBundle = true
	}

	if updatedCheckBundle {
		cm.forceCheckUpdate = true
	}

	cm.cbmu.Unlock()

	return updatedCheckBundle
}

// inventoryMetrics creates list of active metrics in check bundle
func (cm *CheckManager) inventoryMetrics() {
	availableMetrics := make(map[string]bool)
	for _, metric := range cm.checkBundle.Metrics {
		availableMetrics[metric.Name] = metric.Status == "active"
	}
	cm.availableMetrics = availableMetrics
}

// countNewTags returns a count of new tags which do not exist in the current list of tags
func countNewTags(currTags []string, newTags []string) int {
	if len(newTags) == 0 {
		return 0
	}

	if len(currTags) == 0 {
		return len(newTags)
	}

	newTagCount := 0

	for _, newTag := range newTags {
		found := false
		for _, currTag := range currTags {
			if newTag == currTag {
				found = true
				break
			}
		}
		if !found {
			newTagCount++
		}
	}

	return newTagCount
}
<|endoftext|>


<commit_before>// Copyright © 2019 The OpenEBS Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package exporter

import (
	"encoding/json"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	apis "github.com/openebs/maya/pkg/apis/openebs.io/v1alpha1"
	csp "github.com/openebs/maya/pkg/cstorpool/v1alpha3"
	cv "github.com/openebs/maya/pkg/cstorvolume/v1alpha1"
	pvc "github.com/openebs/maya/pkg/kubernetes/persistentvolumeclaim/v1alpha1"
	sc "github.com/openebs/maya/pkg/kubernetes/storageclass/v1alpha1"
	spc "github.com/openebs/maya/pkg/storagepoolclaim/v1alpha1"
	"github.com/openebs/maya/tests"
	framework "github.com/openebs/maya/tests/framework/v1alpha1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
)

var _ = Describe("Test maya-exporter [single-pool-pod]", func() {
	var (
		err error
		pod *corev1.PodList
	)
	BeforeEach(func() {
		When("we are creating pool deployment", func() {
			By("building object of storageclass")
			scObj, err = sc.NewBuilder().
				WithName(scName).
				WithAnnotations(annotations).
				WithProvisioner(openebsProvisioner).Build()
			Expect(err).ShouldNot(HaveOccurred(), "while building storageclass obj for storageclass {%s}", scName)

			By("creating storageclass")
			_, err = ops.SCClient.Create(scObj)
			Expect(err).To(BeNil(), "while creating storageclass", scName)

			By("building spc object")
			spcObj = spc.NewBuilder().
				WithName(spcName).
				WithDiskType(string(apis.TypeSparseCPV)).
				WithMaxPool(1).
				WithOverProvisioning(false).
				WithPoolType(string(apis.PoolTypeStripedCPV)).
				Build().Object

			By("creating storagepoolclaim")
			_, err = ops.SPCClient.Create(spcObj)
			Expect(err).To(BeNil(), "while creating spc", spcName)

			By("verifying healthy csp count")
			Eventually(func() int {
				cspAPIList, err = ops.CSPClient.List(metav1.ListOptions{})
				Expect(err).To(BeNil())
				count := csp.
					ListBuilderForAPIObject(cspAPIList).
					List().
					Filter(csp.HasLabel(string(apis.StoragePoolClaimCPK), spcName), csp.IsStatus("Healthy")).Len()
				return count
			},
				framework.DefaultTimeOut, framework.DefaultPollingInterval).
				Should(Equal(1), "while getting healthy csp count")

			By("listing cstor pool pods")
			selector := map[string]string{
				string(apis.StoragePoolClaimCPK): spcName,
				"app": "cstor-pool",
			}

			ls := labels.Set(selector).
				AsSelector().
				String()
			pod, err = ops.PodClient.List(metav1.ListOptions{
				LabelSelector: ls,
			})

			Expect(err).To(BeNil(), "while listing pool pods with selector ", ls)

			By("verifying pod items")
			Expect(len(pod.Items)).To(Equal(1), "while getting pod items length", pod)

			By("verifying no of containers in pool pod")
			Expect(len(pod.Items[0].Spec.Containers)).To(Equal(3), "while getting no of containers", pod)

			By("verifying whether maya-exporter container exists")
			Expect(pod.Items[0].Spec.Containers[2].Name).To(Equal("maya-exporter"), "while verifying container name", pod)

		})
	})

	AfterEach(func() {
		When("we are deleting resources created for testing maya-exporter", func() {
			By("getting the pvclaim name")
			pvcObj, err = pvc.
				NewKubeClient(pvc.WithKubeConfigPath(kubeConfigPath)).
				WithNamespace(nsName).
				Get(pvcName, metav1.GetOptions{})
			Expect(err).ShouldNot(HaveOccurred())
			Expect(pvcObj.Spec.VolumeName).ShouldNot(BeEmpty())

			By("deleting pvc")
			err = pvc.
				NewKubeClient(pvc.WithKubeConfigPath(kubeConfigPath)).
				WithNamespace(nsName).
				Delete(pvcName, new(metav1.DeleteOptions))
			Expect(err).ShouldNot(HaveOccurred())

			By("listing pvc to verify if it is deleted")
			Eventually(func() int {
				pvcs, err = pvc.
					NewKubeClient(pvc.WithKubeConfigPath(kubeConfigPath)).
					WithNamespace(nsName).
					List(metav1.ListOptions{LabelSelector: "name=exporter-volume"})
				Expect(err).ShouldNot(HaveOccurred())
				return len(pvcs.Items)
			},
				framework.DefaultTimeOut, framework.DefaultPollingInterval).
				Should(Equal(0), "while listing pvc")

			CstorVolumeLabel := "openebs.io/persistent-volume=" + pvcObj.Spec.VolumeName

			By("verifying if cv is deleted")
			// verify deletion of cstorvolume
			Eventually(func() int {
				cvs, err = cv.
					NewKubeclient(cv.WithNamespace("openebs"), cv.WithKubeConfigPath(kubeConfigPath)).
					List(metav1.ListOptions{LabelSelector: CstorVolumeLabel})
				Expect(err).ShouldNot(HaveOccurred())
				return len(cvs.Items)
			},
				framework.DefaultTimeOut, framework.DefaultPollingInterval).
				Should(Equal(0), "while listing cvs")

			By("deleting storageclass")
			err = ops.SCClient.Delete(scName, &metav1.DeleteOptions{})
			Expect(err).To(BeNil(), "while deleting storageclass", scName)

			By("listing spc")
			spcList, err := ops.SPCClient.List(metav1.ListOptions{})
			Expect(err).To(BeNil(), "while listing spc clients", spcList)

			By("deleting spc")
			for _, spc := range spcList.Items {
				_, err = ops.SPCClient.Delete(spc.Name, &metav1.DeleteOptions{})
				Expect(err).To(BeNil(), "while deleting the spc's", spc)
			}
		})
	})

	Context("Test maya-exporter's response", func() {
		It("should show pool status and volume as online (1) and no errors", func() {
			By("sending get request to maya-exporter without pvc")
			curl := "curl localhost:9500/metrics/?format=json"
			cmd := []string{"/bin/bash", "-c", curl}
			opts := tests.NewOptions().
				WithPodName(pod.Items[0].Name).
				WithNamespace(pod.Items[0].Namespace).
				WithContainer(pod.Items[0].Spec.Containers[2].Name).
				WithCommand(cmd...)

			out, err := ops.ExecPod(opts)

			Expect(err).To(BeNil(), "while executing command in container ", cmd)

			By("unmarshalling pool metrics")
			stats := apis.PoolMetricsList{}
			err = json.Unmarshal(out, &stats)
			Expect(err).To(BeNil(), "while unmarshalling metrics", string(out))

			mapResp := stats.ToMap()

			By("verifying whether pool status is online")
			Expect(apis.GetValue("openebs_pool_status", mapResp)).To(Equal(float64(1)), "while getting pool status of", pod.Items[0].Name)

			By("verifying whether there is no error")
			Expect(apis.GetValue("openebs_no_pool_available_error", mapResp)).To(Equal(float64(0)), "while getting total no of no pool available errors", pod.Items[0].Name, mapResp)

			By("building pvc object")
			pvcObj, err = pvc.NewBuilder().
				WithName(pvcName).
				WithNamespace(nsName).
				WithStorageClass(scName).
				WithAccessModes([]corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}).
				WithCapacity("1G").
				Build()
			Expect(err).To(BeNil(), "while creating pvc", pvcName)

			By("creating pvc")
			_, err = ops.PVCClient.WithNamespace(nsName).Create(pvcObj)
			Expect(err).To(BeNil(), "while creating pvc", pvcName)

			By("verifying pvc to be created and bound with pv")
			Eventually(
				func() bool {
					return ops.IsPVCBound(pvcName)
				},
				framework.DefaultTimeOut, framework.DefaultPollingInterval).
				Should(BeTrue())

			Eventually(
				func() bool {
					By("getting the pvclaim name")
					pvcObj, err = pvc.
						NewKubeClient(pvc.WithKubeConfigPath(kubeConfigPath)).
						WithNamespace(nsName).
						Get(pvcName, metav1.GetOptions{})
					Expect(err).ShouldNot(HaveOccurred())
					Expect(pvcObj.Spec.VolumeName).ShouldNot(BeEmpty())

					By("verifying whether cvr is created and healthy")
					csv, err = cv.
						NewKubeclient(cv.WithNamespace("openebs"), cv.WithKubeConfigPath(kubeConfigPath)).
						Get(pvcObj.Spec.VolumeName, metav1.GetOptions{})
					Expect(err).ShouldNot(HaveOccurred())
					return cv.
						NewForAPIObject(csv).IsHealthy()
				},
				framework.DefaultTimeOut, framework.DefaultPollingInterval).
				Should(BeTrue())

			By("sending get request to maya-exporter")
			out, err = ops.ExecPod(opts)
			Expect(err).To(BeNil(), "while executing command in container ", cmd)
			err = json.Unmarshal(out, &stats)

			By("unmarshalling the metrics")
			Expect(err).To(BeNil(), "while unmarshalling the stats", string(out))
			mapResp = stats.ToMap()
			Expect(apis.GetValue("openebs_replica_status", mapResp)).To(Equal(float64(1)), "while getting pool status of", pod.Items[0].Name, mapResp)
		})
	})
})
<commit_msg>fix(bdd,exporter): rename metrics name (#1258)<commit_after>// Copyright © 2019 The OpenEBS Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package exporter

import (
	"encoding/json"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	apis "github.com/openebs/maya/pkg/apis/openebs.io/v1alpha1"
	csp "github.com/openebs/maya/pkg/cstorpool/v1alpha3"
	cv "github.com/openebs/maya/pkg/cstorvolume/v1alpha1"
	pvc "github.com/openebs/maya/pkg/kubernetes/persistentvolumeclaim/v1alpha1"
	sc "github.com/openebs/maya/pkg/kubernetes/storageclass/v1alpha1"
	spc "github.com/openebs/maya/pkg/storagepoolclaim/v1alpha1"
	"github.com/openebs/maya/tests"
	framework "github.com/openebs/maya/tests/framework/v1alpha1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
)

const (
	online, healthy float64 = 1, 1
)

const (
	poolStatus                = "openebs_pool_status"
	replicaStatus             = "openebs_replica_status"
	noPoolAvailableErrorCount = "openebs_zpool_list_no_pool_available_error"
)

var _ = Describe("Test maya-exporter [single-pool-pod]", func() {
	var (
		err error
		pod *corev1.PodList
	)
	BeforeEach(func() {
		When("we are creating pool deployment", func() {
			By("building object of storageclass")
			scObj, err = sc.NewBuilder().
				WithName(scName).
				WithAnnotations(annotations).
				WithProvisioner(openebsProvisioner).Build()
			Expect(err).ShouldNot(HaveOccurred(), "while building storageclass obj for storageclass {%s}", scName)

			By("creating storageclass")
			_, err = ops.SCClient.Create(scObj)
			Expect(err).To(BeNil(), "while creating storageclass", scName)

			By("building spc object")
			spcObj = spc.NewBuilder().
				WithName(spcName).
				WithDiskType(string(apis.TypeBlockDeviceCPV)).
				WithMaxPool(1).
				WithOverProvisioning(false).
				WithPoolType(string(apis.PoolTypeStripedCPV)).
				Build().Object

			By("creating storagepoolclaim")
			_, err = ops.SPCClient.Create(spcObj)
			Expect(err).To(BeNil(), "while creating spc", spcName)

			By("verifying healthy csp count")
			Eventually(func() int {
				cspAPIList, err = ops.CSPClient.List(metav1.ListOptions{})
				Expect(err).To(BeNil())
				count := csp.
					ListBuilderForAPIObject(cspAPIList).
					List().
					Filter(csp.HasLabel(string(apis.StoragePoolClaimCPK), spcName), csp.IsStatus("Healthy")).Len()
				return count
			},
				framework.DefaultTimeOut, framework.DefaultPollingInterval).
				Should(Equal(1), "while getting healthy csp count")

			By("listing cstor pool pods")
			selector := map[string]string{
				string(apis.StoragePoolClaimCPK): spcName,
				"app": "cstor-pool",
			}

			ls := labels.Set(selector).
				AsSelector().
				String()
			pod, err = ops.PodClient.List(metav1.ListOptions{
				LabelSelector: ls,
			})

			Expect(err).To(BeNil(), "while listing pool pods with selector ", ls)

			By("verifying pod items")
			Expect(len(pod.Items)).To(Equal(1), "while getting pod items length", pod)

			By("verifying no of containers in pool pod")
			Expect(len(pod.Items[0].Spec.Containers)).To(Equal(3), "while getting no of containers", pod)

			By("verifying whether maya-exporter container exists")
			Expect(pod.Items[0].Spec.Containers[2].Name).To(Equal("maya-exporter"), "while verifying container name", pod)

		})
	})

	AfterEach(func() {
		When("we are deleting resources created for testing maya-exporter", func() {
			By("getting the pvclaim name")
			pvcObj, err = pvc.
				NewKubeClient(pvc.WithKubeConfigPath(kubeConfigPath)).
				WithNamespace(nsName).
				Get(pvcName, metav1.GetOptions{})
			Expect(err).ShouldNot(HaveOccurred())
			Expect(pvcObj.Spec.VolumeName).ShouldNot(BeEmpty())

			By("deleting pvc")
			err = pvc.
				NewKubeClient(pvc.WithKubeConfigPath(kubeConfigPath)).
				WithNamespace(nsName).
				Delete(pvcName, new(metav1.DeleteOptions))
			Expect(err).ShouldNot(HaveOccurred())

			By("listing pvc to verify if it is deleted")
			Eventually(func() int {
				pvcs, err = pvc.
					NewKubeClient(pvc.WithKubeConfigPath(kubeConfigPath)).
					WithNamespace(nsName).
					List(metav1.ListOptions{LabelSelector: "name=exporter-volume"})
				Expect(err).ShouldNot(HaveOccurred())
				return len(pvcs.Items)
			},
				framework.DefaultTimeOut, framework.DefaultPollingInterval).
				Should(Equal(0), "while listing pvc")

			CstorVolumeLabel := "openebs.io/persistent-volume=" + pvcObj.Spec.VolumeName

			By("verifying if cv is deleted")
			// verify deletion of cstorvolume
			Eventually(func() int {
				cvs, err = cv.
					NewKubeclient(cv.WithNamespace("openebs"), cv.WithKubeConfigPath(kubeConfigPath)).
					List(metav1.ListOptions{LabelSelector: CstorVolumeLabel})
				Expect(err).ShouldNot(HaveOccurred())
				return len(cvs.Items)
			},
				framework.DefaultTimeOut, framework.DefaultPollingInterval).
				Should(Equal(0), "while listing cvs")

			By("deleting storageclass")
			err = ops.SCClient.Delete(scName, &metav1.DeleteOptions{})
			Expect(err).To(BeNil(), "while deleting storageclass", scName)

			By("listing spc")
			spcList, err := ops.SPCClient.List(metav1.ListOptions{})
			Expect(err).To(BeNil(), "while listing spc clients", spcList)

			By("deleting spc")
			for _, spc := range spcList.Items {
				_, err = ops.SPCClient.Delete(spc.Name, &metav1.DeleteOptions{})
				Expect(err).To(BeNil(), "while deleting the spc's", spc)
			}
		})
	})

	Context("Test maya-exporter's response", func() {
		It("should show pool status and volume as online (1) and no errors", func() {
			By("sending get request to maya-exporter without pvc")
			curl := "curl localhost:9500/metrics/?format=json"
			cmd := []string{"/bin/bash", "-c", curl}
			opts := tests.NewOptions().
				WithPodName(pod.Items[0].Name).
				WithNamespace(pod.Items[0].Namespace).
				WithContainer(pod.Items[0].Spec.Containers[2].Name).
				WithCommand(cmd...)

			out, err := ops.ExecPod(opts)

			Expect(err).To(BeNil(), "while executing command in container ", cmd)

			By("unmarshalling pool metrics")
			stats := apis.PoolMetricsList{}
			err = json.Unmarshal(out, &stats)
			Expect(err).To(BeNil(), "while unmarshalling metrics", string(out))

			mapResp := stats.ToMap()

			By("verifying whether pool status is online")
			Expect(apis.GetValue(poolStatus, mapResp)).To(Equal(online), "while getting pool status of", pod.Items[0].Name)

			By("verifying whether there is no error")
			Expect(apis.GetValue(noPoolAvailableErrorCount, mapResp)).To(Equal(float64(0)), "while getting total no of no pool available errors", pod.Items[0].Name, mapResp)

			By("building pvc object")
			pvcObj, err = pvc.NewBuilder().
				WithName(pvcName).
				WithNamespace(nsName).
				WithStorageClass(scName).
				WithAccessModes([]corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}).
				WithCapacity("1G").
				Build()
			Expect(err).To(BeNil(), "while creating pvc", pvcName)

			By("creating pvc")
			_, err = ops.PVCClient.WithNamespace(nsName).Create(pvcObj)
			Expect(err).To(BeNil(), "while creating pvc", pvcName)

			By("verifying pvc to be created and bound with pv")
			Eventually(
				func() bool {
					return ops.IsPVCBound(pvcName)
				},
				framework.DefaultTimeOut, framework.DefaultPollingInterval).
				Should(BeTrue())

			Eventually(
				func() bool {
					By("getting the pvclaim name")
					pvcObj, err = pvc.
						NewKubeClient(pvc.WithKubeConfigPath(kubeConfigPath)).
						WithNamespace(nsName).
						Get(pvcName, metav1.GetOptions{})
					Expect(err).ShouldNot(HaveOccurred())
					Expect(pvcObj.Spec.VolumeName).ShouldNot(BeEmpty())

					By("verifying whether cvr is created and healthy")
					csv, err = cv.
						NewKubeclient(cv.WithNamespace("openebs"), cv.WithKubeConfigPath(kubeConfigPath)).
						Get(pvcObj.Spec.VolumeName, metav1.GetOptions{})
					Expect(err).ShouldNot(HaveOccurred())
					return cv.
						NewForAPIObject(csv).IsHealthy()
				},
				framework.DefaultTimeOut, framework.DefaultPollingInterval).
				Should(BeTrue())

			By("sending get request to maya-exporter")
			out, err = ops.ExecPod(opts)
			Expect(err).To(BeNil(), "while executing command in container ", cmd)
			err = json.Unmarshal(out, &stats)

			By("unmarshalling the metrics")
			Expect(err).To(BeNil(), "while unmarshalling the stats", string(out))
			mapResp = stats.ToMap()
			Expect(apis.GetValue(replicaStatus, mapResp)).To(Equal(healthy), "while getting pool status of", pod.Items[0].Name, mapResp)
		})
	})
})
<|endoftext|>


<commit_before>package client

/*
 Copyleft 2016 Alexander I.Grafov <grafov@gmail.com>

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

 ॐ तारे तुत्तारे तुरे स्व
*/

import (
	"encoding/json"
	"fmt"
	"net/url"

	"github.com/grafov/autograf/grafana"
)

func (r *Instance) SetDashboard(b *grafana.Board) {

}

func (r *Instance) GetDashboard(slug string) (grafana.Board, error) {
	var (
		raw   []byte
		board grafana.Board
		err   error
	)
	if raw, err = r.get(fmt.Sprintf("api/dashboards/db/%s", slug), nil); err != nil {
		return grafana.Board{}, err
	}
	err = json.Unmarshal(raw, &board)
	return board, err
}

// SearchDashboards search dashboards by query substring. Il allows restrict the result set with
// only starred dashboards and only for tags (logical OR applied to multiple tags).
func (r *Instance) SearchDashboards(query string, starred bool, tags ...string) ([]grafana.Board, error) {
	var (
		raw    []byte
		boards []grafana.Board
		err    error
	)
	u := url.URL{}
	q := u.Query()
	if query != "" {
		q.Set("query", query)
	}
	if starred {
		q.Set("starred", "true")
	}
	for _, tag := range tags {
		q.Add("tag", tag)
	}
	if raw, err = r.get("api/search", q); err != nil {
		return nil, err
	}
	err = json.Unmarshal(raw, &boards)
	return boards, err
}
<commit_msg>Use own datatype for search results.<commit_after>package client

/*
 Copyleft 2016 Alexander I.Grafov <grafov@gmail.com>

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.

 ॐ तारे तुत्तारे तुरे स्व
*/

import (
	"encoding/json"
	"fmt"
	"net/url"

	"github.com/grafov/autograf/grafana"
)

func (r *Instance) SetDashboard(b *grafana.Board) {

}

func (r *Instance) GetDashboard(slug string) (grafana.Board, error) {
	var (
		raw   []byte
		board grafana.Board
		err   error
	)
	if raw, err = r.get(fmt.Sprintf("api/dashboards/db/%s", slug), nil); err != nil {
		return grafana.Board{}, err
	}
	err = json.Unmarshal(raw, &board)
	return board, err
}

type FoundBoard struct {
	ID        uint     `json:"id"`
	Title     string   `json:"title"`
	URI       string   `json:"uri"`
	Type      string   `json:"type"`
	Tags      []string `json:"tags"`
	IsStarred bool     `json:"isStarred"`
}

// SearchDashboards search dashboards by query substring. Il allows restrict the result set with
// only starred dashboards and only for tags (logical OR applied to multiple tags).
func (r *Instance) SearchDashboards(query string, starred bool, tags ...string) ([]FoundBoard, error) {
	var (
		raw    []byte
		boards []FoundBoard
		err    error
	)
	u := url.URL{}
	q := u.Query()
	if query != "" {
		q.Set("query", query)
	}
	if starred {
		q.Set("starred", "true")
	}
	for _, tag := range tags {
		q.Add("tag", tag)
	}
	if raw, err = r.get("api/search", q); err != nil {
		return nil, err
	}
	err = json.Unmarshal(raw, &boards)
	return boards, err
}
<|endoftext|>


<commit_before>package compress_test

import (
	"fmt"
	"net/http"

	"github.com/gowww/compress"
)

func Example() {
	mux := http.NewServeMux()

	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Response is gzipped when content is long enough.")
	})

	http.ListenAndServe(":8080", compress.Handle(mux))
}

func ExampleHandle() {
	mux := http.NewServeMux()

	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Response is gzipped when content is long enough.")
	})

	http.ListenAndServe(":8080", compress.Handle(mux))
}

func ExampleHandleFunc() {
	http.Handle("/", compress.HandleFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Response is gzipped when content is long enough.")
	}))

	http.ListenAndServe(":8080", nil)
}
<commit_msg>Update examples<commit_after>package compress_test

import (
	"fmt"
	"net/http"

	"github.com/gowww/compress"
)

func Example() {
	mux := http.NewServeMux()

	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "Response is gzipped when content is long enough.")
	})

	http.ListenAndServe(":8080", compress.Handle(mux))
}

func ExampleHandle() {
	mux := http.NewServeMux()

	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "Response is gzipped when content is long enough.")
	})

	http.ListenAndServe(":8080", compress.Handle(mux))
}

func ExampleHandleFunc() {
	http.Handle("/", compress.HandleFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "Response is gzipped when content is long enough.")
	}))

	http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before>package socks5_test

func ExampleStandardSocks5Server() {
	s, err := NewClassicServer("127.0.0.1:1080", "127.0.0.1", "", "", 60, 0, 60, 60)
	if err != nil {
		panic(err)
	}
	// You can pass in custom Handler
	s.Run(nil)
}
<commit_msg>readme<commit_after>package socks5_test

import "github.com/txthinking/socks5"

func ExampleStandardSocks5Server() {
	s, err := socks5.NewClassicServer("127.0.0.1:1080", "127.0.0.1", "", "", 60, 0, 60, 60)
	if err != nil {
		panic(err)
	}
	// You can pass in custom Handler
	s.Run(nil)
}
<|endoftext|>


<commit_before>package redis_test

import (
	"fmt"
	"strconv"

	"gopkg.in/redis.v2"
)

var client *redis.Client

func init() {
	client = redis.NewTCPClient(&redis.Options{
		Addr: ":6379",
	})
	client.FlushDb()
}

func ExampleNewTCPClient() {
	client := redis.NewTCPClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "", // no password set
		DB:       0,  // use default DB
	})

	pong, err := client.Ping().Result()
	fmt.Println(pong, err)
	// Output: PONG <nil>
}

func ExampleNewFailoverClient() {
	client := redis.NewFailoverClient(&redis.FailoverOptions{
		MasterName:    "master",
		SentinelAddrs: []string{":26379"},
	})

	pong, err := client.Ping().Result()
	fmt.Println(pong, err)
	// Output: PONG <nil>
}

func ExampleClient() {
	if err := client.Set("foo", "bar").Err(); err != nil {
		panic(err)
	}

	v, err := client.Get("hello").Result()
	fmt.Printf("%q %q %v", v, err, err == redis.Nil)
	// Output: "" "redis: nil" true
}

func ExampleClient_Incr() {
	if err := client.Incr("counter").Err(); err != nil {
		panic(err)
	}

	n, err := client.Get("counter").Int64()
	fmt.Println(n, err)
	// Output: 1 <nil>
}

func ExampleClient_Pipelined() {
	cmds, err := client.Pipelined(func(c *redis.Pipeline) error {
		c.Set("key1", "hello1")
		c.Get("key1")
		return nil
	})
	fmt.Println(err)
	set := cmds[0].(*redis.StatusCmd)
	fmt.Println(set)
	get := cmds[1].(*redis.StringCmd)
	fmt.Println(get)
	// Output: <nil>
	// SET key1 hello1: OK
	// GET key1: hello1
}

func ExamplePipeline() {
	pipeline := client.Pipeline()
	set := pipeline.Set("key1", "hello1")
	get := pipeline.Get("key1")
	cmds, err := pipeline.Exec()
	fmt.Println(cmds, err)
	fmt.Println(set)
	fmt.Println(get)
	// Output: [SET key1 hello1: OK GET key1: hello1] <nil>
	// SET key1 hello1: OK
	// GET key1: hello1
}

func ExampleMulti() {
	incr := func(tx *redis.Multi) ([]redis.Cmder, error) {
		s, err := tx.Get("key").Result()
		if err != nil && err != redis.Nil {
			return nil, err
		}
		n, _ := strconv.ParseInt(s, 10, 64)

		return tx.Exec(func() error {
			tx.Set("key", strconv.FormatInt(n+1, 10))
			return nil
		})
	}

	client.Del("key")

	tx := client.Multi()
	defer tx.Close()

	watch := tx.Watch("key")
	_ = watch.Err()

	for {
		cmds, err := incr(tx)
		if err == redis.TxFailedErr {
			continue
		} else if err != nil {
			panic(err)
		}
		fmt.Println(cmds, err)
		break
	}

	// Output: [SET key 1: OK] <nil>
}

func ExamplePubSub() {
	pubsub := client.PubSub()
	defer pubsub.Close()

	err := pubsub.Subscribe("mychannel")
	_ = err

	msg, err := pubsub.Receive()
	fmt.Println(msg, err)

	pub := client.Publish("mychannel", "hello")
	_ = pub.Err()

	msg, err = pubsub.Receive()
	fmt.Println(msg, err)

	// Output: subscribe: mychannel <nil>
	// Message<mychannel: hello> <nil>
}

func ExampleScript() {
	setnx := redis.NewScript(`
        if redis.call("get", KEYS[1]) == false then
            redis.call("set", KEYS[1], ARGV[1])
            return 1
        end
        return 0
    `)

	v1, err := setnx.Run(client, []string{"keynx"}, []string{"foo"}).Result()
	fmt.Println(v1.(int64), err)

	v2, err := setnx.Run(client, []string{"keynx"}, []string{"bar"}).Result()
	fmt.Println(v2.(int64), err)

	get := client.Get("keynx")
	fmt.Println(get)

	// Output: 1 <nil>
	// 0 <nil>
	// GET keynx: foo
}

func Example_customCommand() {
	Get := func(client *redis.Client, key string) *redis.StringCmd {
		cmd := redis.NewStringCmd("GET", key)
		client.Process(cmd)
		return cmd
	}

	v, err := Get(client, "key_does_not_exist").Result()
	fmt.Printf("%q %s", v, err)
	// Output: "" redis: nil
}
<commit_msg>Fix example.<commit_after>package redis_test

import (
	"fmt"
	"strconv"

	"gopkg.in/redis.v2"
)

var client *redis.Client

func init() {
	client = redis.NewTCPClient(&redis.Options{
		Addr: ":6379",
	})
	client.FlushDb()
}

func ExampleNewTCPClient() {
	client := redis.NewTCPClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "", // no password set
		DB:       0,  // use default DB
	})

	pong, err := client.Ping().Result()
	fmt.Println(pong, err)
	// Output: PONG <nil>
}

func ExampleNewFailoverClient() {
	redis.NewFailoverClient(&redis.FailoverOptions{
		MasterName:    "master",
		SentinelAddrs: []string{":26379"},
	})
}

func ExampleClient() {
	if err := client.Set("foo", "bar").Err(); err != nil {
		panic(err)
	}

	v, err := client.Get("hello").Result()
	fmt.Printf("%q %q %v", v, err, err == redis.Nil)
	// Output: "" "redis: nil" true
}

func ExampleClient_Incr() {
	if err := client.Incr("counter").Err(); err != nil {
		panic(err)
	}

	n, err := client.Get("counter").Int64()
	fmt.Println(n, err)
	// Output: 1 <nil>
}

func ExampleClient_Pipelined() {
	cmds, err := client.Pipelined(func(c *redis.Pipeline) error {
		c.Set("key1", "hello1")
		c.Get("key1")
		return nil
	})
	fmt.Println(err)
	set := cmds[0].(*redis.StatusCmd)
	fmt.Println(set)
	get := cmds[1].(*redis.StringCmd)
	fmt.Println(get)
	// Output: <nil>
	// SET key1 hello1: OK
	// GET key1: hello1
}

func ExamplePipeline() {
	pipeline := client.Pipeline()
	set := pipeline.Set("key1", "hello1")
	get := pipeline.Get("key1")
	cmds, err := pipeline.Exec()
	fmt.Println(cmds, err)
	fmt.Println(set)
	fmt.Println(get)
	// Output: [SET key1 hello1: OK GET key1: hello1] <nil>
	// SET key1 hello1: OK
	// GET key1: hello1
}

func ExampleMulti() {
	incr := func(tx *redis.Multi) ([]redis.Cmder, error) {
		s, err := tx.Get("key").Result()
		if err != nil && err != redis.Nil {
			return nil, err
		}
		n, _ := strconv.ParseInt(s, 10, 64)

		return tx.Exec(func() error {
			tx.Set("key", strconv.FormatInt(n+1, 10))
			return nil
		})
	}

	client.Del("key")

	tx := client.Multi()
	defer tx.Close()

	watch := tx.Watch("key")
	_ = watch.Err()

	for {
		cmds, err := incr(tx)
		if err == redis.TxFailedErr {
			continue
		} else if err != nil {
			panic(err)
		}
		fmt.Println(cmds, err)
		break
	}

	// Output: [SET key 1: OK] <nil>
}

func ExamplePubSub() {
	pubsub := client.PubSub()
	defer pubsub.Close()

	err := pubsub.Subscribe("mychannel")
	_ = err

	msg, err := pubsub.Receive()
	fmt.Println(msg, err)

	pub := client.Publish("mychannel", "hello")
	_ = pub.Err()

	msg, err = pubsub.Receive()
	fmt.Println(msg, err)

	// Output: subscribe: mychannel <nil>
	// Message<mychannel: hello> <nil>
}

func ExampleScript() {
	setnx := redis.NewScript(`
        if redis.call("get", KEYS[1]) == false then
            redis.call("set", KEYS[1], ARGV[1])
            return 1
        end
        return 0
    `)

	v1, err := setnx.Run(client, []string{"keynx"}, []string{"foo"}).Result()
	fmt.Println(v1.(int64), err)

	v2, err := setnx.Run(client, []string{"keynx"}, []string{"bar"}).Result()
	fmt.Println(v2.(int64), err)

	get := client.Get("keynx")
	fmt.Println(get)

	// Output: 1 <nil>
	// 0 <nil>
	// GET keynx: foo
}

func Example_customCommand() {
	Get := func(client *redis.Client, key string) *redis.StringCmd {
		cmd := redis.NewStringCmd("GET", key)
		client.Process(cmd)
		return cmd
	}

	v, err := Get(client, "key_does_not_exist").Result()
	fmt.Printf("%q %s", v, err)
	// Output: "" redis: nil
}
<|endoftext|>


<commit_before>package countmin

import (
	"fmt"
)

func ExampleCountMin_Add() {
	cm := New(10, 100000000)
	for _, i := range []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1} {
		cm.Add([]byte(fmt.Sprintf("%d", i)), int64(i))
	}
	fmt.Printf("Estimate of %d is %d\n", 1, cm.Count([]byte("1")))
	fmt.Printf("Estimate of %d is %d\n", 3, cm.Count([]byte("3")))
	fmt.Printf("Estimate of %d is %d\n", 9, cm.Count([]byte("9")))
	fmt.Println("Size: ", cm.Size())
	fmt.Println("Err: ", cm.RelativeError())
	fmt.Println("Confidence: ", cm.Confidence())
	// Output:
	// Estimate of 1 is 3
	// Estimate of 3 is 6
	// Estimate of 9 is 18
	// Size:  91
	// Err:  2e-08
	// Confidence:  0.9990234375
}

func ExampleCountMin_Merge() {
	cm1 := New(10, 100000000)
	for _, i := range []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1} {
		cm1.Add([]byte(fmt.Sprintf("%d", i)), int64(i))
	}

	cm2 := New(10, 100000000)
	for _, i := range []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1} {
		cm2.Add([]byte(fmt.Sprintf("%d", i)), int64(i))
	}
	merged, _ := Merge(cm1, cm2)
	fmt.Printf("Estimate of %d is %d\n", 1, merged.Count([]byte("1")))
	fmt.Printf("Estimate of %d is %d\n", 3, merged.Count([]byte("3")))
	fmt.Printf("Estimate of %d is %d\n", 9, merged.Count([]byte("9")))
	fmt.Println("Size: ", merged.Size())
	fmt.Println("Err: ", merged.RelativeError())
	fmt.Println("Confidence: ", merged.Confidence())
	// Output:
	// Estimate of 1 is 6
	// Estimate of 3 is 12
	// Estimate of 9 is 36
	// Size:  182
	// Err:  2e-08
	// Confidence:  0.9990234375
}
<commit_msg>Fix govet issue with example test function name<commit_after>package countmin

import (
	"fmt"
)

func ExampleCountMin_Add() {
	cm := New(10, 100000000)
	for _, i := range []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1} {
		cm.Add([]byte(fmt.Sprintf("%d", i)), int64(i))
	}
	fmt.Printf("Estimate of %d is %d\n", 1, cm.Count([]byte("1")))
	fmt.Printf("Estimate of %d is %d\n", 3, cm.Count([]byte("3")))
	fmt.Printf("Estimate of %d is %d\n", 9, cm.Count([]byte("9")))
	fmt.Println("Size: ", cm.Size())
	fmt.Println("Err: ", cm.RelativeError())
	fmt.Println("Confidence: ", cm.Confidence())
	// Output:
	// Estimate of 1 is 3
	// Estimate of 3 is 6
	// Estimate of 9 is 18
	// Size:  91
	// Err:  2e-08
	// Confidence:  0.9990234375
}

func ExampleMerge() {
	cm1 := New(10, 100000000)
	for _, i := range []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1} {
		cm1.Add([]byte(fmt.Sprintf("%d", i)), int64(i))
	}

	cm2 := New(10, 100000000)
	for _, i := range []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1} {
		cm2.Add([]byte(fmt.Sprintf("%d", i)), int64(i))
	}
	merged, _ := Merge(cm1, cm2)
	fmt.Printf("Estimate of %d is %d\n", 1, merged.Count([]byte("1")))
	fmt.Printf("Estimate of %d is %d\n", 3, merged.Count([]byte("3")))
	fmt.Printf("Estimate of %d is %d\n", 9, merged.Count([]byte("9")))
	fmt.Println("Size: ", merged.Size())
	fmt.Println("Err: ", merged.RelativeError())
	fmt.Println("Confidence: ", merged.Confidence())
	// Output:
	// Estimate of 1 is 6
	// Estimate of 3 is 12
	// Estimate of 9 is 36
	// Size:  182
	// Err:  2e-08
	// Confidence:  0.9990234375
}
<|endoftext|>


<commit_before>package clock_test

import (
	"testing"
	"time"

	. "github.com/aleasoluciones/goaleasoluciones/clock"

	"github.com/stretchr/testify/assert"
)

func TestClockReturnsCurrentTime(t *testing.T) {
	t.Parallel()
	clock := NewClock()

	result := clock.Now()

	assert.IsType(t, result, time.Time{})
}

func TestClockReturnsToday(t *testing.T) {
	t.Parallel()
	clock := NewClock()

	year, month, day := clock.Today()

	expected_year, expected_month, expected_day := time.Now().Date()
	assert.Equal(t, year, expected_year)
	assert.Equal(t, month, expected_month)
	assert.Equal(t, day, expected_day)
}

func TestSleeperSleep(t *testing.T) {
	t.Parallel()
	sleeper := NewSleeper()

	sleeper.Sleep(1 * time.Millisecond)
}

type FakeClock struct{}

func (clock *FakeClock) Now() time.Time {
	return time.Date(2013, time.September, 9, 23, 0, 0, 0, time.UTC)
}

func (clock *FakeClock) Today() (year int, month time.Month, day int) {
	return 2013, time.September, 9
}

func TestSleeperSleepUntilIfDurationIsAheadOfCurrentTime(t *testing.T) {
	t.Parallel()
	sleeper := NewSleeperWithClock(&FakeClock{})

	start := time.Now()
	sleeper.SleepUntil(time.Date(2013, time.September, 9, 23, 0, 1, 0, time.UTC))

	assert.WithinDuration(t, time.Now(), start, 2*time.Second)
}

func TestSleeperDoNotSleepUntilIfDurationIsBehindOfCurrentTime(t *testing.T) {
	t.Parallel()
	sleeper := NewSleeperWithClock(&FakeClock{})

	start := time.Now()
	sleeper.SleepUntil(time.Date(2013, time.September, 9, 22, 0, 0, 0, time.UTC))

	assert.WithinDuration(t, time.Now(), start, 1*time.Second)
}
<commit_msg>Update clock_test.go<commit_after>// Copyright 2014 Alea Soluciones SLL. All rights reserved.  Use of this
// source code is governed by a MIT-style license that can be found in the
// LICENSE file.

package clock_test

import (
	"testing"
	"time"

	. "github.com/aleasoluciones/goaleasoluciones/clock"

	"github.com/stretchr/testify/assert"
)

func TestClockReturnsCurrentTime(t *testing.T) {
	t.Parallel()
	clock := NewClock()

	result := clock.Now()

	assert.IsType(t, result, time.Time{})
}

func TestClockReturnsToday(t *testing.T) {
	t.Parallel()
	clock := NewClock()

	year, month, day := clock.Today()

	expected_year, expected_month, expected_day := time.Now().Date()
	assert.Equal(t, year, expected_year)
	assert.Equal(t, month, expected_month)
	assert.Equal(t, day, expected_day)
}

func TestSleeperSleep(t *testing.T) {
	t.Parallel()
	sleeper := NewSleeper()

	sleeper.Sleep(1 * time.Millisecond)
}

type FakeClock struct{}

func (clock *FakeClock) Now() time.Time {
	return time.Date(2013, time.September, 9, 23, 0, 0, 0, time.UTC)
}

func (clock *FakeClock) Today() (year int, month time.Month, day int) {
	return 2013, time.September, 9
}

func TestSleeperSleepUntilIfDurationIsAheadOfCurrentTime(t *testing.T) {
	t.Parallel()
	sleeper := NewSleeperWithClock(&FakeClock{})

	start := time.Now()
	sleeper.SleepUntil(time.Date(2013, time.September, 9, 23, 0, 1, 0, time.UTC))

	assert.WithinDuration(t, time.Now(), start, 2*time.Second)
}

func TestSleeperDoNotSleepUntilIfDurationIsBehindOfCurrentTime(t *testing.T) {
	t.Parallel()
	sleeper := NewSleeperWithClock(&FakeClock{})

	start := time.Now()
	sleeper.SleepUntil(time.Date(2013, time.September, 9, 22, 0, 0, 0, time.UTC))

	assert.WithinDuration(t, time.Now(), start, 1*time.Second)
}
<|endoftext|>


<commit_before>/*
Copyright 2022 The Kubernetes Authors.

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

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

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

package main

import (
	"context"
	"flag"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"syscall"
	"time"

	"k8s.io/klog/v2"
	"k8s.io/registry.k8s.io/cmd/archeio/app"
)

func main() {
	// klog setup
	klog.InitFlags(nil)
	flag.Parse()
	defer klog.Flush()

	// cloud run expects us to listen to HTTP on $PORT
	// https://cloud.google.com/run/docs/container-contract#port
	port := getEnv("PORT", "8080")

	// make it possible to override k8s.gcr.io without rebuilding in the future
	registryConfig := app.RegistryConfig{
		UpstreamRegistryEndpoint: getEnv("UPSTREAM_REGISTRY_ENDPOINT", "https://k8s.gcr.io"),
		UpstreamRegistryPath:     getEnv("UPSTREAM_REGISTRY_PATH", ""),
		InfoURL:                  "https://github.com/kubernetes/k8s.io/wiki/New-Registry-url-for-Kubernetes-(registry.k8s.io)",
		PrivacyURL:               "https://www.linuxfoundation.org/privacy-policy/",
	}

	var err error
	// feature gate AWS S3 serving feature
	registryConfig.ServeImagesfromAWS, err = strconv.ParseBool(getEnv("SERVE_IMAGES_FROM_AWS", "true"))
	if err != nil {
		klog.Fatal("SERVE_IMAGES_FROM_AWS environment variable is not set to a boolean value %v", err)
	}

	// configure server with reasonable timeout
	// we only serve redirects, 10s should be sufficient
	server := &http.Server{
		Addr:              ":" + port,
		Handler:           app.MakeHandler(registryConfig),
		ReadTimeout:       10 * time.Second,
		ReadHeaderTimeout: 2 * time.Second,
	}

	// signal handler for graceful shutdown
	done := make(chan os.Signal, 1)
	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)

	// start serving
	go func() {
		if err = server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			klog.Fatal(err)
		}
	}()
	klog.InfoS("listening", "port", port)
	klog.InfoS("registry", "configuration", registryConfig)

	// Graceful shutdown
	<-done
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := server.Shutdown(ctx); err != nil {
		klog.Fatalf("Server didn't exit gracefully %v", err)
	}
}

// getEnv returns defaultValue if key is not set, else the value of os.LookupEnv(key)
func getEnv(key, defaultValue string) string {
	if value, ok := os.LookupEnv(key); ok {
		return value
	}
	return defaultValue
}
<commit_msg>update info URL to point to source repo<commit_after>/*
Copyright 2022 The Kubernetes Authors.

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

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

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

package main

import (
	"context"
	"flag"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"syscall"
	"time"

	"k8s.io/klog/v2"
	"k8s.io/registry.k8s.io/cmd/archeio/app"
)

func main() {
	// klog setup
	klog.InitFlags(nil)
	flag.Parse()
	defer klog.Flush()

	// cloud run expects us to listen to HTTP on $PORT
	// https://cloud.google.com/run/docs/container-contract#port
	port := getEnv("PORT", "8080")

	// make it possible to override k8s.gcr.io without rebuilding in the future
	registryConfig := app.RegistryConfig{
		UpstreamRegistryEndpoint: getEnv("UPSTREAM_REGISTRY_ENDPOINT", "https://k8s.gcr.io"),
		UpstreamRegistryPath:     getEnv("UPSTREAM_REGISTRY_PATH", ""),
		InfoURL:                  "https://github.com/kubernetes/registry.k8s.io",
		PrivacyURL:               "https://www.linuxfoundation.org/privacy-policy/",
	}

	var err error
	// feature gate AWS S3 serving feature
	registryConfig.ServeImagesfromAWS, err = strconv.ParseBool(getEnv("SERVE_IMAGES_FROM_AWS", "true"))
	if err != nil {
		klog.Fatal("SERVE_IMAGES_FROM_AWS environment variable is not set to a boolean value %v", err)
	}

	// configure server with reasonable timeout
	// we only serve redirects, 10s should be sufficient
	server := &http.Server{
		Addr:              ":" + port,
		Handler:           app.MakeHandler(registryConfig),
		ReadTimeout:       10 * time.Second,
		ReadHeaderTimeout: 2 * time.Second,
	}

	// signal handler for graceful shutdown
	done := make(chan os.Signal, 1)
	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)

	// start serving
	go func() {
		if err = server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			klog.Fatal(err)
		}
	}()
	klog.InfoS("listening", "port", port)
	klog.InfoS("registry", "configuration", registryConfig)

	// Graceful shutdown
	<-done
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := server.Shutdown(ctx); err != nil {
		klog.Fatalf("Server didn't exit gracefully %v", err)
	}
}

// getEnv returns defaultValue if key is not set, else the value of os.LookupEnv(key)
func getEnv(key, defaultValue string) string {
	if value, ok := os.LookupEnv(key); ok {
		return value
	}
	return defaultValue
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"net/url"
	"os"
	"sort"

	"github.com/pressly/chi"
	"github.com/pressly/chi/middleware"

	"github.com/disintegration/bebop/api"
	"github.com/disintegration/bebop/avatar"
	"github.com/disintegration/bebop/config"
	"github.com/disintegration/bebop/jwt"
	"github.com/disintegration/bebop/oauth"
	"github.com/disintegration/bebop/static"
)

// startServer configures and starts the bebop web server.
func startServer() {
	cfg, err := config.ReadFile(configFile)
	if err != nil {
		log.Fatalf("failed to load configuration file: %s", err)
	}

	logger := log.New(os.Stdout, "", log.LstdFlags|log.LUTC)

	baseURL, err := url.Parse(cfg.BaseURL)
	if err != nil {
		log.Fatalf("failed to parse base url: %s", err)
	}

	fileStorage, err := getFileStorage(cfg)
	if err != nil {
		log.Fatalf("failed to init file storage: %s", err)
	}

	store, err := getStore(cfg)
	if err != nil {
		log.Fatalf("failed to init data store: %s", err)
	}

	jwtService, err := jwt.NewService(cfg.JWT.Secret)
	if err != nil {
		log.Fatalf("failed to create jwt service: %s", err)
	}

	avatarService := avatar.NewService(store.Users(), fileStorage, logger)

	apiHandler := api.New(&api.Config{
		Logger:        logger,
		Store:         store,
		JWTService:    jwtService,
		AvatarService: avatarService,
	})

	oauthHandler := oauth.New(&oauth.Config{
		Logger:     logger,
		UserStore:  store.Users(),
		JWTService: jwtService,
		MountURL:   baseURL.String() + "/oauth",
		CookiePath: baseURL.Path + "/",
	})

	for providerName, provider := range cfg.OAuth {
		if provider.ClientID != "" && provider.Secret != "" {
			err := oauthHandler.AddProvider(providerName, provider.ClientID, provider.Secret)
			if err != nil {
				log.Fatalf("failed to init oauth provider (%s): %s", providerName, err)
			}
		}
	}

	indexHandler, err := newIndexHandler(cfg)
	if err != nil {
		log.Fatalf("failed to create index handler: %s", err)
	}

	router := chi.NewRouter()

	router.Use(middleware.RequestLogger(&middleware.DefaultLogFormatter{Logger: logger}))
	router.Use(middleware.Recoverer)

	router.Mount("/api/v1", apiHandler)
	router.Mount("/oauth", oauthHandler)

	router.Mount("/static/-", static.Embedded("/static/-"))

	if cfg.FileStorage.Type == "local" {
		router.Mount("/static", static.Dir("/static", cfg.FileStorage.Local.Dir))
	}

	router.Get("/", indexHandler)

	log.Printf("starting the server: %s", cfg.Address)

	if err := http.ListenAndServe(cfg.Address, http.StripPrefix(baseURL.Path, router)); err != nil {
		log.Fatalf("listen and serve failed: %v", err)
	}
}

func newIndexHandler(cfg *config.Config) (http.HandlerFunc, error) {
	t, err := template.New("indexTemplate").Parse(indexTemplate)
	if err != nil {
		return nil, fmt.Errorf("failed to parse template: %s", err)
	}

	appConfig := struct {
		Title string   `json:"title"`
		OAuth []string `json:"oauth"`
	}{
		Title: cfg.Title,
		OAuth: []string{},
	}

	for providerName := range cfg.OAuth {
		appConfig.OAuth = append(appConfig.OAuth, providerName)
	}
	sort.Strings(appConfig.OAuth)

	buf := new(bytes.Buffer)
	err = t.Execute(buf, map[string]interface{}{
		"title":     cfg.Title,
		"appConfig": appConfig,
	})
	if err != nil {
		return nil, fmt.Errorf("failed to execute index template: %s", err)
	}

	indexData := buf.Bytes()

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write(indexData)
	})

	return handler, nil
}

var indexTemplate = `<!doctype html>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>{{.title}}</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha256-916EbMg70RQy9LHiGkXzG8hSg9EdNy97GazNG/aiY1w=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-markdown/2.10.0/css/bootstrap-markdown.min.css" integrity="sha256-umMZCcE/LUcJ3F3V/D6NmvQxdm3OWtRMiMApkNnDIOw=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
    <link rel="stylesheet" href="static/-/frontend/css/bebop.css">

`
<commit_msg>server: don't add unused oauth providers to config<commit_after>package main

import (
	"bytes"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"net/url"
	"os"
	"sort"

	"github.com/pressly/chi"
	"github.com/pressly/chi/middleware"

	"github.com/disintegration/bebop/api"
	"github.com/disintegration/bebop/avatar"
	"github.com/disintegration/bebop/config"
	"github.com/disintegration/bebop/jwt"
	"github.com/disintegration/bebop/oauth"
	"github.com/disintegration/bebop/static"
)

// startServer configures and starts the bebop web server.
func startServer() {
	cfg, err := config.ReadFile(configFile)
	if err != nil {
		log.Fatalf("failed to load configuration file: %s", err)
	}

	logger := log.New(os.Stdout, "", log.LstdFlags|log.LUTC)

	baseURL, err := url.Parse(cfg.BaseURL)
	if err != nil {
		log.Fatalf("failed to parse base url: %s", err)
	}

	fileStorage, err := getFileStorage(cfg)
	if err != nil {
		log.Fatalf("failed to init file storage: %s", err)
	}

	store, err := getStore(cfg)
	if err != nil {
		log.Fatalf("failed to init data store: %s", err)
	}

	jwtService, err := jwt.NewService(cfg.JWT.Secret)
	if err != nil {
		log.Fatalf("failed to create jwt service: %s", err)
	}

	avatarService := avatar.NewService(store.Users(), fileStorage, logger)

	apiHandler := api.New(&api.Config{
		Logger:        logger,
		Store:         store,
		JWTService:    jwtService,
		AvatarService: avatarService,
	})

	oauthHandler := oauth.New(&oauth.Config{
		Logger:     logger,
		UserStore:  store.Users(),
		JWTService: jwtService,
		MountURL:   baseURL.String() + "/oauth",
		CookiePath: baseURL.Path + "/",
	})

	for providerName, provider := range cfg.OAuth {
		if provider.ClientID != "" && provider.Secret != "" {
			err := oauthHandler.AddProvider(providerName, provider.ClientID, provider.Secret)
			if err != nil {
				log.Fatalf("failed to init oauth provider (%s): %s", providerName, err)
			}
		}
	}

	indexHandler, err := newIndexHandler(cfg)
	if err != nil {
		log.Fatalf("failed to create index handler: %s", err)
	}

	router := chi.NewRouter()

	router.Use(middleware.RequestLogger(&middleware.DefaultLogFormatter{Logger: logger}))
	router.Use(middleware.Recoverer)

	router.Mount("/api/v1", apiHandler)
	router.Mount("/oauth", oauthHandler)

	router.Mount("/static/-", static.Embedded("/static/-"))

	if cfg.FileStorage.Type == "local" {
		router.Mount("/static", static.Dir("/static", cfg.FileStorage.Local.Dir))
	}

	router.Get("/", indexHandler)

	log.Printf("starting the server: %s", cfg.Address)

	if err := http.ListenAndServe(cfg.Address, http.StripPrefix(baseURL.Path, router)); err != nil {
		log.Fatalf("listen and serve failed: %v", err)
	}
}

func newIndexHandler(cfg *config.Config) (http.HandlerFunc, error) {
	t, err := template.New("indexTemplate").Parse(indexTemplate)
	if err != nil {
		return nil, fmt.Errorf("failed to parse template: %s", err)
	}

	appConfig := struct {
		Title string   `json:"title"`
		OAuth []string `json:"oauth"`
	}{
		Title: cfg.Title,
		OAuth: []string{},
	}

	for providerName, provider := range cfg.OAuth {
		if provider.ClientID != "" && provider.Secret != "" {
			appConfig.OAuth = append(appConfig.OAuth, providerName)
		}
	}
	sort.Strings(appConfig.OAuth)

	buf := new(bytes.Buffer)
	err = t.Execute(buf, map[string]interface{}{
		"title":     cfg.Title,
		"appConfig": appConfig,
	})
	if err != nil {
		return nil, fmt.Errorf("failed to execute index template: %s", err)
	}

	indexData := buf.Bytes()

	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write(indexData)
	})

	return handler, nil
}

var indexTemplate = `<!doctype html>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>{{.title}}</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha256-916EbMg70RQy9LHiGkXzG8hSg9EdNy97GazNG/aiY1w=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-markdown/2.10.0/css/bootstrap-markdown.min.css" integrity="sha256-umMZCcE/LUcJ3F3V/D6NmvQxdm3OWtRMiMApkNnDIOw=" crossorigin="anonymous" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
    <link rel="stylesheet" href="static/-/frontend/css/bebop.css">

`
<|endoftext|>


<commit_before>// Copyright 2014 ISRG.  All rights reserved
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package main

import (
	"fmt"
	"net/http"
	"os"
	"time"

	"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"

	"github.com/letsencrypt/boulder/ca"
	"github.com/letsencrypt/boulder/cmd"
	"github.com/letsencrypt/boulder/core"
	blog "github.com/letsencrypt/boulder/log"
	"github.com/letsencrypt/boulder/ra"
	"github.com/letsencrypt/boulder/sa"
	"github.com/letsencrypt/boulder/va"
	"github.com/letsencrypt/boulder/wfe"
)

type timedHandler struct {
	f     func(w http.ResponseWriter, r *http.Request)
	stats statsd.Statter
}

var openConnections int64

// HandlerTimer monitors HTTP performance and sends the details to StatsD.
func HandlerTimer(handler http.Handler, stats statsd.Statter) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		cStart := time.Now()
		openConnections++
		stats.Gauge("HttpConnectionsOpen", openConnections, 1.0)

		handler.ServeHTTP(w, r)

		openConnections--
		stats.Gauge("HttpConnectionsOpen", openConnections, 1.0)

		// (FIX: this doesn't seem to really work at catching errors...)
		state := "Success"
		for _, h := range w.Header()["Content-Type"] {
			if h == "application/problem+json" {
				state = "Error"
				break
			}
		}
		// set resp timing key based on success / failure
		stats.TimingDuration(fmt.Sprintf("HttpResponseTime.%s.%s", r.URL, state), time.Since(cStart), 1.0)
	})
}

func main() {
	app := cmd.NewAppShell("boulder")
	app.Action = func(c cmd.Config) {
		stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix)
		cmd.FailOnError(err, "Couldn't connect to statsd")

		// Set up logging
		auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
		cmd.FailOnError(err, "Could not connect to Syslog")

		// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
		defer auditlogger.AuditPanic()

		blog.SetAuditLogger(auditlogger)

		go cmd.DebugServer(c.Monolith.DebugAddr)

		// Run StatsD profiling
		go cmd.ProfileCmd("Monolith", stats)

		// Create the components
		wfei, err := wfe.NewWebFrontEndImpl()
		cmd.FailOnError(err, "Unable to create WFE")
		sa, err := sa.NewSQLStorageAuthority(c.SA.DBDriver, c.SA.DBConnect)
		cmd.FailOnError(err, "Unable to create SA")
		sa.SetSQLDebug(c.SQL.SQLDebug)

		wfei.CertCacheDuration, err = time.ParseDuration(c.WFE.CertCacheDuration)
		cmd.FailOnError(err, "Couldn't parse certificate caching duration")
		wfei.CertNoCacheExpirationWindow, err = time.ParseDuration(c.WFE.CertNoCacheExpirationWindow)
		cmd.FailOnError(err, "Couldn't parse certificate expiration no-cache window")
		wfei.IndexCacheDuration, err = time.ParseDuration(c.WFE.IndexCacheDuration)
		cmd.FailOnError(err, "Couldn't parse index caching duration")
		wfei.IssuerCacheDuration, err = time.ParseDuration(c.WFE.IssuerCacheDuration)
		cmd.FailOnError(err, "Couldn't parse issuer caching duration")

		ra := ra.NewRegistrationAuthorityImpl()
		raDNSTimeout, err := time.ParseDuration(c.RA.DNSTimeout)
		cmd.FailOnError(err, "Couldn't parse RA DNS timeout")
		ra.DNSResolver = core.NewDNSResolverImpl(raDNSTimeout, []string{c.RA.DNSResolver})

		va := va.NewValidationAuthorityImpl(c.CA.TestMode)
		vaDNSTimeout, err := time.ParseDuration(c.VA.DNSTimeout)
		cmd.FailOnError(err, "Couldn't parse VA DNS timeout")
		va.DNSResolver = core.NewDNSResolverImpl(vaDNSTimeout, []string{c.VA.DNSResolver})
		va.UserAgent = c.VA.UserAgent

		cadb, err := ca.NewCertificateAuthorityDatabaseImpl(c.CA.DBDriver, c.CA.DBConnect)
		cmd.FailOnError(err, "Failed to create CA database")

		ca, err := ca.NewCertificateAuthorityImpl(cadb, c.CA, c.Common.IssuerCert)
		cmd.FailOnError(err, "Unable to create CA")

		if c.SQL.CreateTables {
			err = sa.CreateTablesIfNotExists()
			cmd.FailOnError(err, "Failed to create SA tables")

			err = cadb.CreateTablesIfNotExists()
			cmd.FailOnError(err, "Failed to create CA tables")
		}

		// Wire them up
		wfei.RA = &ra
		wfei.SA = sa
		wfei.Stats = stats
		wfei.SubscriberAgreementURL = c.SubscriberAgreementURL

		wfei.IssuerCert, err = cmd.LoadCert(c.Common.IssuerCert)
		cmd.FailOnError(err, fmt.Sprintf("Couldn't read issuer cert [%s]", c.Common.IssuerCert))

		ra.CA = ca
		ra.SA = sa
		ra.VA = &va
		va.RA = &ra
		ca.SA = sa

		// Set up paths
		ra.AuthzBase = c.Common.BaseURL + wfe.AuthzPath
		wfei.BaseURL = c.Common.BaseURL
		h := wfei.Handler()

		ra.MaxKeySize = c.Common.MaxKeySize
		ca.MaxKeySize = c.Common.MaxKeySize

		auditlogger.Info(app.VersionString())

		fmt.Fprintf(os.Stderr, "Server running, listening on %s...\n", c.WFE.ListenAddress)
		err = http.ListenAndServe(c.WFE.ListenAddress, HandlerTimer(h, stats))
		cmd.FailOnError(err, "Error starting HTTP server")
	}

	app.Run()
}
<commit_msg>Fix monolithic binary<commit_after>// Copyright 2014 ISRG.  All rights reserved
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package main

import (
	"fmt"
	"net/http"
	"os"
	"time"

	"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"

	"github.com/letsencrypt/boulder/ca"
	"github.com/letsencrypt/boulder/cmd"
	"github.com/letsencrypt/boulder/core"
	blog "github.com/letsencrypt/boulder/log"
	"github.com/letsencrypt/boulder/ra"
	"github.com/letsencrypt/boulder/sa"
	"github.com/letsencrypt/boulder/va"
	"github.com/letsencrypt/boulder/wfe"
)

type timedHandler struct {
	f     func(w http.ResponseWriter, r *http.Request)
	stats statsd.Statter
}

var openConnections int64

// HandlerTimer monitors HTTP performance and sends the details to StatsD.
func HandlerTimer(handler http.Handler, stats statsd.Statter) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		cStart := time.Now()
		openConnections++
		stats.Gauge("HttpConnectionsOpen", openConnections, 1.0)

		handler.ServeHTTP(w, r)

		openConnections--
		stats.Gauge("HttpConnectionsOpen", openConnections, 1.0)

		// (FIX: this doesn't seem to really work at catching errors...)
		state := "Success"
		for _, h := range w.Header()["Content-Type"] {
			if h == "application/problem+json" {
				state = "Error"
				break
			}
		}
		// set resp timing key based on success / failure
		stats.TimingDuration(fmt.Sprintf("HttpResponseTime.%s.%s", r.URL, state), time.Since(cStart), 1.0)
	})
}

func main() {
	app := cmd.NewAppShell("boulder")
	app.Action = func(c cmd.Config) {
		stats, err := statsd.NewClient(c.Statsd.Server, c.Statsd.Prefix)
		cmd.FailOnError(err, "Couldn't connect to statsd")

		// Set up logging
		auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
		cmd.FailOnError(err, "Could not connect to Syslog")

		// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
		defer auditlogger.AuditPanic()

		blog.SetAuditLogger(auditlogger)

		go cmd.DebugServer(c.Monolith.DebugAddr)

		// Run StatsD profiling
		go cmd.ProfileCmd("Monolith", stats)

		// Create the components
		wfei, err := wfe.NewWebFrontEndImpl()
		cmd.FailOnError(err, "Unable to create WFE")
		sa, err := sa.NewSQLStorageAuthority(c.SA.DBDriver, c.SA.DBConnect)
		cmd.FailOnError(err, "Unable to create SA")
		sa.SetSQLDebug(c.SQL.SQLDebug)

		wfei.CertCacheDuration, err = time.ParseDuration(c.WFE.CertCacheDuration)
		cmd.FailOnError(err, "Couldn't parse certificate caching duration")
		wfei.CertNoCacheExpirationWindow, err = time.ParseDuration(c.WFE.CertNoCacheExpirationWindow)
		cmd.FailOnError(err, "Couldn't parse certificate expiration no-cache window")
		wfei.IndexCacheDuration, err = time.ParseDuration(c.WFE.IndexCacheDuration)
		cmd.FailOnError(err, "Couldn't parse index caching duration")
		wfei.IssuerCacheDuration, err = time.ParseDuration(c.WFE.IssuerCacheDuration)
		cmd.FailOnError(err, "Couldn't parse issuer caching duration")

		dnsTimeout, err := time.ParseDuration(c.Common.DNSTimeout)
		cmd.FailOnError(err, "Couldn't parse DNS timeout")
		dnsResolver := core.NewDNSResolverImpl(dnsTimeout, []string{c.Common.DNSResolver})

		ra := ra.NewRegistrationAuthorityImpl()
		cmd.FailOnError(err, "Couldn't parse RA DNS timeout")
		ra.DNSResolver = dnsResolver

		va := va.NewValidationAuthorityImpl(c.CA.TestMode)
		va.DNSResolver = dnsResolver
		va.UserAgent = c.VA.UserAgent

		cadb, err := ca.NewCertificateAuthorityDatabaseImpl(c.CA.DBDriver, c.CA.DBConnect)
		cmd.FailOnError(err, "Failed to create CA database")

		ca, err := ca.NewCertificateAuthorityImpl(cadb, c.CA, c.Common.IssuerCert)
		cmd.FailOnError(err, "Unable to create CA")

		if c.SQL.CreateTables {
			err = sa.CreateTablesIfNotExists()
			cmd.FailOnError(err, "Failed to create SA tables")

			err = cadb.CreateTablesIfNotExists()
			cmd.FailOnError(err, "Failed to create CA tables")
		}

		// Wire them up
		wfei.RA = &ra
		wfei.SA = sa
		wfei.Stats = stats
		wfei.SubscriberAgreementURL = c.SubscriberAgreementURL

		wfei.IssuerCert, err = cmd.LoadCert(c.Common.IssuerCert)
		cmd.FailOnError(err, fmt.Sprintf("Couldn't read issuer cert [%s]", c.Common.IssuerCert))

		ra.CA = ca
		ra.SA = sa
		ra.VA = &va
		va.RA = &ra
		ca.SA = sa

		// Set up paths
		ra.AuthzBase = c.Common.BaseURL + wfe.AuthzPath
		wfei.BaseURL = c.Common.BaseURL
		h := wfei.Handler()

		ra.MaxKeySize = c.Common.MaxKeySize
		ca.MaxKeySize = c.Common.MaxKeySize

		auditlogger.Info(app.VersionString())

		fmt.Fprintf(os.Stderr, "Server running, listening on %s...\n", c.WFE.ListenAddress)
		err = http.ListenAndServe(c.WFE.ListenAddress, HandlerTimer(h, stats))
		cmd.FailOnError(err, "Error starting HTTP server")
	}

	app.Run()
}
<|endoftext|>