<commit_before>package protobuf_test

import (
	"reflect"
	"testing"

	"github.com/nats-io/nats"
	"github.com/nats-io/nats/test"

	"github.com/nats-io/nats/encoders/protobuf"
	pb "github.com/nats-io/nats/encoders/protobuf/testdata"
)

const TEST_PORT = 8068

func NewProtoEncodedConn(tl test.TestLogger) *nats.EncodedConn {
	ec, err := nats.NewEncodedConn(test.NewConnection(tl, TEST_PORT), protobuf.PROTOBUF_ENCODER)
	if err != nil {
		tl.Fatalf("Failed to create an encoded connection: %v\n", err)
	}
	return ec
}

func TestProtoMarshalStruct(t *testing.T) {
	s := test.RunServerOnPort(TEST_PORT)
	defer s.Shutdown()

	ec := NewProtoEncodedConn(t)
	defer ec.Close()
	ch := make(chan bool)

	me := &pb.Person{Name: "derek", Age: 22, Address: "140 New Montgomery St"}
	me.Children = make(map[string]*pb.Person)

	me.Children["sam"] = &pb.Person{Name: "sam", Age: 19, Address: "140 New Montgomery St"}
	me.Children["meg"] = &pb.Person{Name: "meg", Age: 17, Address: "140 New Montgomery St"}

	ec.Subscribe("protobuf_test", func(p *pb.Person) {
		if !reflect.DeepEqual(p, me) {
			t.Fatal("Did not receive the correct protobuf response")
		}
		ch <- true
	})

	ec.Publish("protobuf_test", me)
	if e := test.Wait(ch); e != nil {
		t.Fatal("Did not receive the message")
	}
}

func BenchmarkProtobufMarshalStruct(b *testing.B) {
	me := &pb.Person{Name: "derek", Age: 22, Address: "140 New Montgomery St"}
	me.Children = make(map[string]*pb.Person)

	me.Children["sam"] = &pb.Person{Name: "sam", Age: 19, Address: "140 New Montgomery St"}
	me.Children["meg"] = &pb.Person{Name: "meg", Age: 17, Address: "140 New Montgomery St"}

	encoder := &protobuf.ProtobufEncoder{}
	for n := 0; n < b.N; n++ {
		if _, err := encoder.Encode("protobuf_test", me); err != nil {
			b.Fatal("Couldn't serialize object", err)
		}
	}
}

func BenchmarkPublishProtobufStruct(b *testing.B) {
	// stop benchmark for set-up
	b.StopTimer()

	s := test.RunServerOnPort(TEST_PORT)
	defer s.Shutdown()

	ec := NewProtoEncodedConn(b)
	defer ec.Close()
	ch := make(chan bool)

	me := &pb.Person{Name: "derek", Age: 22, Address: "140 New Montgomery St"}
	me.Children = make(map[string]*pb.Person)

	me.Children["sam"] = &pb.Person{Name: "sam", Age: 19, Address: "140 New Montgomery St"}
	me.Children["meg"] = &pb.Person{Name: "meg", Age: 17, Address: "140 New Montgomery St"}

	ec.Subscribe("protobuf_test", func(p *pb.Person) {
		if !reflect.DeepEqual(p, me) {
			b.Fatalf("Did not receive the correct protobuf response")
		}
		ch <- true
	})

	// resume benchmark
	b.StartTimer()

	for n := 0; n < b.N; n++ {
		ec.Publish("protobuf_test", me)
		if e := test.Wait(ch); e != nil {
			b.Fatal("Did not receive the message")
		}
	}
}
<commit_msg>Add tests to show failed scenario for proto connection<commit_after>package protobuf_test

import (
	"reflect"
	"testing"
	"time"

	"github.com/nats-io/nats"
	"github.com/nats-io/nats/test"

	"github.com/nats-io/nats/encoders/protobuf"
	pb "github.com/nats-io/nats/encoders/protobuf/testdata"
)

const TEST_PORT = 8068

func NewProtoEncodedConn(tl test.TestLogger) *nats.EncodedConn {
	ec, err := nats.NewEncodedConn(test.NewConnection(tl, TEST_PORT), protobuf.PROTOBUF_ENCODER)
	if err != nil {
		tl.Fatalf("Failed to create an encoded connection: %v\n", err)
	}
	return ec
}

func TestProtoMarshalStruct(t *testing.T) {
	s := test.RunServerOnPort(TEST_PORT)
	defer s.Shutdown()

	ec := NewProtoEncodedConn(t)
	defer ec.Close()
	ch := make(chan bool)

	me := &pb.Person{Name: "derek", Age: 22, Address: "140 New Montgomery St"}
	me.Children = make(map[string]*pb.Person)

	me.Children["sam"] = &pb.Person{Name: "sam", Age: 19, Address: "140 New Montgomery St"}
	me.Children["meg"] = &pb.Person{Name: "meg", Age: 17, Address: "140 New Montgomery St"}

	ec.Subscribe("protobuf_test", func(p *pb.Person) {
		if !reflect.DeepEqual(p, me) {
			t.Fatal("Did not receive the correct protobuf response")
		}
		ch <- true
	})

	ec.Publish("protobuf_test", me)
	if e := test.Wait(ch); e != nil {
		t.Fatal("Did not receive the message")
	}
}

func TestProtoNilRequest(t *testing.T) {
	s := test.RunServerOnPort(TEST_PORT)
	defer s.Shutdown()

	ec := NewProtoEncodedConn(t)
	defer ec.Close()

	testPerson := &pb.Person{Name: "Anatolii", Age: 25, Address: "Ukraine, Nikolaev"}

	//Subscribe with empty interface shouldn't failed on empty message
	ec.Subscribe("nil_test", func(_, reply string, _ interface{}) {
		ec.Publish(reply, testPerson)
	})

	resp := new(pb.Person)

	//Request with nil argument shouldn't failed with nil argument
	err := ec.Request("nil_test", nil, resp, 100*time.Millisecond)
	ec.Flush()

	if err != nil {
		t.Error("Fail to send empty message via encoded proto connection")
	}

	if !reflect.DeepEqual(testPerson, resp) {
		t.Error("Fail to receive encoded response")
	}
}

func BenchmarkProtobufMarshalStruct(b *testing.B) {
	me := &pb.Person{Name: "derek", Age: 22, Address: "140 New Montgomery St"}
	me.Children = make(map[string]*pb.Person)

	me.Children["sam"] = &pb.Person{Name: "sam", Age: 19, Address: "140 New Montgomery St"}
	me.Children["meg"] = &pb.Person{Name: "meg", Age: 17, Address: "140 New Montgomery St"}

	encoder := &protobuf.ProtobufEncoder{}
	for n := 0; n < b.N; n++ {
		if _, err := encoder.Encode("protobuf_test", me); err != nil {
			b.Fatal("Couldn't serialize object", err)
		}
	}
}

func BenchmarkPublishProtobufStruct(b *testing.B) {
	// stop benchmark for set-up
	b.StopTimer()

	s := test.RunServerOnPort(TEST_PORT)
	defer s.Shutdown()

	ec := NewProtoEncodedConn(b)
	defer ec.Close()
	ch := make(chan bool)

	me := &pb.Person{Name: "derek", Age: 22, Address: "140 New Montgomery St"}
	me.Children = make(map[string]*pb.Person)

	me.Children["sam"] = &pb.Person{Name: "sam", Age: 19, Address: "140 New Montgomery St"}
	me.Children["meg"] = &pb.Person{Name: "meg", Age: 17, Address: "140 New Montgomery St"}

	ec.Subscribe("protobuf_test", func(p *pb.Person) {
		if !reflect.DeepEqual(p, me) {
			b.Fatalf("Did not receive the correct protobuf response")
		}
		ch <- true
	})

	// resume benchmark
	b.StartTimer()

	for n := 0; n < b.N; n++ {
		ec.Publish("protobuf_test", me)
		if e := test.Wait(ch); e != nil {
			b.Fatal("Did not receive the message")
		}
	}
}
<|endoftext|>


<commit_before>// service for discovering Lantern instances in the local network
package localdiscovery

import (
	"github.com/getlantern/flashlight/ui"
	"github.com/getlantern/golog"
	"github.com/getlantern/multicast"
	"sync"
	"time"
)

const (
	messageType  = `LocalDiscovery`
	updatePeriod = 10
)

var (
	log           = golog.LoggerFor("flashlight.localdiscovery")
	service       *ui.Service
	mc            *multicast.Multicast
	lastPeers     []multicast.PeerInfo
	peersMutex    sync.Mutex
)

func Start(portToAdvertise string) {
	if service == nil {
		helloFn := func(write func(interface{}) error) error {
			log.Debugf("Sending local Lanterns list to the Lantern UI")
			return write(buildPeersList())
		}
		var err error
		service, err = ui.Register(messageType, nil, helloFn)

		if err != nil {
			log.Errorf("Unable to register Local Discovery service: %q", err)
			return
		}
	}

	mc = multicast.JoinMulticast()

	mc.Payload = portToAdvertise
	mc.AddPeerCallback = func(peer string, peersInfo []multicast.PeerInfo) {
		peersMutex.Lock()
		lastPeers = peersInfo
		peersMutex.Unlock()

		service.Out <- peersInfo
	}
	mc.RemovePeerCallback = func(peer string, peersInfo []multicast.PeerInfo) {
		peersMutex.Lock()
		lastPeers = peersInfo
		peersMutex.Unlock()

		service.Out <- peersInfo
	}

	mc.StartMulticast()

	go func() {
		c := time.Tick(updatePeriod * time.Second)
		for range c {
			service.Out <- buildPeersList()
		}
	}()
}

func Stop() {
	mc.LeaveMulticast()
}

func buildPeersList() []string {
	peersList := make([]string, len(lastPeers))

	peersMutex.Lock()
	for i, peer := range lastPeers {
		peersList[i] = "http://" + peer.IP.String() + ":" + peer.Payload
	}
	peersMutex.Unlock()

	return peersList
}
<commit_msg>Fixed wrongly structured UI localdiscovery messages<commit_after>// service for discovering Lantern instances in the local network
package localdiscovery

import (
	"github.com/getlantern/flashlight/ui"
	"github.com/getlantern/golog"
	"github.com/getlantern/multicast"
	"sync"
	"time"
)

const (
	messageType  = `LocalDiscovery`
	updatePeriod = 10
)

var (
	log           = golog.LoggerFor("flashlight.localdiscovery")
	service       *ui.Service
	mc            *multicast.Multicast
	lastPeers     []multicast.PeerInfo
	peersMutex    sync.Mutex
)

func Start(portToAdvertise string) {
	if service == nil {
		var err error
		service, err = ui.Register(messageType, nil, func(write func(interface{}) error) error {
			return write(buildPeersList())
		})
		if err != nil {
			log.Errorf("Unable to register Local Discovery service: %q", err)
			return
		}
	}

	mc = multicast.JoinMulticast()

	mc.Payload = portToAdvertise
	mc.AddPeerCallback = func(peer string, peersInfo []multicast.PeerInfo) {
		peersMutex.Lock()
		lastPeers = peersInfo
		peersMutex.Unlock()

		service.Out <- buildPeersList()
	}
	mc.RemovePeerCallback = func(peer string, peersInfo []multicast.PeerInfo) {
		peersMutex.Lock()
		lastPeers = peersInfo
		peersMutex.Unlock()

		service.Out <- buildPeersList()
	}

	mc.StartMulticast()

	go func() {
		c := time.Tick(updatePeriod * time.Second)
		for range c {
			service.Out <- buildPeersList()
		}
	}()
}

func Stop() {
	mc.LeaveMulticast()
}

func buildPeersList() []string {
	peersList := make([]string, len(lastPeers))

	peersMutex.Lock()
	for i, peer := range lastPeers {
		peersList[i] = "http://" + peer.IP.String() + ":" + peer.Payload
	}
	peersMutex.Unlock()

	return peersList
}
<|endoftext|>


<commit_before>package controllers

import (
	"encoding/json"
	"log"
	"strconv"
	"time"

	"github.com/astaxie/beego"
	"github.com/lfq7413/tomato/auth"
	"github.com/lfq7413/tomato/config"
	"github.com/lfq7413/tomato/orm"
	"github.com/lfq7413/tomato/rest"
	"github.com/lfq7413/tomato/utils"
	"gopkg.in/mgo.v2/bson"
)

// ObjectsController ...
type ObjectsController struct {
	beego.Controller
	Info      *RequestInfo
	Auth      *auth.Auth
	ClassName string
	ObjectID  string
}

// RequestInfo ...
type RequestInfo struct {
	AppID          string
	MasterKey      string
	ClientKey      string
	SessionToken   string
	InstallationID string
}

// Prepare ...
func (o *ObjectsController) Prepare() {
	//TODO 1、获取请求头
	info := &RequestInfo{}
	info.AppID = o.Ctx.Input.Header("X-Parse-Application-Id")
	info.MasterKey = o.Ctx.Input.Header("X-Parse-Master-Key")
	info.ClientKey = o.Ctx.Input.Header("X-Parse-Client-Key")
	info.SessionToken = o.Ctx.Input.Header("X-Parse-Session-Token")
	info.InstallationID = o.Ctx.Input.Header("X-Parse-Installation-Id")
	o.Info = info
	//TODO 2、校验头部数据
	if info.AppID != config.TConfig.AppID {
		//TODO AppID 不正确
	}
	if info.MasterKey == config.TConfig.MasterKey {
		o.Auth = &auth.Auth{InstallationID: info.InstallationID, IsMaster: true}
		return
	}
	if info.ClientKey != config.TConfig.ClientKey {
		//TODO ClientKey 不正确
	}
	//TODO 3、生成当前会话用户权限信息
	if info.SessionToken == "" {
		o.Auth = &auth.Auth{InstallationID: info.InstallationID, IsMaster: false}
	} else {
		o.Auth = auth.GetAuthForSessionToken(info.SessionToken, info.InstallationID)
	}

}

