<commit_before>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !nacl

package websocket

import (
	"io"
	"net"
	"net/http"
	"sync"
	"time"

	"github.com/gorilla/websocket"

	"v.io/x/ref/internal/logger"
	"v.io/x/ref/runtime/protocols/lib/tcputil"

	"v.io/v23/context"
	"v.io/v23/flow"
)

const classificationTime = 10 * time.Second

// A listener that is able to handle either raw tcp or websocket requests.
type wsTCPListener struct {
	closed bool // GUARDED_BY(mu)
	mu     sync.Mutex

	acceptQ chan interface{} // flow.Conn or error returned by netLn.Accept
	httpQ   chan net.Conn    // Candidates for websocket upgrades before being added to acceptQ
	netLn   net.Listener     // The underlying listener
	httpReq sync.WaitGroup   // Number of active HTTP requests
	hybrid  bool             // true if running in 'hybrid' mode
}

func listener(protocol, address string, hybrid bool) (flow.Listener, error) {
	netLn, err := net.Listen(mapWebSocketToTCP[protocol], address)
	if err != nil {
		return nil, err
	}
	ln := &wsTCPListener{
		acceptQ: make(chan interface{}),
		httpQ:   make(chan net.Conn),
		netLn:   netLn,
		hybrid:  hybrid,
	}
	go ln.netAcceptLoop()
	httpsrv := http.Server{Handler: ln}
	go httpsrv.Serve(&chanListener{Listener: netLn, c: ln.httpQ}) //nolint:errcheck
	return ln, nil
}

func (ln *wsTCPListener) Accept(ctx *context.T) (flow.Conn, error) {
	for {
		item, ok := <-ln.acceptQ
		if !ok {
			return nil, NewErrListenerClosed(ctx)
		}
		switch v := item.(type) {
		case flow.Conn:
			return v, nil
		case error:
			return nil, v
		default:
			logger.Global().Errorf("Unexpected type %T in channel (%v)", v, v)
		}
	}
}

func (ln *wsTCPListener) Addr() net.Addr {
	protocol := "ws"
	if ln.hybrid {
		protocol = "wsh"
	}
	return addr{protocol, ln.netLn.Addr().String()}
}

func (ln *wsTCPListener) Close() error {
	ln.mu.Lock()
	if ln.closed {
		ln.mu.Unlock()
		return NewErrListenerClosed(nil)
	}
	ln.closed = true
	ln.mu.Unlock()
	addr := ln.netLn.Addr()
	err := ln.netLn.Close()
	logger.Global().VI(1).Infof("Closed net.Listener on (%q, %q): %v", addr.Network(), addr, err)
	// netAcceptLoop might be trying to push new TCP connections that
	// arrived while the listener was being closed. Drop those.
	drainChan(ln.acceptQ)
	return nil
}

func (ln *wsTCPListener) netAcceptLoop() {
	var classifications sync.WaitGroup
	defer func() {
		// This sequence of closures is carefully curated based on the
		// following invariants:
		// (1) All calls to ln.classify have been added to classifications.
		// (2) Only ln.classify sends on ln.httpQ
		// (3) All calls to ln.ServeHTTP have been added to ln.httpReq
		// (4) Sends on ln.acceptQ are done by either ln.netAcceptLoop ro ln.ServeHTTP
		classifications.Wait()
		close(ln.httpQ)
		ln.httpReq.Wait()
		close(ln.acceptQ)
	}()
	for {
		conn, err := ln.netLn.Accept()
		if err != nil {
			// If the listener has been closed, quit - otherwise
			// propagate the error.
			ln.mu.Lock()
			closed := ln.closed
			ln.mu.Unlock()
			if closed {
				return
			}
			ln.acceptQ <- err
			continue
		}
		logger.Global().VI(1).Infof("New net.Conn accepted from %s (local address: %s)", conn.RemoteAddr(), conn.LocalAddr())
		if err := tcputil.EnableTCPKeepAlive(conn); err != nil {
			logger.Global().Errorf("Failed to enable TCP keep alive: %v", err)
		}
		classifications.Add(1)
		go ln.classify(conn, &classifications)
	}
}

// classify classifies conn as either an HTTP connection or a non-HTTP one.
//
// If a non-HTTP, then the connection is added to ln.acceptQ.
// If a HTTP, then the connection is queued up for a websocket upgrade.
func (ln *wsTCPListener) classify(conn net.Conn, done *sync.WaitGroup) {
	defer done.Done()
	isHTTP := true
	if ln.hybrid {
		conn.SetReadDeadline(time.Now().Add(classificationTime)) //nolint:errcheck
		defer conn.SetReadDeadline(time.Time{})                  //nolint:errcheck
		var magic [1]byte
		n, err := io.ReadFull(conn, magic[:])
		if err != nil {
			// Unable to classify, ignore this connection.
			logger.Global().VI(1).Infof("Shutting down connection from %v since the magic bytes could not be read: %v", conn.RemoteAddr(), err)
			conn.Close()
			return
		}
		conn = &hybridConn{conn: conn, buffered: magic[:n]}
		isHTTP = magic[0] == 'G'
	}
	if isHTTP {
		ln.httpReq.Add(1)
		ln.httpQ <- conn
		return
	}
	ln.acceptQ <- tcputil.NewTCPConn(conn)
}

func (ln *wsTCPListener) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer ln.httpReq.Done()
	if r.Method != "GET" {
		http.Error(w, "Method not allowed.", http.StatusMethodNotAllowed)
		return
	}
	ws, err := websocket.Upgrade(w, r, nil, bufferSize, bufferSize)
	if _, ok := err.(websocket.HandshakeError); ok {
		// Close the connection to not serve HTTP requests from this connection
		// any more. Otherwise panic from negative httpReq counter can occur.
		// Although go http.Server gracefully shutdowns the server from a panic,
		// it would be nice to avoid it.
		w.Header().Set("Connection", "close")
		http.Error(w, "Not a websocket handshake", http.StatusBadRequest)
		logger.Global().Errorf("Rejected a non-websocket request: %v", err)
		return
	}
	if err != nil {
		w.Header().Set("Connection", "close")
		http.Error(w, "Internal Error", http.StatusInternalServerError)
		logger.Global().Errorf("Rejected a non-websocket request: %v", err)
		return
	}
	ln.acceptQ <- WebsocketConn(ws)
}

// chanListener implements net.Listener, with Accept reading from c.
type chanListener struct {
	net.Listener // Embedded for all other net.Listener functionality.
	c            <-chan net.Conn
}

func (ln *chanListener) Accept() (net.Conn, error) {
	conn, ok := <-ln.c
	if !ok {
		return nil, NewErrListenerClosed(nil)
	}
	return conn, nil
}

type addr struct{ n, a string }

func (a addr) Network() string { return a.n }
func (a addr) String() string  { return a.a }

func drainChan(c <-chan interface{}) {
	for {
		item, ok := <-c
		if !ok {
			return
		}
		if conn, ok := item.(flow.Conn); ok {
			conn.Close()
		}
	}
}
<commit_msg>x/ref/runtime/protocols/lib/websocket: reduce log noise due to monitoring connections (#134)<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !nacl

package websocket

import (
	"io"
	"net"
	"net/http"
	"sync"
	"time"

	"github.com/gorilla/websocket"

	"v.io/x/ref/internal/logger"
	"v.io/x/ref/runtime/protocols/lib/tcputil"

	"v.io/v23/context"
	"v.io/v23/flow"
)

const classificationTime = 10 * time.Second

// A listener that is able to handle either raw tcp or websocket requests.
type wsTCPListener struct {
	closed bool // GUARDED_BY(mu)
	mu     sync.Mutex

	acceptQ chan interface{} // flow.Conn or error returned by netLn.Accept
	httpQ   chan net.Conn    // Candidates for websocket upgrades before being added to acceptQ
	netLn   net.Listener     // The underlying listener
	httpReq sync.WaitGroup   // Number of active HTTP requests
	hybrid  bool             // true if running in 'hybrid' mode
}

func listener(protocol, address string, hybrid bool) (flow.Listener, error) {
	netLn, err := net.Listen(mapWebSocketToTCP[protocol], address)
	if err != nil {
		return nil, err
	}
	ln := &wsTCPListener{
		acceptQ: make(chan interface{}),
		httpQ:   make(chan net.Conn),
		netLn:   netLn,
		hybrid:  hybrid,
	}
	go ln.netAcceptLoop()
	httpsrv := http.Server{Handler: ln}
	go httpsrv.Serve(&chanListener{Listener: netLn, c: ln.httpQ}) //nolint:errcheck
	return ln, nil
}

func (ln *wsTCPListener) Accept(ctx *context.T) (flow.Conn, error) {
	for {
		item, ok := <-ln.acceptQ
		if !ok {
			return nil, NewErrListenerClosed(ctx)
		}
		switch v := item.(type) {
		case flow.Conn:
			return v, nil
		case error:
			return nil, v
		default:
			logger.Global().Errorf("Unexpected type %T in channel (%v)", v, v)
		}
	}
}

func (ln *wsTCPListener) Addr() net.Addr {
	protocol := "ws"
	if ln.hybrid {
		protocol = "wsh"
	}
	return addr{protocol, ln.netLn.Addr().String()}
}

func (ln *wsTCPListener) Close() error {
	ln.mu.Lock()
	if ln.closed {
		ln.mu.Unlock()
		return NewErrListenerClosed(nil)
	}
	ln.closed = true
	ln.mu.Unlock()
	addr := ln.netLn.Addr()
	err := ln.netLn.Close()
	logger.Global().VI(1).Infof("Closed net.Listener on (%q, %q): %v", addr.Network(), addr, err)
	// netAcceptLoop might be trying to push new TCP connections that
	// arrived while the listener was being closed. Drop those.
	drainChan(ln.acceptQ)
	return nil
}

func (ln *wsTCPListener) netAcceptLoop() {
	var classifications sync.WaitGroup
	defer func() {
		// This sequence of closures is carefully curated based on the
		// following invariants:
		// (1) All calls to ln.classify have been added to classifications.
		// (2) Only ln.classify sends on ln.httpQ
		// (3) All calls to ln.ServeHTTP have been added to ln.httpReq
		// (4) Sends on ln.acceptQ are done by either ln.netAcceptLoop ro ln.ServeHTTP
		classifications.Wait()
		close(ln.httpQ)
		ln.httpReq.Wait()
		close(ln.acceptQ)
	}()
	for {
		conn, err := ln.netLn.Accept()
		if err != nil {
			// If the listener has been closed, quit - otherwise
			// propagate the error.
			ln.mu.Lock()
			closed := ln.closed
			ln.mu.Unlock()
			if closed {
				return
			}
			ln.acceptQ <- err
			continue
		}
		logger.Global().VI(2).Infof("New net.Conn accepted from %s (local address: %s)", conn.RemoteAddr(), conn.LocalAddr())
		if err := tcputil.EnableTCPKeepAlive(conn); err != nil {
			logger.Global().Errorf("Failed to enable TCP keep alive for connection from %s (local address %s): %v", conn.RemoteAddr(), conn.LocalAddr(), err)
		}
		classifications.Add(1)
		go ln.classify(conn, &classifications)
	}
}

// classify classifies conn as either an HTTP connection or a non-HTTP one.
//
// If a non-HTTP, then the connection is added to ln.acceptQ.
// If a HTTP, then the connection is queued up for a websocket upgrade.
func (ln *wsTCPListener) classify(conn net.Conn, done *sync.WaitGroup) {
	defer done.Done()
	isHTTP := true
	if ln.hybrid {
		conn.SetReadDeadline(time.Now().Add(classificationTime)) //nolint:errcheck
		defer conn.SetReadDeadline(time.Time{})                  //nolint:errcheck
		var magic [1]byte
		n, err := io.ReadFull(conn, magic[:])
		if err != nil {
			// Unable to classify, ignore this connection.
			logger.Global().VI(2).Infof("Shutting down connection from %v since the magic bytes could not be read: %v", conn.RemoteAddr(), err)
			conn.Close()
			return
		}
		conn = &hybridConn{conn: conn, buffered: magic[:n]}
		isHTTP = magic[0] == 'G'
	}
	logger.Global().VI(1).Infof("New net.Conn accepted from %s (local address: %s), classified: isHTTP %v", conn.RemoteAddr(), conn.LocalAddr(), isHTTP)
	if isHTTP {
		ln.httpReq.Add(1)
		ln.httpQ <- conn
		return
	}
	ln.acceptQ <- tcputil.NewTCPConn(conn)
}

func (ln *wsTCPListener) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer ln.httpReq.Done()
	if r.Method != "GET" {
		http.Error(w, "Method not allowed.", http.StatusMethodNotAllowed)
		return
	}
	ws, err := websocket.Upgrade(w, r, nil, bufferSize, bufferSize)
	if _, ok := err.(websocket.HandshakeError); ok {
		// Close the connection to not serve HTTP requests from this connection
		// any more. Otherwise panic from negative httpReq counter can occur.
		// Although go http.Server gracefully shutdowns the server from a panic,
		// it would be nice to avoid it.
		w.Header().Set("Connection", "close")
		http.Error(w, "Not a websocket handshake", http.StatusBadRequest)
		logger.Global().Errorf("Rejected a non-websocket request: %v", err)
		return
	}
	if err != nil {
		w.Header().Set("Connection", "close")
		http.Error(w, "Internal Error", http.StatusInternalServerError)
		logger.Global().Errorf("Rejected a non-websocket request: %v", err)
		return
	}
	ln.acceptQ <- WebsocketConn(ws)
}

