<commit_before>package api

import (
	"testing"

	"github.com/grafana/grafana/pkg/api/dtos"
	"github.com/grafana/grafana/pkg/bus"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/services/annotations"

	. "github.com/smartystreets/goconvey/convey"
)

func TestAnnotationsApiEndpoint(t *testing.T) {
	Convey("Given an annotation without a dashboard id", t, func() {
		cmd := dtos.PostAnnotationsCmd{
			Time:     1000,
			Text:     "annotation text",
			Tags:     []string{"tag1", "tag2"},
			IsRegion: false,
		}

		updateCmd := dtos.UpdateAnnotationsCmd{
			Time:     1000,
			Text:     "annotation text",
			Tags:     []string{"tag1", "tag2"},
			IsRegion: false,
		}

		Convey("When user is an Org Viewer", func() {
			role := m.ROLE_VIEWER
			Convey("Should not be allowed to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})
			})
		})

		Convey("When user is an Org Editor", func() {
			role := m.ROLE_EDITOR
			Convey("Should be able to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})
			})
		})
	})

	Convey("Given an annotation with a dashboard id and the dashboard does not have an acl", t, func() {
		cmd := dtos.PostAnnotationsCmd{
			Time:        1000,
			Text:        "annotation text",
			Tags:        []string{"tag1", "tag2"},
			IsRegion:    false,
			DashboardId: 1,
			PanelId:     1,
		}

		updateCmd := dtos.UpdateAnnotationsCmd{
			Time:     1000,
			Text:     "annotation text",
			Tags:     []string{"tag1", "tag2"},
			IsRegion: false,
			Id:       1,
		}

		viewerRole := m.ROLE_VIEWER
		editorRole := m.ROLE_EDITOR

		aclMockResp := []*m.DashboardAclInfoDTO{
			{Role: &viewerRole, Permission: m.PERMISSION_VIEW},
			{Role: &editorRole, Permission: m.PERMISSION_EDIT},
		}

		bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
			query.Result = aclMockResp
			return nil
		})

		bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error {
			query.Result = []*m.Team{}
			return nil
		})

		Convey("When user is an Org Viewer", func() {
			role := m.ROLE_VIEWER
			Convey("Should not be allowed to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})
			})
		})

		Convey("When user is an Org Editor", func() {
			role := m.ROLE_EDITOR
			Convey("Should be able to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})
			})
		})
	})
}

type fakeAnnotationsRepo struct {
}

func (repo *fakeAnnotationsRepo) Delete(params *annotations.DeleteParams) error {
	return nil
}
func (repo *fakeAnnotationsRepo) Save(item *annotations.Item) error {
	item.Id = 1
	return nil
}
func (repo *fakeAnnotationsRepo) Update(item *annotations.Item) error {
	return nil
}
func (repo *fakeAnnotationsRepo) Find(query *annotations.ItemQuery) ([]*annotations.ItemDTO, error) {
	annotations := []*annotations.ItemDTO{{Id: 1}}
	return annotations, nil
}

var fakeAnnoRepo *fakeAnnotationsRepo

func postAnnotationScenario(desc string, url string, routePattern string, role m.RoleType, cmd dtos.PostAnnotationsCmd, fn scenarioFunc) {
	Convey(desc+" "+url, func() {
		defer bus.ClearBusHandlers()

		sc := setupScenarioContext(url)
		sc.defaultHandler = wrap(func(c *m.ReqContext) Response {
			sc.context = c
			sc.context.UserId = TestUserID
			sc.context.OrgId = TestOrgID
			sc.context.OrgRole = role

			return PostAnnotation(c, cmd)
		})

		fakeAnnoRepo = &fakeAnnotationsRepo{}
		annotations.SetRepository(fakeAnnoRepo)

		sc.m.Post(routePattern, sc.defaultHandler)

		fn(sc)
	})
}

func putAnnotationScenario(desc string, url string, routePattern string, role m.RoleType, cmd dtos.UpdateAnnotationsCmd, fn scenarioFunc) {
	Convey(desc+" "+url, func() {
		defer bus.ClearBusHandlers()

		sc := setupScenarioContext(url)
		sc.defaultHandler = wrap(func(c *m.ReqContext) Response {
			sc.context = c
			sc.context.UserId = TestUserID
			sc.context.OrgId = TestOrgID
			sc.context.OrgRole = role

			return UpdateAnnotation(c, cmd)
		})

		fakeAnnoRepo = &fakeAnnotationsRepo{}
		annotations.SetRepository(fakeAnnoRepo)

		sc.m.Put(routePattern, sc.defaultHandler)

		fn(sc)
	})
}
<commit_msg>add dashboardId to test<commit_after>package api

import (
	"testing"

	"github.com/grafana/grafana/pkg/api/dtos"
	"github.com/grafana/grafana/pkg/bus"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/services/annotations"

	. "github.com/smartystreets/goconvey/convey"
)

func TestAnnotationsApiEndpoint(t *testing.T) {
	Convey("Given an annotation without a dashboard id", t, func() {
		cmd := dtos.PostAnnotationsCmd{
			Time:        1000,
			Text:        "annotation text",
			Tags:        []string{"tag1", "tag2"},
			IsRegion:    false,
			DashboardId: 1,
		}

		updateCmd := dtos.UpdateAnnotationsCmd{
			Time:     1000,
			Text:     "annotation text",
			Tags:     []string{"tag1", "tag2"},
			IsRegion: false,
		}

		Convey("When user is an Org Viewer", func() {
			role := m.ROLE_VIEWER
			Convey("Should not be allowed to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})
			})
		})

		Convey("When user is an Org Editor", func() {
			role := m.ROLE_EDITOR
			Convey("Should be able to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})
			})
		})
	})

	Convey("Given an annotation with a dashboard id and the dashboard does not have an acl", t, func() {
		cmd := dtos.PostAnnotationsCmd{
			Time:        1000,
			Text:        "annotation text",
			Tags:        []string{"tag1", "tag2"},
			IsRegion:    false,
			DashboardId: 1,
			PanelId:     1,
		}

		updateCmd := dtos.UpdateAnnotationsCmd{
			Time:     1000,
			Text:     "annotation text",
			Tags:     []string{"tag1", "tag2"},
			IsRegion: false,
			Id:       1,
		}

		viewerRole := m.ROLE_VIEWER
		editorRole := m.ROLE_EDITOR

		aclMockResp := []*m.DashboardAclInfoDTO{
			{Role: &viewerRole, Permission: m.PERMISSION_VIEW},
			{Role: &editorRole, Permission: m.PERMISSION_EDIT},
		}

		bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
			query.Result = aclMockResp
			return nil
		})

		bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error {
			query.Result = []*m.Team{}
			return nil
		})

		Convey("When user is an Org Viewer", func() {
			role := m.ROLE_VIEWER
			Convey("Should not be allowed to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 403)
				})
			})
		})

		Convey("When user is an Org Editor", func() {
			role := m.ROLE_EDITOR
			Convey("Should be able to save an annotation", func() {
				postAnnotationScenario("When calling POST on", "/api/annotations", "/api/annotations", role, cmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				putAnnotationScenario("When calling PUT on", "/api/annotations/1", "/api/annotations/:annotationId", role, updateCmd, func(sc *scenarioContext) {
					sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/1", "/api/annotations/:annotationId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationById
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})

				loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/annotations/region/1", "/api/annotations/region/:regionId", role, func(sc *scenarioContext) {
					sc.handlerFunc = DeleteAnnotationRegion
					sc.fakeReqWithParams("DELETE", sc.url, map[string]string{}).exec()
					So(sc.resp.Code, ShouldEqual, 200)
				})
			})
		})
	})
}

type fakeAnnotationsRepo struct {
}

func (repo *fakeAnnotationsRepo) Delete(params *annotations.DeleteParams) error {
	return nil
}
func (repo *fakeAnnotationsRepo) Save(item *annotations.Item) error {
	item.Id = 1
	return nil
}
func (repo *fakeAnnotationsRepo) Update(item *annotations.Item) error {
	return nil
}
func (repo *fakeAnnotationsRepo) Find(query *annotations.ItemQuery) ([]*annotations.ItemDTO, error) {
	annotations := []*annotations.ItemDTO{{Id: 1}}
	return annotations, nil
}

var fakeAnnoRepo *fakeAnnotationsRepo

func postAnnotationScenario(desc string, url string, routePattern string, role m.RoleType, cmd dtos.PostAnnotationsCmd, fn scenarioFunc) {
	Convey(desc+" "+url, func() {
		defer bus.ClearBusHandlers()

		sc := setupScenarioContext(url)
		sc.defaultHandler = wrap(func(c *m.ReqContext) Response {
			sc.context = c
			sc.context.UserId = TestUserID
			sc.context.OrgId = TestOrgID
			sc.context.OrgRole = role

			return PostAnnotation(c, cmd)
		})

		fakeAnnoRepo = &fakeAnnotationsRepo{}
		annotations.SetRepository(fakeAnnoRepo)

		sc.m.Post(routePattern, sc.defaultHandler)

		fn(sc)
	})
}

func putAnnotationScenario(desc string, url string, routePattern string, role m.RoleType, cmd dtos.UpdateAnnotationsCmd, fn scenarioFunc) {
	Convey(desc+" "+url, func() {
		defer bus.ClearBusHandlers()

		sc := setupScenarioContext(url)
		sc.defaultHandler = wrap(func(c *m.ReqContext) Response {
			sc.context = c
			sc.context.UserId = TestUserID
			sc.context.OrgId = TestOrgID
			sc.context.OrgRole = role

			return UpdateAnnotation(c, cmd)
		})

		fakeAnnoRepo = &fakeAnnotationsRepo{}
		annotations.SetRepository(fakeAnnoRepo)

		sc.m.Put(routePattern, sc.defaultHandler)

		fn(sc)
	})
}
<|endoftext|>


<commit_before>package looli

import (
	"testing"
)

func TestNewRouter(t *testing.T) {

}
<commit_msg>feat: add test for router<commit_after>package looli

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

func TestNewRouter(t *testing.T) {
	router := NewRouter()
	assert.True(t, router.TrailingSlashRedirect)
	assert.NotNil(t, router.allowMethods)
	assert.NotNil(t, router.tree)
	assert.NotNil(t, router.tree.children)
	assert.NotNil(t, router.tree.handlers)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"image"
	"image/color"
	"image/png"
	"log"
	"os"
	"os/signal"
	"strconv"
	"time"
)

// Version number of this tool
const Version = "0.0.2"

// Data is a struct for each network packet
type Data struct {
	toa     int64 // Timestamp of arrival in microseconds
	payload []byte  // Copied network packet
}

