<commit_before>package plugins

import (
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os/exec"
	"strings"

	"github.com/belak/irc"
	"github.com/belak/seabird/bot"
	"github.com/belak/seabird/mux"
)

type PastebinPlugin struct {
	Key string
}

func init() {
	bot.RegisterPlugin("net_tools", NewNetToolsPlugin)
}

func NewNetToolsPlugin(b *bot.Bot, m *mux.CommandMux) error {
	p := &PastebinPlugin{}

	b.Config("pastebin", p)

	m.Event("dig", p.Dig)
	m.Event("ping", p.Ping)
	m.Event("traceroute", p.Traceroute)
	m.Event("whois", p.Whois)
	m.Event("dnscheck", p.DnsCheck)

	return nil
}

func (p *PastebinPlugin) Dig(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Domain required")
			return
		}

		addrs, err := net.LookupHost(e.Trailing())
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		if len(addrs) == 0 {
			c.MentionReply(e, "No results found")
			return
		}

		c.MentionReply(e, addrs[0])

		if len(addrs) > 1 {
			for _, addr := range addrs[1:] {
				c.Writef("NOTICE %s :%s", e.Identity.Nick, addr)
			}
		}
	}()
}

func (p *PastebinPlugin) Ping(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Host required")
			return
		}

		out, err := exec.Command("ping", "-c1", e.Trailing()).Output()
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		result := strings.Split(string(out), "\n")[1]
		c.MentionReply(e, result)
	}()
}

func (p *PastebinPlugin) Traceroute(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Host required")
			return
		}

		out, err := exec.Command("traceroute", e.Trailing()).Output()
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		hc := http.Client{}

		form := url.Values{}
		form.Add("api_dev_key", p.Key)
		form.Add("api_option", "paste")
		form.Add("api_paste_code", string(out))
		req, err := http.NewRequest("POST", "http://pastebin.com/api/api_post.php", strings.NewReader(form.Encode()))
		req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

		resp, err := hc.Do(req)
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		c.MentionReply(e, "%s", body)
	}()
}

func (p *PastebinPlugin) Whois(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Domain required")
			return
		}

		out, err := exec.Command("whois", e.Trailing()).Output()
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		hc := http.Client{}

		form := url.Values{}
		form.Add("api_dev_key", p.Key)
		form.Add("api_option", "paste")
		form.Add("api_paste_code", string(out))
		req, err := http.NewRequest("POST", "http://pastebin.com/api/api_post.php", strings.NewReader(form.Encode()))
		req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

		resp, err := hc.Do(req)
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		c.MentionReply(e, "%s", body)
	}()
}

func (p *PastebinPlugin) DnsCheck(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Domain required")
			return
		}

		c.MentionReply(e, "https://www.whatsmydns.net/#A/" + e.Trailing())
	}()
}
<commit_msg>Remove potential panic in Ping<commit_after>package plugins

import (
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"os/exec"
	"strings"

	"github.com/belak/irc"
	"github.com/belak/seabird/bot"
	"github.com/belak/seabird/mux"
)

type PastebinPlugin struct {
	Key string
}

func init() {
	bot.RegisterPlugin("net_tools", NewNetToolsPlugin)
}

func NewNetToolsPlugin(b *bot.Bot, m *mux.CommandMux) error {
	p := &PastebinPlugin{}

	b.Config("pastebin", p)

	m.Event("dig", p.Dig)
	m.Event("ping", p.Ping)
	m.Event("traceroute", p.Traceroute)
	m.Event("whois", p.Whois)
	m.Event("dnscheck", p.DnsCheck)

	return nil
}

func (p *PastebinPlugin) Dig(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Domain required")
			return
		}

		addrs, err := net.LookupHost(e.Trailing())
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		if len(addrs) == 0 {
			c.MentionReply(e, "No results found")
			return
		}

		c.MentionReply(e, addrs[0])

		if len(addrs) > 1 {
			for _, addr := range addrs[1:] {
				c.Writef("NOTICE %s :%s", e.Identity.Nick, addr)
			}
		}
	}()
}

func (p *PastebinPlugin) Ping(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Host required")
			return
		}

		out, err := exec.Command("ping", "-c1", e.Trailing()).Output()
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		arr := strings.Split(string(out), "\n")
		if len(arr) < 2 {
			c.MentionReply(e, "Error retrieving ping results")
			return
		}

		c.MentionReply(e, arr[1])
	}()
}

func (p *PastebinPlugin) Traceroute(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Host required")
			return
		}

		out, err := exec.Command("traceroute", e.Trailing()).Output()
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		hc := http.Client{}

		form := url.Values{}
		form.Add("api_dev_key", p.Key)
		form.Add("api_option", "paste")
		form.Add("api_paste_code", string(out))
		req, err := http.NewRequest("POST", "http://pastebin.com/api/api_post.php", strings.NewReader(form.Encode()))
		req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

		resp, err := hc.Do(req)
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		c.MentionReply(e, "%s", body)
	}()
}

func (p *PastebinPlugin) Whois(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Domain required")
			return
		}

		out, err := exec.Command("whois", e.Trailing()).Output()
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		hc := http.Client{}

		form := url.Values{}
		form.Add("api_dev_key", p.Key)
		form.Add("api_option", "paste")
		form.Add("api_paste_code", string(out))
		req, err := http.NewRequest("POST", "http://pastebin.com/api/api_post.php", strings.NewReader(form.Encode()))
		req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

		resp, err := hc.Do(req)
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}
		defer resp.Body.Close()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			c.MentionReply(e, "%s", err)
			return
		}

		c.MentionReply(e, "%s", body)
	}()
}