// chanListener implements net.Listener, with Accept reading from c.
type chanListener struct {
	net.Listener // Embedded for all other net.Listener functionality.
	c            <-chan net.Conn
}

func (ln *chanListener) Accept() (net.Conn, error) {
	conn, ok := <-ln.c
	if !ok {
		return nil, NewErrListenerClosed(nil)
	}
	return conn, nil
}

type addr struct{ n, a string }

func (a addr) Network() string { return a.n }
func (a addr) String() string  { return a.a }

func drainChan(c <-chan interface{}) {
	for {
		item, ok := <-c
		if !ok {
			return
		}
		if conn, ok := item.(flow.Conn); ok {
			conn.Close()
		}
	}
}
<|endoftext|>


<commit_before>package nail

import (
	"fmt"
	"log"
	"strings"

	"github.com/antihax/evedata/internal/datapackages"
	"github.com/antihax/evedata/internal/gobcoder"
	nsq "github.com/nsqio/go-nsq"
)

func init() {
	AddHandler("characterAssets", spawnCharacterAssetsConsumer)
}

func spawnCharacterAssetsConsumer(s *Nail, consumer *nsq.Consumer) {
	consumer.AddHandler(s.wait(nsq.HandlerFunc(s.characterAssetsConsumer)))
}

func (s *Nail) characterAssetsConsumer(message *nsq.Message) error {
	assets := datapackages.CharacterAssets{}
	err := gobcoder.GobDecoder(message.Body, &assets)
	if err != nil {
		log.Println(err)
		return err
	}
	if len(assets.Assets) == 0 {
		return nil
	}
	var values []string

	err = s.doSQL("DELETE FROM evedata.assets WHERE characterID = ?;", assets.TokenCharacterID)
	if err != nil {
		log.Println(err)
		return err
	}

	// Dump all assets into the DB.
	count := 0
	for _, asset := range assets.Assets {
		count++
		values = append(values, fmt.Sprintf("(%d,%d,%d,%d,%q,%d,%q,%v)",
			asset.LocationId, asset.TypeId, asset.Quantity, assets.TokenCharacterID,
			asset.LocationFlag, asset.ItemId, asset.LocationType, asset.IsSingleton))

		if count > 100 {
			err := s.doSQL(doAssets(values))
			if err != nil {
				return err
			}
			values = values[:0]
			count = 0
		}
	}

	stmt := doAssets(values)

	err = s.doSQL(stmt)
	if err != nil {
		log.Printf("%s %s\n", err, stmt)
		return err
	}

	return nil
}

func doAssets(values []string) string {
	return fmt.Sprintf(`INSERT INTO evedata.assets
		(locationID, typeID, quantity, characterID,
		locationFlag, itemID, locationType, isSingleton)
		VALUES %s
		ON DUPLICATE KEY UPDATE typeID = typeID;`, strings.Join(values, ",\n"))
}
<commit_msg>Debug<commit_after>package nail

import (
	"fmt"
	"log"
	"strings"

	"github.com/antihax/evedata/internal/datapackages"
	"github.com/antihax/evedata/internal/gobcoder"
	nsq "github.com/nsqio/go-nsq"
)

func init() {
	AddHandler("characterAssets", spawnCharacterAssetsConsumer)
}

func spawnCharacterAssetsConsumer(s *Nail, consumer *nsq.Consumer) {
	consumer.AddHandler(s.wait(nsq.HandlerFunc(s.characterAssetsConsumer)))
}

func (s *Nail) characterAssetsConsumer(message *nsq.Message) error {
	assets := datapackages.CharacterAssets{}
	err := gobcoder.GobDecoder(message.Body, &assets)
	if err != nil {
		log.Println(err)
		return err
	}
	if len(assets.Assets) == 0 {
		return nil
	}
	var values []string

	err = s.doSQL("DELETE FROM evedata.assets WHERE characterID = ?;", assets.TokenCharacterID)
	if err != nil {
		log.Println(err)
		return err
	}

	// Dump all assets into the DB.
	count := 0
	for _, asset := range assets.Assets {
		count++
		values = append(values, fmt.Sprintf("(%d,%d,%d,%d,%q,%d,%q,%v)",
			asset.LocationId, asset.TypeId, asset.Quantity, assets.TokenCharacterID,
			asset.LocationFlag, asset.ItemId, asset.LocationType, asset.IsSingleton))
	}

	stmt := doAssets(values)

	err = s.doSQL(stmt)
	if err != nil {
		log.Printf("%s %s\n", err, stmt)
		return err
	}

	return nil
}

func doAssets(values []string) string {
	return fmt.Sprintf(`INSERT INTO evedata.assets
		(locationID, typeID, quantity, characterID,
		locationFlag, itemID, locationType, isSingleton)
		VALUES %s
		ON DUPLICATE KEY UPDATE typeID = typeID;`, strings.Join(values, ",\n"))
}
<|endoftext|>


<commit_before>package modelhelper

