<commit_before>/*
   Copyright (c) 2015, Mark Bucciarelli <mkbucc@gmail.com>
*/

package vufs

import (
	"fmt"
	. "github.com/smartystreets/goconvey/convey"
	"io/ioutil"
	"os"
	"testing"

	"9fans.net/go/plan9"
	"9fans.net/go/plan9/client"
)

const (
	port               = ":5000"
	messageSizeInBytes = 8192
)

// Initialize file system as:
//
//          /
//           |
//           +-- adm/            --rwx------ adm adm
//                   |
//                   +-- users     --rw------- adm adm
//
//         Notes:
//
//          a.    Users shown are virtual ones, not ones on disk.
//
//          b.    If no ownership specified (in .uidgid), it defaults to adm adm.
//
//
func initfs(rootdir string, mode os.FileMode, userdata string) {
	os.RemoveAll(rootdir)
	os.Mkdir(rootdir, mode)
	os.Mkdir(rootdir+"/adm", 0700)
	ioutil.WriteFile(rootdir+"/adm/users", []byte(userdata), 0600)
}

func runserver(rootdir, port string) *client.Conn {

	var err error
	fs := New(rootdir)
	fs.Id = "vufs"
	fs.Upool, err = NewVusers(rootdir)
	if err != nil {
		panic(err)
	}
	//fs.Debuglevel = 1

	fs.Start(fs)

	go func() {
		err = fs.StartNetListener("tcp", port)
		if err != nil {
			panic(err)
		}
	}()

	// Make sure runserver is listening before returning.
	var conn *client.Conn
	for i := 0; i < 16; i++ {
		if conn, err = client.Dial("tcp", port); err == nil {
			fmt.Printf("Server is up, got connnection %+v\n", conn)
			break
		}

	}

	if err != nil {
		panic("couldn't connect to runserver after 15 tries: " + err.Error())
	}

	return conn
}

func listDir(conn *client.Conn, path, user string) ([]*plan9.Dir, error) {

	fsys, err := conn.Attach(nil, user, "/")
	if err != nil {
		return nil, err
	}

	fid, err := fsys.Open("/", plan9.OREAD)
	if err != nil {
		return nil, err
	}
	defer fid.Close()

	d, err := fid.Dirreadall()
	if err != nil {
		return nil, err
	}

	return d, nil

}

func TestServer(t *testing.T) {

	rootdir := "./tmpfs"

	initfs(rootdir, 0755, "1:adm:adm\n2:mark:mark\n3:other:other\n")

	conn := runserver(rootdir, port)

	Convey("Given a vufs rooted in a directory and a client", t, func() {

		var dirs []*plan9.Dir
		var err error

		Convey("/adm/users is 0600 adm, adm", func() {
			dirs, err = listDir(conn, "/", "adm")
			So(err, ShouldBeNil)
			So(len(dirs), ShouldEqual, 1)
		})

		Convey("A valid user can list the one file in a 0755 root directory", func() {
			os.Chmod(rootdir, 0755)
			dirs, err = listDir(conn, "/", "mark")
			So(err, ShouldBeNil)
			So(len(dirs), ShouldEqual, 1)
		})

		Convey("An invalid user cannot list root directory", func() {
			os.Chmod(rootdir, 0777)
			_, err = listDir(conn, ".", "hugo")
			So(err.Error(), ShouldEqual, "unknown user: 22")
		})

		Convey("A valid user without permissions cannot list files", func() {
			err = os.Chmod(rootdir, 0700)
			So(err, ShouldBeNil)
			dirs, err = listDir(conn, ".", "mark")
			So(err.Error(), ShouldEqual, "permission denied: 1")
		})

		Convey("Given an 0755 root and the file: 0600 mark mark test.txt", func() {
			os.Chmod(rootdir, 0755)

			fn := "test.txt"
			os.RemoveAll(rootdir+"/" + fn)
			ioutil.WriteFile(rootdir+"/" + fn, []byte("whatever"), 0600)
			ioutil.WriteFile(rootdir+"/"+uidgidFile, []byte(fn + ":2:2\n"), 0600)

			Convey("adm should not be able to read it ", func() {

				fsys, err := conn.Attach(nil, "adm", "/")
				So(err, ShouldBeNil)
				_, err = fsys.Open("/" + fn, plan9.OREAD)
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "permission denied: 1")

			})

			Convey("mark should be able to read it ", func() {

				fsys, err := conn.Attach(nil, "mark", "/")
				So(err, ShouldBeNil)
				_, err = fsys.Open("/" + fn, plan9.OREAD)
				So(err, ShouldBeNil)
			})

			Convey("other should not be able to read it ", func() {

				fsys, err := conn.Attach(nil, "other", "/")
				So(err, ShouldBeNil)
				_, err = fsys.Open("/" + fn, plan9.OREAD)
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "permission denied: 1")

			})

		})

// adm mark other
// 0400	read: Y N N	write: N N N
// 0600	read: Y N N	write: Y N N
// 0640	read: Y Y N	write: Y N N
// 0644	read: Y Y Y	write: Y N N
// 0664	read: Y Y N	write: Y Y N
// 0666	read: Y Y N	write: Y Y N

	})

	conn.Close()

	//os.RemoveAll(rootdir)

}
<commit_msg>Add couple write permission tests<commit_after>/*
   Copyright (c) 2015, Mark Bucciarelli <mkbucc@gmail.com>
*/

package vufs

import (
	"fmt"
	. "github.com/smartystreets/goconvey/convey"
	"io/ioutil"
	"os"
	"testing"

	"9fans.net/go/plan9"
	"9fans.net/go/plan9/client"
)

const (
	port               = ":5000"
	messageSizeInBytes = 8192
)

// Initialize file system as:
//
//          /
//           |
//           +-- adm/            --rwx------ adm adm
//                   |
//                   +-- users     --rw------- adm adm
//
//         Notes:
//
//          a.    Users shown are virtual ones, not ones on disk.
//
//          b.    If no ownership specified (in .uidgid), it defaults to adm adm.
//
//
func initfs(rootdir string, mode os.FileMode, userdata string) {
	os.RemoveAll(rootdir)
	os.Mkdir(rootdir, mode)
	os.Mkdir(rootdir+"/adm", 0700)
	ioutil.WriteFile(rootdir+"/adm/users", []byte(userdata), 0600)
}

func runserver(rootdir, port string) *client.Conn {

	var err error
	fs := New(rootdir)
	fs.Id = "vufs"
	fs.Upool, err = NewVusers(rootdir)
	if err != nil {
		panic(err)
	}
	//fs.Debuglevel = 1

	fs.Start(fs)

	go func() {
		err = fs.StartNetListener("tcp", port)
		if err != nil {
			panic(err)
		}
	}()

	// Make sure runserver is listening before returning.
	var conn *client.Conn
	for i := 0; i < 16; i++ {
		if conn, err = client.Dial("tcp", port); err == nil {
			fmt.Printf("Server is up, got connnection %+v\n", conn)
			break
		}

	}

	if err != nil {
		panic("couldn't connect to runserver after 15 tries: " + err.Error())
	}

	return conn
}

func listDir(conn *client.Conn, path, user string) ([]*plan9.Dir, error) {

	fsys, err := conn.Attach(nil, user, "/")
	if err != nil {
		return nil, err
	}

	fid, err := fsys.Open("/", plan9.OREAD)
	if err != nil {
		return nil, err
	}
	defer fid.Close()

	d, err := fid.Dirreadall()
	if err != nil {
		return nil, err
	}

	return d, nil

}

func TestServer(t *testing.T) {

	rootdir := "./tmpfs"

	initfs(rootdir, 0755, "1:adm:adm\n2:mark:mark\n3:other:other\n")

	conn := runserver(rootdir, port)

	Convey("Given a vufs rooted in a directory and a client", t, func() {

		var fsys *client.Fsys
		var dirs []*plan9.Dir
		var err error
		var fid *client.Fid
		var n int

		Convey("/adm/users is 0600 adm, adm", func() {
			dirs, err = listDir(conn, "/", "adm")
			So(err, ShouldBeNil)
			So(len(dirs), ShouldEqual, 1)
		})

		Convey("A valid user can list the one file in a 0755 root directory", func() {
			os.Chmod(rootdir, 0755)
			dirs, err = listDir(conn, "/", "mark")
			So(err, ShouldBeNil)
			So(len(dirs), ShouldEqual, 1)
		})

		Convey("An invalid user cannot list root directory", func() {
			os.Chmod(rootdir, 0777)
			_, err = listDir(conn, ".", "hugo")
			So(err.Error(), ShouldEqual, "unknown user: 22")
		})

		Convey("A valid user without permissions cannot list files", func() {
			err = os.Chmod(rootdir, 0700)
			So(err, ShouldBeNil)
			dirs, err = listDir(conn, ".", "mark")
			So(err.Error(), ShouldEqual, "permission denied: 1")
		})

		Convey("Given an 0755 root and the file: 0600 mark mark test.txt", func() {

			os.Chmod(rootdir, 0755)

			fn := "test.txt"

			os.RemoveAll(rootdir+"/" + fn)
			ioutil.WriteFile(rootdir+"/" + fn, []byte("whatever"), 0600)
			ioutil.WriteFile(rootdir+"/"+uidgidFile, []byte(fn + ":2:2\n"), 0600)

			Convey("adm should not be able to read it ", func() {

				fsys, err = conn.Attach(nil, "adm", "/")
				So(err, ShouldBeNil)
				_, err = fsys.Open("/" + fn, plan9.OREAD)
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "permission denied: 1")

			})

			Convey("mark should be able to read it ", func() {

				fsys, err = conn.Attach(nil, "mark", "/")
				So(err, ShouldBeNil)
				_, err = fsys.Open("/" + fn, plan9.OREAD)
				So(err, ShouldBeNil)
			})

			Convey("other should not be able to read it ", func() {

				fsys, err = conn.Attach(nil, "other", "/")
				So(err, ShouldBeNil)
				_, err = fsys.Open("/" + fn, plan9.OREAD)
				So(err, ShouldNotBeNil)
				So(err.Error(), ShouldEqual, "permission denied: 1")

			})

			Convey("mark should be able to write to it ", func() {

				fsys, err = conn.Attach(nil, "mark", "/")
				So(err, ShouldBeNil)
				fid, err = fsys.Open("/" + fn, plan9.OWRITE)
				So(err, ShouldBeNil)
				n, err = fid.Write([]byte("whom"))
				So(err, ShouldBeNil)
				So(n, ShouldEqual, 4)
				err = fid.Close()
				So(err, ShouldBeNil)

				contents, err := ioutil.ReadFile(rootdir + "/" + fn)
				So(err, ShouldBeNil)
				So(string(contents), ShouldEqual, "whomever")

			})

			Convey("adm and other should not be able to write it ", func() {

				fsys, err = conn.Attach(nil, "adm", "/")
				So(err, ShouldBeNil)
				_, err = fsys.Open("/" + fn, plan9.OWRITE)
				So(err.Error(), ShouldEqual, "permission denied: 1")

				fsys, err = conn.Attach(nil, "other", "/")
				So(err, ShouldBeNil)
				_, err = fsys.Open("/" + fn, plan9.OWRITE)
				So(err.Error(), ShouldEqual, "permission denied: 1")
			})

		})

// adm mark other
// 0400	read: Y N N	write: N N N
// 0600	read: Y N N	write: Y N N
// 0640	read: Y Y N	write: Y N N
// 0644	read: Y Y Y	write: Y N N
// 0664	read: Y Y N	write: Y Y N
// 0666	read: Y Y N	write: Y Y N

	})

	conn.Close()

	//os.RemoveAll(rootdir)

}
<|endoftext|>


