<commit_before>package ember

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

var e = New()

type routeTest struct {
	method   string
	path     string
	expected string
}

func init() {
	// Register a route for index.html file.
	e.Index("example/dist/index.html")

	// Register a route for assets.
	e.Assets("/assets", "example/dist/assets")

	// Create a model and register a route for /stats
	e.Model("stats").FindAll(responce)

	// Register a namespace.
	api := e.Namespace("/api/v1")

	// Create routes for a model.
	people := api.Model("people")

	// GET /api/v1/people
	people.FindAll(responce)

	// GET /api/v1/people/{id}
	people.Find(responce)

	// POST /api/v1/people
	people.Create(responce)

	// PUT /api/v1/people/{id}
	people.Update(responce)

	// DELETE /api/v1/people/{id}
	people.Delete(responce)
}

func responce(w http.ResponseWriter, req *http.Request) {
	fmt.Fprintf(w, "%v %v", req.Method, req.URL)
}

func TestIndex(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	testFile(t, server, "/")
}

func TestAssets(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	tests := []string{
		"/assets/example.css",
		"/assets/example.js",
	}

	for _, test := range tests {
		testFile(t, server, test)
	}
}

func TestNotFound(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	testFile(t, server, "/devnull")
}

func TestGetModel(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	tests := []routeTest{
		{
			method:   "GET",
			path:     "/stats",
			expected: "GET /stats",
		},
	}

	for _, test := range tests {
		testRoute(t, server, test)
	}
}

func TestNamespace(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	tests := []routeTest{
		{
			method:   "GET",
			path:     "/api/v1/people",
			expected: "GET /api/v1/people",
		},
		{
			method:   "GET",
			path:     "/api/v1/people/1",
			expected: "GET /api/v1/people/1",
		},
		{
			method:   "PUT",
			path:     "/api/v1/people/1",
			expected: "PUT /api/v1/people/1",
		},
		{
			method:   "POST",
			path:     "/api/v1/people",
			expected: "POST /api/v1/people",
		},
		{
			method:   "DELETE",
			path:     "/api/v1/people/1",
			expected: "DELETE /api/v1/people/1",
		},
	}

	for _, test := range tests {
		testRoute(t, server, test)
	}
}

func testRoute(t *testing.T, server *httptest.Server, test routeTest) {
	res, err := sendRequest(test.method, server.URL+test.path)
	if err != nil {
		panic(err)
	}

	data, err := ioutil.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}

	actual := strings.Trim(string(data), "\n")

	if test.expected == actual {
		return
	}

	t.Errorf(
		"[%v %v] expected: [%v], got: [%v]\n",
		test.method,
		test.path,
		test.expected,
		actual,
	)
}

func testFile(t *testing.T, server *httptest.Server, path string) {
	res, err := sendRequest("GET", server.URL+path)
	if err != nil {
		panic(err)
	}

	if res.StatusCode == http.StatusOK {
		return
	}

	t.Errorf("[%v] expected: [%d], got: [%d]\n", path, http.StatusOK, res.StatusCode)
}

func sendRequest(method string, url string) (res *http.Response, err error) {
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, err
	}

	client := &http.Client{}
	return client.Do(req)
}
<commit_msg>use relative paths in tests<commit_after>package ember

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)

var e = New()

type routeTest struct {
	method   string
	path     string
	expected string
}

func init() {
	// Register a route for index.html file.
	e.Index("./example/dist/index.html")

	// Register a route for assets.
	e.Assets("/assets", "./example/dist/assets")

	// Create a model and register a route for /stats
	e.Model("stats").FindAll(responce)

	// Register a namespace.
	api := e.Namespace("/api/v1")

	// Create routes for a model.
	people := api.Model("people")

	// GET /api/v1/people
	people.FindAll(responce)

	// GET /api/v1/people/{id}
	people.Find(responce)

	// POST /api/v1/people
	people.Create(responce)

	// PUT /api/v1/people/{id}
	people.Update(responce)

	// DELETE /api/v1/people/{id}
	people.Delete(responce)
}

func responce(w http.ResponseWriter, req *http.Request) {
	fmt.Fprintf(w, "%v %v", req.Method, req.URL)
}

func TestIndex(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	testFile(t, server, "/")
}

func TestAssets(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	tests := []string{
		"/assets/example.css",
		"/assets/example.js",
	}

	for _, test := range tests {
		testFile(t, server, test)
	}
}

func TestNotFound(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	testFile(t, server, "/devnull")
}

func TestGetModel(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	tests := []routeTest{
		{
			method:   "GET",
			path:     "/stats",
			expected: "GET /stats",
		},
	}

	for _, test := range tests {
		testRoute(t, server, test)
	}
}

func TestNamespace(t *testing.T) {
	server := httptest.NewServer(e.Router)
	defer server.Close()

	tests := []routeTest{
		{
			method:   "GET",
			path:     "/api/v1/people",
			expected: "GET /api/v1/people",
		},
		{
			method:   "GET",
			path:     "/api/v1/people/1",
			expected: "GET /api/v1/people/1",
		},
		{
			method:   "PUT",
			path:     "/api/v1/people/1",
			expected: "PUT /api/v1/people/1",
		},
		{
			method:   "POST",
			path:     "/api/v1/people",
			expected: "POST /api/v1/people",
		},
		{
			method:   "DELETE",
			path:     "/api/v1/people/1",
			expected: "DELETE /api/v1/people/1",
		},
	}

	for _, test := range tests {
		testRoute(t, server, test)
	}
}

func testRoute(t *testing.T, server *httptest.Server, test routeTest) {
	res, err := sendRequest(test.method, server.URL+test.path)
	if err != nil {
		panic(err)
	}

	data, err := ioutil.ReadAll(res.Body)
	if err != nil {
		panic(err)
	}

	actual := strings.Trim(string(data), "\n")

	if test.expected == actual {
		return
	}

	t.Errorf(
		"[%v %v] expected: [%v], got: [%v]\n",
		test.method,
		test.path,
		test.expected,
		actual,
	)
}

func testFile(t *testing.T, server *httptest.Server, path string) {
	res, err := sendRequest("GET", server.URL+path)
	if err != nil {
		panic(err)
	}

	if res.StatusCode == http.StatusOK {
		return
	}

	t.Errorf("[%v] expected: [%d], got: [%d]\n", path, http.StatusOK, res.StatusCode)
}

func sendRequest(method string, url string) (res *http.Response, err error) {
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, err
	}

	client := &http.Client{}
	return client.Do(req)
}
<|endoftext|>


<commit_before>package quic

import (
	"reflect"
	"testing"
)