import (
	"koding/db/models"

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

type Bongo struct {
	ConstructorName string `json:"constructorName"`
	InstanceId      string `json:"instanceId"`
}

type MachineContainer struct {
	Bongo Bongo           `json:"bongo_"`
	Data  *models.Machine `json:"data"`
	*models.Machine
}

var (
	MachineColl            = "jMachines"
	MachineConstructorName = "JMachine"
)

func GetMachines(userId bson.ObjectId) ([]*MachineContainer, error) {
	machines := []*models.Machine{}

	query := func(c *mgo.Collection) error {
		return c.Find(bson.M{"users.id": userId}).All(&machines)
	}

	err := Mongo.Run(MachineColl, query)
	if err != nil {
		return nil, err
	}

	containers := []*MachineContainer{}

	for _, machine := range machines {
		bongo := Bongo{
			ConstructorName: MachineConstructorName,
			InstanceId:      "1", // TODO: what should go here?
		}
		container := &MachineContainer{bongo, machine, machine}

		containers = append(containers, container)
	}

	return containers, nil
}

var (
	MachineStateRunning = "Running"
)

func GetRunningVms() ([]models.Machine, error) {
	machines := []models.Machine{}

	query := func(c *mgo.Collection) error {
		iter := c.Find(bson.M{"status.state": MachineStateRunning}).Iter()

		var machine models.Machine
		for iter.Next(&machine) {
			machines = append(machines, machine)
		}

		return nil
	}

	err := Mongo.Run(MachineColl, query)
	if err != nil {
		return nil, err
	}

	return machines, nil
}

// GetMachineByUid returns the machine by its uid field
func GetMachineByUid(uid string) (*models.Machine, error) {
	machine := &models.Machine{}

	query := func(c *mgo.Collection) error {
		return c.Find(bson.M{"uid": uid}).One(machine)
	}

	err := Mongo.Run(MachineColl, query)
	if err != nil {
		return nil, err
	}

	return machine, nil
}

// UnshareMachineByUid unshares the machine from all other users except the
// owner
func UnshareMachineByUid(uid string) error {
	machine, err := GetMachineByUid(uid)
	if err != nil {
		return err
	}

	owner := make([]models.MachineUser, 1)
	for _, user := range machine.Users {
		// this is the correct way to remove all users but the owner from a
		// machine
		if user.Sudo && user.Owner {
			owner[0] = user
			break
		}
	}

	if len(owner) == 0 {
		return errors.New("owner couldnt found")
	}

	s := Selector{"_id": machine.ObjectId}
	o := Selector{"$set": Selector{
		"users": owner,
	}}

	query := func(c *mgo.Collection) error {
		return c.Update(s, o)
	}

	return Mongo.Run(MachineColl, query)
}

func GetMachinesByUsername(username string) ([]*models.Machine, error) {
	user, err := GetUser(username)
	if err != nil {
		return nil, err
	}

	machines := []*models.Machine{}

	query := func(c *mgo.Collection) error {
		return c.Find(
			bson.M{"provider": "koding", "users.id": user.ObjectId, "users.sudo": true},
		).All(&machines)
	}

	err = Mongo.Run(MachineColl, query)
	if err != nil {
		return nil, err
	}

	return machines, nil
}

func CreateMachine(m *models.Machine) error {
	query := func(c *mgo.Collection) error {
		return c.Insert(m)
	}

	return Mongo.Run(MachineColl, query)
}

func UpdateMachineAlwaysOn(machineId bson.ObjectId, alwaysOn bool) error {
	query := func(c *mgo.Collection) error {
		return c.Update(
			bson.M{"_id": machineId},
			bson.M{"$set": bson.M{"meta.alwaysOn": alwaysOn}},
		)
	}

	return Mongo.Run("jMachines", query)
}
<commit_msg>koding/model: implemented DeleteMachine function for removing the machine from db<commit_after>package modelhelper

import (
	"errors"
	"koding/db/models"

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

type Bongo struct {
	ConstructorName string `json:"constructorName"`
	InstanceId      string `json:"instanceId"`
}

type MachineContainer struct {
	Bongo Bongo           `json:"bongo_"`
	Data  *models.Machine `json:"data"`
	*models.Machine
}

var (
	MachineColl            = "jMachines"
	MachineConstructorName = "JMachine"
)

func GetMachines(userId bson.ObjectId) ([]*MachineContainer, error) {
	machines := []*models.Machine{}

	query := func(c *mgo.Collection) error {
		return c.Find(bson.M{"users.id": userId}).All(&machines)
	}

	err := Mongo.Run(MachineColl, query)
	if err != nil {
		return nil, err
	}

	containers := []*MachineContainer{}

	for _, machine := range machines {
		bongo := Bongo{
			ConstructorName: MachineConstructorName,
			InstanceId:      "1", // TODO: what should go here?
		}
		container := &MachineContainer{bongo, machine, machine}

		containers = append(containers, container)
	}

	return containers, nil
}

var (
	MachineStateRunning = "Running"
)

func GetRunningVms() ([]models.Machine, error) {
	machines := []models.Machine{}

	query := func(c *mgo.Collection) error {
		iter := c.Find(bson.M{"status.state": MachineStateRunning}).Iter()

		var machine models.Machine
		for iter.Next(&machine) {
			machines = append(machines, machine)
		}

		return nil
	}

	err := Mongo.Run(MachineColl, query)
	if err != nil {
		return nil, err
	}

	return machines, nil
}

// GetMachineByUid returns the machine by its uid field
func GetMachineByUid(uid string) (*models.Machine, error) {
	machine := &models.Machine{}

	query := func(c *mgo.Collection) error {
		return c.Find(bson.M{"uid": uid}).One(machine)
	}

	err := Mongo.Run(MachineColl, query)
	if err != nil {
		return nil, err
	}

	return machine, nil
}

// UnshareMachineByUid unshares the machine from all other users except the
// owner
func UnshareMachineByUid(uid string) error {
	machine, err := GetMachineByUid(uid)
	if err != nil {
		return err
	}

	owner := make([]models.MachineUser, 1)
	for _, user := range machine.Users {
		// this is the correct way to remove all users but the owner from a
		// machine
		if user.Sudo && user.Owner {
			owner[0] = user
			break
		}
	}

	if len(owner) == 0 {
		return errors.New("owner couldnt found")
	}

	s := Selector{"_id": machine.ObjectId}
	o := Selector{"$set": Selector{
		"users": owner,
	}}

	query := func(c *mgo.Collection) error {
		return c.Update(s, o)
	}

	return Mongo.Run(MachineColl, query)
}

func GetMachinesByUsername(username string) ([]*models.Machine, error) {
	user, err := GetUser(username)
	if err != nil {
		return nil, err
	}

	machines := []*models.Machine{}

	query := func(c *mgo.Collection) error {
		return c.Find(
			bson.M{"provider": "koding", "users.id": user.ObjectId, "users.sudo": true},
		).All(&machines)
	}

	err = Mongo.Run(MachineColl, query)
	if err != nil {
		return nil, err
	}

	return machines, nil
}

func CreateMachine(m *models.Machine) error {
	query := func(c *mgo.Collection) error {
		return c.Insert(m)
	}

	return Mongo.Run(MachineColl, query)
}

// DeleteMachine deletes the machine from mongodb, it is here just for cleaning
// purposes(after tests), machines should not be removed from database  unless
// you are kloud
func DeleteMachine(id bson.ObjectId) error {
	selector := bson.M{"_id": id}

	query := func(c *mgo.Collection) error {
		return c.Remove(selector)
	}

	return Mongo.Run(MachineColl, query)
}

func UpdateMachineAlwaysOn(machineId bson.ObjectId, alwaysOn bool) error {
	query := func(c *mgo.Collection) error {
		return c.Update(
			bson.M{"_id": machineId},
			bson.M{"$set": bson.M{"meta.alwaysOn": alwaysOn}},
		)
	}

	return Mongo.Run(MachineColl, query)
}
<|endoftext|>


<commit_before>package aws

import (
	"bytes"
	"fmt"
	"strconv"
	"text/template"
	"time"

	"koding/kites/kloud/api/amazon"
	"koding/kites/kloud/stack"
	"koding/kites/kloud/stack/provider"
	"koding/kites/kloud/userdata"
)

//go:generate $GOPATH/bin/go-bindata -mode 420 -modtime 1470666525 -pkg aws -o bootstrap.json.tmpl.go bootstrap.json.tmpl
//go:generate go fmt bootstrap.json.tmpl.go

var bootstrap = template.Must(template.New("").Parse(mustAsset("bootstrap.json.tmpl")))

type bootstrapConfig struct {
	AvailabilityZone string
	KeyPairName      string
	PublicKey        string
	EnvironmentName  string
}

// Stack implements the stackplan.Stack interface.
type Stack struct {
	*provider.BaseStack
}

var (
	_ provider.Stack = (*Stack)(nil) // public API
	_ stack.Stacker  = (*Stack)(nil) // internal API
)

func (s *Stack) VerifyCredential(c *stack.Credential) error {
	cred := c.Credential.(*Cred)

	if err := cred.Valid(); err != nil {
		return err
	}

	_, err := amazon.NewClient(cred.Options())
	return err
}

func (s *Stack) BootstrapTemplates(c *stack.Credential) ([]*stack.Template, error) {
	cred := c.Credential.(*Cred)

	opts := cred.Options()
	opts.Log = s.Log.New("amazon")

	cfg := &bootstrapConfig{
		AvailabilityZone: "${lookup(var.aws_availability_zones, var.aws_region)}",
		KeyPairName:      fmt.Sprintf("koding-deployment-%s-%s-%d", s.Req.Username, s.BootstrapArg().GroupName, time.Now().UTC().UnixNano()),
		PublicKey:        s.Keys.PublicKey,
		EnvironmentName:  fmt.Sprintf("Koding-%s-Bootstrap", s.BootstrapArg().GroupName),
	}

	if client, err := amazon.NewClient(opts); err == nil && len(client.Zones) != 0 {
		cfg.AvailabilityZone = client.Zones[0]
	} else {
		s.Log.Warning("unable to guess availability zones for %q: %s", c.Identifier, err)
	}

	t, err := newBootstrapTemplate(cfg)
	if err != nil {
		return nil, err
	}

	if accountID, err := cred.AccountID(); err == nil {
		t.Key = accountID + "-" + s.BootstrapArg().GroupName + "-" + c.Identifier
	} else {
		s.Log.Warning("unable to read account ID for %q: %s", c.Identifier, err)
	}

	s.Log.Debug("bootstrap template key: %q", t.Key)

	return []*stack.Template{t}, nil
}

func (s *Stack) ApplyTemplate(c *stack.Credential) (*stack.Template, error) {
	t := s.Builder.Template
	cred := c.Credential.(*Cred)
	bootstrap := c.Bootstrap.(*Bootstrap)

	if err := s.SetAwsRegion(cred.Region); err != nil {
		return nil, err
	}

	var resource struct {
		AwsInstance map[string]map[string]interface{} `hcl:"aws_instance"`
	}

	if err := t.DecodeResource(&resource); err != nil {
		return nil, err
	}

	if len(resource.AwsInstance) == 0 {
		return nil, fmt.Errorf("instances are empty: %v", resource.AwsInstance)
	}

	for resourceName, instance := range resource.AwsInstance {
		// Do not overwrite SSH key pair with the bootstrap one
		// when user sets it explicitly in a template.
		if s, ok := instance["key_name"]; !ok || s == "" {
			instance["key_name"] = bootstrap.KeyPair
		}

		// if nothing is provided or the ami is empty use default Ubuntu AMI's
		if a, ok := instance["ami"]; !ok {
			instance["ami"] = bootstrap.AMI
		} else {
			if ami, ok := a.(string); ok && ami == "" {
				instance["ami"] = bootstrap.AMI
			}
		}

		// only ovveride if the user doesn't provider it's own subnet_id
		if instance["subnet_id"] == nil {
			instance["subnet_id"] = bootstrap.Subnet
			instance["security_groups"] = []string{bootstrap.SG}
		}

		// means there will be several instances, we need to create a userdata
		// with count interpolation, because each machine must have an unique
		// kite id.
		count := 1
		if n, ok := instance["count"].(int); ok && n > 1 {
			count = n
		}

		labels := []string{resourceName}
		if count > 1 {
			for i := 0; i < count; i++ {
				labels = append(labels, fmt.Sprintf("%s.%d", resourceName, i))
			}
		}

		// TODO(rjeczalik): move to stackplan
		if b, ok := instance["debug"].(bool); ok && b {
			s.Debug = true
			delete(instance, "debug")
		}

		kiteKeyName := fmt.Sprintf("kitekeys_%s", resourceName)

		s.Builder.InterpolateField(instance, resourceName, "user_data")

		// this part will be the same for all machines
		userCfg := &userdata.CloudInitConfig{
			Username: s.Req.Username,
			Groups:   []string{"sudo"},
			Hostname: s.Req.Username, // no typo here. hostname = username
			KiteKey:  fmt.Sprintf("${lookup(var.%s, count.index)}", kiteKeyName),
		}

		if s, ok := instance["user_data"].(string); ok {
			userCfg.UserData = s
		}

		userdata, err := s.Session.Userdata.Create(userCfg)
		if err != nil {
			return nil, err
		}

		instance["user_data"] = string(userdata)

		// create independent kiteKey for each machine and create a Terraform
		// lookup map, which is used in conjuctuon with the `count.index`
		countKeys := make(map[string]string, count)
		for i, label := range labels {
			kiteKey, err := s.BuildKiteKey(label, s.Req.Username)
			if err != nil {
				return nil, err
			}

			countKeys[strconv.Itoa(i)] = kiteKey
		}

		t.Variable[kiteKeyName] = map[string]interface{}{
			"default": countKeys,
		}

		resource.AwsInstance[resourceName] = instance
	}

	t.Resource["aws_instance"] = resource.AwsInstance

	if err := t.Flush(); err != nil {
		return nil, err
	}

	// TODO(rjeczalik): move to stackplan
	err := t.ShadowVariables("FORBIDDEN", "aws_access_key", "aws_secret_key")
	if err != nil {
		return nil, err
	}

	content, err := t.JsonOutput()
	if err != nil {
		return nil, err
	}

	return &stack.Template{
		Content: content,
	}, nil
}

func (s *Stack) SetAwsRegion(region string) error {
	t := s.Builder.Template

	var p struct {
		Aws struct {
			Region    string `hcl:"region"`
			AccessKey string `hcl:"access_key"`
			SecretKey string `hcl:"secret_key"`
		}
	}

	if err := t.DecodeProvider(&p); err != nil {
		return err
	}

	if p.Aws.Region == "" {
		t.Provider["aws"] = map[string]interface{}{
			"region":     region,
			"access_key": p.Aws.AccessKey,
			"secret_key": p.Aws.SecretKey,
		}
	} else if !provider.IsVariable(p.Aws.Region) && p.Aws.Region != region {
		return fmt.Errorf("region is already set as '%s'. Can't override it with: %s",
			p.Aws.Region, region)
	}

	return t.Flush()
}

func (s *Stack) Credential() *Cred {
	return s.BaseStack.Credential.(*Cred)
}

func (s *Stack) Bootstrap() *Bootstrap {
	return s.BaseStack.Bootstrap.(*Bootstrap)
}

func (s *Stack) BootstrapArg() *stack.BootstrapRequest {
	return s.BaseStack.Arg.(*stack.BootstrapRequest)
}

func mustAsset(s string) string {
	p, err := Asset(s)
	if err != nil {
		panic(err)
	}
	return string(p)
}

func newBootstrapTemplate(cfg *bootstrapConfig) (*stack.Template, error) {
	var buf bytes.Buffer

	if err := bootstrap.Execute(&buf, cfg); err != nil {
		return nil, err
	}

	return &stack.Template{
		Content: buf.String(),
	}, nil
}
<commit_msg>provider/aws: fix labeling instances<commit_after>package aws

import (
	"bytes"
	"fmt"
	"strconv"
	"text/template"
	"time"

	"koding/kites/kloud/api/amazon"
	"koding/kites/kloud/stack"
	"koding/kites/kloud/stack/provider"
	"koding/kites/kloud/userdata"
)

//go:generate $GOPATH/bin/go-bindata -mode 420 -modtime 1470666525 -pkg aws -o bootstrap.json.tmpl.go bootstrap.json.tmpl
//go:generate go fmt bootstrap.json.tmpl.go

var bootstrap = template.Must(template.New("").Parse(mustAsset("bootstrap.json.tmpl")))

type bootstrapConfig struct {
	AvailabilityZone string
	KeyPairName      string
	PublicKey        string
	EnvironmentName  string
}

// Stack implements the stackplan.Stack interface.
type Stack struct {
	*provider.BaseStack
}

var (
	_ provider.Stack = (*Stack)(nil) // public API
	_ stack.Stacker  = (*Stack)(nil) // internal API
)

func (s *Stack) VerifyCredential(c *stack.Credential) error {
	cred := c.Credential.(*Cred)

	if err := cred.Valid(); err != nil {
		return err
	}

	_, err := amazon.NewClient(cred.Options())
	return err
}

func (s *Stack) BootstrapTemplates(c *stack.Credential) ([]*stack.Template, error) {
	cred := c.Credential.(*Cred)

	opts := cred.Options()
	opts.Log = s.Log.New("amazon")

	cfg := &bootstrapConfig{
		AvailabilityZone: "${lookup(var.aws_availability_zones, var.aws_region)}",
		KeyPairName:      fmt.Sprintf("koding-deployment-%s-%s-%d", s.Req.Username, s.BootstrapArg().GroupName, time.Now().UTC().UnixNano()),
		PublicKey:        s.Keys.PublicKey,
		EnvironmentName:  fmt.Sprintf("Koding-%s-Bootstrap", s.BootstrapArg().GroupName),
	}

	if client, err := amazon.NewClient(opts); err == nil && len(client.Zones) != 0 {
		cfg.AvailabilityZone = client.Zones[0]
	} else {
		s.Log.Warning("unable to guess availability zones for %q: %s", c.Identifier, err)
	}

	t, err := newBootstrapTemplate(cfg)
	if err != nil {
		return nil, err
	}

	if accountID, err := cred.AccountID(); err == nil {
		t.Key = accountID + "-" + s.BootstrapArg().GroupName + "-" + c.Identifier
	} else {
		s.Log.Warning("unable to read account ID for %q: %s", c.Identifier, err)
	}

	s.Log.Debug("bootstrap template key: %q", t.Key)

	return []*stack.Template{t}, nil
}

func (s *Stack) ApplyTemplate(c *stack.Credential) (*stack.Template, error) {
	t := s.Builder.Template
	cred := c.Credential.(*Cred)
	bootstrap := c.Bootstrap.(*Bootstrap)

	if err := s.SetAwsRegion(cred.Region); err != nil {
		return nil, err
	}

	var resource struct {
		AwsInstance map[string]map[string]interface{} `hcl:"aws_instance"`
	}

	if err := t.DecodeResource(&resource); err != nil {
		return nil, err
	}

	if len(resource.AwsInstance) == 0 {
		return nil, fmt.Errorf("instances are empty: %v", resource.AwsInstance)
	}

	for resourceName, instance := range resource.AwsInstance {
		// Do not overwrite SSH key pair with the bootstrap one
		// when user sets it explicitly in a template.
		if s, ok := instance["key_name"]; !ok || s == "" {
			instance["key_name"] = bootstrap.KeyPair
		}

		// if nothing is provided or the ami is empty use default Ubuntu AMI's
		if a, ok := instance["ami"]; !ok {
			instance["ami"] = bootstrap.AMI
		} else {
			if ami, ok := a.(string); ok && ami == "" {
				instance["ami"] = bootstrap.AMI
			}
		}

		// only ovveride if the user doesn't provider it's own subnet_id
		if instance["subnet_id"] == nil {
			instance["subnet_id"] = bootstrap.Subnet
			instance["security_groups"] = []string{bootstrap.SG}
		}

		// means there will be several instances, we need to create a userdata
		// with count interpolation, because each machine must have an unique
		// kite id.
		count := 1
		if n, ok := instance["count"].(int); ok && n > 1 {
			count = n
		}

		var labels []string
		if count > 1 {
			for i := 0; i < count; i++ {
				labels = append(labels, fmt.Sprintf("%s.%d", resourceName, i))
			}
		} else {
			labels = append(labels, resourceName)
		}

		// TODO(rjeczalik): move to stackplan
		if b, ok := instance["debug"].(bool); ok && b {
			s.Debug = true
			delete(instance, "debug")
		}

		kiteKeyName := fmt.Sprintf("kitekeys_%s", resourceName)

		s.Builder.InterpolateField(instance, resourceName, "user_data")

		// this part will be the same for all machines
		userCfg := &userdata.CloudInitConfig{
			Username: s.Req.Username,
			Groups:   []string{"sudo"},
			Hostname: s.Req.Username, // no typo here. hostname = username
			KiteKey:  fmt.Sprintf("${lookup(var.%s, count.index)}", kiteKeyName),
		}

		if s, ok := instance["user_data"].(string); ok {
			userCfg.UserData = s
		}

		userdata, err := s.Session.Userdata.Create(userCfg)
		if err != nil {
			return nil, err
		}

		instance["user_data"] = string(userdata)

		// create independent kiteKey for each machine and create a Terraform
		// lookup map, which is used in conjuctuon with the `count.index`
		countKeys := make(map[string]string, count)
		for i, label := range labels {
			kiteKey, err := s.BuildKiteKey(label, s.Req.Username)
			if err != nil {
				return nil, err
			}

			countKeys[strconv.Itoa(i)] = kiteKey
		}

		t.Variable[kiteKeyName] = map[string]interface{}{
			"default": countKeys,
		}

		resource.AwsInstance[resourceName] = instance
	}

	t.Resource["aws_instance"] = resource.AwsInstance

	if err := t.Flush(); err != nil {
		return nil, err
	}

	// TODO(rjeczalik): move to stackplan
	err := t.ShadowVariables("FORBIDDEN", "aws_access_key", "aws_secret_key")
	if err != nil {
		return nil, err
	}

	content, err := t.JsonOutput()
	if err != nil {
		return nil, err
	}

	return &stack.Template{
		Content: content,
	}, nil
}

func (s *Stack) SetAwsRegion(region string) error {
	t := s.Builder.Template

	var p struct {
		Aws struct {
			Region    string `hcl:"region"`
			AccessKey string `hcl:"access_key"`
			SecretKey string `hcl:"secret_key"`
		}
	}

	if err := t.DecodeProvider(&p); err != nil {
		return err
	}

	if p.Aws.Region == "" {
		t.Provider["aws"] = map[string]interface{}{
			"region":     region,
			"access_key": p.Aws.AccessKey,
			"secret_key": p.Aws.SecretKey,
		}
	} else if !provider.IsVariable(p.Aws.Region) && p.Aws.Region != region {
		return fmt.Errorf("region is already set as '%s'. Can't override it with: %s",
			p.Aws.Region, region)
	}

	return t.Flush()
}

func (s *Stack) Credential() *Cred {
	return s.BaseStack.Credential.(*Cred)
}

func (s *Stack) Bootstrap() *Bootstrap {
	return s.BaseStack.Bootstrap.(*Bootstrap)
}

func (s *Stack) BootstrapArg() *stack.BootstrapRequest {
	return s.BaseStack.Arg.(*stack.BootstrapRequest)
}

func mustAsset(s string) string {
	p, err := Asset(s)
	if err != nil {
		panic(err)
	}
	return string(p)
}

func newBootstrapTemplate(cfg *bootstrapConfig) (*stack.Template, error) {
	var buf bytes.Buffer

	if err := bootstrap.Execute(&buf, cfg); err != nil {
		return nil, err
	}

	return &stack.Template{
		Content: buf.String(),
	}, nil
}
<|endoftext|>


<commit_before>package object

import "reflect"

// Merge overwrites fields in v1 with a value of complementary
// field in v2, if the field in v2 is non-empty.
func Merge(v1, v2 interface{}) {
	vv2 := reflect.ValueOf(v2).Elem()
	if !vv2.IsValid() {
		return
	}
	vv1 := reflect.ValueOf(v1).Elem()
	for i := 0; i < vv1.NumField(); i++ {
		field := vv2.Field(i)
		var empty bool
		switch field.Type().Kind() {
		case reflect.Chan, reflect.Func, reflect.Slice, reflect.Map:
			empty = field.IsNil()
		default:
			empty = field.Interface() == reflect.Zero(field.Type()).Interface()
		}
		if !empty {
			vv1.Field(i).Set(vv2.Field(i))
		}
	}
}
<commit_msg>object: ensure arguments are of the same type in Merge<commit_after>package object

import "reflect"

// Merge overwrites fields in v1 with a value of complementary
// field in v2, if the field in v2 is non-empty.
//
// TODO(rjeczalik): Does not not merge struct fields
// recursively yet.
func Merge(v1, v2 interface{}) {
	vv1 := reflect.ValueOf(v1)
	if vv1.Kind() == reflect.Ptr {
		vv1 = vv1.Elem()
	}

	vv2 := reflect.ValueOf(v2)
	if vv2.Kind() == reflect.Ptr {
		vv2 = vv2.Elem()
	}

	if !vv2.IsValid() {
		return
	}

	if vv1.Type() != vv2.Type() {
		return
	}

	for i := 0; i < vv1.NumField(); i++ {
		field := vv2.Field(i)
		var empty bool
		switch field.Type().Kind() {
		case reflect.Chan, reflect.Func, reflect.Slice, reflect.Map:
			empty = field.IsNil()
		default:
			empty = field.Interface() == reflect.Zero(field.Type()).Interface()
		}
		if !empty {
			vv1.Field(i).Set(vv2.Field(i))
		}
	}
}
<|endoftext|>


<commit_before>package system

import (
	boshlog "bosh/logger"
	"bytes"
	"github.com/stretchr/testify/assert"
	"io"
	"os"
	"path/filepath"
	"testing"
)

func TestHomeDir(t *testing.T) {
	osFs := createOsFs()

	homeDir, err := osFs.HomeDir("root")
	assert.NoError(t, err)
	assert.Contains(t, homeDir, "/root")
}

func TestMkdirAll(t *testing.T) {
	osFs := createOsFs()
	tmpPath := os.TempDir()
	testPath := filepath.Join(tmpPath, "MkdirAllTestDir", "bar", "baz")
	defer os.RemoveAll(filepath.Join(tmpPath, "MkdirAllTestDir"))

	_, err := os.Stat(testPath)
	assert.Error(t, err)
	assert.True(t, os.IsNotExist(err))

	fileMode := os.FileMode(0700)

	err = osFs.MkdirAll(testPath, fileMode)
	assert.NoError(t, err)

	stat, err := os.Stat(testPath)
	assert.NoError(t, err)
	assert.True(t, stat.IsDir())
	assert.Equal(t, stat.Mode().Perm(), fileMode)
}

func TestChown(t *testing.T) {
	osFs := createOsFs()
	testPath := filepath.Join(os.TempDir(), "ChownTestDir")

	err := os.Mkdir(testPath, os.FileMode(0700))
	assert.NoError(t, err)
	defer os.RemoveAll(testPath)

	err = osFs.Chown(testPath, "root")
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "not permitted")
}

func TestChmod(t *testing.T) {
	osFs := createOsFs()
	testPath := filepath.Join(os.TempDir(), "ChmodTestDir")

	_, err := os.Create(testPath)
	assert.NoError(t, err)
	defer os.Remove(testPath)

	os.Chmod(testPath, os.FileMode(0666))

	err = osFs.Chmod(testPath, os.FileMode(0644))
	assert.NoError(t, err)

	fileStat, err := os.Stat(testPath)
	assert.NoError(t, err)
	assert.Equal(t, fileStat.Mode(), os.FileMode(0644))
}

func TestWriteToFile(t *testing.T) {
	osFs := createOsFs()
	testPath := filepath.Join(os.TempDir(), "subDir", "WriteToFileTestFile")

	_, err := os.Stat(testPath)
	assert.Error(t, err)

	written, err := osFs.WriteToFile(testPath, "initial write")
	assert.NoError(t, err)
	assert.True(t, written)
	defer os.Remove(testPath)

	file, err := os.Open(testPath)
	assert.NoError(t, err)
	defer file.Close()

	assert.Equal(t, readFile(file), "initial write")

	written, err = osFs.WriteToFile(testPath, "second write")
	assert.NoError(t, err)
	assert.True(t, written)

	file.Close()
	file, err = os.Open(testPath)
	assert.NoError(t, err)

	assert.Equal(t, readFile(file), "second write")

	file.Close()
	file, err = os.Open(testPath)

	written, err = osFs.WriteToFile(testPath, "second write")
	assert.NoError(t, err)
	assert.False(t, written)
	assert.Equal(t, readFile(file), "second write")
}

func TestReadFile(t *testing.T) {
	osFs := createOsFs()
	testPath := filepath.Join(os.TempDir(), "ReadFileTestFile")

	osFs.WriteToFile(testPath, "some contents")
	defer os.Remove(testPath)

	content, err := osFs.ReadFile(testPath)
	assert.NoError(t, err)
	assert.Equal(t, "some contents", content)
}

func TestFileExists(t *testing.T) {
	osFs := createOsFs()
	testPath := filepath.Join(os.TempDir(), "FileExistsTestFile")

	assert.False(t, osFs.FileExists(testPath))

	osFs.WriteToFile(testPath, "initial write")
	defer os.Remove(testPath)

	assert.True(t, osFs.FileExists(testPath))
}

func TestSymlink(t *testing.T) {
	osFs := createOsFs()
	filePath := filepath.Join(os.TempDir(), "SymlinkTestFile")
	symlinkPath := filepath.Join(os.TempDir(), "SymlinkTestSymlink")

	osFs.WriteToFile(filePath, "some content")
	defer os.Remove(filePath)

	osFs.Symlink(filePath, symlinkPath)
	defer os.Remove(symlinkPath)

	symlinkStats, err := os.Lstat(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, os.ModeSymlink, os.ModeSymlink&symlinkStats.Mode())

	symlinkFile, err := os.Open(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, "some content", readFile(symlinkFile))
}

func TestSymlinkWhenLinkAlreadyExistsAndLinksToTheIntendedPath(t *testing.T) {
	osFs := createOsFs()
	filePath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1File")
	symlinkPath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1Symlink")

	osFs.WriteToFile(filePath, "some content")
	defer os.Remove(filePath)

	osFs.Symlink(filePath, symlinkPath)
	defer os.Remove(symlinkPath)

	firstSymlinkStats, err := os.Lstat(symlinkPath)
	assert.NoError(t, err)

	err = osFs.Symlink(filePath, symlinkPath)
	assert.NoError(t, err)

	secondSymlinkStats, err := os.Lstat(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, firstSymlinkStats.ModTime(), secondSymlinkStats.ModTime())
}

func TestSymlinkWhenLinkAlreadyExistsAndDoesNotLinkToTheIntendedPath(t *testing.T) {
	osFs := createOsFs()
	filePath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1File")
	otherFilePath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1OtherFile")
	symlinkPath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1Symlink")

	osFs.WriteToFile(filePath, "some content")
	defer os.Remove(filePath)

	osFs.WriteToFile(otherFilePath, "other content")
	defer os.Remove(otherFilePath)

	err := osFs.Symlink(otherFilePath, symlinkPath)
	assert.NoError(t, err)

	// Repoints symlink to new destination
	err = osFs.Symlink(filePath, symlinkPath)
	assert.NoError(t, err)

	defer os.Remove(symlinkPath)

	symlinkStats, err := os.Lstat(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, os.ModeSymlink, os.ModeSymlink&symlinkStats.Mode())

	symlinkFile, err := os.Open(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, "some content", readFile(symlinkFile))
}

func TestSymlinkWhenAFileExistsAtIntendedPath(t *testing.T) {
	osFs := createOsFs()
	filePath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1File")
	symlinkPath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1Symlink")

	osFs.WriteToFile(filePath, "some content")
	defer os.Remove(filePath)

	osFs.WriteToFile(symlinkPath, "some other content")
	defer os.Remove(symlinkPath)

	// Repoints symlink to new destination
	err := osFs.Symlink(filePath, symlinkPath)
	assert.NoError(t, err)

	defer os.Remove(symlinkPath)

	symlinkStats, err := os.Lstat(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, os.ModeSymlink, os.ModeSymlink&symlinkStats.Mode())

	symlinkFile, err := os.Open(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, "some content", readFile(symlinkFile))
}

func createOsFs() (fs FileSystem) {
	logger := boshlog.NewLogger(boshlog.LEVEL_NONE)
	fs = NewOsFileSystem(logger)
	return
}

func readFile(file *os.File) string {
	buf := &bytes.Buffer{}
	_, err := io.Copy(buf, file)

	if err != nil {
		return ""
	}

	return string(buf.Bytes())
}
<commit_msg>added idempotency test for MkdirAll<commit_after>package system

import (
	boshlog "bosh/logger"
	"bytes"
	"github.com/stretchr/testify/assert"
	"io"
	"os"
	"path/filepath"
	"testing"
)

func TestHomeDir(t *testing.T) {
	osFs := createOsFs()

	homeDir, err := osFs.HomeDir("root")
	assert.NoError(t, err)
	assert.Contains(t, homeDir, "/root")
}

func TestMkdirAll(t *testing.T) {
	osFs := createOsFs()
	tmpPath := os.TempDir()
	testPath := filepath.Join(tmpPath, "MkdirAllTestDir", "bar", "baz")
	defer os.RemoveAll(filepath.Join(tmpPath, "MkdirAllTestDir"))

	_, err := os.Stat(testPath)
	assert.Error(t, err)
	assert.True(t, os.IsNotExist(err))

	fileMode := os.FileMode(0700)

	err = osFs.MkdirAll(testPath, fileMode)
	assert.NoError(t, err)

	stat, err := os.Stat(testPath)
	assert.NoError(t, err)
	assert.True(t, stat.IsDir())
	assert.Equal(t, stat.Mode().Perm(), fileMode)

	// check idempotency
	err = osFs.MkdirAll(testPath, fileMode)
	assert.NoError(t, err)
}

func TestChown(t *testing.T) {
	osFs := createOsFs()
	testPath := filepath.Join(os.TempDir(), "ChownTestDir")

	err := os.Mkdir(testPath, os.FileMode(0700))
	assert.NoError(t, err)
	defer os.RemoveAll(testPath)

	err = osFs.Chown(testPath, "root")
	assert.Error(t, err)
	assert.Contains(t, err.Error(), "not permitted")
}

func TestChmod(t *testing.T) {
	osFs := createOsFs()
	testPath := filepath.Join(os.TempDir(), "ChmodTestDir")

	_, err := os.Create(testPath)
	assert.NoError(t, err)
	defer os.Remove(testPath)

	os.Chmod(testPath, os.FileMode(0666))

	err = osFs.Chmod(testPath, os.FileMode(0644))
	assert.NoError(t, err)

	fileStat, err := os.Stat(testPath)
	assert.NoError(t, err)
	assert.Equal(t, fileStat.Mode(), os.FileMode(0644))
}

func TestWriteToFile(t *testing.T) {
	osFs := createOsFs()
	testPath := filepath.Join(os.TempDir(), "subDir", "WriteToFileTestFile")

	_, err := os.Stat(testPath)
	assert.Error(t, err)

	written, err := osFs.WriteToFile(testPath, "initial write")
	assert.NoError(t, err)
	assert.True(t, written)
	defer os.Remove(testPath)

	file, err := os.Open(testPath)
	assert.NoError(t, err)
	defer file.Close()

	assert.Equal(t, readFile(file), "initial write")

	written, err = osFs.WriteToFile(testPath, "second write")
	assert.NoError(t, err)
	assert.True(t, written)

	file.Close()
	file, err = os.Open(testPath)
	assert.NoError(t, err)

	assert.Equal(t, readFile(file), "second write")

	file.Close()
	file, err = os.Open(testPath)

	written, err = osFs.WriteToFile(testPath, "second write")
	assert.NoError(t, err)
	assert.False(t, written)
	assert.Equal(t, readFile(file), "second write")
}

func TestReadFile(t *testing.T) {
	osFs := createOsFs()
	testPath := filepath.Join(os.TempDir(), "ReadFileTestFile")

	osFs.WriteToFile(testPath, "some contents")
	defer os.Remove(testPath)

	content, err := osFs.ReadFile(testPath)
	assert.NoError(t, err)
	assert.Equal(t, "some contents", content)
}

func TestFileExists(t *testing.T) {
	osFs := createOsFs()
	testPath := filepath.Join(os.TempDir(), "FileExistsTestFile")

	assert.False(t, osFs.FileExists(testPath))

	osFs.WriteToFile(testPath, "initial write")
	defer os.Remove(testPath)

	assert.True(t, osFs.FileExists(testPath))
}

func TestSymlink(t *testing.T) {
	osFs := createOsFs()
	filePath := filepath.Join(os.TempDir(), "SymlinkTestFile")
	symlinkPath := filepath.Join(os.TempDir(), "SymlinkTestSymlink")

	osFs.WriteToFile(filePath, "some content")
	defer os.Remove(filePath)

	osFs.Symlink(filePath, symlinkPath)
	defer os.Remove(symlinkPath)

	symlinkStats, err := os.Lstat(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, os.ModeSymlink, os.ModeSymlink&symlinkStats.Mode())

	symlinkFile, err := os.Open(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, "some content", readFile(symlinkFile))
}

func TestSymlinkWhenLinkAlreadyExistsAndLinksToTheIntendedPath(t *testing.T) {
	osFs := createOsFs()
	filePath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1File")
	symlinkPath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1Symlink")

	osFs.WriteToFile(filePath, "some content")
	defer os.Remove(filePath)

	osFs.Symlink(filePath, symlinkPath)
	defer os.Remove(symlinkPath)

	firstSymlinkStats, err := os.Lstat(symlinkPath)
	assert.NoError(t, err)

	err = osFs.Symlink(filePath, symlinkPath)
	assert.NoError(t, err)

	secondSymlinkStats, err := os.Lstat(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, firstSymlinkStats.ModTime(), secondSymlinkStats.ModTime())
}

func TestSymlinkWhenLinkAlreadyExistsAndDoesNotLinkToTheIntendedPath(t *testing.T) {
	osFs := createOsFs()
	filePath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1File")
	otherFilePath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1OtherFile")
	symlinkPath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1Symlink")

	osFs.WriteToFile(filePath, "some content")
	defer os.Remove(filePath)

	osFs.WriteToFile(otherFilePath, "other content")
	defer os.Remove(otherFilePath)

	err := osFs.Symlink(otherFilePath, symlinkPath)
	assert.NoError(t, err)

	// Repoints symlink to new destination
	err = osFs.Symlink(filePath, symlinkPath)
	assert.NoError(t, err)

	defer os.Remove(symlinkPath)

	symlinkStats, err := os.Lstat(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, os.ModeSymlink, os.ModeSymlink&symlinkStats.Mode())

	symlinkFile, err := os.Open(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, "some content", readFile(symlinkFile))
}

func TestSymlinkWhenAFileExistsAtIntendedPath(t *testing.T) {
	osFs := createOsFs()
	filePath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1File")
	symlinkPath := filepath.Join(os.TempDir(), "SymlinkTestIdempotent1Symlink")

	osFs.WriteToFile(filePath, "some content")
	defer os.Remove(filePath)

	osFs.WriteToFile(symlinkPath, "some other content")
	defer os.Remove(symlinkPath)

	// Repoints symlink to new destination
	err := osFs.Symlink(filePath, symlinkPath)
	assert.NoError(t, err)

	defer os.Remove(symlinkPath)

	symlinkStats, err := os.Lstat(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, os.ModeSymlink, os.ModeSymlink&symlinkStats.Mode())

	symlinkFile, err := os.Open(symlinkPath)
	assert.NoError(t, err)
	assert.Equal(t, "some content", readFile(symlinkFile))
}

func createOsFs() (fs FileSystem) {
	logger := boshlog.NewLogger(boshlog.LEVEL_NONE)
	fs = NewOsFileSystem(logger)
	return
}

func readFile(file *os.File) string {
	buf := &bytes.Buffer{}
	_, err := io.Copy(buf, file)

	if err != nil {
		return ""
	}

	return string(buf.Bytes())
}
<|endoftext|>


<commit_before>package google

import (
	"fmt"
	"testing"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccComputeSslCertificate_basic(t *testing.T) {
	t.Parallel()

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckComputeSslCertificateDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccComputeSslCertificate_basic(),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckComputeSslCertificateExists(
						"google_compute_ssl_certificate.foobar"),
				),
			},
			resource.TestStep{
				ResourceName:            "google_compute_ssl_certificate.foobar",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"private_key"},
			},
		},
	})
}