func getBitsFromPacket(packet []byte, byteP, bitP *int, bpP int) uint8 {
	var c uint8
	for i := 0; i < (bpP / 3); i++ {
		if *byteP >= len(packet) {
			break
		}
		c |= (packet[*byteP] & (1 << uint8(7-*bitP)))
		*bitP += 1
		if *bitP%8 == 0 {
			*bitP = 0
			*byteP += 1
		}
	}
	return c
}

func createPixel(packet []byte, byteP, bitP *int, bpP int) (c color.Color) {
	var r, g, b uint8

	if bpP == 1 {
		if (packet[*byteP] & (1 << uint8(7-*bitP))) == 0 {
			c = color.NRGBA{R: 0,
				G: 0,
				B: 0,
				A: 255}
		} else {
			c = color.NRGBA{R: 255,
				G: 255,
				B: 255,
				A: 255}
		}
		*bitP += 1
		if *bitP%8 == 0 {
			*bitP = 0
			*byteP += 1
		}
	} else {
		r = getBitsFromPacket(packet, byteP, bitP, bpP)
		g = getBitsFromPacket(packet, byteP, bitP, bpP)
		b = getBitsFromPacket(packet, byteP, bitP, bpP)

		c = color.NRGBA{R: r,
			G: g,
			B: b,
			A: 255}
	}
	return
}

func createTerminalVisualization(data []Data, bitsPerPixel int) {
	var bitPos int
	var bytePos int
	var packetLen int

	for i := range data {
		packetLen = len(data[i].payload)
		bitPos = 0
		bytePos = 0
		for {
			c := createPixel(data[i].payload, &bytePos, &bitPos, bitsPerPixel)
			r, g, b, _ := c.RGBA()
			fmt.Printf("\x1B[0m\x1B[38;2;%d;%d;%dm\u2588", uint8(r), uint8(g), uint8(b))
			if bytePos >= packetLen {
				break
			}
		}
		fmt.Printf("\x1B[m\n")

	}

}
func createTimeVisualization(data []Data, xMax int, prefix string, ts uint, bitsPerPixel int) {
	var xPos int
	var bitPos int
	var bytePos int
	var packetLen int
	var firstPkg time.Time

	img := image.NewNRGBA(image.Rect(0, 0, (xMax*8)/bitsPerPixel+1, int(ts)))

	for pkg := range data {
		if firstPkg.IsZero() {
			firstPkg = time.Unix(0, data[pkg].toa*int64(time.Microsecond))
		}
		packetLen = len(data[pkg].payload)
		xPos = 0
		bitPos = 0
		bytePos = 0
		for {
			c := createPixel(data[pkg].payload, &bytePos, &bitPos, bitsPerPixel)
			img.Set(xPos, int(data[pkg].toa%int64(ts)), c)
			xPos++
			if bytePos >= packetLen {
				break
			}
		}
	}

	filename := prefix
	filename += "-"
	filename += firstPkg.Format(time.RFC3339Nano)
	filename += ".png"
	f, err := os.Create(filename)
	if err != nil {
		log.Fatal(err)
	}

	if err := png.Encode(f, img); err != nil {
		f.Close()
		log.Fatal(err)
	}

	if err := f.Close(); err != nil {
		log.Fatal(err)
	}

	return
}

func createFixedVisualization(data []Data, xMax int, prefix string, num int, bitsPerPixel int) {
	var xPos int
	var bitPos int
	var bytePos int
	var packetLen int

	img := image.NewNRGBA(image.Rect(0, 0, (xMax*8)/bitsPerPixel+1, len(data)))

	for yPos := range data {
		packetLen = len(data[yPos].payload)
		xPos = 0
		bitPos = 0
		bytePos = 0
		for {
			c := createPixel(data[yPos].payload, &bytePos, &bitPos, bitsPerPixel)
			img.Set(xPos, yPos, c)
			xPos++
			if bytePos >= packetLen {
				break
			}
		}

	}

	filename := prefix
	filename += strconv.Itoa(num)
	filename += ".png"
	f, err := os.Create(filename)
	if err != nil {
		log.Fatal(err)
	}

	if err := png.Encode(f, img); err != nil {
		f.Close()
		log.Fatal(err)
	}

	if err := f.Close(); err != nil {
		log.Fatal(err)
	}

	return
}

func handlePackets(ps *gopacket.PacketSource, num uint, ch chan Data, sig <-chan os.Signal) {
	var count uint
	for packet := range ps.Packets() {
		var k Data

		select {
		case isr := <-sig:
			fmt.Println(isr)
			close(ch)
			return
		default:
		}
		count++
		if num != 0 && count > num {
			break
		}

		elements := packet.Data()
		if len(elements) == 0 {
			continue
		}
		k = Data{toa: (packet.Metadata().CaptureInfo.Timestamp.UnixNano() / int64(time.Microsecond)), payload: packet.Data()}
		ch <- k
	}
	close(ch)
	return
}

func availableInterfaces() {
	devices, err := pcap.FindAllDevs()
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}

	for _, device := range devices {
		if len(device.Addresses) == 0 {
			continue
		}
		fmt.Println("Interface: ", device.Name)
		for _, address := range device.Addresses {
			fmt.Println("   IP address:  ", address.IP)
			fmt.Println("   Subnet mask: ", address.Netmask)
		}
		fmt.Println("")
	}
}

func initSource(dev, file *string) (handle *pcap.Handle , err error){
	if len(*dev) > 0 {
		handle, err = pcap.OpenLive(*dev, 4096, true, pcap.BlockForever)
		if err != nil {
			log.Fatal(err)
			os.Exit(1)
		}
	} else if len(*file) > 0 {
		handle, err = pcap.OpenOffline(*file)
		if err != nil {
			log.Fatal(err)
			os.Exit(1)
		}
	} else {
		return nil, fmt.Errorf("Source is missing\n")
	}
        return
}

func main() {
	var err error
	var handle *pcap.Handle
	var data []Data
	var xMax int
	var index int = 1
	var slicer int64
	var flagTimeslize bool = false
	ch := make(chan Data)
	sig := make(chan os.Signal)
	signal.Notify(sig, os.Interrupt)

	dev := flag.String("interface", "", "Choose an interface for online processing")
	file := flag.String("file", "", "Choose a file for offline processing")
	filter := flag.String("filter", "", "Set a specific filter")
	lst := flag.Bool("list_interfaces", false, "List available interfaces")
	vers := flag.Bool("version", false, "Show version")
	help := flag.Bool("help", false, "Show this help")
	terminalOut := flag.Bool("terminal", false, "Visualize on terminal")
	num := flag.Uint("count", 25, "Number of packets to process.\n\tIf argument is 0 the limit is removed")
	output := flag.String("prefix", "image", "Prefix of the resulting image")
	size := flag.Uint("size", 25, "Number of packets per image")
	bits := flag.Uint("bits", 24, "Number of bits per pixel.\n\tIt must be divisible by three and smaller than 25\n\tTo get black/white results, choose 1 as input.")
	ts := flag.Uint("timeslize", 0, "Number of microseconds per resulting image.\n\tSo each pixel of the height of the resulting image represents one microsecond")
	flag.Parse()

	if flag.NFlag() < 1 {
		fmt.Println(os.Args[0], "[-bits ...] [-count ...] [-file ... | -interface ...] [-filter ...] [-list_interfaces] [-help] [-prefix ...] [-size ... | -timeslize ... | -terminal] [-version]")
		flag.PrintDefaults()
		return
	}

	if *lst {
		availableInterfaces()
		return
	}

	if *vers {
		fmt.Println("Version:", Version)
		return
	}

	if *bits%3 != 0 && *bits != 1 {
		fmt.Println(*bits, "must be divisible by three or one")
		return
	} else if *bits > 25 {
		fmt.Println(*bits, "must be smaller than 25")
		return
	}

	if *ts != 0 {
		flagTimeslize = true
	}

	if *help {
		fmt.Println(os.Args[0], "[-bits ...] [-count ...] [-file ... | -interface ...] [-filter ...] [-list_interfaces] [-help] [-prefix ...] [-size ... | -timeslize ... | -terminal] [-version]")
		flag.PrintDefaults()
		return
	}

	switch {
	case flagTimeslize == true && *terminalOut:
		fmt.Println("-timeslize and -terminal can't be combined")

		fmt.Println(os.Args[0], "[-bits ...] [-count ...] [-file ... | -interface ...] [-filter ...] [-list_interfaces] [-help] [-prefix ...] [-size ... | -timeslize ... | -terminal] [-version]")
		flag.PrintDefaults()
		return
	}

        handle, err = initSource(dev, file)
        if err != nil {
                log.Fatal(err)
                os.Exit(1)
        }
	defer handle.Close()

	if len(*filter) != 0 {
		err = handle.SetBPFFilter(*filter)
		if err != nil {
			log.Fatal(err, "\tInvalid filter: ", *filter)
			os.Exit(1)
		}
	}

	packetSource := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
	packetSource.DecodeOptions = gopacket.Lazy

	go handlePackets(packetSource, *num, ch, sig)

	switch {
	case flagTimeslize:
		for i, ok := <-ch; ok; i, ok = <-ch {
			if slicer == 0 {
				slicer = i.toa + int64(*ts)
			}
			if slicer < i.toa {
				xMax++
				createTimeVisualization(data, xMax, *output, *ts, int(*bits))
				xMax = 0
				data = data[:0]
				slicer = i.toa + int64(*ts)
			}
			data = append(data, i)
			if xMax < len(i.payload) {
				xMax = len(i.payload)
			}
		}
	case *terminalOut:
		for i, ok := <-ch; ok; i, ok = <-ch {
			data = append(data, i)
			createTerminalVisualization(data, int(*bits))
			data = data[:0]
		}
	default:
		for i, ok := <-ch; ok; i, ok = <-ch {
			data = append(data, i)
			if xMax < len(i.payload) {
				xMax = len(i.payload)
			}
			if len(data) >= int(*size) {
				xMax++
				createFixedVisualization(data, xMax, *output, index, int(*bits))
				xMax = 0
				index++
				data = data[:0]
			}
		}
	}

	if len(data) > 0 {
		xMax++
		if flagTimeslize {
			createTimeVisualization(data, xMax, *output, *ts, int(*bits))
		} else {
			createFixedVisualization(data, xMax, *output, index, int(*bits))
		}
	}

}
<commit_msg>Add a struct for configs<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"image"
	"image/color"
	"image/png"
	"log"
	"os"
	"os/signal"
	"strconv"
	"time"
)