// Post ...
// @router /:className [post]
func (o *ObjectsController) Post() {

	var object map[string]interface{}
	json.Unmarshal(o.Ctx.Input.RequestBody, &object)

	rest.Create(o.Auth, o.ClassName, object)

	className := o.Ctx.Input.Param(":className")

	var cls bson.M
	json.Unmarshal(o.Ctx.Input.RequestBody, &cls)

	objectId := utils.CreateObjectId()
	now := time.Now().UTC()
	cls["_id"] = objectId
	cls["createdAt"] = now
	cls["updatedAt"] = now

	err := orm.TomatoDB.Insert(className, cls)
	if err != nil {
		log.Fatal(err)
	}

	data := bson.M{}
	data["objectId"] = objectId
	data["createdAt"] = utils.TimetoString(now)

	o.Data["json"] = data
	o.Ctx.Output.SetStatus(201)
	o.Ctx.Output.Header("Location", config.TConfig.ServerURL+"/classes/"+className+"/"+objectId)
	o.ServeJSON()
}

// Get ...
// @router /:className/:objectId [get]
func (o *ObjectsController) Get() {

	options := map[string]interface{}{}
	where := map[string]interface{}{"objectId": o.ObjectID}

	rest.Find(o.Auth, o.ClassName, where, options)

	className := o.Ctx.Input.Param(":className")
	objectId := o.Ctx.Input.Param(":objectId")

	cls := bson.M{}
	cls["_id"] = objectId

	data, err := orm.TomatoDB.FindOne(className, cls)
	if err != nil {
		log.Fatal(err)
	}

	data["objectId"] = data["_id"]
	delete(data, "_id")
	if createdAt, ok := data["createdAt"].(time.Time); ok {
		data["createdAt"] = utils.TimetoString(createdAt.UTC())
	}
	if updatedAt, ok := data["updatedAt"].(time.Time); ok {
		data["updatedAt"] = utils.TimetoString(updatedAt.UTC())
	}

	o.Data["json"] = data
	o.ServeJSON()
}

// Put ...
// @router /:className/:objectId [put]
func (o *ObjectsController) Put() {
	className := o.Ctx.Input.Param(":className")
	objectId := o.Ctx.Input.Param(":objectId")

	var cls bson.M
	json.Unmarshal(o.Ctx.Input.RequestBody, &cls)

	now := time.Now().UTC()
	cls["updatedAt"] = now
	update := bson.M{"$set": cls}

	err := orm.TomatoDB.Update(className, bson.M{"_id": objectId}, update)
	if err != nil {
		log.Fatal(err)
	}

	data := bson.M{}
	data["updatedAt"] = utils.TimetoString(now)
	o.Data["json"] = data
	o.ServeJSON()
}

// GetAll ...
// @router /:className [get]
func (o *ObjectsController) GetAll() {

	// TODO 获取查询参数，并组装
	options := map[string]interface{}{}
	if o.GetString("skip") != "" {
		if i, err := strconv.Atoi(o.GetString("skip")); err == nil {
			options["skip"] = i
		} else {
			// TODO return error
		}
	}
	if o.GetString("limit") != "" {
		if i, err := strconv.Atoi(o.GetString("limit")); err == nil {
			options["limit"] = i
		} else {
			// TODO return error
		}
	} else {
		options["limit"] = 100
	}
	if o.GetString("order") != "" {
		options["order"] = o.GetString("order")
	}
	if o.GetString("count") != "" {
		options["count"] = true
	}
	if o.GetString("keys") != "" {
		options["keys"] = o.GetString("keys")
	}
	if o.GetString("include") != "" {
		options["include"] = o.GetString("include")
	}

	where := map[string]interface{}{}
	if o.GetString("where") != "" {
		err := json.Unmarshal([]byte(o.GetString("where")), &where)
		if err != nil {
			// TODO return err
		}
	}

	rest.Find(o.Auth, o.ClassName, where, options)

	className := o.Ctx.Input.Param(":className")

	cls := bson.M{}

	data, err := orm.TomatoDB.Find(className, cls)
	if err != nil {
		log.Fatal(err)
	}

	for _, v := range data {
		v["objectId"] = v["_id"]
		delete(v, "_id")
		if createdAt, ok := v["createdAt"].(time.Time); ok {
			v["createdAt"] = utils.TimetoString(createdAt.UTC())
		}
		if updatedAt, ok := v["updatedAt"].(time.Time); ok {
			v["updatedAt"] = utils.TimetoString(updatedAt.UTC())
		}
	}
	o.Data["json"] = bson.M{"results": data}
	o.ServeJSON()
}

// Delete ...
// @router /:className/:objectId [delete]
func (o *ObjectsController) Delete() {
	className := o.Ctx.Input.Param(":className")
	objectId := o.Ctx.Input.Param(":objectId")

	cls := bson.M{}
	cls["_id"] = objectId

	err := orm.TomatoDB.Remove(className, cls)
	if err != nil {
		log.Fatal(err)
	}

	data := bson.M{}
	o.Data["json"] = data
	o.ServeJSON()
}
<commit_msg>Delete() 组装参数<commit_after>package controllers

import (
	"encoding/json"
	"log"
	"strconv"
	"time"

	"github.com/astaxie/beego"
	"github.com/lfq7413/tomato/auth"
	"github.com/lfq7413/tomato/config"
	"github.com/lfq7413/tomato/orm"
	"github.com/lfq7413/tomato/rest"
	"github.com/lfq7413/tomato/utils"
	"gopkg.in/mgo.v2/bson"
)

// ObjectsController ...
type ObjectsController struct {
	beego.Controller
	Info      *RequestInfo
	Auth      *auth.Auth
	ClassName string
	ObjectID  string
}

// RequestInfo ...
type RequestInfo struct {
	AppID          string
	MasterKey      string
	ClientKey      string
	SessionToken   string
	InstallationID string
}

// Prepare ...
func (o *ObjectsController) Prepare() {
	//TODO 1、获取请求头
	info := &RequestInfo{}
	info.AppID = o.Ctx.Input.Header("X-Parse-Application-Id")
	info.MasterKey = o.Ctx.Input.Header("X-Parse-Master-Key")
	info.ClientKey = o.Ctx.Input.Header("X-Parse-Client-Key")
	info.SessionToken = o.Ctx.Input.Header("X-Parse-Session-Token")
	info.InstallationID = o.Ctx.Input.Header("X-Parse-Installation-Id")
	o.Info = info
	//TODO 2、校验头部数据
	if info.AppID != config.TConfig.AppID {
		//TODO AppID 不正确
	}
	if info.MasterKey == config.TConfig.MasterKey {
		o.Auth = &auth.Auth{InstallationID: info.InstallationID, IsMaster: true}
		return
	}
	if info.ClientKey != config.TConfig.ClientKey {
		//TODO ClientKey 不正确
	}
	//TODO 3、生成当前会话用户权限信息
	if info.SessionToken == "" {
		o.Auth = &auth.Auth{InstallationID: info.InstallationID, IsMaster: false}
	} else {
		o.Auth = auth.GetAuthForSessionToken(info.SessionToken, info.InstallationID)
	}

}

// Post ...
// @router /:className [post]
func (o *ObjectsController) Post() {

	var object map[string]interface{}
	json.Unmarshal(o.Ctx.Input.RequestBody, &object)

	rest.Create(o.Auth, o.ClassName, object)

	className := o.Ctx.Input.Param(":className")

	var cls bson.M
	json.Unmarshal(o.Ctx.Input.RequestBody, &cls)

	objectId := utils.CreateObjectId()
	now := time.Now().UTC()
	cls["_id"] = objectId
	cls["createdAt"] = now
	cls["updatedAt"] = now

	err := orm.TomatoDB.Insert(className, cls)
	if err != nil {
		log.Fatal(err)
	}

	data := bson.M{}
	data["objectId"] = objectId
	data["createdAt"] = utils.TimetoString(now)

	o.Data["json"] = data
	o.Ctx.Output.SetStatus(201)
	o.Ctx.Output.Header("Location", config.TConfig.ServerURL+"/classes/"+className+"/"+objectId)
	o.ServeJSON()
}

// Get ...
// @router /:className/:objectId [get]
func (o *ObjectsController) Get() {

	options := map[string]interface{}{}
	where := map[string]interface{}{"objectId": o.ObjectID}

	rest.Find(o.Auth, o.ClassName, where, options)

	className := o.Ctx.Input.Param(":className")
	objectId := o.Ctx.Input.Param(":objectId")

	cls := bson.M{}
	cls["_id"] = objectId

	data, err := orm.TomatoDB.FindOne(className, cls)
	if err != nil {
		log.Fatal(err)
	}

	data["objectId"] = data["_id"]
	delete(data, "_id")
	if createdAt, ok := data["createdAt"].(time.Time); ok {
		data["createdAt"] = utils.TimetoString(createdAt.UTC())
	}
	if updatedAt, ok := data["updatedAt"].(time.Time); ok {
		data["updatedAt"] = utils.TimetoString(updatedAt.UTC())
	}

	o.Data["json"] = data
	o.ServeJSON()
}

// Put ...
// @router /:className/:objectId [put]
func (o *ObjectsController) Put() {
	className := o.Ctx.Input.Param(":className")
	objectId := o.Ctx.Input.Param(":objectId")

	var cls bson.M
	json.Unmarshal(o.Ctx.Input.RequestBody, &cls)

	now := time.Now().UTC()
	cls["updatedAt"] = now
	update := bson.M{"$set": cls}

	err := orm.TomatoDB.Update(className, bson.M{"_id": objectId}, update)
	if err != nil {
		log.Fatal(err)
	}

	data := bson.M{}
	data["updatedAt"] = utils.TimetoString(now)
	o.Data["json"] = data
	o.ServeJSON()
}

// GetAll ...
// @router /:className [get]
func (o *ObjectsController) GetAll() {

	// TODO 获取查询参数，并组装
	options := map[string]interface{}{}
	if o.GetString("skip") != "" {
		if i, err := strconv.Atoi(o.GetString("skip")); err == nil {
			options["skip"] = i
		} else {
			// TODO return error
		}
	}
	if o.GetString("limit") != "" {
		if i, err := strconv.Atoi(o.GetString("limit")); err == nil {
			options["limit"] = i
		} else {
			// TODO return error
		}
	} else {
		options["limit"] = 100
	}
	if o.GetString("order") != "" {
		options["order"] = o.GetString("order")
	}
	if o.GetString("count") != "" {
		options["count"] = true
	}
	if o.GetString("keys") != "" {
		options["keys"] = o.GetString("keys")
	}
	if o.GetString("include") != "" {
		options["include"] = o.GetString("include")
	}

	where := map[string]interface{}{}
	if o.GetString("where") != "" {
		err := json.Unmarshal([]byte(o.GetString("where")), &where)
		if err != nil {
			// TODO return err
		}
	}

	rest.Find(o.Auth, o.ClassName, where, options)

	className := o.Ctx.Input.Param(":className")

	cls := bson.M{}

	data, err := orm.TomatoDB.Find(className, cls)
	if err != nil {
		log.Fatal(err)
	}

	for _, v := range data {
		v["objectId"] = v["_id"]
		delete(v, "_id")
		if createdAt, ok := v["createdAt"].(time.Time); ok {
			v["createdAt"] = utils.TimetoString(createdAt.UTC())
		}
		if updatedAt, ok := v["updatedAt"].(time.Time); ok {
			v["updatedAt"] = utils.TimetoString(updatedAt.UTC())
		}
	}
	o.Data["json"] = bson.M{"results": data}
	o.ServeJSON()
}

// Delete ...
// @router /:className/:objectId [delete]
func (o *ObjectsController) Delete() {

	rest.Delete(o.Auth, o.ClassName, o.ObjectID)

	className := o.Ctx.Input.Param(":className")
	objectId := o.Ctx.Input.Param(":objectId")

	cls := bson.M{}
	cls["_id"] = objectId

	err := orm.TomatoDB.Remove(className, cls)
	if err != nil {
		log.Fatal(err)
	}

	data := bson.M{}
	o.Data["json"] = data
	o.ServeJSON()
}
<|endoftext|>


<commit_before>package controllers

import (
	"encoding/json"
	"net/http"
	"time"

	"github.com/dgrijalva/jwt-go"

	"github.com/julienschmidt/httprouter"
	"gopkg.in/mgo.v2"

	"github.com/herald-it/goncord/models"
	. "github.com/herald-it/goncord/utils"
	"github.com/herald-it/goncord/utils/querying"
)

type ServiceController struct {
	session *mgo.Session
}

func (sc ServiceController) GetDB() *mgo.Database {
	return sc.session.DB(models.Set.Database.DbName)
}

func NewServiceController(s *mgo.Session) *ServiceController {
	return &ServiceController{s}
}

// Logout removes the current token from
// the database. The next validation
// the user is not authorized.
func (sc ServiceController) Logout(
	w http.ResponseWriter,
	r *http.Request,
	ps httprouter.Params) *HttpError {

	collect := sc.GetDB().C(models.Set.Database.TokenTable)
	token := models.DumpToken{}

	tokenTmp, httpErr := getToken(r)
	if httpErr != nil {
		return httpErr
	}
	token.Token = tokenTmp

	if token.Token == "" {
		return &HttpError{nil, "Invalid token value.", 500}
	}

	if err := collect.Remove(token); err != nil {
		return &HttpError{err, "Delete token error.", 500}
	}

	return nil
}