func TestAccComputeSslCertificate_no_name(t *testing.T) {
	t.Parallel()

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckComputeSslCertificateDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccComputeSslCertificate_no_name(),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckComputeSslCertificateExists(
						"google_compute_ssl_certificate.foobar"),
				),
			},
			resource.TestStep{
				ResourceName:            "google_compute_ssl_certificate.foobar",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"private_key"},
			},
		},
	})
}

func TestAccComputeSslCertificate_name_prefix(t *testing.T) {
	t.Parallel()

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckComputeSslCertificateDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccComputeSslCertificate_name_prefix(),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckComputeSslCertificateExists(
						"google_compute_ssl_certificate.foobar"),
				),
			},
			resource.TestStep{
				ResourceName:            "google_compute_ssl_certificate.foobar",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"private_key, name_prefix"},
			},
		},
	})
}

func testAccCheckComputeSslCertificateDestroy(s *terraform.State) error {
	config := testAccProvider.Meta().(*Config)

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "google_compute_ssl_certificate" {
			continue
		}

		_, err := config.clientCompute.SslCertificates.Get(
			config.Project, rs.Primary.ID).Do()
		if err == nil {
			return fmt.Errorf("SslCertificate still exists")
		}
	}

	return nil
}

func testAccCheckComputeSslCertificateExists(n string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}

		config := testAccProvider.Meta().(*Config)

		found, err := config.clientCompute.SslCertificates.Get(
			config.Project, rs.Primary.ID).Do()
		if err != nil {
			return err
		}

		if found.Name != rs.Primary.ID {
			return fmt.Errorf("Certificate not found")
		}

		return nil
	}
}