// Version number of this tool
const Version = "0.0.2"

// Data is a struct for each network packet
type Data struct {
	toa     int64 // Timestamp of arrival in microseconds
	payload []byte  // Copied network packet
}

// configs represents all the configuration data
type configs struct {
        bpP     uint // Bits per Pixel
}

func getBitsFromPacket(packet []byte, byteP, bitP *int, bpP uint) uint8 {
	var c uint8
	for i := 0; i < (int(bpP) / 3); i++ {
		if *byteP >= len(packet) {
			break
		}
		c |= (packet[*byteP] & (1 << uint8(7-*bitP)))
		*bitP += 1
		if *bitP%8 == 0 {
			*bitP = 0
			*byteP += 1
		}
	}
	return c
}

func createPixel(packet []byte, byteP, bitP *int, bpP uint) (c color.Color) {
	var r, g, b uint8

	if bpP == 1 {
		if (packet[*byteP] & (1 << uint8(7-*bitP))) == 0 {
			c = color.NRGBA{R: 0,
				G: 0,
				B: 0,
				A: 255}
		} else {
			c = color.NRGBA{R: 255,
				G: 255,
				B: 255,
				A: 255}
		}
		*bitP += 1
		if *bitP%8 == 0 {
			*bitP = 0
			*byteP += 1
		}
	} else {
		r = getBitsFromPacket(packet, byteP, bitP, bpP)
		g = getBitsFromPacket(packet, byteP, bitP, bpP)
		b = getBitsFromPacket(packet, byteP, bitP, bpP)

		c = color.NRGBA{R: r,
			G: g,
			B: b,
			A: 255}
	}
	return
}

func createTerminalVisualization(data []Data, bitsPerPixel uint) {
	var bitPos int
	var bytePos int
	var packetLen int

	for i := range data {
		packetLen = len(data[i].payload)
		bitPos = 0
		bytePos = 0
		for {
			c := createPixel(data[i].payload, &bytePos, &bitPos, bitsPerPixel)
			r, g, b, _ := c.RGBA()
			fmt.Printf("\x1B[0m\x1B[38;2;%d;%d;%dm\u2588", uint8(r), uint8(g), uint8(b))
			if bytePos >= packetLen {
				break
			}
		}
		fmt.Printf("\x1B[m\n")

	}

}
func createTimeVisualization(data []Data, xMax int, prefix string, ts uint, bitsPerPixel uint) {
	var xPos int
	var bitPos int
	var bytePos int
	var packetLen int
	var firstPkg time.Time

	img := image.NewNRGBA(image.Rect(0, 0, (xMax*8)/int(bitsPerPixel)+1, int(ts)))

	for pkg := range data {
		if firstPkg.IsZero() {
			firstPkg = time.Unix(0, data[pkg].toa*int64(time.Microsecond))
		}
		packetLen = len(data[pkg].payload)
		xPos = 0
		bitPos = 0
		bytePos = 0
		for {
			c := createPixel(data[pkg].payload, &bytePos, &bitPos, bitsPerPixel)
			img.Set(xPos, int(data[pkg].toa%int64(ts)), c)
			xPos++
			if bytePos >= packetLen {
				break
			}
		}
	}

	filename := prefix
	filename += "-"
	filename += firstPkg.Format(time.RFC3339Nano)
	filename += ".png"
	f, err := os.Create(filename)
	if err != nil {
		log.Fatal(err)
	}

	if err := png.Encode(f, img); err != nil {
		f.Close()
		log.Fatal(err)
	}

	if err := f.Close(); err != nil {
		log.Fatal(err)
	}

	return
}

func createFixedVisualization(data []Data, xMax int, prefix string, num int, bitsPerPixel uint) {
	var xPos int
	var bitPos int
	var bytePos int
	var packetLen int

	img := image.NewNRGBA(image.Rect(0, 0, (xMax*8)/int(bitsPerPixel)+1, len(data)))

	for yPos := range data {
		packetLen = len(data[yPos].payload)
		xPos = 0
		bitPos = 0
		bytePos = 0
		for {
			c := createPixel(data[yPos].payload, &bytePos, &bitPos, bitsPerPixel)
			img.Set(xPos, yPos, c)
			xPos++
			if bytePos >= packetLen {
				break
			}
		}

	}

	filename := prefix
	filename += strconv.Itoa(num)
	filename += ".png"
	f, err := os.Create(filename)
	if err != nil {
		log.Fatal(err)
	}

	if err := png.Encode(f, img); err != nil {
		f.Close()
		log.Fatal(err)
	}

	if err := f.Close(); err != nil {
		log.Fatal(err)
	}

	return
}

func handlePackets(ps *gopacket.PacketSource, num uint, ch chan Data, sig <-chan os.Signal) {
	var count uint
	for packet := range ps.Packets() {
		var k Data

		select {
		case isr := <-sig:
			fmt.Println(isr)
			close(ch)
			return
		default:
		}
		count++
		if num != 0 && count > num {
			break
		}

		elements := packet.Data()
		if len(elements) == 0 {
			continue
		}
		k = Data{toa: (packet.Metadata().CaptureInfo.Timestamp.UnixNano() / int64(time.Microsecond)), payload: packet.Data()}
		ch <- k
	}
	close(ch)
	return
}

func availableInterfaces() {
	devices, err := pcap.FindAllDevs()
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}

	for _, device := range devices {
		if len(device.Addresses) == 0 {
			continue
		}
		fmt.Println("Interface: ", device.Name)
		for _, address := range device.Addresses {
			fmt.Println("   IP address:  ", address.IP)
			fmt.Println("   Subnet mask: ", address.Netmask)
		}
		fmt.Println("")
	}
}

func initSource(dev, file *string) (handle *pcap.Handle , err error){
	if len(*dev) > 0 {
		handle, err = pcap.OpenLive(*dev, 4096, true, pcap.BlockForever)
		if err != nil {
			log.Fatal(err)
			os.Exit(1)
		}
	} else if len(*file) > 0 {
		handle, err = pcap.OpenOffline(*file)
		if err != nil {
			log.Fatal(err)
			os.Exit(1)
		}
	} else {
		return nil, fmt.Errorf("Source is missing\n")
	}
        return
}

func checkConfig(config configs) error {
        if config.bpP %3 != 0 && config.bpP != 1 {
		return  fmt.Errorf("%d must be divisible by three or should be one", config.bpP)
	} else if config.bpP > 25 {
		return  fmt.Errorf("%d must be smaller than 25", config.bpP)
	}
       return nil
}

func main() {
	var err error
	var handle *pcap.Handle
	var data []Data
	var xMax int
	var index int = 1
	var slicer int64
	var flagTimeslize bool = false
        var config configs
	ch := make(chan Data)
	sig := make(chan os.Signal)
	signal.Notify(sig, os.Interrupt)

	dev := flag.String("interface", "", "Choose an interface for online processing")
	file := flag.String("file", "", "Choose a file for offline processing")
	filter := flag.String("filter", "", "Set a specific filter")
	lst := flag.Bool("list_interfaces", false, "List available interfaces")
	vers := flag.Bool("version", false, "Show version")
	help := flag.Bool("help", false, "Show this help")
	terminalOut := flag.Bool("terminal", false, "Visualize on terminal")
	num := flag.Uint("count", 25, "Number of packets to process.\n\tIf argument is 0 the limit is removed")
	output := flag.String("prefix", "image", "Prefix of the resulting image")
	size := flag.Uint("size", 25, "Number of packets per image")
	bits := flag.Uint("bits", 24, "Number of bits per pixel.\n\tIt must be divisible by three and smaller than 25\n\tTo get black/white results, choose 1 as input.")
	ts := flag.Uint("timeslize", 0, "Number of microseconds per resulting image.\n\tSo each pixel of the height of the resulting image represents one microsecond")
	flag.Parse()

	if flag.NFlag() < 1 {
		fmt.Println(os.Args[0], "[-bits ...] [-count ...] [-file ... | -interface ...] [-filter ...] [-list_interfaces] [-help] [-prefix ...] [-size ... | -timeslize ... | -terminal] [-version]")
		flag.PrintDefaults()
		return
	}

	if *lst {
		availableInterfaces()
		return
	}

	if *vers {
		fmt.Println("Version:", Version)
		return
	}

        config.bpP = *bits;

        if err = checkConfig(config); err != nil {
                log.Fatal(err)
                os.Exit(1)
        }

	if *ts != 0 {
		flagTimeslize = true
	}

	if *help {
		fmt.Println(os.Args[0], "[-bits ...] [-count ...] [-file ... | -interface ...] [-filter ...] [-list_interfaces] [-help] [-prefix ...] [-size ... | -timeslize ... | -terminal] [-version]")
		flag.PrintDefaults()
		return
	}

	switch {
	case flagTimeslize == true && *terminalOut:
		fmt.Println("-timeslize and -terminal can't be combined")

		fmt.Println(os.Args[0], "[-bits ...] [-count ...] [-file ... | -interface ...] [-filter ...] [-list_interfaces] [-help] [-prefix ...] [-size ... | -timeslize ... | -terminal] [-version]")
		flag.PrintDefaults()
		return
	}

        handle, err = initSource(dev, file)
        if err != nil {
                log.Fatal(err)
                os.Exit(1)
        }
	defer handle.Close()

	if len(*filter) != 0 {
		err = handle.SetBPFFilter(*filter)
		if err != nil {
			log.Fatal(err, "\tInvalid filter: ", *filter)
			os.Exit(1)
		}
	}

	packetSource := gopacket.NewPacketSource(handle, layers.LayerTypeEthernet)
	packetSource.DecodeOptions = gopacket.Lazy

	go handlePackets(packetSource, *num, ch, sig)

	switch {
	case flagTimeslize:
		for i, ok := <-ch; ok; i, ok = <-ch {
			if slicer == 0 {
				slicer = i.toa + int64(*ts)
			}
			if slicer < i.toa {
				xMax++
				createTimeVisualization(data, xMax, *output, *ts, config.bpP)
				xMax = 0
				data = data[:0]
				slicer = i.toa + int64(*ts)
			}
			data = append(data, i)
			if xMax < len(i.payload) {
				xMax = len(i.payload)
			}
		}
	case *terminalOut:
		for i, ok := <-ch; ok; i, ok = <-ch {
			data = append(data, i)
			createTerminalVisualization(data, config.bpP)
			data = data[:0]
		}
	default:
		for i, ok := <-ch; ok; i, ok = <-ch {
			data = append(data, i)
			if xMax < len(i.payload) {
				xMax = len(i.payload)
			}
			if len(data) >= int(*size) {
				xMax++
				createFixedVisualization(data, xMax, *output, index, config.bpP)
				xMax = 0
				index++
				data = data[:0]
			}
		}
	}

	if len(data) > 0 {
		xMax++
		if flagTimeslize {
			createTimeVisualization(data, xMax, *output, *ts, config.bpP)
		} else {
			createFixedVisualization(data, xMax, *output, index, config.bpP)
		}
	}

}
<|endoftext|>