// IsValid Check the token for validity.
// The token can be a cookie or transferred
// post the form. First we checked the cookies.
// If the token is valid, the response will contain
// user model in json format.
func (sc ServiceController) IsValid(
	w http.ResponseWriter,
	r *http.Request,
	ps httprouter.Params) *HttpError {

	collect := sc.GetDB().C(models.Set.Database.TokenTable)
	token := &models.DumpToken{}

	tokenTmp, httpErr := getToken(r)
	if httpErr != nil {
		return httpErr
	}
	token.Token = tokenTmp

	if token.Token == "" {
		return &HttpError{nil, "Invalid token value.", 500}
	}

	findDumpToken, err := querying.FindDumpToken(token, collect)
	if err != nil || findDumpToken == nil {
		return &HttpError{err, "Token not found.", 500}
	}

	tokenParse, err := jwt.Parse(findDumpToken.Token, nil)
	if checkLifeTime(tokenParse) {
		collect.Remove(findDumpToken)
		return &HttpError{nil, "Time token life has expired.", 500}
	}

	usr := new(models.User)
	usr.ID = findDumpToken.UserId

	findUsr, err := querying.FindUserID(usr, sc.GetDB().C(models.Set.Database.UserTable))
	if err != nil {
		return &HttpError{err, "User not found.", 500}
	}

	jsonUsr, err := json.Marshal(findUsr)
	if err != nil {
		return &HttpError{err, "User can not convert to json.", 500}
	}

	w.Write(jsonUsr)
	return nil
}

// getToken returns the token from the cookie,
// if the cookie is not present in the token, then looking in
// post the form if the token is not exist, then returned
// an empty string and error code.
func getToken(r *http.Request) (string, *HttpError) {
	jwtCookie, err := r.Cookie("jwt")
	if err != nil {
		if err := r.ParseForm(); err != nil {
			return "", &HttpError{err, "Post form can not be parsed.", 500}
		}

		token := r.PostForm.Get("jwt")
		return token, nil
	}

	return jwtCookie.Value, nil
}

// checkLifeTime checks the token lifetime.
func checkLifeTime(token *jwt.Token) bool {
	claims := token.Claims.(jwt.MapClaims)

	lifeTime := claims["iat"]
	timeSpan := time.Now().Unix() - int64(lifeTime.(float64))

	return timeSpan > (7 * 24 * 60 * 60)
}
<commit_msg>Change error info on more detail info.<commit_after>package controllers

import (
	"encoding/json"
	"net/http"
	"time"

	"github.com/dgrijalva/jwt-go"

	"github.com/julienschmidt/httprouter"
	"gopkg.in/mgo.v2"

	"github.com/herald-it/goncord/models"
	. "github.com/herald-it/goncord/utils"
	"github.com/herald-it/goncord/utils/querying"
)

type ServiceController struct {
	session *mgo.Session
}

func (sc ServiceController) GetDB() *mgo.Database {
	return sc.session.DB(models.Set.Database.DbName)
}

func NewServiceController(s *mgo.Session) *ServiceController {
	return &ServiceController{s}
}

// Logout removes the current token from
// the database. The next validation
// the user is not authorized.
func (sc ServiceController) Logout(
	w http.ResponseWriter,
	r *http.Request,
	ps httprouter.Params) *HttpError {

	collect := sc.GetDB().C(models.Set.Database.TokenTable)
	token := models.DumpToken{}

	tokenTmp, httpErr := getToken(r)
	if httpErr != nil {
		return httpErr
	}
	token.Token = tokenTmp

	if token.Token == "" {
		return &HttpError{nil, "Empty token value.", 500}
	}

	if err := collect.Remove(token); err != nil {
		return &HttpError{err, "Delete token error.", 500}
	}

	return nil
}

// IsValid Check the token for validity.
// The token can be a cookie or transferred
// post the form. First we checked the cookies.
// If the token is valid, the response will contain
// user model in json format.
func (sc ServiceController) IsValid(
	w http.ResponseWriter,
	r *http.Request,
	ps httprouter.Params) *HttpError {

	collect := sc.GetDB().C(models.Set.Database.TokenTable)
	token := &models.DumpToken{}

	tokenTmp, httpErr := getToken(r)
	if httpErr != nil {
		return httpErr
	}
	token.Token = tokenTmp

	if token.Token == "" {
		return &HttpError{nil, "Empty token value.", 500}
	}

	findDumpToken, err := querying.FindDumpToken(token, collect)
	if err != nil || findDumpToken == nil {
		return &HttpError{err, "Token not found.", 500}
	}

	tokenParse, err := jwt.Parse(findDumpToken.Token, nil)
	if checkLifeTime(tokenParse) {
		collect.Remove(findDumpToken)
		return &HttpError{nil, "Time token life has expired.", 500}
	}

	usr := new(models.User)
	usr.ID = findDumpToken.UserId

	findUsr, err := querying.FindUserID(usr, sc.GetDB().C(models.Set.Database.UserTable))
	if err != nil {
		return &HttpError{err, "User not found.", 500}
	}

	jsonUsr, err := json.Marshal(findUsr)
	if err != nil {
		return &HttpError{err, "User can not convert to json.", 500}
	}

	w.Write(jsonUsr)
	return nil
}

// getToken returns the token from the cookie,
// if the cookie is not present in the token, then looking in
// post the form if the token is not exist, then returned
// an empty string and error code.
func getToken(r *http.Request) (string, *HttpError) {
	jwtCookie, err := r.Cookie("jwt")
	if err != nil {
		if err := r.ParseForm(); err != nil {
			return "", &HttpError{err, "Post form can not be parsed.", 500}
		}

		token := r.PostForm.Get("jwt")
		return token, nil
	}

	return jwtCookie.Value, nil
}

// checkLifeTime checks the token lifetime.
func checkLifeTime(token *jwt.Token) bool {
	claims := token.Claims.(jwt.MapClaims)

	lifeTime := claims["iat"]
	timeSpan := time.Now().Unix() - int64(lifeTime.(float64))

	return timeSpan > (7 * 24 * 60 * 60)
}
<|endoftext|>


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

// Garbage collection benchmark: parse Go packages repeatedly.

package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"os"
	"path"
	"runtime"
	"strings"
	"time"
)

func isGoFile(dir *os.FileInfo) bool {
	return dir.IsRegular() &&
		!strings.HasPrefix(dir.Name, ".") && // ignore .files
		path.Ext(dir.Name) == ".go"
}

func isPkgFile(dir *os.FileInfo) bool {
	return isGoFile(dir) &&
		!strings.HasSuffix(dir.Name, "_test.go") // ignore test files
}

func pkgName(filename string) string {
	file, err := parser.ParseFile(filename, nil, nil, parser.PackageClauseOnly)
	if err != nil || file == nil {
		return ""
	}
	return file.Name.Name()
}

func parseDir(dirpath string) map[string]*ast.Package {
	// the package name is the directory name within its parent
	// (use dirname instead of path because dirname is clean; i.e. has no trailing '/')
	_, pkgname := path.Split(dirpath)

	// filter function to select the desired .go files
	filter := func(d *os.FileInfo) bool {
		if isPkgFile(d) {
			// Some directories contain main packages: Only accept
			// files that belong to the expected package so that
			// parser.ParsePackage doesn't return "multiple packages
			// found" errors.
			// Additionally, accept the special package name
			// fakePkgName if we are looking at cmd documentation.
			name := pkgName(dirpath + "/" + d.Name)
			return name == pkgname
		}
		return false
	}

	// get package AST
	pkgs, err := parser.ParseDir(dirpath, filter, parser.ParseComments)
	if err != nil {
		println("parse", dirpath, err.String())
		panic("fail")
	}
	return pkgs
}

func main() {
	st := &runtime.MemStats
	n := flag.Int("n", 4, "iterations")
	p := flag.Int("p", len(packages), "# of packages to keep in memory")
	flag.BoolVar(&st.DebugGC, "d", st.DebugGC, "print GC debugging info (pause times)")
	flag.Parse()

	var t0 int64
	pkgroot := runtime.GOROOT() + "/src/pkg/"
	for pass := 0; pass < 2; pass++ {
		// Once the heap is grown to full size, reset counters.
		// This hides the start-up pauses, which are much smaller
		// than the normal pauses and would otherwise make
		// the average look much better than it actually is.
		st.NumGC = 0
		st.PauseNs = 0
		t0 = time.Nanoseconds()

		for i := 0; i < *n; i++ {
			parsed := make([]map[string]*ast.Package, *p)
			for j := range parsed {
				parsed[j] = parseDir(pkgroot + packages[j%len(packages)])
			}
		}
		runtime.GC()
	}
	t1 := time.Nanoseconds()

	fmt.Printf("Alloc=%d/%d Heap=%d Mallocs=%d PauseTime=%.3f/%d = %.3f\n",
		st.Alloc, st.TotalAlloc,
		st.Sys,
		st.Mallocs, float64(st.PauseNs)/1e9,
		st.NumGC, float64(st.PauseNs)/1e9/float64(st.NumGC))

	fmt.Printf("%10s %10s %10s\n", "size", "#alloc", "#free")
	for _, s := range st.BySize {
		fmt.Printf("%10d %10d %10d\n", s.Size, s.Mallocs, s.Frees)
	}

	// Standard gotest benchmark output, collected by build dashboard.
	fmt.Printf("garbage.BenchmarkParser %d %d ns/op\n", *n, (t1-t0)/int64(*n))
	fmt.Printf("garbage.BenchmarkParserPause %d %d ns/op\n", st.NumGC, int64(st.PauseNs)/int64(st.NumGC))
}

var packages = []string{
	"archive/tar",
	"asn1",
	"big",
	"bufio",
	"bytes",
	"cmath",
	"compress/flate",
	"compress/gzip",
	"compress/zlib",
	"container/heap",
	"container/list",
	"container/ring",
	"container/vector",
	"crypto/aes",
	"crypto/block",
	"crypto/blowfish",
	"crypto/hmac",
	"crypto/md4",
	"crypto/md5",
	"crypto/rand",
	"crypto/rc4",
	"crypto/rsa",
	"crypto/sha1",
	"crypto/sha256",
	"crypto/sha512",
	"crypto/subtle",
	"crypto/tls",
	"crypto/x509",
	"crypto/xtea",
	"debug/dwarf",
	"debug/macho",
	"debug/elf",
	"debug/gosym",
	"debug/proc",
	"ebnf",
	"encoding/ascii85",
	"encoding/base64",
	"encoding/binary",
	"encoding/git85",
	"encoding/hex",
	"encoding/pem",
	"exec",
	"exp/datafmt",
	"exp/draw",
	"exp/eval",
	"exp/iterable",
	"expvar",
	"flag",
	"fmt",
	"go/ast",
	"go/doc",
	"go/parser",
	"go/printer",
	"go/scanner",
	"go/token",
	"gob",
	"hash",
	"hash/adler32",
	"hash/crc32",
	"hash/crc64",
	"http",
	"image",
	"image/jpeg",
	"image/png",
	"io",
	"io/ioutil",
	"json",
	"log",
	"math",
	"mime",
	"net",
	"nntp",
	"os",
	"os/signal",
	"patch",
	"path",
	"rand",
	"reflect",
	"regexp",
	"rpc",
	"runtime",
	"scanner",
	"sort",
	"strconv",
	"strings",
	"sync",
	"syscall",
	"syslog",
	"tabwriter",
	"template",
	"testing",
	"testing/iotest",
	"testing/quick",
	"testing/script",
	"time",
	"unicode",
	"utf8",
	"utf16",
	"websocket",
	"xml",
}
<commit_msg>test/garbage/parser: sync with recent parser changes<commit_after>// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Garbage collection benchmark: parse Go packages repeatedly.

package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"os"
	"path"
	"runtime"
	"strings"
	"time"
)

func isGoFile(dir *os.FileInfo) bool {
	return dir.IsRegular() &&
		!strings.HasPrefix(dir.Name, ".") && // ignore .files
		path.Ext(dir.Name) == ".go"
}

func isPkgFile(dir *os.FileInfo) bool {
	return isGoFile(dir) &&
		!strings.HasSuffix(dir.Name, "_test.go") // ignore test files
}

func pkgName(filename string) string {
	file, err := parser.ParseFile(filename, nil, parser.PackageClauseOnly)
	if err != nil || file == nil {
		return ""
	}
	return file.Name.Name
}

func parseDir(dirpath string) map[string]*ast.Package {
	// the package name is the directory name within its parent
	// (use dirname instead of path because dirname is clean; i.e. has no trailing '/')
	_, pkgname := path.Split(dirpath)

	// filter function to select the desired .go files
	filter := func(d *os.FileInfo) bool {
		if isPkgFile(d) {
			// Some directories contain main packages: Only accept
			// files that belong to the expected package so that
			// parser.ParsePackage doesn't return "multiple packages
			// found" errors.
			// Additionally, accept the special package name
			// fakePkgName if we are looking at cmd documentation.
			name := pkgName(dirpath + "/" + d.Name)
			return name == pkgname
		}
		return false
	}

	// get package AST
	pkgs, err := parser.ParseDir(dirpath, filter, parser.ParseComments)
	if err != nil {
		println("parse", dirpath, err.String())
		panic("fail")
	}
	return pkgs
}