func (p *PastebinPlugin) DnsCheck(c *irc.Client, e *irc.Event) {
	go func() {
		if e.Trailing() == "" {
			c.MentionReply(e, "Domain required")
			return
		}

		c.MentionReply(e, "https://www.whatsmydns.net/#A/" + e.Trailing())
	}()
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package simulator

import (
	"fmt"
	"testing"

	. "k8s.io/autoscaler/cluster-autoscaler/utils/test"

	apiv1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/labels"
	schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"

	"github.com/stretchr/testify/assert"
)

var snapshots = map[string]func() ClusterSnapshot{
	"basic": func() ClusterSnapshot { return NewBasicClusterSnapshot() },
	"delta": func() ClusterSnapshot { return NewDeltaClusterSnapshot() },
}

func nodeNames(nodes []*apiv1.Node) []string {
	names := make([]string, len(nodes), len(nodes))
	for i, node := range nodes {
		names[i] = node.Name
	}
	return names
}

func nodeInfoNames(nodeInfos []*schedulernodeinfo.NodeInfo) []string {
	names := make([]string, len(nodeInfos), len(nodeInfos))
	for i, node := range nodeInfos {
		names[i] = node.Node().Name
	}
	return names
}

func nodeInfoPods(nodeInfos []*schedulernodeinfo.NodeInfo) []*apiv1.Pod {
	pods := []*apiv1.Pod{}
	for _, node := range nodeInfos {
		pods = append(pods, node.Pods()...)
	}
	return pods
}

func TestForkAddNode(t *testing.T) {
	nodeCount := 3

	nodes := createTestNodes(nodeCount)
	extraNodes := createTestNodesWithPrefix("tmp", 2)

	for name, snapshotFactory := range snapshots {
		t.Run(fmt.Sprintf("%s: fork should not affect base data: adding nodes", name),
			func(t *testing.T) {
				clusterSnapshot := snapshotFactory()
				err := clusterSnapshot.AddNodes(nodes)
				assert.NoError(t, err)

				err = clusterSnapshot.Fork()
				assert.NoError(t, err)

				for _, node := range extraNodes {
					err = clusterSnapshot.AddNode(node)
					assert.NoError(t, err)
				}
				forkNodes, err := clusterSnapshot.NodeInfos().List()
				assert.NoError(t, err)
				assert.ElementsMatch(t, append(nodeNames(nodes), nodeNames(extraNodes)...), nodeInfoNames(forkNodes))

				err = clusterSnapshot.Revert()
				assert.NoError(t, err)

				baseNodes, err := clusterSnapshot.NodeInfos().List()
				assert.NoError(t, err)
				assert.ElementsMatch(t, nodeNames(nodes), nodeInfoNames(baseNodes))
			})
	}
}

func TestForkAddPods(t *testing.T) {
	nodeCount := 3
	podCount := 90

	nodes := createTestNodes(nodeCount)
	pods := createTestPods(podCount)
	assignPodsToNodes(pods, nodes)

	for name, snapshotFactory := range snapshots {
		t.Run(fmt.Sprintf("%s: fork should not affect base data: adding pods", name),
			func(t *testing.T) {
				clusterSnapshot := snapshotFactory()
				err := clusterSnapshot.AddNodes(nodes)
				assert.NoError(t, err)

				err = clusterSnapshot.Fork()
				assert.NoError(t, err)

				for _, pod := range pods {
					err = clusterSnapshot.AddPod(pod, pod.Spec.NodeName)
					assert.NoError(t, err)
				}
				forkPods, err := clusterSnapshot.Pods().List(labels.Everything())
				assert.NoError(t, err)
				assert.ElementsMatch(t, pods, forkPods)
				forkNodes, err := clusterSnapshot.NodeInfos().List()
				assert.NoError(t, err)
				assert.ElementsMatch(t, nodeNames(nodes), nodeInfoNames(forkNodes))

				err = clusterSnapshot.Revert()
				assert.NoError(t, err)

				basePods, err := clusterSnapshot.Pods().List(labels.Everything())
				assert.NoError(t, err)
				assert.Equal(t, 0, len(basePods))
				baseNodes, err := clusterSnapshot.NodeInfos().List()
				assert.NoError(t, err)
				assert.ElementsMatch(t, nodeNames(nodes), nodeInfoNames(baseNodes))
			})
	}
}

func TestForkRemovePods(t *testing.T) {
	nodeCount := 3
	podCount := 90
	deletedPodCount := 10

	nodes := createTestNodes(nodeCount)
	pods := createTestPods(podCount)
	assignPodsToNodes(pods, nodes)

	for name, snapshotFactory := range snapshots {
		t.Run(fmt.Sprintf("%s: fork should not affect base data: removing pods", name),
			func(t *testing.T) {
				clusterSnapshot := snapshotFactory()
				err := clusterSnapshot.AddNodes(nodes)
				assert.NoError(t, err)

				for _, pod := range pods {
					err = clusterSnapshot.AddPod(pod, pod.Spec.NodeName)
					assert.NoError(t, err)
				}

				err = clusterSnapshot.Fork()
				assert.NoError(t, err)

				for _, pod := range pods[:deletedPodCount] {
					err = clusterSnapshot.RemovePod(pod.Namespace, pod.Name, pod.Spec.NodeName)
					assert.NoError(t, err)
				}

				forkPods, err := clusterSnapshot.Pods().List(labels.Everything())
				assert.NoError(t, err)
				assert.ElementsMatch(t, pods[deletedPodCount:], forkPods)
				forkNodes, err := clusterSnapshot.NodeInfos().List()
				assert.NoError(t, err)
				assert.ElementsMatch(t, nodeNames(nodes), nodeInfoNames(forkNodes))
				assert.ElementsMatch(t, pods[deletedPodCount:], nodeInfoPods(forkNodes))

				err = clusterSnapshot.Revert()
				assert.NoError(t, err)

				basePods, err := clusterSnapshot.Pods().List(labels.Everything())
				assert.NoError(t, err)
				assert.ElementsMatch(t, pods, basePods)
				baseNodes, err := clusterSnapshot.NodeInfos().List()
				assert.NoError(t, err)
				assert.ElementsMatch(t, nodeNames(nodes), nodeInfoNames(baseNodes))
				assert.ElementsMatch(t, pods, nodeInfoPods(baseNodes))
			})
	}
}

func extractNodes(nodeInfos []*schedulernodeinfo.NodeInfo) []*apiv1.Node {
	nodes := []*apiv1.Node{}
	for _, ni := range nodeInfos {
		nodes = append(nodes, ni.Node())
	}
	return nodes
}

func TestReAddNode(t *testing.T) {
	for name, snapshotFactory := range snapshots {
		t.Run(fmt.Sprintf("%s: re-add node", name),
			func(t *testing.T) {
				snapshot := snapshotFactory()

				node := BuildTestNode("node", 10, 100)
				err := snapshot.AddNode(node)
				assert.NoError(t, err)

				err = snapshot.Fork()
				assert.NoError(t, err)

				err = snapshot.RemoveNode("node")
				assert.NoError(t, err)

				err = snapshot.AddNode(node)
				assert.NoError(t, err)

				forkNodes, err := snapshot.NodeInfos().List()
				assert.NoError(t, err)
				assert.ElementsMatch(t, []*apiv1.Node{node}, extractNodes(forkNodes))

				err = snapshot.Commit()
				committedNodes, err := snapshot.NodeInfos().List()
				assert.NoError(t, err)
				assert.ElementsMatch(t, []*apiv1.Node{node}, extractNodes(committedNodes))
			})
	}
}

type snapshotState struct {
	nodes []*apiv1.Node
	pods  []*apiv1.Pod
}

func compareStates(t *testing.T, a, b snapshotState) {
	assert.ElementsMatch(t, a.nodes, b.nodes)
	assert.ElementsMatch(t, a.pods, b.pods)
}

func getSnapshotState(t *testing.T, snapshot ClusterSnapshot) snapshotState {
	nodes, err := snapshot.NodeInfos().List()
	assert.NoError(t, err)
	pods, err := snapshot.Pods().List(labels.Everything())
	assert.NoError(t, err)
	return snapshotState{extractNodes(nodes), pods}
}

func startSnapshot(t *testing.T, snapshotFactory func() ClusterSnapshot, state snapshotState) ClusterSnapshot {
	snapshot := snapshotFactory()
	err := snapshot.AddNodes(state.nodes)
	assert.NoError(t, err)
	for _, pod := range state.pods {
		err := snapshot.AddPod(pod, pod.Spec.NodeName)
		assert.NoError(t, err)
	}
	return snapshot
}

func TestForking(t *testing.T) {
	node := BuildTestNode("specialNode", 10, 100)
	pod := BuildTestPod("specialPod", 1, 1)
	pod.Spec.NodeName = node.Name

	testCases := []struct {
		name          string
		op            func(ClusterSnapshot)
		state         snapshotState
		modifiedState snapshotState
	}{
		{
			name: "add node",
			op: func(snapshot ClusterSnapshot) {
				err := snapshot.AddNode(node)
				assert.NoError(t, err)
			},
			modifiedState: snapshotState{
				nodes: []*apiv1.Node{node},
			},
		},
		{
			name: "remove node",
			state: snapshotState{
				nodes: []*apiv1.Node{node},
			},
			op: func(snapshot ClusterSnapshot) {
				err := snapshot.RemoveNode(node.Name)
				assert.NoError(t, err)
			},
		},
		{
			name: "add pod, then remove node",
			state: snapshotState{
				nodes: []*apiv1.Node{node},
			},
			op: func(snapshot ClusterSnapshot) {
				err := snapshot.AddPod(pod, node.Name)
				assert.NoError(t, err)
				err = snapshot.RemoveNode(node.Name)
				assert.NoError(t, err)
			},
		},
	}

	for name, snapshotFactory := range snapshots {
		for _, tc := range testCases {
			t.Run(fmt.Sprintf("%s: %s base", name, tc.name), func(t *testing.T) {
				snapshot := startSnapshot(t, snapshotFactory, tc.state)
				tc.op(snapshot)

				// Modifications should be applied.
				compareStates(t, tc.modifiedState, getSnapshotState(t, snapshot))
			})
			t.Run(fmt.Sprintf("%s: %s fork", name, tc.name), func(t *testing.T) {
				snapshot := startSnapshot(t, snapshotFactory, tc.state)

				err := snapshot.Fork()
				assert.NoError(t, err)

				tc.op(snapshot)

				// Modifications should be applied.
				compareStates(t, tc.modifiedState, getSnapshotState(t, snapshot))
			})
			t.Run(fmt.Sprintf("%s: %s fork & revert", name, tc.name), func(t *testing.T) {
				snapshot := startSnapshot(t, snapshotFactory, tc.state)

				err := snapshot.Fork()
				assert.NoError(t, err)

				tc.op(snapshot)

				err = snapshot.Revert()
				assert.NoError(t, err)

				// Modifications should no longer be applied.
				compareStates(t, tc.state, getSnapshotState(t, snapshot))
			})
			t.Run(fmt.Sprintf("%s: %s fork & commit", name, tc.name), func(t *testing.T) {
				snapshot := startSnapshot(t, snapshotFactory, tc.state)

				err := snapshot.Fork()
				assert.NoError(t, err)

				tc.op(snapshot)

				err = snapshot.Commit()
				assert.NoError(t, err)

				// Modifications should be applied.
				compareStates(t, tc.modifiedState, getSnapshotState(t, snapshot))
			})
		}
	}
}

func TestNode404(t *testing.T) {
	// Anything and everything that returns errNodeNotFound should be tested here.
	ops := []struct {
		name string
		op   func(ClusterSnapshot) error
	}{
		{"add pod", func(snapshot ClusterSnapshot) error {
			return snapshot.AddPod(BuildTestPod("p1", 0, 0), "node")
		}},
		{"remove pod", func(snapshot ClusterSnapshot) error {
			return snapshot.RemovePod("default", "p1", "node")
		}},
		{"get node", func(snapshot ClusterSnapshot) error {
			_, err := snapshot.NodeInfos().Get("node")
			return err
		}},
		{"remove node", func(snapshot ClusterSnapshot) error {
			return snapshot.RemoveNode("node")
		}},
	}

	for name, snapshotFactory := range snapshots {
		for _, op := range ops {
			t.Run(fmt.Sprintf("%s: %s empty", name, op.name),
				func(t *testing.T) {
					snapshot := snapshotFactory()

					// Empty snapshot - shouldn't be able to operate on nodes that are not here.
					err := op.op(snapshot)
					assert.Error(t, err)
				})

			t.Run(fmt.Sprintf("%s: %s fork", name, op.name),
				func(t *testing.T) {
					snapshot := snapshotFactory()

					node := BuildTestNode("node", 10, 100)
					err := snapshot.AddNode(node)
					assert.NoError(t, err)

					err = snapshot.Fork()
					assert.NoError(t, err)

					err = snapshot.RemoveNode("node")
					assert.NoError(t, err)

					// Node deleted after fork - shouldn't be able to operate on it.
					err = op.op(snapshot)
					assert.Error(t, err)

					err = snapshot.Commit()
					assert.NoError(t, err)

					// Node deleted before commit - shouldn't be able to operate on it.
					err = op.op(snapshot)
					assert.Error(t, err)
				})

			t.Run(fmt.Sprintf("%s: %s base", name, op.name),
				func(t *testing.T) {
					snapshot := snapshotFactory()

					node := BuildTestNode("node", 10, 100)
					err := snapshot.AddNode(node)
					assert.NoError(t, err)

					err = snapshot.RemoveNode("node")
					assert.NoError(t, err)

					// Node deleted from base - shouldn't be able to operate on it.
					err = op.op(snapshot)
					assert.Error(t, err)
				})
		}
	}
}
<commit_msg>clean up snapshot tests<commit_after>/*
Copyright 2020 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package simulator

import (
	"fmt"
	"testing"

	. "k8s.io/autoscaler/cluster-autoscaler/utils/test"

	apiv1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/labels"
	schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"

	"github.com/stretchr/testify/assert"
)

var snapshots = map[string]func() ClusterSnapshot{
	"basic": func() ClusterSnapshot { return NewBasicClusterSnapshot() },
	"delta": func() ClusterSnapshot { return NewDeltaClusterSnapshot() },
}

func nodeNames(nodes []*apiv1.Node) []string {
	names := make([]string, len(nodes), len(nodes))
	for i, node := range nodes {
		names[i] = node.Name
	}
	return names
}

func extractNodes(nodeInfos []*schedulernodeinfo.NodeInfo) []*apiv1.Node {
	nodes := []*apiv1.Node{}
	for _, ni := range nodeInfos {
		nodes = append(nodes, ni.Node())
	}
	return nodes
}

type snapshotState struct {
	nodes []*apiv1.Node
	pods  []*apiv1.Pod
}

func compareStates(t *testing.T, a, b snapshotState) {
	assert.ElementsMatch(t, a.nodes, b.nodes)
	assert.ElementsMatch(t, a.pods, b.pods)
}

func getSnapshotState(t *testing.T, snapshot ClusterSnapshot) snapshotState {
	nodes, err := snapshot.NodeInfos().List()
	assert.NoError(t, err)
	pods, err := snapshot.Pods().List(labels.Everything())
	assert.NoError(t, err)
	return snapshotState{extractNodes(nodes), pods}
}

func startSnapshot(t *testing.T, snapshotFactory func() ClusterSnapshot, state snapshotState) ClusterSnapshot {
	snapshot := snapshotFactory()
	err := snapshot.AddNodes(state.nodes)
	assert.NoError(t, err)
	for _, pod := range state.pods {
		err := snapshot.AddPod(pod, pod.Spec.NodeName)
		assert.NoError(t, err)
	}
	return snapshot
}

func TestForking(t *testing.T) {
	node := BuildTestNode("specialNode", 10, 100)
	pod := BuildTestPod("specialPod", 1, 1)
	pod.Spec.NodeName = node.Name

	testCases := []struct {
		name          string
		op            func(ClusterSnapshot)
		state         snapshotState
		modifiedState snapshotState
	}{
		{
			name: "add node",
			op: func(snapshot ClusterSnapshot) {
				err := snapshot.AddNode(node)
				assert.NoError(t, err)
			},
			modifiedState: snapshotState{
				nodes: []*apiv1.Node{node},
			},
		},
		{
			name: "remove node",
			state: snapshotState{
				nodes: []*apiv1.Node{node},
			},
			op: func(snapshot ClusterSnapshot) {
				err := snapshot.RemoveNode(node.Name)
				assert.NoError(t, err)
			},
		},
		{
			name: "remove node, then add it back",
			state: snapshotState{
				nodes: []*apiv1.Node{node},
			},
			op: func(snapshot ClusterSnapshot) {
				err := snapshot.RemoveNode(node.Name)
				assert.NoError(t, err)

				err = snapshot.AddNode(node)
				assert.NoError(t, err)
			},
			modifiedState: snapshotState{
				nodes: []*apiv1.Node{node},
			},
		},
		{
			name: "add pod, then remove node",
			state: snapshotState{
				nodes: []*apiv1.Node{node},
			},
			op: func(snapshot ClusterSnapshot) {
				err := snapshot.AddPod(pod, node.Name)
				assert.NoError(t, err)
				err = snapshot.RemoveNode(node.Name)
				assert.NoError(t, err)
			},
		},
	}

	for name, snapshotFactory := range snapshots {
		for _, tc := range testCases {
			t.Run(fmt.Sprintf("%s: %s base", name, tc.name), func(t *testing.T) {
				snapshot := startSnapshot(t, snapshotFactory, tc.state)
				tc.op(snapshot)

				// Modifications should be applied.
				compareStates(t, tc.modifiedState, getSnapshotState(t, snapshot))
			})
			t.Run(fmt.Sprintf("%s: %s fork", name, tc.name), func(t *testing.T) {
				snapshot := startSnapshot(t, snapshotFactory, tc.state)

				err := snapshot.Fork()
				assert.NoError(t, err)

				tc.op(snapshot)

				// Modifications should be applied.
				compareStates(t, tc.modifiedState, getSnapshotState(t, snapshot))
			})
			t.Run(fmt.Sprintf("%s: %s fork & revert", name, tc.name), func(t *testing.T) {
				snapshot := startSnapshot(t, snapshotFactory, tc.state)

				err := snapshot.Fork()
				assert.NoError(t, err)

				tc.op(snapshot)

				err = snapshot.Revert()
				assert.NoError(t, err)

				// Modifications should no longer be applied.
				compareStates(t, tc.state, getSnapshotState(t, snapshot))
			})
			t.Run(fmt.Sprintf("%s: %s fork & commit", name, tc.name), func(t *testing.T) {
				snapshot := startSnapshot(t, snapshotFactory, tc.state)

				err := snapshot.Fork()
				assert.NoError(t, err)

				tc.op(snapshot)

				err = snapshot.Commit()
				assert.NoError(t, err)

				// Modifications should be applied.
				compareStates(t, tc.modifiedState, getSnapshotState(t, snapshot))
			})
		}
	}
}

func TestNode404(t *testing.T) {
	// Anything and everything that returns errNodeNotFound should be tested here.
	ops := []struct {
		name string
		op   func(ClusterSnapshot) error
	}{
		{"add pod", func(snapshot ClusterSnapshot) error {
			return snapshot.AddPod(BuildTestPod("p1", 0, 0), "node")
		}},
		{"remove pod", func(snapshot ClusterSnapshot) error {
			return snapshot.RemovePod("default", "p1", "node")
		}},
		{"get node", func(snapshot ClusterSnapshot) error {
			_, err := snapshot.NodeInfos().Get("node")
			return err
		}},
		{"remove node", func(snapshot ClusterSnapshot) error {
			return snapshot.RemoveNode("node")
		}},
	}

	for name, snapshotFactory := range snapshots {
		for _, op := range ops {
			t.Run(fmt.Sprintf("%s: %s empty", name, op.name),
				func(t *testing.T) {
					snapshot := snapshotFactory()

					// Empty snapshot - shouldn't be able to operate on nodes that are not here.
					err := op.op(snapshot)
					assert.Error(t, err)
				})

			t.Run(fmt.Sprintf("%s: %s fork", name, op.name),
				func(t *testing.T) {
					snapshot := snapshotFactory()

					node := BuildTestNode("node", 10, 100)
					err := snapshot.AddNode(node)
					assert.NoError(t, err)

					err = snapshot.Fork()
					assert.NoError(t, err)

					err = snapshot.RemoveNode("node")
					assert.NoError(t, err)

					// Node deleted after fork - shouldn't be able to operate on it.
					err = op.op(snapshot)
					assert.Error(t, err)

					err = snapshot.Commit()
					assert.NoError(t, err)

					// Node deleted before commit - shouldn't be able to operate on it.
					err = op.op(snapshot)
					assert.Error(t, err)
				})

			t.Run(fmt.Sprintf("%s: %s base", name, op.name),
				func(t *testing.T) {
					snapshot := snapshotFactory()

					node := BuildTestNode("node", 10, 100)
					err := snapshot.AddNode(node)
					assert.NoError(t, err)

					err = snapshot.RemoveNode("node")
					assert.NoError(t, err)

					// Node deleted from base - shouldn't be able to operate on it.
					err = op.op(snapshot)
					assert.Error(t, err)
				})
		}
	}
}
<|endoftext|>


<commit_before>package adjust

import (
	"image"
	"image/color"

	"github.com/anthonynsimon/bild/clone"
	"github.com/anthonynsimon/bild/parallel"
)

// Apply returns a copy of the provided image after applying the provided color function to each pixel.
func Apply(img image.Image, fn func(color.RGBA) color.RGBA) *image.RGBA {
	bounds := img.Bounds()
	dst := clone.AsRGBA(img)
	w, h := bounds.Dx(), bounds.Dy()

	parallel.Line(h, func(start, end int) {
		for y := start; y < end; y++ {
			for x := 0; x < w; x++ {
				dstPos := y*dst.Stride + x*4

				c := color.RGBA{}

				c.R = dst.Pix[dstPos+0]
				c.G = dst.Pix[dstPos+1]
				c.B = dst.Pix[dstPos+2]
				c.A = dst.Pix[dstPos+3]

				c = fn(c)

				dst.Pix[dstPos+0] = c.R
				dst.Pix[dstPos+1] = c.G
				dst.Pix[dstPos+2] = c.B
				dst.Pix[dstPos+3] = c.A
			}
		}
	})

	return dst
}
<commit_msg>feat: improve adjust apply<commit_after>package adjust

import (
	"image"
	"image/color"

	"github.com/anthonynsimon/bild/clone"
	"github.com/anthonynsimon/bild/parallel"
)

// Apply returns a copy of the provided image after applying the provided color function to each pixel.
func Apply(img image.Image, fn func(color.RGBA) color.RGBA) *image.RGBA {
	bounds := img.Bounds()
	dst := clone.AsRGBA(img)
	w, h := bounds.Dx(), bounds.Dy()

	parallel.Line(h, func(start, end int) {
		for y := start; y < end; y++ {
			for x := 0; x < w; x++ {
				dstPos := y*dst.Stride + x*4

				c := color.RGBA{}

				dr := &dst.Pix[dstPos+0]
				dg := &dst.Pix[dstPos+1]
				db := &dst.Pix[dstPos+2]
				da := &dst.Pix[dstPos+3]

				c.R = *dr
				c.G = *dg
				c.B = *db
				c.A = *da

				c = fn(c)

				*dr = c.R
				*dg = c.G
				*db = c.B
				*da = c.A
			}
		}
	})

	return dst
}
<|endoftext|>


<commit_before>package http_util

import (
	"fmt"
	"log"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"sync"
	"time"
)

var Get func(string, http.Header, time.Duration) (*http.Response, error) = get

func get(url_ string, header http.Header, timeout time.Duration) (*http.Response, error) {
	for i := 0; i < 10; i += 1 {
		client := http.Client{CheckRedirect: CheckRedirect}
		client.Timeout = timeout
		req, err := http.NewRequest("GET", url_, nil)
		if err != nil {
			return nil, err
		}
		// log.Printf("url: %v\n\n", req.URL)
		req.Header = header
		resp, err := client.Do(req)
		// log.Print(resp.Header)
		if err != nil {
			switch err.(*url.Error).Err.(type) {
			case RedirectError:
				tmp, err := resp.Location()
				if err != nil {
					return nil, err
				}
				url_ = tmp.String()
				continue
			default:
				return nil, err
			}
		} else {
			return resp, err
		}
	}
	return nil, fmt.Errorf("unknow error")
}

func RangeGet(req Request, start, length int64, out chan<- []byte) {
	header := http.Header{}
	for k, vs := range req.header {
		for _, v := range vs {
			header.Add(k, v)
		}
	}
	last_downloaded_block_time := GetNowEpochInSecond()
	header.Add("Range", fmt.Sprintf("bytes=%d-", start))
	resp, err := get(req.url, header, 0)
	mutex := sync.Mutex{}
	finished := false
	defer func() {
		mutex.Lock()
		finished = true
		mutex.Unlock()
	}()
	go func() {
		for {
			time.Sleep(TimeoutOfPerBlockDownload)
			mutex.Lock()
			if finished {
				mutex.Unlock()
				return
			}
			now := GetNowEpochInSecond()
			if time.Second*time.Duration(now-last_downloaded_block_time) > TimeoutOfPerBlockDownload {
				log.Print("timeout")
				resp.Body.Close()
				break
			}
			mutex.Unlock()
		}
	}()
	if err != nil {
		close(out)
		return
	}
	defer func() {
		resp.Body.Close()
	}()
	if resp.Header.Get("Content-Range") == "" {
		close(out)
		return
	}
	// if resp.StatusCode != 206 {
	// 	close(out)
	// 	return
	// }
	buf := make([]byte, BlockSize)
	var downloaded int64 = 0
	base := 0
	for {
		n, err := resp.Body.Read(buf[base:])
		downloaded += int64(n)
		base += n
		if err != nil {
			log.Print(err)
			out <- buf[:base]
			close(out)
			return
		} else {
			if downloaded >= length {
				out <- buf[:base-int(downloaded-length)]
				mutex.Lock()
				last_downloaded_block_time = GetNowEpochInSecond()
				mutex.Unlock()
				close(out)
				return
			}
			if int64(base) >= BlockSize {
				out <- buf[:base]
				mutex.Lock()
				last_downloaded_block_time = GetNowEpochInSecond()
				mutex.Unlock()
				buf = make([]byte, BlockSize)
				base = 0
			}
		}
	}
}

func get_content_length(header http.Header) (rv int64, err error) {
	defer func() {
		if x := recover(); x != nil {
			err = fmt.Errorf("can't get content length, Content-Length : %v", header["Content-Length"])
		}
	}()
	rv, err = strconv.ParseInt(header["Content-Length"][0], 10, 64)
	return rv, err
}
func get_attchment_filename(header http.Header) (fn string, err error) {
	content_disposition := header["Content-Disposition"]
	if len(content_disposition) != 1 {
		return "", fmt.Errorf("wrong Content-Disposition :%v", content_disposition)
	}
	re := regexp.MustCompile(`filename=?(.+)?`)
	tmp := re.FindAllStringSubmatch(content_disposition[0], 1)
	if len(tmp) != 1 || len(tmp[0]) != 2 {
		return "", fmt.Errorf("wrong Content-Disposition :%v", content_disposition)
	}
	fn = tmp[0][1]
	re = regexp.MustCompile("/|\x00")
	fn = re.ReplaceAllString(fn, " ")
	re = regexp.MustCompile("\"|'")
	fn = re.ReplaceAllString(fn, "")
	return
}
func GetResourceInfo(url_ string, header http.Header) (resource_info ResourceInfo, err error) {
	for i := 0; i < 3; i++ {
		var resp *http.Response
		resp, err = get(url_, header, TimeoutOfGetResourceInfo)
		if err != nil {
			if i < 2 {
				time.Sleep(time.Duration(10+30*i) * time.Second)
				continue
			}
			return
		}
		defer resp.Body.Close()
		resource_info.length, err = get_content_length(resp.Header)
		if err != nil {
			return
		}
		resource_info.filename, err = get_attchment_filename(resp.Header)
		if err != nil {
			return
		}
		return
	}
	return
}

func ConvertWaitGroupToBoolChan(wg *sync.WaitGroup, c chan<- bool) {
	wg.Wait()
	c <- true
}

func GetNowEpochInMilli() int64 {
	now := time.Now()
	return now.UnixNano() / 1000000
}
func GetNowEpochInSecond() int64 {
	now := time.Now()
	return now.UnixNano() / 1000000000
}
<commit_msg>unescape filename<commit_after>package http_util

import (
	"fmt"
	"log"
	"net/http"
	"net/url"
	"regexp"
	"strconv"
	"sync"
	"time"
)

var Get func(string, http.Header, time.Duration) (*http.Response, error) = get

func get(url_ string, header http.Header, timeout time.Duration) (*http.Response, error) {
	for i := 0; i < 10; i += 1 {
		client := http.Client{CheckRedirect: CheckRedirect}
		client.Timeout = timeout
		req, err := http.NewRequest("GET", url_, nil)
		if err != nil {
			return nil, err
		}
		// log.Printf("url: %v\n\n", req.URL)
		req.Header = header
		resp, err := client.Do(req)
		// log.Print(resp.Header)
		if err != nil {
			switch err.(*url.Error).Err.(type) {
			case RedirectError:
				tmp, err := resp.Location()
				if err != nil {
					return nil, err
				}
				url_ = tmp.String()
				continue
			default:
				return nil, err
			}
		} else {
			return resp, err
		}
	}
	return nil, fmt.Errorf("unknow error")
}

func RangeGet(req Request, start, length int64, out chan<- []byte) {
	header := http.Header{}
	for k, vs := range req.header {
		for _, v := range vs {
			header.Add(k, v)
		}
	}
	last_downloaded_block_time := GetNowEpochInSecond()
	header.Add("Range", fmt.Sprintf("bytes=%d-", start))
	resp, err := get(req.url, header, 0)
	mutex := sync.Mutex{}
	finished := false
	defer func() {
		mutex.Lock()
		finished = true
		mutex.Unlock()
	}()
	go func() {
		for {
			time.Sleep(TimeoutOfPerBlockDownload)
			mutex.Lock()
			if finished {
				mutex.Unlock()
				return
			}
			now := GetNowEpochInSecond()
			if time.Second*time.Duration(now-last_downloaded_block_time) > TimeoutOfPerBlockDownload {
				log.Print("timeout")
				resp.Body.Close()
				break
			}
			mutex.Unlock()
		}
	}()
	if err != nil {
		close(out)
		return
	}
	defer func() {
		resp.Body.Close()
	}()
	if resp.Header.Get("Content-Range") == "" {
		close(out)
		return
	}
	// if resp.StatusCode != 206 {
	// 	close(out)
	// 	return
	// }
	buf := make([]byte, BlockSize)
	var downloaded int64 = 0
	base := 0
	for {
		n, err := resp.Body.Read(buf[base:])
		downloaded += int64(n)
		base += n
		if err != nil {
			log.Print(err)
			out <- buf[:base]
			close(out)
			return
		} else {
			if downloaded >= length {
				out <- buf[:base-int(downloaded-length)]
				mutex.Lock()
				last_downloaded_block_time = GetNowEpochInSecond()
				mutex.Unlock()
				close(out)
				return
			}
			if int64(base) >= BlockSize {
				out <- buf[:base]
				mutex.Lock()
				last_downloaded_block_time = GetNowEpochInSecond()
				mutex.Unlock()
				buf = make([]byte, BlockSize)
				base = 0
			}
		}
	}
}

func get_content_length(header http.Header) (rv int64, err error) {
	defer func() {
		if x := recover(); x != nil {
			err = fmt.Errorf("can't get content length, Content-Length : %v", header["Content-Length"])
		}
	}()
	rv, err = strconv.ParseInt(header["Content-Length"][0], 10, 64)
	return rv, err
}
func get_attchment_filename(header http.Header) (fn string, err error) {
	content_disposition := header["Content-Disposition"]
	if len(content_disposition) != 1 {
		return "", fmt.Errorf("wrong Content-Disposition :%v", content_disposition)
	}
	re := regexp.MustCompile(`filename=?(.+)?`)
	tmp := re.FindAllStringSubmatch(content_disposition[0], 1)
	if len(tmp) != 1 || len(tmp[0]) != 2 {
		return "", fmt.Errorf("wrong Content-Disposition :%v", content_disposition)
	}
	fn = tmp[0][1]
	fn, err = url.QueryUnescape(fn)
	if err != nil {
		return
	}
	re = regexp.MustCompile("/|\x00")
	fn = re.ReplaceAllString(fn, " ")
	re = regexp.MustCompile("\"|'")
	fn = re.ReplaceAllString(fn, "")
	return
}
func GetResourceInfo(url_ string, header http.Header) (resource_info ResourceInfo, err error) {
	for i := 0; i < 3; i++ {
		var resp *http.Response
		resp, err = get(url_, header, TimeoutOfGetResourceInfo)
		if err != nil {
			if i < 2 {
				time.Sleep(time.Duration(10+30*i) * time.Second)
				continue
			}
			return
		}
		defer resp.Body.Close()
		resource_info.length, err = get_content_length(resp.Header)
		if err != nil {
			return
		}
		resource_info.filename, err = get_attchment_filename(resp.Header)
		if err != nil {
			return
		}
		return
	}
	return
}

func ConvertWaitGroupToBoolChan(wg *sync.WaitGroup, c chan<- bool) {
	wg.Wait()
	c <- true
}

func GetNowEpochInMilli() int64 {
	now := time.Now()
	return now.UnixNano() / 1000000
}
func GetNowEpochInSecond() int64 {
	now := time.Now()
	return now.UnixNano() / 1000000000
}
<|endoftext|>


<commit_before>package pointers

// TODO: Add test
func StrPtr(str string) *string {
	return &str
}

func BoolPtr(bl bool) *bool {
	return &bl
}

func Float64Ptr(f float64) *float64 {
	return &f
}
func IntPtr(i int) *int {
	return &i
}

// TODO: Add test
func IsBlank(pStr *string) bool {
	return pStr == nil || *pStr == ""
}
<commit_msg>Update pointers.go<commit_after>package pointers

// TODO: Add test
func StrPtr(str string) *string {
	return &str
}

func BoolPtr(bl bool) *bool {
	return &bl
}

func Float64Ptr(f float64) *float64 {
	return &f
}
func IntPtr(i int) *int {
	return &i
}
func Int64Ptr(i int64) *int64 {
	return &i
}
// TODO: Add test
func IsBlank(pStr *string) bool {
	return pStr == nil || *pStr == ""
}
<|endoftext|>


<commit_before><commit_msg>Remove empty.go<commit_after><|endoftext|>


<commit_before><commit_msg>Allow namespace of type 'user' (#527)<commit_after><|endoftext|>


<commit_before>package godruid

import (
    "encoding/json"
)

type PostAggregation struct {
    Type       string            `json:"type"`
    Name       string            `json:"name,omitempty"`
    Value      interface{}       `json:"value,omitempty"`
    Fn         string            `json:"fn,omitempty"`
    Fields     []PostAggregation `json:"fields,omitempty"`
    FieldName  string            `json:"fieldName,omitempty"`
    FieldNames []string          `json:"fieldNames,omitempty"`
    Function   string            `json:"function,omitempty"`
}

// Return the aggregations which this post-aggregation used.
// It could be helpful while automatically filling the aggregations base on post-aggregations.
func (pa PostAggregation) GetRelativeAggs() (aggs []string) {
    if pa.FieldName != "" {
        aggs = append(aggs, pa.FieldName)
    }
    aggs = append(aggs, pa.FieldNames...)
    for _, spa := range pa.Fields {
        aggs = append(aggs, spa.GetRelativeAggs()...)
    }
    return
}

func PostAggRawJson(rawJson string) PostAggregation {
    pa := &PostAggregation{}
    json.Unmarshal([]byte(rawJson), pa)
    return *pa
}

func PostAggArithmetic(name, fn string, fields []PostAggregation) PostAggregation {
    return PostAggregation{
        Type:   "arithmetic",
        Name:   name,
        Fn:     fn,
        Fields: fields,
    }
}

func PostAggFieldAccessor(fieldName string) PostAggregation {
    return PostAggregation{
        Type:      "fieldAccess",
        FieldName: fieldName,
    }
}

func PostAggConstant(name string, value interface{}) PostAggregation {
    return PostAggregation{
        Type:  "constant",
        Name:  name,
        Value: value,
    }
}

func PostAggJavaScript(name, function string, fieldNames []string) PostAggregation {
    return PostAggregation{
        Type:       "javascript",
        Name:       name,
        FieldNames: fieldNames,
        Function:   function,
    }
}

func PostAggFieldHyperUnique(fieldName string) PostAggregation {
    return PostAggregation{
        Type:      "hyperUniqueCardinality",
        FieldName: fieldName,
    }
}
<commit_msg>fixed GetRelativeAggs and renamed to GetReferAggs, still looks like a dummy version...<commit_after>package godruid

import (
    "encoding/json"
)

type PostAggregation struct {
    Type       string            `json:"type"`
    Name       string            `json:"name,omitempty"`
    Value      interface{}       `json:"value,omitempty"`
    Fn         string            `json:"fn,omitempty"`
    Fields     []PostAggregation `json:"fields,omitempty"`
    FieldName  string            `json:"fieldName,omitempty"`
    FieldNames []string          `json:"fieldNames,omitempty"`
    Function   string            `json:"function,omitempty"`
}

// The agg reference.
type AggRefer struct {
    Name  string
    Refer string // The refer of Name, empty means Name has no refer.
}

// Return the aggregations or post aggregations which this post aggregation used.
// It could be helpful while automatically filling the aggregations or post aggregations base on this.
func (pa PostAggregation) GetReferAggs(parentName ...string) (refers []AggRefer) {
    switch pa.Type {
    case "arithmetic":
        for _, spa := range pa.Fields {
            refers = append(refers, spa.GetReferAggs(pa.Name)...)
        }
        refers = append(refers, AggRefer{pa.Name, ""})
    case "fieldAccess":
        refers = append(refers, AggRefer{parentName[0], pa.FieldName})
    case "constant":
        // no need refers.
    case "javascript":
        for _, f := range pa.FieldNames {
            refers = append(refers, AggRefer{pa.Name, f})
        }
    case "hyperUniqueCardinality":
        refers = append(refers, AggRefer{parentName[0], pa.FieldName})
    }
    return
}

func PostAggRawJson(rawJson string) PostAggregation {
    pa := &PostAggregation{}
    json.Unmarshal([]byte(rawJson), pa)
    return *pa
}

func PostAggArithmetic(name, fn string, fields []PostAggregation) PostAggregation {
    return PostAggregation{
        Type:   "arithmetic",
        Name:   name,
        Fn:     fn,
        Fields: fields,
    }
}

func PostAggFieldAccessor(fieldName string) PostAggregation {
    return PostAggregation{
        Type:      "fieldAccess",
        FieldName: fieldName,
    }
}

func PostAggConstant(name string, value interface{}) PostAggregation {
    return PostAggregation{
        Type:  "constant",
        Name:  name,
        Value: value,
    }
}

func PostAggJavaScript(name, function string, fieldNames []string) PostAggregation {
    return PostAggregation{
        Type:       "javascript",
        Name:       name,
        FieldNames: fieldNames,
        Function:   function,
    }
}

func PostAggFieldHyperUnique(fieldName string) PostAggregation {
    return PostAggregation{
        Type:      "hyperUniqueCardinality",
        FieldName: fieldName,
    }
}
<|endoftext|>


<commit_before>package postgres

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strings"

	"github.com/caarlos0/env"
	"github.com/jmoiron/sqlx"
	// Used pg drive on sqlx
	_ "github.com/lib/pq"

	"database/sql"

	"github.com/nuveo/prest/api"
	"github.com/nuveo/prest/config"
)

const (
	pageNumberKey   = "_page"
	pageSizeKey     = "_page_size"
	defaultPageSize = "10"
)

// Conn connect on PostgreSQL
// Used sqlx
func Conn() (db *sqlx.DB) {
	cfg := config.Prest{}
	env.Parse(&cfg)

	db, err := sqlx.Connect("postgres", fmt.Sprintf("user=%s dbname=%s host=%s port=%v sslmode=disable", cfg.PGUser, cfg.PGDatabase, cfg.PGHost, cfg.PGPort))
	if err != nil {
		panic(fmt.Sprintf("Unable to connection to database: %v\n", err))
	}
	return
}

// WhereByRequest create interface for queries + where
func WhereByRequest(r *http.Request) (whereSyntax string) {
	u, _ := url.Parse(r.URL.String())
	where := []string{}
	for key, val := range u.Query() {
		if !strings.HasPrefix(key, "_") {
			where = append(where, fmt.Sprintf("%s='%s'", key, val[0]))
		}
	}

	whereSyntax = strings.Join(where, " and ")
	return
}

// Query process queries
func Query(SQL string, params ...interface{}) (jsonData []byte, err error) {
	db := Conn()
	rows, err := db.Queryx(SQL, params...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	columns, err := rows.Columns()
	if err != nil {
		return nil, err
	}

	count := len(columns)
	tableData := make([]map[string]interface{}, 0)
	values := make([]interface{}, count)
	valuePtrs := make([]interface{}, count)
	for rows.Next() {
		for i := 0; i < count; i++ {
			valuePtrs[i] = &values[i]
		}
		rows.Scan(valuePtrs...)
		entry := make(map[string]interface{})
		for i, col := range columns {
			var v interface{}
			val := values[i]
			b, ok := val.([]byte)
			if ok {
				v = string(b)
			} else {
				v = val
			}
			entry[col] = v
		}
		tableData = append(tableData, entry)
	}
	jsonData, err = json.Marshal(tableData)

	return
}

// PaginateIfPossible func
func PaginateIfPossible(r *http.Request) (paginatedQuery string) {
	u, _ := url.Parse(r.URL.String())
	values := u.Query()
	if _, ok := values[pageNumberKey]; !ok {
		paginatedQuery = ""
		return
	}
	pageNumber := values[pageNumberKey][0]
	pageSize := defaultPageSize
	if size, ok := values[pageSizeKey]; ok {
		pageSize = size[0]
	}
	paginatedQuery = fmt.Sprintf("LIMIT %s OFFSET(%s - 1) * %s", pageSize, pageNumber, pageSize)
	return
}

// Insert execute insert sql into a table
func Insert(database, schema, table string, body api.Request) (jsonData []byte, err error) {
	var result sql.Result
	var rowsAffected int64

	fields := make([]string, 0)
	values := make([]string, 0)
	for key, value := range body.Data {
		fields = append(fields, key)
		values = append(values, value)
	}
	colsName := strings.Join(fields, ", ")
	colsValue := strings.Join(values, "', '")
	sql := fmt.Sprintf("INSERT INTO %s.%s.%s (%s) VALUES ('%s')", database, schema, table, colsName, colsValue)

	db := Conn()
	result, err = db.Exec(sql)
	if err != nil {
		return
	}
	rowsAffected, err = result.RowsAffected()
	if err != nil {
		return
	}

	data := make(map[string]interface{})
	data["rows_affected"] = rowsAffected
	jsonData, err = json.Marshal(data)
	return
}

// Delete execute delete sql into a table
func Delete(database, schema, table, where string) (jsonData []byte, err error) {
	var result sql.Result
	var rowsAffected int64

	sql := fmt.Sprintf("DELETE FROM %s.%s.%s", database, schema, table)
	if where != "" {
		sql = fmt.Sprint(
			sql,
			" WHERE ",
			where)
	}

	db := Conn()
	result, err = db.Exec(sql)
	if err != nil {
		return
	}
	rowsAffected, err = result.RowsAffected()
	if err != nil {
		return
	}

	data := make(map[string]interface{})
	data["rows_affected"] = rowsAffected
	jsonData, err = json.Marshal(data)
	return
}

// Update execute update sql into a table
func Update(database, schema, table, where string, body api.Request) (jsonData []byte, err error) {
	var result sql.Result
	var rowsAffected int64

	fields := []string{}
	for key, value := range body.Data {
		fields = append(fields, fmt.Sprintf("%s='%s'", key, value))
	}
	setSyntax := strings.Join(fields, ", ")

	sql := fmt.Sprintf("UPDATE %s.%s.%s SET %s", database, schema, table, setSyntax)

	if where != "" {
		sql = fmt.Sprint(
			sql,
			" WHERE ",
			where)
	}

	db := Conn()
	result, err = db.Exec(sql)
	if err != nil {
		return
	}
	rowsAffected, err = result.RowsAffected()
	if err != nil {
		return
	}

	data := make(map[string]interface{})
	data["rows_affected"] = rowsAffected
	jsonData, err = json.Marshal(data)
	return
}
<commit_msg>jsonb support implementation<commit_after>package postgres

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strings"

	"github.com/caarlos0/env"
	"github.com/jmoiron/sqlx"
	// Used pg drive on sqlx
	_ "github.com/lib/pq"

	"database/sql"

	"github.com/nuveo/prest/api"
	"github.com/nuveo/prest/config"
)

const (
	pageNumberKey   = "_page"
	pageSizeKey     = "_page_size"
	defaultPageSize = "10"
)

// Conn connect on PostgreSQL
// Used sqlx
func Conn() (db *sqlx.DB) {
	cfg := config.Prest{}
	env.Parse(&cfg)

	db, err := sqlx.Connect("postgres", fmt.Sprintf("user=%s dbname=%s host=%s port=%v sslmode=disable", cfg.PGUser, cfg.PGDatabase, cfg.PGHost, cfg.PGPort))
	if err != nil {
		panic(fmt.Sprintf("Unable to connection to database: %v\n", err))
	}
	return
}

// WhereByRequest create interface for queries + where
func WhereByRequest(r *http.Request) (whereSyntax string) {
	u, _ := url.Parse(r.URL.String())
	where := []string{}
	for key, val := range u.Query() {
		if !strings.HasPrefix(key, "_") {
			keyInfo := strings.Split(key, ":")
			if len(keyInfo) > 1 {
				switch keyInfo[1] {
				case "jsonb":
					jsonField := strings.Split(keyInfo[0], "->>")
					where = append(where, fmt.Sprintf("%s->>'%s'='%s'", jsonField[0], jsonField[1], val[0]))
				default:
					where = append(where, fmt.Sprintf("%s='%s'", keyInfo[0], val[0]))

				}
				continue
			}
			where = append(where, fmt.Sprintf("%s='%s'", key, val[0]))
		}
	}

	whereSyntax = strings.Join(where, " and ")
	return
}

// Query process queries
func Query(SQL string, params ...interface{}) (jsonData []byte, err error) {
	db := Conn()
	rows, err := db.Queryx(SQL, params...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	columns, err := rows.Columns()
	if err != nil {
		return nil, err
	}

	count := len(columns)
	tableData := make([]map[string]interface{}, 0)
	values := make([]interface{}, count)
	valuePtrs := make([]interface{}, count)
	for rows.Next() {
		for i := 0; i < count; i++ {
			valuePtrs[i] = &values[i]
		}
		rows.Scan(valuePtrs...)
		entry := make(map[string]interface{})
		for i, col := range columns {
			var v interface{}
			val := values[i]
			b, ok := val.([]byte)
			if ok {
				v = string(b)
			} else {
				v = val
			}
			entry[col] = v
		}
		tableData = append(tableData, entry)
	}
	jsonData, err = json.Marshal(tableData)

	return
}

// PaginateIfPossible func
func PaginateIfPossible(r *http.Request) (paginatedQuery string) {
	u, _ := url.Parse(r.URL.String())
	values := u.Query()
	if _, ok := values[pageNumberKey]; !ok {
		paginatedQuery = ""
		return
	}
	pageNumber := values[pageNumberKey][0]
	pageSize := defaultPageSize
	if size, ok := values[pageSizeKey]; ok {
		pageSize = size[0]
	}
	paginatedQuery = fmt.Sprintf("LIMIT %s OFFSET(%s - 1) * %s", pageSize, pageNumber, pageSize)
	return
}

// Insert execute insert sql into a table
func Insert(database, schema, table string, body api.Request) (jsonData []byte, err error) {
	var result sql.Result
	var rowsAffected int64

	fields := make([]string, 0)
	values := make([]string, 0)
	for key, value := range body.Data {
		fields = append(fields, key)
		values = append(values, value)
	}
	colsName := strings.Join(fields, ", ")
	colsValue := strings.Join(values, "', '")
	sql := fmt.Sprintf("INSERT INTO %s.%s.%s (%s) VALUES ('%s')", database, schema, table, colsName, colsValue)

	db := Conn()
	result, err = db.Exec(sql)
	if err != nil {
		return
	}
	rowsAffected, err = result.RowsAffected()
	if err != nil {
		return
	}

	data := make(map[string]interface{})
	data["rows_affected"] = rowsAffected
	jsonData, err = json.Marshal(data)
	return
}

// Delete execute delete sql into a table
func Delete(database, schema, table, where string) (jsonData []byte, err error) {
	var result sql.Result
	var rowsAffected int64

	sql := fmt.Sprintf("DELETE FROM %s.%s.%s", database, schema, table)
	if where != "" {
		sql = fmt.Sprint(
			sql,
			" WHERE ",
			where)
	}

	db := Conn()
	result, err = db.Exec(sql)
	if err != nil {
		return
	}
	rowsAffected, err = result.RowsAffected()
	if err != nil {
		return
	}

	data := make(map[string]interface{})
	data["rows_affected"] = rowsAffected
	jsonData, err = json.Marshal(data)
	return
}

// Update execute update sql into a table
func Update(database, schema, table, where string, body api.Request) (jsonData []byte, err error) {
	var result sql.Result
	var rowsAffected int64

	fields := []string{}
	for key, value := range body.Data {
		fields = append(fields, fmt.Sprintf("%s='%s'", key, value))
	}
	setSyntax := strings.Join(fields, ", ")

	sql := fmt.Sprintf("UPDATE %s.%s.%s SET %s", database, schema, table, setSyntax)

	if where != "" {
		sql = fmt.Sprint(
			sql,
			" WHERE ",
			where)
	}

	db := Conn()
	result, err = db.Exec(sql)
	if err != nil {
		return
	}
	rowsAffected, err = result.RowsAffected()
	if err != nil {
		return
	}

	data := make(map[string]interface{})
	data["rows_affected"] = rowsAffected
	jsonData, err = json.Marshal(data)
	return
}
<|endoftext|>


<commit_before>package agent

import (
	"log"
	"net/http"
	"os"

	"github.com/coreos/go-etcd/etcd"
	"github.com/flynn/rpcplus"
	rpc "github.com/flynn/rpcplus/comborpc"
)

const (
	HeartbeatIntervalSecs = 5
	MissedHearbeatTTL     = 5
)

type ServiceUpdate struct {
	Name    string
	Addr    string
	Online  bool
	Attrs   map[string]string
	Created uint
}

type Args struct {
	Name  string
	Addr  string
	Attrs map[string]string
}

type UpdateStream interface {
	Chan() chan *ServiceUpdate
	Close()
}

type DiscoveryBackend interface {
	Subscribe(name string) (UpdateStream, error)
	Register(name string, addr string, attrs map[string]string) error
	Unregister(name string, addr string) error
	Heartbeat(name string, addr string) error
}

type Agent struct {
	Backend DiscoveryBackend
	Address string
}

func NewServer(addr string, etcdAddrs []string) *Agent {
	return &Agent{
		Backend: &EtcdBackend{Client: etcd.NewClient(etcdAddrs)},
		Address: addr,
	}
}

func ListenAndServe(server *Agent) error {
	rpc.HandleHTTP()
	if err := rpc.Register(server); err != nil {
		return err
	}
	return http.ListenAndServe(server.Address, nil)
}

func expandAddr(addr string) string {
	if addr[0] == ':' {
		return os.Getenv("EXTERNAL_IP") + addr
	}
	return addr
}

func (s *Agent) Subscribe(args *Args, stream rpcplus.Stream) error {
	updates, err := s.Backend.Subscribe(args.Name)
	if err != nil {
		log.Println("Subscribe: error:", err)
		stream.Send <- &ServiceUpdate{} // be sure to unblock client
		return err
	}
	log.Println("Subscribe:", args.Name)
	for update := range updates.Chan() {
		select {
		case stream.Send <- update:
		case <-stream.Error:
			updates.Close()
			return nil
		}
	}
	return nil
}

func (s *Agent) Register(args *Args, ret *string) error {
	addr := expandAddr(args.Addr)
	err := s.Backend.Register(args.Name, addr, args.Attrs)
	if err != nil {
		log.Println("Register: error:", err)
		return err
	}
	ret = &addr
	log.Println("Register:", args.Name, addr, args.Attrs)
	return nil
}

func (s *Agent) Unregister(args *Args, ret *struct{}) error {
	addr := expandAddr(args.Addr)
	err := s.Backend.Unregister(args.Name, addr)
	if err != nil {
		log.Println("Unregister: error:", err)
		return err
	}
	log.Println("Unregister:", args.Name, addr)
	return nil
}

func (s *Agent) Heartbeat(args *Args, ret *struct{}) error {
	addr := expandAddr(args.Addr)
	err := s.Backend.Heartbeat(args.Name, addr)
	if err != nil {
		log.Println("Heartbeat: error:", err)
		return err
	}
	log.Println("Heartbeat:", args.Name, addr)
	return nil
}
<commit_msg>discoverd: assign string to string pointer properly<commit_after>package agent

import (
	"log"
	"net/http"
	"os"

	"github.com/coreos/go-etcd/etcd"
	"github.com/flynn/rpcplus"
	rpc "github.com/flynn/rpcplus/comborpc"
)

const (
	HeartbeatIntervalSecs = 5
	MissedHearbeatTTL     = 5
)

type ServiceUpdate struct {
	Name    string
	Addr    string
	Online  bool
	Attrs   map[string]string
	Created uint
}

type Args struct {
	Name  string
	Addr  string
	Attrs map[string]string
}

type UpdateStream interface {
	Chan() chan *ServiceUpdate
	Close()
}

type DiscoveryBackend interface {
	Subscribe(name string) (UpdateStream, error)
	Register(name string, addr string, attrs map[string]string) error
	Unregister(name string, addr string) error
	Heartbeat(name string, addr string) error
}

type Agent struct {
	Backend DiscoveryBackend
	Address string
}

func NewServer(addr string, etcdAddrs []string) *Agent {
	return &Agent{
		Backend: &EtcdBackend{Client: etcd.NewClient(etcdAddrs)},
		Address: addr,
	}
}

func ListenAndServe(server *Agent) error {
	rpc.HandleHTTP()
	if err := rpc.Register(server); err != nil {
		return err
	}
	return http.ListenAndServe(server.Address, nil)
}

func expandAddr(addr string) string {
	if addr[0] == ':' {
		return os.Getenv("EXTERNAL_IP") + addr
	}
	return addr
}

func (s *Agent) Subscribe(args *Args, stream rpcplus.Stream) error {
	updates, err := s.Backend.Subscribe(args.Name)
	if err != nil {
		log.Println("Subscribe: error:", err)
		stream.Send <- &ServiceUpdate{} // be sure to unblock client
		return err
	}
	log.Println("Subscribe:", args.Name)
	for update := range updates.Chan() {
		select {
		case stream.Send <- update:
		case <-stream.Error:
			updates.Close()
			return nil
		}
	}
	return nil
}

func (s *Agent) Register(args *Args, ret *string) error {
	addr := expandAddr(args.Addr)
	err := s.Backend.Register(args.Name, addr, args.Attrs)
	if err != nil {
		log.Println("Register: error:", err)
		return err
	}
	*ret = addr
	log.Println("Register:", args.Name, addr, args.Attrs)
	return nil
}

func (s *Agent) Unregister(args *Args, ret *struct{}) error {
	addr := expandAddr(args.Addr)
	err := s.Backend.Unregister(args.Name, addr)
	if err != nil {
		log.Println("Unregister: error:", err)
		return err
	}
	log.Println("Unregister:", args.Name, addr)
	return nil
}

func (s *Agent) Heartbeat(args *Args, ret *struct{}) error {
	addr := expandAddr(args.Addr)
	err := s.Backend.Heartbeat(args.Name, addr)
	if err != nil {
		log.Println("Heartbeat: error:", err)
		return err
	}
	log.Println("Heartbeat:", args.Name, addr)
	return nil
}
<|endoftext|>


<commit_before>package notification

import (
	"ironman/config"
	"ironman/logging"
	//"log"
)

// Run all notifications configured for a
func Notify(c *config.Config, j *logging.Job) {
	// always notify the person who comitted
	go email(c, j, j.Email)

	/*config, err := c.ConfigForRepo(job.URL)

	if err != nil {
		log.Println("could not find repo", job.URL)
		return
	}*/
}
<commit_msg>run all notifications when a build finished<commit_after>// Notifications to send after a build process finished.
package notification