<commit_before>package client

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/types"

	buildv1 "github.com/openshift/api/build/v1"
	buildclient "github.com/openshift/client-go/build/clientset/versioned"
	buildclienttyped "github.com/openshift/client-go/build/clientset/versioned/typed/build/v1"
	buildlister "github.com/openshift/client-go/build/listers/build/v1"
)

// BuildConfigGetter provides methods for getting BuildConfigs
type BuildConfigGetter interface {
	Get(namespace, name string, options metav1.GetOptions) (*buildv1.BuildConfig, error)
}

// BuildConfigUpdater provides methods for updating BuildConfigs
type BuildConfigUpdater interface {
	Update(buildConfig *buildv1.BuildConfig) error
}

// ClientBuildConfigClient delegates get and update operations to the OpenShift client interface
type ClientBuildConfigClient struct {
	Client buildclient.Interface
}

// NewClientBuildConfigClient creates a new build config client that uses an openshift client to create and get BuildConfigs
func NewClientBuildConfigClient(client buildclient.Interface) *ClientBuildConfigClient {
	return &ClientBuildConfigClient{Client: client}
}

// Get returns a BuildConfig using the OpenShift client.
func (c ClientBuildConfigClient) Get(namespace, name string, options metav1.GetOptions) (*buildv1.BuildConfig, error) {
	return c.Client.BuildV1().BuildConfigs(namespace).Get(name, options)
}

// Update updates a BuildConfig using the OpenShift client.
func (c ClientBuildConfigClient) Update(buildConfig *buildv1.BuildConfig) error {
	_, err := c.Client.BuildV1().BuildConfigs(buildConfig.Namespace).Update(buildConfig)
	return err
}

// BuildUpdater provides methods for updating existing Builds.
type BuildUpdater interface {
	Update(namespace string, build *buildv1.Build) error
}

type BuildPatcher interface {
	Patch(namespace, name string, patch []byte) (*buildv1.Build, error)
}

// BuildLister provides methods for listing the Builds.
type BuildLister interface {
	List(namespace string, opts metav1.ListOptions) (*buildv1.BuildList, error)
}

// BuildDeleter knows how to delete buildclient from OpenShift.
type BuildDeleter interface {
	// DeleteBuild removes the build from OpenShift's storage.
	DeleteBuild(build *buildv1.Build) error
}

// ClientBuildClient delegates build create and update operations to the OpenShift client interface
type ClientBuildClient struct {
	Client buildclient.Interface
}

// NewClientBuildClient creates a new build client that uses an openshift client to update buildclient
func NewClientBuildClient(client buildclient.Interface) *ClientBuildClient {
	return &ClientBuildClient{Client: client}
}

// Update updates buildclient using the OpenShift client.
func (c ClientBuildClient) Update(namespace string, build *buildv1.Build) error {
	_, e := c.Client.BuildV1().Builds(namespace).Update(build)
	return e
}

// Patch patches buildclient using the OpenShift client.
func (c ClientBuildClient) Patch(namespace, name string, patch []byte) (*buildv1.Build, error) {
	return c.Client.BuildV1().Builds(namespace).Patch(name, types.StrategicMergePatchType, patch)
}

// List lists the buildclient using the OpenShift client.
func (c ClientBuildClient) List(namespace string, opts metav1.ListOptions) (*buildv1.BuildList, error) {
	return c.Client.BuildV1().Builds(namespace).List(opts)
}

// DeleteBuild deletes a build from OpenShift.
func (c ClientBuildClient) DeleteBuild(build *buildv1.Build) error {
	return c.Client.BuildV1().Builds(build.Namespace).Delete(build.Name, &metav1.DeleteOptions{})
}

// ClientBuildLister implements the build lister interface over a client
type ClientBuildLister struct {
	client buildclienttyped.BuildsGetter
}

// NewClientBuildClient creates a new build client that uses an openshift client to update buildclient
func NewClientBuildLister(client buildclienttyped.BuildsGetter) buildlister.BuildLister {
	return &ClientBuildLister{client: client}
}

// List lists the buildclient using the OpenShift client.
func (c *ClientBuildLister) List(label labels.Selector) ([]*buildv1.Build, error) {
	list, err := c.client.Builds(metav1.NamespaceAll).List(metav1.ListOptions{LabelSelector: label.String()})
	return buildListToPointerArray(list), err
}

func (c *ClientBuildLister) Builds(ns string) buildlister.BuildNamespaceLister {
	return &ClientBuildListerNamespacer{client: c.client, ns: ns}
}

// ClientBuildClientNamespacer implements internalversion lister
type ClientBuildListerNamespacer struct {
	client buildclienttyped.BuildsGetter
	ns     string
}

// List lists the buildclient using the OpenShift client.
func (c ClientBuildListerNamespacer) List(label labels.Selector) ([]*buildv1.Build, error) {
	list, err := c.client.Builds(c.ns).List(metav1.ListOptions{LabelSelector: label.String()})
	return buildListToPointerArray(list), err
}

func (c ClientBuildListerNamespacer) Get(name string) (*buildv1.Build, error) {
	return c.client.Builds(c.ns).Get(name, metav1.GetOptions{})
}

func buildListToPointerArray(list *buildv1.BuildList) []*buildv1.Build {
	if list == nil {
		return nil
	}
	result := make([]*buildv1.Build, len(list.Items))
	for i := range list.Items {
		result[i] = &list.Items[i]
	}
	return result
}

// ClientBuildLister implements the build lister interface over a client
type ClientBuildConfigLister struct {
	client buildclienttyped.BuildConfigsGetter
}

// NewClientBuildConfigLister creates a new build config client that uses an openshift client.
func NewClientBuildConfigLister(client buildclienttyped.BuildConfigsGetter) buildlister.BuildConfigLister {
	return &ClientBuildConfigLister{client: client}
}

// List lists the buildclient using the OpenShift client.
func (c *ClientBuildConfigLister) List(label labels.Selector) ([]*buildv1.BuildConfig, error) {
	list, err := c.client.BuildConfigs(metav1.NamespaceAll).List(metav1.ListOptions{LabelSelector: label.String()})
	return buildConfigListToPointerArray(list), err
}

func (c *ClientBuildConfigLister) BuildConfigs(ns string) buildlister.BuildConfigNamespaceLister {
	return &ClientBuildConfigListerNamespacer{client: c.client, ns: ns}
}

// ClientBuildConfigListerNamespacer implements internalversion lister
type ClientBuildConfigListerNamespacer struct {
	client buildclienttyped.BuildConfigsGetter
	ns     string
}

// List lists the buildclient using the OpenShift client.
func (c ClientBuildConfigListerNamespacer) List(label labels.Selector) ([]*buildv1.BuildConfig, error) {
	list, err := c.client.BuildConfigs(c.ns).List(metav1.ListOptions{LabelSelector: label.String()})
	return buildConfigListToPointerArray(list), err
}

func (c ClientBuildConfigListerNamespacer) Get(name string) (*buildv1.BuildConfig, error) {
	return c.client.BuildConfigs(c.ns).Get(name, metav1.GetOptions{})
}

func buildConfigListToPointerArray(list *buildv1.BuildConfigList) []*buildv1.BuildConfig {
	if list == nil {
		return nil
	}
	result := make([]*buildv1.BuildConfig, len(list.Items))
	for i := range list.Items {
		result[i] = &list.Items[i]
	}
	return result
}

// BuildCloner provides methods for cloning buildclient
type BuildCloner interface {
	Clone(namespace string, request *buildv1.BuildRequest) (*buildv1.Build, error)
}

// OSClientBuildClonerClient creates a new build client that uses an openshift client to clone buildclient
type ClientBuildClonerClient struct {
	Client buildclient.Interface
}

// NewOSClientBuildClonerClient creates a new build client that uses an openshift client to clone buildclient
func NewClientBuildClonerClient(client buildclient.Interface) *ClientBuildClonerClient {
	return &ClientBuildClonerClient{Client: client}
}

// Clone generates new build for given build name
func (c ClientBuildClonerClient) Clone(namespace string, request *buildv1.BuildRequest) (*buildv1.Build, error) {
	return c.Client.BuildV1().Builds(namespace).Clone(request.Name, request)
}

// BuildConfigInstantiator provides methods for instantiating buildclient from build configs
type BuildConfigInstantiator interface {
	Instantiate(namespace string, request *buildv1.BuildRequest) (*buildv1.Build, error)
}

// ClientBuildConfigInstantiatorClient creates a new build client that uses an openshift client to create buildclient
type ClientBuildConfigInstantiatorClient struct {
	Client buildclient.Interface
}

// NewClientBuildConfigInstantiatorClient creates a new build client that uses an openshift client to create buildclient
func NewClientBuildConfigInstantiatorClient(client buildclient.Interface) *ClientBuildConfigInstantiatorClient {
	return &ClientBuildConfigInstantiatorClient{Client: client}
}

// Instantiate generates new build for given buildConfig
func (c ClientBuildConfigInstantiatorClient) Instantiate(namespace string, request *buildv1.BuildRequest) (*buildv1.Build, error) {
	return c.Client.BuildV1().BuildConfigs(namespace).Instantiate(request.Name, request)
}

// TODO: Why we need this, seems like an copy of the client above
type BuildConfigInstantiatorClient struct {
	Client buildclienttyped.BuildV1Interface
}

func (c BuildConfigInstantiatorClient) Instantiate(namespace string, request *buildv1.BuildRequest) (*buildv1.Build, error) {
	return c.Client.BuildConfigs(namespace).Instantiate(request.Name, request)
}
<commit_msg>build/client: remove instantiator and other cruft<commit_after>package client

import (
	buildv1 "github.com/openshift/api/build/v1"
	buildclienttyped "github.com/openshift/client-go/build/clientset/versioned/typed/build/v1"
	buildlister "github.com/openshift/client-go/build/listers/build/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
)

// ClientBuildLister implements the build lister interface over a client
type ClientBuildLister struct {
	client buildclienttyped.BuildsGetter
}

// NewClientBuildClient creates a new build client that uses an openshift client to update buildclient
func NewClientBuildLister(client buildclienttyped.BuildsGetter) buildlister.BuildLister {
	return &ClientBuildLister{client: client}
}