func main() {
	st := &runtime.MemStats
	n := flag.Int("n", 4, "iterations")
	p := flag.Int("p", len(packages), "# of packages to keep in memory")
	flag.BoolVar(&st.DebugGC, "d", st.DebugGC, "print GC debugging info (pause times)")
	flag.Parse()

	var t0 int64
	pkgroot := runtime.GOROOT() + "/src/pkg/"
	for pass := 0; pass < 2; pass++ {
		// Once the heap is grown to full size, reset counters.
		// This hides the start-up pauses, which are much smaller
		// than the normal pauses and would otherwise make
		// the average look much better than it actually is.
		st.NumGC = 0
		st.PauseNs = 0
		t0 = time.Nanoseconds()

		for i := 0; i < *n; i++ {
			parsed := make([]map[string]*ast.Package, *p)
			for j := range parsed {
				parsed[j] = parseDir(pkgroot + packages[j%len(packages)])
			}
		}
		runtime.GC()
	}
	t1 := time.Nanoseconds()

	fmt.Printf("Alloc=%d/%d Heap=%d Mallocs=%d PauseTime=%.3f/%d = %.3f\n",
		st.Alloc, st.TotalAlloc,
		st.Sys,
		st.Mallocs, float64(st.PauseNs)/1e9,
		st.NumGC, float64(st.PauseNs)/1e9/float64(st.NumGC))

	fmt.Printf("%10s %10s %10s\n", "size", "#alloc", "#free")
	for _, s := range st.BySize {
		fmt.Printf("%10d %10d %10d\n", s.Size, s.Mallocs, s.Frees)
	}

	// Standard gotest benchmark output, collected by build dashboard.
	fmt.Printf("garbage.BenchmarkParser %d %d ns/op\n", *n, (t1-t0)/int64(*n))
	fmt.Printf("garbage.BenchmarkParserPause %d %d ns/op\n", st.NumGC, int64(st.PauseNs)/int64(st.NumGC))
}

var packages = []string{
	"archive/tar",
	"asn1",
	"big",
	"bufio",
	"bytes",
	"cmath",
	"compress/flate",
	"compress/gzip",
	"compress/zlib",
	"container/heap",
	"container/list",
	"container/ring",
	"container/vector",
	"crypto/aes",
	"crypto/block",
	"crypto/blowfish",
	"crypto/hmac",
	"crypto/md4",
	"crypto/md5",
	"crypto/rand",
	"crypto/rc4",
	"crypto/rsa",
	"crypto/sha1",
	"crypto/sha256",
	"crypto/sha512",
	"crypto/subtle",
	"crypto/tls",
	"crypto/x509",
	"crypto/xtea",
	"debug/dwarf",
	"debug/macho",
	"debug/elf",
	"debug/gosym",
	"debug/proc",
	"ebnf",
	"encoding/ascii85",
	"encoding/base64",
	"encoding/binary",
	"encoding/git85",
	"encoding/hex",
	"encoding/pem",
	"exec",
	"exp/datafmt",
	"exp/draw",
	"exp/eval",
	"exp/iterable",
	"expvar",
	"flag",
	"fmt",
	"go/ast",
	"go/doc",
	"go/parser",
	"go/printer",
	"go/scanner",
	"go/token",
	"gob",
	"hash",
	"hash/adler32",
	"hash/crc32",
	"hash/crc64",
	"http",
	"image",
	"image/jpeg",
	"image/png",
	"io",
	"io/ioutil",
	"json",
	"log",
	"math",
	"mime",
	"net",
	"nntp",
	"os",
	"os/signal",
	"patch",
	"path",
	"rand",
	"reflect",
	"regexp",
	"rpc",
	"runtime",
	"scanner",
	"sort",
	"strconv",
	"strings",
	"sync",
	"syscall",
	"syslog",
	"tabwriter",
	"template",
	"testing",
	"testing/iotest",
	"testing/quick",
	"testing/script",
	"time",
	"unicode",
	"utf8",
	"utf16",
	"websocket",
	"xml",
}
<|endoftext|>


<commit_before>package dashboard_graph

import (
	"fmt"
	"sort"
	"strings"

	h "github.com/Cepave/open-falcon-backend/modules/f2e-api/app/helper"
	m "github.com/Cepave/open-falcon-backend/modules/f2e-api/app/model/dashboard"
	"github.com/gin-gonic/gin"
)

type APIGraphCreateReqDataWithNewScreenInputs struct {
	ScreenName string   `json:"screen_name" form:"screen_name" binding:"required"`
	Title      string   `json:"title" form:"title" binding:"required"`
	Endpoints  []string `json:"endpoints" form:"endpoints" binding:"required"`
	Counters   []string `json:"counters" form:"counters" binding:"required"`
	TimeSpan   int64    `json:"timespan" form:"timespan"`
	GraphType  string   `json:"graph_type" form:"graph_type" binding:"required"`
	Method     string   `json:"method" form:"method"`
	Position   int64    `json:"position" form:"position"`
	FalconTags string   `json:"falcon_tags" form:"falcon_tags"`
}

func (mine APIGraphCreateReqDataWithNewScreenInputs) Check() (err error) {
	sc := m.DashboardScreen{Name: mine.ScreenName}
	// check screen_id
	if sc.ExistName() {
		err = fmt.Errorf("screen name:%v already existing", mine.ScreenName)
		return
	}

	if mine.TimeSpan%60 != 0 {
		err = fmt.Errorf("value of timespan is not vaild: %v", mine.TimeSpan)
		return
	}

	if mine.GraphType != "h" && mine.GraphType != "k" && mine.GraphType != "a" {
		err = fmt.Errorf("value of graph_type only accpet 'k' or 'h' or 'a', you typed: %v", mine.GraphType)
		return
	}
	return
}

func GraphCreateReqDataWithNewScreen(c *gin.Context) {
	inputs := APIGraphCreateReqDataWithNewScreenInputs{}
	// set default value
	inputs.TimeSpan = 3600
	inputs.GraphType = "h"
	if err := c.Bind(&inputs); err != nil {
		h.JSONR(c, badstatus, err)
		return
	}

	if err := inputs.Check(); err != nil {
		h.JSONR(c, badstatus, err)
		return
	}

	dt := db.Dashboard.Begin()
	sc := m.DashboardScreen{Name: inputs.ScreenName}
	dt = dt.Save(&sc)
	if dt.Error != nil {
		h.JSONR(c, badstatus, dt.Error)
		dt.Rollback()
		return
	}

	es := inputs.Endpoints
	cs := inputs.Counters
	sort.Strings(es)
	sort.Strings(cs)
	esString := strings.Join(es, TMP_GRAPH_FILED_DELIMITER)
	csString := strings.Join(cs, TMP_GRAPH_FILED_DELIMITER)
	user, _ := h.GetUser(c)

	d := m.DashboardGraph{
		Title:     inputs.Title,
		Hosts:     esString,
		Counters:  csString,
		ScreenId:  sc.ID,
		TimeSpan:  inputs.TimeSpan,
		GraphType: inputs.GraphType,
		Method:    inputs.Method,
		Position:  inputs.Position,
		Creator:   user.Name,
	}
	dt = dt.Save(&d)
	if dt.Error != nil {
		dt.Rollback()
		h.JSONR(c, badstatus, dt.Error)
		return
	}

	var lid []int
	dt = dt.Table(d.TableName()).Raw("select LAST_INSERT_ID() as id").Pluck("id", &lid)
	if dt.Error != nil {
		dt.Rollback()
		h.JSONR(c, badstatus, dt.Error)
		return
	}
	dt.Commit()
	aid := lid[0]

	h.JSONR(c, map[string]interface{}{"id": aid, "screen_id": d.ScreenId})

}
<commit_msg>add screen_name response for create_graph_screen api<commit_after>package dashboard_graph

import (
	"fmt"
	"sort"
	"strings"

	h "github.com/Cepave/open-falcon-backend/modules/f2e-api/app/helper"
	m "github.com/Cepave/open-falcon-backend/modules/f2e-api/app/model/dashboard"
	"github.com/gin-gonic/gin"
)

type APIGraphCreateReqDataWithNewScreenInputs struct {
	ScreenName string   `json:"screen_name" form:"screen_name" binding:"required"`
	Title      string   `json:"title" form:"title" binding:"required"`
	Endpoints  []string `json:"endpoints" form:"endpoints" binding:"required"`
	Counters   []string `json:"counters" form:"counters" binding:"required"`
	TimeSpan   int64    `json:"timespan" form:"timespan"`
	GraphType  string   `json:"graph_type" form:"graph_type" binding:"required"`
	Method     string   `json:"method" form:"method"`
	Position   int64    `json:"position" form:"position"`
	FalconTags string   `json:"falcon_tags" form:"falcon_tags"`
}

func (mine APIGraphCreateReqDataWithNewScreenInputs) Check() (err error) {
	sc := m.DashboardScreen{Name: mine.ScreenName}
	// check screen_id
	if sc.ExistName() {
		err = fmt.Errorf("screen name:%v already existing", mine.ScreenName)
		return
	}

	if mine.TimeSpan%60 != 0 {
		err = fmt.Errorf("value of timespan is not vaild: %v", mine.TimeSpan)
		return
	}

	if mine.GraphType != "h" && mine.GraphType != "k" && mine.GraphType != "a" {
		err = fmt.Errorf("value of graph_type only accpet 'k' or 'h' or 'a', you typed: %v", mine.GraphType)
		return
	}
	return
}

func GraphCreateReqDataWithNewScreen(c *gin.Context) {
	inputs := APIGraphCreateReqDataWithNewScreenInputs{}
	// set default value
	inputs.TimeSpan = 3600
	inputs.GraphType = "h"
	if err := c.Bind(&inputs); err != nil {
		h.JSONR(c, badstatus, err)
		return
	}

	if err := inputs.Check(); err != nil {
		h.JSONR(c, badstatus, err)
		return
	}

	dt := db.Dashboard.Begin()
	sc := m.DashboardScreen{Name: inputs.ScreenName}
	dt = dt.Save(&sc)
	if dt.Error != nil {
		h.JSONR(c, badstatus, dt.Error)
		dt.Rollback()
		return
	}

	es := inputs.Endpoints
	cs := inputs.Counters
	sort.Strings(es)
	sort.Strings(cs)
	esString := strings.Join(es, TMP_GRAPH_FILED_DELIMITER)
	csString := strings.Join(cs, TMP_GRAPH_FILED_DELIMITER)
	user, _ := h.GetUser(c)

	d := m.DashboardGraph{
		Title:     inputs.Title,
		Hosts:     esString,
		Counters:  csString,
		ScreenId:  sc.ID,
		TimeSpan:  inputs.TimeSpan,
		GraphType: inputs.GraphType,
		Method:    inputs.Method,
		Position:  inputs.Position,
		Creator:   user.Name,
	}
	dt = dt.Save(&d)
	if dt.Error != nil {
		dt.Rollback()
		h.JSONR(c, badstatus, dt.Error)
		return
	}

	var lid []int
	dt = dt.Table(d.TableName()).Raw("select LAST_INSERT_ID() as id").Pluck("id", &lid)
	if dt.Error != nil {
		dt.Rollback()
		h.JSONR(c, badstatus, dt.Error)
		return
	}
	dt.Commit()
	aid := lid[0]

	h.JSONR(c, map[string]interface{}{"id": aid, "screen_id": d.ScreenId, "screen_name": inputs.ScreenName})
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/Dieterbe/statsd-go"
	"github.com/vimeo/statsdaemon"
	"github.com/vimeo/statsdaemon/timers"
	"io"
	"net"
	"os"
	"runtime/pprof"
	"strings"
	"time"
    "runtime"
)

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var memprofile = flag.String("memprofile", "", "write memory profile to this file")

func main() {
    runtime.GOMAXPROCS(4)
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			panic(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}
	if *memprofile != "" {
		f, err := os.Create(*memprofile)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		defer pprof.WriteHeapProfile(f)
	}

	cl, clerr := statsd.NewClient(true, "localhost:8125", "statsd-tester")
	laddr, err := net.ResolveTCPAddr("tcp", "localhost:2003")
	if nil != clerr {
		panic(clerr)
	}
	if nil != err {
		panic(err)
	}
	w := NewWatcher(laddr)
	go w.Run()
	pct := timers.Percentiles{}
	daemon := statsdaemon.New("test", ":8125", ":8126", ":2003", "rates.", "timers.", "gauges.", pct, 10, 1000, 1000, nil, false)
	tick := time.Tick(time.Duration(1) * time.Second)
	go func() {
		for range tick {
			// send 1M packets per second in theory. in practice this takes more than a second
            msg := []byte("test.counter:1|c")
			for i := 0; i < 1000000; i++ {
				//cl.Increment("test-counter")
                cl.SendRaw(msg)
			}
		}
	}()

	daemon.Run()
}

type watcher struct {
	l      *net.TCPListener
	seen   int
	values chan string
}

func NewWatcher(laddr *net.TCPAddr) *watcher {
	l, err := net.ListenTCP("tcp", laddr)
	if nil != err {
		panic(err)
	}
	return &watcher{
		l,
		0,
		make(chan string),
	}
}

func (w *watcher) Run() {
	go w.accept()
	counter_per_s_key := "service_is_statsdaemon.instance_is_test.direction_is_in.statsd_type_is_counter.target_type_is_rate.unit_is_Metricps"
	for {
		select {
		case str := <-w.values:
			if strings.HasPrefix(str, counter_per_s_key) {
				vals := strings.Fields(str)
				fmt.Println("counters received per second:", vals[1])
				w.seen += 1
				if w.seen == 10 {
					os.Exit(0)
				}
			}
		}
	}
}