<commit_before>package pmb

import (
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/gorilla/websocket"
)

func connectWS(URI string, id string, sub string) (*Connection, error) {

	in := make(chan Message, 10)
	out := make(chan Message, 10)

	done := make(chan error)

	conn := &Connection{In: in, Out: out, uri: URI, prefix: "", Id: id}

	logrus.Debugf("calling listen/send WS")
	go openWS(conn, done, id)

	err := <-done
	if err != nil {
		return nil, err
	}

	return conn, nil
}

func openWS(pmbConn *Connection, done chan error, id string) {

	logrus.Debugf("calling connectSocket")
	conn, err := connectSocket(pmbConn.uri)

	if err != nil {
		done <- err
		return
	}

	done <- nil

	for {
		processSocket(pmbConn, conn, id)

		conn, err = connectSocketForever(pmbConn.uri)

		if err != nil {
			logrus.Errorf("Unable to reconnect, exiting... %s", err)
			return
		} else {
			pmbConn.In <- Message{
				Contents: map[string]interface{}{"type": "Reconnected"},
				Internal: true,
			}
			logrus.Infof("Reconnected.")
		}
	}

}

func connectSocketForever(uri string) (*websocket.Conn, error) {

	for {
		conn, err := connectSocket(uri)

		if err == nil {
			return conn, nil
		}

		logrus.Warningf("Listen setup failed, sleeping and then re-trying")
		time.Sleep(1 * time.Second)
	}
}

func connectSocket(uri string) (*websocket.Conn, error) {
	c, _, err := websocket.DefaultDialer.Dial(uri, nil)
	if err != nil {
		return nil, err
	}

	return c, err
}

func processSocket(pmbConn *Connection, conn *websocket.Conn, id string) {
	logrus.Debugf("start of processSocket")

	done := make(chan struct{})

	// Start up reader side of socket
	go func() {
		defer close(done)
		for {
			messageType, message, err := conn.ReadMessage()
			if err != nil {
				logrus.Errorf("error reading: %v", err)
				return
			}

			logrus.Debugf("WS received message of type: %d", messageType)
			if messageType == websocket.TextMessage {
				logrus.Debugf("message: %s", string(message))
				parseMessage(message, pmbConn.Keys, pmbConn.In, id)
			}
		}
	}()

	// Set up writer side of socket
	go func() {
		for {
			select {
			case <-done:
				logrus.Infof("exiting writer side of socket")
				return
			case message := <-pmbConn.Out:
				bodies, err := prepareMessage(message, pmbConn.Keys, id)
				if err != nil {
					logrus.Warningf("Error preparing message: %s", err)
					continue
				}

				for _, body := range bodies {
					err = conn.WriteMessage(websocket.TextMessage, body)
					if err != nil {
						logrus.Errorf("error writing:", err)
						return
					}
				}

				if message.Done != nil {
					logrus.Debugf("Done channel present, sending message")
					message.Done <- nil
				}
			}
		}
	}()

	<-done
}
<commit_msg>Set up pings on client side of websocket to detect stale sockets<commit_after>package pmb

import (
	"time"

	"github.com/Sirupsen/logrus"
	"github.com/gorilla/websocket"
)

const (
	writeWait      = 10 * time.Second
	pongWait       = 60 * time.Second
	pingPeriod     = (pongWait * 9) / 10
	maxMessageSize = 256 * 1024
)

func connectWS(URI string, id string, sub string) (*Connection, error) {

	in := make(chan Message, 10)
	out := make(chan Message, 10)

	done := make(chan error)

	conn := &Connection{In: in, Out: out, uri: URI, prefix: "", Id: id}

	logrus.Debugf("calling listen/send WS")
	go openWS(conn, done, id)

	err := <-done
	if err != nil {
		return nil, err
	}

	return conn, nil
}

func openWS(pmbConn *Connection, done chan error, id string) {

	logrus.Debugf("calling connectSocket")
	conn, err := connectSocket(pmbConn.uri)

	if err != nil {
		done <- err
		return
	}

	done <- nil

	for {
		processSocket(pmbConn, conn, id)

		conn, err = connectSocketForever(pmbConn.uri)

		if err != nil {
			logrus.Errorf("Unable to reconnect, exiting... %s", err)
			return
		} else {
			pmbConn.In <- Message{
				Contents: map[string]interface{}{"type": "Reconnected"},
				Internal: true,
			}
			logrus.Infof("Reconnected.")
		}
	}

}

func connectSocketForever(uri string) (*websocket.Conn, error) {

	for {
		conn, err := connectSocket(uri)

		if err == nil {
			return conn, nil
		}

		logrus.Warningf("Listen setup failed, sleeping and then re-trying")
		time.Sleep(1 * time.Second)
	}
}

func connectSocket(uri string) (*websocket.Conn, error) {
	c, _, err := websocket.DefaultDialer.Dial(uri, nil)
	if err != nil {
		return nil, err
	}

	c.SetReadLimit(maxMessageSize)
	c.SetReadDeadline(time.Now().Add(pongWait))
	c.SetPongHandler(func(string) error {
		logrus.Debugf("received pong")
		c.SetReadDeadline(time.Now().Add(pongWait))
		return nil
	})

	return c, err
}