// List lists the buildclient using the OpenShift client.
func (c *ClientBuildLister) List(label labels.Selector) ([]*buildv1.Build, error) {
	list, err := c.client.Builds(metav1.NamespaceAll).List(metav1.ListOptions{LabelSelector: label.String()})
	return buildListToPointerArray(list), err
}

func (c *ClientBuildLister) Builds(ns string) buildlister.BuildNamespaceLister {
	return &ClientBuildListerNamespacer{client: c.client, ns: ns}
}

// ClientBuildClientNamespacer implements internalversion lister
type ClientBuildListerNamespacer struct {
	client buildclienttyped.BuildsGetter
	ns     string
}

// List lists the buildclient using the OpenShift client.
func (c ClientBuildListerNamespacer) List(label labels.Selector) ([]*buildv1.Build, error) {
	list, err := c.client.Builds(c.ns).List(metav1.ListOptions{LabelSelector: label.String()})
	return buildListToPointerArray(list), err
}

func (c ClientBuildListerNamespacer) Get(name string) (*buildv1.Build, error) {
	return c.client.Builds(c.ns).Get(name, metav1.GetOptions{})
}

func buildListToPointerArray(list *buildv1.BuildList) []*buildv1.Build {
	if list == nil {
		return nil
	}
	result := make([]*buildv1.Build, len(list.Items))
	for i := range list.Items {
		result[i] = &list.Items[i]
	}
	return result
}

// ClientBuildLister implements the build lister interface over a client
type ClientBuildConfigLister struct {
	client buildclienttyped.BuildConfigsGetter
}

// NewClientBuildConfigLister creates a new build config client that uses an openshift client.
func NewClientBuildConfigLister(client buildclienttyped.BuildConfigsGetter) buildlister.BuildConfigLister {
	return &ClientBuildConfigLister{client: client}
}

// List lists the buildclient using the OpenShift client.
func (c *ClientBuildConfigLister) List(label labels.Selector) ([]*buildv1.BuildConfig, error) {
	list, err := c.client.BuildConfigs(metav1.NamespaceAll).List(metav1.ListOptions{LabelSelector: label.String()})
	return buildConfigListToPointerArray(list), err
}

func (c *ClientBuildConfigLister) BuildConfigs(ns string) buildlister.BuildConfigNamespaceLister {
	return &ClientBuildConfigListerNamespacer{client: c.client, ns: ns}
}

// ClientBuildConfigListerNamespacer implements internalversion lister
type ClientBuildConfigListerNamespacer struct {
	client buildclienttyped.BuildConfigsGetter
	ns     string
}

// List lists the buildclient using the OpenShift client.
func (c ClientBuildConfigListerNamespacer) List(label labels.Selector) ([]*buildv1.BuildConfig, error) {
	list, err := c.client.BuildConfigs(c.ns).List(metav1.ListOptions{LabelSelector: label.String()})
	return buildConfigListToPointerArray(list), err
}

func (c ClientBuildConfigListerNamespacer) Get(name string) (*buildv1.BuildConfig, error) {
	return c.client.BuildConfigs(c.ns).Get(name, metav1.GetOptions{})
}

func buildConfigListToPointerArray(list *buildv1.BuildConfigList) []*buildv1.BuildConfig {
	if list == nil {
		return nil
	}
	result := make([]*buildv1.BuildConfig, len(list.Items))
	for i := range list.Items {
		result[i] = &list.Items[i]
	}
	return result
}
<|endoftext|>


<commit_before><commit_msg>Fixed conf_test.go<commit_after><|endoftext|>


<commit_before>package gofakes3

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"regexp"
	"strings"
	"time"

	"github.com/boltdb/bolt"
	"github.com/gorilla/mux"
	"gopkg.in/mgo.v2/bson"
)

type GoFakeS3 struct {
	storage *bolt.DB
}
type Content struct {
	Key          string    `xml:"Key"`
	LastModified time.Time `xml:"LastModified"`
	ETag         string    `xml:"ETag"`
	Size         int       `xml:"Size"`
	StorageClass string    `xml:"StorageClass"`
}
type Bucket struct {
	XMLName  xml.Name   `xml:"ListBucketResult"`
	Xmlns    string     `xml:"xmlns,attr"`
	Name     string     `xml:"Name"`
	Prefix   string     `xml:"Prefix"`
	Marker   string     `xml:"Marker"`
	Contents []*Content `xml:"Contents"`
}
type Object struct {
	Metadata map[string]string
	Obj      []byte
}

// Setup a new fake object storage
func New(dbname string) *GoFakeS3 {
	db, err := bolt.Open(dbname, 0600, nil)
	if err != nil {
		log.Fatal(err)
	}

	log.Println("locals3 db created or opened")
	return &GoFakeS3{storage: db}
}

// Create the AWS S3 API
func (g *GoFakeS3) Server() http.Handler {
	r := mux.NewRouter()
	r.Queries("marker", "prefix")
	// BUCKET
	r.HandleFunc("/{BucketName}", g.GetBucket).Methods("GET")
	r.HandleFunc("/{BucketName}", g.CreateBucket).Methods("PUT")
	r.HandleFunc("/{BucketName}", g.DeleteBucket).Methods("DELETE")
	r.HandleFunc("/{BucketName}", g.HeadBucket).Methods("HEAD")
	// OBJECT
	r.HandleFunc("/{BucketName}/{ObjectName:.{1,}}", g.GetObject).Methods("GET")
	r.HandleFunc("/{BucketName}/{ObjectName:.{1,}}", g.CreateObject).Methods("PUT")
	r.HandleFunc("/{BucketName}/{ObjectName:.{0,}}", g.CreateObject).Methods("POST")
	r.HandleFunc("/{BucketName}/{ObjectName:.{1,}}", g.DeleteObject).Methods("DELETE")
	r.HandleFunc("/{BucketName}/{ObjectName:.{1,}}", g.HeadObject).Methods("HEAD")

	return &WithCORS{r}
}

type WithCORS struct {
	r *mux.Router
}

func (s *WithCORS) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, HEAD")
	w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, X-Amz-User-Agent, X-Amz-Date, x-amz-meta-from, x-amz-meta-to, x-amz-meta-filename, x-amz-meta-private")
	if r.Method == "OPTIONS" {
		return
	}
	// Bucket name rewriting
	// this is due to some inconsistencies in the AWS SDKs
	re := regexp.MustCompile("(127.0.0.1:\\d{1,7})|(.localhost:\\d{1,7})")
	bucket := re.ReplaceAllString(r.Host, "")
	if len(bucket) > 0 {
		p := r.URL.Path
		r.URL.Path = "/" + bucket
		if p != "/" {
			r.URL.Path += p
		}
	}
	log.Println("=>", r.URL)

	s.r.ServeHTTP(w, r)
}

// GetBucket lists the contents of a bucket.
func (g *GoFakeS3) GetBucket(w http.ResponseWriter, r *http.Request) {
	log.Println("GET BUCKET")

	bucketName := strings.Replace(r.Host, ".localhost:9000", "", -1)

	log.Println("bucketname:", bucketName)
	log.Println("prefix    :", r.URL.Query().Get("prefix"))

	g.storage.View(func(tx *bolt.Tx) error {
		// Assume bucket exists and has keys
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			http.Error(w, "No bucket", http.StatusInternalServerError)
			return nil
		}
		c := b.Cursor()
		bucketc := &Bucket{
			Xmlns:    "http://s3.amazonaws.com/doc/2006-03-01/",
			Name:     "crowdpatent.com",
			Prefix:   r.URL.Query().Get("prefix"),
			Marker:   "",
			Contents: []*Content{},
		}

		for k, v := c.First(); k != nil; k, v = c.Next() {
			if strings.Contains(string(k), r.URL.Query().Get("prefix")) {
				hash := md5.Sum(v)
				bucketc.Contents = append(bucketc.Contents, &Content{
					Key:          string(k),
					LastModified: time.Now(),
					ETag:         "\"" + hex.EncodeToString(hash[:]) + "\"",
					Size:         len(v),
					StorageClass: "STANDARD",
				})
				t := Object{}
				err := bson.Unmarshal(v, &t)
				if err != nil {
					panic(err)
				}
			}
		}

		x, err := xml.MarshalIndent(bucketc, "", "  ")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return nil
		}
		w.Write(x)
		return nil
	})
}

// CreateBucket creates a new S3 bucket in the BoltDB storage.
func (g *GoFakeS3) CreateBucket(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	var bucketName string
	log.Println("CREATE BUCKET:", bucketName)
	if len(vars["BucketName"]) > 0 {
		bucketName = vars["BucketName"]
	} else {
		bucketName = strings.Replace(r.Host, ".localhost:9000", "", -1)
	}

	g.storage.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucket([]byte(bucketName))
		if err != nil {
			http.Error(w, "bucket existed", http.StatusBadRequest)
			return err
		}
		log.Println("bucket created")
		w.Header().Set("Host", r.Header.Get("Host"))
		w.Header().Set("Location", "/"+bucketName)
		w.Write([]byte{})
		return nil
	})
}

// DeleteBucket creates a new S3 bucket in the BoltDB storage.
func (g *GoFakeS3) DeleteBucket(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "delete bucket")
}

// HeadBucket checks whether a bucket exists.
func (g *GoFakeS3) HeadBucket(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	bucketName := vars["BucketName"]
	log.Println("HEAD BUCKET", bucketName)
	log.Println("bucketname:", bucketName)
	g.storage.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			log.Println("no bucket")
			http.Error(w, "bucket does not exist", http.StatusInternalServerError)
		}
		w.Header().Set("x-amz-id-2", "LriYPLdmOdAiIfgSm/F1YsViT1LW94/xUQxMsF7xiEb1a0wiIOIxl+zbwZ163pt7")
		w.Header().Set("x-amz-request-id", "0A49CE4060975EAC")
		w.Header().Set("Server", "AmazonS3")
		w.Write([]byte{})
		return nil
	})
}