import (
	"ironman/config"
	"ironman/logging"
	"log"
)

// Run all notifications configured for a
func Notify(c *config.Config, j *logging.Job) {
	// always notify the person who comitted
	go email(c, j, j.Email)

	repo, err := c.ConfigForRepo(j.URL)

	if err != nil {
		log.Println("could not find repo", j.URL)
		return
	}

	for _, n := range repo.Notify {
		if n.Service == "email" {
			// Arguments for email are the mail addresses to notify
			for _, mail := range n.Arguments {
				go email(c, j, mail)
			}
			continue
		}

		if n.Service == "slack" {
			// No arguments for Slack
			go slack(c, j)
			continue
		}
	}
}
<|endoftext|>


<commit_before>package accessors

import "github.com/labstack/echo"

type Income struct {
	ID     int    `json:"id"`
	User   int    `json:"user"`
	Time   string `json:"time"`
	Payer  string `json:"payer"`
	Amount int    `json:"amount,string"`
}

func (ag *AccessorGroup) LogIncome(c echo.Context, email string) (Income, error) {
	income := Income{}
	err := c.Bind(&income)
	if err != nil {
		return Income{}, err
	}

	userID, err := ag.GetUserID(email)
	if err != nil {
		return Income{}, err
	}

	income.User = userID

	// TODO: Make sure the information passed in is complete and don't submit if it's not

	_, err = ag.Database.Query("INSERT INTO income (user, payer, amount) VALUES (?,?,?)", income.User, income.Payer, income.Amount)
	if err != nil {
		return Income{}, err
	}

	return Income{}, nil
}