func TestPaddingFrame(t *testing.T) {
	data := []byte{0x00}
	fp := NewFramePacket(0, 0)
	frame := &PaddingFrame{FramePacket: fp}
	actualFrame := NewPaddingFrame(fp)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestRstStreamFrame(t *testing.T) {
	// streamID:1, offset:1, errorcode: NO_ERROR
	data := []byte{0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}
	fp := NewFramePacket(0, 0)
	frame := &RstStreamFrame{FramePacket: fp}
	actualFrame := NewRstStreamFrame(fp, 1, 1, NO_ERROR)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestPingFrame(t *testing.T) {
	data := []byte{0x07}
	fp := NewFramePacket(0, 0)
	frame := &PingFrame{FramePacket: fp}
	actualFrame := NewPingFrame(fp)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestConnectionCloseFrame(t *testing.T) {
	// errorcode: NO_ERROR, reason length: 14, reason: "This is reason",
	data := []byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e}
	reason := "This is reason"
	data = append(data, []byte(reason)...)
	fp := NewFramePacket(0, 0)
	frame := &ConnectionCloseFrame{FramePacket: fp}
	actualFrame := NewConnectionCloseFrame(fp, NO_ERROR, reason)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestGoAwayFrame(t *testing.T) {
	// errorcode: NO_ERROR, last streamID: 1, reason length: 14, reason: "This is reason",
	data := []byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0e}
	reason := "This is reason"
	data = append(data, []byte(reason)...)
	fp := NewFramePacket(0, 0)
	frame := &GoAwayFrame{FramePacket: fp}
	actualFrame := NewGoAwayFrame(fp, NO_ERROR, 1, reason)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestWindowUpdateFrame(t *testing.T) {
	// streamID: 1, offset 1
	data := []byte{0x04, 0x00, 0x00, 0x00, 0x01, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
	fp := NewFramePacket(0, 0)
	frame := &WindowUpdateFrame{FramePacket: fp}
	actualFrame := NewWindowUpdateFrame(fp, 1, 1)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestBlockedFrame(t *testing.T) {
	// streamID: 1
	data := []byte{0x05, 0x00, 0x00, 0x00, 0x01}
	fp := NewFramePacket(0, 0)
	frame := &BlockedFrame{FramePacket: fp}
	actualFrame := NewBlockedFrame(fp, 1)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestStopWaitingFrame(t *testing.T) {
	// Sent Entropy: 1, least unacked delta: 1
	data := []byte{0x06, 0x01, 0x01}
	fp := NewFramePacket(0, 0)
	frame := &StopWaitingFrame{FramePacket: fp}
	actualFrame := NewStopWaitingFrame(fp, 1, 1)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}
<commit_msg>write streamFrame test case<commit_after>package quic

import (
	"reflect"
	"testing"
)

func TestStreamFrameFrame(t *testing.T) {
	// fin: true, streamID: 1, offset: 1, dataLength: 1
	data := []byte{0xe4, 0x01, 0x00, 0x01, 0x00, 0x01}
	fp := NewFramePacket(0, 0)
	frame := &StreamFrame{FramePacket: fp}
	actualFrame := NewStreamFrame(fp, true, 1, 1, 1)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestPaddingFrame(t *testing.T) {
	data := []byte{0x00}
	fp := NewFramePacket(0, 0)
	frame := &PaddingFrame{FramePacket: fp}
	actualFrame := NewPaddingFrame(fp)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestRstStreamFrame(t *testing.T) {
	// streamID:1, offset:1, errorcode: NO_ERROR
	data := []byte{0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}
	fp := NewFramePacket(0, 0)
	frame := &RstStreamFrame{FramePacket: fp}
	actualFrame := NewRstStreamFrame(fp, 1, 1, NO_ERROR)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestPingFrame(t *testing.T) {
	data := []byte{0x07}
	fp := NewFramePacket(0, 0)
	frame := &PingFrame{FramePacket: fp}
	actualFrame := NewPingFrame(fp)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}
}

func TestConnectionCloseFrame(t *testing.T) {
	// errorcode: NO_ERROR, reason length: 14, reason: "This is reason",
	data := []byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e}
	reason := "This is reason"
	data = append(data, []byte(reason)...)
	fp := NewFramePacket(0, 0)
	frame := &ConnectionCloseFrame{FramePacket: fp}
	actualFrame := NewConnectionCloseFrame(fp, NO_ERROR, reason)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestGoAwayFrame(t *testing.T) {
	// errorcode: NO_ERROR, last streamID: 1, reason length: 14, reason: "This is reason",
	data := []byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0e}
	reason := "This is reason"
	data = append(data, []byte(reason)...)
	fp := NewFramePacket(0, 0)
	frame := &GoAwayFrame{FramePacket: fp}
	actualFrame := NewGoAwayFrame(fp, NO_ERROR, 1, reason)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestWindowUpdateFrame(t *testing.T) {
	// streamID: 1, offset 1
	data := []byte{0x04, 0x00, 0x00, 0x00, 0x01, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
	fp := NewFramePacket(0, 0)
	frame := &WindowUpdateFrame{FramePacket: fp}
	actualFrame := NewWindowUpdateFrame(fp, 1, 1)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestBlockedFrame(t *testing.T) {
	// streamID: 1
	data := []byte{0x05, 0x00, 0x00, 0x00, 0x01}
	fp := NewFramePacket(0, 0)
	frame := &BlockedFrame{FramePacket: fp}
	actualFrame := NewBlockedFrame(fp, 1)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}

func TestStopWaitingFrame(t *testing.T) {
	// Sent Entropy: 1, least unacked delta: 1
	data := []byte{0x06, 0x01, 0x01}
	fp := NewFramePacket(0, 0)
	frame := &StopWaitingFrame{FramePacket: fp}
	actualFrame := NewStopWaitingFrame(fp, 1, 1)

	actualLen, _ := frame.Parse(data)
	if actualLen != len(data) {
		t.Errorf("got %v\nwant %v", actualLen, len(data))
	}

	if !reflect.DeepEqual(actualFrame, frame) {
		t.Errorf("got %v\nwant %v", actualFrame, frame)
	}

	actualWire, _ := frame.GetWire()
	if !reflect.DeepEqual(actualWire, data) {
		t.Errorf("got %v\nwant %v", actualWire, data)
	}

}
<|endoftext|>


<commit_before>package agent

import (
	"fmt"
	"github.com/golang/glog"
	. "github.com/infradash/dash/pkg/dash"
	"github.com/qorio/maestro/pkg/docker"
	"strings"
)

func (this *Agent) DiscoverSelfInDocker() error {

	docker_name := this.Name

	if docker_name == "" {
		return ErrNoDockerName
	}

	glog.Infoln("Discovering container in Docker with name=", docker_name)

	dc, err := this.docker.FindContainersByName(docker_name)
	if err != nil {
		return err
	}

	if len(dc) > 1 {
		// This is unlikely, since Docker itself will prevent containers with
		// the same assigned name from starting.  However, it's possible that
		// the name provided isn't a complete name, so we have partial match.
		// In this case, it's programming error.
		return ErrMoreThanOneAgent
	}

	if len(dc) == 1 {
		this.self_container = dc[0]

		this.self_container.Inspect()
		glog.Infoln("Found self as container:", this.self_container)

		if len(dc[0].Ports) > 0 {
			this.Port = dc[0].Ports[0]
		}
	}

	return nil
}

type ContainerMatchRule struct {
	MatchContainerRule

	Domain      string
	Service     ServiceKey
	PortMatched bool
}

func (this *MatchContainerRule) GetMatchContainerPort() int {
	if this.MatchContainerPort != nil {
		return *this.MatchContainerPort
	} else {
		return 0
	}
}

func (this *ContainerMatchRule) GetMatchContainerPort() int {
	return this.MatchContainerRule.GetMatchContainerPort()
}

func (this *ContainerMatchRule) match_by_running_port(c *docker.Container) bool {
	if this.MatchContainerPort == nil {
		return false // Don't care
	}
	port := *this.MatchContainerPort
	if port > 0 {
		for _, p := range c.Ports {
			if port == int(p.ContainerPort) {
				this.PortMatched = true
				return true
			}
		}
	}
	return false
}

func (this *ContainerMatchRule) match(c *docker.Container) bool {
	if c.DockerData == nil {
		return false
	}

	// We first try by matching image. Then by name, environment variable.
	if !ImageMatch(c.Image, &this.Image) {
		return false
	}

	// When the container isn't running, the port information is erased.
	// So we count on other conditions to match -- we at least eliminate the negative case
	// where it's running and the port doesn't match
	if c.DockerData.State.Running && this.MatchContainerPort != nil && !this.match_by_running_port(c) {
		return false
	}

	// If we have no other criteria by now, just match
	if len(this.MatchAll) == 0 && len(this.MatchFirst) == 0 {
		return true
	}

	match := true
	for _, r := range this.MatchAll {
		match = match && r.Match(c)
	}
	if !match {
		return false
	}

	match = false // reset
	for _, r := range this.MatchFirst {
		if r.Match(c) {
			match = true
			break
		}
	}
	return match
}

type CheckContainer func(*docker.Container) map[ServiceKey]*ContainerMatchRule
type OnMatch func(*docker.Container, *ContainerMatchRule)

func (this *Agent) DiscoverRunningContainers(check CheckContainer, do OnMatch) error {

	glog.Infoln("Querying docker for all containers")
	all_containers, err := this.docker.FindContainers(nil) //map[string][]string{"status": []string{"running"}})
	if err != nil {
		return err
	}
	glog.Infoln("Found", len(all_containers), "containers")

	for _, container := range all_containers {
		glog.Infoln("Checking", "Name=", container.Name, "Image=", container.Image, "Id=", container.Id[0:12])
		match_rules := check(container)

		glog.Infoln("For container=", container, "matched_rules=", match_rules)

		for serviceKey, rule := range match_rules {
			glog.Infoln("==========================>>>>  Matched",
				"ServiceKey=", serviceKey,
				"Rule=", rule,
				"Name=", container.Name,
				"Id=", container.Id[0:12],
				"Image=", container.Image)
			do(container, rule)
		}
	}
	return nil
}

type DiscoveryContainerMatcher struct {
	rulesByDomainService map[string]map[ServiceKey]ContainerMatchRule
}

func (this *DiscoveryContainerMatcher) Init() *DiscoveryContainerMatcher {
	this.rulesByDomainService = make(map[string]map[ServiceKey]ContainerMatchRule)
	return this
}

func (this *DiscoveryContainerMatcher) C(domain string, service ServiceKey, spec *MatchContainerRule) *DiscoveryContainerMatcher {
	match_rule := ContainerMatchRule{
		MatchContainerRule: *spec,
		Domain:             domain,
		Service:            service,
	}
	if _, has := this.rulesByDomainService[domain]; !has {
		this.rulesByDomainService[domain] = map[ServiceKey]ContainerMatchRule{}
	}

	this.rulesByDomainService[domain][service] = match_rule
	return this
}

// This is critical for the discovery to know how to locate the rule for matching.  This is because rules are
// organized by domain and service.  We look for hints in the container's metadata to determine which domain
// this container may belong to.
func findContainerDomain(c *docker.Container) *string {
	if c.DockerData == nil || c.DockerData.Config == nil {
		return nil
	}
	v := ""
	// Find by label or environment variables
	if c.DockerData != nil && c.DockerData.Config != nil {
		if len(c.DockerData.Config.Labels) > 0 {
			v = find_container_domain_by_label(c)
		}
		if v == "" && len(c.DockerData.Config.Env) > 0 {
			v = find_container_domain_by_env(c)
		}
	}
	return &v
}

func find_container_domain_by_label(c *docker.Container) string {
	if l, exists := c.DockerData.Config.Labels[EnvDomain]; exists {
		return l
	}
	return ""
}

func find_container_domain_by_env(c *docker.Container) string {
	search := fmt.Sprintf("%s=", EnvDomain)
	for _, env := range c.DockerData.Config.Env {
		index := strings.Index(env, search)
		if index == 0 {
			return env[len(search):]
		}
	}
	return ""
}

func (this *DiscoveryContainerMatcher) MatcherForDomain(domain string, service ServiceKey) func(docker.Action, *docker.Container) bool {
	// get the rule
	if service_rule_map, has_domain := this.rulesByDomainService[domain]; has_domain {
		if rule, has_map := service_rule_map[service]; has_map {
			return func(a docker.Action, c *docker.Container) bool {
				if a == docker.Remove {
					return ImageMatch(c.Image, &rule.Image)
				}

				if env := findContainerDomain(c); env != nil {
					return *env == domain && rule.match(c)
				} else {
					return rule.match(c)
				}
			}
		}
	}
	glog.Warningln("No matcher for Domain=", domain, "Service=", service)
	return func(docker.Action, *docker.Container) bool {
		return false
	}
}

func (this *DiscoveryContainerMatcher) Match(c *docker.Container) map[ServiceKey]*ContainerMatchRule {
	return this.match(findContainerDomain(c), c)
}

func (this *DiscoveryContainerMatcher) match(domain *string, c *docker.Container) map[ServiceKey]*ContainerMatchRule {
	if domain != nil {
		matches := map[ServiceKey]*ContainerMatchRule{}
		// Now we have matched by the domain of the container.  Let's see if it's running an image we care about:
		for serviceKey, match_rule := range this.rulesByDomainService[*domain] {
			glog.Infoln("Checking domain=", domain, "service=", serviceKey, "rule=", match_rule)

			matched := false
			if env := findContainerDomain(c); env != nil {
				matched = *env == *domain && match_rule.match(c)
			} else {
				matched = match_rule.match(c)
			}

			glog.Infoln(">>>>>> matched=", matched)
			if matched {
				matches[serviceKey] = &match_rule
			}
		}
		return matches
	} else {
		matches := map[ServiceKey]*ContainerMatchRule{}
		// if we don't know the domain, then search through all the images...
		for _, rules := range this.rulesByDomainService {
			for serviceKey, match_rule := range rules {
				if match_rule.match(c) {
					glog.Infoln("Matched service=", serviceKey, "rule=", match_rule)
					matches[serviceKey] = &match_rule
				}
			}
		}
		return matches
	}

}

func ImageMatch(image string, spec *docker.Image) bool {
	glog.V(100).Infoln("Matching image", image, "vs", spec)
	if spec.Tag != "" {
		return image == fmt.Sprintf("%s:%s", spec.Repository, spec.Tag)
	} else {
		return strings.Index(image, spec.Repository) == 0
	}
}

func BuildRegistryEntry(container *docker.Container, match_port int) (*RegistryContainerEntry, error) {
	_, version, _, err := ParseVersion(container.Image)
	if err != nil {
		return nil, err
	}

	entry := &RegistryContainerEntry{
		RegistryReleaseEntry: RegistryReleaseEntry{
			RegistryEntryBase: RegistryEntryBase{
				Version: version,
			},
			Image: container.Image,
		},
		ContainerId: container.Id,
	}

	// Interactive sessions don't have ports... So we add an entry only if we don't care
	// to match ports (match_container_port == 0)
	for _, p := range container.Ports {
		if match_port == int(p.ContainerPort) || match_port == 0 {
			entry.Port = p
			return entry, nil
		}
	}

	if match_port == 0 {
		return entry, nil
	} else {
		return nil, nil
	}
}
<commit_msg>Discover multiple services - fix references<commit_after>package agent

import (
	"fmt"
	"github.com/golang/glog"
	. "github.com/infradash/dash/pkg/dash"
	"github.com/qorio/maestro/pkg/docker"
	"strings"
)

func (this *Agent) DiscoverSelfInDocker() error {

	docker_name := this.Name

	if docker_name == "" {
		return ErrNoDockerName
	}

	glog.Infoln("Discovering container in Docker with name=", docker_name)

	dc, err := this.docker.FindContainersByName(docker_name)
	if err != nil {
		return err
	}

	if len(dc) > 1 {
		// This is unlikely, since Docker itself will prevent containers with
		// the same assigned name from starting.  However, it's possible that
		// the name provided isn't a complete name, so we have partial match.
		// In this case, it's programming error.
		return ErrMoreThanOneAgent
	}

	if len(dc) == 1 {
		this.self_container = dc[0]

		this.self_container.Inspect()
		glog.Infoln("Found self as container:", this.self_container)

		if len(dc[0].Ports) > 0 {
			this.Port = dc[0].Ports[0]
		}
	}

	return nil
}

type ContainerMatchRule struct {
	MatchContainerRule

	Domain      string
	Service     ServiceKey
	PortMatched bool
}

func (this *MatchContainerRule) GetMatchContainerPort() int {
	if this.MatchContainerPort != nil {
		return *this.MatchContainerPort
	} else {
		return 0
	}
}

func (this *ContainerMatchRule) GetMatchContainerPort() int {
	return this.MatchContainerRule.GetMatchContainerPort()
}

func (this *ContainerMatchRule) match_by_running_port(c *docker.Container) bool {
	if this.MatchContainerPort == nil {
		return false // Don't care
	}
	port := *this.MatchContainerPort
	if port > 0 {
		for _, p := range c.Ports {
			if port == int(p.ContainerPort) {
				this.PortMatched = true
				return true
			}
		}
	}
	return false
}

func (this *ContainerMatchRule) match(c *docker.Container) bool {
	if c.DockerData == nil {
		return false
	}

	// We first try by matching image. Then by name, environment variable.
	if !ImageMatch(c.Image, &this.Image) {
		return false
	}

	// When the container isn't running, the port information is erased.
	// So we count on other conditions to match -- we at least eliminate the negative case
	// where it's running and the port doesn't match
	if c.DockerData.State.Running && this.MatchContainerPort != nil && !this.match_by_running_port(c) {
		return false
	}

	// If we have no other criteria by now, just match
	if len(this.MatchAll) == 0 && len(this.MatchFirst) == 0 {
		return true
	}

	match := true
	for _, r := range this.MatchAll {
		match = match && r.Match(c)
	}
	if !match {
		return false
	}

	match = false // reset
	for _, r := range this.MatchFirst {
		if r.Match(c) {
			match = true
			break
		}
	}
	return match
}

type CheckContainer func(*docker.Container) map[ServiceKey]*ContainerMatchRule
type OnMatch func(*docker.Container, *ContainerMatchRule)

func (this *Agent) DiscoverRunningContainers(check CheckContainer, do OnMatch) error {

	glog.Infoln("Querying docker for all containers")
	all_containers, err := this.docker.FindContainers(nil) //map[string][]string{"status": []string{"running"}})
	if err != nil {
		return err
	}
	glog.Infoln("Found", len(all_containers), "containers")

	for _, container := range all_containers {
		glog.Infoln("Checking", "Name=", container.Name, "Image=", container.Image, "Id=", container.Id[0:12])
		match_rules := check(container)

		glog.Infoln("For container=", container, "matched_rules=", match_rules)

		for serviceKey, rule := range match_rules {
			glog.Infoln("==========================>>>>  Matched",
				"ServiceKey=", serviceKey,
				"Rule=", rule,
				"Name=", container.Name,
				"Id=", container.Id[0:12],
				"Image=", container.Image)
			do(container, rule)
		}
	}
	return nil
}

type DiscoveryContainerMatcher struct {
	rulesByDomainService map[string]map[ServiceKey]*ContainerMatchRule
}

func (this *DiscoveryContainerMatcher) Init() *DiscoveryContainerMatcher {
	this.rulesByDomainService = make(map[string]map[ServiceKey]*ContainerMatchRule)
	return this
}

func (this *DiscoveryContainerMatcher) C(domain string, service ServiceKey, spec *MatchContainerRule) *DiscoveryContainerMatcher {
	match_rule := &ContainerMatchRule{
		MatchContainerRule: *spec,
		Domain:             domain,
		Service:            service,
	}
	if _, has := this.rulesByDomainService[domain]; !has {
		this.rulesByDomainService[domain] = map[ServiceKey]*ContainerMatchRule{}
	}

	this.rulesByDomainService[domain][service] = match_rule
	return this
}

// This is critical for the discovery to know how to locate the rule for matching.  This is because rules are
// organized by domain and service.  We look for hints in the container's metadata to determine which domain
// this container may belong to.
func findContainerDomain(c *docker.Container) *string {
	if c.DockerData == nil || c.DockerData.Config == nil {
		return nil
	}
	v := ""
	// Find by label or environment variables
	if c.DockerData != nil && c.DockerData.Config != nil {
		if len(c.DockerData.Config.Labels) > 0 {
			v = find_container_domain_by_label(c)
		}
		if v == "" && len(c.DockerData.Config.Env) > 0 {
			v = find_container_domain_by_env(c)
		}
	}
	return &v
}

func find_container_domain_by_label(c *docker.Container) string {
	if l, exists := c.DockerData.Config.Labels[EnvDomain]; exists {
		return l
	}
	return ""
}

func find_container_domain_by_env(c *docker.Container) string {
	search := fmt.Sprintf("%s=", EnvDomain)
	for _, env := range c.DockerData.Config.Env {
		index := strings.Index(env, search)
		if index == 0 {
			return env[len(search):]
		}
	}
	return ""
}

func (this *DiscoveryContainerMatcher) MatcherForDomain(domain string, service ServiceKey) func(docker.Action, *docker.Container) bool {
	// get the rule
	if service_rule_map, has_domain := this.rulesByDomainService[domain]; has_domain {
		if rule, has_map := service_rule_map[service]; has_map {
			return func(a docker.Action, c *docker.Container) bool {
				if a == docker.Remove {
					return ImageMatch(c.Image, &rule.Image)
				}

				if env := findContainerDomain(c); env != nil {
					return *env == domain && rule.match(c)
				} else {
					return rule.match(c)
				}
			}
		}
	}
	glog.Warningln("No matcher for Domain=", domain, "Service=", service)
	return func(docker.Action, *docker.Container) bool {
		return false
	}
}

func (this *DiscoveryContainerMatcher) Match(c *docker.Container) map[ServiceKey]*ContainerMatchRule {
	return this.match(findContainerDomain(c), c)
}

func (this *DiscoveryContainerMatcher) match(domain *string, c *docker.Container) map[ServiceKey]*ContainerMatchRule {
	if domain != nil {
		matches := map[ServiceKey]*ContainerMatchRule{}

		rules_by_service := this.rulesByDomainService[*domain]
		// Now we have matched by the domain of the container.  Let's see if it's running an image we care about:
		for serviceKey, match_rule := range rules_by_service {
			glog.Infoln("Checking domain=", domain, "service=", serviceKey, "rule=", match_rule)

			matched := false
			if env := findContainerDomain(c); env != nil {
				matched = *env == *domain && match_rule.match(c)
			} else {
				matched = match_rule.match(c)
			}

			glog.Infoln(">>>>>> matched=", matched)
			if matched {
				matches[serviceKey] = match_rule
			}
		}
		glog.Infoln("==> Matched Rules:", matches)
		return matches
	} else {
		matches := map[ServiceKey]*ContainerMatchRule{}
		// if we don't know the domain, then search through all the images...
		for _, rules := range this.rulesByDomainService {
			for serviceKey, match_rule := range rules {
				if match_rule.match(c) {
					glog.Infoln("Matched service=", serviceKey, "rule=", match_rule)
					matches[serviceKey] = match_rule
				}
			}
		}
		return matches
	}

}

func ImageMatch(image string, spec *docker.Image) bool {
	glog.V(100).Infoln("Matching image", image, "vs", spec)
	if spec.Tag != "" {
		return image == fmt.Sprintf("%s:%s", spec.Repository, spec.Tag)
	} else {
		return strings.Index(image, spec.Repository) == 0
	}
}

func BuildRegistryEntry(container *docker.Container, match_port int) (*RegistryContainerEntry, error) {
	_, version, _, err := ParseVersion(container.Image)
	if err != nil {
		return nil, err
	}

	entry := &RegistryContainerEntry{
		RegistryReleaseEntry: RegistryReleaseEntry{
			RegistryEntryBase: RegistryEntryBase{
				Version: version,
			},
			Image: container.Image,
		},
		ContainerId: container.Id,
	}

	// Interactive sessions don't have ports... So we add an entry only if we don't care
	// to match ports (match_container_port == 0)
	for _, p := range container.Ports {
		if match_port == int(p.ContainerPort) || match_port == 0 {
			entry.Port = p
			return entry, nil
		}
	}

	if match_port == 0 {
		return entry, nil
	} else {
		return nil, nil
	}
}
<|endoftext|>


<commit_before>// Packege pidctrl implements a PID controller.
//
// see http://en.wikipedia.org/wiki/PID_controller
package pidctrl

import (
	"fmt"
	"math"
	"time"
)

type MinMaxError struct {
	min, max float64
}

func (e MinMaxError) Error() string {
	return fmt.Sprintf("min: %v is greater than max: %v", e.min, e.max)
}

// NewPIDController returns a new PIDController using the given gain values.
func NewPIDController(p, i, d float64) *PIDController {
	return &PIDController{p: p, i: i, d: d, outMin: math.Inf(-1), outMax: math.Inf(0)}
}

// PIDController implements a PID controller.
type PIDController struct {
	p          float64   // proportional gain
	i          float64   // integral gain
	d          float64   // derrivate gain
	setpoint   float64   // current setpoint
	prevValue  float64   // last process value
	integral   float64   // integral sum
	lastUpdate time.Time // time of last update
	outMin     float64   // Output Min
	outMax     float64   // Output Max
}

// Set changes the setpoint of the controller.
func (c *PIDController) Set(setpoint float64) *PIDController {
	c.setpoint = setpoint
	return c
}

// Get returns the setpoint of the controller.
func (c *PIDController) Get() float64 {
	return c.setpoint
}

// SetPID changes the P, I, and D constants
func (c *PIDController) SetPID(p, i, d float64) *PIDController {
	c.p = p
	c.i = i
	c.d = d
	return c
}

// PID returns the P, I, and D constants
func (c *PIDController) PID() (p, i, d float64) {
	return c.p, c.i, c.d
}

// SetOutputLimits sets the min and max output values
func (c *PIDController) SetOutputLimits(min, max float64) *PIDController {
	if min > max {
		panic(MinMaxError{min, max})
	}
	c.outMin = min
	c.outMax = max

	if c.integral > c.outMax {
		c.integral = c.outMax
	} else if c.integral < c.outMin {
		c.integral = c.outMin
	}
	return c
}

// OutputLimits returns the min and max output values
func (c *PIDController) OutputLimits() (min, max float64) {
	return c.outMin, c.outMax
}

// Update is identical to UpdateDuration, but automatically keeps track of the
// durations between updates.
func (c *PIDController) Update(value float64) float64 {
	var duration time.Duration
	if !c.lastUpdate.IsZero() {
		duration = time.Since(c.lastUpdate)
	}
	c.lastUpdate = time.Now()
	return c.UpdateDuration(value, duration)
}

// UpdateDuration updates the controller with the given value and duration since
// the last update. It returns the new output.
//
// see http://en.wikipedia.org/wiki/PID_controller#Pseudocode
func (c *PIDController) UpdateDuration(value float64, duration time.Duration) float64 {
	var (
		dt  = duration.Seconds()
		err = c.setpoint - value
		d   float64
	)
	c.integral += err * dt * c.i
	if dt > 0 {
		d = -((value - c.prevValue) / dt)
	}
	c.prevValue = value
	output := (c.p * err) + c.integral + (c.d * d)

	if output > c.outMax {
		c.integral -= output - c.outMax
		output = c.outMax
	} else if output < c.outMin {
		c.integral += c.outMin - output
		output = c.outMin
	}

	return output
}
<commit_msg>fix integral windup prevention<commit_after>// Packege pidctrl implements a PID controller.
//
// see http://en.wikipedia.org/wiki/PID_controller
package pidctrl

import (
	"fmt"
	"math"
	"time"
)

type MinMaxError struct {
	min, max float64
}

func (e MinMaxError) Error() string {
	return fmt.Sprintf("min: %v is greater than max: %v", e.min, e.max)
}

// NewPIDController returns a new PIDController using the given gain values.
func NewPIDController(p, i, d float64) *PIDController {
	return &PIDController{p: p, i: i, d: d, outMin: math.Inf(-1), outMax: math.Inf(0)}
}

// PIDController implements a PID controller.
type PIDController struct {
	p          float64   // proportional gain
	i          float64   // integral gain
	d          float64   // derrivate gain
	setpoint   float64   // current setpoint
	prevValue  float64   // last process value
	integral   float64   // integral sum
	lastUpdate time.Time // time of last update
	outMin     float64   // Output Min
	outMax     float64   // Output Max
}

// Set changes the setpoint of the controller.
func (c *PIDController) Set(setpoint float64) *PIDController {
	c.setpoint = setpoint
	return c
}

// Get returns the setpoint of the controller.
func (c *PIDController) Get() float64 {
	return c.setpoint
}

// SetPID changes the P, I, and D constants
func (c *PIDController) SetPID(p, i, d float64) *PIDController {
	c.p = p
	c.i = i
	c.d = d
	return c
}

// PID returns the P, I, and D constants
func (c *PIDController) PID() (p, i, d float64) {
	return c.p, c.i, c.d
}

// SetOutputLimits sets the min and max output values
func (c *PIDController) SetOutputLimits(min, max float64) *PIDController {
	if min > max {
		panic(MinMaxError{min, max})
	}
	c.outMin = min
	c.outMax = max

	if c.integral > c.outMax {
		c.integral = c.outMax
	} else if c.integral < c.outMin {
		c.integral = c.outMin
	}
	return c
}

// OutputLimits returns the min and max output values
func (c *PIDController) OutputLimits() (min, max float64) {
	return c.outMin, c.outMax
}

// Update is identical to UpdateDuration, but automatically keeps track of the
// durations between updates.
func (c *PIDController) Update(value float64) float64 {
	var duration time.Duration
	if !c.lastUpdate.IsZero() {
		duration = time.Since(c.lastUpdate)
	}
	c.lastUpdate = time.Now()
	return c.UpdateDuration(value, duration)
}

// UpdateDuration updates the controller with the given value and duration since
// the last update. It returns the new output.
//
// see http://en.wikipedia.org/wiki/PID_controller#Pseudocode
func (c *PIDController) UpdateDuration(value float64, duration time.Duration) float64 {
	var (
		dt  = duration.Seconds()
		err = c.setpoint - value
		d   float64
	)
	c.integral += err * dt * c.i
	if c.integral > c.outMax {
		c.integral = c.outMax
	} else if c.integral < c.outMin {
		c.integral = c.outMin
	}
	if dt > 0 {
		d = -((value - c.prevValue) / dt)
	}
	c.prevValue = value
	output := (c.p * err) + c.integral + (c.d * d)

	if output > c.outMax {
		output = c.outMax
	} else if output < c.outMin {
		output = c.outMin
	}

	return output
}
<|endoftext|>


<commit_before>package coreutil

import (
	"net/http"
	"reflect"

	"github.com/volatile/core"
)

// ResponseStatus returns the HTTP response status.
// Remember that the status is only set by the server after ResponseWriter.WriteHeader() has been called.
func ResponseStatus(c *core.Context) int {
	return int(httpResponseStruct(reflect.ValueOf(c.ResponseWriter)).FieldByName("status").Int())
}

// httpResponseStruct returns the response structure after going trough all the intermediary responseWriter Binders.
func httpResponseStruct(v reflect.Value) reflect.Value {
	switch v.Type().String() {
	case "core.ResponseWriterBinder":
		return httpResponseStruct(v.FieldByName("ResponseWriter").Elem())
	case "*http.response":
		return v.Elem()
	default:
		panic("coreutil: call of httpResponseStruct on unknown interface type")
	}
}

// SetDetectedContentType detects and sets and returns the response content type.
func SetDetectedContentType(c *core.Context, b []byte) string {
	ct := c.ResponseWriter.Header().Get("Content-Type")
	if len(ct) == 0 {
		ct := http.DetectContentType(b)
		c.ResponseWriter.Header().Set("Content-Type", ct)
	}
	return ct
}
<commit_msg>Fix coreutil<commit_after>package coreutil

import (
	"net/http"
	"reflect"

	"github.com/volatile/core"
)

// ResponseStatus returns the HTTP response status.
// Remember that the status is only set by the server after "ResponseWriter.WriteHeader()"" has been called.
func ResponseStatus(c *core.Context) int {
	return int(httpResponseStruct(reflect.ValueOf(c.ResponseWriter)).FieldByName("status").Int())
}

// httpResponseStruct returns the response structure after going trough all the intermediary response writers.
func httpResponseStruct(v reflect.Value) reflect.Value {
	switch v.Type().String() {
	case "*http.response":
		return v.Elem()
	default:
		return httpResponseStruct(v.FieldByName("ResponseWriter").Elem())
	}
}

// SetDetectedContentType detects and sets and returns the response content type.
func SetDetectedContentType(c *core.Context, b []byte) string {
	ct := c.ResponseWriter.Header().Get("Content-Type")
	if ct == "" {
		ct = http.DetectContentType(b)
		c.ResponseWriter.Header().Set("Content-Type", ct)
	}
	return ct
}
<|endoftext|>


<commit_before>package fleetworkspace

import (
	"context"

	fleet "github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
	mgmt "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
	mgmtcontrollers "github.com/rancher/rancher/pkg/generated/controllers/management.cattle.io/v3"
	"github.com/rancher/rancher/pkg/wrangler"
	v1 "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
	"github.com/rancher/wrangler/pkg/generic"
	"github.com/rancher/wrangler/pkg/yaml"
	corev1 "k8s.io/api/core/v1"
	apierror "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

var (
	managed = "provisioning.cattle.io/managed"
)

type handle struct {
	workspaceCache mgmtcontrollers.FleetWorkspaceCache
	namespaceCache v1.NamespaceCache
	workspaces     mgmtcontrollers.FleetWorkspaceClient
}

func Register(ctx context.Context, clients *wrangler.Context) {
	h := &handle{
		workspaceCache: clients.Mgmt.FleetWorkspace().Cache(),
		workspaces:     clients.Mgmt.FleetWorkspace(),
		namespaceCache: clients.Core.Namespace().Cache(),
	}

	clients.Mgmt.Setting().OnChange(ctx, "default-workspace", h.OnSetting)

	mgmtcontrollers.RegisterFleetWorkspaceGeneratingHandler(ctx,
		clients.Mgmt.FleetWorkspace(),
		clients.Apply.
			WithCacheTypes(clients.Core.Namespace()),
		"",
		"workspace",
		h.OnChange,
		&generic.GeneratingHandlerOptions{
			AllowClusterScoped: true,
		})

	clients.Fleet.Cluster().OnChange(ctx, "workspace-backport",
		func(s string, obj *fleet.Cluster) (*fleet.Cluster, error) {
			if obj == nil {
				return nil, nil
			}
			return obj, h.onFleetObject(obj)
		})
	clients.Fleet.Bundle().OnChange(ctx, "workspace-backport",
		func(s string, obj *fleet.Bundle) (*fleet.Bundle, error) {
			if obj == nil {
				return nil, nil
			}
			return obj, h.onFleetObject(obj)
		})
}

func (h *handle) OnSetting(key string, setting *mgmt.Setting) (*mgmt.Setting, error) {
	if setting == nil || setting.Name != "fleet-default-workspace-name" {
		return setting, nil
	}

	value := setting.Value
	if value == "" {
		value = setting.Default
	}

	if value == "" {
		return setting, nil
	}

	_, err := h.workspaceCache.Get(value)
	if apierror.IsNotFound(err) {
		_, err = h.workspaces.Create(&mgmt.FleetWorkspace{
			ObjectMeta: metav1.ObjectMeta{
				Name: value,
			},
		})
	}

	return setting, err
}

func (h *handle) OnChange(workspace *mgmt.FleetWorkspace, status mgmt.FleetWorkspaceStatus) ([]runtime.Object, mgmt.FleetWorkspaceStatus, error) {
	if workspace.Annotations[managed] == "false" {
		return nil, status, nil
	}

	return []runtime.Object{
		&corev1.Namespace{
			ObjectMeta: metav1.ObjectMeta{
				Name:   workspace.Name,
				Labels: yaml.CleanAnnotationsForExport(workspace.Labels),
			},
		},
	}, status, nil
}

func (h *handle) onFleetObject(obj runtime.Object) error {
	m, err := meta.Accessor(obj)
	if err != nil {
		return err
	}

	_, err = h.workspaceCache.Get(m.GetNamespace())
	if apierror.IsNotFound(err) {
		ns, err := h.namespaceCache.Get(m.GetNamespace())
		if err != nil {
			return err
		}

		_, err = h.workspaces.Create(&mgmt.FleetWorkspace{
			ObjectMeta: metav1.ObjectMeta{
				Name: m.GetNamespace(),
				OwnerReferences: []metav1.OwnerReference{
					{
						APIVersion: "v1",
						Kind:       "Namespace",
						Name:       ns.Name,
						UID:        ns.UID,
					},
				},
				Annotations: map[string]string{
					managed: "false",
				},
			},
			Status: mgmt.FleetWorkspaceStatus{},
		})
		if apierror.IsAlreadyExists(err) {
			return nil
		}
	}

	return err
}
<commit_msg>Only create fleetworkspaces if mcm is enabled<commit_after>package fleetworkspace

import (
	"context"

	fleet "github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
	mgmt "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
	"github.com/rancher/rancher/pkg/features"
	mgmtcontrollers "github.com/rancher/rancher/pkg/generated/controllers/management.cattle.io/v3"
	"github.com/rancher/rancher/pkg/wrangler"
	v1 "github.com/rancher/wrangler/pkg/generated/controllers/core/v1"
	"github.com/rancher/wrangler/pkg/generic"
	"github.com/rancher/wrangler/pkg/yaml"
	corev1 "k8s.io/api/core/v1"
	apierror "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

var (
	managed = "provisioning.cattle.io/managed"
)

type handle struct {
	workspaceCache mgmtcontrollers.FleetWorkspaceCache
	namespaceCache v1.NamespaceCache
	workspaces     mgmtcontrollers.FleetWorkspaceClient
}

func Register(ctx context.Context, clients *wrangler.Context) {
	h := &handle{
		workspaceCache: clients.Mgmt.FleetWorkspace().Cache(),
		workspaces:     clients.Mgmt.FleetWorkspace(),
		namespaceCache: clients.Core.Namespace().Cache(),
	}

	if features.MCM.Enabled() {
		clients.Mgmt.Setting().OnChange(ctx, "default-workspace", h.OnSetting)
	}

	mgmtcontrollers.RegisterFleetWorkspaceGeneratingHandler(ctx,
		clients.Mgmt.FleetWorkspace(),
		clients.Apply.
			WithCacheTypes(clients.Core.Namespace()),
		"",
		"workspace",
		h.OnChange,
		&generic.GeneratingHandlerOptions{
			AllowClusterScoped: true,
		})

	clients.Fleet.Cluster().OnChange(ctx, "workspace-backport",
		func(s string, obj *fleet.Cluster) (*fleet.Cluster, error) {
			if obj == nil {
				return nil, nil
			}
			return obj, h.onFleetObject(obj)
		})
	clients.Fleet.Bundle().OnChange(ctx, "workspace-backport",
		func(s string, obj *fleet.Bundle) (*fleet.Bundle, error) {
			if obj == nil {
				return nil, nil
			}
			return obj, h.onFleetObject(obj)
		})
}

func (h *handle) OnSetting(key string, setting *mgmt.Setting) (*mgmt.Setting, error) {
	if setting == nil || setting.Name != "fleet-default-workspace-name" {
		return setting, nil
	}

	value := setting.Value
	if value == "" {
		value = setting.Default
	}

	if value == "" {
		return setting, nil
	}

	_, err := h.workspaceCache.Get(value)
	if apierror.IsNotFound(err) {
		_, err = h.workspaces.Create(&mgmt.FleetWorkspace{
			ObjectMeta: metav1.ObjectMeta{
				Name: value,
			},
		})
	}

	return setting, err
}

func (h *handle) OnChange(workspace *mgmt.FleetWorkspace, status mgmt.FleetWorkspaceStatus) ([]runtime.Object, mgmt.FleetWorkspaceStatus, error) {
	if workspace.Annotations[managed] == "false" {
		return nil, status, nil
	}

	return []runtime.Object{
		&corev1.Namespace{
			ObjectMeta: metav1.ObjectMeta{
				Name:   workspace.Name,
				Labels: yaml.CleanAnnotationsForExport(workspace.Labels),
			},
		},
	}, status, nil
}

func (h *handle) onFleetObject(obj runtime.Object) error {
	m, err := meta.Accessor(obj)
	if err != nil {
		return err
	}

	_, err = h.workspaceCache.Get(m.GetNamespace())
	if apierror.IsNotFound(err) {
		ns, err := h.namespaceCache.Get(m.GetNamespace())
		if err != nil {
			return err
		}

		_, err = h.workspaces.Create(&mgmt.FleetWorkspace{
			ObjectMeta: metav1.ObjectMeta{
				Name: m.GetNamespace(),
				OwnerReferences: []metav1.OwnerReference{
					{
						APIVersion: "v1",
						Kind:       "Namespace",
						Name:       ns.Name,
						UID:        ns.UID,
					},
				},
				Annotations: map[string]string{
					managed: "false",
				},
			},
			Status: mgmt.FleetWorkspaceStatus{},
		})
		if apierror.IsAlreadyExists(err) {
			return nil
		}
	}

	return err
}
<|endoftext|>


<commit_before>// Copyright 2015-2016 trivago GmbH
//
// 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 tgo

import (
	"fmt"
)

// ErrorStack is a helper to store errors from multiple statements for
// batch handling. Convenience functions to wrap function calls of the
// form func() (<type>, error) do exist for all golang base types.
type ErrorStack struct {
	errors []error
	format ErrorStackFormat
}

type ErrorStackFormat int

const (
	// ErrorStackFormatNumbered formats like "0: error\n..."
	ErrorStackFormatNumbered = ErrorStackFormat(iota)
	// ErrorStackFormatNewline formats like "error\n..."
	ErrorStackFormatNewline = ErrorStackFormat(iota)
	// ErrorStackFormatCSV formats like "error, ..."
	ErrorStackFormatCSV = ErrorStackFormat(iota)
)

// NewErrorStack creates a new error stack
func NewErrorStack() ErrorStack {
	return ErrorStack{
		errors: []error{},
		format: ErrorStackFormatNumbered,
	}
}

// SetFormat set the format used when Error() is called.
func (stack *ErrorStack) SetFormat(format ErrorStackFormat) {
	stack.format = format
}

// Push adds a new error to the top of the error stack.
// Returns if err != nil.
func (stack *ErrorStack) Push(err error) bool {
	if err != nil {
		stack.errors = append(stack.errors, err)
		return true
	}
	return false
}

// Pushf adds a new error message to the top of the error stack
func (stack *ErrorStack) Pushf(message string, args ...interface{}) {
	stack.errors = append(stack.errors, fmt.Errorf(message, args...))
}

// PushAndDescribe behaves like Push but allows to prepend a text before
// the error messages returned by err. The type of err will be lost.
func (stack *ErrorStack) PushAndDescribe(message string, err error) bool {
	if err != nil {
		stack.errors = append(stack.errors, fmt.Errorf(message+" %s", err.Error()))
		return true
	}
	return false
}

// Pop removes an error from the top of the stack and returns it
func (stack *ErrorStack) Pop() error {
	if len(stack.errors) == 0 {
		return nil
	}
	err := stack.errors[len(stack.errors)-1]
	stack.errors = stack.errors[:len(stack.errors)-1]
	return err
}

// Top returns the error on top of the stack (last error pushed)
func (stack ErrorStack) Top() error {
	if len(stack.errors) == 0 {
		return nil
	}
	return stack.errors[len(stack.errors)-1]
}

// Error implements the Error interface
func (stack ErrorStack) Error() string {
	if len(stack.errors) == 0 {
		return ""
	}

	errString := ""
	for idx, err := range stack.errors {
		switch stack.format {
		case ErrorStackFormatNumbered:
			errString = fmt.Sprintf("%s%d: %s\n", errString, idx, err.Error())
		case ErrorStackFormatNewline:
			errString = fmt.Sprintf("%s%s\n", errString, err.Error())
		case ErrorStackFormatCSV:
			errString = fmt.Sprintf("%s%s, ", errString, err.Error())
		}
	}
	return errString
}

// Errors returns all gathered errors as an array
func (stack ErrorStack) Errors() []error {
	return stack.errors
}

// OrNil returns this object or nil of no errors are stored
func (stack *ErrorStack) OrNil() error {
	if len(stack.errors) == 0 {
		return nil
	}
	return stack
}

// Clear removes all errors from the stack
func (stack *ErrorStack) Clear() {
	stack.errors = []error{}
}
<commit_msg>Added Len to errorstack<commit_after>// Copyright 2015-2016 trivago GmbH
//
// 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 tgo

import (
	"fmt"
)

// ErrorStack is a helper to store errors from multiple statements for
// batch handling. Convenience functions to wrap function calls of the
// form func() (<type>, error) do exist for all golang base types.
type ErrorStack struct {
	errors []error
	format ErrorStackFormat
}

type ErrorStackFormat int

const (
	// ErrorStackFormatNumbered formats like "0: error\n..."
	ErrorStackFormatNumbered = ErrorStackFormat(iota)
	// ErrorStackFormatNewline formats like "error\n..."
	ErrorStackFormatNewline = ErrorStackFormat(iota)
	// ErrorStackFormatCSV formats like "error, ..."
	ErrorStackFormatCSV = ErrorStackFormat(iota)
)

// NewErrorStack creates a new error stack
func NewErrorStack() ErrorStack {
	return ErrorStack{
		errors: []error{},
		format: ErrorStackFormatNumbered,
	}
}

// SetFormat set the format used when Error() is called.
func (stack *ErrorStack) SetFormat(format ErrorStackFormat) {
	stack.format = format
}

// Push adds a new error to the top of the error stack.
// Returns if err != nil.
func (stack *ErrorStack) Push(err error) bool {
	if err != nil {
		stack.errors = append(stack.errors, err)
		return true
	}
	return false
}

// Pushf adds a new error message to the top of the error stack
func (stack *ErrorStack) Pushf(message string, args ...interface{}) {
	stack.errors = append(stack.errors, fmt.Errorf(message, args...))
}

// PushAndDescribe behaves like Push but allows to prepend a text before
// the error messages returned by err. The type of err will be lost.
func (stack *ErrorStack) PushAndDescribe(message string, err error) bool {
	if err != nil {
		stack.errors = append(stack.errors, fmt.Errorf(message+" %s", err.Error()))
		return true
	}
	return false
}

// Pop removes an error from the top of the stack and returns it
func (stack *ErrorStack) Pop() error {
	if len(stack.errors) == 0 {
		return nil
	}
	err := stack.errors[len(stack.errors)-1]
	stack.errors = stack.errors[:len(stack.errors)-1]
	return err
}

// Top returns the error on top of the stack (last error pushed)
func (stack ErrorStack) Top() error {
	if len(stack.errors) == 0 {
		return nil
	}
	return stack.errors[len(stack.errors)-1]
}

// Error implements the Error interface
func (stack ErrorStack) Error() string {
	if len(stack.errors) == 0 {
		return ""
	}

	errString := ""
	for idx, err := range stack.errors {
		switch stack.format {
		case ErrorStackFormatNumbered:
			errString = fmt.Sprintf("%s%d: %s\n", errString, idx, err.Error())
		case ErrorStackFormatNewline:
			errString = fmt.Sprintf("%s%s\n", errString, err.Error())
		case ErrorStackFormatCSV:
			errString = fmt.Sprintf("%s%s, ", errString, err.Error())
		}
	}
	return errString
}

// Errors returns all gathered errors as an array
func (stack ErrorStack) Errors() []error {
	return stack.errors
}

// Len returns the number of error on the stack
func (stack ErrorStack) Len() int {
	return len(stack.errors)
}

// OrNil returns this object or nil of no errors are stored
func (stack *ErrorStack) OrNil() error {
	if len(stack.errors) == 0 {
		return nil
	}
	return stack
}

// Clear removes all errors from the stack
func (stack *ErrorStack) Clear() {
	stack.errors = []error{}
}
<|endoftext|>


<commit_before>package integration_test

import (
	"os"
	"path/filepath"

	"github.com/cloudfoundry/libbuildpack/cutlass"

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

var _ = Describe("CF PHP Buildpack", func() {
	var app *cutlass.App
	AfterEach(func() { app = DestroyApp(app) })

	BeforeEach(func() {
		app = cutlass.New(filepath.Join(bpDir, "fixtures", "php_app"))
		app.SetEnv("COMPOSER_GITHUB_OAUTH_TOKEN", os.Getenv("COMPOSER_GITHUB_OAUTH_TOKEN"))
		app.SetEnv("BP_DEBUG", "1")
	})

	It("deploying a basic PHP app", func() {
		PushAppAndConfirm(app)

		By("installs our hard-coded default version of PHP")
		Expect(app.Stdout.String()).To(ContainSubstring("Installing PHP"))
		Expect(app.Stdout.String()).To(ContainSubstring("PHP 7.2"))

		By("does not return the version of PHP in the response headers")
		body, headers, err := app.Get("/", map[string]string{})
		Expect(err).ToNot(HaveOccurred())
		Expect(body).To(ContainSubstring("PHP Version"))
		Expect(headers).ToNot(HaveKey("X-Powered-By"))

		By("does not display a warning message about the php version config")
		Expect(app.Stdout.String()).ToNot(ContainSubstring("WARNING: A version of PHP has been specified in both `composer.json` and `./bp-config/options.json`."))
		Expect(app.Stdout.String()).ToNot(ContainSubstring("WARNING: The version defined in `composer.json` will be used."))

		By("installs the default version of PHP")
		Expect(app.Stdout.String()).To(ContainSubstring(`"update_default_version" is setting [PHP_VERSION]`))

		By("installs the default version of composer")
		Expect(app.Stdout.String()).To(ContainSubstring("DEBUG: default_version_for composer is"))

		if cutlass.Cached && app.Stack == "cflinuxfs2" {
			By("downloads the binaries directly from the buildpack")
			Expect(app.Stdout.String()).To(MatchRegexp(`Downloaded \[file://.*/dependencies/https___buildpacks.cloudfoundry.org_dependencies_php_php-5.6.\d+-linux-x64-[\da-f]+.tgz\] to \[/tmp\]`))
		}
	})

	AssertNoInternetTraffic("php_app")
})
<commit_msg>Update regex to be less stringent on cached download<commit_after>package integration_test

import (
	"os"
	"path/filepath"

	"github.com/cloudfoundry/libbuildpack/cutlass"

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

var _ = Describe("CF PHP Buildpack", func() {
	var app *cutlass.App
	AfterEach(func() { app = DestroyApp(app) })

	BeforeEach(func() {
		app = cutlass.New(filepath.Join(bpDir, "fixtures", "php_app"))
		app.SetEnv("COMPOSER_GITHUB_OAUTH_TOKEN", os.Getenv("COMPOSER_GITHUB_OAUTH_TOKEN"))
		app.SetEnv("BP_DEBUG", "1")
	})

	It("deploying a basic PHP app", func() {
		PushAppAndConfirm(app)

		By("installs our hard-coded default version of PHP")
		Expect(app.Stdout.String()).To(ContainSubstring("Installing PHP"))
		Expect(app.Stdout.String()).To(ContainSubstring("PHP 7.2"))

		By("does not return the version of PHP in the response headers")
		body, headers, err := app.Get("/", map[string]string{})
		Expect(err).ToNot(HaveOccurred())
		Expect(body).To(ContainSubstring("PHP Version"))
		Expect(headers).ToNot(HaveKey("X-Powered-By"))

		By("does not display a warning message about the php version config")
		Expect(app.Stdout.String()).ToNot(ContainSubstring("WARNING: A version of PHP has been specified in both `composer.json` and `./bp-config/options.json`."))
		Expect(app.Stdout.String()).ToNot(ContainSubstring("WARNING: The version defined in `composer.json` will be used."))

		By("installs the default version of PHP")
		Expect(app.Stdout.String()).To(ContainSubstring(`"update_default_version" is setting [PHP_VERSION]`))

		By("installs the default version of composer")
		Expect(app.Stdout.String()).To(ContainSubstring("DEBUG: default_version_for composer is"))

		if cutlass.Cached {
			By("downloads the binaries directly from the buildpack")
			Expect(app.Stdout.String()).To(MatchRegexp(`Downloaded \[file://.*/dependencies/https___buildpacks.cloudfoundry.org_dependencies_php_php.*-linux-x64-.*.tgz\] to \[/tmp\]`))
		}
	})

	AssertNoInternetTraffic("php_app")
})
<|endoftext|>


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

package fuseutil

import (
	"io"
	"sync"

	"golang.org/x/net/context"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseops"
)

// An interface with a method for each op type in the fuseops package. This can
// be used in conjunction with NewFileSystemServer to avoid writing a "dispatch
// loop" that switches on op types, instead receiving typed method calls
// directly.
//
// The FileSystem implementation should not call Op.Respond, instead returning
// the error with which the caller should respond.
//
// See NotImplementedFileSystem for a convenient way to embed default
// implementations for methods you don't care about.
type FileSystem interface {
	LookUpInode(context.Context, *fuseops.LookUpInodeOp) error
	GetInodeAttributes(context.Context, *fuseops.GetInodeAttributesOp) error
	SetInodeAttributes(context.Context, *fuseops.SetInodeAttributesOp) error
	ForgetInode(context.Context, *fuseops.ForgetInodeOp) error
	MkDir(context.Context, *fuseops.MkDirOp) error
	CreateFile(context.Context, *fuseops.CreateFileOp) error
	CreateSymlink(context.Context, *fuseops.CreateSymlinkOp) error
	Rename(context.Context, *fuseops.RenameOp) error
	RmDir(context.Context, *fuseops.RmDirOp) error
	Unlink(context.Context, *fuseops.UnlinkOp) error
	OpenDir(context.Context, *fuseops.OpenDirOp) error
	ReadDir(context.Context, *fuseops.ReadDirOp) error
	ReleaseDirHandle(context.Context, *fuseops.ReleaseDirHandleOp) error
	OpenFile(context.Context, *fuseops.OpenFileOp) error
	ReadFile(context.Context, *fuseops.ReadFileOp) error
	WriteFile(context.Context, *fuseops.WriteFileOp) error
	SyncFile(context.Context, *fuseops.SyncFileOp) error
	FlushFile(context.Context, *fuseops.FlushFileOp) error
	ReleaseFileHandle(context.Context, *fuseops.ReleaseFileHandleOp) error
	ReadSymlink(context.Context, *fuseops.ReadSymlinkOp) error

	// Regard all inodes (including the root inode) as having their lookup counts
	// decremented to zero, and clean up any resources associated with the file
	// system. No further calls to the file system will be made.
	Destroy()
}

// Create a fuse.Server that handles ops by calling the associated FileSystem
// method.Respond with the resulting error. Unsupported ops are responded to
// directly with ENOSYS.
//
// Each call to a FileSystem method is made on its own goroutine, and is free
// to block.
//
// (It is safe to naively process ops concurrently because the kernel
// guarantees to serialize operations that the user expects to happen in order,
// cf. http://goo.gl/jnkHPO, fuse-devel thread "Fuse guarantees on concurrent
// requests").
func NewFileSystemServer(fs FileSystem) fuse.Server {
	return &fileSystemServer{
		fs: fs,
	}
}

type fileSystemServer struct {
	fs          FileSystem
	opsInFlight sync.WaitGroup
}

func (s *fileSystemServer) ServeOps(c *fuse.Connection) {
	// When we are done, we clean up by waiting for all in-flight ops then
	// destroying the file system.
	defer func() {
		s.opsInFlight.Wait()
		s.fs.Destroy()
	}()

	for {
		ctx, op, err := c.ReadOp()
		if err == io.EOF {
			break
		}

		if err != nil {
			panic(err)
		}

		s.opsInFlight.Add(1)
		go s.handleOp(c, ctx, op)
	}
}

func (s *fileSystemServer) handleOp(
	c *fuse.Connection,
	ctx context.Context,
	op fuseops.Op) {
	defer s.opsInFlight.Done()

	// Dispatch to the appropriate method.
	var err error
	switch typed := op.(type) {
	default:
		err = fuse.ENOSYS

	case *fuseops.LookUpInodeOp:
		err = s.fs.LookUpInode(ctx, typed)

	case *fuseops.GetInodeAttributesOp:
		err = s.fs.GetInodeAttributes(ctx, typed)

	case *fuseops.SetInodeAttributesOp:
		err = s.fs.SetInodeAttributes(ctx, typed)

	case *fuseops.ForgetInodeOp:
		err = s.fs.ForgetInode(ctx, typed)

	case *fuseops.MkDirOp:
		err = s.fs.MkDir(ctx, typed)

	case *fuseops.CreateFileOp:
		err = s.fs.CreateFile(ctx, typed)

	case *fuseops.CreateSymlinkOp:
		err = s.fs.CreateSymlink(ctx, typed)

	case *fuseops.RenameOp:
		err = s.fs.Rename(ctx, typed)

	case *fuseops.RmDirOp:
		err = s.fs.RmDir(ctx, typed)

	case *fuseops.UnlinkOp:
		err = s.fs.Unlink(ctx, typed)

	case *fuseops.OpenDirOp:
		err = s.fs.OpenDir(ctx, typed)

	case *fuseops.ReadDirOp:
		err = s.fs.ReadDir(ctx, typed)

	case *fuseops.ReleaseDirHandleOp:
		err = s.fs.ReleaseDirHandle(ctx, typed)

	case *fuseops.OpenFileOp:
		err = s.fs.OpenFile(ctx, typed)

	case *fuseops.ReadFileOp:
		err = s.fs.ReadFile(ctx, typed)

	case *fuseops.WriteFileOp:
		err = s.fs.WriteFile(ctx, typed)

	case *fuseops.SyncFileOp:
		err = s.fs.SyncFile(ctx, typed)

	case *fuseops.FlushFileOp:
		err = s.fs.FlushFile(ctx, typed)

	case *fuseops.ReleaseFileHandleOp:
		err = s.fs.ReleaseFileHandle(ctx, typed)

	case *fuseops.ReadSymlinkOp:
		err = s.fs.ReadSymlink(ctx, typed)
	}

	c.Reply(ctx, err)
}
<commit_msg>Fixed package fuse.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package fuseutil

import (
	"io"
	"sync"

	"golang.org/x/net/context"

	"github.com/jacobsa/fuse"
	"github.com/jacobsa/fuse/fuseops"
)

// An interface with a method for each op type in the fuseops package. This can
// be used in conjunction with NewFileSystemServer to avoid writing a "dispatch
// loop" that switches on op types, instead receiving typed method calls
// directly.
//
// The FileSystem implementation should not call Connection.Reply, instead
// returning the error with which the caller should respond.
//
// See NotImplementedFileSystem for a convenient way to embed default
// implementations for methods you don't care about.
type FileSystem interface {
	LookUpInode(context.Context, *fuseops.LookUpInodeOp) error
	GetInodeAttributes(context.Context, *fuseops.GetInodeAttributesOp) error
	SetInodeAttributes(context.Context, *fuseops.SetInodeAttributesOp) error
	ForgetInode(context.Context, *fuseops.ForgetInodeOp) error
	MkDir(context.Context, *fuseops.MkDirOp) error
	CreateFile(context.Context, *fuseops.CreateFileOp) error
	CreateSymlink(context.Context, *fuseops.CreateSymlinkOp) error
	Rename(context.Context, *fuseops.RenameOp) error
	RmDir(context.Context, *fuseops.RmDirOp) error
	Unlink(context.Context, *fuseops.UnlinkOp) error
	OpenDir(context.Context, *fuseops.OpenDirOp) error
	ReadDir(context.Context, *fuseops.ReadDirOp) error
	ReleaseDirHandle(context.Context, *fuseops.ReleaseDirHandleOp) error
	OpenFile(context.Context, *fuseops.OpenFileOp) error
	ReadFile(context.Context, *fuseops.ReadFileOp) error
	WriteFile(context.Context, *fuseops.WriteFileOp) error
	SyncFile(context.Context, *fuseops.SyncFileOp) error
	FlushFile(context.Context, *fuseops.FlushFileOp) error
	ReleaseFileHandle(context.Context, *fuseops.ReleaseFileHandleOp) error
	ReadSymlink(context.Context, *fuseops.ReadSymlinkOp) error

	// Regard all inodes (including the root inode) as having their lookup counts
	// decremented to zero, and clean up any resources associated with the file
	// system. No further calls to the file system will be made.
	Destroy()
}

// Create a fuse.Server that handles ops by calling the associated FileSystem
// method.Respond with the resulting error. Unsupported ops are responded to
// directly with ENOSYS.
//
// Each call to a FileSystem method is made on its own goroutine, and is free
// to block.
//
// (It is safe to naively process ops concurrently because the kernel
// guarantees to serialize operations that the user expects to happen in order,
// cf. http://goo.gl/jnkHPO, fuse-devel thread "Fuse guarantees on concurrent
// requests").
func NewFileSystemServer(fs FileSystem) fuse.Server {
	return &fileSystemServer{
		fs: fs,
	}
}

type fileSystemServer struct {
	fs          FileSystem
	opsInFlight sync.WaitGroup
}

func (s *fileSystemServer) ServeOps(c *fuse.Connection) {
	// When we are done, we clean up by waiting for all in-flight ops then
	// destroying the file system.
	defer func() {
		s.opsInFlight.Wait()
		s.fs.Destroy()
	}()

	for {
		ctx, op, err := c.ReadOp()
		if err == io.EOF {
			break
		}

		if err != nil {
			panic(err)
		}

		s.opsInFlight.Add(1)
		go s.handleOp(c, ctx, op)
	}
}

func (s *fileSystemServer) handleOp(
	c *fuse.Connection,
	ctx context.Context,
	op interface{}) {
	defer s.opsInFlight.Done()

	// Dispatch to the appropriate method.
	var err error
	switch typed := op.(type) {
	default:
		err = fuse.ENOSYS

	case *fuseops.LookUpInodeOp:
		err = s.fs.LookUpInode(ctx, typed)

	case *fuseops.GetInodeAttributesOp:
		err = s.fs.GetInodeAttributes(ctx, typed)

	case *fuseops.SetInodeAttributesOp:
		err = s.fs.SetInodeAttributes(ctx, typed)

	case *fuseops.ForgetInodeOp:
		err = s.fs.ForgetInode(ctx, typed)

	case *fuseops.MkDirOp:
		err = s.fs.MkDir(ctx, typed)

	case *fuseops.CreateFileOp:
		err = s.fs.CreateFile(ctx, typed)

	case *fuseops.CreateSymlinkOp:
		err = s.fs.CreateSymlink(ctx, typed)

	case *fuseops.RenameOp:
		err = s.fs.Rename(ctx, typed)

	case *fuseops.RmDirOp:
		err = s.fs.RmDir(ctx, typed)

	case *fuseops.UnlinkOp:
		err = s.fs.Unlink(ctx, typed)

	case *fuseops.OpenDirOp:
		err = s.fs.OpenDir(ctx, typed)

	case *fuseops.ReadDirOp:
		err = s.fs.ReadDir(ctx, typed)

	case *fuseops.ReleaseDirHandleOp:
		err = s.fs.ReleaseDirHandle(ctx, typed)

	case *fuseops.OpenFileOp:
		err = s.fs.OpenFile(ctx, typed)

	case *fuseops.ReadFileOp:
		err = s.fs.ReadFile(ctx, typed)

	case *fuseops.WriteFileOp:
		err = s.fs.WriteFile(ctx, typed)

	case *fuseops.SyncFileOp:
		err = s.fs.SyncFile(ctx, typed)

	case *fuseops.FlushFileOp:
		err = s.fs.FlushFile(ctx, typed)

	case *fuseops.ReleaseFileHandleOp:
		err = s.fs.ReleaseFileHandle(ctx, typed)

	case *fuseops.ReadSymlinkOp:
		err = s.fs.ReadSymlink(ctx, typed)
	}

	c.Reply(ctx, err)
}
<|endoftext|>


<commit_before>// Copyright William Schwartz 2014. All rights reserved.

// Package pigosat is a Go binding for the PicoSAT satisfiability solver.
package pigosat

// To build the PicoSAT dependency, run
//     $ cd picosat; make picosat.o
// No need to run picosat/configure.

// #cgo CFLAGS:-I picosat
// #cgo LDFLAGS: -l picosat.o -L picosat
// #include "picosat.h"
import "C"
import "time"
import "fmt"

// Note: Any comment that is in the /**/ style is (at least mostly) copied
// directly from version 957 of picosat.h.

// Return values for Picosat.Solve's status.
const (
	// NotReady is a solver status only used in PiGoSAT and it means the
	// underlying data structures of the solver have not been initialized or
	// their memory was previously freed.
	NotReady = -1
	// PicoSAT cannot determine the satisfiability of the formula.
	Unknown = 0
	// The formula is satisfiable.
	Satisfiable = 10
	// The formula cannot be satisfied.
	Unsatisfiable = 20
)

// Struct Picosat must be created with NewPicosat and destroyed with DelPicosat.
type Picosat struct {
	// Pointer to the underlying C struct.
	p *C.PicoSAT
}

// NewPicosat returns a new Picosat instance, ready to have literals added to
// it. Set propogation_limit to a positive value to limit how long the solver
// tries to find a solution.
func NewPicosat(propagation_limit uint64) *Picosat {
	// PicoSAT * picosat_init (void);
	p := C.picosat_init()
	// void picosat_set_propagation_limit (PicoSAT *, unsigned long long limit);
	// Must be called after init, before solve, so we do it in the constructor.
	if propagation_limit > 0 {
		C.picosat_set_propagation_limit(p, C.ulonglong(propagation_limit))
	}
	return &Picosat{p: p}
}

// DelPicosat must be called on every Picosat instance before each goes out of
// scope or the program ends, or else the program will leak memory. Once
// DelPicosat has been called on an instance, it cannot be used again.
func (p *Picosat) Delete() {
	if p == nil || p.p == nil {
		return
	}
	// void picosat_reset (PicoSAT *);
	C.picosat_reset(p.p)
	p.p = nil
}

// Variables returns the number of variables in the formula: The m in the DIMACS
// header "p cnf <m> n".
func (p *Picosat) Variables() int {
	if p == nil || p.p == nil {
		return 0
	}
	// int picosat_variables (PicoSAT *);
	return int(C.picosat_variables(p.p))
}

// AddedOriginalClauses returns the number of clauses in the formula: The n in
// the DIMACS header "p cnf m <n>".
func (p *Picosat) AddedOriginalClauses() int {
	if p == nil || p.p == nil {
		return 0
	}
	// int picosat_added_original_clauses (PicoSAT *);
	return int(C.picosat_added_original_clauses(p.p))
}

// Seconds returns the time spent in the PicoSAT library.
func (p *Picosat) Seconds() time.Duration {
	if p == nil || p.p == nil {
		return 0
	}
	// double picosat_seconds (PicoSAT *);
	return time.Duration(float64(C.picosat_seconds(p.p)) * float64(time.Second))
}

// AddClauses adds a list (as a slice) of clauses (the sub-slices). Each clause
// is a list of integers called literals. The absolute value of the literal i is
// the subscript for some variable x_i. If the literal is positive, x_i must end
// up being true when the formula is solved. If the literal is negative, it must
// end up false. Each clause ORs the literals together. All the clauses are
// ANDed together. Literals cannot be zero: a zero in the middle of a slice ends
// the clause, and causes AddClauses to skip reading the rest of the slice. Nil
// slices are ignored and skipped.
func (p *Picosat) AddClauses(clauses [][]int32) {
	if p == nil || p.p == nil {
		return
	}
	var had0 bool
	for _, clause := range clauses {
		if len(clause) == 0 {
			continue
		}
		had0 = false
		for _, lit := range clause {
			// int picosat_add (PicoSAT *, int lit);
			C.picosat_add(p.p, C.int(lit))
			if lit == 0 {
				had0 = true
				break
			}
		}
		if !had0 {
			C.picosat_add(p.p, 0)
		}
	}
}

// Solve the formula and return the status of the solution: one of the constants
// Unsatisfiable, Satisfiable, or Unknown. If satisfiable, return a slice
// indexed by the variables in the formula (so the first element is always
// false).
func (p *Picosat) Solve() (status int, solution []bool) {
	if p == nil || p.p == nil {
		return NotReady, nil
	}
	// int picosat_sat (PicoSAT *, int decision_limit);
	status = int(C.picosat_sat(p.p, -1))
	if status == Unsatisfiable || status == Unknown {
		return
	} else if status != Satisfiable {
		panic(fmt.Errorf("Unknown sat status: %d", status))
	}
	n := p.Variables()
	solution = make([]bool, n+1)
	for i := 1; i <= n; i++ {
		// int picosat_deref (PicoSAT *, int lit);
		if val := C.picosat_deref(p.p, C.int(i)); val > 0 {
			solution[i] = true
		} else if val < 0 {
			solution[i] = false
		} else {
			panic(fmt.Errorf("Variable %d was assigned value 0", i))
		}
	}
	return
}
<commit_msg>Remove note about where nonexistent /**/-style comments come from<commit_after>// Copyright William Schwartz 2014. All rights reserved.

// Package pigosat is a Go binding for the PicoSAT satisfiability solver.
package pigosat

// To build the PicoSAT dependency, run
//     $ cd picosat; make picosat.o
// No need to run picosat/configure.

// #cgo CFLAGS:-I picosat
// #cgo LDFLAGS: -l picosat.o -L picosat
// #include "picosat.h"
import "C"
import "time"
import "fmt"

// Return values for Picosat.Solve's status.
const (
	// NotReady is a solver status only used in PiGoSAT and it means the
	// underlying data structures of the solver have not been initialized or
	// their memory was previously freed.
	NotReady = -1
	// PicoSAT cannot determine the satisfiability of the formula.
	Unknown = 0
	// The formula is satisfiable.
	Satisfiable = 10
	// The formula cannot be satisfied.
	Unsatisfiable = 20
)

// Struct Picosat must be created with NewPicosat and destroyed with DelPicosat.
type Picosat struct {
	// Pointer to the underlying C struct.
	p *C.PicoSAT
}

// NewPicosat returns a new Picosat instance, ready to have literals added to
// it. Set propogation_limit to a positive value to limit how long the solver
// tries to find a solution.
func NewPicosat(propagation_limit uint64) *Picosat {
	// PicoSAT * picosat_init (void);
	p := C.picosat_init()
	// void picosat_set_propagation_limit (PicoSAT *, unsigned long long limit);
	// Must be called after init, before solve, so we do it in the constructor.
	if propagation_limit > 0 {
		C.picosat_set_propagation_limit(p, C.ulonglong(propagation_limit))
	}
	return &Picosat{p: p}
}

// DelPicosat must be called on every Picosat instance before each goes out of
// scope or the program ends, or else the program will leak memory. Once
// DelPicosat has been called on an instance, it cannot be used again.
func (p *Picosat) Delete() {
	if p == nil || p.p == nil {
		return
	}
	// void picosat_reset (PicoSAT *);
	C.picosat_reset(p.p)
	p.p = nil
}

// Variables returns the number of variables in the formula: The m in the DIMACS
// header "p cnf <m> n".
func (p *Picosat) Variables() int {
	if p == nil || p.p == nil {
		return 0
	}
	// int picosat_variables (PicoSAT *);
	return int(C.picosat_variables(p.p))
}

// AddedOriginalClauses returns the number of clauses in the formula: The n in
// the DIMACS header "p cnf m <n>".
func (p *Picosat) AddedOriginalClauses() int {
	if p == nil || p.p == nil {
		return 0
	}
	// int picosat_added_original_clauses (PicoSAT *);
	return int(C.picosat_added_original_clauses(p.p))
}

// Seconds returns the time spent in the PicoSAT library.
func (p *Picosat) Seconds() time.Duration {
	if p == nil || p.p == nil {
		return 0
	}
	// double picosat_seconds (PicoSAT *);
	return time.Duration(float64(C.picosat_seconds(p.p)) * float64(time.Second))
}

// AddClauses adds a list (as a slice) of clauses (the sub-slices). Each clause
// is a list of integers called literals. The absolute value of the literal i is
// the subscript for some variable x_i. If the literal is positive, x_i must end
// up being true when the formula is solved. If the literal is negative, it must
// end up false. Each clause ORs the literals together. All the clauses are
// ANDed together. Literals cannot be zero: a zero in the middle of a slice ends
// the clause, and causes AddClauses to skip reading the rest of the slice. Nil
// slices are ignored and skipped.
func (p *Picosat) AddClauses(clauses [][]int32) {
	if p == nil || p.p == nil {
		return
	}
	var had0 bool
	for _, clause := range clauses {
		if len(clause) == 0 {
			continue
		}
		had0 = false
		for _, lit := range clause {
			// int picosat_add (PicoSAT *, int lit);
			C.picosat_add(p.p, C.int(lit))
			if lit == 0 {
				had0 = true
				break
			}
		}
		if !had0 {
			C.picosat_add(p.p, 0)
		}
	}
}

// Solve the formula and return the status of the solution: one of the constants
// Unsatisfiable, Satisfiable, or Unknown. If satisfiable, return a slice
// indexed by the variables in the formula (so the first element is always
// false).
func (p *Picosat) Solve() (status int, solution []bool) {
	if p == nil || p.p == nil {
		return NotReady, nil
	}
	// int picosat_sat (PicoSAT *, int decision_limit);
	status = int(C.picosat_sat(p.p, -1))
	if status == Unsatisfiable || status == Unknown {
		return
	} else if status != Satisfiable {
		panic(fmt.Errorf("Unknown sat status: %d", status))
	}
	n := p.Variables()
	solution = make([]bool, n+1)
	for i := 1; i <= n; i++ {
		// int picosat_deref (PicoSAT *, int lit);
		if val := C.picosat_deref(p.p, C.int(i)); val > 0 {
			solution[i] = true
		} else if val < 0 {
			solution[i] = false
		} else {
			panic(fmt.Errorf("Variable %d was assigned value 0", i))
		}
	}
	return
}
<|endoftext|>