func processSocket(pmbConn *Connection, conn *websocket.Conn, id string) {
	logrus.Debugf("start of processSocket")

	done := make(chan struct{})

	// Start up reader side of socket
	go func() {
		defer close(done)
		for {
			messageType, message, err := conn.ReadMessage()
			if err != nil {
				logrus.Errorf("error reading: %v", err)
				return
			}

			logrus.Debugf("WS received message of type: %d", messageType)
			if messageType == websocket.TextMessage {
				logrus.Debugf("message: %s", string(message))
				parseMessage(message, pmbConn.Keys, pmbConn.In, id)
			}
		}
	}()

	// Set up writer side of socket
	go func() {
		ticker := time.NewTicker(pingPeriod)
		defer func() {
			ticker.Stop()
			conn.Close()
		}()
		for {
			select {
			case <-done:
				logrus.Infof("exiting writer side of socket")
				return
			case message := <-pmbConn.Out:
				bodies, err := prepareMessage(message, pmbConn.Keys, id)
				if err != nil {
					logrus.Warningf("Error preparing message: %s", err)
					continue
				}

				for _, body := range bodies {
					conn.SetWriteDeadline(time.Now().Add(writeWait))
					err = conn.WriteMessage(websocket.TextMessage, body)
					if err != nil {
						logrus.Errorf("error writing:", err)
						return
					}
				}

				if message.Done != nil {
					logrus.Debugf("Done channel present, sending message")
					message.Done <- nil
				}
			case <-ticker.C:
				conn.SetWriteDeadline(time.Now().Add(writeWait))
				logrus.Debugf("sending ping")
				if err := conn.WriteMessage(websocket.PingMessage, nil); err != nil {
					return
				}
			}
		}
	}()

	<-done
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 e2e

import (
	"fmt"
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/test/e2e/framework"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

// This test requires Rescheduler to be enabled.
var _ = framework.KubeDescribe("Rescheduler [Serial]", func() {
	f := framework.NewDefaultFramework("rescheduler")
	var ns string
	var totalMillicores int

	BeforeEach(func() {
		framework.SkipUnlessProviderIs("gce", "gke")
		ns = f.Namespace.Name
		nodes := framework.GetReadySchedulableNodesOrDie(f.Client)
		nodeCount := len(nodes.Items)
		Expect(nodeCount).NotTo(BeZero())

		cpu := nodes.Items[0].Status.Capacity[api.ResourceCPU]
		totalMillicores = int((&cpu).MilliValue()) * nodeCount
	})

	It("should ensure that critical pod is scheduled in case there is no resources available", func() {
		By("reserving all available cpu")
		err := reserveAllCpu(f, "reserve-all-cpu", totalMillicores)
		defer framework.DeleteRCAndPods(f.Client, ns, "reserve-all-cpu")
		framework.ExpectNoError(err)

		By("creating a new instance of DNS and waiting for DNS to be scheduled")
		label := labels.SelectorFromSet(labels.Set(map[string]string{"k8s-app": "kube-dns"}))
		listOpts := api.ListOptions{LabelSelector: label}
		rcs, err := f.Client.ReplicationControllers(api.NamespaceSystem).List(listOpts)
		framework.ExpectNoError(err)
		Expect(len(rcs.Items)).Should(Equal(1))

		rc := rcs.Items[0]
		replicas := uint(rc.Spec.Replicas)

		err = framework.ScaleRC(f.Client, api.NamespaceSystem, rc.Name, replicas+1, true)
		defer framework.ExpectNoError(framework.ScaleRC(f.Client, api.NamespaceSystem, rc.Name, replicas, true))
		framework.ExpectNoError(err)
	})
})

func reserveAllCpu(f *framework.Framework, id string, millicores int) error {
	timeout := 5 * time.Minute
	replicas := millicores / 100

	ReserveCpu(f, id, 1, 100)
	framework.ExpectNoError(framework.ScaleRC(f.Client, f.Namespace.Name, id, uint(replicas), false))

	for start := time.Now(); time.Since(start) < timeout; time.Sleep(10 * time.Second) {
		pods, err := framework.GetPodsInNamespace(f.Client, f.Namespace.Name, framework.ImagePullerLabels)
		if err != nil {
			return err
		}

		if len(pods) != replicas {
			continue
		}

		allRunningOrUnschedulable := true
		for _, pod := range pods {
			if !podRunningOrUnschedulable(pod) {
				allRunningOrUnschedulable = false
				break
			}
		}
		if allRunningOrUnschedulable {
			return nil
		}
	}
	return fmt.Errorf("Pod name %s: Gave up waiting %v for %d pods to come up", id, timeout, replicas)
}

func podRunningOrUnschedulable(pod *api.Pod) bool {
	_, cond := api.GetPodCondition(&pod.Status, api.PodScheduled)
	if cond != nil && cond.Status == api.ConditionFalse && cond.Reason == "Unschedulable" {
		return true
	}
	running, _ := framework.PodRunningReady(pod)
	return running
}
<commit_msg>Revert "Enabled Rescheduler e2e for gke"<commit_after>/*
Copyright 2016 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 e2e

import (
	"fmt"
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/labels"
	"k8s.io/kubernetes/test/e2e/framework"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

// This test requires Rescheduler to be enabled.
var _ = framework.KubeDescribe("Rescheduler [Serial]", func() {
	f := framework.NewDefaultFramework("rescheduler")
	var ns string
	var totalMillicores int

	BeforeEach(func() {
		framework.SkipUnlessProviderIs("gce")
		ns = f.Namespace.Name
		nodes := framework.GetReadySchedulableNodesOrDie(f.Client)
		nodeCount := len(nodes.Items)
		Expect(nodeCount).NotTo(BeZero())

		cpu := nodes.Items[0].Status.Capacity[api.ResourceCPU]
		totalMillicores = int((&cpu).MilliValue()) * nodeCount
	})

	It("should ensure that critical pod is scheduled in case there is no resources available", func() {
		By("reserving all available cpu")
		err := reserveAllCpu(f, "reserve-all-cpu", totalMillicores)
		defer framework.DeleteRCAndPods(f.Client, ns, "reserve-all-cpu")
		framework.ExpectNoError(err)

		By("creating a new instance of DNS and waiting for DNS to be scheduled")
		label := labels.SelectorFromSet(labels.Set(map[string]string{"k8s-app": "kube-dns"}))
		listOpts := api.ListOptions{LabelSelector: label}
		rcs, err := f.Client.ReplicationControllers(api.NamespaceSystem).List(listOpts)
		framework.ExpectNoError(err)
		Expect(len(rcs.Items)).Should(Equal(1))

		rc := rcs.Items[0]
		replicas := uint(rc.Spec.Replicas)

		err = framework.ScaleRC(f.Client, api.NamespaceSystem, rc.Name, replicas+1, true)
		defer framework.ExpectNoError(framework.ScaleRC(f.Client, api.NamespaceSystem, rc.Name, replicas, true))
		framework.ExpectNoError(err)
	})
})

func reserveAllCpu(f *framework.Framework, id string, millicores int) error {
	timeout := 5 * time.Minute
	replicas := millicores / 100

	ReserveCpu(f, id, 1, 100)
	framework.ExpectNoError(framework.ScaleRC(f.Client, f.Namespace.Name, id, uint(replicas), false))

	for start := time.Now(); time.Since(start) < timeout; time.Sleep(10 * time.Second) {
		pods, err := framework.GetPodsInNamespace(f.Client, f.Namespace.Name, framework.ImagePullerLabels)
		if err != nil {
			return err
		}

		if len(pods) != replicas {
			continue
		}

		allRunningOrUnschedulable := true
		for _, pod := range pods {
			if !podRunningOrUnschedulable(pod) {
				allRunningOrUnschedulable = false
				break
			}
		}
		if allRunningOrUnschedulable {
			return nil
		}
	}
	return fmt.Errorf("Pod name %s: Gave up waiting %v for %d pods to come up", id, timeout, replicas)
}

func podRunningOrUnschedulable(pod *api.Pod) bool {
	_, cond := api.GetPodCondition(&pod.Status, api.PodScheduled)
	if cond != nil && cond.Status == api.ConditionFalse && cond.Reason == "Unschedulable" {
		return true
	}
	running, _ := framework.PodRunningReady(pod)
	return running
}
<|endoftext|>


<commit_before>/*
Package telsh provides "middleware" (for the telnet package) that can be used to implement a TELNET or TELNETS server
that provides a "shell" interface (also known as a "command-line interface" or "CLI").

Shell interfaces you may be familiar with include: "bash", "csh", "sh", "zsk", etc.

TELNET Server

Here is an example usage:

	package main

	import (
		"github.com/reiver/go-oi"
		"github.com/reiver/go-telnet"
		"github.com/reiver/go-telnet/telsh"

		"io"
	)

	func main() {

		telnetHandler := telsh.NewShellHandler()

		if err := telnetHandler.RegisterElse(
			telsh.ProducerFunc(
				func(ctx telnet.Context, name string, args ...string) telsh.Handler {
					return telsh.PromoteHandlerFunc(
						func(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
							oi.LongWrite(stdout, []byte{'w','a','t','?', '\r','\n'})

							return nil
						},
					)
				},
			),
		); nil != err {
			panic(err)
		}

		if err := telnetHandler.Register("help",
			telsh.ProducerFunc(
				func(ctx telnet.Context, name string, args ...string) telsh.Handler {
				return telsh.PromoteHandlerFunc(
						func(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
							oi.LongWrite(stdout, []byte{'r','t','f','m','!', '\r','\n'})

							return nil
						},
					)
				},
			),
		); nil != err {
			panic(err)
		}

		err := telnet.ListenAndServe(":5555", telnetHandler)
		if nil != err {
			//@TODO: Handle this error better.
			panic(err)
		}
	}

Here is a more "unpacked" example:

	package main

	import (
		"github.com/reiver/go-oi"
		"github.com/reiver/go-telnet"
		"github.com/reiver/go-telnet/telsh"

		"fmt"
		"io"
		"time"
	)

	var (
		shellHandler := telsh.NewShellHandler()
	)

	func init() {

		shellHandler.Register("dance", telsh.ProducerFunc(producer))

		shellHandler.WelcomeMessage = `
	 __          __ ______  _        _____   ____   __  __  ______
	 \ \        / /|  ____|| |      / ____| / __ \ |  \/  ||  ____|
	  \ \  /\  / / | |__   | |     | |     | |  | || \  / || |__
	   \ \/  \/ /  |  __|  | |     | |     | |  | || |\/| ||  __|
	    \  /\  /   | |____ | |____ | |____ | |__| || |  | || |____
	     \/  \/    |______||______| \_____| \____/ |_|  |_||______|

	`
	}

	func producer(ctx telnet.Context, name string, args ...string) telsh.Handler{
		return telsh.PromoteHandlerFunc(handler)
	}

	func handler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
		for i:=0; i<20; i++ {
			oi.LongWriteString(stdout, "\r⠋")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠙")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠹")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠸")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠼")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠴")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠦")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠧")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠇")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠏")
			time.Sleep(50*time.Millisecond)
		}
		oi.LongWriteString(stdout, "\r \r\n")

		return nil
	}

	func main() {

		addr := ":5555"
		if err := telnet.ListenAndServe(addr, shellHandler); nil != err {
			panic(err)
		}
	}

*/
package telsh
<commit_msg>corrected/updated docs<commit_after>/*
Package telsh provides "middleware" (for the telnet package) that can be used to implement a TELNET or TELNETS server
that provides a "shell" interface (also known as a "command-line interface" or "CLI").

Shell interfaces you may be familiar with include: "bash", "csh", "sh", "zsk", etc.

TELNET Server

Here is an example usage:

	package main

	import (
		"github.com/reiver/go-oi"
		"github.com/reiver/go-telnet"
		"github.com/reiver/go-telnet/telsh"

		"io"
	)

	func main() {

		telnetHandler := telsh.NewShellHandler()

		if err := telnetHandler.RegisterElse(
			telsh.ProducerFunc(
				func(ctx telnet.Context, name string, args ...string) telsh.Handler {
					return telsh.PromoteHandlerFunc(
						func(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
							oi.LongWrite(stdout, []byte{'w','a','t','?', '\r','\n'})

							return nil
						},
					)
				},
			),
		); nil != err {
			panic(err)
		}

		if err := telnetHandler.Register("help",
			telsh.ProducerFunc(
				func(ctx telnet.Context, name string, args ...string) telsh.Handler {
				return telsh.PromoteHandlerFunc(
						func(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
							oi.LongWrite(stdout, []byte{'r','t','f','m','!', '\r','\n'})

							return nil
						},
					)
				},
			),
		); nil != err {
			panic(err)
		}

		err := telnet.ListenAndServe(":5555", telnetHandler)
		if nil != err {
			//@TODO: Handle this error better.
			panic(err)
		}
	}

Here is a more "unpacked" example:

	package main

	import (
		"github.com/reiver/go-oi"
		"github.com/reiver/go-telnet"
		"github.com/reiver/go-telnet/telsh"

		"io"
		"time"
	)

	var (
		shellHandler = telsh.NewShellHandler()
	)

	func init() {

		shellHandler.Register("dance", telsh.ProducerFunc(producer))

		shellHandler.WelcomeMessage = `
	 __          __ ______  _        _____   ____   __  __  ______
	 \ \        / /|  ____|| |      / ____| / __ \ |  \/  ||  ____|
	  \ \  /\  / / | |__   | |     | |     | |  | || \  / || |__
	   \ \/  \/ /  |  __|  | |     | |     | |  | || |\/| ||  __|
	    \  /\  /   | |____ | |____ | |____ | |__| || |  | || |____
	     \/  \/    |______||______| \_____| \____/ |_|  |_||______|

	`
	}

	func producer(ctx telnet.Context, name string, args ...string) telsh.Handler{
		return telsh.PromoteHandlerFunc(handler)
	}

	func handler(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser, args ...string) error {
		for i:=0; i<20; i++ {
			oi.LongWriteString(stdout, "\r⠋")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠙")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠹")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠸")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠼")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠴")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠦")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠧")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠇")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠏")
			time.Sleep(50*time.Millisecond)
		}
		oi.LongWriteString(stdout, "\r \r\n")

		return nil
	}

	func main() {

		addr := ":5555"
		if err := telnet.ListenAndServe(addr, shellHandler); nil != err {
			panic(err)
		}
	}

*/
package telsh
<|endoftext|>


<commit_before>package posts

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"testing"
	"time"

	"github.com/boatilus/peppercorn/db"
	"github.com/spf13/viper"
	"github.com/stretchr/testify/assert"
	rethink "gopkg.in/dancannon/gorethink.v2"
)

const tableName = "posts_test"

type doc struct {
	Active  bool
	Author  string
	Content string
	Time    int64
}

var docs []doc // Stores test data read in from JSON

func makePostFromDoc(d doc) Post {
	return Post{
		Active:  d.Active,
		Author:  d.Author,
		Content: d.Content,
		Time:    time.Unix(d.Time, 0),
	}
}

func setupDB() {
	if !db.Session.IsConnected() {
		panic("No DB connected")
	}

	rethink.DBCreate("peppercorn").RunWrite(db.Session)

	peppercorn := rethink.DB(db.Name)

	c, err := peppercorn.TableList().Contains(tableName).Run(db.Session)
	if err != nil {
		panic(err)
	}

	var hasTable bool

	err = c.One(&hasTable)
	if err != nil {
		panic(err)
	}

	table := peppercorn.Table(tableName)

	if !hasTable {
		_, err := peppercorn.TableCreate(tableName).RunWrite(db.Session)
		if err != nil {
			panic(err)
		}

		table.IndexCreate("active").RunWrite(db.Session)
		table.IndexCreate("author").RunWrite(db.Session)
		table.IndexCreate("time").RunWrite(db.Session)

		table.IndexCreateFunc("active_time", func(row rethink.Term) interface{} {
			return []interface{}{row.Field("active"), row.Field("time")}
		}).RunWrite(db.Session)

		table.IndexWait().Run(db.Session)
	} else {
		// Due to a lack of mocking in gorethink, we'll tear down the test data and repopulate on each
		// run of the tests.
		table.Delete().RunWrite(db.Session)
	}

	bytes, err := ioutil.ReadFile("posts.test_data.json")

	if err := json.Unmarshal(bytes, &docs); err != nil {
		panic(err)
	}

	if len(docs) != 7 {
		panic(err)
	}

	posts := make([]Post, len(docs))

	for i := range docs {
		posts[i].Active = docs[i].Active
		posts[i].Author = docs[i].Author
		posts[i].Content = docs[i].Content
		posts[i].Time = time.Unix(docs[i].Time, 0)
	}

	if _, err := table.Insert(posts).RunWrite(db.Session); err != nil {
		panic(err)
	}

	cursor, err := table.Count().Run(db.Session)

	if err != nil {
		panic(err)
	}

	var n int

	cursor.One(&n)
	cursor.Close()

	if n != 7 {
		panic(err)
	}
}

func init() {
	viper.Set("db.posts_table", "posts_test")

	var err error

	if db.Session, err = rethink.Connect(rethink.ConnectOpts{Address: "localhost:28015"}); err != nil {
		panic(err)
	}

	log.SetOutput(ioutil.Discard)

	setupDB()
}

///////////
// Tests //
///////////

func TestNew(t *testing.T) {
	assert := assert.New(t)

	type data struct {
		author  string
		content string
	}

	passCases := []data{
		{"user", "content"},
		{"_", "_"},
	}

	for _, c := range passCases {
		got, err := New(c.author, c.content)

		assert.Nil(err)
		assert.Empty(got.ID)
		assert.True(got.Active)
		assert.Equal(c.author, got.Author)
		assert.Equal(c.content, got.Content)
	}

	failCases := []data{
		{"", "content"},
		{"user", ""},
		{"", ""},
	}

	for _, c := range failCases {
		_, err := New(c.author, c.content)

		assert.NotNil(err)
	}
}

func TestCount(t *testing.T) {
	n, err := Count()

	assert.Nil(t, err)
	assert.Equal(t, n, db.CountType(6))
}

func TestCountAll(t *testing.T) {
	n, err := CountAll()

	assert.Nil(t, err)
	assert.Equal(t, n, db.CountType(7))
}

func TestGetRange(t *testing.T) {
	assert := assert.New(t)

	cases := []struct {
		first db.CountType
		limit db.CountType
		want  []Post
	}{
		{1, 2, []Post{makePostFromDoc(docs[0]), makePostFromDoc(docs[1])}},
		{3, 2, []Post{makePostFromDoc(docs[2]), makePostFromDoc(docs[3])}},
		{2, 3, []Post{makePostFromDoc(docs[1]), makePostFromDoc(docs[2]), makePostFromDoc(docs[3])}},
		// The 'first' argument is locked to 1 if < 1, so we should check that we get posts 1 and 2...
		{0, 2, []Post{makePostFromDoc(docs[0]), makePostFromDoc(docs[1])}},
	}

	for _, c := range cases {
		got, err := GetRange(c.first, c.limit)

		assert.Nil(err)

		for i := range got {
			g := got[i]
			w := c.want[i]

			assert.Equal(g.Active, w.Active)
			assert.Equal(g.Author, w.Author)
			assert.Equal(g.Content, w.Content)
			assert.True(g.Time.Equal(w.Time))
		}
	}
}

func TestGetOne(t *testing.T) {
	assert := assert.New(t)

	cases := []struct {
		in   db.CountType
		want Post
	}{
		{1, makePostFromDoc(docs[0])},
		{3, makePostFromDoc(docs[2])},
	}

	for _, c := range cases {
		got, err := GetOne(c.in)

		assert.Nil(err)

		assert.Equal(got.Active, c.want.Active)
		assert.Equal(got.Author, c.want.Author)
		assert.Equal(got.Content, c.want.Content)
		assert.True(got.Time.Equal(c.want.Time))
	}

	failCases := [3]db.CountType{0, 7, 12}

	for _, c := range failCases {
		_, err := GetOne(c)

		if err == nil {
			t.Errorf("GetOne(%v) should return an error", c)
		}
	}
}

func TestGetByID(t *testing.T) {
	assert := assert.New(t)

	want, err := GetOne(1)
	assert.Nil(err)

	got, err := GetByID(want.ID)
	assert.Nil(err)

	assert.Equal(want, got)
}

func TestGetOffset(t *testing.T) {
	assert := assert.New(t)

	p, err := GetOne(3)
	if !assert.NoError(err) {
		t.FailNow()
	}

	n, err := GetOffset(p.ID)
	if !assert.NoError(err) {
		t.FailNow()
	}

	assert.Equal(db.CountType(3), n)
}

func TestEdit(t *testing.T) {
	assert := assert.New(t)

	p, _ := GetOne(3)

	err := Edit(p.ID, "edited content")
	assert.Nil(err)

	pEdit, _ := GetByID(p.ID)

	assert.Equal(pEdit.ID, p.ID)
	assert.Equal(pEdit.Active, p.Active)
	assert.Equal(pEdit.Author, p.Author)
	assert.Equal("edited content", pEdit.Content)
	assert.True(p.Time.Equal(pEdit.Time))
}

func TestSubmit(t *testing.T) {
	assert := assert.New(t)

	p, _ := New("user", "content")

	id, err := Submit(p)
	assert.Nil(err)
	assert.NotEmpty(id)

	n, err := Count()
	assert.Nil(err)
	assert.Equal(n, db.CountType(7))

	pt, err := GetOne(7)
	assert.Nil(err)

	assert.Equal(p.Active, pt.Active)
	assert.Equal(p.Author, pt.Author)
	assert.Equal(p.Content, pt.Content)
	assert.Equal(p.Time.Hour(), pt.Time.Hour())     // If the hour and second are equal we can be
	assert.Equal(p.Time.Second(), pt.Time.Second()) // reasonably confident the times are equal

	id, err = Submit(nil)
	assert.NotNil(err)
	assert.Empty(id)
}
<commit_msg>Fix failing test for posts<commit_after>package posts

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"testing"
	"time"

	"github.com/boatilus/peppercorn/db"
	"github.com/spf13/viper"
	"github.com/stretchr/testify/assert"
	rethink "gopkg.in/dancannon/gorethink.v2"
)