func (ag *AccessorGroup) GetIncome(c echo.Context, email string) ([]Income, error) {
	allIncome := []Income{}

	userID, err := ag.GetUserID(email)
	if err != nil {
		return []Income{}, err
	}

	rows, err := ag.Database.Query("SELECT * FROM income WHERE user=? AND MONTH(time) = MONTH(CURDATE())", userID)
	if err != nil {
		return []Income{}, err
	}

	defer rows.Close()

	for rows.Next() {
		income := Income{}

		err := rows.Scan(&income.ID, &income.User, &income.Time, &income.Payer, &income.Amount)
		if err != nil {
			return []Income{}, err
		}

		allIncome = append(allIncome, income)
	}

	err = rows.Err()
	if err != nil {
		return []Income{}, err
	}

	return allIncome, nil
}
<commit_msg>Sharing income works<commit_after>package accessors

import "github.com/labstack/echo"

type Income struct {
	ID     int    `json:"id"`
	User   int    `json:"user"`
	Time   string `json:"time"`
	Payer  string `json:"payer"`
	Amount int    `json:"amount,string"`
}

func (ag *AccessorGroup) LogIncome(c echo.Context, email string) (Income, error) {
	income := Income{}
	err := c.Bind(&income)
	if err != nil {
		return Income{}, err
	}

	userID, err := ag.GetUserID(email)
	if err != nil {
		return Income{}, err
	}

	income.User = userID

	// TODO: Make sure the information passed in is complete and don't submit if it's not

	_, err = ag.Database.Query("INSERT INTO income (user, payer, amount) VALUES (?,?,?)", income.User, income.Payer, income.Amount)
	if err != nil {
		return Income{}, err
	}

	return Income{}, nil
}