// GetObject retrievs a bucket object.
func (g *GoFakeS3) GetObject(w http.ResponseWriter, r *http.Request) {
	log.Println("GET OBJECT")
	vars := mux.Vars(r)
	bucketName := vars["BucketName"]
	log.Println("Bucket:", bucketName)
	log.Println("└── Object:", vars["ObjectName"])

	g.storage.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			log.Println("no bucket")
			http.Error(w, "bucket does not exist", http.StatusInternalServerError)
		}
		v := b.Get([]byte(vars["ObjectName"]))

		if v == nil {
			log.Println("no object")
			http.Error(w, "object does not exist", http.StatusInternalServerError)
			return nil
		}
		t := Object{}
		err := bson.Unmarshal(v, &t)
		if err != nil {
			panic(err)
		}
		hash := md5.Sum(t.Obj)
		w.Header().Set("x-amz-id-2", "LriYPLdmOdAiIfgSm/F1YsViT1LW94/xUQxMsF7xiEb1a0wiIOIxl+zbwZ163pt7")
		w.Header().Set("x-amz-request-id", "0A49CE4060975EAC")
		for mk, mv := range t.Metadata {
			w.Header().Set(mk, mv)
		}
		w.Header().Set("Last-Modified", time.Now().Format("Mon, 2 Jan 2006 15:04:05 MST"))
		w.Header().Set("ETag", "\""+hex.EncodeToString(hash[:])+"\"")
		w.Header().Set("Server", "AmazonS3")
		w.Header().Set("Content-Length", fmt.Sprintf("%v", len(t.Obj)))
		w.Header().Set("Connection", "close")
		w.Write(t.Obj)
		return nil
	})
}

// CreateObject creates a new S3 object.
func (g *GoFakeS3) CreateObject(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	var bucketName string
	if len(vars["BucketName"]) > 0 {
		bucketName = vars["BucketName"]
	} else {
		bucketName = strings.Replace(r.Host, ".localhost:9000", "", -1)
	}
	log.Println("CREATE OBJECT:", bucketName, vars["ObjectName"])
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}

	meta := make(map[string]string)
	for hk, hv := range r.Header {
		if strings.Contains(hk, "X-Amz-") {
			meta[hk] = hv[0]
		}
	}
	meta["Last-Modified"] = time.Now().Format("Mon, 2 Jan 2006 15:04:05 MST")

	obj := &Object{meta, body}

	g.storage.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			log.Println("no bucket")
			http.Error(w, "bucket does not exist", http.StatusInternalServerError)
			return nil
		}
		log.Println("bucket", bucketName, "found")
		data, err := bson.Marshal(obj)
		if err != nil {
			panic(err)
		}
		err = b.Put([]byte(vars["ObjectName"]), data)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return fmt.Errorf("error while creating")
		}
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("x-amz-id-2", "LriYPLdmOdAiIfgSm/F1YsViT1LW94/xUQxMsF7xiEb1a0wiIOIxl+zbwZ163pt7")
		w.Header().Set("x-amz-request-id", "0A49CE4060975EAC")
		w.Header().Set("ETag", "\"fbacf535f27731c9771645a39863328\"")
		w.Header().Set("Server", "AmazonS3")
		w.Write([]byte{})
		return nil
	})
}

// DeleteObject deletes a S3 object from the bucket.
func (g *GoFakeS3) DeleteObject(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "delete object")
}

// HeadObject retrieves only meta information of an object and not the whole.
func (g *GoFakeS3) HeadObject(w http.ResponseWriter, r *http.Request) {
	log.Println("HEAD OBJECT")
	vars := mux.Vars(r)
	bucketName := strings.Replace(r.Host, ".localhost:9000", "", -1)
	log.Println("Bucket:", bucketName)
	log.Println("└── Object:", vars["ObjectName"])

	g.storage.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			log.Println("no bucket")
			http.Error(w, "bucket does not exist", http.StatusInternalServerError)
		}
		v := b.Get([]byte(vars["ObjectName"]))

		if v == nil {
			log.Println("no object")
			http.Error(w, "object does not exist", http.StatusInternalServerError)
		}
		t := Object{}
		err := bson.Unmarshal(v, &t)
		if err != nil {
			panic(err)
		}
		hash := md5.Sum(t.Obj)
		w.Header().Set("x-amz-id-2", "LriYPLdmOdAiIfgSm/F1YsViT1LW94/xUQxMsF7xiEb1a0wiIOIxl+zbwZ163pt7")
		w.Header().Set("x-amz-request-id", "0A49CE4060975EAC")
		for mk, mv := range t.Metadata {
			w.Header().Set(mk, mv)
		}
		w.Header().Set("Last-Modified", t.Metadata["Last-Modified"])
		w.Header().Set("ETag", "\""+hex.EncodeToString(hash[:])+"\"")
		w.Header().Set("Server", "AmazonS3")
		w.Write([]byte{})
		return nil
	})

}
<commit_msg>Change bucket and object retrieval<commit_after>package gofakes3

import (
	"crypto/md5"
	"encoding/hex"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"regexp"
	"strings"
	"time"

	"github.com/boltdb/bolt"
	"github.com/gorilla/mux"
	"gopkg.in/mgo.v2/bson"
)

type GoFakeS3 struct {
	storage *bolt.DB
}
type Content struct {
	Key          string    `xml:"Key"`
	LastModified time.Time `xml:"LastModified"`
	ETag         string    `xml:"ETag"`
	Size         int       `xml:"Size"`
	StorageClass string    `xml:"StorageClass"`
}
type Bucket struct {
	XMLName  xml.Name   `xml:"ListBucketResult"`
	Xmlns    string     `xml:"xmlns,attr"`
	Name     string     `xml:"Name"`
	Prefix   string     `xml:"Prefix"`
	Marker   string     `xml:"Marker"`
	Contents []*Content `xml:"Contents"`
}
type Object struct {
	Metadata map[string]string
	Obj      []byte
}

// Setup a new fake object storage
func New(dbname string) *GoFakeS3 {
	db, err := bolt.Open(dbname, 0600, nil)
	if err != nil {
		log.Fatal(err)
	}

	log.Println("locals3 db created or opened")
	return &GoFakeS3{storage: db}
}

// Create the AWS S3 API
func (g *GoFakeS3) Server() http.Handler {
	r := mux.NewRouter()
	r.Queries("marker", "prefix")
	// BUCKET
	r.HandleFunc("/{BucketName}", g.GetBucket).Methods("GET")
	r.HandleFunc("/{BucketName}", g.CreateBucket).Methods("PUT")
	r.HandleFunc("/{BucketName}", g.DeleteBucket).Methods("DELETE")
	r.HandleFunc("/{BucketName}", g.HeadBucket).Methods("HEAD")
	// OBJECT
	r.HandleFunc("/{BucketName}/{ObjectName:.{1,}}", g.GetObject).Methods("GET")
	r.HandleFunc("/{BucketName}/{ObjectName:.{1,}}", g.CreateObject).Methods("PUT")
	r.HandleFunc("/{BucketName}/{ObjectName:.{0,}}", g.CreateObject).Methods("POST")
	r.HandleFunc("/{BucketName}/{ObjectName:.{1,}}", g.DeleteObject).Methods("DELETE")
	r.HandleFunc("/{BucketName}/{ObjectName:.{1,}}", g.HeadObject).Methods("HEAD")

	return &WithCORS{r}
}

type WithCORS struct {
	r *mux.Router
}

func (s *WithCORS) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, HEAD")
	w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, X-Amz-User-Agent, X-Amz-Date, x-amz-meta-from, x-amz-meta-to, x-amz-meta-filename, x-amz-meta-private")
	if r.Method == "OPTIONS" {
		return
	}
	// Bucket name rewriting
	// this is due to some inconsistencies in the AWS SDKs
	re := regexp.MustCompile("(127.0.0.1:\\d{1,7})|(.localhost:\\d{1,7})|(localhost:\\d{1,7})")
	bucket := re.ReplaceAllString(r.Host, "")
	if len(bucket) > 0 {
		log.Println("rewrite bucket ->", bucket)
		p := r.URL.Path
		r.URL.Path = "/" + bucket
		if p != "/" {
			r.URL.Path += p
		}
	}
	log.Println("=>", r.URL)

	s.r.ServeHTTP(w, r)
}

// GetBucket lists the contents of a bucket.
func (g *GoFakeS3) GetBucket(w http.ResponseWriter, r *http.Request) {
	log.Println("GET BUCKET")
	vars := mux.Vars(r)
	bucketName := vars["BucketName"]

	log.Println("bucketname:", bucketName)
	log.Println("prefix    :", r.URL.Query().Get("prefix"))

	g.storage.View(func(tx *bolt.Tx) error {
		// Assume bucket exists and has keys
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			http.Error(w, "No bucket", http.StatusInternalServerError)
			return nil
		}
		c := b.Cursor()
		bucketc := &Bucket{
			Xmlns:    "http://s3.amazonaws.com/doc/2006-03-01/",
			Name:     "crowdpatent.com",
			Prefix:   r.URL.Query().Get("prefix"),
			Marker:   "",
			Contents: []*Content{},
		}

		for k, v := c.First(); k != nil; k, v = c.Next() {
			if strings.Contains(string(k), r.URL.Query().Get("prefix")) {
				hash := md5.Sum(v)
				bucketc.Contents = append(bucketc.Contents, &Content{
					Key:          string(k),
					LastModified: time.Now(),
					ETag:         "\"" + hex.EncodeToString(hash[:]) + "\"",
					Size:         len(v),
					StorageClass: "STANDARD",
				})
				t := Object{}
				err := bson.Unmarshal(v, &t)
				if err != nil {
					panic(err)
				}
			}
		}

		x, err := xml.MarshalIndent(bucketc, "", "  ")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return nil
		}
		w.Write(x)
		return nil
	})
}

// CreateBucket creates a new S3 bucket in the BoltDB storage.
func (g *GoFakeS3) CreateBucket(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	bucketName := vars["BucketName"]
	log.Println("CREATE BUCKET:", bucketName)

	g.storage.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucket([]byte(bucketName))
		if err != nil {
			http.Error(w, "bucket existed", http.StatusBadRequest)
			return err
		}
		log.Println("bucket created")
		w.Header().Set("Host", r.Header.Get("Host"))
		w.Header().Set("Location", "/"+bucketName)
		w.Write([]byte{})
		return nil
	})
}

// DeleteBucket creates a new S3 bucket in the BoltDB storage.
func (g *GoFakeS3) DeleteBucket(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "delete bucket")
}

// HeadBucket checks whether a bucket exists.
func (g *GoFakeS3) HeadBucket(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	bucketName := vars["BucketName"]
	log.Println("HEAD BUCKET", bucketName)
	log.Println("bucketname:", bucketName)
	g.storage.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			log.Println("no bucket")
			http.Error(w, "bucket does not exist", http.StatusInternalServerError)
		}
		w.Header().Set("x-amz-id-2", "LriYPLdmOdAiIfgSm/F1YsViT1LW94/xUQxMsF7xiEb1a0wiIOIxl+zbwZ163pt7")
		w.Header().Set("x-amz-request-id", "0A49CE4060975EAC")
		w.Header().Set("Server", "AmazonS3")
		w.Write([]byte{})
		return nil
	})
}