const tableName = "posts_test"

type doc struct {
	Active  bool
	Author  string
	Content string
	Time    int64
}

var docs []doc // Stores test data read in from JSON

func makePostFromDoc(d doc) Post {
	return Post{
		Active:  d.Active,
		Author:  d.Author,
		Content: d.Content,
		Time:    time.Unix(d.Time, 0),
	}
}

func setupDB() {
	if !db.Session.IsConnected() {
		panic("No DB connected")
	}

	rethink.DBCreate("peppercorn").RunWrite(db.Session)

	peppercorn := rethink.DB(db.Name)

	c, err := peppercorn.TableList().Contains(tableName).Run(db.Session)
	if err != nil {
		panic(err)
	}

	var hasTable bool

	err = c.One(&hasTable)
	if err != nil {
		panic(err)
	}

	table := peppercorn.Table(tableName)

	if !hasTable {
		_, err := peppercorn.TableCreate(tableName).RunWrite(db.Session)
		if err != nil {
			panic(err)
		}

		table.IndexCreate("active").RunWrite(db.Session)
		table.IndexCreate("user_id").RunWrite(db.Session)

		table.IndexCreateFunc("active_time", func(row rethink.Term) interface{} {
			return []interface{}{row.Field("active"), row.Field("time")}
		}).RunWrite(db.Session)

		table.IndexWait().Run(db.Session)
	} else {
		// Due to a lack of mocking in gorethink, we'll tear down the test data and repopulate on each
		// run of the tests.
		table.Delete().RunWrite(db.Session)
	}

	bytes, err := ioutil.ReadFile("posts.test_data.json")

	if err := json.Unmarshal(bytes, &docs); err != nil {
		panic(err)
	}

	if len(docs) != 7 {
		panic(err)
	}

	posts := make([]Post, len(docs))

	for i := range docs {
		posts[i].Active = docs[i].Active
		posts[i].Author = docs[i].Author
		posts[i].Content = docs[i].Content
		posts[i].Time = time.Unix(docs[i].Time, 0)
	}

	if _, err := table.Insert(posts).RunWrite(db.Session); err != nil {
		panic(err)
	}

	cursor, err := table.Count().Run(db.Session)

	if err != nil {
		panic(err)
	}

	var n int

	cursor.One(&n)
	cursor.Close()

	if n != 7 {
		panic(err)
	}
}

func init() {
	viper.Set("db.posts_table", "posts_test")

	var err error

	if db.Session, err = rethink.Connect(rethink.ConnectOpts{Address: "localhost:28015"}); err != nil {
		panic(err)
	}

	log.SetOutput(ioutil.Discard)

	setupDB()
}

///////////
// Tests //
///////////

func TestNew(t *testing.T) {
	assert := assert.New(t)

	type data struct {
		author  string
		content string
	}

	passCases := []data{
		{"user", "content"},
		{"_", "_"},
	}

	for _, c := range passCases {
		got, err := New(c.author, c.content)

		assert.Nil(err)
		assert.Empty(got.ID)
		assert.True(got.Active)
		assert.Equal(c.author, got.Author)
		assert.Equal(c.content, got.Content)
	}

	failCases := []data{
		{"", "content"},
		{"user", ""},
		{"", ""},
	}

	for _, c := range failCases {
		_, err := New(c.author, c.content)

		assert.NotNil(err)
	}
}

func TestCount(t *testing.T) {
	n, err := Count()

	assert.Nil(t, err)
	assert.Equal(t, n, db.CountType(6))
}

func TestCountAll(t *testing.T) {
	n, err := CountAll()

	assert.Nil(t, err)
	assert.Equal(t, n, db.CountType(7))
}

func TestGetRange(t *testing.T) {
	assert := assert.New(t)

	cases := []struct {
		first db.CountType
		limit db.CountType
		want  []Post
	}{
		{1, 2, []Post{makePostFromDoc(docs[0]), makePostFromDoc(docs[1])}},
		{3, 2, []Post{makePostFromDoc(docs[2]), makePostFromDoc(docs[3])}},
		{2, 3, []Post{makePostFromDoc(docs[1]), makePostFromDoc(docs[2]), makePostFromDoc(docs[3])}},
		// The 'first' argument is locked to 1 if < 1, so we should check that we get posts 1 and 2...
		{0, 2, []Post{makePostFromDoc(docs[0]), makePostFromDoc(docs[1])}},
	}

	for _, c := range cases {
		got, err := GetRange(c.first, c.limit)

		assert.Nil(err)

		for i := range got {
			g := got[i]
			w := c.want[i]

			assert.Equal(g.Active, w.Active)
			assert.Equal(g.Author, w.Author)
			assert.Equal(g.Content, w.Content)
			assert.True(g.Time.Equal(w.Time))
		}
	}
}

func TestGetOne(t *testing.T) {
	assert := assert.New(t)

	cases := []struct {
		in   db.CountType
		want Post
	}{
		{1, makePostFromDoc(docs[0])},
		{3, makePostFromDoc(docs[2])},
	}

	for _, c := range cases {
		got, err := GetOne(c.in)

		assert.Nil(err)

		assert.Equal(got.Active, c.want.Active)
		assert.Equal(got.Author, c.want.Author)
		assert.Equal(got.Content, c.want.Content)
		assert.True(got.Time.Equal(c.want.Time))
	}

	failCases := [3]db.CountType{0, 7, 12}

	for _, c := range failCases {
		_, err := GetOne(c)

		if err == nil {
			t.Errorf("GetOne(%v) should return an error", c)
		}
	}
}

func TestGetByID(t *testing.T) {
	assert := assert.New(t)

	want, err := GetOne(1)
	assert.Nil(err)

	got, err := GetByID(want.ID)
	assert.Nil(err)

	assert.Equal(want, got)
}

func TestGetOffset(t *testing.T) {
	assert := assert.New(t)

	p, err := GetOne(3)
	if !assert.NoError(err) {
		t.FailNow()
	}

	n, err := GetOffset(p.ID)
	if !assert.NoError(err) {
		t.FailNow()
	}

	assert.Equal(db.CountType(3), n)
}

func TestEdit(t *testing.T) {
	assert := assert.New(t)

	p, _ := GetOne(3)

	err := Edit(p.ID, "edited content")
	assert.Nil(err)

	pEdit, _ := GetByID(p.ID)

	assert.Equal(pEdit.ID, p.ID)
	assert.Equal(pEdit.Active, p.Active)
	assert.Equal(pEdit.Author, p.Author)
	assert.Equal("edited content", pEdit.Content)
	assert.True(p.Time.Equal(pEdit.Time))
}