func (ag *AccessorGroup) GetIncome(c echo.Context, email string) ([]Income, error) {
	allIncome := []Income{}

	userID, err := ag.GetUserID(email)
	if err != nil {
		return []Income{}, err
	}

	allIncome, err = ag.GetIncomeByUserID(c, allIncome, userID)
	if err != nil {
		return []Income{}, err
	}

	allShares, err := ag.GetSharing(c, email)
	if err != nil {
		return []Income{}, err
	}

	for i := range allShares {
		if allShares[i].User != userID {
			allIncome, err = ag.GetIncomeByUserID(c, allIncome, allShares[i].User)
			if err != nil {
				return []Income{}, err
			}
		} else if allShares[i].Sharee != userID {
			allIncome, err = ag.GetIncomeByUserID(c, allIncome, allShares[i].Sharee)
			if err != nil {
				return []Income{}, err
			}
		}
	}

	return allIncome, nil
}

func (ag *AccessorGroup) GetIncomeByUserID(c echo.Context, allIncome []Income, id int) ([]Income, error) {
	rows, err := ag.Database.Query("SELECT * FROM income WHERE user=? AND MONTH(time) = MONTH(CURDATE())", id)
	if err != nil {
		return []Income{}, err
	}

	defer rows.Close()

	for rows.Next() {
		income := Income{}

		err := rows.Scan(&income.ID, &income.User, &income.Time, &income.Payer, &income.Amount)
		if err != nil {
			return []Income{}, err
		}

		allIncome = append(allIncome, income)
	}

	err = rows.Err()
	if err != nil {
		return []Income{}, err
	}

	return allIncome, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package node

import (
	"fmt"
	"strings"
	"time"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/p2p"
	"github.com/ethereum/go-ethereum/p2p/discover"
	"github.com/ethereum/go-ethereum/rpc"
	"github.com/rcrowley/go-metrics"
)

// PrivateAdminAPI is the collection of administrative API methods exposed only
// over a secure RPC channel.
type PrivateAdminAPI struct {
	node *Node // Node interfaced by this API
}

// NewPrivateAdminAPI creates a new API definition for the private admin methods
// of the node itself.
func NewPrivateAdminAPI(node *Node) *PrivateAdminAPI {
	return &PrivateAdminAPI{node: node}
}

// AddPeer requests connecting to a remote node, and also maintaining the new
// connection at all times, even reconnecting if it is lost.
func (api *PrivateAdminAPI) AddPeer(url string) (bool, error) {
	// Make sure the server is running, fail otherwise
	server := api.node.Server()
	if server == nil {
		return false, ErrNodeStopped
	}
	// Try to add the url as a static peer and return
	node, err := discover.ParseNode(url)
	if err != nil {
		return false, fmt.Errorf("invalid enode: %v", err)
	}
	server.AddPeer(node)
	return true, nil
}

// StartRPC starts the HTTP RPC API server.
func (api *PrivateAdminAPI) StartRPC(host *string, port *rpc.HexNumber, cors *string, apis *string) (bool, error) {
	api.node.lock.Lock()
	defer api.node.lock.Unlock()

	if api.node.httpHandler != nil {
		return false, fmt.Errorf("HTTP RPC already running on %s", api.node.httpEndpoint)
	}

	if host == nil {
		host = &api.node.httpHost
	}
	if port == nil {
		port = rpc.NewHexNumber(api.node.httpPort)
	}
	if cors == nil {
		cors = &api.node.httpCors
	}

	modules := api.node.httpWhitelist
	if apis != nil {
		modules = nil
		for _, m := range strings.Split(*apis, ",") {
			modules = append(modules, strings.TrimSpace(m))
		}
	}

	if err := api.node.startHTTP(fmt.Sprintf("%s:%d", *host, port.Int()), api.node.rpcAPIs, modules, *cors); err != nil {
		return false, err
	}
	return true, nil
}

// StopRPC terminates an already running HTTP RPC API endpoint.
func (api *PrivateAdminAPI) StopRPC() (bool, error) {
	api.node.lock.Lock()
	defer api.node.lock.Unlock()

	if api.node.httpHandler == nil {
		return false, fmt.Errorf("HTTP RPC not running")
	}
	api.node.stopHTTP()
	return true, nil
}

// StartWS starts the websocket RPC API server.
func (api *PrivateAdminAPI) StartWS(host *string, port *rpc.HexNumber, allowedOrigins *string, apis *string) (bool, error) {
	api.node.lock.Lock()
	defer api.node.lock.Unlock()

	if api.node.wsHandler != nil {
		return false, fmt.Errorf("WebSocket RPC already running on %s", api.node.wsEndpoint)
	}

	if host == nil {
		host = &api.node.wsHost
	}
	if port == nil {
		port = rpc.NewHexNumber(api.node.wsPort)
	}
	if allowedOrigins == nil {
		allowedOrigins = &api.node.wsOrigins
	}

	modules := api.node.wsWhitelist
	if apis != nil {
		modules = nil
		for _, m := range strings.Split(*apis, ",") {
			modules = append(modules, strings.TrimSpace(m))
		}
	}

	if err := api.node.startWS(fmt.Sprintf("%s:%d", *host, port.Int()), api.node.rpcAPIs, modules, *allowedOrigins); err != nil {
		return false, err
	}
	return true, nil
}

// StopRPC terminates an already running websocket RPC API endpoint.
func (api *PrivateAdminAPI) StopWS() (bool, error) {
	api.node.lock.Lock()
	defer api.node.lock.Unlock()

	if api.node.wsHandler == nil {
		return false, fmt.Errorf("WebSocket RPC not running")
	}
	api.node.stopWS()
	return true, nil
}

// PublicAdminAPI is the collection of administrative API methods exposed over
// both secure and unsecure RPC channels.
type PublicAdminAPI struct {
	node *Node // Node interfaced by this API
}

// NewPublicAdminAPI creates a new API definition for the public admin methods
// of the node itself.
func NewPublicAdminAPI(node *Node) *PublicAdminAPI {
	return &PublicAdminAPI{node: node}
}

// Peers retrieves all the information we know about each individual peer at the
// protocol granularity.
func (api *PublicAdminAPI) Peers() ([]*p2p.PeerInfo, error) {
	server := api.node.Server()
	if server == nil {
		return nil, ErrNodeStopped
	}
	return server.PeersInfo(), nil
}

// NodeInfo retrieves all the information we know about the host node at the
// protocol granularity.
func (api *PublicAdminAPI) NodeInfo() (*p2p.NodeInfo, error) {
	server := api.node.Server()
	if server == nil {
		return nil, ErrNodeStopped
	}
	return server.NodeInfo(), nil
}

// Datadir retrieves the current data directory the node is using.
func (api *PublicAdminAPI) Datadir() string {
	return api.node.DataDir()
}

// PublicDebugAPI is the collection of debugging related API methods exposed over
// both secure and unsecure RPC channels.
type PublicDebugAPI struct {
	node *Node // Node interfaced by this API
}

// NewPublicDebugAPI creates a new API definition for the public debug methods
// of the node itself.
func NewPublicDebugAPI(node *Node) *PublicDebugAPI {
	return &PublicDebugAPI{node: node}
}

// Metrics retrieves all the known system metric collected by the node.
func (api *PublicDebugAPI) Metrics(raw bool) (map[string]interface{}, error) {
	// Create a rate formatter
	units := []string{"", "K", "M", "G", "T", "E", "P"}
	round := func(value float64, prec int) string {
		unit := 0
		for value >= 1000 {
			unit, value, prec = unit+1, value/1000, 2
		}
		return fmt.Sprintf(fmt.Sprintf("%%.%df%s", prec, units[unit]), value)
	}
	format := func(total float64, rate float64) string {
		return fmt.Sprintf("%s (%s/s)", round(total, 0), round(rate, 2))
	}
	// Iterate over all the metrics, and just dump for now
	counters := make(map[string]interface{})
	metrics.DefaultRegistry.Each(func(name string, metric interface{}) {
		// Create or retrieve the counter hierarchy for this metric
		root, parts := counters, strings.Split(name, "/")
		for _, part := range parts[:len(parts)-1] {
			if _, ok := root[part]; !ok {
				root[part] = make(map[string]interface{})
			}
			root = root[part].(map[string]interface{})
		}
		name = parts[len(parts)-1]

		// Fill the counter with the metric details, formatting if requested
		if raw {
			switch metric := metric.(type) {
			case metrics.Meter:
				root[name] = map[string]interface{}{
					"AvgRate01Min": metric.Rate1(),
					"AvgRate05Min": metric.Rate5(),
					"AvgRate15Min": metric.Rate15(),
					"MeanRate":     metric.RateMean(),
					"Overall":      float64(metric.Count()),
				}

			case metrics.Timer:
				root[name] = map[string]interface{}{
					"AvgRate01Min": metric.Rate1(),
					"AvgRate05Min": metric.Rate5(),
					"AvgRate15Min": metric.Rate15(),
					"MeanRate":     metric.RateMean(),
					"Overall":      float64(metric.Count()),
					"Percentiles": map[string]interface{}{
						"5":  metric.Percentile(0.05),
						"20": metric.Percentile(0.2),
						"50": metric.Percentile(0.5),
						"80": metric.Percentile(0.8),
						"95": metric.Percentile(0.95),
					},
				}

			default:
				root[name] = "Unknown metric type"
			}
		} else {
			switch metric := metric.(type) {
			case metrics.Meter:
				root[name] = map[string]interface{}{
					"Avg01Min": format(metric.Rate1()*60, metric.Rate1()),
					"Avg05Min": format(metric.Rate5()*300, metric.Rate5()),
					"Avg15Min": format(metric.Rate15()*900, metric.Rate15()),
					"Overall":  format(float64(metric.Count()), metric.RateMean()),
				}

			case metrics.Timer:
				root[name] = map[string]interface{}{
					"Avg01Min": format(metric.Rate1()*60, metric.Rate1()),
					"Avg05Min": format(metric.Rate5()*300, metric.Rate5()),
					"Avg15Min": format(metric.Rate15()*900, metric.Rate15()),
					"Overall":  format(float64(metric.Count()), metric.RateMean()),
					"Maximum":  time.Duration(metric.Max()).String(),
					"Minimum":  time.Duration(metric.Min()).String(),
					"Percentiles": map[string]interface{}{
						"5":  time.Duration(metric.Percentile(0.05)).String(),
						"20": time.Duration(metric.Percentile(0.2)).String(),
						"50": time.Duration(metric.Percentile(0.5)).String(),
						"80": time.Duration(metric.Percentile(0.8)).String(),
						"95": time.Duration(metric.Percentile(0.95)).String(),
					},
				}

			default:
				root[name] = "Unknown metric type"
			}
		}
	})
	return counters, nil
}

// PublicWeb3API offers helper utils
type PublicWeb3API struct {
	stack *Node
}

// NewPublicWeb3API creates a new Web3Service instance
func NewPublicWeb3API(stack *Node) *PublicWeb3API {
	return &PublicWeb3API{stack}
}

// ClientVersion returns the node name
func (s *PublicWeb3API) ClientVersion() string {
	return s.stack.Server().Name
}

// Sha3 applies the ethereum sha3 implementation on the input.
// It assumes the input is hex encoded.
func (s *PublicWeb3API) Sha3(input string) string {
	return common.ToHex(crypto.Keccak256(common.FromHex(input)))
}
<commit_msg>node: start RPC/WS interface on localhost by default<commit_after>// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package node

import (
	"fmt"
	"strings"
	"time"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/p2p"
	"github.com/ethereum/go-ethereum/p2p/discover"
	"github.com/ethereum/go-ethereum/rpc"
	"github.com/rcrowley/go-metrics"
)

// PrivateAdminAPI is the collection of administrative API methods exposed only
// over a secure RPC channel.
type PrivateAdminAPI struct {
	node *Node // Node interfaced by this API
}

// NewPrivateAdminAPI creates a new API definition for the private admin methods
// of the node itself.
func NewPrivateAdminAPI(node *Node) *PrivateAdminAPI {
	return &PrivateAdminAPI{node: node}
}

// AddPeer requests connecting to a remote node, and also maintaining the new
// connection at all times, even reconnecting if it is lost.
func (api *PrivateAdminAPI) AddPeer(url string) (bool, error) {
	// Make sure the server is running, fail otherwise
	server := api.node.Server()
	if server == nil {
		return false, ErrNodeStopped
	}
	// Try to add the url as a static peer and return
	node, err := discover.ParseNode(url)
	if err != nil {
		return false, fmt.Errorf("invalid enode: %v", err)
	}
	server.AddPeer(node)
	return true, nil
}

// StartRPC starts the HTTP RPC API server.
func (api *PrivateAdminAPI) StartRPC(host *string, port *rpc.HexNumber, cors *string, apis *string) (bool, error) {
	api.node.lock.Lock()
	defer api.node.lock.Unlock()

	if api.node.httpHandler != nil {
		return false, fmt.Errorf("HTTP RPC already running on %s", api.node.httpEndpoint)
	}

	if host == nil {
		h := common.DefaultHTTPHost
		if api.node.httpHost != "" {
			h = api.node.httpHost
		}
		host = &h
	}
	if port == nil {
		port = rpc.NewHexNumber(api.node.httpPort)
	}
	if cors == nil {
		cors = &api.node.httpCors
	}

	modules := api.node.httpWhitelist
	if apis != nil {
		modules = nil
		for _, m := range strings.Split(*apis, ",") {
			modules = append(modules, strings.TrimSpace(m))
		}
	}

	if err := api.node.startHTTP(fmt.Sprintf("%s:%d", *host, port.Int()), api.node.rpcAPIs, modules, *cors); err != nil {
		return false, err
	}
	return true, nil
}

// StopRPC terminates an already running HTTP RPC API endpoint.
func (api *PrivateAdminAPI) StopRPC() (bool, error) {
	api.node.lock.Lock()
	defer api.node.lock.Unlock()

	if api.node.httpHandler == nil {
		return false, fmt.Errorf("HTTP RPC not running")
	}
	api.node.stopHTTP()
	return true, nil
}

// StartWS starts the websocket RPC API server.
func (api *PrivateAdminAPI) StartWS(host *string, port *rpc.HexNumber, allowedOrigins *string, apis *string) (bool, error) {
	api.node.lock.Lock()
	defer api.node.lock.Unlock()

	if api.node.wsHandler != nil {
		return false, fmt.Errorf("WebSocket RPC already running on %s", api.node.wsEndpoint)
	}

	if host == nil {
		h := common.DefaultWSHost
		if api.node.wsHost != "" {
			h = api.node.wsHost
		}
		host = &h
	}
	if port == nil {
		port = rpc.NewHexNumber(api.node.wsPort)
	}
	if allowedOrigins == nil {
		allowedOrigins = &api.node.wsOrigins
	}

	modules := api.node.wsWhitelist
	if apis != nil {
		modules = nil
		for _, m := range strings.Split(*apis, ",") {
			modules = append(modules, strings.TrimSpace(m))
		}
	}

	if err := api.node.startWS(fmt.Sprintf("%s:%d", *host, port.Int()), api.node.rpcAPIs, modules, *allowedOrigins); err != nil {
		return false, err
	}
	return true, nil
}

// StopRPC terminates an already running websocket RPC API endpoint.
func (api *PrivateAdminAPI) StopWS() (bool, error) {
	api.node.lock.Lock()
	defer api.node.lock.Unlock()

	if api.node.wsHandler == nil {
		return false, fmt.Errorf("WebSocket RPC not running")
	}
	api.node.stopWS()
	return true, nil
}

// PublicAdminAPI is the collection of administrative API methods exposed over
// both secure and unsecure RPC channels.
type PublicAdminAPI struct {
	node *Node // Node interfaced by this API
}

// NewPublicAdminAPI creates a new API definition for the public admin methods
// of the node itself.
func NewPublicAdminAPI(node *Node) *PublicAdminAPI {
	return &PublicAdminAPI{node: node}
}

// Peers retrieves all the information we know about each individual peer at the
// protocol granularity.
func (api *PublicAdminAPI) Peers() ([]*p2p.PeerInfo, error) {
	server := api.node.Server()
	if server == nil {
		return nil, ErrNodeStopped
	}
	return server.PeersInfo(), nil
}

// NodeInfo retrieves all the information we know about the host node at the
// protocol granularity.
func (api *PublicAdminAPI) NodeInfo() (*p2p.NodeInfo, error) {
	server := api.node.Server()
	if server == nil {
		return nil, ErrNodeStopped
	}
	return server.NodeInfo(), nil
}

// Datadir retrieves the current data directory the node is using.
func (api *PublicAdminAPI) Datadir() string {
	return api.node.DataDir()
}

// PublicDebugAPI is the collection of debugging related API methods exposed over
// both secure and unsecure RPC channels.
type PublicDebugAPI struct {
	node *Node // Node interfaced by this API
}

// NewPublicDebugAPI creates a new API definition for the public debug methods
// of the node itself.
func NewPublicDebugAPI(node *Node) *PublicDebugAPI {
	return &PublicDebugAPI{node: node}
}

// Metrics retrieves all the known system metric collected by the node.
func (api *PublicDebugAPI) Metrics(raw bool) (map[string]interface{}, error) {
	// Create a rate formatter
	units := []string{"", "K", "M", "G", "T", "E", "P"}
	round := func(value float64, prec int) string {
		unit := 0
		for value >= 1000 {
			unit, value, prec = unit+1, value/1000, 2
		}
		return fmt.Sprintf(fmt.Sprintf("%%.%df%s", prec, units[unit]), value)
	}
	format := func(total float64, rate float64) string {
		return fmt.Sprintf("%s (%s/s)", round(total, 0), round(rate, 2))
	}
	// Iterate over all the metrics, and just dump for now
	counters := make(map[string]interface{})
	metrics.DefaultRegistry.Each(func(name string, metric interface{}) {
		// Create or retrieve the counter hierarchy for this metric
		root, parts := counters, strings.Split(name, "/")
		for _, part := range parts[:len(parts)-1] {
			if _, ok := root[part]; !ok {
				root[part] = make(map[string]interface{})
			}
			root = root[part].(map[string]interface{})
		}
		name = parts[len(parts)-1]

		// Fill the counter with the metric details, formatting if requested
		if raw {
			switch metric := metric.(type) {
			case metrics.Meter:
				root[name] = map[string]interface{}{
					"AvgRate01Min": metric.Rate1(),
					"AvgRate05Min": metric.Rate5(),
					"AvgRate15Min": metric.Rate15(),
					"MeanRate":     metric.RateMean(),
					"Overall":      float64(metric.Count()),
				}

			case metrics.Timer:
				root[name] = map[string]interface{}{
					"AvgRate01Min": metric.Rate1(),
					"AvgRate05Min": metric.Rate5(),
					"AvgRate15Min": metric.Rate15(),
					"MeanRate":     metric.RateMean(),
					"Overall":      float64(metric.Count()),
					"Percentiles": map[string]interface{}{
						"5":  metric.Percentile(0.05),
						"20": metric.Percentile(0.2),
						"50": metric.Percentile(0.5),
						"80": metric.Percentile(0.8),
						"95": metric.Percentile(0.95),
					},
				}

			default:
				root[name] = "Unknown metric type"
			}
		} else {
			switch metric := metric.(type) {
			case metrics.Meter:
				root[name] = map[string]interface{}{
					"Avg01Min": format(metric.Rate1()*60, metric.Rate1()),
					"Avg05Min": format(metric.Rate5()*300, metric.Rate5()),
					"Avg15Min": format(metric.Rate15()*900, metric.Rate15()),
					"Overall":  format(float64(metric.Count()), metric.RateMean()),
				}

			case metrics.Timer:
				root[name] = map[string]interface{}{
					"Avg01Min": format(metric.Rate1()*60, metric.Rate1()),
					"Avg05Min": format(metric.Rate5()*300, metric.Rate5()),
					"Avg15Min": format(metric.Rate15()*900, metric.Rate15()),
					"Overall":  format(float64(metric.Count()), metric.RateMean()),
					"Maximum":  time.Duration(metric.Max()).String(),
					"Minimum":  time.Duration(metric.Min()).String(),
					"Percentiles": map[string]interface{}{
						"5":  time.Duration(metric.Percentile(0.05)).String(),
						"20": time.Duration(metric.Percentile(0.2)).String(),
						"50": time.Duration(metric.Percentile(0.5)).String(),
						"80": time.Duration(metric.Percentile(0.8)).String(),
						"95": time.Duration(metric.Percentile(0.95)).String(),
					},
				}

			default:
				root[name] = "Unknown metric type"
			}
		}
	})
	return counters, nil
}

// PublicWeb3API offers helper utils
type PublicWeb3API struct {
	stack *Node
}

// NewPublicWeb3API creates a new Web3Service instance
func NewPublicWeb3API(stack *Node) *PublicWeb3API {
	return &PublicWeb3API{stack}
}

// ClientVersion returns the node name
func (s *PublicWeb3API) ClientVersion() string {
	return s.stack.Server().Name
}

// Sha3 applies the ethereum sha3 implementation on the input.
// It assumes the input is hex encoded.
func (s *PublicWeb3API) Sha3(input string) string {
	return common.ToHex(crypto.Keccak256(common.FromHex(input)))
}
<|endoftext|>


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

// +build darwin freebsd linux netbsd

package tcp_test

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"runtime"
	"testing"
	"time"

	"github.com/mikioh/tcp"
	"github.com/mikioh/tcpinfo"
)