func testAccComputeSslCertificate_basic() string {
	return fmt.Sprintf(`
resource "google_compute_ssl_certificate" "foobar" {
	name = "sslcert-test-%s"
	description = "very descriptive"
	private_key = "${file("test-fixtures/ssl_cert/test.key")}"
	certificate = "${file("test-fixtures/ssl_cert/test.crt")}"
}
`, acctest.RandString(10))
}

func testAccComputeSslCertificate_no_name() string {
	return fmt.Sprintf(`
resource "google_compute_ssl_certificate" "foobar" {
	description = "really descriptive"
	private_key = "${file("test-fixtures/ssl_cert/test.key")}"
	certificate = "${file("test-fixtures/ssl_cert/test.crt")}"
}
`)
}

func testAccComputeSslCertificate_name_prefix() string {
	return fmt.Sprintf(`
resource "google_compute_ssl_certificate" "foobar" {
	name_prefix = "sslcert-test-%s-"
	description = "extremely descriptive"
	private_key = "${file("test-fixtures/ssl_cert/test.key")}"
	certificate = "${file("test-fixtures/ssl_cert/test.crt")}"
}
`, acctest.RandString(10))
}
<commit_msg>Add missing quotation marks to compute_ssl_certificate tests (#2042)<commit_after>package google

import (
	"fmt"
	"testing"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccComputeSslCertificate_basic(t *testing.T) {
	t.Parallel()

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckComputeSslCertificateDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccComputeSslCertificate_basic(),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckComputeSslCertificateExists(
						"google_compute_ssl_certificate.foobar"),
				),
			},
			resource.TestStep{
				ResourceName:            "google_compute_ssl_certificate.foobar",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"private_key"},
			},
		},
	})
}