func TestSubmit(t *testing.T) {
	assert := assert.New(t)

	p, _ := New("user", "content")

	id, err := Submit(p)
	assert.Nil(err)
	assert.NotEmpty(id)

	n, err := Count()
	assert.Nil(err)
	assert.Equal(n, db.CountType(7))

	pt, err := GetOne(7)
	assert.Nil(err)

	assert.Equal(p.Active, pt.Active)
	assert.Equal(p.Author, pt.Author)
	assert.Equal(p.Content, pt.Content)
	assert.Equal(p.Time.Hour(), pt.Time.Hour())     // If the hour and second are equal we can be
	assert.Equal(p.Time.Second(), pt.Time.Second()) // reasonably confident the times are equal

	id, err = Submit(nil)
	assert.NotNil(err)
	assert.Empty(id)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"path/filepath"
	"sort"
	"strings"
	"text/template"

	"github.com/vattle/sqlboiler/bdb"
	"github.com/vattle/sqlboiler/queries"
	"github.com/vattle/sqlboiler/strmangle"
)

// templateData for sqlboiler templates
type templateData struct {
	Tables []bdb.Table
	Table  bdb.Table

	// Controls what names are output
	PkgName string
	Schema  string

	// Controls which code is output (mysql vs postgres ...)
	DriverName      string
	UseLastInsertID bool

	// Turn off auto timestamps or hook generation
	NoHooks          bool
	NoAutoTimestamps bool

	// Tags control which
	Tags []string

	// StringFuncs are usable in templates with stringMap
	StringFuncs map[string]func(string) string

	// Dialect controls quoting
	Dialect queries.Dialect
	LQ      string
	RQ      string
}

func (t templateData) Quotes(s string) string {
	return fmt.Sprintf("%s%s%s", t.LQ, s, t.RQ)
}

func (t templateData) SchemaTable(table string) string {
	return strmangle.SchemaTable(t.LQ, t.RQ, t.DriverName, t.Schema, table)
}

type templateList struct {
	*template.Template
}

type templateNameList []string

func (t templateNameList) Len() int {
	return len(t)
}

func (t templateNameList) Swap(k, j int) {
	t[k], t[j] = t[j], t[k]
}

func (t templateNameList) Less(k, j int) bool {
	// Make sure "struct" goes to the front
	if t[k] == "struct.tpl" {
		return true
	}

	res := strings.Compare(t[k], t[j])
	if res <= 0 {
		return true
	}

	return false
}

// Templates returns the name of all the templates defined in the template list
func (t templateList) Templates() []string {
	tplList := t.Template.Templates()

	if len(tplList) == 0 {
		return nil
	}

	ret := make([]string, 0, len(tplList))
	for _, tpl := range tplList {
		if name := tpl.Name(); strings.HasSuffix(name, ".tpl") {
			ret = append(ret, name)
		}
	}

	sort.Sort(templateNameList(ret))

	return ret
}

// loadTemplates loads all of the template files in the specified directory.
func loadTemplates(dir string) (*templateList, error) {
	pattern := filepath.Join(dir, "*.tpl")
	tpl, err := template.New("").Funcs(templateFunctions).ParseGlob(pattern)

	if err != nil {
		return nil, err
	}

	return &templateList{Template: tpl}, err
}

// loadTemplate loads a single template file.
func loadTemplate(dir string, filename string) (*template.Template, error) {
	pattern := filepath.Join(dir, filename)
	tpl, err := template.New("").Funcs(templateFunctions).ParseFiles(pattern)

	if err != nil {
		return nil, err
	}

	return tpl.Lookup(filename), err
}

// templateStringMappers are placed into the data to make it easy to use the
// stringMap function.
var templateStringMappers = map[string]func(string) string{
	// String ops
	"quoteWrap": func(a string) string { return fmt.Sprintf(`"%s"`, a) },

	// Casing
	"titleCase": strmangle.TitleCase,
	"camelCase": strmangle.CamelCase,
}

// templateFunctions is a map of all the functions that get passed into the
// templates. If you wish to pass a new function into your own template,
// add a function pointer here.
var templateFunctions = template.FuncMap{
	// String ops
	"quoteWrap": func(s string) string { return fmt.Sprintf(`"%s"`, s) },
	"id":        strmangle.Identifier,

	// Pluralization
	"singular": strmangle.Singular,
	"plural":   strmangle.Plural,

	// Casing
	"titleCase": strmangle.TitleCase,
	"camelCase": strmangle.CamelCase,

	// String Slice ops
	"join":               func(sep string, slice []string) string { return strings.Join(slice, sep) },
	"joinSlices":         strmangle.JoinSlices,
	"stringMap":          strmangle.StringMap,
	"prefixStringSlice":  strmangle.PrefixStringSlice,
	"containsAny":        strmangle.ContainsAny,
	"generateTags":       strmangle.GenerateTags,
	"generateIgnoreTags": strmangle.GenerateIgnoreTags,

	// String Map ops
	"makeStringMap": strmangle.MakeStringMap,

	// Set operations
	"setInclude": strmangle.SetInclude,

	// Database related mangling
	"whereClause": strmangle.WhereClause,

	// Relationship text helpers
	"textsFromForeignKey":           txtsFromFKey,
	"textsFromOneToOneRelationship": txtsFromOneToOne,
	"textsFromRelationship":         txtsFromToMany,

	// dbdrivers ops
	"filterColumnsByDefault": bdb.FilterColumnsByDefault,
	"autoIncPrimaryKey":      bdb.AutoIncPrimaryKey,
	"sqlColDefinitions":      bdb.SQLColDefinitions,
	"columnNames":            bdb.ColumnNames,
	"columnDBTypes":          bdb.ColumnDBTypes,
	"getTable":               bdb.GetTable,
}
<commit_msg>Fix names of things for templates<commit_after>package main

import (
	"fmt"
	"path/filepath"
	"sort"
	"strings"
	"text/template"

	"github.com/vattle/sqlboiler/bdb"
	"github.com/vattle/sqlboiler/queries"
	"github.com/vattle/sqlboiler/strmangle"
)

// templateData for sqlboiler templates
type templateData struct {
	Tables []bdb.Table
	Table  bdb.Table

	// Controls what names are output
	PkgName string
	Schema  string

	// Controls which code is output (mysql vs postgres ...)
	DriverName      string
	UseLastInsertID bool

	// Turn off auto timestamps or hook generation
	NoHooks          bool
	NoAutoTimestamps bool

	// Tags control which
	Tags []string

	// StringFuncs are usable in templates with stringMap
	StringFuncs map[string]func(string) string

	// Dialect controls quoting
	Dialect queries.Dialect
	LQ      string
	RQ      string
}

func (t templateData) Quotes(s string) string {
	return fmt.Sprintf("%s%s%s", t.LQ, s, t.RQ)
}

func (t templateData) SchemaTable(table string) string {
	return strmangle.SchemaTable(t.LQ, t.RQ, t.DriverName, t.Schema, table)
}

type templateList struct {
	*template.Template
}

type templateNameList []string

func (t templateNameList) Len() int {
	return len(t)
}

func (t templateNameList) Swap(k, j int) {
	t[k], t[j] = t[j], t[k]
}

func (t templateNameList) Less(k, j int) bool {
	// Make sure "struct" goes to the front
	if t[k] == "struct.tpl" {
		return true
	}

	res := strings.Compare(t[k], t[j])
	if res <= 0 {
		return true
	}

	return false
}

// Templates returns the name of all the templates defined in the template list
func (t templateList) Templates() []string {
	tplList := t.Template.Templates()

	if len(tplList) == 0 {
		return nil
	}

	ret := make([]string, 0, len(tplList))
	for _, tpl := range tplList {
		if name := tpl.Name(); strings.HasSuffix(name, ".tpl") {
			ret = append(ret, name)
		}
	}

	sort.Sort(templateNameList(ret))

	return ret
}

// loadTemplates loads all of the template files in the specified directory.
func loadTemplates(dir string) (*templateList, error) {
	pattern := filepath.Join(dir, "*.tpl")
	tpl, err := template.New("").Funcs(templateFunctions).ParseGlob(pattern)

	if err != nil {
		return nil, err
	}

	return &templateList{Template: tpl}, err
}

// loadTemplate loads a single template file.
func loadTemplate(dir string, filename string) (*template.Template, error) {
	pattern := filepath.Join(dir, filename)
	tpl, err := template.New("").Funcs(templateFunctions).ParseFiles(pattern)

	if err != nil {
		return nil, err
	}

	return tpl.Lookup(filename), err
}

// templateStringMappers are placed into the data to make it easy to use the
// stringMap function.
var templateStringMappers = map[string]func(string) string{
	// String ops
	"quoteWrap": func(a string) string { return fmt.Sprintf(`"%s"`, a) },

	// Casing
	"titleCase": strmangle.TitleCase,
	"camelCase": strmangle.CamelCase,
}

// templateFunctions is a map of all the functions that get passed into the
// templates. If you wish to pass a new function into your own template,
// add a function pointer here.
var templateFunctions = template.FuncMap{
	// String ops
	"quoteWrap": func(s string) string { return fmt.Sprintf(`"%s"`, s) },
	"id":        strmangle.Identifier,

	// Pluralization
	"singular": strmangle.Singular,
	"plural":   strmangle.Plural,

	// Casing
	"titleCase": strmangle.TitleCase,
	"camelCase": strmangle.CamelCase,

	// String Slice ops
	"join":               func(sep string, slice []string) string { return strings.Join(slice, sep) },
	"joinSlices":         strmangle.JoinSlices,
	"stringMap":          strmangle.StringMap,
	"prefixStringSlice":  strmangle.PrefixStringSlice,
	"containsAny":        strmangle.ContainsAny,
	"generateTags":       strmangle.GenerateTags,
	"generateIgnoreTags": strmangle.GenerateIgnoreTags,

	// String Map ops
	"makeStringMap": strmangle.MakeStringMap,

	// Set operations
	"setInclude": strmangle.SetInclude,

	// Database related mangling
	"whereClause": strmangle.WhereClause,

	// Relationship text helpers
	"txtsFromFKey":     txtsFromFKey,
	"txtsFromOneToOne": txtsFromOneToOne,
	"txtsFromToMany":   txtsFromToMany,

	// dbdrivers ops
	"filterColumnsByDefault": bdb.FilterColumnsByDefault,
	"autoIncPrimaryKey":      bdb.AutoIncPrimaryKey,
	"sqlColDefinitions":      bdb.SQLColDefinitions,
	"columnNames":            bdb.ColumnNames,
	"columnDBTypes":          bdb.ColumnDBTypes,
	"getTable":               bdb.GetTable,
}
<|endoftext|>