// GetObject retrievs a bucket object.
func (g *GoFakeS3) GetObject(w http.ResponseWriter, r *http.Request) {
	log.Println("GET OBJECT")
	vars := mux.Vars(r)
	bucketName := vars["BucketName"]
	log.Println("Bucket:", bucketName)
	log.Println("└── Object:", vars["ObjectName"])

	g.storage.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			log.Println("no bucket")
			http.Error(w, "bucket does not exist", http.StatusInternalServerError)
		}
		v := b.Get([]byte(vars["ObjectName"]))

		if v == nil {
			log.Println("no object")
			http.Error(w, "object does not exist", http.StatusInternalServerError)
			return nil
		}
		t := Object{}
		err := bson.Unmarshal(v, &t)
		if err != nil {
			panic(err)
		}
		hash := md5.Sum(t.Obj)
		w.Header().Set("x-amz-id-2", "LriYPLdmOdAiIfgSm/F1YsViT1LW94/xUQxMsF7xiEb1a0wiIOIxl+zbwZ163pt7")
		w.Header().Set("x-amz-request-id", "0A49CE4060975EAC")
		for mk, mv := range t.Metadata {
			w.Header().Set(mk, mv)
		}
		w.Header().Set("Last-Modified", time.Now().Format("Mon, 2 Jan 2006 15:04:05 MST"))
		w.Header().Set("ETag", "\""+hex.EncodeToString(hash[:])+"\"")
		w.Header().Set("Server", "AmazonS3")
		w.Header().Set("Content-Length", fmt.Sprintf("%v", len(t.Obj)))
		w.Header().Set("Connection", "close")
		w.Write(t.Obj)
		return nil
	})
}

// CreateObject creates a new S3 object.
func (g *GoFakeS3) CreateObject(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	bucketName := vars["BucketName"]

	log.Println("CREATE OBJECT:", bucketName, vars["ObjectName"])
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		panic(err)
	}

	meta := make(map[string]string)
	for hk, hv := range r.Header {
		if strings.Contains(hk, "X-Amz-") {
			meta[hk] = hv[0]
		}
	}
	meta["Last-Modified"] = time.Now().Format("Mon, 2 Jan 2006 15:04:05 MST")

	obj := &Object{meta, body}

	g.storage.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			log.Println("no bucket")
			http.Error(w, "bucket does not exist", http.StatusInternalServerError)
			return nil
		}
		log.Println("bucket", bucketName, "found")
		data, err := bson.Marshal(obj)
		if err != nil {
			panic(err)
		}
		err = b.Put([]byte(vars["ObjectName"]), data)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return fmt.Errorf("error while creating")
		}
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("x-amz-id-2", "LriYPLdmOdAiIfgSm/F1YsViT1LW94/xUQxMsF7xiEb1a0wiIOIxl+zbwZ163pt7")
		w.Header().Set("x-amz-request-id", "0A49CE4060975EAC")
		w.Header().Set("ETag", "\"fbacf535f27731c9771645a39863328\"")
		w.Header().Set("Server", "AmazonS3")
		w.Write([]byte{})
		return nil
	})
}

// DeleteObject deletes a S3 object from the bucket.
func (g *GoFakeS3) DeleteObject(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "delete object")
}

// HeadObject retrieves only meta information of an object and not the whole.
func (g *GoFakeS3) HeadObject(w http.ResponseWriter, r *http.Request) {
	log.Println("HEAD OBJECT")
	vars := mux.Vars(r)
	bucketName := strings.Replace(r.Host, ".localhost:9000", "", -1)
	log.Println("Bucket:", bucketName)
	log.Println("└── Object:", vars["ObjectName"])

	g.storage.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(bucketName))
		if b == nil {
			log.Println("no bucket")
			http.Error(w, "bucket does not exist", http.StatusInternalServerError)
		}
		v := b.Get([]byte(vars["ObjectName"]))

		if v == nil {
			log.Println("no object")
			http.Error(w, "object does not exist", http.StatusInternalServerError)
		}
		t := Object{}
		err := bson.Unmarshal(v, &t)
		if err != nil {
			panic(err)
		}
		hash := md5.Sum(t.Obj)
		w.Header().Set("x-amz-id-2", "LriYPLdmOdAiIfgSm/F1YsViT1LW94/xUQxMsF7xiEb1a0wiIOIxl+zbwZ163pt7")
		w.Header().Set("x-amz-request-id", "0A49CE4060975EAC")
		for mk, mv := range t.Metadata {
			w.Header().Set(mk, mv)
		}
		w.Header().Set("Last-Modified", t.Metadata["Last-Modified"])
		w.Header().Set("ETag", "\""+hex.EncodeToString(hash[:])+"\"")
		w.Header().Set("Server", "AmazonS3")
		w.Write([]byte{})
		return nil
	})
}
<|endoftext|>


<commit_before>package depot

import (
	"io"
	"sync"

	"github.com/cloudfoundry-incubator/executor"
	"github.com/cloudfoundry-incubator/executor/depot/event"
	"github.com/cloudfoundry-incubator/executor/depot/store"
	"github.com/pivotal-golang/lager"
)

const ContainerInitializationFailedMessage = "failed to initialize container"

type AllocationsTracker interface {
	Allocations() []executor.Container
}

type client struct {
	*clientProvider
	logger lager.Logger
}

type clientProvider struct {
	totalCapacity   executor.ExecutorResources
	gardenStore     GardenStore
	allocationStore AllocationStore
	tracker         AllocationsTracker
	eventHub        event.Hub

	resourcesL sync.Mutex
}

type Store interface {
	Create(executor.Container) (executor.Container, error)
	Lookup(guid string) (executor.Container, error)
	List(executor.Tags) ([]executor.Container, error)
	Destroy(guid string) error
}

type AllocationStore interface {
	Store

	StartInitializing(guid string) error
	Complete(guid string, result executor.ContainerRunResult) error
}

type GardenStore interface {
	Store

	Ping() error
	Run(executor.Container, lager.Logger)
	Stop(guid string) error
	GetFiles(guid, sourcePath string) (io.ReadCloser, error)
}

func NewClientProvider(
	totalCapacity executor.ExecutorResources,
	gardenStore GardenStore,
	allocationStore AllocationStore,
	tracker AllocationsTracker,
	eventHub event.Hub,
) executor.ClientProvider {
	return &clientProvider{
		totalCapacity:   totalCapacity,
		gardenStore:     gardenStore,
		allocationStore: allocationStore,
		tracker:         tracker,
		eventHub:        eventHub,
	}
}

func (provider *clientProvider) WithLogger(logger lager.Logger) executor.Client {
	return &client{
		provider,
		logger.Session("depot-client"),
	}
}

func (c *client) AllocateContainer(executorContainer executor.Container) (executor.Container, error) {
	if executorContainer.CPUWeight > 100 || executorContainer.CPUWeight < 0 {
		return executor.Container{}, executor.ErrLimitsInvalid
	} else if executorContainer.CPUWeight == 0 {
		executorContainer.CPUWeight = 100
	}

	if executorContainer.Guid == "" {
		return executor.Container{}, executor.ErrGuidNotSpecified
	}

	logger := c.logger.Session("allocate", lager.Data{
		"guid": executorContainer.Guid,
	})

	c.resourcesL.Lock()
	defer c.resourcesL.Unlock()

	if !c.hasSpace(executorContainer) {
		logger.Info("full")
		return executor.Container{}, executor.ErrInsufficientResourcesAvailable
	}

	createdContainer, err := c.allocationStore.Create(executorContainer)
	if err != nil {
		logger.Error("container-allocation-failed", err)
		return executor.Container{}, err
	}

	return createdContainer, nil
}

func (c *client) GetContainer(guid string) (executor.Container, error) {
	logger := c.logger.Session("get", lager.Data{
		"guid": guid,
	})

	container, err := c.allocationStore.Lookup(guid)
	if err != nil {
		container, err = c.gardenStore.Lookup(guid)
		if err != nil {
			logger.Error("container-not-found", err)
			return executor.Container{}, executor.ErrContainerNotFound
		}
	}

	return container, nil
}

func (c *client) RunContainer(guid string) error {
	logger := c.logger.Session("run", lager.Data{
		"guid": guid,
	})

	container, err := c.allocationStore.Lookup(guid)
	if err != nil {
		logger.Error("failed-to-find-container", err)
		return executor.ErrContainerNotFound
	}

	err = c.allocationStore.StartInitializing(container.Guid)
	if err != nil {
		logger.Error("failed-to-initialize-container", err)
		return executor.ErrContainerNotFound
	}

	go func() {
		container, err := c.gardenStore.Create(container)
		if err != nil {
			logger.Error("failed-to-create-container", err)

			c.allocationStore.Complete(guid, executor.ContainerRunResult{
				Failed:        true,
				FailureReason: ContainerInitializationFailedMessage,
			})

			return
		}

		err = c.allocationStore.Destroy(guid)
		if err == store.ErrContainerNotFound {
			logger.Debug("container-deleted-while-initilizing")

			err := c.gardenStore.Destroy(container.Guid)
			if err != nil {
				logger.Error("failed-to-destroy-newly-initialized-container", err)
			}

			logger.Info("destroyed-newly-initialized-container")

			return
		} else if err != nil {
			logger.Error("failed-to-remove-allocated-container-for-some-reason", err)
			return
		}

		c.gardenStore.Run(container, logger)
	}()

	return nil
}

func (c *client) ListContainers(tags executor.Tags) ([]executor.Container, error) {
	containersByHandle := make(map[string]executor.Container)

	gardenContainers, err := c.gardenStore.List(tags)
	if err != nil {
		return nil, err
	}

	allocatedContainers, err := c.allocationStore.List(tags)
	if err != nil {
		return nil, err
	}

	//the ordering here is important.  we want allocated containers to override
	//garden containers as a member of latter is uninitialized until its
	//counterpart in the former is gone and we don't want to publicize containers that
	//are in a half-baked state
	for _, gardenContainer := range gardenContainers {
		containersByHandle[gardenContainer.Guid] = gardenContainer
	}
	for _, gardenContainer := range allocatedContainers {
		containersByHandle[gardenContainer.Guid] = gardenContainer
	}

	containers := make([]executor.Container, 0, len(containersByHandle))
	for _, container := range containersByHandle {
		containers = append(containers, container)
	}

	return containers, nil
}

func (c *client) StopContainer(guid string) error {
	logger := c.logger.Session("stop", lager.Data{
		"guid": guid,
	})

	logger.Info("stopping-container")
	return c.gardenStore.Stop(guid)
}