var infoTests = []struct {
	host, url string
}{
	{
		host: "golang.org",
		url:  "https://golang.org/robots.txt",
	},
	{
		host: "github.com",
		url:  "https://github.com/robots.txt",
	},
}

func TestInfo(t *testing.T) {
	switch runtime.GOOS {
	case "darwin":
		vers := kernelVersion()
		if vers == nil || vers[0] < 15 {
			t.Skipf("not supported on %v, %s/%s", vers, runtime.GOOS, runtime.GOARCH)
		}
	case "freebsd", "linux", "netbsd":
	default:
		t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
	}

	var logs []chan string
	for i := 0; i < len(infoTests); i++ {
		logs = append(logs, make(chan string, 100))
	}

	for i, tt := range infoTests {
		sig := make(chan struct{})
		tr := &http.Transport{
			Dial: func(network, address string) (net.Conn, error) {
				d := net.Dialer{DualStack: true}
				c, err := d.Dial(network, address)
				if err != nil {
					return nil, err
				}
				tc, err := tcp.NewConn(c)
				if err != nil {
					c.Close()
					return nil, err
				}
				go monitor(tc, logs[i], sig)
				return tc.Conn, nil
			},
			TLSClientConfig: &tls.Config{ServerName: tt.host},
		}
		client := http.Client{Transport: tr}
		resp, err := client.Get(tt.url)
		if err != nil {
			t.Fatal(err)
		}
		if _, err := io.Copy(ioutil.Discard, resp.Body); err != nil {
			t.Fatal(err)
		}
		resp.Body.Close()
		sig <- struct{}{}
	}

	for _, log := range logs {
		for r := range log {
			t.Log(r)
		}
	}
}