<commit_before>/*
Copyright IBM Corp All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package raft

import (
	"encoding/json"
	"fmt"
	"testing"

	"github.com/hyperledger/fabric/common/flogging"
	"github.com/hyperledger/fabric/integration"
	"github.com/hyperledger/fabric/integration/nwo"
	"github.com/hyperledger/fabric/integration/nwo/commands"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

func TestRaft(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Raft-based Ordering Service Suite")
}

var (
	buildServer *nwo.BuildServer
	components  *nwo.Components
)

var _ = SynchronizedBeforeSuite(func() []byte {
	buildServer = nwo.NewBuildServer()
	buildServer.Serve()

	components = buildServer.Components()
	payload, err := json.Marshal(components)
	Expect(err).NotTo(HaveOccurred())

	return payload
}, func(payload []byte) {
	err := json.Unmarshal(payload, &components)
	Expect(err).NotTo(HaveOccurred())

	flogging.SetWriter(GinkgoWriter)
})

var _ = SynchronizedAfterSuite(func() {
}, func() {
	buildServer.Shutdown()
})

func StartPort() int {
	return integration.RaftBasePort.StartPortForNode()
}

func RunInvoke(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, channel string) {
	By("Querying chaincode")
	sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeInvoke{
		ChannelID: channel,
		Orderer:   n.OrdererAddress(orderer, nwo.ListenPort),
		Name:      "mycc",
		Ctor:      `{"Args":["invoke","a","b","10"]}`,
		PeerAddresses: []string{
			n.PeerAddress(n.Peer("Org1", "peer0"), nwo.ListenPort),
			n.PeerAddress(n.Peer("Org2", "peer0"), nwo.ListenPort),
		},
		WaitForEvent: true,
	})
	Expect(err).NotTo(HaveOccurred())
	Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))
	Expect(sess.Err).To(gbytes.Say("Chaincode invoke successful. result: status:200"))
}

func RunQuery(n *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer, channel string) int {
	By("Invoking chaincode")
	sess, err := n.PeerUserSession(peer, "User1", commands.ChaincodeQuery{
		ChannelID: channel,
		Name:      "mycc",
		Ctor:      `{"Args":["query","a"]}`,
	})
	Expect(err).NotTo(HaveOccurred())
	Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0))

	var result int
	i, err := fmt.Sscanf(string(sess.Out.Contents()), "%d", &result)
	Expect(err).NotTo(HaveOccurred())
	Expect(i).To(Equal(1))
	return int(result)
}
<commit_msg>Remove unused helpers from raft suite<commit_after>/*
Copyright IBM Corp All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package raft

import (
	"encoding/json"
	"testing"

	"github.com/hyperledger/fabric/common/flogging"
	"github.com/hyperledger/fabric/integration"
	"github.com/hyperledger/fabric/integration/nwo"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

func TestRaft(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Raft-based Ordering Service Suite")
}

var (
	buildServer *nwo.BuildServer
	components  *nwo.Components
)

var _ = SynchronizedBeforeSuite(func() []byte {
	buildServer = nwo.NewBuildServer()
	buildServer.Serve()

	components = buildServer.Components()
	payload, err := json.Marshal(components)
	Expect(err).NotTo(HaveOccurred())

	return payload
}, func(payload []byte) {
	err := json.Unmarshal(payload, &components)
	Expect(err).NotTo(HaveOccurred())

	flogging.SetWriter(GinkgoWriter)
})

var _ = SynchronizedAfterSuite(func() {
}, func() {
	buildServer.Shutdown()
})

func StartPort() int {
	return integration.RaftBasePort.StartPortForNode()
}
<|endoftext|>


<commit_before>package integrationtest

import (
	"bytes"
	"encoding/json"
	"os"
	"regexp"
	"testing"
	"time"

	"github.com/taskcluster/slugid-go/slugid"
	"github.com/taskcluster/taskcluster-base-go/jsontest"
	"github.com/taskcluster/taskcluster-client-go/index"
	"github.com/taskcluster/taskcluster-client-go/queue"
	"github.com/taskcluster/taskcluster-client-go/tcclient"
)

// This is a silly test that looks for the latest mozilla-central buildbot linux64 l10n build
// and asserts that it must have a created time between a year ago and an hour in the future.
//
// Could easily break at a point in the future, at which point we can change to something else.
//
// Note, no credentials are needed, so this can be run even on travis-ci.org, for example.
func TestFindLatestBuildbotTask(t *testing.T) {
	creds := &tcclient.Credentials{}
	Index := index.New(creds)
	Queue := queue.New(creds)
	itr, _, err := Index.FindTask("buildbot.branches.mozilla-central.linux64.l10n")
	if err != nil {
		t.Fatalf("%v\n", err)
	}
	taskId := itr.TaskId
	td, _, err := Queue.Task(taskId)
	if err != nil {
		t.Fatalf("%v\n", err)
	}
	created := time.Time(td.Created).Local()

	// calculate time an hour in the future to allow for clock drift
	now := time.Now().Local()
	inAnHour := now.Add(time.Hour * 1)
	aYearAgo := now.AddDate(-1, 0, 0)
	t.Log("")
	t.Log("  => Task " + taskId + " was created on " + created.Format("Mon, 2 Jan 2006 at 15:04:00 -0700"))
	t.Log("")
	if created.After(inAnHour) {
		t.Log("Current time: " + now.Format("Mon, 2 Jan 2006 at 15:04:00 -0700"))
		t.Error("Task " + taskId + " has a creation date that is over an hour in the future")
	}
	if created.Before(aYearAgo) {
		t.Log("Current time: " + now.Format("Mon, 2 Jan 2006 at 15:04:00 -0700"))
		t.Error("Task " + taskId + " has a creation date that is over a year old")
	}

}

func permaCreds(t *testing.T) *tcclient.Credentials {
	permaCreds := &tcclient.Credentials{
		ClientId:    os.Getenv("TASKCLUSTER_CLIENT_ID"),
		AccessToken: os.Getenv("TASKCLUSTER_ACCESS_TOKEN"),
		Certificate: os.Getenv("TASKCLUSTER_CERTIFICATE"),
	}
	if permaCreds.ClientId == "" || permaCreds.AccessToken == "" {
		t.Skip("Skipping test TestDefineTask since TASKCLUSTER_CLIENT_ID and/or TASKCLUSTER_ACCESS_TOKEN env vars not set")
	}
	return permaCreds
}

// Tests whether it is possible to define a task against the production Queue.
func TestDefineTask(t *testing.T) {
	permaCreds := permaCreds(t)
	myQueue := queue.New(permaCreds)

	taskId := slugid.Nice()
	created := time.Now()
	deadline := created.AddDate(0, 0, 1)
	expires := deadline

	td := &queue.TaskDefinitionRequest{
		Created:  tcclient.Time(created),
		Deadline: tcclient.Time(deadline),
		Expires:  tcclient.Time(expires),
		Extra:    json.RawMessage(`{"index":{"rank":12345}}`),
		Metadata: struct {
			Description string `json:"description"`
			Name        string `json:"name"`
			Owner       string `json:"owner"`
			Source      string `json:"source"`
		}{
			Description: "Stuff",
			Name:        "[TC] Pete",
			Owner:       "pmoore@mozilla.com",
			Source:      "http://everywhere.com/",
		},
		Payload:       json.RawMessage(`{"features":{"relengApiProxy":true}}`),
		ProvisionerId: "win-provisioner",
		Retries:       5,
		Routes: []string{
			"tc-treeherder.mozilla-inbound.bcf29c305519d6e120b2e4d3b8aa33baaf5f0163",
			"tc-treeherder-stage.mozilla-inbound.bcf29c305519d6e120b2e4d3b8aa33baaf5f0163",
		},
		SchedulerId: "go-test-test-scheduler",
		Scopes: []string{
			"test-worker:image:toastposter/pumpkin:0.5.6",
		},
		Tags:        json.RawMessage(`{"createdForUser":"cbook@mozilla.com"}`),
		Priority:    "high",
		TaskGroupId: "dtwuF2n9S-i83G37V9eBuQ",
		WorkerType:  "win2008-worker",
	}

	tsr, cs, err := myQueue.DefineTask(taskId, td)

	//////////////////////////////////
	// And now validate results.... //
	//////////////////////////////////

	if err != nil {
		b := bytes.Buffer{}
		cs.HttpRequest.Header.Write(&b)
		headers := regexp.MustCompile(`(mac|nonce)="[^"]*"`).ReplaceAllString(b.String(), `$1="***********"`)
		t.Logf("\n\nRequest sent:\n\nURL: %s\nMethod: %s\nHeaders:\n%v\nBody: %s", cs.HttpRequest.URL, cs.HttpRequest.Method, headers, cs.HttpRequestBody)
		t.Fatalf("\n\nResponse received:\n\n%s", err)
	}

	t.Logf("Task https://queue.taskcluster.net/v1/task/%v created successfully", taskId)

	if provisionerId := cs.HttpRequestObject.(*queue.TaskDefinitionRequest).ProvisionerId; provisionerId != "win-provisioner" {
		t.Errorf("provisionerId 'win-provisioner' expected but got %s", provisionerId)
	}
	if schedulerId := tsr.Status.SchedulerId; schedulerId != "go-test-test-scheduler" {
		t.Errorf("schedulerId 'go-test-test-scheduler' expected but got %s", schedulerId)
	}
	if retriesLeft := tsr.Status.RetriesLeft; retriesLeft != 5 {
		t.Errorf("Expected 'retriesLeft' to be 5, but got %v", retriesLeft)
	}
	if state := tsr.Status.State; state != "unscheduled" {
		t.Errorf("Expected 'state' to be 'unscheduled', but got %s", state)
	}
	submittedPayload := cs.HttpRequestBody

	// only the contents is relevant below - the formatting and order of properties does not matter
	// since a json comparison is done, not a string comparison...
	expectedJson := []byte(`
	{
	  "created":  "` + created.UTC().Format("2006-01-02T15:04:05.000Z") + `",
	  "deadline": "` + deadline.UTC().Format("2006-01-02T15:04:05.000Z") + `",
	  "expires":  "` + expires.UTC().Format("2006-01-02T15:04:05.000Z") + `",

	  "taskGroupId": "dtwuF2n9S-i83G37V9eBuQ",
	  "workerType":  "win2008-worker",
	  "schedulerId": "go-test-test-scheduler",

	  "payload": {
	    "features": {
	      "relengApiProxy":true
	    }
	  },

	  "priority":      "high",
	  "provisionerId": "win-provisioner",
	  "retries":       5,

	  "routes": [
	    "tc-treeherder.mozilla-inbound.bcf29c305519d6e120b2e4d3b8aa33baaf5f0163",
	    "tc-treeherder-stage.mozilla-inbound.bcf29c305519d6e120b2e4d3b8aa33baaf5f0163"
	  ],

	  "scopes": [
	    "test-worker:image:toastposter/pumpkin:0.5.6"
	  ],

	  "tags": {
	    "createdForUser": "cbook@mozilla.com"
	  },

	  "extra": {
	    "index": {
	      "rank": 12345
	    }
	  },

	  "metadata": {
	    "description": "Stuff",
	    "name":        "[TC] Pete",
	    "owner":       "pmoore@mozilla.com",
	    "source":      "http://everywhere.com/"
	  }
	}
	`)

	jsonCorrect, formattedExpected, formattedActual, err := jsontest.JsonEqual(expectedJson, []byte(submittedPayload))
	if err != nil {
		t.Fatalf("Exception thrown formatting json data!\n%s\n\nStruggled to format either:\n%s\n\nor:\n\n%s", err, string(expectedJson), submittedPayload)
	}

	if !jsonCorrect {
		t.Log("Anticipated json not generated. Expected:")
		t.Logf("%s", formattedExpected)
		t.Log("Actual:")
		t.Errorf("%s", formattedActual)
	}

	// check it is possible to cancel the unscheduled task using **temporary credentials**
	tempCreds, err := permaCreds.CreateTemporaryCredentials(30*time.Second, "queue:cancel-task:"+td.SchedulerId+"/"+td.TaskGroupId+"/"+taskId)
	if err != nil {
		t.Fatalf("Exception thrown generating temporary credentials!\n\n%s\n\n", err)
	}
	myQueue = queue.New(tempCreds)
	_, cs, err = myQueue.CancelTask(taskId)
	if err != nil {
		t.Logf("Exception thrown cancelling task with temporary credentials!\n\n%s\n\n", err)
		t.Fatalf("\n\n%s\n", cs.HttpRequest.Header)
	}
}
<commit_msg>Fixed integration test to not create a task in an existing task graph that has tasks with another schedulerId already<commit_after>package integrationtest

import (
	"bytes"
	"encoding/json"
	"os"
	"regexp"
	"testing"
	"time"

	"github.com/taskcluster/slugid-go/slugid"
	"github.com/taskcluster/taskcluster-base-go/jsontest"
	"github.com/taskcluster/taskcluster-client-go/index"
	"github.com/taskcluster/taskcluster-client-go/queue"
	"github.com/taskcluster/taskcluster-client-go/tcclient"
)

// This is a silly test that looks for the latest mozilla-central buildbot linux64 l10n build
// and asserts that it must have a created time between a year ago and an hour in the future.
//
// Could easily break at a point in the future, at which point we can change to something else.
//
// Note, no credentials are needed, so this can be run even on travis-ci.org, for example.
func TestFindLatestBuildbotTask(t *testing.T) {
	creds := &tcclient.Credentials{}
	Index := index.New(creds)
	Queue := queue.New(creds)
	itr, _, err := Index.FindTask("buildbot.branches.mozilla-central.linux64.l10n")
	if err != nil {
		t.Fatalf("%v\n", err)
	}
	taskId := itr.TaskId
	td, _, err := Queue.Task(taskId)
	if err != nil {
		t.Fatalf("%v\n", err)
	}
	created := time.Time(td.Created).Local()

	// calculate time an hour in the future to allow for clock drift
	now := time.Now().Local()
	inAnHour := now.Add(time.Hour * 1)
	aYearAgo := now.AddDate(-1, 0, 0)
	t.Log("")
	t.Log("  => Task " + taskId + " was created on " + created.Format("Mon, 2 Jan 2006 at 15:04:00 -0700"))
	t.Log("")
	if created.After(inAnHour) {
		t.Log("Current time: " + now.Format("Mon, 2 Jan 2006 at 15:04:00 -0700"))
		t.Error("Task " + taskId + " has a creation date that is over an hour in the future")
	}
	if created.Before(aYearAgo) {
		t.Log("Current time: " + now.Format("Mon, 2 Jan 2006 at 15:04:00 -0700"))
		t.Error("Task " + taskId + " has a creation date that is over a year old")
	}

}

func permaCreds(t *testing.T) *tcclient.Credentials {
	permaCreds := &tcclient.Credentials{
		ClientId:    os.Getenv("TASKCLUSTER_CLIENT_ID"),
		AccessToken: os.Getenv("TASKCLUSTER_ACCESS_TOKEN"),
		Certificate: os.Getenv("TASKCLUSTER_CERTIFICATE"),
	}
	if permaCreds.ClientId == "" || permaCreds.AccessToken == "" {
		t.Skip("Skipping test TestDefineTask since TASKCLUSTER_CLIENT_ID and/or TASKCLUSTER_ACCESS_TOKEN env vars not set")
	}
	return permaCreds
}

// Tests whether it is possible to define a task against the production Queue.
func TestDefineTask(t *testing.T) {
	permaCreds := permaCreds(t)
	myQueue := queue.New(permaCreds)

	taskId := slugid.Nice()
	taskGroupId := slugid.Nice()
	created := time.Now()
	deadline := created.AddDate(0, 0, 1)
	expires := deadline

	td := &queue.TaskDefinitionRequest{
		Created:  tcclient.Time(created),
		Deadline: tcclient.Time(deadline),
		Expires:  tcclient.Time(expires),
		Extra:    json.RawMessage(`{"index":{"rank":12345}}`),
		Metadata: struct {
			Description string `json:"description"`
			Name        string `json:"name"`
			Owner       string `json:"owner"`
			Source      string `json:"source"`
		}{
			Description: "Stuff",
			Name:        "[TC] Pete",
			Owner:       "pmoore@mozilla.com",
			Source:      "http://everywhere.com/",
		},
		Payload:       json.RawMessage(`{"features":{"relengApiProxy":true}}`),
		ProvisionerId: "win-provisioner",
		Retries:       5,
		Routes: []string{
			"tc-treeherder.mozilla-inbound.bcf29c305519d6e120b2e4d3b8aa33baaf5f0163",
			"tc-treeherder-stage.mozilla-inbound.bcf29c305519d6e120b2e4d3b8aa33baaf5f0163",
		},
		SchedulerId: "go-test-test-scheduler",
		Scopes: []string{
			"test-worker:image:toastposter/pumpkin:0.5.6",
		},
		Tags:        json.RawMessage(`{"createdForUser":"cbook@mozilla.com"}`),
		Priority:    "high",
		TaskGroupId: taskGroupId,
		WorkerType:  "win2008-worker",
	}

	tsr, cs, err := myQueue.DefineTask(taskId, td)

	//////////////////////////////////
	// And now validate results.... //
	//////////////////////////////////

	if err != nil {
		b := bytes.Buffer{}
		cs.HttpRequest.Header.Write(&b)
		headers := regexp.MustCompile(`(mac|nonce)="[^"]*"`).ReplaceAllString(b.String(), `$1="***********"`)
		t.Logf("\n\nRequest sent:\n\nURL: %s\nMethod: %s\nHeaders:\n%v\nBody: %s", cs.HttpRequest.URL, cs.HttpRequest.Method, headers, cs.HttpRequestBody)
		t.Fatalf("\n\nResponse received:\n\n%s", err)
	}

	t.Logf("Task https://queue.taskcluster.net/v1/task/%v created successfully", taskId)

	if provisionerId := cs.HttpRequestObject.(*queue.TaskDefinitionRequest).ProvisionerId; provisionerId != "win-provisioner" {
		t.Errorf("provisionerId 'win-provisioner' expected but got %s", provisionerId)
	}
	if schedulerId := tsr.Status.SchedulerId; schedulerId != "go-test-test-scheduler" {
		t.Errorf("schedulerId 'go-test-test-scheduler' expected but got %s", schedulerId)
	}
	if retriesLeft := tsr.Status.RetriesLeft; retriesLeft != 5 {
		t.Errorf("Expected 'retriesLeft' to be 5, but got %v", retriesLeft)
	}
	if state := tsr.Status.State; state != "unscheduled" {
		t.Errorf("Expected 'state' to be 'unscheduled', but got %s", state)
	}
	submittedPayload := cs.HttpRequestBody

	// only the contents is relevant below - the formatting and order of properties does not matter
	// since a json comparison is done, not a string comparison...
	expectedJson := []byte(`
	{
	  "created":  "` + created.UTC().Format("2006-01-02T15:04:05.000Z") + `",
	  "deadline": "` + deadline.UTC().Format("2006-01-02T15:04:05.000Z") + `",
	  "expires":  "` + expires.UTC().Format("2006-01-02T15:04:05.000Z") + `",

	  "taskGroupId": "` + taskGroupId + `",
	  "workerType":  "win2008-worker",
	  "schedulerId": "go-test-test-scheduler",

	  "payload": {
	    "features": {
	      "relengApiProxy":true
	    }
	  },

	  "priority":      "high",
	  "provisionerId": "win-provisioner",
	  "retries":       5,

	  "routes": [
	    "tc-treeherder.mozilla-inbound.bcf29c305519d6e120b2e4d3b8aa33baaf5f0163",
	    "tc-treeherder-stage.mozilla-inbound.bcf29c305519d6e120b2e4d3b8aa33baaf5f0163"
	  ],

	  "scopes": [
	    "test-worker:image:toastposter/pumpkin:0.5.6"
	  ],

	  "tags": {
	    "createdForUser": "cbook@mozilla.com"
	  },

	  "extra": {
	    "index": {
	      "rank": 12345
	    }
	  },

	  "metadata": {
	    "description": "Stuff",
	    "name":        "[TC] Pete",
	    "owner":       "pmoore@mozilla.com",
	    "source":      "http://everywhere.com/"
	  }
	}
	`)

	jsonCorrect, formattedExpected, formattedActual, err := jsontest.JsonEqual(expectedJson, []byte(submittedPayload))
	if err != nil {
		t.Fatalf("Exception thrown formatting json data!\n%s\n\nStruggled to format either:\n%s\n\nor:\n\n%s", err, string(expectedJson), submittedPayload)
	}

	if !jsonCorrect {
		t.Log("Anticipated json not generated. Expected:")
		t.Logf("%s", formattedExpected)
		t.Log("Actual:")
		t.Errorf("%s", formattedActual)
	}

	// check it is possible to cancel the unscheduled task using **temporary credentials**
	tempCreds, err := permaCreds.CreateTemporaryCredentials(30*time.Second, "queue:cancel-task:"+td.SchedulerId+"/"+td.TaskGroupId+"/"+taskId)
	if err != nil {
		t.Fatalf("Exception thrown generating temporary credentials!\n\n%s\n\n", err)
	}
	myQueue = queue.New(tempCreds)
	_, cs, err = myQueue.CancelTask(taskId)
	if err != nil {
		t.Logf("Exception thrown cancelling task with temporary credentials!\n\n%s\n\n", err)
		t.Fatalf("\n\n%s\n", cs.HttpRequest.Header)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"time"

	"cloud.google.com/go/spanner"
	"google.golang.org/api/iterator"
	adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
	spannerpb "google.golang.org/genproto/googleapis/spanner/v1"
)

type Statement interface {
	Execute(session *Session) (*Result, error)
}

type Result struct {
	ColumnNames []string
	Rows        []Row
	QueryStats  QueryStats
	IsMutation  bool
}

type Row struct {
	Columns []string
}

type QueryStats struct {
	Rows        int
	ElapsedTime string
}

var (
	exitRe            = regexp.MustCompile(`(?i)^EXIT$`)
	selectRe          = regexp.MustCompile(`(?i)^SELECT\s.+$`)
	createTableRe     = regexp.MustCompile(`(?i)^CREATE\s+TABLE\s.+$`)
	showDatabasesRe   = regexp.MustCompile(`(?i)^SHOW\s+DATABASES$`)
	showCreateTableRe = regexp.MustCompile(`(?i)^SHOW\s+CREATE\s+TABLE\s+(.*)$`)
)

var (
	statementExitError = errors.New("exit")
)

func buildStatement(input string) (Statement, error) {
	var stmt Statement

	if exitRe.MatchString(input) {
		return nil, statementExitError
	} else if selectRe.MatchString(input) {
		stmt = &QueryStatement{
			text: input,
		}
	} else if createTableRe.MatchString(input) {
		stmt = &CreateTableStatement{
			text: input,
		}
	} else if showDatabasesRe.MatchString(input) {
		stmt = &ShowDatabasesStatement{}
	} else if showCreateTableRe.MatchString(input) {
		matched := showCreateTableRe.FindStringSubmatch(input)
		stmt = &ShowCreateTableStatement{
			table: matched[1],
		}
	}

	if stmt == nil {
		return nil, errors.New("invalid statement")
	}

	return stmt, nil
}

type QueryStatement struct {
	text string
}

func (s *QueryStatement) Execute(session *Session) (*Result, error) {
	stmt := spanner.NewStatement(s.text)
	iter := session.client.Single().QueryWithStats(session.ctx, stmt)

	result := &Result{
		ColumnNames: make([]string, 0),
		Rows:        make([]Row, 0),
		IsMutation:  false,
	}

	defer iter.Stop()
	for {
		row, err := iter.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, err
		}

		resultRow := Row{
			Columns: make([]string, row.Size()),
		}

		result.ColumnNames = row.ColumnNames() // TODO

		for i := 0; i < row.Size(); i++ {
			var column spanner.GenericColumnValue
			err := row.Column(i, &column)
			if err != nil {
				return nil, err
			}
			// fmt.Println(column.Type.Code)
			switch column.Type.Code {
			case spannerpb.TypeCode_INT64:
				var v int64
				if err := column.Decode(&v); err != nil {
					return nil, err
				}
				resultRow.Columns[i] = fmt.Sprintf("%d", v)
			case spannerpb.TypeCode_STRING:
				var v string
				if err := column.Decode(&v); err != nil {
					return nil, err
				}
				resultRow.Columns[i] = v
			default:
				resultRow.Columns[i] = fmt.Sprintf("%s", column.Value)
			}
		}

		result.Rows = append(result.Rows, resultRow)
	}

	rowsReturned, _ := strconv.Atoi(iter.QueryStats["rows_returned"].(string))
	elapsedTime := iter.QueryStats["elapsed_time"].(string)
	result.QueryStats = QueryStats{
		Rows:        rowsReturned,
		ElapsedTime: elapsedTime,
	}

	return result, nil
}

type CreateTableStatement struct {
	text string
}

func (s *CreateTableStatement) Execute(session *Session) (*Result, error) {
	result := &Result{
		ColumnNames: make([]string, 0),
		Rows:        make([]Row, 0),
		IsMutation:  true,
	}

	t1 := time.Now()
	op, err := session.adminClient.UpdateDatabaseDdl(session.ctx, &adminpb.UpdateDatabaseDdlRequest{
		Database:   session.GetDatabasePath(),
		Statements: []string{s.text},
	})
	if err != nil {
		return nil, err
	}
	if err := op.Wait(session.ctx); err != nil {
		return nil, err
	}
	elapsed := time.Since(t1).String()

	result.QueryStats = QueryStats{
		Rows:        0,
		ElapsedTime: elapsed,
	}

	return result, nil
}

type ShowDatabasesStatement struct {
}

func (s *ShowDatabasesStatement) Execute(session *Session) (*Result, error) {
	result := &Result{
		ColumnNames: []string{"Database"},
		Rows:        make([]Row, 0),
		IsMutation:  false,
	}

	t1 := time.Now()

	dbIter := session.adminClient.ListDatabases(session.ctx, &adminpb.ListDatabasesRequest{
		Parent: session.GetInstancePath(),
	})

	for {
		database, err := dbIter.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, err
		}

		re := regexp.MustCompile(`projects/[^/]+/instances/[^/]+/databases/(.+)`)
		matched := re.FindStringSubmatch(database.GetName())
		dbname := matched[1]
		resultRow := Row{
			Columns: []string{dbname},
		}
		result.Rows = append(result.Rows, resultRow)
	}

	elapsed := time.Since(t1).String()

	result.QueryStats = QueryStats{
		Rows:        len(result.Rows),
		ElapsedTime: elapsed,
	}

	return result, nil
}

type ShowCreateTableStatement struct {
	table string
}

func (s *ShowCreateTableStatement) Execute(session *Session) (*Result, error) {
	result := &Result{
		ColumnNames: []string{"Table", "Create Table"},
		Rows:        make([]Row, 0),
		IsMutation:  false,
	}

	t1 := time.Now()

	ddlResponse, err := session.adminClient.GetDatabaseDdl(session.ctx, &adminpb.GetDatabaseDdlRequest{
		Database: session.GetDatabasePath(),
	})
	if err != nil {
		return nil, err
	}
	for _, statement := range ddlResponse.Statements {
		if strings.HasPrefix(statement, fmt.Sprintf("CREATE TABLE %s", s.table)) {
			resultRow := Row{
				Columns: []string{s.table, statement},
			}
			result.Rows = append(result.Rows, resultRow)
			break
		}
	}

	elapsed := time.Since(t1).String()

	result.QueryStats = QueryStats{
		Rows:        len(result.Rows),
		ElapsedTime: elapsed,
	}

	return result, nil
}
<commit_msg>Implement SHOW TABLES<commit_after>package main

import (
	"errors"
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"time"

	"cloud.google.com/go/spanner"
	"google.golang.org/api/iterator"
	adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
	spannerpb "google.golang.org/genproto/googleapis/spanner/v1"
)

type Statement interface {
	Execute(session *Session) (*Result, error)
}

type Result struct {
	ColumnNames []string
	Rows        []Row
	QueryStats  QueryStats
	IsMutation  bool
}

type Row struct {
	Columns []string
}

type QueryStats struct {
	Rows        int
	ElapsedTime string
}

var (
	exitRe            = regexp.MustCompile(`(?i)^EXIT$`)
	selectRe          = regexp.MustCompile(`(?i)^SELECT\s.+$`)
	createTableRe     = regexp.MustCompile(`(?i)^CREATE\s+TABLE\s.+$`)
	showDatabasesRe   = regexp.MustCompile(`(?i)^SHOW\s+DATABASES$`)
	showCreateTableRe = regexp.MustCompile(`(?i)^SHOW\s+CREATE\s+TABLE\s+(.*)$`)
	showTablesRe      = regexp.MustCompile(`(?i)^SHOW\s+TABLES$`)
)

var (
	statementExitError = errors.New("exit")
)

func buildStatement(input string) (Statement, error) {
	var stmt Statement

	if exitRe.MatchString(input) {
		return nil, statementExitError
	} else if selectRe.MatchString(input) {
		stmt = &QueryStatement{
			text: input,
		}
	} else if createTableRe.MatchString(input) {
		stmt = &CreateTableStatement{
			text: input,
		}
	} else if showDatabasesRe.MatchString(input) {
		stmt = &ShowDatabasesStatement{}
	} else if showCreateTableRe.MatchString(input) {
		matched := showCreateTableRe.FindStringSubmatch(input)
		stmt = &ShowCreateTableStatement{
			table: matched[1],
		}
	} else if showTablesRe.MatchString(input) {
		stmt = &ShowTablesStatement{}
	}

	if stmt == nil {
		return nil, errors.New("invalid statement")
	}

	return stmt, nil
}

type QueryStatement struct {
	text string
}

func (s *QueryStatement) Execute(session *Session) (*Result, error) {
	stmt := spanner.NewStatement(s.text)
	iter := session.client.Single().QueryWithStats(session.ctx, stmt)

	result := &Result{
		ColumnNames: make([]string, 0),
		Rows:        make([]Row, 0),
		IsMutation:  false,
	}

	defer iter.Stop()
	for {
		row, err := iter.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, err
		}

		resultRow := Row{
			Columns: make([]string, row.Size()),
		}

		result.ColumnNames = row.ColumnNames() // TODO

		for i := 0; i < row.Size(); i++ {
			var column spanner.GenericColumnValue
			err := row.Column(i, &column)
			if err != nil {
				return nil, err
			}
			// fmt.Println(column.Type.Code)
			switch column.Type.Code {
			case spannerpb.TypeCode_INT64:
				var v int64
				if err := column.Decode(&v); err != nil {
					return nil, err
				}
				resultRow.Columns[i] = fmt.Sprintf("%d", v)
			case spannerpb.TypeCode_STRING:
				var v string
				if err := column.Decode(&v); err != nil {
					return nil, err
				}
				resultRow.Columns[i] = v
			default:
				resultRow.Columns[i] = fmt.Sprintf("%s", column.Value)
			}
		}

		result.Rows = append(result.Rows, resultRow)
	}

	rowsReturned, _ := strconv.Atoi(iter.QueryStats["rows_returned"].(string))
	elapsedTime := iter.QueryStats["elapsed_time"].(string)
	result.QueryStats = QueryStats{
		Rows:        rowsReturned,
		ElapsedTime: elapsedTime,
	}

	return result, nil
}

type CreateTableStatement struct {
	text string
}

func (s *CreateTableStatement) Execute(session *Session) (*Result, error) {
	result := &Result{
		ColumnNames: make([]string, 0),
		Rows:        make([]Row, 0),
		IsMutation:  true,
	}

	t1 := time.Now()
	op, err := session.adminClient.UpdateDatabaseDdl(session.ctx, &adminpb.UpdateDatabaseDdlRequest{
		Database:   session.GetDatabasePath(),
		Statements: []string{s.text},
	})
	if err != nil {
		return nil, err
	}
	if err := op.Wait(session.ctx); err != nil {
		return nil, err
	}
	elapsed := time.Since(t1).String()

	result.QueryStats = QueryStats{
		Rows:        0,
		ElapsedTime: elapsed,
	}

	return result, nil
}

type ShowDatabasesStatement struct {
}

func (s *ShowDatabasesStatement) Execute(session *Session) (*Result, error) {
	result := &Result{
		ColumnNames: []string{"Database"},
		Rows:        make([]Row, 0),
		IsMutation:  false,
	}

	t1 := time.Now()

	dbIter := session.adminClient.ListDatabases(session.ctx, &adminpb.ListDatabasesRequest{
		Parent: session.GetInstancePath(),
	})

	for {
		database, err := dbIter.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, err
		}

		re := regexp.MustCompile(`projects/[^/]+/instances/[^/]+/databases/(.+)`)
		matched := re.FindStringSubmatch(database.GetName())
		dbname := matched[1]
		resultRow := Row{
			Columns: []string{dbname},
		}
		result.Rows = append(result.Rows, resultRow)
	}

	elapsed := time.Since(t1).String()

	result.QueryStats = QueryStats{
		Rows:        len(result.Rows),
		ElapsedTime: elapsed,
	}

	return result, nil
}

type ShowCreateTableStatement struct {
	table string
}

func (s *ShowCreateTableStatement) Execute(session *Session) (*Result, error) {
	result := &Result{
		ColumnNames: []string{"Table", "Create Table"},
		Rows:        make([]Row, 0),
		IsMutation:  false,
	}

	t1 := time.Now()

	ddlResponse, err := session.adminClient.GetDatabaseDdl(session.ctx, &adminpb.GetDatabaseDdlRequest{
		Database: session.GetDatabasePath(),
	})
	if err != nil {
		return nil, err
	}
	for _, statement := range ddlResponse.Statements {
		if strings.HasPrefix(statement, fmt.Sprintf("CREATE TABLE %s", s.table)) {
			resultRow := Row{
				Columns: []string{s.table, statement},
			}
			result.Rows = append(result.Rows, resultRow)
			break
		}
	}

	elapsed := time.Since(t1).String()

	result.QueryStats = QueryStats{
		Rows:        len(result.Rows),
		ElapsedTime: elapsed,
	}

	return result, nil
}

type ShowTablesStatement struct{}

func (s *ShowTablesStatement) Execute(session *Session) (*Result, error) {
	query := QueryStatement{
		text: `SELECT t.table_name FROM information_schema.tables AS t WHERE t.table_catalog = '' and t.table_schema = ''`,
	}

	result, err := query.Execute(session)
	if err != nil {
		return nil, err
	}

	// rename column name
	if len(result.ColumnNames) == 1 {
		result.ColumnNames[0] = fmt.Sprintf("Tables_in_%s", session.databaseId)
	}

	return result, nil
}
<|endoftext|>