func (w *watcher) accept() {
	for {
		c, err := w.l.AcceptTCP()
		if nil != err {
			panic(err)
		}
		go w.handle(c)
	}
}
func (w *watcher) handle(c *net.TCPConn) {
	defer c.Close()
	r := bufio.NewReaderSize(c, 4096)
	for {
		buf, _, err := r.ReadLine()
		if nil != err {
			if io.EOF != err {
				panic(err)
			}
			break
		}
		str := string(buf)
		w.values <- str
	}
}
<commit_msg>gofmt<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/Dieterbe/statsd-go"
	"github.com/vimeo/statsdaemon"
	"github.com/vimeo/statsdaemon/timers"
	"io"
	"net"
	"os"
	"runtime"
	"runtime/pprof"
	"strings"
	"time"
)

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
var memprofile = flag.String("memprofile", "", "write memory profile to this file")

func main() {
	runtime.GOMAXPROCS(4)
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			panic(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}
	if *memprofile != "" {
		f, err := os.Create(*memprofile)
		if err != nil {
			panic(err)
		}
		defer f.Close()
		defer pprof.WriteHeapProfile(f)
	}

	cl, clerr := statsd.NewClient(true, "localhost:8125", "statsd-tester")
	laddr, err := net.ResolveTCPAddr("tcp", "localhost:2003")
	if nil != clerr {
		panic(clerr)
	}
	if nil != err {
		panic(err)
	}
	w := NewWatcher(laddr)
	go w.Run()
	pct := timers.Percentiles{}
	daemon := statsdaemon.New("test", ":8125", ":8126", ":2003", "rates.", "timers.", "gauges.", pct, 10, 1000, 1000, nil, false)
	tick := time.Tick(time.Duration(1) * time.Second)
	go func() {
		for range tick {
			// send 1M packets per second in theory. in practice this takes more than a second
			msg := []byte("test.counter:1|c")
			for i := 0; i < 1000000; i++ {
				//cl.Increment("test-counter")
				cl.SendRaw(msg)
			}
		}
	}()

	daemon.Run()
}

type watcher struct {
	l      *net.TCPListener
	seen   int
	values chan string
}

func NewWatcher(laddr *net.TCPAddr) *watcher {
	l, err := net.ListenTCP("tcp", laddr)
	if nil != err {
		panic(err)
	}
	return &watcher{
		l,
		0,
		make(chan string),
	}
}

func (w *watcher) Run() {
	go w.accept()
	counter_per_s_key := "service_is_statsdaemon.instance_is_test.direction_is_in.statsd_type_is_counter.target_type_is_rate.unit_is_Metricps"
	for {
		select {
		case str := <-w.values:
			if strings.HasPrefix(str, counter_per_s_key) {
				vals := strings.Fields(str)
				fmt.Println("counters received per second:", vals[1])
				w.seen += 1
				if w.seen == 10 {
					os.Exit(0)
				}
			}
		}
	}
}

func (w *watcher) accept() {
	for {
		c, err := w.l.AcceptTCP()
		if nil != err {
			panic(err)
		}
		go w.handle(c)
	}
}
func (w *watcher) handle(c *net.TCPConn) {
	defer c.Close()
	r := bufio.NewReaderSize(c, 4096)
	for {
		buf, _, err := r.ReadLine()
		if nil != err {
			if io.EOF != err {
				panic(err)
			}
			break
		}
		str := string(buf)
		w.values <- str
	}
}
<|endoftext|>


<commit_before>package main

import (
	"container/heap"
	"context"
	"time"

	"github.com/dshearer/jobber/common"
	"github.com/dshearer/jobber/jobfile"
)

func nextRunTime(job *jobfile.Job, now time.Time) *time.Time {
	/*
	 * We test every second from now till 2 years from now,
	 * looking for a time that satisfies the job's schedule
	 * criteria.
	 */

	var year time.Duration = time.Hour * 24 * 365
	var max time.Time = now.Add(2 * year)
	for next := now; next.Before(max); next = next.Add(time.Second) {
		if job.FullTimeSpec.Satisfied(next) {
			return &next
		}
	}

	return nil
}

/*
 * jobQueueImpl is a priority queue containing Jobs that sorts
 * them by next run time.
 */
type jobQueueImpl []*jobfile.Job // implements heap.Interface

func (q jobQueueImpl) Len() int {
	return len(q)
}

func (q jobQueueImpl) Less(i, j int) bool {
	return q[i].NextRunTime.Before(*q[j].NextRunTime)
}

func (q jobQueueImpl) Swap(i, j int) {
	q[i], q[j] = q[j], q[i]
}

func (q *jobQueueImpl) Push(x interface{}) {
	*q = append(*q, x.(*jobfile.Job))
}

func (q *jobQueueImpl) Pop() interface{} {
	n := len(*q)
	if n == 0 {
		return nil
	} else {
		item := (*q)[n-1]
		*q = (*q)[0 : n-1]
		return item
	}
}

/*
 * A priority queue containing jobs.  It's a public
 * wrapper for an instance of jobQueueImpl.
 */
type JobQueue struct {
	q jobQueueImpl
}

func (jq *JobQueue) SetJobs(now time.Time, jobs []*jobfile.Job) {
	jq.q = make(jobQueueImpl, 0)
	heap.Init(&jq.q)

	for i := 0; i < len(jobs); i++ {
		var job *jobfile.Job = jobs[i]
		job.NextRunTime = nextRunTime(job, now)
		if job.NextRunTime != nil {
			heap.Push(&jq.q, job)
		}
	}
}

func (jq *JobQueue) Empty() bool {
	return jq.q.Len() == 0
}

/*!
 * Get the next job to run, after sleeping until the time it's supposed
 * to run.
 *
 * @return The next job to run, or nil if the context has been canceled.
 */