func monitor(c *tcp.Conn, log chan<- string, sig <-chan struct{}) {
	defer close(log)
	log <- fmt.Sprintf("%s %v->%v", c.LocalAddr().Network(), c.LocalAddr(), c.RemoteAddr())
	var o tcpinfo.Info
	var b [256]byte
	for {
		i, err := c.Option(o.Level(), o.Name(), b[:])
		if err != nil {
			return
		}
		txt, err := json.MarshalIndent(i, "", "\t")
		if err != nil {
			continue
		}
		select {
		case <-sig:
			return
		default:
			log <- string(txt)
			time.Sleep(100 * time.Millisecond)
		}
	}
}
<commit_msg>tcp: tweak test<commit_after>// Copyright 2014 Mikio Hara. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build darwin freebsd linux netbsd

package tcp_test

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"runtime"
	"testing"
	"time"

	"github.com/mikioh/tcp"
	"github.com/mikioh/tcpinfo"
)

var infoTests = []struct {
	host, url string
}{
	{
		host: "golang.org",
		url:  "https://golang.org/robots.txt",
	},
	{
		host: "github.com",
		url:  "https://github.com/robots.txt",
	},
}

func TestInfo(t *testing.T) {
	switch runtime.GOOS {
	case "darwin":
		vers := kernelVersion()
		if vers == nil || vers[0] < 15 {
			t.Skipf("not supported on %v, %s/%s", vers, runtime.GOOS, runtime.GOARCH)
		}
	case "freebsd", "linux", "netbsd":
	default:
		t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
	}

	var logs []chan string
	for i := 0; i < len(infoTests); i++ {
		logs = append(logs, make(chan string, 100))
	}

	for i, tt := range infoTests {
		sig := make(chan struct{}, 1)
		tr := &http.Transport{
			Dial: func(network, address string) (net.Conn, error) {
				d := net.Dialer{DualStack: true}
				c, err := d.Dial(network, address)
				if err != nil {
					return nil, err
				}
				tc, err := tcp.NewConn(c)
				if err != nil {
					c.Close()
					return nil, err
				}
				go monitor(tc, logs[i], sig)
				return tc.Conn, nil
			},
			TLSClientConfig: &tls.Config{ServerName: tt.host},
		}
		client := http.Client{Transport: tr}
		resp, err := client.Get(tt.url)
		if err != nil {
			t.Fatal(err)
		}
		if _, err := io.Copy(ioutil.Discard, resp.Body); err != nil {
			t.Fatal(err)
		}
		sig <- struct{}{}
		resp.Body.Close()
	}

	for _, log := range logs {
		for r := range log {
			t.Log(r)
		}
	}
}

func monitor(c *tcp.Conn, log chan<- string, sig <-chan struct{}) {
	defer close(log)
	log <- fmt.Sprintf("%s %v->%v", c.LocalAddr().Network(), c.LocalAddr(), c.RemoteAddr())
	var o tcpinfo.Info
	var b [256]byte
	for {
		i, err := c.Option(o.Level(), o.Name(), b[:])
		if err != nil {
			return
		}
		txt, err := json.MarshalIndent(i, "", "\t")
		if err != nil {
			continue
		}
		select {
		case <-sig:
			return
		default:
			log <- string(txt)
			time.Sleep(100 * time.Millisecond)
		}
	}
}
<|endoftext|>


<commit_before>package init

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strings"
	"syscall"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/archive"
	"github.com/rancher/docker-from-scratch"
	"github.com/rancherio/os/config"
)

func cleanupTarget(rootfs, targetUsr, usr, usrVer, tmpDir string) (bool, error) {
	log.Debugf("Deleting %s", targetUsr)
	if err := os.Remove(targetUsr); err != nil && !os.IsNotExist(err) {
		log.Errorf("Failed to delete %s, possibly invalid RancherOS state partition: %v", targetUsr, err)
		return false, err
	}

	if err := dockerlaunch.CreateSymlink(usrVer, path.Join(rootfs, "usr")); err != nil {
		return false, err
	}

	log.Debugf("Deleting %s", tmpDir)
	if err := os.RemoveAll(tmpDir); err != nil {
		// Don't care if this fails
		log.Errorf("Failed to cleanup temp directory %s: %v", tmpDir, err)
	}

	if strings.HasSuffix(usrVer, "dev") {
		log.Debugf("Deleteing old usr: %s", usr)
		if err := os.RemoveAll(usr); err != nil {
			// Don't care if this fails
			log.Errorf("Failed to remove %s: %v", usr, err)
		}
		return true, nil
	}

	if _, err := os.Stat(usrVer); os.IsNotExist(err) {
		return false, nil
	}

	return true, nil
}