func TestAccComputeSslCertificate_no_name(t *testing.T) {
	t.Parallel()

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckComputeSslCertificateDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccComputeSslCertificate_no_name(),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckComputeSslCertificateExists(
						"google_compute_ssl_certificate.foobar"),
				),
			},
			resource.TestStep{
				ResourceName:            "google_compute_ssl_certificate.foobar",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"private_key"},
			},
		},
	})
}

func TestAccComputeSslCertificate_name_prefix(t *testing.T) {
	t.Parallel()

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckComputeSslCertificateDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccComputeSslCertificate_name_prefix(),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckComputeSslCertificateExists(
						"google_compute_ssl_certificate.foobar"),
				),
			},
			resource.TestStep{
				ResourceName:            "google_compute_ssl_certificate.foobar",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"private_key", "name_prefix"},
			},
		},
	})
}

func testAccCheckComputeSslCertificateDestroy(s *terraform.State) error {
	config := testAccProvider.Meta().(*Config)

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "google_compute_ssl_certificate" {
			continue
		}

		_, err := config.clientCompute.SslCertificates.Get(
			config.Project, rs.Primary.ID).Do()
		if err == nil {
			return fmt.Errorf("SslCertificate still exists")
		}
	}

	return nil
}

func testAccCheckComputeSslCertificateExists(n string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No ID is set")
		}

		config := testAccProvider.Meta().(*Config)

		found, err := config.clientCompute.SslCertificates.Get(
			config.Project, rs.Primary.ID).Do()
		if err != nil {
			return err
		}

		if found.Name != rs.Primary.ID {
			return fmt.Errorf("Certificate not found")
		}

		return nil
	}
}

func testAccComputeSslCertificate_basic() string {
	return fmt.Sprintf(`
resource "google_compute_ssl_certificate" "foobar" {
	name = "sslcert-test-%s"
	description = "very descriptive"
	private_key = "${file("test-fixtures/ssl_cert/test.key")}"
	certificate = "${file("test-fixtures/ssl_cert/test.crt")}"
}
`, acctest.RandString(10))
}

func testAccComputeSslCertificate_no_name() string {
	return fmt.Sprintf(`
resource "google_compute_ssl_certificate" "foobar" {
	description = "really descriptive"
	private_key = "${file("test-fixtures/ssl_cert/test.key")}"
	certificate = "${file("test-fixtures/ssl_cert/test.crt")}"
}
`)
}

func testAccComputeSslCertificate_name_prefix() string {
	return fmt.Sprintf(`
resource "google_compute_ssl_certificate" "foobar" {
	name_prefix = "sslcert-test-%s-"
	description = "extremely descriptive"
	private_key = "${file("test-fixtures/ssl_cert/test.key")}"
	certificate = "${file("test-fixtures/ssl_cert/test.crt")}"
}
`, acctest.RandString(10))
}
<|endoftext|>


<commit_before>package google