func (jq *JobQueue) Pop(ctx context.Context, now time.Time) *jobfile.Job {
	if jq.Empty() {
		// just wait till the context has been canceled
		common.Logger.Println("Queue: waiting...")
		<-ctx.Done()
		common.Logger.Println("Queue: done")
		return nil

	} else {
		// get next-scheduled job
		job := heap.Pop(&jq.q).(*jobfile.Job)

		var timeFmt = "Jan _2 15:04:05"

		common.Logger.Printf("Next job to run is %v, at %v.", job.Name,
			job.NextRunTime.Format(timeFmt))

		// sleep till it's time to run it
		for now.Before(*job.NextRunTime) {
			sleepDur := job.NextRunTime.Sub(now)

			common.Logger.Printf("It is now %v.", now.Format(timeFmt))
			common.Logger.Printf("Sleeping for %v.", sleepDur)

			afterChan := time.After(sleepDur)
			select {
			case now = <-afterChan:
			case <-ctx.Done():
				// abort!
				heap.Push(&jq.q, job)
				return nil
			}
		}

		common.Logger.Printf("It is now %v, which is NOT before %v",
			now.Format(timeFmt), job.NextRunTime.Format(timeFmt))

		// schedule this job's next run
		job.NextRunTime = nextRunTime(job, now.Add(time.Second))
		if job.NextRunTime != nil {
			heap.Push(&jq.q, job)
		}

		// decide whether we really should run this job
		if job.ShouldRun() {
			common.Logger.Printf("Running %v", job.Name)
			return job
		} else {
			// skip this job
			common.Logger.Printf("Skipping %v", job.Name)
			return jq.Pop(ctx, now)
		}
	}
}
<commit_msg>(#192) Bugfix in queue.go: Job execed multiple times<commit_after>package main

import (
	"container/heap"
	"context"
	"time"

	"github.com/dshearer/jobber/common"
	"github.com/dshearer/jobber/jobfile"
)

func nextRunTime(job *jobfile.Job, now time.Time) *time.Time {
	/*
	 * We test every second from now till 2 years from now,
	 * looking for a time that satisfies the job's schedule
	 * criteria.
	 */

	var year time.Duration = time.Hour * 24 * 365
	var max time.Time = now.Add(2 * year)
	for next := now; next.Before(max); next = next.Add(time.Second) {
		if job.FullTimeSpec.Satisfied(next) {
			return &next
		}
	}

	return nil
}

/*
 * jobQueueImpl is a priority queue containing Jobs that sorts
 * them by next run time.
 */
type jobQueueImpl []*jobfile.Job // implements heap.Interface

func (q jobQueueImpl) Len() int {
	return len(q)
}

func (q jobQueueImpl) Less(i, j int) bool {
	return q[i].NextRunTime.Before(*q[j].NextRunTime)
}

func (q jobQueueImpl) Swap(i, j int) {
	q[i], q[j] = q[j], q[i]
}

func (q *jobQueueImpl) Push(x interface{}) {
	*q = append(*q, x.(*jobfile.Job))
}

func (q *jobQueueImpl) Pop() interface{} {
	n := len(*q)
	if n == 0 {
		return nil
	} else {
		item := (*q)[n-1]
		*q = (*q)[0 : n-1]
		return item
	}
}

/*
 * A priority queue containing jobs.  It's a public
 * wrapper for an instance of jobQueueImpl.
 */
type JobQueue struct {
	q jobQueueImpl
}

func (jq *JobQueue) SetJobs(now time.Time, jobs []*jobfile.Job) {
	jq.q = make(jobQueueImpl, 0)
	heap.Init(&jq.q)

	for i := 0; i < len(jobs); i++ {
		var job *jobfile.Job = jobs[i]
		job.NextRunTime = nextRunTime(job, now)
		if job.NextRunTime != nil {
			heap.Push(&jq.q, job)
		}
	}
}

func (jq *JobQueue) Empty() bool {
	return jq.q.Len() == 0
}

/*!
 * Get the next job to run, after sleeping until the time it's supposed
 * to run.
 *
 * @return The next job to run, or nil if the context has been canceled.
 */
func (jq *JobQueue) Pop(ctx context.Context, now time.Time) *jobfile.Job {
	if jq.Empty() {
		// just wait till the context has been canceled
		common.Logger.Println("Queue: waiting...")
		<-ctx.Done()
		common.Logger.Println("Queue: done")
		return nil

	} else {
		// get next-scheduled job
		job := heap.Pop(&jq.q).(*jobfile.Job)

		var timeFmt = "Jan _2 15:04:05"

		common.Logger.Printf("Next job to run is %v, at %v.", job.Name,
			job.NextRunTime.Format(timeFmt))

		/*
			Golang has a bug in its time package.  We must avoid using most of the
			Time methods.  Cf. https://github.com/golang/go/issues/27090
		*/

		// sleep till it's time to run it
		for now.UnixNano() < job.NextRunTime.UnixNano() {
			nanoDiff := job.NextRunTime.UnixNano() - now.UnixNano()
			sleepDur := time.Duration(nanoDiff) * time.Nanosecond

			common.Logger.Printf("It is now %v.", now.Format(timeFmt))
			common.Logger.Printf("Sleeping for %v.", sleepDur)

			afterChan := time.After(sleepDur)
			select {
			case now = <-afterChan:
			case <-ctx.Done():
				// abort!
				heap.Push(&jq.q, job)
				return nil
			}
		}

		common.Logger.Printf("It is now %v, which is NOT before %v",
			now.Format(timeFmt), job.NextRunTime.Format(timeFmt))

		// schedule this job's next run
		job.NextRunTime = nextRunTime(job, now.Add(time.Second))
		if job.NextRunTime != nil {
			heap.Push(&jq.q, job)
		}

		// decide whether we really should run this job
		if job.ShouldRun() {
			common.Logger.Printf("Running %v", job.Name)
			return job
		} else {
			// skip this job
			common.Logger.Printf("Skipping %v", job.Name)
			return jq.Pop(ctx, now)
		}
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2017 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 (
	"encoding/xml"
	"fmt"
	"log"
	"math/rand"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
	"time"
)

type testCase struct {
	XMLName   xml.Name `xml:"testcase"`
	ClassName string   `xml:"classname,attr"`
	Name      string   `xml:"name,attr"`
	Time      float64  `xml:"time,attr"`
	Failure   string   `xml:"failure,omitempty"`
}

type TestSuite struct {
	XMLName  xml.Name `xml:"testsuite"`
	Failures int      `xml:"failures,attr"`
	Tests    int      `xml:"tests,attr"`
	Time     float64  `xml:"time,attr"`
	Cases    []testCase
}

// append(errs, err) if err != nil
func appendError(errs []error, err error) []error {
	if err != nil {
		return append(errs, err)
	}
	return errs
}

func writeXML(dump string, start time.Time) {
	suite.Time = time.Since(start).Seconds()
	out, err := xml.MarshalIndent(&suite, "", "    ")
	if err != nil {
		log.Fatalf("Could not marshal XML: %s", err)
	}
	path := filepath.Join(dump, "junit_runner.xml")
	f, err := os.Create(path)
	if err != nil {
		log.Fatalf("Could not create file: %s", err)
	}
	defer f.Close()
	if _, err := f.WriteString(xml.Header); err != nil {
		log.Fatalf("Error writing XML header: %s", err)
	}
	if _, err := f.Write(out); err != nil {
		log.Fatalf("Error writing XML data: %s", err)
	}
	log.Printf("Saved XML output to %s.", path)
}

// return f(), adding junit xml testcase result for name
func xmlWrap(name string, f func() error) error {
	start := time.Now()
	err := f()
	duration := time.Since(start)
	c := testCase{
		Name:      name,
		ClassName: "e2e.go",
		Time:      duration.Seconds(),
	}
	if err != nil {
		c.Failure = err.Error()
		suite.Failures++
	}
	suite.Cases = append(suite.Cases, c)
	suite.Tests++
	return err
}

var (
	interruptTimeout = time.Duration(10 * time.Minute)
	terminateTimeout = time.Duration(5 * time.Minute) // terminate 5 minutes after SIGINT is sent.

	interrupt = time.NewTimer(interruptTimeout) // interrupt testing at this time.
	terminate = time.NewTimer(time.Duration(0)) // terminate testing at this time.

	suite TestSuite
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz")

// return cmd.Output(), potentially timing out in the process.
func output(cmd *exec.Cmd) ([]byte, error) {
	interrupt.Reset(interruptTimeout)
	stepName := strings.Join(cmd.Args, " ")
	cmd.Stderr = os.Stderr

	log.Printf("Running: %v", stepName)
	defer func(start time.Time) {
		log.Printf("Step '%s' finished in %s", stepName, time.Since(start))
	}(time.Now())

	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	type result struct {
		bytes []byte
		err   error
	}
	finished := make(chan result)
	go func() {
		b, err := cmd.Output()
		finished <- result{b, err}
	}()
	for {
		select {
		case <-terminate.C:
			terminate.Reset(time.Duration(0)) // Kill subsequent processes immediately.
			syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
			cmd.Process.Kill()
			return nil, fmt.Errorf("Terminate testing after 15m after %s timeout during %s", interruptTimeout, stepName)
		case <-interrupt.C:
			log.Printf("Interrupt testing after %s timeout. Will terminate in another %s", interruptTimeout, terminateTimeout)
			terminate.Reset(terminateTimeout)
			if err := syscall.Kill(-cmd.Process.Pid, syscall.SIGINT); err != nil {
				log.Printf("Failed to interrupt %v. Will terminate immediately: %v", stepName, err)
				syscall.Kill(-cmd.Process.Pid, syscall.SIGTERM)
				cmd.Process.Kill()
			}
		case fin := <-finished:
			return fin.bytes, fin.err
		}
	}
}

func randStringRunes(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func main() {
	matches, err := filepath.Glob("stable/*")
	defer writeXML("/workspace/_artifacts", time.Now())
	if !terminate.Stop() {
		<-terminate.C // Drain the value if necessary.
	}

	if !interrupt.Stop() {
		<-interrupt.C // Drain value
	}

	if err != nil {
		fmt.Println(err)
		return
	}

	for _, dir := range matches {
		ns := randStringRunes(10)
		rel := randStringRunes(3)

		xmlWrap(fmt.Sprintf("lint %s", dir), func() error {
			_, execErr := output(exec.Command("linux-amd64/helm", "lint", dir))
			return execErr
		})

		xmlWrap(fmt.Sprintf("install %s", dir), func() error {
			o, execErr := output(exec.Command("linux-amd64/helm", "install", dir, "--namespace", ns, "--name", rel, "--wait"))
			if execErr != nil {
				return fmt.Errorf("%s Command output: %s", execErr, string(o[:]))
			}
			return nil
		})

		xmlWrap(fmt.Sprintf("test %s", dir), func() error {
			o, execErr := output(exec.Command("linux-amd64/helm", "test", rel))
			if execErr != nil {
				return fmt.Errorf("%s Command output: %s", execErr, string(o[:]))
			}
			return nil
		})

		xmlWrap(fmt.Sprintf("purge %s", dir), func() error {
			o, execErr := output(exec.Command("linux-amd64/helm", "delete", rel, "--purge"))
			if execErr != nil {
				return fmt.Errorf("%s Command output: %s", execErr, string(o[:]))
			}
			return nil
		})
	}
}
<commit_msg>Update junit file name (#937)<commit_after>/*
Copyright 2017 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 (
	"encoding/xml"
	"fmt"
	"log"
	"math/rand"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
	"time"
)

type testCase struct {
	XMLName   xml.Name `xml:"testcase"`
	ClassName string   `xml:"classname,attr"`
	Name      string   `xml:"name,attr"`
	Time      float64  `xml:"time,attr"`
	Failure   string   `xml:"failure,omitempty"`
}

type TestSuite struct {
	XMLName  xml.Name `xml:"testsuite"`
	Failures int      `xml:"failures,attr"`
	Tests    int      `xml:"tests,attr"`
	Time     float64  `xml:"time,attr"`
	Cases    []testCase
}

// append(errs, err) if err != nil
func appendError(errs []error, err error) []error {
	if err != nil {
		return append(errs, err)
	}
	return errs
}

func writeXML(dump string, start time.Time) {
	suite.Time = time.Since(start).Seconds()
	out, err := xml.MarshalIndent(&suite, "", "    ")
	if err != nil {
		log.Fatalf("Could not marshal XML: %s", err)
	}
	path := filepath.Join(dump, "junit_01.xml")
	f, err := os.Create(path)
	if err != nil {
		log.Fatalf("Could not create file: %s", err)
	}
	defer f.Close()
	if _, err := f.WriteString(xml.Header); err != nil {
		log.Fatalf("Error writing XML header: %s", err)
	}
	if _, err := f.Write(out); err != nil {
		log.Fatalf("Error writing XML data: %s", err)
	}
	log.Printf("Saved XML output to %s.", path)
}

// return f(), adding junit xml testcase result for name
func xmlWrap(name string, f func() error) error {
	start := time.Now()
	err := f()
	duration := time.Since(start)
	c := testCase{
		Name:      name,
		ClassName: "e2e.go",
		Time:      duration.Seconds(),
	}
	if err != nil {
		c.Failure = err.Error()
		suite.Failures++
	}
	suite.Cases = append(suite.Cases, c)
	suite.Tests++
	return err
}

var (
	interruptTimeout = time.Duration(10 * time.Minute)
	terminateTimeout = time.Duration(5 * time.Minute) // terminate 5 minutes after SIGINT is sent.

	interrupt = time.NewTimer(interruptTimeout) // interrupt testing at this time.
	terminate = time.NewTimer(time.Duration(0)) // terminate testing at this time.

	suite TestSuite
)

func init() {
	rand.Seed(time.Now().UnixNano())
}

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz")

// return cmd.Output(), potentially timing out in the process.
func output(cmd *exec.Cmd) ([]byte, error) {
	interrupt.Reset(interruptTimeout)
	stepName := strings.Join(cmd.Args, " ")
	cmd.Stderr = os.Stderr

	log.Printf("Running: %v", stepName)
	defer func(start time.Time) {
		log.Printf("Step '%s' finished in %s", stepName, time.Since(start))
	}(time.Now())

	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	type result struct {
		bytes []byte
		err   error
	}
	finished := make(chan result)
	go func() {
		b, err := cmd.Output()
		finished <- result{b, err}
	}()
	for {
		select {
		case <-terminate.C:
			terminate.Reset(time.Duration(0)) // Kill subsequent processes immediately.
			syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
			cmd.Process.Kill()
			return nil, fmt.Errorf("Terminate testing after 15m after %s timeout during %s", interruptTimeout, stepName)
		case <-interrupt.C:
			log.Printf("Interrupt testing after %s timeout. Will terminate in another %s", interruptTimeout, terminateTimeout)
			terminate.Reset(terminateTimeout)
			if err := syscall.Kill(-cmd.Process.Pid, syscall.SIGINT); err != nil {
				log.Printf("Failed to interrupt %v. Will terminate immediately: %v", stepName, err)
				syscall.Kill(-cmd.Process.Pid, syscall.SIGTERM)
				cmd.Process.Kill()
			}
		case fin := <-finished:
			return fin.bytes, fin.err
		}
	}
}

func randStringRunes(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letterRunes[rand.Intn(len(letterRunes))]
	}
	return string(b)
}

func main() {
	matches, err := filepath.Glob("stable/*")
	defer writeXML("/workspace/_artifacts", time.Now())
	if !terminate.Stop() {
		<-terminate.C // Drain the value if necessary.
	}

	if !interrupt.Stop() {
		<-interrupt.C // Drain value
	}

	if err != nil {
		fmt.Println(err)
		return
	}

	for _, dir := range matches {
		ns := randStringRunes(10)
		rel := randStringRunes(3)

		xmlWrap(fmt.Sprintf("lint %s", dir), func() error {
			_, execErr := output(exec.Command("linux-amd64/helm", "lint", dir))
			return execErr
		})

		xmlWrap(fmt.Sprintf("install %s", dir), func() error {
			o, execErr := output(exec.Command("linux-amd64/helm", "install", dir, "--namespace", ns, "--name", rel, "--wait"))
			if execErr != nil {
				return fmt.Errorf("%s Command output: %s", execErr, string(o[:]))
			}
			return nil
		})

		xmlWrap(fmt.Sprintf("test %s", dir), func() error {
			o, execErr := output(exec.Command("linux-amd64/helm", "test", rel))
			if execErr != nil {
				return fmt.Errorf("%s Command output: %s", execErr, string(o[:]))
			}
			return nil
		})

		xmlWrap(fmt.Sprintf("purge %s", dir), func() error {
			o, execErr := output(exec.Command("linux-amd64/helm", "delete", rel, "--purge"))
			if execErr != nil {
				return fmt.Errorf("%s Command output: %s", execErr, string(o[:]))
			}
			return nil
		})
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 Google Inc. All Rights Reserved.
//
// 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 watcher holds tools for loglist-files versioning and updates propagation.
package watcher

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

	"github.com/google/certificate-transparency-go/x509util"
	"github.com/sergi/go-diff/diffmatchpatch"
)

// Diff regularly check data at path provided, notifies if changes detected.
type Diff struct {
	latest []byte

	synced []byte
	diffs  []diffmatchpatch.Diff
	// mu guards all data-fields: latest, synced and diffs.
	mu sync.Mutex

	// Exactly one of url/filepath fields is specified.
	url      string
	filepath string

	checkInterval time.Duration
	ticker        *time.Ticker

	events chan<- DiffEvent
}

// DiffEvent refelects diff/error detection.
type DiffEvent struct {
	Diffs []diffmatchpatch.Diff
	Err   error
}

// NewDiff is factory for Diff.
func NewDiff(ctx context.Context, path string, isPathURL bool, checkInterval time.Duration, events chan<- DiffEvent) *Diff {
	var d Diff
	if isPathURL {
		d.url = path
	} else {
		d.filepath = path
	}
	d.checkInterval = checkInterval
	d.events = events

	d.init(ctx)
	return &d
}

func (d *Diff) init(ctx context.Context) {
	d.checkUpdate()
	d.ticker = time.NewTicker(d.checkInterval)
	go func() {
		select {
		case <-ctx.Done():
			d.ticker.Stop()
		case <-d.ticker.C:
			d.checkUpdate()
		}
	}()
}

func (d *Diff) checkUpdate() {
	var path string
	if len(d.url) > 0 {
		path = d.url
	} else {
		path = d.filepath
	}
	llData, err := x509util.ReadFileOrURL(path, &http.Client{Timeout: time.Second * 10})
	if err != nil {
		d.events <- DiffEvent{Err: err}
		return
	}
	d.mu.Lock()
	defer d.mu.Unlock()
	d.latest = llData
	// Compare data as strings
	dmp := diffmatchpatch.New()
	diffs := dmp.DiffMain(string(d.synced), string(d.latest), false)
	d.diffs = diffs
	if len(diffs) > 0 && d.events != nil {
		d.events <- DiffEvent{Diffs: d.diffs}
	}
}

func (d *Diff) sync() {
	d.mu.Lock()
	d.synced = d.latest
	d.diffs = []diffmatchpatch.Diff{}
	d.mu.Unlock()
}

// GetSyncedData provides acces to Diff data.
func (d *Diff) GetSyncedData() []byte {
	d.mu.Lock()
	defer d.mu.Unlock()
	return d.synced
}
<commit_msg>watcher: silence warning about as-yet unused function<commit_after>// Copyright 2018 Google Inc. All Rights Reserved.
//
// 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 watcher holds tools for loglist-files versioning and updates propagation.
package watcher

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

	"github.com/google/certificate-transparency-go/x509util"
	"github.com/sergi/go-diff/diffmatchpatch"
)

// Diff regularly check data at path provided, notifies if changes detected.
type Diff struct {
	latest []byte

	synced []byte
	diffs  []diffmatchpatch.Diff
	// mu guards all data-fields: latest, synced and diffs.
	mu sync.Mutex

	// Exactly one of url/filepath fields is specified.
	url      string
	filepath string

	checkInterval time.Duration
	ticker        *time.Ticker

	events chan<- DiffEvent
}

// DiffEvent refelects diff/error detection.
type DiffEvent struct {
	Diffs []diffmatchpatch.Diff
	Err   error
}

// NewDiff is factory for Diff.
func NewDiff(ctx context.Context, path string, isPathURL bool, checkInterval time.Duration, events chan<- DiffEvent) *Diff {
	var d Diff
	if isPathURL {
		d.url = path
	} else {
		d.filepath = path
	}
	d.checkInterval = checkInterval
	d.events = events

	d.init(ctx)
	return &d
}

func (d *Diff) init(ctx context.Context) {
	d.checkUpdate()
	d.ticker = time.NewTicker(d.checkInterval)
	go func() {
		select {
		case <-ctx.Done():
			d.ticker.Stop()
		case <-d.ticker.C:
			d.checkUpdate()
		}
	}()
}

func (d *Diff) checkUpdate() {
	var path string
	if len(d.url) > 0 {
		path = d.url
	} else {
		path = d.filepath
	}
	llData, err := x509util.ReadFileOrURL(path, &http.Client{Timeout: time.Second * 10})
	if err != nil {
		d.events <- DiffEvent{Err: err}
		return
	}
	d.mu.Lock()
	defer d.mu.Unlock()
	d.latest = llData
	// Compare data as strings
	dmp := diffmatchpatch.New()
	diffs := dmp.DiffMain(string(d.synced), string(d.latest), false)
	d.diffs = diffs
	if len(diffs) > 0 && d.events != nil {
		d.events <- DiffEvent{Diffs: d.diffs}
	}
}

func (d *Diff) sync() { // nolint:unused
	d.mu.Lock()
	d.synced = d.latest
	d.diffs = []diffmatchpatch.Diff{}
	d.mu.Unlock()
}

// GetSyncedData provides acces to Diff data.
func (d *Diff) GetSyncedData() []byte {
	d.mu.Lock()
	defer d.mu.Unlock()
	return d.synced
}
<|endoftext|>


<commit_before>package notify

import (
	"os"
	"path/filepath"
	"sync"
	"testing"
	"time"
)

func nonil(err ...error) error {
	for _, err := range err {
		if err != nil {
			return err
		}
	}
	return nil
}

func strip(e Event) Event {
	return e & ^Recursive
}

func test(t *testing.T, w Watcher, ei []EventInfo, d time.Duration) {
	done, c, fn := make(chan error), make(chan EventInfo, len(ei)), filepath.WalkFunc(nil)
	walk, exec, cleanup := Tree.Create(t)
	defer cleanup()
	if w.IsRecursive() {
		var once sync.Once
		fn = func(p string, fi os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			once.Do(func() {
				err = w.Watch(p, All)
			})
			return nonil(err, filepath.SkipDir)
		}
	} else {
		fn = func(p string, fi os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if fi.IsDir() {
				err = w.Watch(p, strip(All))
			}
			return err
		}
	}
	w.Fanin(c)
	if err := walk(fn); err != nil {
		t.Fatal(err)
	}
	go func() {
		for _, ei := range ei {
			exec(ei)
			if err := equal(<-c, ei); err != nil {
				done <- err
				return
			}
		}
		done <- nil
	}()
	select {
	case <-time.After(d):
		t.Fatalf("test has timed out after %v", d)
	case err := <-done:
		if err != nil {
			t.Fatal(err)
		}
	}
}

func TestWatcher(t *testing.T) {
	if global.Watcher == nil {
		t.Skip("no watcher to test")
	}
	ei := []EventInfo{
		Ev("github.com/rjeczalik/fs/fs_test.go", Create, false),
		Ev("github.com/rjeczalik/fs/binfs", Create, true),
		Ev("github.com/rjeczalik/fs/binfs.go", Create, false),
		Ev("github.com/rjeczalik/fs/binfs_test.go", Create, false),
		Ev("github.com/rjeczalik/fs/binfs", Delete, true),
		Ev("github.com/rjeczalik/fs/binfs", Create, true),
		// BUG(OS X): Fsnotify claims, the following is Create not Move.
		// Ev("github.com/rjeczalik/fs/binfs", Move, true),
		Ev("github.com/rjeczalik/fs/virfs", Create, false),
		// BUG(OS X): When being watched by fsnotify, writing to the newly-created
		// file fails with "bad file descriptor".
		// Ev("github.com/rjeczalik/fs/virfs", Write, false),
		Ev("github.com/rjeczalik/fs/virfs", Delete, false),
		// BUG(OS X): The same as above, this time "bad file descriptor" on a file
		// that was created previously.
		Ev("github.com/rjeczalik/fs/LICENSE", Write, false),
	}
	test(t, global.Watcher, ei, time.Second)
}
<commit_msg>Rename TestWatcher -> TestGlobalWatcher<commit_after>package notify

import (
	"os"
	"path/filepath"
	"sync"
	"testing"
	"time"
)

func nonil(err ...error) error {
	for _, err := range err {
		if err != nil {
			return err
		}
	}
	return nil
}

func strip(e Event) Event {
	return e & ^Recursive
}

func test(t *testing.T, w Watcher, ei []EventInfo, d time.Duration) {
	done, c, fn := make(chan error), make(chan EventInfo, len(ei)), filepath.WalkFunc(nil)
	walk, exec, cleanup := Tree.Create(t)
	defer cleanup()
	if w.IsRecursive() {
		var once sync.Once
		fn = func(p string, fi os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			once.Do(func() {
				err = w.Watch(p, All)
			})
			return nonil(err, filepath.SkipDir)
		}
	} else {
		fn = func(p string, fi os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			if fi.IsDir() {
				err = w.Watch(p, strip(All))
			}
			return err
		}
	}
	w.Fanin(c)
	if err := walk(fn); err != nil {
		t.Fatal(err)
	}
	go func() {
		for _, ei := range ei {
			exec(ei)
			if err := equal(<-c, ei); err != nil {
				done <- err
				return
			}
		}
		done <- nil
	}()
	select {
	case <-time.After(d):
		t.Fatalf("test has timed out after %v", d)
	case err := <-done:
		if err != nil {
			t.Fatal(err)
		}
	}
}

func TestGlobalWatcher(t *testing.T) {
	if global.Watcher == nil {
		t.Skip("no global watcher to test")
	}
	ei := []EventInfo{
		Ev("github.com/rjeczalik/fs/fs_test.go", Create, false),
		Ev("github.com/rjeczalik/fs/binfs", Create, true),
		Ev("github.com/rjeczalik/fs/binfs.go", Create, false),
		Ev("github.com/rjeczalik/fs/binfs_test.go", Create, false),
		Ev("github.com/rjeczalik/fs/binfs", Delete, true),
		Ev("github.com/rjeczalik/fs/binfs", Create, true),
		// BUG(OS X): Fsnotify claims, the following is Create not Move.
		// Ev("github.com/rjeczalik/fs/binfs", Move, true),
		Ev("github.com/rjeczalik/fs/virfs", Create, false),
		// BUG(OS X): When being watched by fsnotify, writing to the newly-created
		// file fails with "bad file descriptor".
		// Ev("github.com/rjeczalik/fs/virfs", Write, false),
		Ev("github.com/rjeczalik/fs/virfs", Delete, false),
		// BUG(OS X): The same as above, this time "bad file descriptor" on a file
		// that was created previously.
		Ev("github.com/rjeczalik/fs/LICENSE", Write, false),
	}
	test(t, global.Watcher, ei, time.Second)
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	cmds "github.com/jbenet/go-ipfs/commands"
	"strings"
)

type TestOutput struct {
	Foo string
	Bar int
}

var Root = &cmds.Command{
	Options: []cmds.Option{
		cmds.Option{[]string{"config", "c"}, cmds.String},
		cmds.Option{[]string{"debug", "D"}, cmds.Bool},
		cmds.Option{[]string{"help", "h"}, cmds.Bool},
		cmds.Option{[]string{"local", "L"}, cmds.Bool},
	},
	Help: `ipfs - global versioned p2p merkledag file system

Basic commands:

    init          Initialize ipfs local configuration.
    add <path>    Add an object to ipfs.
    cat <ref>     Show ipfs object data.
    ls <ref>      List links from an object.
    refs <ref>    List link hashes from an object.

Tool commands:

    config        Manage configuration.
    version       Show ipfs version information.
    commands      List all available commands.

Advanced Commands:

    mount         Mount an ipfs read-only mountpoint.
    serve         Serve an interface to ipfs.
    net-diag      Print network diagnostic.

Use "ipfs help <command>" for more information about a command.
`,
	Subcommands: map[string]*cmds.Command{
		"cat": cat,

		// test subcommands
		// TODO: remove these when we don't need them anymore
		"beep": &cmds.Command{
			Run: func(req cmds.Request, res cmds.Response) {
				v := &TestOutput{"hello, world", 1337}
				res.SetValue(v)
			},
			Format: func(res cmds.Response) (string, error) {
				v := res.Value().(*TestOutput)
				s := fmt.Sprintf("Foo: %s\n", v.Foo)
				s += fmt.Sprintf("Bar: %v\n", v.Bar)
				return s, nil
			},
			Type: &TestOutput{},
		},
		"boop": &cmds.Command{
			Run: func(req cmds.Request, res cmds.Response) {
				v := strings.NewReader("hello, world")
				res.SetValue(v)
			},
		},
		"warp": &cmds.Command{
			Options: []cmds.Option{
				cmds.Option{[]string{"power", "p"}, cmds.Float},
			},
			Run: func(req cmds.Request, res cmds.Response) {
				threshold := 1.21

				if power, found := req.Option("power"); found && power.(float64) >= threshold {
					res.SetValue(struct {
						Status string
						Power  float64
					}{"Flux capacitor activated!", power.(float64)})

				} else {
					err := fmt.Errorf("Insufficient power (%v jiggawatts required)", threshold)
					res.SetError(err, cmds.ErrClient)
				}
			},
		},
		"args": &cmds.Command{
			Run: func(req cmds.Request, res cmds.Response) {
				res.SetValue(req.Arguments())
			},
		},
		"echo": &cmds.Command{
			Run: func(req cmds.Request, res cmds.Response) {
				res.SetValue(req.Stream())
			},
		},
	},
}
<commit_msg>fix(core/commands2) ipfs help message<commit_after>package commands

import (
	"fmt"
	"strings"

	cmds "github.com/jbenet/go-ipfs/commands"
)

type TestOutput struct {
	Foo string
	Bar int
}

var Root = &cmds.Command{
	Options: []cmds.Option{
		cmds.Option{[]string{"config", "c"}, cmds.String},
		cmds.Option{[]string{"debug", "D"}, cmds.Bool},
		cmds.Option{[]string{"help", "h"}, cmds.Bool},
		cmds.Option{[]string{"local", "L"}, cmds.Bool},
	},
	Help: `ipfs - global versioned p2p merkledag file system

Basic commands:

    init          Initialize ipfs local configuration.
    add <path>    Add an object to ipfs.
    cat <ref>     Show ipfs object data.
    ls <ref>      List links from an object.
    refs <ref>    List link hashes from an object.

Tool commands:

    config        Manage configuration.
    update        Download and apply go-ipfs updates.
    version       Show ipfs version information.
    commands      List all available commands.

Advanced Commands:

    mount         Mount an ipfs read-only mountpoint.
    serve         Serve an interface to ipfs.
    net-diag      Print network diagnostic

Plumbing commands:

    block         Interact with raw blocks in the datastore
    object        Interact with raw dag nodes

Use "ipfs help <command>" for more information about a command.
`,
	Subcommands: map[string]*cmds.Command{
		"cat": cat,

		// test subcommands
		// TODO: remove these when we don't need them anymore
		"beep": &cmds.Command{
			Run: func(req cmds.Request, res cmds.Response) {
				v := &TestOutput{"hello, world", 1337}
				res.SetValue(v)
			},
			Format: func(res cmds.Response) (string, error) {
				v := res.Value().(*TestOutput)
				s := fmt.Sprintf("Foo: %s\n", v.Foo)
				s += fmt.Sprintf("Bar: %v\n", v.Bar)
				return s, nil
			},
			Type: &TestOutput{},
		},
		"boop": &cmds.Command{
			Run: func(req cmds.Request, res cmds.Response) {
				v := strings.NewReader("hello, world")
				res.SetValue(v)
			},
		},
		"warp": &cmds.Command{
			Options: []cmds.Option{
				cmds.Option{[]string{"power", "p"}, cmds.Float},
			},
			Run: func(req cmds.Request, res cmds.Response) {
				threshold := 1.21

				if power, found := req.Option("power"); found && power.(float64) >= threshold {
					res.SetValue(struct {
						Status string
						Power  float64
					}{"Flux capacitor activated!", power.(float64)})

				} else {
					err := fmt.Errorf("Insufficient power (%v jiggawatts required)", threshold)
					res.SetError(err, cmds.ErrClient)
				}
			},
		},
		"args": &cmds.Command{
			Run: func(req cmds.Request, res cmds.Response) {
				res.SetValue(req.Arguments())
			},
		},
		"echo": &cmds.Command{
			Run: func(req cmds.Request, res cmds.Response) {
				res.SetValue(req.Stream())
			},
		},
	},
}
<|endoftext|>


<commit_before>package compute

import "fmt"

// Entity represents a Cloud Control entity.
type Entity interface {
	// GetID retrieves the entity's ID.
	GetID() string
}

// NamedEntity represents a named Cloud Control entity.
type NamedEntity interface {
	Entity

	// GetName retrieves the entity's name.
	GetName() string

	// ToEntityReference creates an EntityReference representing the entity.
	ToEntityReference() EntityReference
}

// EntityReference is used to group an entity Id and name together for serialisation / deserialisation purposes.
type EntityReference struct {
	// The entity Id.
	ID string `json:"id"`
	// The entity name.
	Name string `json:"name,omitempty"`
}

// IPRange represents an IPvX range.
type IPRange interface {
	// Convert the IPvX range to a display string.
	ToDisplayString() string
}

// IPv4Range represents an IPv4 network (base address and prefix size)
type IPv4Range struct {
	// The network base address.
	BaseAddress string `json:"address"`
	// The network prefix size.
	PrefixSize int `json:"prefixSize"`
}

// ToDisplayString converts the IPv4 range to a display string.
func (network IPv4Range) ToDisplayString() string {
	return fmt.Sprintf("%s/%d", network.BaseAddress, network.PrefixSize)
}

// IPv6Range represents an IPv6 network (base address and prefix size)
type IPv6Range struct {
	// The network base address.
	BaseAddress string `json:"address"`
	// The network prefix size.
	PrefixSize int `json:"prefixSize"`
}

// ToDisplayString converts the IPv6 range to a display string.
func (network IPv6Range) ToDisplayString() string {
	return fmt.Sprintf("%s/%d", network.BaseAddress, network.PrefixSize)
}

// OperatingSystem represents a well-known operating system for virtual machines.
type OperatingSystem struct {
	// The operating system Id.
	ID string `json:"id"`

	// The operating system type.
	Family string `json:"family"`

	// The operating system display-name.
	DisplayName string `json:"displayName"`
}

// VirtualMachineCPU represents the CPU configuration for a virtual machine.
type VirtualMachineCPU struct {
	Count          int    `json:"count,omitempty"`
	Speed          string `json:"speed,omitempty"`
	CoresPerSocket int    `json:"coresPerSocket,omitempty"`
}

// VirtualMachineSCSIController represents the configuration for a SCSI controller in a virtual machine.
type VirtualMachineSCSIController struct {
	ID          string               `json:"id,omitempty"`
	BusNumber   int                  `json:"busNumber"`
	AdapterType string               `json:"adapterType"`
	Disks       []VirtualMachineDisk `json:"disk"`
	State       string               `json:"state,omitempty"`
}

// VirtualMachineDisk represents the configuration for disk in a virtual machine.
type VirtualMachineDisk struct {
	ID         string `json:"id,omitempty"`
	SCSIUnitID int    `json:"scsiId"`
	SizeGB     int    `json:"sizeGb"`
	Speed      string `json:"speed"`
	State      string `json:"state,omitempty"`
}

// VirtualMachineNetwork represents the networking configuration for a virtual machine.
type VirtualMachineNetwork struct {
	NetworkDomainID           string                         `json:"networkDomainId,omitempty"`
	PrimaryAdapter            VirtualMachineNetworkAdapter   `json:"primaryNic"`
	AdditionalNetworkAdapters []VirtualMachineNetworkAdapter `json:"additionalNic"`
}

// VirtualMachineNetworkAdapter represents the configuration for a virtual machine's network adapter.
// If deploying a new VM, exactly one of VLANID / PrivateIPv4Address must be specified.
//
// AdapterType (if specified) must be either E1000 or VMXNET3.
type VirtualMachineNetworkAdapter struct {
	ID                 *string `json:"id,omitempty"`
	MACAddress         *string `json:"macAddress,omitempty"` // CloudControl v2.4 and higher
	VLANID             *string `json:"vlanId,omitempty"`
	VLANName           *string `json:"vlanName,omitempty"`
	PrivateIPv4Address *string `json:"privateIpv4,omitempty"`
	PrivateIPv6Address *string `json:"ipv6,omitempty"`
	AdapterType        *string `json:"networkAdapter,omitempty"`
	AdapterKey         *int    `json:"key,omitempty"` // CloudControl v2.4 and higher
	State              *string `json:"state,omitempty"`
}

// GetID returns the network adapter's Id.
func (networkAdapter *VirtualMachineNetworkAdapter) GetID() string {
	if networkAdapter.ID == nil {
		return ""
	}

	return *networkAdapter.ID
}

// GetResourceType returns the network domain's resource type.
func (networkAdapter *VirtualMachineNetworkAdapter) GetResourceType() ResourceType {
	return ResourceTypeNetworkAdapter
}

// GetName returns the network adapter's name (actually Id, since adapters don't have names).
func (networkAdapter *VirtualMachineNetworkAdapter) GetName() string {
	return networkAdapter.GetID()
}

// GetState returns the network adapter's current state.
func (networkAdapter *VirtualMachineNetworkAdapter) GetState() string {
	if networkAdapter.State == nil {
		return ""
	}

	return *networkAdapter.State
}

// IsDeleted determines whether the network adapter has been deleted (is nil).
func (networkAdapter *VirtualMachineNetworkAdapter) IsDeleted() bool {
	return networkAdapter == nil
}

// ToEntityReference creates an EntityReference representing the CustomerImage.
func (networkAdapter *VirtualMachineNetworkAdapter) ToEntityReference() EntityReference {
	id := ""
	if networkAdapter.ID != nil {
		id = *networkAdapter.ID
	}
	name := ""
	if networkAdapter.VLANName != nil {
		name = *networkAdapter.VLANName
	}

	return EntityReference{
		ID:   id,
		Name: name,
	}
}

var _ Resource = &VirtualMachineNetworkAdapter{}
<commit_msg>Add "Key" field to VirtualMachineSCSIController.<commit_after>package compute

import "fmt"

// Entity represents a Cloud Control entity.
type Entity interface {
	// GetID retrieves the entity's ID.
	GetID() string
}

// NamedEntity represents a named Cloud Control entity.
type NamedEntity interface {
	Entity

	// GetName retrieves the entity's name.
	GetName() string

	// ToEntityReference creates an EntityReference representing the entity.
	ToEntityReference() EntityReference
}

// EntityReference is used to group an entity Id and name together for serialisation / deserialisation purposes.
type EntityReference struct {
	// The entity Id.
	ID string `json:"id"`
	// The entity name.
	Name string `json:"name,omitempty"`
}

// IPRange represents an IPvX range.
type IPRange interface {
	// Convert the IPvX range to a display string.
	ToDisplayString() string
}

// IPv4Range represents an IPv4 network (base address and prefix size)
type IPv4Range struct {
	// The network base address.
	BaseAddress string `json:"address"`
	// The network prefix size.
	PrefixSize int `json:"prefixSize"`
}

// ToDisplayString converts the IPv4 range to a display string.
func (network IPv4Range) ToDisplayString() string {
	return fmt.Sprintf("%s/%d", network.BaseAddress, network.PrefixSize)
}

// IPv6Range represents an IPv6 network (base address and prefix size)
type IPv6Range struct {
	// The network base address.
	BaseAddress string `json:"address"`
	// The network prefix size.
	PrefixSize int `json:"prefixSize"`
}

// ToDisplayString converts the IPv6 range to a display string.
func (network IPv6Range) ToDisplayString() string {
	return fmt.Sprintf("%s/%d", network.BaseAddress, network.PrefixSize)
}

// OperatingSystem represents a well-known operating system for virtual machines.
type OperatingSystem struct {
	// The operating system Id.
	ID string `json:"id"`

	// The operating system type.
	Family string `json:"family"`

	// The operating system display-name.
	DisplayName string `json:"displayName"`
}

// VirtualMachineCPU represents the CPU configuration for a virtual machine.
type VirtualMachineCPU struct {
	Count          int    `json:"count,omitempty"`
	Speed          string `json:"speed,omitempty"`
	CoresPerSocket int    `json:"coresPerSocket,omitempty"`
}

// VirtualMachineSCSIController represents the configuration for a SCSI controller in a virtual machine.
type VirtualMachineSCSIController struct {
	ID          string               `json:"id,omitempty"`
	BusNumber   int                  `json:"busNumber"`
	Key         int                  `json:"key"`
	AdapterType string               `json:"adapterType"`
	Disks       []VirtualMachineDisk `json:"disk"`
	State       string               `json:"state,omitempty"`
}

// VirtualMachineDisk represents the configuration for disk in a virtual machine.
type VirtualMachineDisk struct {
	ID         string `json:"id,omitempty"`
	SCSIUnitID int    `json:"scsiId"`
	SizeGB     int    `json:"sizeGb"`
	Speed      string `json:"speed"`
	State      string `json:"state,omitempty"`
}

// VirtualMachineNetwork represents the networking configuration for a virtual machine.
type VirtualMachineNetwork struct {
	NetworkDomainID           string                         `json:"networkDomainId,omitempty"`
	PrimaryAdapter            VirtualMachineNetworkAdapter   `json:"primaryNic"`
	AdditionalNetworkAdapters []VirtualMachineNetworkAdapter `json:"additionalNic"`
}

// VirtualMachineNetworkAdapter represents the configuration for a virtual machine's network adapter.
// If deploying a new VM, exactly one of VLANID / PrivateIPv4Address must be specified.
//
// AdapterType (if specified) must be either E1000 or VMXNET3.
type VirtualMachineNetworkAdapter struct {
	ID                 *string `json:"id,omitempty"`
	MACAddress         *string `json:"macAddress,omitempty"` // CloudControl v2.4 and higher
	VLANID             *string `json:"vlanId,omitempty"`
	VLANName           *string `json:"vlanName,omitempty"`
	PrivateIPv4Address *string `json:"privateIpv4,omitempty"`
	PrivateIPv6Address *string `json:"ipv6,omitempty"`
	AdapterType        *string `json:"networkAdapter,omitempty"`
	AdapterKey         *int    `json:"key,omitempty"` // CloudControl v2.4 and higher
	State              *string `json:"state,omitempty"`
}

// GetID returns the network adapter's Id.
func (networkAdapter *VirtualMachineNetworkAdapter) GetID() string {
	if networkAdapter.ID == nil {
		return ""
	}

	return *networkAdapter.ID
}

// GetResourceType returns the network domain's resource type.
func (networkAdapter *VirtualMachineNetworkAdapter) GetResourceType() ResourceType {
	return ResourceTypeNetworkAdapter
}

// GetName returns the network adapter's name (actually Id, since adapters don't have names).
func (networkAdapter *VirtualMachineNetworkAdapter) GetName() string {
	return networkAdapter.GetID()
}

// GetState returns the network adapter's current state.
func (networkAdapter *VirtualMachineNetworkAdapter) GetState() string {
	if networkAdapter.State == nil {
		return ""
	}

	return *networkAdapter.State
}

// IsDeleted determines whether the network adapter has been deleted (is nil).
func (networkAdapter *VirtualMachineNetworkAdapter) IsDeleted() bool {
	return networkAdapter == nil
}

// ToEntityReference creates an EntityReference representing the CustomerImage.
func (networkAdapter *VirtualMachineNetworkAdapter) ToEntityReference() EntityReference {
	id := ""
	if networkAdapter.ID != nil {
		id = *networkAdapter.ID
	}
	name := ""
	if networkAdapter.VLANName != nil {
		name = *networkAdapter.VLANName
	}

	return EntityReference{
		ID:   id,
		Name: name,
	}
}

var _ Resource = &VirtualMachineNetworkAdapter{}
<|endoftext|>


<commit_before>package corehttp

// TODO: move to IPNS
const WebUIPath = "/ipfs/QmUnXcWZC5Ve21gUseouJsH5mLAyz5JPp8aHsg8qVUUK8e"

// this is a list of all past webUI paths.
var WebUIPaths = []string{
	WebUIPath,
	"/ipfs/QmSDgpiHco5yXdyVTfhKxr3aiJ82ynz8V14QcGKicM3rVh",
	"/ipfs/QmRuvWJz1Fc8B9cTsAYANHTXqGmKR9DVfY5nvMD1uA2WQ8",
	"/ipfs/QmQLXHs7K98JNQdWrBB2cQLJahPhmupbDjRuH1b9ibmwVa",
	"/ipfs/QmXX7YRpU7nNBKfw75VG7Y1c3GwpSAGHRev67XVPgZFv9R",
	"/ipfs/QmXdu7HWdV6CUaUabd9q2ZeA4iHZLVyDRj3Gi4dsJsWjbr",
	"/ipfs/QmaaqrHyAQm7gALkRW8DcfGX3u8q9rWKnxEMmf7m9z515w",
	"/ipfs/QmSHDxWsMPuJQKWmVA1rB5a3NX2Eme5fPqNb63qwaqiqSp",
	"/ipfs/QmctngrQAt9fjpQUZr7Bx3BsXUcif52eZGTizWhvcShsjz",
	"/ipfs/QmS2HL9v5YeKgQkkWMvs1EMnFtUowTEdFfSSeMT4pos1e6",
	"/ipfs/QmR9MzChjp1MdFWik7NjEjqKQMzVmBkdK3dz14A6B5Cupm",
	"/ipfs/QmRyWyKWmphamkMRnJVjUTzSFSAAZowYP4rnbgnfMXC9Mr",
	"/ipfs/QmU3o9bvfenhTKhxUakbYrLDnZU7HezAVxPM6Ehjw9Xjqy",
	"/ipfs/QmPhnvn747LqwPYMJmQVorMaGbMSgA7mRRoyyZYz3DoZRQ",
}

var WebUIOption = RedirectOption("webui", WebUIPath)
<commit_msg>feat: update to Web UI v2.3.2<commit_after>package corehttp

// TODO: move to IPNS
const WebUIPath = "/ipfs/QmenEBWcAk3tN94fSKpKFtUMwty1qNwSYw3DMDFV6cPBXA"

// this is a list of all past webUI paths.
var WebUIPaths = []string{
	WebUIPath,
	"/ipfs/QmUnXcWZC5Ve21gUseouJsH5mLAyz5JPp8aHsg8qVUUK8e",
	"/ipfs/QmSDgpiHco5yXdyVTfhKxr3aiJ82ynz8V14QcGKicM3rVh",
	"/ipfs/QmRuvWJz1Fc8B9cTsAYANHTXqGmKR9DVfY5nvMD1uA2WQ8",
	"/ipfs/QmQLXHs7K98JNQdWrBB2cQLJahPhmupbDjRuH1b9ibmwVa",
	"/ipfs/QmXX7YRpU7nNBKfw75VG7Y1c3GwpSAGHRev67XVPgZFv9R",
	"/ipfs/QmXdu7HWdV6CUaUabd9q2ZeA4iHZLVyDRj3Gi4dsJsWjbr",
	"/ipfs/QmaaqrHyAQm7gALkRW8DcfGX3u8q9rWKnxEMmf7m9z515w",
	"/ipfs/QmSHDxWsMPuJQKWmVA1rB5a3NX2Eme5fPqNb63qwaqiqSp",
	"/ipfs/QmctngrQAt9fjpQUZr7Bx3BsXUcif52eZGTizWhvcShsjz",
	"/ipfs/QmS2HL9v5YeKgQkkWMvs1EMnFtUowTEdFfSSeMT4pos1e6",
	"/ipfs/QmR9MzChjp1MdFWik7NjEjqKQMzVmBkdK3dz14A6B5Cupm",
	"/ipfs/QmRyWyKWmphamkMRnJVjUTzSFSAAZowYP4rnbgnfMXC9Mr",
	"/ipfs/QmU3o9bvfenhTKhxUakbYrLDnZU7HezAVxPM6Ehjw9Xjqy",
	"/ipfs/QmPhnvn747LqwPYMJmQVorMaGbMSgA7mRRoyyZYz3DoZRQ",
}

var WebUIOption = RedirectOption("webui", WebUIPath)
<|endoftext|>