func copyMoveRoot(rootfs string) error {
	usrVer := fmt.Sprintf("usr-%s", config.VERSION)
	usr := path.Join(rootfs, usrVer)
	targetUsr := path.Join(rootfs, "usr")
	tmpDir := path.Join(rootfs, "tmp")

	if cont, err := cleanupTarget(rootfs, targetUsr, usr, usrVer, tmpDir); !cont {
		return err
	}

	log.Debugf("Creating temp dir directory %s", tmpDir)
	if err := os.MkdirAll(tmpDir, 0755); err != nil {
		return err
	}

	usrVerTmp, err := ioutil.TempDir(tmpDir, usrVer)
	if err != nil {
		return err
	}

	log.Debugf("Copying to temp dir %s", usrVerTmp)

	if err := archive.CopyWithTar("/usr", usrVerTmp); err != nil {
		return err
	}

	log.Debugf("Renaming %s => %s", usrVerTmp, usr)
	if err := os.Rename(usrVerTmp, usr); err != nil {
		return err
	}

	files, err := ioutil.ReadDir("/")
	if err != nil {
		return err
	}

	for _, file := range files {
		filename := path.Join("/", file.Name())

		if filename == rootfs {
			log.Debugf("Skipping Deleting %s", filename)
			continue
		}

		log.Debugf("Deleting %s", filename)
		if err := os.RemoveAll(filename); err != nil {
			return err
		}
	}

	return nil
}

func switchRoot(rootfs string) error {
	for _, i := range []string{"/dev", "/sys", "/proc", "/run"} {
		log.Debugf("Moving mount %s to %s", i, path.Join(rootfs, i))
		if err := os.MkdirAll(path.Join(rootfs, i), 0755); err != nil {
			return err
		}
		if err := syscall.Mount(i, path.Join(rootfs, i), "", syscall.MS_MOVE, ""); err != nil {
			return err
		}
	}

	if err := copyMoveRoot(rootfs); err != nil {
		return err
	}

	if err := syscall.Chdir(rootfs); err != nil {
		return err
	}

	if err := syscall.Mount(rootfs, "/", "", syscall.MS_MOVE, ""); err != nil {
		return err
	}

	if err := syscall.Chroot("."); err != nil {
		return err
	}

	if err := syscall.Chdir("/"); err != nil {
		return err
	}

	log.Debugf("Successfully moved to new root at %s", rootfs)
	os.Unsetenv("DOCKER_RAMDISK")

	return nil
}
<commit_msg>Fix mounting /usr filesystem in non-dev RancherOS versions<commit_after>package init

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strings"
	"syscall"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/archive"
	"github.com/rancher/docker-from-scratch"
	"github.com/rancherio/os/config"
)

func cleanupTarget(rootfs, targetUsr, usr, usrVer, tmpDir string) (bool, error) {
	log.Debugf("Deleting %s", targetUsr)
	if err := os.Remove(targetUsr); err != nil && !os.IsNotExist(err) {
		log.Errorf("Failed to delete %s, possibly invalid RancherOS state partition: %v", targetUsr, err)
		return false, err
	}

	if err := dockerlaunch.CreateSymlink(usrVer, path.Join(rootfs, "usr")); err != nil {
		return false, err
	}

	log.Debugf("Deleting %s", tmpDir)
	if err := os.RemoveAll(tmpDir); err != nil {
		// Don't care if this fails
		log.Errorf("Failed to cleanup temp directory %s: %v", tmpDir, err)
	}

	if strings.HasSuffix(usrVer, "dev") {
		log.Debugf("Deleteing old usr: %s", usr)
		if err := os.RemoveAll(usr); err != nil {
			// Don't care if this fails
			log.Errorf("Failed to remove %s: %v", usr, err)
		}
		return true, nil
	}

	if _, err := os.Stat(usr); err == nil {
		return false, nil
	}

	return true, nil
}

func copyMoveRoot(rootfs string) error {
	usrVer := fmt.Sprintf("usr-%s", config.VERSION)
	usr := path.Join(rootfs, usrVer)
	targetUsr := path.Join(rootfs, "usr")
	tmpDir := path.Join(rootfs, "tmp")

	if cont, err := cleanupTarget(rootfs, targetUsr, usr, usrVer, tmpDir); !cont {
		return err
	}

	log.Debugf("Creating temp dir directory %s", tmpDir)
	if err := os.MkdirAll(tmpDir, 0755); err != nil {
		return err
	}

	usrVerTmp, err := ioutil.TempDir(tmpDir, usrVer)
	if err != nil {
		return err
	}

	log.Debugf("Copying to temp dir %s", usrVerTmp)

	if err := archive.CopyWithTar("/usr", usrVerTmp); err != nil {
		return err
	}

	log.Debugf("Renaming %s => %s", usrVerTmp, usr)
	if err := os.Rename(usrVerTmp, usr); err != nil {
		return err
	}

	files, err := ioutil.ReadDir("/")
	if err != nil {
		return err
	}

	for _, file := range files {
		filename := path.Join("/", file.Name())

		if filename == rootfs {
			log.Debugf("Skipping Deleting %s", filename)
			continue
		}

		log.Debugf("Deleting %s", filename)
		if err := os.RemoveAll(filename); err != nil {
			return err
		}
	}

	return nil
}

func switchRoot(rootfs string) error {
	for _, i := range []string{"/dev", "/sys", "/proc", "/run"} {
		log.Debugf("Moving mount %s to %s", i, path.Join(rootfs, i))
		if err := os.MkdirAll(path.Join(rootfs, i), 0755); err != nil {
			return err
		}
		if err := syscall.Mount(i, path.Join(rootfs, i), "", syscall.MS_MOVE, ""); err != nil {
			return err
		}
	}

	if err := copyMoveRoot(rootfs); err != nil {
		return err
	}

	if err := syscall.Chdir(rootfs); err != nil {
		return err
	}

	if err := syscall.Mount(rootfs, "/", "", syscall.MS_MOVE, ""); err != nil {
		return err
	}

	if err := syscall.Chroot("."); err != nil {
		return err
	}

	if err := syscall.Chdir("/"); err != nil {
		return err
	}

	log.Debugf("Successfully moved to new root at %s", rootfs)
	os.Unsetenv("DOCKER_RAMDISK")

	return nil
}
<|endoftext|>


<commit_before>package lib

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

type Mux map[string]func(wr http.ResponseWriter, r *http.Request)

func (m Mux) ToHandler() (h http.Handler) {

	serveMux := http.NewServeMux()
	for p, f := range m {
		serveMux.HandleFunc(p, f)
	}
	return serveMux
}

type MuxHandlers struct {
	auth    Mux
	brain   Mux
	billing Mux
	spp     Mux
	api     Mux
}

func (mh MuxHandlers) ToHandlers() (h Handlers) {
	h.auth = mh.auth.ToHandler()
	if mh.auth == nil {
		h.auth = nil
	}
	h.brain = mh.brain.ToHandler()
	h.billing = mh.billing.ToHandler()
	h.spp = mh.spp.ToHandler()
	h.api = mh.api.ToHandler()
	return
}

type Handlers struct {
	auth    http.Handler
	brain   http.Handler
	billing http.Handler
	spp     http.Handler
	api     http.Handler
}

func (h *Handlers) Fill(t *testing.T) {
	if h.brain == nil {
		h.brain = mkNilHandler(t)
	}
	if h.billing == nil {
		h.billing = mkNilHandler(t)
	}
	if h.spp == nil {
		h.spp = mkNilHandler(t)
	}
	if h.api == nil {
		h.api = mkNilHandler(t)
	}
}

type Servers struct {
	auth    *httptest.Server
	brain   *httptest.Server
	billing *httptest.Server
	spp     *httptest.Server
	api     *httptest.Server
}

func (s *Servers) Close() {
	if s.auth != nil {
		s.auth.Close()
	}
	if s.brain != nil {
		s.brain.Close()
	}
	if s.billing != nil {
		s.billing.Close()
	}
	if s.spp != nil {
		s.spp.Close()
	}
	if s.api != nil {
		s.api.Close()
	}
	s.auth = nil
	s.brain = nil
	s.billing = nil
	s.spp = nil
	s.api = nil
}

// URLs creates an EndpointURLs
func (s Servers) URLs() (urls EndpointURLs) {
	urls.API = s.api.URL
	urls.Auth = s.auth.URL
	urls.Billing = s.billing.URL
	urls.Brain = s.brain.URL
	urls.SPP = s.spp.URL
	return
}

// Client makes a bytemarkClient for these Servers
func (s Servers) Client() (c Client, err error) {
	urls := s.URLs()
	c, err = NewWithURLs(urls)
	if err != nil {
		return nil, err
	}
	c.AllowInsecureRequests()
	return
}

// mkTestClientAndServers constructs httptest Servers for a pretend auth and API endpoint, then constructs a Client that uses those servers.
// Used to test that the right URLs are being requested and such.
func mkTestClientAndServers(t *testing.T, h Handlers) (c Client, s Servers, err error) {
	h.Fill(t)

	if h.auth != nil {
		s.auth = mkTestServer(h.auth)
	} else {
		s.auth = mkTestAuthServer()
	}
	s.brain = mkTestServer(h.brain)
	s.billing = mkTestServer(h.billing)
	s.api = mkTestServer(h.api)
	s.spp = mkTestServer(h.spp)

	c, err = s.Client()
	return
}

// mkTestServer creates an httptest.Server for the given http.Handler. It's basically an alias for httptest.NewServer. Why did I write it?
func mkTestServer(handler http.Handler) *httptest.Server {
	return httptest.NewServer(handler)
}

func mkNilHandler(t *testing.T) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		t.Fatalf("Unexpected request to a nil server\r\n%s %s", r.Method, r.URL.String())
	})
}

func mkTestAuthServer() *httptest.Server {
	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w,
			`{
    "token": "working-auth-token",
    "username": "account",
    "factors": []
}`)
	}))

}
<commit_msg>Remove unused imports from client_test<commit_after>package lib

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

type Mux map[string]func(wr http.ResponseWriter, r *http.Request)

func (m Mux) ToHandler() (h http.Handler) {

	serveMux := http.NewServeMux()
	for p, f := range m {
		serveMux.HandleFunc(p, f)
	}
	return serveMux
}

type MuxHandlers struct {
	auth    Mux
	brain   Mux
	billing Mux
	spp     Mux
	api     Mux
}

func (mh MuxHandlers) ToHandlers() (h Handlers) {
	h.auth = mh.auth.ToHandler()
	if mh.auth == nil {
		h.auth = nil
	}
	h.brain = mh.brain.ToHandler()
	h.billing = mh.billing.ToHandler()
	h.spp = mh.spp.ToHandler()
	h.api = mh.api.ToHandler()
	return
}

type Handlers struct {
	auth    http.Handler
	brain   http.Handler
	billing http.Handler
	spp     http.Handler
	api     http.Handler
}

func (h *Handlers) Fill(t *testing.T) {
	if h.brain == nil {
		h.brain = mkNilHandler(t)
	}
	if h.billing == nil {
		h.billing = mkNilHandler(t)
	}
	if h.spp == nil {
		h.spp = mkNilHandler(t)
	}
	if h.api == nil {
		h.api = mkNilHandler(t)
	}
}

type Servers struct {
	auth    *httptest.Server
	brain   *httptest.Server
	billing *httptest.Server
	spp     *httptest.Server
	api     *httptest.Server
}

func (s *Servers) Close() {
	if s.auth != nil {
		s.auth.Close()
	}
	if s.brain != nil {
		s.brain.Close()
	}
	if s.billing != nil {
		s.billing.Close()
	}
	if s.spp != nil {
		s.spp.Close()
	}
	if s.api != nil {
		s.api.Close()
	}
	s.auth = nil
	s.brain = nil
	s.billing = nil
	s.spp = nil
	s.api = nil
}

// URLs creates an EndpointURLs
func (s Servers) URLs() (urls EndpointURLs) {
	urls.API = s.api.URL
	urls.Auth = s.auth.URL
	urls.Billing = s.billing.URL
	urls.Brain = s.brain.URL
	urls.SPP = s.spp.URL
	return
}

// Client makes a bytemarkClient for these Servers
func (s Servers) Client() (c Client, err error) {
	urls := s.URLs()
	c, err = NewWithURLs(urls)
	if err != nil {
		return nil, err
	}
	c.AllowInsecureRequests()
	return
}

// mkTestClientAndServers constructs httptest Servers for a pretend auth and API endpoint, then constructs a Client that uses those servers.
// Used to test that the right URLs are being requested and such.
func mkTestClientAndServers(t *testing.T, h Handlers) (c Client, s Servers, err error) {
	h.Fill(t)

	if h.auth != nil {
		s.auth = mkTestServer(h.auth)
	} else {
		s.auth = mkTestAuthServer()
	}
	s.brain = mkTestServer(h.brain)
	s.billing = mkTestServer(h.billing)
	s.api = mkTestServer(h.api)
	s.spp = mkTestServer(h.spp)

	c, err = s.Client()
	return
}

// mkTestServer creates an httptest.Server for the given http.Handler. It's basically an alias for httptest.NewServer. Why did I write it?
func mkTestServer(handler http.Handler) *httptest.Server {
	return httptest.NewServer(handler)
}

func mkNilHandler(t *testing.T) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		t.Fatalf("Unexpected request to a nil server\r\n%s %s", r.Method, r.URL.String())
	})
}

func mkTestAuthServer() *httptest.Server {
	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w,
			`{
    "token": "working-auth-token",
    "username": "account",
    "factors": []
}`)
	}))

}
<|endoftext|>