func (c *client) DeleteContainer(guid string) error {
	logger := c.logger.Session("delete", lager.Data{
		"guid": guid,
	})

	if err := c.allocationStore.Destroy(guid); err == nil {
		logger.Info("deleted-allocation")
		return nil
	}

	container, err := c.gardenStore.Lookup(guid)
	if err != nil {
		logger.Error("container-not-found", err)
		return err
	}

	if container.State != executor.StateCompleted {
		logger.Error("container-not-completed", err)
		return executor.ErrContainerNotCompleted
	}

	err = c.gardenStore.Destroy(guid)
	if err != nil {
		logger.Error("failed-to-destroy", err)
		return executor.ErrContainerNotFound
	}

	return nil
}

func (c *client) RemainingResources() (executor.ExecutorResources, error) {
	remainingResources, err := c.TotalResources()
	if err != nil {
		return executor.ExecutorResources{}, err
	}

	for _, allocation := range c.tracker.Allocations() {
		remainingResources.Containers--
		remainingResources.DiskMB -= allocation.DiskMB
		remainingResources.MemoryMB -= allocation.MemoryMB
	}

	return remainingResources, nil
}

func (c *client) Ping() error {
	return c.gardenStore.Ping()
}

func (c *client) TotalResources() (executor.ExecutorResources, error) {
	totalCapacity := c.totalCapacity

	return executor.ExecutorResources{
		MemoryMB:   totalCapacity.MemoryMB,
		DiskMB:     totalCapacity.DiskMB,
		Containers: totalCapacity.Containers,
	}, nil
}

func (c *client) GetFiles(guid, sourcePath string) (io.ReadCloser, error) {
	return c.gardenStore.GetFiles(guid, sourcePath)
}

func (c *client) SubscribeToEvents() (<-chan executor.Event, error) {
	return c.eventHub.Subscribe(), nil
}

func (c *client) hasSpace(container executor.Container) bool {
	remainingResources, err := c.RemainingResources()
	if err != nil {
		panic("welp")
	}

	if remainingResources.MemoryMB < container.MemoryMB {
		return false
	}

	if remainingResources.DiskMB < container.DiskMB {
		return false
	}

	if remainingResources.Containers < 1 {
		return false
	}

	return true
}
<commit_msg>fix subtle race in ListContainers<commit_after>package depot

import (
	"io"
	"sync"

	"github.com/cloudfoundry-incubator/executor"
	"github.com/cloudfoundry-incubator/executor/depot/event"
	"github.com/cloudfoundry-incubator/executor/depot/store"
	"github.com/pivotal-golang/lager"
)

const ContainerInitializationFailedMessage = "failed to initialize container"

type AllocationsTracker interface {
	Allocations() []executor.Container
}

type client struct {
	*clientProvider
	logger lager.Logger
}

type clientProvider struct {
	totalCapacity   executor.ExecutorResources
	gardenStore     GardenStore
	allocationStore AllocationStore
	tracker         AllocationsTracker
	eventHub        event.Hub

	resourcesL sync.Mutex
}

type Store interface {
	Create(executor.Container) (executor.Container, error)
	Lookup(guid string) (executor.Container, error)
	List(executor.Tags) ([]executor.Container, error)
	Destroy(guid string) error
}

type AllocationStore interface {
	Store

	StartInitializing(guid string) error
	Complete(guid string, result executor.ContainerRunResult) error
}

type GardenStore interface {
	Store

	Ping() error
	Run(executor.Container, lager.Logger)
	Stop(guid string) error
	GetFiles(guid, sourcePath string) (io.ReadCloser, error)
}

func NewClientProvider(
	totalCapacity executor.ExecutorResources,
	gardenStore GardenStore,
	allocationStore AllocationStore,
	tracker AllocationsTracker,
	eventHub event.Hub,
) executor.ClientProvider {
	return &clientProvider{
		totalCapacity:   totalCapacity,
		gardenStore:     gardenStore,
		allocationStore: allocationStore,
		tracker:         tracker,
		eventHub:        eventHub,
	}
}

func (provider *clientProvider) WithLogger(logger lager.Logger) executor.Client {
	return &client{
		provider,
		logger.Session("depot-client"),
	}
}

func (c *client) AllocateContainer(executorContainer executor.Container) (executor.Container, error) {
	if executorContainer.CPUWeight > 100 || executorContainer.CPUWeight < 0 {
		return executor.Container{}, executor.ErrLimitsInvalid
	} else if executorContainer.CPUWeight == 0 {
		executorContainer.CPUWeight = 100
	}

	if executorContainer.Guid == "" {
		return executor.Container{}, executor.ErrGuidNotSpecified
	}

	logger := c.logger.Session("allocate", lager.Data{
		"guid": executorContainer.Guid,
	})

	c.resourcesL.Lock()
	defer c.resourcesL.Unlock()

	if !c.hasSpace(executorContainer) {
		logger.Info("full")
		return executor.Container{}, executor.ErrInsufficientResourcesAvailable
	}

	createdContainer, err := c.allocationStore.Create(executorContainer)
	if err != nil {
		logger.Error("container-allocation-failed", err)
		return executor.Container{}, err
	}

	return createdContainer, nil
}

func (c *client) GetContainer(guid string) (executor.Container, error) {
	logger := c.logger.Session("get", lager.Data{
		"guid": guid,
	})

	container, err := c.allocationStore.Lookup(guid)
	if err != nil {
		container, err = c.gardenStore.Lookup(guid)
		if err != nil {
			logger.Error("container-not-found", err)
			return executor.Container{}, executor.ErrContainerNotFound
		}
	}

	return container, nil
}

func (c *client) RunContainer(guid string) error {
	logger := c.logger.Session("run", lager.Data{
		"guid": guid,
	})

	container, err := c.allocationStore.Lookup(guid)
	if err != nil {
		logger.Error("failed-to-find-container", err)
		return executor.ErrContainerNotFound
	}

	err = c.allocationStore.StartInitializing(container.Guid)
	if err != nil {
		logger.Error("failed-to-initialize-container", err)
		return executor.ErrContainerNotFound
	}

	go func() {
		container, err := c.gardenStore.Create(container)
		if err != nil {
			logger.Error("failed-to-create-container", err)

			c.allocationStore.Complete(guid, executor.ContainerRunResult{
				Failed:        true,
				FailureReason: ContainerInitializationFailedMessage,
			})

			return
		}

		err = c.allocationStore.Destroy(guid)
		if err == store.ErrContainerNotFound {
			logger.Debug("container-deleted-while-initilizing")

			err := c.gardenStore.Destroy(container.Guid)
			if err != nil {
				logger.Error("failed-to-destroy-newly-initialized-container", err)
			}

			logger.Info("destroyed-newly-initialized-container")

			return
		} else if err != nil {
			logger.Error("failed-to-remove-allocated-container-for-some-reason", err)
			return
		}

		c.gardenStore.Run(container, logger)
	}()

	return nil
}

func (c *client) ListContainers(tags executor.Tags) ([]executor.Container, error) {
	containersByHandle := make(map[string]executor.Container)

	// order here is important; listing containers from garden takes time, and in
	// that time a container may transition from allocation store to garden
	// store.
	//
	// in this case, if the garden store were fetched first, the container would
	// not be listed anywhere. this ordering guarantees that it will at least
	// show up allocated.

	allocatedContainers, err := c.allocationStore.List(tags)
	if err != nil {
		return nil, err
	}

	gardenContainers, err := c.gardenStore.List(tags)
	if err != nil {
		return nil, err
	}

	//the ordering here is important.  we want allocated containers to override
	//garden containers as a member of latter is uninitialized until its
	//counterpart in the former is gone and we don't want to publicize containers that
	//are in a half-baked state
	for _, gardenContainer := range gardenContainers {
		containersByHandle[gardenContainer.Guid] = gardenContainer
	}

	for _, gardenContainer := range allocatedContainers {
		containersByHandle[gardenContainer.Guid] = gardenContainer
	}

	containers := make([]executor.Container, 0, len(containersByHandle))
	for _, container := range containersByHandle {
		containers = append(containers, container)
	}

	return containers, nil
}

func (c *client) StopContainer(guid string) error {
	logger := c.logger.Session("stop", lager.Data{
		"guid": guid,
	})

	logger.Info("stopping-container")
	return c.gardenStore.Stop(guid)
}

func (c *client) DeleteContainer(guid string) error {
	logger := c.logger.Session("delete", lager.Data{
		"guid": guid,
	})

	if err := c.allocationStore.Destroy(guid); err == nil {
		logger.Info("deleted-allocation")
		return nil
	}

	container, err := c.gardenStore.Lookup(guid)
	if err != nil {
		logger.Error("container-not-found", err)
		return err
	}

	if container.State != executor.StateCompleted {
		logger.Error("container-not-completed", err)
		return executor.ErrContainerNotCompleted
	}

	err = c.gardenStore.Destroy(guid)
	if err != nil {
		logger.Error("failed-to-destroy", err)
		return executor.ErrContainerNotFound
	}

	return nil
}

func (c *client) RemainingResources() (executor.ExecutorResources, error) {
	remainingResources, err := c.TotalResources()
	if err != nil {
		return executor.ExecutorResources{}, err
	}

	for _, allocation := range c.tracker.Allocations() {
		remainingResources.Containers--
		remainingResources.DiskMB -= allocation.DiskMB
		remainingResources.MemoryMB -= allocation.MemoryMB
	}

	return remainingResources, nil
}

func (c *client) Ping() error {
	return c.gardenStore.Ping()
}

func (c *client) TotalResources() (executor.ExecutorResources, error) {
	totalCapacity := c.totalCapacity

	return executor.ExecutorResources{
		MemoryMB:   totalCapacity.MemoryMB,
		DiskMB:     totalCapacity.DiskMB,
		Containers: totalCapacity.Containers,
	}, nil
}

func (c *client) GetFiles(guid, sourcePath string) (io.ReadCloser, error) {
	return c.gardenStore.GetFiles(guid, sourcePath)
}

func (c *client) SubscribeToEvents() (<-chan executor.Event, error) {
	return c.eventHub.Subscribe(), nil
}

func (c *client) hasSpace(container executor.Container) bool {
	remainingResources, err := c.RemainingResources()
	if err != nil {
		panic("welp")
	}

	if remainingResources.MemoryMB < container.MemoryMB {
		return false
	}

	if remainingResources.DiskMB < container.DiskMB {
		return false
	}

	if remainingResources.Containers < 1 {
		return false
	}

	return true
}
<|endoftext|>