import (
	"fmt"
	"testing"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

// Stackdriver tests cannot be run in parallel otherwise they will error out with:
// Error 503: Too many concurrent edits to the project configuration. Please try again.

func TestAccMonitoringAlertPolicy_basic(t *testing.T) {

	alertName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
	conditionName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
	filter := `metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\"`

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAlertPolicyDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccMonitoringAlertPolicy_basic(alertName, conditionName, "ALIGN_RATE", filter),
			},
			{
				ResourceName:      "google_monitoring_alert_policy.basic",
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccMonitoringAlertPolicy_update(t *testing.T) {

	alertName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
	conditionName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
	filter1 := `metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\"`
	aligner1 := "ALIGN_RATE"
	filter2 := `metric.type=\"compute.googleapis.com/instance/cpu/utilization\" AND resource.type=\"gce_instance\"`
	aligner2 := "ALIGN_MAX"

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAlertPolicyDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccMonitoringAlertPolicy_basic(alertName, conditionName, aligner1, filter1),
			},
			{
				ResourceName:      "google_monitoring_alert_policy.basic",
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: testAccMonitoringAlertPolicy_basic(alertName, conditionName, aligner2, filter2),
			},
			{
				ResourceName:      "google_monitoring_alert_policy.basic",
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccMonitoringAlertPolicy_full(t *testing.T) {

	alertName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
	conditionName1 := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
	conditionName2 := fmt.Sprintf("tf-test-%s", acctest.RandString(10))

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAlertPolicyDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccMonitoringAlertPolicy_full(alertName, conditionName1, conditionName2),
			},
			{
				ResourceName:      "google_monitoring_alert_policy.full",
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func testAccCheckAlertPolicyDestroy(s *terraform.State) error {
	config := testAccProvider.Meta().(*Config)

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "google_monitoring_alert_policy" {
			continue
		}

		name := rs.Primary.Attributes["name"]

		url := fmt.Sprintf("https://monitoring.googleapis.com/v3/%s", name)
		_, err := sendRequest(config, "GET", url, nil)

		if err == nil {
			return fmt.Errorf("Error, alert policy %s still exists", name)
		}
	}

	return nil
}

func testAccMonitoringAlertPolicy_basic(alertName, conditionName, aligner, filter string) string {
	return fmt.Sprintf(`
resource "google_monitoring_alert_policy" "basic" {
  display_name = "%s"
  enabled      = true
  combiner     = "OR"

  conditions {
    display_name = "%s"

    condition_threshold {
      aggregations {
        alignment_period   = "60s"
        per_series_aligner = "%s"
      }

      duration   = "60s"
      comparison = "COMPARISON_GT"
      filter     = "%s"
    }
  }
}
`, alertName, conditionName, aligner, filter)
}

func testAccMonitoringAlertPolicy_full(alertName, conditionName1, conditionName2 string) string {
	return fmt.Sprintf(`
resource "google_monitoring_alert_policy" "full" {
  display_name = "%s"
  combiner     = "OR"
  enabled      = true

  conditions {
    display_name = "%s"

    condition_threshold {
      threshold_value = 50
      filter          = "metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\""
      duration        = "60s"
      comparison      = "COMPARISON_GT"

      aggregations {
        alignment_period     = "60s"
        per_series_aligner   = "ALIGN_RATE"
        cross_series_reducer = "REDUCE_MEAN"

        group_by_fields = [
          "metric.label.device_name",
          "project",
          "resource.label.instance_id",
          "resource.label.zone",
        ]
      }

      trigger {
        percent = 10
      }
    }
  }

  conditions {
    display_name = "%s"

    condition_absent {
      duration = "3600s"
      filter   = "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" AND resource.type=\"gce_instance\""

      aggregations {
        alignment_period     = "60s"
        cross_series_reducer = "REDUCE_MEAN"
        per_series_aligner   = "ALIGN_MEAN"

        group_by_fields = [
          "project",
          "resource.label.instance_id",
          "resource.label.zone",
        ]
      }

      trigger {
        count = 1
      }
    }
  }

  documentation {
    content   = "test content"
    mime_type = "text/markdown"
  }
}
`, alertName, conditionName1, conditionName2)
}
<commit_msg>Change alert threshold to something less sensitive (#2758)<commit_after>package google

import (
	"fmt"
	"testing"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

// Stackdriver tests cannot be run in parallel otherwise they will error out with:
// Error 503: Too many concurrent edits to the project configuration. Please try again.

func TestAccMonitoringAlertPolicy_basic(t *testing.T) {

	alertName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
	conditionName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
	filter := `metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\"`

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAlertPolicyDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccMonitoringAlertPolicy_basic(alertName, conditionName, "ALIGN_RATE", filter),
			},
			{
				ResourceName:      "google_monitoring_alert_policy.basic",
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccMonitoringAlertPolicy_update(t *testing.T) {

	alertName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
	conditionName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
	filter1 := `metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\"`
	aligner1 := "ALIGN_RATE"
	filter2 := `metric.type=\"compute.googleapis.com/instance/cpu/utilization\" AND resource.type=\"gce_instance\"`
	aligner2 := "ALIGN_MAX"

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAlertPolicyDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccMonitoringAlertPolicy_basic(alertName, conditionName, aligner1, filter1),
			},
			{
				ResourceName:      "google_monitoring_alert_policy.basic",
				ImportState:       true,
				ImportStateVerify: true,
			},
			{
				Config: testAccMonitoringAlertPolicy_basic(alertName, conditionName, aligner2, filter2),
			},
			{
				ResourceName:      "google_monitoring_alert_policy.basic",
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func TestAccMonitoringAlertPolicy_full(t *testing.T) {

	alertName := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
	conditionName1 := fmt.Sprintf("tf-test-%s", acctest.RandString(10))
	conditionName2 := fmt.Sprintf("tf-test-%s", acctest.RandString(10))

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAlertPolicyDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccMonitoringAlertPolicy_full(alertName, conditionName1, conditionName2),
			},
			{
				ResourceName:      "google_monitoring_alert_policy.full",
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func testAccCheckAlertPolicyDestroy(s *terraform.State) error {
	config := testAccProvider.Meta().(*Config)

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "google_monitoring_alert_policy" {
			continue
		}

		name := rs.Primary.Attributes["name"]

		url := fmt.Sprintf("https://monitoring.googleapis.com/v3/%s", name)
		_, err := sendRequest(config, "GET", url, nil)

		if err == nil {
			return fmt.Errorf("Error, alert policy %s still exists", name)
		}
	}

	return nil
}

func testAccMonitoringAlertPolicy_basic(alertName, conditionName, aligner, filter string) string {
	return fmt.Sprintf(`
resource "google_monitoring_alert_policy" "basic" {
  display_name = "%s"
  enabled      = true
  combiner     = "OR"

  conditions {
    display_name = "%s"

    condition_threshold {
      aggregations {
        alignment_period   = "60s"
        per_series_aligner = "%s"
      }

      duration       = "60s"
      comparison     = "COMPARISON_GT"
      filter         = "%s"
      thresholdValue = "0.5"
    }
  }
}
`, alertName, conditionName, aligner, filter)
}

func testAccMonitoringAlertPolicy_full(alertName, conditionName1, conditionName2 string) string {
	return fmt.Sprintf(`
resource "google_monitoring_alert_policy" "full" {
  display_name = "%s"
  combiner     = "OR"
  enabled      = true

  conditions {
    display_name = "%s"

    condition_threshold {
      threshold_value = 50
      filter          = "metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\""
      duration        = "60s"
      comparison      = "COMPARISON_GT"

      aggregations {
        alignment_period     = "60s"
        per_series_aligner   = "ALIGN_RATE"
        cross_series_reducer = "REDUCE_MEAN"

        group_by_fields = [
          "metric.label.device_name",
          "project",
          "resource.label.instance_id",
          "resource.label.zone",
        ]
      }

      trigger {
        percent = 10
      }
    }
  }

  conditions {
    display_name = "%s"

    condition_absent {
      duration = "3600s"
      filter   = "metric.type=\"compute.googleapis.com/instance/cpu/utilization\" AND resource.type=\"gce_instance\""

      aggregations {
        alignment_period     = "60s"
        cross_series_reducer = "REDUCE_MEAN"
        per_series_aligner   = "ALIGN_MEAN"

        group_by_fields = [
          "project",
          "resource.label.instance_id",
          "resource.label.zone",
        ]
      }

      trigger {
        count = 1
      }
    }
  }

  documentation {
    content   = "test content"
    mime_type = "text/markdown"
  }
}
`, alertName, conditionName1, conditionName2)
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"os"
	"os/signal"
	"sync"
)

// shutdownRequestChannel is used to initiate shutdown from one of the
// subsystems using the same code paths as when an interrupt signal is received.
var shutdownRequestChannel = make(chan struct{})

// interruptSignals defines the default signals to catch in order to do a proper
// shutdown.  This may be modified during init depending on the platform.
var interruptSignals = []os.Signal{os.Interrupt}

// interruptListener listens for OS Signals such as SIGINT (Ctrl+C) and shutdown
// requests from shutdownRequestChannel.  It returns a channel that is closed
// when either signal is received.
func interruptListener() <-chan struct{} {
	c := make(chan struct{})
	closeOnce := sync.Once{}
	go func() {
		interruptChannel := make(chan os.Signal, 1)
		signal.Notify(interruptChannel, interruptSignals...)

		for {
			select {
			case sig := <-interruptChannel:
				btcdLog.Infof("Received signal (%s).  "+
					"shutting down...", sig)

			case <-shutdownRequestChannel:
				btcdLog.Info("Shutdown requested.  " +
					"shutting down...")
			}

			closeOnce.Do(
				func() {
					close(c)
				})
		}
	}()

	return c
}

// interruptRequested returns true when the channel returned by
// interruptListener was closed.  This simplifies early shutdown slightly since
// the caller can just use an if statement instead of a select.
func interruptRequested(interrupted <-chan struct{}) bool {
	select {
	case <-interrupted:
		return true
	default:
	}

	return false
}
<commit_msg>fix signal.go file<commit_after>// Copyright (c) 2013-2016 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"github.com/btcboost/copernicus/log"
	"os"
	"os/signal"
	"sync"
)

// shutdownRequestChannel is used to initiate shutdown from one of the
// subsystems using the same code paths as when an interrupt signal is received.
var shutdownRequestChannel = make(chan struct{})

// interruptSignals defines the default signals to catch in order to do a proper
// shutdown.  This may be modified during init depending on the platform.
var interruptSignals = []os.Signal{os.Interrupt}

// interruptListener listens for OS Signals such as SIGINT (Ctrl+C) and shutdown
// requests from shutdownRequestChannel.  It returns a channel that is closed
// when either signal is received.
func interruptListener() <-chan struct{} {
	c := make(chan struct{})
	closeOnce := sync.Once{}
	go func() {
		interruptChannel := make(chan os.Signal, 1)
		signal.Notify(interruptChannel, interruptSignals...)

		for {
			select {
			case sig := <-interruptChannel:
				log.Info("Received signal (%s).  "+
					"shutting down...", sig)

			case <-shutdownRequestChannel:
				log.Info("Shutdown requested.  " +
					"shutting down...")
			}

			closeOnce.Do(
				func() {
					close(c)
				})
		}
	}()

	return c
}

// interruptRequested returns true when the channel returned by
// interruptListener was closed.  This simplifies early shutdown slightly since
// the caller can just use an if statement instead of a select.
func interruptRequested(interrupted <-chan struct{}) bool {
	select {
	case <-interrupted:
		return true
	default:
	}

	return false
}
<|endoftext|>


<commit_before>package bot

func commHelp(pack *commPackage) {
	if len(pack.params) == 0 {
		pack.session.ChannelMessageSend(pack.channel.ID, "Moebot has the following commands:\n"+
			"`"+ComPrefix+" team <role name>` - Changes your role to one of the approved roles. `"+ComPrefix+" team` to list all teams\n"+
			"`"+ComPrefix+" rank <rank name>` - Changes your rank to one of the approved ranks. `"+ComPrefix+" rank` to list all the ranks\n"+
			"`"+ComPrefix+" changelog` - Displays the changelog for moebot\n"+
			"`"+ComPrefix+" NSFW` - Gives you NSFW channel permissions\n"+
			"`"+ComPrefix+" permit <perm level> <role name>` - Master/All only. Grants permission to the selected role.\n"+
			"`"+ComPrefix+" custom <command name> <role name>` - Master/All/Mod Links up a role to be toggable by the command name. Type `"+ComPrefix+" role <command name> to toggle`\n"+
			"`"+ComPrefix+" help` - Displays this message")
	}
}
<commit_msg>Added new command in help file<commit_after>package bot

func commHelp(pack *commPackage) {
	if len(pack.params) == 0 {
		pack.session.ChannelMessageSend(pack.channel.ID, "Moebot has the following commands:\n"+
			"`"+ComPrefix+" team <role name>` - Changes your role to one of the approved roles. `"+ComPrefix+" team` to list all teams\n"+
			"`"+ComPrefix+" rank <rank name>` - Changes your rank to one of the approved ranks. `"+ComPrefix+" rank` to list all the ranks\n"+
			"`"+ComPrefix+" changelog` - Displays the changelog for moebot\n"+
			"`"+ComPrefix+" NSFW` - Gives you NSFW channel permissions\n"+
			"`"+ComPrefix+" spoiler [<spoiler title>] <spoiler text>` - Creates a spoiler gif with the given text and (optional) title\n"+
			"`"+ComPrefix+" permit <perm level> <role name>` - Master/All only. Grants permission to the selected role.\n"+
			"`"+ComPrefix+" custom <command name> <role name>` - Master/All/Mod Links up a role to be toggable by the command name. Type `"+ComPrefix+" role <command name> to toggle`\n"+
			"`"+ComPrefix+" help` - Displays this message")
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 Alexander Palaistras. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

// Package context contains methods related to PHP engine execution contexts. It
// allows for binding Go variables and executing PHP scripts as a single request.
package context

// #cgo CFLAGS: -I/usr/include/php -I/usr/include/php/main -I/usr/include/php/TSRM
// #cgo CFLAGS: -I/usr/include/php/Zend -I../value
// #cgo LDFLAGS: -lphp5
//
// #include <stdlib.h>
// #include "context.h"
import "C"

import (
	"fmt"
	"io"
	"net/http"
	"strings"
	"unsafe"

	"github.com/deuill/go-php/value"
)

// Context represents an individual execution context.
type Context struct {
	// Output and Log are unbuffered writers used for regular and debug output,
	// respectively. If left unset, any data written into either by the calling
	// context will be lost.
	Output io.Writer
	Log    io.Writer

	context *C.struct__engine_context
	header  http.Header
	values  map[string]*value.Value
}

// New creates a new execution context, passing all script output into w. It
// returns an error if the execution context failed to initialize at any point.
func New() (*Context, error) {
	ctx := &Context{
		header: make(http.Header),
		values: make(map[string]*value.Value),
	}

	ptr, err := C.context_new(unsafe.Pointer(ctx))
	if err != nil {
		return nil, fmt.Errorf("Failed to initialize context for PHP engine")
	}

	ctx.context = ptr

	return ctx, nil
}

// Bind allows for binding Go values into the current execution context under
// a certain name. Bind returns an error if attempting to bind an invalid value
// (check the documentation for value.New for what is considered to be a "valid"
// value).
func (c *Context) Bind(name string, val interface{}) error {
	v, err := value.New(val)
	if err != nil {
		return err
	}

	n := C.CString(name)
	defer C.free(unsafe.Pointer(n))

	if _, err = C.context_bind(c.context, n, v.Ptr()); err != nil {
		v.Destroy()
		return fmt.Errorf("Binding value '%v' to context failed", val)
	}

	c.values[name] = v

	return nil
}

// Exec executes a PHP script pointed to by filename in the current execution
// context, and returns an error, if any. Output produced by the script is
// written to the context's pre-defined io.Writer instance.
func (c *Context) Exec(filename string) error {
	f := C.CString(filename)
	defer C.free(unsafe.Pointer(f))

	_, err := C.context_exec(c.context, f)
	if err != nil {
		return fmt.Errorf("Error executing script '%s' in context", filename)
	}

	return nil
}

// Eval executes the PHP expression contained in script, and returns a Value
// containing the PHP value returned by the expression, if any. Any output
// produced is written context's pre-defined io.Writer instance.
func (c *Context) Eval(script string) (*value.Value, error) {
	// When PHP compiles code with a non-NULL return value expected, it simply
	// prepends a `return` call to the code, thus breaking simple scripts that
	// would otherwise work. Thus, we need to wrap the code in a closure, and
	// call it immediately.
	s := C.CString("call_user_func(function(){" + script + "});")
	defer C.free(unsafe.Pointer(s))

	vptr, err := C.context_eval(c.context, s)
	if err != nil {
		return nil, fmt.Errorf("Error executing script '%s' in context", script)
	}

	val, err := value.NewFromPtr(vptr)
	if err != nil {
		return nil, err
	}

	return val, nil
}

// Header returns the HTTP headers set by current PHP context.
func (c *Context) Header() http.Header {
	return c.header
}

// Destroy tears down the current execution context along with any active value
// bindings for that context.
func (c *Context) Destroy() {
	for _, v := range c.values {
		v.Destroy()
	}

	c.values = nil

	if c.context != nil {
		C.context_destroy(c.context)
		c.context = nil
	}
}

func (c *Context) write(w io.Writer, p []byte) int {
	if w == nil {
		return 0
	}

	written, err := w.Write(p)
	if err != nil {
		return 0
	}

	return written
}

//export contextWrite
func contextWrite(ctxptr unsafe.Pointer, buffer unsafe.Pointer, length C.uint) C.int {
	c := (*Context)(ctxptr)

	return C.int(c.write(c.Output, C.GoBytes(buffer, C.int(length))))
}

//export contextLog
func contextLog(ctxptr unsafe.Pointer, buffer unsafe.Pointer, length C.uint) C.int {
	c := (*Context)(ctxptr)

	return C.int(c.write(c.Log, C.GoBytes(buffer, C.int(length))))
}

//export contextHeader
func contextHeader(ctxptr unsafe.Pointer, operation C.uint, buffer unsafe.Pointer, length C.uint) {
	c := (*Context)(ctxptr)

	header := (string)(C.GoBytes(buffer, C.int(length)))
	split := strings.SplitN(header, ":", 2)

	for i := range split {
		split[i] = strings.TrimSpace(split[i])
	}

	switch operation {
	case 0: // Replace header.
		if len(split) == 2 && split[1] != "" {
			c.header.Set(split[0], split[1])
		}
	case 1: // Append header.
		if len(split) == 2 && split[1] != "" {
			c.header.Add(split[0], split[1])
		}
	case 2: // Delete header.
		if split[0] != "" {
			c.header.Del(split[0])
		}
	}
}
<commit_msg>Fix docblock for context.New() method<commit_after>// Copyright 2015 Alexander Palaistras. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

// Package context contains methods related to PHP engine execution contexts. It
// allows for binding Go variables and executing PHP scripts as a single request.
package context

// #cgo CFLAGS: -I/usr/include/php -I/usr/include/php/main -I/usr/include/php/TSRM
// #cgo CFLAGS: -I/usr/include/php/Zend -I../value
// #cgo LDFLAGS: -lphp5
//
// #include <stdlib.h>
// #include "context.h"
import "C"

import (
	"fmt"
	"io"
	"net/http"
	"strings"
	"unsafe"

	"github.com/deuill/go-php/value"
)

// Context represents an individual execution context.
type Context struct {
	// Output and Log are unbuffered writers used for regular and debug output,
	// respectively. If left unset, any data written into either by the calling
	// context will be lost.
	Output io.Writer
	Log    io.Writer

	context *C.struct__engine_context
	header  http.Header
	values  map[string]*value.Value
}

// New creates a new execution context for the active engine and returns an
// error if the execution context failed to initialize at any point.
func New() (*Context, error) {
	ctx := &Context{
		header: make(http.Header),
		values: make(map[string]*value.Value),
	}

	ptr, err := C.context_new(unsafe.Pointer(ctx))
	if err != nil {
		return nil, fmt.Errorf("Failed to initialize context for PHP engine")
	}

	ctx.context = ptr

	return ctx, nil
}

// Bind allows for binding Go values into the current execution context under
// a certain name. Bind returns an error if attempting to bind an invalid value
// (check the documentation for value.New for what is considered to be a "valid"
// value).
func (c *Context) Bind(name string, val interface{}) error {
	v, err := value.New(val)
	if err != nil {
		return err
	}

	n := C.CString(name)
	defer C.free(unsafe.Pointer(n))

	if _, err = C.context_bind(c.context, n, v.Ptr()); err != nil {
		v.Destroy()
		return fmt.Errorf("Binding value '%v' to context failed", val)
	}

	c.values[name] = v

	return nil
}

// Exec executes a PHP script pointed to by filename in the current execution
// context, and returns an error, if any. Output produced by the script is
// written to the context's pre-defined io.Writer instance.
func (c *Context) Exec(filename string) error {
	f := C.CString(filename)
	defer C.free(unsafe.Pointer(f))

	_, err := C.context_exec(c.context, f)
	if err != nil {
		return fmt.Errorf("Error executing script '%s' in context", filename)
	}

	return nil
}

// Eval executes the PHP expression contained in script, and returns a Value
// containing the PHP value returned by the expression, if any. Any output
// produced is written context's pre-defined io.Writer instance.
func (c *Context) Eval(script string) (*value.Value, error) {
	// When PHP compiles code with a non-NULL return value expected, it simply
	// prepends a `return` call to the code, thus breaking simple scripts that
	// would otherwise work. Thus, we need to wrap the code in a closure, and
	// call it immediately.
	s := C.CString("call_user_func(function(){" + script + "});")
	defer C.free(unsafe.Pointer(s))

	vptr, err := C.context_eval(c.context, s)
	if err != nil {
		return nil, fmt.Errorf("Error executing script '%s' in context", script)
	}

	val, err := value.NewFromPtr(vptr)
	if err != nil {
		return nil, err
	}

	return val, nil
}

// Header returns the HTTP headers set by current PHP context.
func (c *Context) Header() http.Header {
	return c.header
}

// Destroy tears down the current execution context along with any active value
// bindings for that context.
func (c *Context) Destroy() {
	for _, v := range c.values {
		v.Destroy()
	}

	c.values = nil

	if c.context != nil {
		C.context_destroy(c.context)
		c.context = nil
	}
}

func (c *Context) write(w io.Writer, p []byte) int {
	if w == nil {
		return 0
	}

	written, err := w.Write(p)
	if err != nil {
		return 0
	}

	return written
}

//export contextWrite
func contextWrite(ctxptr unsafe.Pointer, buffer unsafe.Pointer, length C.uint) C.int {
	c := (*Context)(ctxptr)

	return C.int(c.write(c.Output, C.GoBytes(buffer, C.int(length))))
}

//export contextLog
func contextLog(ctxptr unsafe.Pointer, buffer unsafe.Pointer, length C.uint) C.int {
	c := (*Context)(ctxptr)

	return C.int(c.write(c.Log, C.GoBytes(buffer, C.int(length))))
}

//export contextHeader
func contextHeader(ctxptr unsafe.Pointer, operation C.uint, buffer unsafe.Pointer, length C.uint) {
	c := (*Context)(ctxptr)

	header := (string)(C.GoBytes(buffer, C.int(length)))
	split := strings.SplitN(header, ":", 2)

	for i := range split {
		split[i] = strings.TrimSpace(split[i])
	}

	switch operation {
	case 0: // Replace header.
		if len(split) == 2 && split[1] != "" {
			c.header.Set(split[0], split[1])
		}
	case 1: // Append header.
		if len(split) == 2 && split[1] != "" {
			c.header.Add(split[0], split[1])
		}
	case 2: // Delete header.
		if split[0] != "" {
			c.header.Del(split[0])
		}
	}
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	"net/http"
	"testing"
)

// TestNewerVersion checks that in all cases, newerVesion returns the correct
// result.
func TestNewerVersion(t *testing.T) {
	// If the VERSION is changed, these tests might no longer be valid.
	if VERSION != "0.3.2" {
		t.Fatal("Need to update version tests")
	}

	versionMap := map[string]bool{
		VERSION:   false,
		"0.1":     false,
		"0.1.1":   false,
		"1":       true,
		"0.9":     true,
		"0.3.1.9": false,
		"0.3.2.0": true,
		"0.3.2.1": true,
	}

	for version, expected := range versionMap {
		if newerVersion(version) != expected {
			t.Error("Comparing %v to %v should return %v", version, VERSION, expected)
		}
	}
}

type updateHandler struct {
	version string
}

func (uh *updateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.URL.String() {
	case "/current/MANIFEST":
		fmt.Fprintf(w, "%s\nsiad\n", uh.version)
	case "/current/siad":
		fmt.Fprint(w, "yep this is siad")
	case "/current/siad.sig":
		fmt.Fprint(w, "and this is totally a signature")
	default:
		http.NotFound(w, r)
	}
}

// TestUpdate checks that updates work properly.
func TestSignedUpdate(t *testing.T) {
	st := newServerTester("TestSignedUpdate", t)

	// to test the update process, we need to spoof the update server
	uh := new(updateHandler)
	http.Handle("/", uh)
	go http.ListenAndServe(":8080", nil)
	updateURL = "http://localhost:8080"

	// same version
	uh.version = VERSION
	var info UpdateInfo
	st.getAPI("/daemon/updates/check", &info)
	if info.Available {
		t.Error("new version should not be available")
	}

	// newer version
	uh.version = "0.4"
	st.getAPI("/daemon/updates/check", &info)
	if !info.Available {
		t.Error("new version should be available")
	}

	// apply (bad signature)
	resp, err := http.Get("http://localhost" + st.server.apiServer.Addr + "/daemon/updates/apply?version=current")
	if err != nil {
		t.Fatal("GET failed:", err)
	}
	if resp.StatusCode != http.StatusInternalServerError {
		t.Error("expected internal server error, got", resp.StatusCode)
	}
}
<commit_msg>fix Errorf call<commit_after>package api

import (
	"fmt"
	"net/http"
	"testing"
)

// TestNewerVersion checks that in all cases, newerVesion returns the correct
// result.
func TestNewerVersion(t *testing.T) {
	// If the VERSION is changed, these tests might no longer be valid.
	if VERSION != "0.3.2" {
		t.Fatal("Need to update version tests")
	}

	versionMap := map[string]bool{
		VERSION:   false,
		"0.1":     false,
		"0.1.1":   false,
		"1":       true,
		"0.9":     true,
		"0.3.1.9": false,
		"0.3.2.0": true,
		"0.3.2.1": true,
	}

	for version, expected := range versionMap {
		if newerVersion(version) != expected {
			t.Errorf("Comparing %v to %v should return %v", version, VERSION, expected)
		}
	}
}

type updateHandler struct {
	version string
}

func (uh *updateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.URL.String() {
	case "/current/MANIFEST":
		fmt.Fprintf(w, "%s\nsiad\n", uh.version)
	case "/current/siad":
		fmt.Fprint(w, "yep this is siad")
	case "/current/siad.sig":
		fmt.Fprint(w, "and this is totally a signature")
	default:
		http.NotFound(w, r)
	}
}

// TestUpdate checks that updates work properly.
func TestSignedUpdate(t *testing.T) {
	st := newServerTester("TestSignedUpdate", t)

	// to test the update process, we need to spoof the update server
	uh := new(updateHandler)
	http.Handle("/", uh)
	go http.ListenAndServe(":8080", nil)
	updateURL = "http://localhost:8080"

	// same version
	uh.version = VERSION
	var info UpdateInfo
	st.getAPI("/daemon/updates/check", &info)
	if info.Available {
		t.Error("new version should not be available")
	}

	// newer version
	uh.version = "0.4"
	st.getAPI("/daemon/updates/check", &info)
	if !info.Available {
		t.Error("new version should be available")
	}

	// apply (bad signature)
	resp, err := http.Get("http://localhost" + st.server.apiServer.Addr + "/daemon/updates/apply?version=current")
	if err != nil {
		t.Fatal("GET failed:", err)
	}
	if resp.StatusCode != http.StatusInternalServerError {
		t.Error("expected internal server error, got", resp.StatusCode)
	}
}
<|endoftext|>