<commit_before>package detailed

import (
	"sort"
	"time"

	"github.com/ugorji/go/codec"

	"github.com/weaveworks/scope/probe/awsecs"
	"github.com/weaveworks/scope/probe/docker"
	"github.com/weaveworks/scope/probe/host"
	"github.com/weaveworks/scope/probe/kubernetes"
	"github.com/weaveworks/scope/probe/process"
	"github.com/weaveworks/scope/report"
)

// Node is the data type that's yielded to the JavaScript layer when
// we want deep information about an individual node.
type Node struct {
	NodeSummary
	Controls    []ControlInstance    `json:"controls"`
	Children    []NodeSummaryGroup   `json:"children,omitempty"`
	Connections []ConnectionsSummary `json:"connections,omitempty"`
}

// ControlInstance contains a control description, and all the info
// needed to execute it.
type ControlInstance struct {
	ProbeID string
	NodeID  string
	Control report.Control
}

// MarshalJSON shouldn't be used, use CodecEncodeSelf instead
func (ControlInstance) MarshalJSON() ([]byte, error) {
	panic("MarshalJSON shouldn't be used, use CodecEncodeSelf instead")
}

// UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead
func (*ControlInstance) UnmarshalJSON(b []byte) error {
	panic("UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead")
}

type wiredControlInstance struct {
	ProbeID string `json:"probeId"`
	NodeID  string `json:"nodeId"`
	ID      string `json:"id"`
	Human   string `json:"human"`
	Icon    string `json:"icon"`
	Rank    int    `json:"rank"`
}

// CodecEncodeSelf marshals this ControlInstance. It takes the basic Metric
// rendering, then adds some row-specific fields.
func (c *ControlInstance) CodecEncodeSelf(encoder *codec.Encoder) {
	encoder.Encode(wiredControlInstance{
		ProbeID: c.ProbeID,
		NodeID:  c.NodeID,
		ID:      c.Control.ID,
		Human:   c.Control.Human,
		Icon:    c.Control.Icon,
		Rank:    c.Control.Rank,
	})
}

// CodecDecodeSelf implements codec.Selfer
func (c *ControlInstance) CodecDecodeSelf(decoder *codec.Decoder) {
	var in wiredControlInstance
	decoder.Decode(&in)
	*c = ControlInstance{
		ProbeID: in.ProbeID,
		NodeID:  in.NodeID,
		Control: report.Control{
			ID:    in.ID,
			Human: in.Human,
			Icon:  in.Icon,
			Rank:  in.Rank,
		},
	}
}

// MakeNode transforms a renderable node to a detailed node. It uses
// aggregate metadata, plus the set of origin node IDs, to produce tables.
func MakeNode(topologyID string, r report.Report, ns report.Nodes, n report.Node) Node {
	summary, _ := MakeNodeSummary(r, n)
	return Node{
		NodeSummary: summary,
		Controls:    controls(r, n),
		Children:    children(r, n),
		Connections: []ConnectionsSummary{
			incomingConnectionsSummary(topologyID, r, n, ns),
			outgoingConnectionsSummary(topologyID, r, n, ns),
		},
	}
}

func controlsFor(topology report.Topology, nodeID string) []ControlInstance {
	result := []ControlInstance{}
	node, ok := topology.Nodes[nodeID]
	if !ok {
		return result
	}
	probeID, ok := node.Latest.Lookup(report.ControlProbeID)
	if !ok {
		return result
	}
	node.LatestControls.ForEach(func(controlID string, _ time.Time, data report.NodeControlData) {
		if data.Dead {
			return
		}
		if control, ok := topology.Controls[controlID]; ok {
			result = append(result, ControlInstance{
				ProbeID: probeID,
				NodeID:  nodeID,
				Control: control,
			})
		}
	})
	return result
}

func controls(r report.Report, n report.Node) []ControlInstance {
	if t, ok := r.Topology(n.Topology); ok {
		return controlsFor(t, n.ID)
	}
	return []ControlInstance{}
}

var nodeSummaryGroupSpecs = []struct {
	topologyID string
	NodeSummaryGroup
}{
	{
		topologyID: report.Host,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Hosts",
			Columns: []Column{
				{ID: host.CPUUsage, Label: "CPU", Datatype: "number"},
				{ID: host.MemoryUsage, Label: "Memory", Datatype: "number"},
			},
		},
	},
	{
		topologyID: report.Service,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Services",
			Columns: []Column{
				{ID: report.Pod, Label: "# Pods", Datatype: "number"},
				{ID: kubernetes.IP, Label: "IP", Datatype: "ip"},
			},
		},
	},
	{
		topologyID: report.ReplicaSet,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Replica Sets",
			Columns: []Column{
				{ID: report.Pod, Label: "# Pods", Datatype: "number"},
				{ID: kubernetes.ObservedGeneration, Label: "Observed Gen.", Datatype: "number"},
			},
		},
	},
	{
		topologyID: report.Pod,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Pods",

			Columns: []Column{
				{ID: kubernetes.State, Label: "State"},
				{ID: report.Container, Label: "# Containers", Datatype: "number"},
				{ID: kubernetes.IP, Label: "IP", Datatype: "ip"},
			},
		},
	},
	{
		topologyID: report.ECSService,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Services",
			Columns: []Column{
				{ID: awsecs.ServiceRunningCount, Label: "Running", Datatype: "number"},
				{ID: awsecs.ServiceDesiredCount, Label: "Desired", Datatype: "number"},
			},
		},
	},
	{
		topologyID: report.ECSTask,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Tasks",
			Columns: []Column{
				{ID: awsecs.CreatedAt, Label: "Created At", Datatype: "datetime"},
			},
		},
	},
	{
		topologyID: report.Container,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Containers", Columns: []Column{
				{ID: docker.CPUTotalUsage, Label: "CPU", Datatype: "number"},
				{ID: docker.MemoryUsage, Label: "Memory", Datatype: "number"},
			},
		},
	},
	{
		topologyID: report.Process,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Processes", Columns: []Column{
				{ID: process.PID, Label: "PID", Datatype: "number"},
				{ID: process.CPUUsage, Label: "CPU", Datatype: "number"},
				{ID: process.MemoryUsage, Label: "Memory", Datatype: "number"},
			},
		},
	},
	{
		topologyID: report.ContainerImage,
		NodeSummaryGroup: NodeSummaryGroup{
			TopologyID: "containers-by-image",
			Label:      "Container Images",
			Columns: []Column{
				{ID: report.Container, Label: "# Containers", DefaultSort: true, Datatype: "number"},
			},
		},
	},
}

func children(r report.Report, n report.Node) []NodeSummaryGroup {
	summaries := map[string][]NodeSummary{}
	n.Children.ForEach(func(child report.Node) {
		if child.ID == n.ID {
			return
		}
		summary, ok := MakeNodeSummary(r, child)
		if !ok {
			return
		}
		summaries[child.Topology] = append(summaries[child.Topology], summary.SummarizeMetrics())
	})

	nodeSummaryGroups := []NodeSummaryGroup{}
	// Apply specific group specs in the order they're listed
	for _, spec := range nodeSummaryGroupSpecs {
		if len(summaries[spec.topologyID]) == 0 {
			continue
		}
		apiTopology, ok := primaryAPITopology[spec.topologyID]
		if !ok {
			continue
		}
		sort.Sort(nodeSummariesByID(summaries[spec.topologyID]))
		group := spec.NodeSummaryGroup
		group.Nodes = summaries[spec.topologyID]
		group.TopologyID = apiTopology
		nodeSummaryGroups = append(nodeSummaryGroups, group)
		delete(summaries, spec.topologyID)
	}
	// As a fallback, in case a topology has no group spec defined, add any remaining at the end
	for topologyID, nodeSummaries := range summaries {
		if len(nodeSummaries) == 0 {
			continue
		}
		topology, ok := r.Topology(topologyID)
		if !ok {
			continue
		}
		apiTopology, ok := primaryAPITopology[topologyID]
		if !ok {
			continue
		}
		sort.Sort(nodeSummariesByID(nodeSummaries))
		group := NodeSummaryGroup{
			TopologyID: apiTopology,
			Label:      topology.LabelPlural,
			Columns:    []Column{},
		}
		nodeSummaryGroups = append(nodeSummaryGroups, group)
	}

	return nodeSummaryGroups
}
<commit_msg>make nodeSummaryGroupSpecs only include what's needed<commit_after>package detailed

import (
	"sort"
	"time"

	"github.com/ugorji/go/codec"

	"github.com/weaveworks/scope/probe/awsecs"
	"github.com/weaveworks/scope/probe/docker"
	"github.com/weaveworks/scope/probe/kubernetes"
	"github.com/weaveworks/scope/probe/process"
	"github.com/weaveworks/scope/report"
)

// Node is the data type that's yielded to the JavaScript layer when
// we want deep information about an individual node.
type Node struct {
	NodeSummary
	Controls    []ControlInstance    `json:"controls"`
	Children    []NodeSummaryGroup   `json:"children,omitempty"`
	Connections []ConnectionsSummary `json:"connections,omitempty"`
}

// ControlInstance contains a control description, and all the info
// needed to execute it.
type ControlInstance struct {
	ProbeID string
	NodeID  string
	Control report.Control
}

// MarshalJSON shouldn't be used, use CodecEncodeSelf instead
func (ControlInstance) MarshalJSON() ([]byte, error) {
	panic("MarshalJSON shouldn't be used, use CodecEncodeSelf instead")
}

// UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead
func (*ControlInstance) UnmarshalJSON(b []byte) error {
	panic("UnmarshalJSON shouldn't be used, use CodecDecodeSelf instead")
}

type wiredControlInstance struct {
	ProbeID string `json:"probeId"`
	NodeID  string `json:"nodeId"`
	ID      string `json:"id"`
	Human   string `json:"human"`
	Icon    string `json:"icon"`
	Rank    int    `json:"rank"`
}

// CodecEncodeSelf marshals this ControlInstance. It takes the basic Metric
// rendering, then adds some row-specific fields.
func (c *ControlInstance) CodecEncodeSelf(encoder *codec.Encoder) {
	encoder.Encode(wiredControlInstance{
		ProbeID: c.ProbeID,
		NodeID:  c.NodeID,
		ID:      c.Control.ID,
		Human:   c.Control.Human,
		Icon:    c.Control.Icon,
		Rank:    c.Control.Rank,
	})
}

// CodecDecodeSelf implements codec.Selfer
func (c *ControlInstance) CodecDecodeSelf(decoder *codec.Decoder) {
	var in wiredControlInstance
	decoder.Decode(&in)
	*c = ControlInstance{
		ProbeID: in.ProbeID,
		NodeID:  in.NodeID,
		Control: report.Control{
			ID:    in.ID,
			Human: in.Human,
			Icon:  in.Icon,
			Rank:  in.Rank,
		},
	}
}

// MakeNode transforms a renderable node to a detailed node. It uses
// aggregate metadata, plus the set of origin node IDs, to produce tables.
func MakeNode(topologyID string, r report.Report, ns report.Nodes, n report.Node) Node {
	summary, _ := MakeNodeSummary(r, n)
	return Node{
		NodeSummary: summary,
		Controls:    controls(r, n),
		Children:    children(r, n),
		Connections: []ConnectionsSummary{
			incomingConnectionsSummary(topologyID, r, n, ns),
			outgoingConnectionsSummary(topologyID, r, n, ns),
		},
	}
}

func controlsFor(topology report.Topology, nodeID string) []ControlInstance {
	result := []ControlInstance{}
	node, ok := topology.Nodes[nodeID]
	if !ok {
		return result
	}
	probeID, ok := node.Latest.Lookup(report.ControlProbeID)
	if !ok {
		return result
	}
	node.LatestControls.ForEach(func(controlID string, _ time.Time, data report.NodeControlData) {
		if data.Dead {
			return
		}
		if control, ok := topology.Controls[controlID]; ok {
			result = append(result, ControlInstance{
				ProbeID: probeID,
				NodeID:  nodeID,
				Control: control,
			})
		}
	})
	return result
}

func controls(r report.Report, n report.Node) []ControlInstance {
	if t, ok := r.Topology(n.Topology); ok {
		return controlsFor(t, n.ID)
	}
	return []ControlInstance{}
}

// We only need to include topologies here where the nodes may appear
// as children of other nodes in some topology.
var nodeSummaryGroupSpecs = []struct {
	topologyID string
	NodeSummaryGroup
}{
	{
		topologyID: report.ReplicaSet,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Replica Sets",
			Columns: []Column{
				{ID: report.Pod, Label: "# Pods", Datatype: "number"},
				{ID: kubernetes.ObservedGeneration, Label: "Observed Gen.", Datatype: "number"},
			},
		},
	},
	{
		topologyID: report.Pod,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Pods",

			Columns: []Column{
				{ID: kubernetes.State, Label: "State"},
				{ID: report.Container, Label: "# Containers", Datatype: "number"},
				{ID: kubernetes.IP, Label: "IP", Datatype: "ip"},
			},
		},
	},
	{
		topologyID: report.ECSTask,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Tasks",
			Columns: []Column{
				{ID: awsecs.CreatedAt, Label: "Created At", Datatype: "datetime"},
			},
		},
	},
	{
		topologyID: report.Container,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Containers", Columns: []Column{
				{ID: docker.CPUTotalUsage, Label: "CPU", Datatype: "number"},
				{ID: docker.MemoryUsage, Label: "Memory", Datatype: "number"},
			},
		},
	},
	{
		topologyID: report.Process,
		NodeSummaryGroup: NodeSummaryGroup{
			Label: "Processes", Columns: []Column{
				{ID: process.PID, Label: "PID", Datatype: "number"},
				{ID: process.CPUUsage, Label: "CPU", Datatype: "number"},
				{ID: process.MemoryUsage, Label: "Memory", Datatype: "number"},
			},
		},
	},
	{
		topologyID: report.ContainerImage,
		NodeSummaryGroup: NodeSummaryGroup{
			TopologyID: "containers-by-image",
			Label:      "Container Images",
			Columns: []Column{
				{ID: report.Container, Label: "# Containers", DefaultSort: true, Datatype: "number"},
			},
		},
	},
}

func children(r report.Report, n report.Node) []NodeSummaryGroup {
	summaries := map[string][]NodeSummary{}
	n.Children.ForEach(func(child report.Node) {
		if child.ID == n.ID {
			return
		}
		summary, ok := MakeNodeSummary(r, child)
		if !ok {
			return
		}
		summaries[child.Topology] = append(summaries[child.Topology], summary.SummarizeMetrics())
	})

	nodeSummaryGroups := []NodeSummaryGroup{}
	// Apply specific group specs in the order they're listed
	for _, spec := range nodeSummaryGroupSpecs {
		if len(summaries[spec.topologyID]) == 0 {
			continue
		}
		apiTopology, ok := primaryAPITopology[spec.topologyID]
		if !ok {
			continue
		}
		sort.Sort(nodeSummariesByID(summaries[spec.topologyID]))
		group := spec.NodeSummaryGroup
		group.Nodes = summaries[spec.topologyID]
		group.TopologyID = apiTopology
		nodeSummaryGroups = append(nodeSummaryGroups, group)
		delete(summaries, spec.topologyID)
	}
	// As a fallback, in case a topology has no group spec defined, add any remaining at the end
	for topologyID, nodeSummaries := range summaries {
		if len(nodeSummaries) == 0 {
			continue
		}
		topology, ok := r.Topology(topologyID)
		if !ok {
			continue
		}
		apiTopology, ok := primaryAPITopology[topologyID]
		if !ok {
			continue
		}
		sort.Sort(nodeSummariesByID(nodeSummaries))
		group := NodeSummaryGroup{
			TopologyID: apiTopology,
			Label:      topology.LabelPlural,
			Columns:    []Column{},
		}
		nodeSummaryGroups = append(nodeSummaryGroups, group)
	}

	return nodeSummaryGroups
}
<|endoftext|>


<commit_before>package handshaketests

import (
	"crypto/tls"
	"fmt"
	"net"
	"time"

	quic "github.com/lucas-clemente/quic-go"
	"github.com/lucas-clemente/quic-go/integrationtests/proxy"
	"github.com/lucas-clemente/quic-go/protocol"
	"github.com/lucas-clemente/quic-go/qerr"
	"github.com/lucas-clemente/quic-go/testdata"
	"github.com/lucas-clemente/quic-go/utils"

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

var _ = Describe("Handshake integration tets", func() {
	var (
		proxy         *quicproxy.QuicProxy
		server        quic.Listener
		serverConfig  *quic.Config
		testStartedAt time.Time
	)

	rtt := 300 * time.Millisecond

	BeforeEach(func() {
		serverConfig = &quic.Config{TLSConfig: testdata.GetTLSConfig()}
	})

	AfterEach(func() {
		Expect(proxy.Close()).To(Succeed())
		Expect(server.Close()).To(Succeed())
	})

	runServerAndProxy := func() {
		var err error
		// start the server
		server, err = quic.ListenAddr("localhost:0", serverConfig)
		Expect(err).ToNot(HaveOccurred())
		// start the proxy
		proxy, err = quicproxy.NewQuicProxy("localhost:0", quicproxy.Opts{
			RemoteAddr:  server.Addr().String(),
			DelayPacket: func(_ quicproxy.Direction, _ protocol.PacketNumber) time.Duration { return rtt / 2 },
		})
		Expect(err).ToNot(HaveOccurred())

		testStartedAt = time.Now()

		go func() {
			for {
				_, _ = server.Accept()
			}
		}()
	}

	expectDurationInRTTs := func(num int) {
		testDuration := time.Now().Sub(testStartedAt)
		expectedDuration := time.Duration(num) * rtt
		Expect(testDuration).To(SatisfyAll(
			BeNumerically(">=", expectedDuration),
			BeNumerically("<", expectedDuration+rtt/3),
		))
	}

	It("fails when there's no matching version, after 1 RTT", func() {
		Expect(len(protocol.SupportedVersions)).To(BeNumerically(">", 1))
		serverConfig.Versions = protocol.SupportedVersions[:1]
		runServerAndProxy()
		clientConfig := &quic.Config{
			Versions: protocol.SupportedVersions[1:2],
		}
		_, err := quic.DialAddr(proxy.LocalAddr().String(), clientConfig)
		Expect(err).To(HaveOccurred())
		Expect(err.(qerr.ErrorCode)).To(Equal(qerr.InvalidVersion))
		expectDurationInRTTs(1)
	})

	// 1 RTT for verifying the source address
	// 1 RTT to become secure
	// 1 RTT to become forward-secure
	It("is forward-secure after 3 RTTs", func() {
		runServerAndProxy()
		_, err := quic.DialAddr(proxy.LocalAddr().String(), &quic.Config{TLSConfig: &tls.Config{InsecureSkipVerify: true}})
		Expect(err).ToNot(HaveOccurred())
		expectDurationInRTTs(3)
	})

	// 1 RTT for verifying the source address
	// 1 RTT to become secure
	// TODO (marten-seemann): enable this test (see #625)
	PIt("is secure after 2 RTTs", func() {
		utils.SetLogLevel(utils.LogLevelDebug)
		runServerAndProxy()
		_, err := quic.DialAddrNonFWSecure(proxy.LocalAddr().String(), &quic.Config{TLSConfig: &tls.Config{InsecureSkipVerify: true}})
		fmt.Println("#### is non fw secure ###")
		Expect(err).ToNot(HaveOccurred())
		expectDurationInRTTs(2)
	})

	It("is forward-secure after 2 RTTs when the server doesn't require an STK", func() {
		serverConfig.AcceptSTK = func(_ net.Addr, _ *quic.STK) bool {
			return true
		}
		runServerAndProxy()
		_, err := quic.DialAddr(proxy.LocalAddr().String(), &quic.Config{TLSConfig: &tls.Config{InsecureSkipVerify: true}})
		Expect(err).ToNot(HaveOccurred())
		expectDurationInRTTs(2)
	})

	It("doesn't complete the handshake when the server never accepts the STK", func() {
		serverConfig.AcceptSTK = func(_ net.Addr, _ *quic.STK) bool {
			return false
		}
		runServerAndProxy()
		_, err := quic.DialAddr(proxy.LocalAddr().String(), &quic.Config{TLSConfig: &tls.Config{InsecureSkipVerify: true}})
		Expect(err).To(HaveOccurred())
		Expect(err.(*qerr.QuicError).ErrorCode).To(Equal(qerr.CryptoTooManyRejects))
	})
})
<commit_msg>add a handshake integration test for the handshake timeout<commit_after>package handshaketests

import (
	"crypto/tls"
	"fmt"
	"net"
	"time"

	quic "github.com/lucas-clemente/quic-go"
	"github.com/lucas-clemente/quic-go/integrationtests/proxy"
	"github.com/lucas-clemente/quic-go/protocol"
	"github.com/lucas-clemente/quic-go/qerr"
	"github.com/lucas-clemente/quic-go/testdata"
	"github.com/lucas-clemente/quic-go/utils"

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

var _ = Describe("Handshake integration tets", func() {
	var (
		proxy         *quicproxy.QuicProxy
		server        quic.Listener
		serverConfig  *quic.Config
		testStartedAt time.Time
	)

	rtt := 300 * time.Millisecond

	BeforeEach(func() {
		serverConfig = &quic.Config{TLSConfig: testdata.GetTLSConfig()}
	})

	AfterEach(func() {
		Expect(proxy.Close()).To(Succeed())
		Expect(server.Close()).To(Succeed())
	})

	runServerAndProxy := func() {
		var err error
		// start the server
		server, err = quic.ListenAddr("localhost:0", serverConfig)
		Expect(err).ToNot(HaveOccurred())
		// start the proxy
		proxy, err = quicproxy.NewQuicProxy("localhost:0", quicproxy.Opts{
			RemoteAddr:  server.Addr().String(),
			DelayPacket: func(_ quicproxy.Direction, _ protocol.PacketNumber) time.Duration { return rtt / 2 },
		})
		Expect(err).ToNot(HaveOccurred())

		testStartedAt = time.Now()

		go func() {
			for {
				_, _ = server.Accept()
			}
		}()
	}

	expectDurationInRTTs := func(num int) {
		testDuration := time.Now().Sub(testStartedAt)
		expectedDuration := time.Duration(num) * rtt
		Expect(testDuration).To(SatisfyAll(
			BeNumerically(">=", expectedDuration),
			BeNumerically("<", expectedDuration+rtt/3),
		))
	}

	It("fails when there's no matching version, after 1 RTT", func() {
		Expect(len(protocol.SupportedVersions)).To(BeNumerically(">", 1))
		serverConfig.Versions = protocol.SupportedVersions[:1]
		runServerAndProxy()
		clientConfig := &quic.Config{
			Versions: protocol.SupportedVersions[1:2],
		}
		_, err := quic.DialAddr(proxy.LocalAddr().String(), clientConfig)
		Expect(err).To(HaveOccurred())
		Expect(err.(qerr.ErrorCode)).To(Equal(qerr.InvalidVersion))
		expectDurationInRTTs(1)
	})

	// 1 RTT for verifying the source address
	// 1 RTT to become secure
	// 1 RTT to become forward-secure
	It("is forward-secure after 3 RTTs", func() {
		runServerAndProxy()
		_, err := quic.DialAddr(proxy.LocalAddr().String(), &quic.Config{TLSConfig: &tls.Config{InsecureSkipVerify: true}})
		Expect(err).ToNot(HaveOccurred())
		expectDurationInRTTs(3)
	})

	// 1 RTT for verifying the source address
	// 1 RTT to become secure
	// TODO (marten-seemann): enable this test (see #625)
	PIt("is secure after 2 RTTs", func() {
		utils.SetLogLevel(utils.LogLevelDebug)
		runServerAndProxy()
		_, err := quic.DialAddrNonFWSecure(proxy.LocalAddr().String(), &quic.Config{TLSConfig: &tls.Config{InsecureSkipVerify: true}})
		fmt.Println("#### is non fw secure ###")
		Expect(err).ToNot(HaveOccurred())
		expectDurationInRTTs(2)
	})

	It("is forward-secure after 2 RTTs when the server doesn't require an STK", func() {
		serverConfig.AcceptSTK = func(_ net.Addr, _ *quic.STK) bool {
			return true
		}
		runServerAndProxy()
		_, err := quic.DialAddr(proxy.LocalAddr().String(), &quic.Config{TLSConfig: &tls.Config{InsecureSkipVerify: true}})
		Expect(err).ToNot(HaveOccurred())
		expectDurationInRTTs(2)
	})

	It("doesn't complete the handshake when the server never accepts the STK", func() {
		serverConfig.AcceptSTK = func(_ net.Addr, _ *quic.STK) bool {
			return false
		}
		runServerAndProxy()
		_, err := quic.DialAddr(proxy.LocalAddr().String(), &quic.Config{TLSConfig: &tls.Config{InsecureSkipVerify: true}})
		Expect(err).To(HaveOccurred())
		Expect(err.(*qerr.QuicError).ErrorCode).To(Equal(qerr.CryptoTooManyRejects))
	})

	It("doesn't complete the handshake when the handshake timeout is too short", func() {
		serverConfig.HandshakeTimeout = 2 * rtt
		runServerAndProxy()
		_, err := quic.DialAddr(proxy.LocalAddr().String(), &quic.Config{TLSConfig: &tls.Config{InsecureSkipVerify: true}})
		Expect(err).To(HaveOccurred())
		Expect(err.(*qerr.QuicError).ErrorCode).To(Equal(qerr.HandshakeTimeout))
		// 2 RTTs during the timeout
		// plus 1 RTT: the timer starts 0.5 RTTs after sending the first packet, and the CONNECTION_CLOSE needs another 0.5 RTTs to reach the client
		expectDurationInRTTs(3)
	})
})
<|endoftext|>


<commit_before>package googleloadbalancer

type TargetPools struct {
	BackupPool        string   `json:"backupPool"`
	CreationTimestamp string   `json:"creationTimestamp"`
	Description       string   `json:"description"`
	HealthChecks      []string `json:"healthChecks"`
	FailoverRatio     int      `json:"failoverRatio"`
	ID                string   `json:"id"`
	Instances         []string `json:"instances"`
	Kind              string   `json:"kind"`
	Name              string   `json:"name"`
	Region            string   `json:"region"`
	SelfLink          string   `json:"selfLink"`
	SessionAffinity   string   `json:"sessionAffinity"`
}

func (googleloadbalancer *Googleloadbalancer) Creatloadbalancer(request interface{}) (resp interface{}, err error) {

	var option TargetPools

	var Project string

	var Region string

	param := request.(map[string]interface{})

	for key, value := range param {
		switch key {
		case "Project":
			Project, _ = value.(string)

		case "name":
			name, _ := value.(string)
			option.Name = name

		case "Region":
			RegionV, _ := value.(string)
			option.Region = RegionV

		case "healthChecks":
			HealthChecksV, _ := value.([]string)
			option.HealthChecks = HealthChecksV

		case "description":
			DescriptionV, _ := value.(string)
			option.Description = Description

		case "BackupPool":
			BackupPoolV, _ := value.([]string)
			option.BackupPool = BackupPoolV

		case "failoverRatio":
			FailoverRatioV, _ := value.(int)
			option.FailoverRatio = FailoverRatio

		case "id":
			IDV, _ := value.(string)
			option.ID = ID

		case "instances":
			InstancesV, _ := value.([]string)
			option.Instances = Instances

		case "kind":
			KindV, _ := value.(string)
			option.Kind = KindV

		case "sessionAffinity":
			SessionAffinityV, _ := value.(string)
			option.SessionAffinity = SessionAffinityV

		case "name":
			NameV, _ := value.(string)
			option.Name = NameV

		case "region":
			RegionV, _ := value.(string)
			option.FailoverRatio = FailoverRatio

		case "selfLink":
			SelfLinkV, _ := value.(string)
			option.SelfLink = SelfLinkV

		}
	}

	option.CreationTimestamp = ""

	Creatloadbalancerjsonmap := make(map[string]interface{})

	Creatloadbalancerdictnoaryconvert(option, Creatloadbalancerjsonmap)

	Creatloadbalancerjson, _ := json.Marshal(Creatloadbalancerjsonmap)

	Creatloadbalancerjsonstring := string(Createclusterjson)

	fmt.Println(Creatloadbalancerjsonstring)

	var Creatloadbalancerstringbyte = []byte(Creatloadbalancerjsonstring)

	url := "https://www.googleapis.com/compute/v1/projects/" + Project + "regions/" + option.Region + "targetPools"

	client := googleauth.SignJWT()

	Creatloadbalancerrequest, err := http.NewRequest("POST", url, bytes.NewBuffer(Creatloadbalancerjsonstringbyte))

	Creatloadbalancerrequest.Header.Set("Content-Type", "application/json")

	Creatloadbalancerresp, err := client.Do(Creatloadbalancerrequest)

	defer Creatloadbalancerresp.Body.Close()

	body, err := ioutil.ReadAll(Creatloadbalancerresp.Body)

	fmt.Println(string(body))

	return

}

func Creatloadbalancerdictnoaryconvert(option TargetPools, Creatloadbalancerjsonmap map[string]interface{}){

	if(option.ID == ""){
		Creatloadbalancerjsonmap["id"]= option.ID
	}

	if(len(option.BackupPool) != 0){
		Creatloadbalancerjsonmap["backupPool"]= option.BackupPool
	}

	if(len(option.Instances) != 0){
		Creatloadbalancerjsonmap["instances"]= option.Instances
	}

	if(len(option.FailoverRatio) != 0){
		Creatloadbalancerjsonmap["failoverRatio"]= option.FailoverRatio
	}

	if(option.CreationTimestamp == ""){
		Creatloadbalancerjsonmap["creationTimestamp"]= option.CreationTimestamp
	}

	if(option.Description == ""){
		Creatloadbalancerjsonmap["description"]= option.Description
	}

	if(option.HealthChecks == ""){
		Creatloadbalancerjsonmap["healthChecks"]= option.HealthChecks
	}

	if(option.SessionAffinity == ""){
		Creatloadbalancerjsonmap["sessionAffinity"]= option.SessionAffinity
	}

	if(option.SelfLink == ""){
		Creatloadbalancerjsonmap["selfLink"]= option.SelfLink
	}
	if(option.Region == ""){
		Creatloadbalancerjsonmap["region"]= option.Region
	}

	if(option.Name == ""){
		Creatloadbalancerjsonmap["name"]= option.Name
	}

	if(option.Kind == ""){
		Creatloadbalancerjsonmap["kind"]= option.Kind
	}

}

func (googleloadbalancer *Googleloadbalancer) Deleteloadbalancer(request interface{}) (resp interface{}, err error) {

		options := request.(map[string]string)

		url := "https://www.googleapis.com/compute/v1/projects/" + options["project"] + "/regions/" + options["region"] + "/targetPools/" + options["targetPool"]

		client := googleauth.SignJWT()

		Deleteloadbalancerrequest, err := http.NewRequest("DELETE", url, nil)
		Deleteloadbalancerrequest.Header.Set("Content-Type", "application/json")

		Deleteloadbalancerresp, err := client.Do(Deleteloadbalancerrequest)

		defer Deleteloadbalancerresp.Body.Close()

		body, err := ioutil.ReadAll(Deleteloadbalancerresp.Body)

		fmt.Println(string(body))

		return
}

func (googleloadbalancer *Googleloadbalancer) Listloadbalancer(request interface{}) (resp interface{}, err error) {

	options := request.(map[string]string)

	url := "https://www.googleapis.com/compute/v1/projects/" + options["project"] + "/regions/" + options["region"] + "/targetPools/"

	client := googleauth.SignJWT()

	Listloadbalancerrequest, err := http.NewRequest("GET", url, nil)
	Listloadbalancerrequest.Header.Set("Content-Type", "application/json")

	Listloadbalancerresp, err := client.Do(Listloadbalancerrequest)

	defer Listloadbalancerresp.Body.Close()

	body, err := ioutil.ReadAll(Listloadbalancerresp.Body)

	fmt.Println(string(body))

	return
}

func (googleloadbalancer *Googleloadbalancer) Attachnodewithloadbalancer(request interface{}) (resp interface{}, err error) {

	var TargetPool string

	var Project string

	var Region string

	var Instances []string

	param := request.(map[string]interface{})

	for key, value := range param {
		switch key {
		case "Project":
			Project, _ = value.(string)

		case "TargetPool":
			TargetPoolV, _ := value.(string)
			TargetPool = TargetPoolV

		case "Region":
			RegionV, _ := value.(string)
			Region = RegionV

		case "Instances":
			InstancesV, _ := value.([]string)
			Instances = InstancesV
		}
}
	url := "https://www.googleapis.com/compute/v1/projects/" + Project + "/regions/" + Region + "/targetPools/" + TargetPool +"/addInstance"

	Attachnodewithloadbalancerjsonmap := make(map[string]interface{})

	if(len(Instances)!=0){
		instance := []interface{}
		for i :=0;i<(len(Instances));i++{
				val= map[string]string{}
				val["instance"] = Instances[i]
				instance = instance.append(val)
		}
		Attachnodewithloadbalancerjsonmap["instances"] = instance
	}

	Attachnodewithloadbalancerjson, _ := json.Marshal(Attachnodewithloadbalancerjsonmap)

	Attachnodewithloadbalancerjsonstring := string(Attachnodewithloadbalancerjson)

	fmt.Println(Attachnodewithloadbalancerjsonstring)

	var Attachnodewithloadbalancerstringbyte = []byte(Attachnodewithloadbalancerjsonstring)

	client := googleauth.SignJWT()

	Creatloadbalancerrequest, err := http.NewRequest("POST", url, bytes.NewBuffer(Attachnodewithloadbalancerjsonstringbyte))

	Attachnodewithloadbalancerrequest.Header.Set("Content-Type", "application/json")

	Attachnodewithloadbalancerresp, err := client.Do(Attachnodewithloadbalancerrequest)

	defer Attachnodewithloadbalancerresp.Body.Close()

	body, err := ioutil.ReadAll(Attachnodewithloadbalancerresp.Body)

	fmt.Println(string(body))

	return
}

func (googleloadbalancer *Googleloadbalancer) Detachnodewithloadbalancer(request interface{}) (resp interface{}, err error) {
	var TargetPool string

	var Project string

	var Region string

	var Instances []string

	param := request.(map[string]interface{})

	for key, value := range param {
		switch key {
		case "Project":
			Project, _ = value.(string)

		case "TargetPool":
			TargetPoolV, _ := value.(string)
			TargetPool = TargetPoolV

		case "Region":
			RegionV, _ := value.(string)
			Region = RegionV

		case "Instances":
			InstancesV, _ := value.([]string)
			Instances = InstancesV
		}
}
	url := "https://www.googleapis.com/compute/v1/projects/" + Project + "/regions/" + Region + "/targetPools/" + TargetPool +"/addInstance"

	Detachnodewithloadbalancerjsonmap := make(map[string]interface{})

	if(len(Instances)!=0){
		instance := []interface{}
		for i :=0;i<(len(Instances));i++{
				val= map[string]string{}
				val["instance"] = Instances[i]
				instance = instance.append(val)
		}
		Detachnodewithloadbalancerjsonmap["instances"] = instance
	}

	Detachnodewithloadbalancerjson, _ := json.Marshal(Detachnodewithloadbalancerjsonmap)

	Detachnodewithloadbalancerjsonstring := string(Detachnodewithloadbalancerjson)

	fmt.Println(Detachnodewithloadbalancerjsonstring)

	var Detachnodewithloadbalancerstringbyte = []byte(Detachnodewithloadbalancerjsonstring)

	client := googleauth.SignJWT()

	Detachnodewithloadbalancerrequest, err := http.NewRequest("POST", url, bytes.NewBuffer(Detachnodewithloadbalancerjsonstringbyte))

	Detachnodewithloadbalancerrequest.Header.Set("Content-Type", "application/json")

	Attachnodewithloadbalancerresp, err := client.Do(Detachnodewithloadbalancerrequest)

	defer Detachnodewithloadbalancerresp.Body.Close()

	body, err := ioutil.ReadAll(Detachnodewithloadbalancerresp.Body)

	fmt.Println(string(body))

	return

}
<commit_msg>gofmt<commit_after>package googleloadbalancer

type TargetPools struct {
	BackupPool        string   `json:"backupPool"`
	CreationTimestamp string   `json:"creationTimestamp"`
	Description       string   `json:"description"`
	HealthChecks      []string `json:"healthChecks"`
	FailoverRatio     int      `json:"failoverRatio"`
	ID                string   `json:"id"`
	Instances         []string `json:"instances"`
	Kind              string   `json:"kind"`
	Name              string   `json:"name"`
	Region            string   `json:"region"`
	SelfLink          string   `json:"selfLink"`
	SessionAffinity   string   `json:"sessionAffinity"`
}

func (googleloadbalancer *Googleloadbalancer) Creatloadbalancer(request interface{}) (resp interface{}, err error) {

	var option TargetPools

	var Project string

	var Region string

	param := request.(map[string]interface{})

	for key, value := range param {
		switch key {
		case "Project":
			Project, _ = value.(string)

		case "name":
			name, _ := value.(string)
			option.Name = name

		case "Region":
			RegionV, _ := value.(string)
			option.Region = RegionV

		case "healthChecks":
			HealthChecksV, _ := value.([]string)
			option.HealthChecks = HealthChecksV

		case "description":
			DescriptionV, _ := value.(string)
			option.Description = Description

		case "BackupPool":
			BackupPoolV, _ := value.([]string)
			option.BackupPool = BackupPoolV

		case "failoverRatio":
			FailoverRatioV, _ := value.(int)
			option.FailoverRatio = FailoverRatio

		case "id":
			IDV, _ := value.(string)
			option.ID = ID

		case "instances":
			InstancesV, _ := value.([]string)
			option.Instances = Instances

		case "kind":
			KindV, _ := value.(string)
			option.Kind = KindV

		case "sessionAffinity":
			SessionAffinityV, _ := value.(string)
			option.SessionAffinity = SessionAffinityV

		case "name":
			NameV, _ := value.(string)
			option.Name = NameV

		case "region":
			RegionV, _ := value.(string)
			option.FailoverRatio = FailoverRatio

		case "selfLink":
			SelfLinkV, _ := value.(string)
			option.SelfLink = SelfLinkV

		}
	}

	option.CreationTimestamp = ""

	Creatloadbalancerjsonmap := make(map[string]interface{})

	Creatloadbalancerdictnoaryconvert(option, Creatloadbalancerjsonmap)

	Creatloadbalancerjson, _ := json.Marshal(Creatloadbalancerjsonmap)

	Creatloadbalancerjsonstring := string(Createclusterjson)

	fmt.Println(Creatloadbalancerjsonstring)

	var Creatloadbalancerstringbyte = []byte(Creatloadbalancerjsonstring)

	url := "https://www.googleapis.com/compute/v1/projects/" + Project + "regions/" + option.Region + "targetPools"

	client := googleauth.SignJWT()

	Creatloadbalancerrequest, err := http.NewRequest("POST", url, bytes.NewBuffer(Creatloadbalancerjsonstringbyte))

	Creatloadbalancerrequest.Header.Set("Content-Type", "application/json")

	Creatloadbalancerresp, err := client.Do(Creatloadbalancerrequest)

	defer Creatloadbalancerresp.Body.Close()

	body, err := ioutil.ReadAll(Creatloadbalancerresp.Body)

	fmt.Println(string(body))

	return

}

func Creatloadbalancerdictnoaryconvert(option TargetPools, Creatloadbalancerjsonmap map[string]interface{}){

	if(option.ID == ""){
		Creatloadbalancerjsonmap["id"]= option.ID
	}

	if(len(option.BackupPool) != 0){
		Creatloadbalancerjsonmap["backupPool"]= option.BackupPool
	}

	if(len(option.Instances) != 0){
		Creatloadbalancerjsonmap["instances"]= option.Instances
	}

	if(len(option.FailoverRatio) != 0){
		Creatloadbalancerjsonmap["failoverRatio"]= option.FailoverRatio
	}

	if(option.CreationTimestamp == ""){
		Creatloadbalancerjsonmap["creationTimestamp"]= option.CreationTimestamp
	}

	if(option.Description == ""){
		Creatloadbalancerjsonmap["description"]= option.Description
	}

	if(option.HealthChecks == ""){
		Creatloadbalancerjsonmap["healthChecks"]= option.HealthChecks
	}

	if(option.SessionAffinity == ""){
		Creatloadbalancerjsonmap["sessionAffinity"]= option.SessionAffinity
	}

	if(option.SelfLink == ""){
		Creatloadbalancerjsonmap["selfLink"]= option.SelfLink
	}
	if(option.Region == ""){
		Creatloadbalancerjsonmap["region"]= option.Region
	}

	if(option.Name == ""){
		Creatloadbalancerjsonmap["name"]= option.Name
	}

	if(option.Kind == ""){
		Creatloadbalancerjsonmap["kind"]= option.Kind
	}

}

func (googleloadbalancer *Googleloadbalancer) Deleteloadbalancer(request interface{}) (resp interface{}, err error) {

		options := request.(map[string]string)

		url := "https://www.googleapis.com/compute/v1/projects/" + options["project"] + "/regions/" + options["region"] + "/targetPools/" + options["targetPool"]

		client := googleauth.SignJWT()

		Deleteloadbalancerrequest, err := http.NewRequest("DELETE", url, nil)
		Deleteloadbalancerrequest.Header.Set("Content-Type", "application/json")

		Deleteloadbalancerresp, err := client.Do(Deleteloadbalancerrequest)

		defer Deleteloadbalancerresp.Body.Close()

		body, err := ioutil.ReadAll(Deleteloadbalancerresp.Body)

		fmt.Println(string(body))

		return
}

func (googleloadbalancer *Googleloadbalancer) Listloadbalancer(request interface{}) (resp interface{}, err error) {

	options := request.(map[string]string)

	url := "https://www.googleapis.com/compute/v1/projects/" + options["project"] + "/regions/" + options["region"] + "/targetPools/"

	client := googleauth.SignJWT()

	Listloadbalancerrequest, err := http.NewRequest("GET", url, nil)
	Listloadbalancerrequest.Header.Set("Content-Type", "application/json")

	Listloadbalancerresp, err := client.Do(Listloadbalancerrequest)

	defer Listloadbalancerresp.Body.Close()

	body, err := ioutil.ReadAll(Listloadbalancerresp.Body)

	fmt.Println(string(body))

	return
}

func (googleloadbalancer *Googleloadbalancer) Attachnodewithloadbalancer(request interface{}) (resp interface{}, err error) {

	var TargetPool string

	var Project string

	var Region string

	var Instances []string

	param := request.(map[string]interface{})

	for key, value := range param {
		switch key {
		case "Project":
			Project, _ = value.(string)

		case "TargetPool":
			TargetPoolV, _ := value.(string)
			TargetPool = TargetPoolV

		case "Region":
			RegionV, _ := value.(string)
			Region = RegionV

		case "Instances":
			InstancesV, _ := value.([]string)
			Instances = InstancesV
		}
}
	url := "https://www.googleapis.com/compute/v1/projects/" + Project + "/regions/" + Region + "/targetPools/" + TargetPool +"/addInstance"

	Attachnodewithloadbalancerjsonmap := make(map[string]interface{})

	if(len(Instances)!=0){
		instance := []interface{}{}
		for i :=0;i<(len(Instances));i++{
				val= map[string]string{}
				val["instance"] = Instances[i]
				instance = instance.append(val)
		}
		Attachnodewithloadbalancerjsonmap["instances"] = instance
	}

	Attachnodewithloadbalancerjson, _ := json.Marshal(Attachnodewithloadbalancerjsonmap)

	Attachnodewithloadbalancerjsonstring := string(Attachnodewithloadbalancerjson)

	fmt.Println(Attachnodewithloadbalancerjsonstring)

	var Attachnodewithloadbalancerstringbyte = []byte(Attachnodewithloadbalancerjsonstring)

	client := googleauth.SignJWT()

	Creatloadbalancerrequest, err := http.NewRequest("POST", url, bytes.NewBuffer(Attachnodewithloadbalancerjsonstringbyte))

	Attachnodewithloadbalancerrequest.Header.Set("Content-Type", "application/json")

	Attachnodewithloadbalancerresp, err := client.Do(Attachnodewithloadbalancerrequest)

	defer Attachnodewithloadbalancerresp.Body.Close()

	body, err := ioutil.ReadAll(Attachnodewithloadbalancerresp.Body)

	fmt.Println(string(body))

	return
}

func (googleloadbalancer *Googleloadbalancer) Detachnodewithloadbalancer(request interface{}) (resp interface{}, err error) {
	var TargetPool string

	var Project string

	var Region string

	var Instances []string

	param := request.(map[string]interface{})

	for key, value := range param {
		switch key {
		case "Project":
			Project, _ = value.(string)

		case "TargetPool":
			TargetPoolV, _ := value.(string)
			TargetPool = TargetPoolV

		case "Region":
			RegionV, _ := value.(string)
			Region = RegionV

		case "Instances":
			InstancesV, _ := value.([]string)
			Instances = InstancesV
		}
}
	url := "https://www.googleapis.com/compute/v1/projects/" + Project + "/regions/" + Region + "/targetPools/" + TargetPool +"/addInstance"

	Detachnodewithloadbalancerjsonmap := make(map[string]interface{})

	if(len(Instances)!=0){
		instance := []interface{}
		for i :=0;i<(len(Instances));i++{
				val= map[string]string{}
				val["instance"] = Instances[i]
				instance = instance.append(val)
		}
		Detachnodewithloadbalancerjsonmap["instances"] = instance
	}

	Detachnodewithloadbalancerjson, _ := json.Marshal(Detachnodewithloadbalancerjsonmap)

	Detachnodewithloadbalancerjsonstring := string(Detachnodewithloadbalancerjson)

	fmt.Println(Detachnodewithloadbalancerjsonstring)

	var Detachnodewithloadbalancerstringbyte = []byte(Detachnodewithloadbalancerjsonstring)

	client := googleauth.SignJWT()

	Detachnodewithloadbalancerrequest, err := http.NewRequest("POST", url, bytes.NewBuffer(Detachnodewithloadbalancerjsonstringbyte))

	Detachnodewithloadbalancerrequest.Header.Set("Content-Type", "application/json")

	Attachnodewithloadbalancerresp, err := client.Do(Detachnodewithloadbalancerrequest)

	defer Detachnodewithloadbalancerresp.Body.Close()

	body, err := ioutil.ReadAll(Detachnodewithloadbalancerresp.Body)

	fmt.Println(string(body))

	return

}
<|endoftext|>


<commit_before>package stats

import (
	"fmt"
	"time"

	"github.com/rancher/sparse-tools/log"
)

import "sync"

const (
	defaultBufferSize = 100 * 1000 // sample buffer size (cyclic)
)

//SampleOp operation
type SampleOp int

const (
	// OpRead read from replica
	OpRead = SampleOp(0)
	// OpWrite write to replica
	OpWrite = SampleOp(1)
	// OpPing ping replica
	OpPing = SampleOp(2)
)

type dataPoint struct {
	target    int // e.g replica index
	op        SampleOp
	timestamp time.Time
	duration  time.Duration
	size      int // i/o operation size
}

// String conversions
func (op SampleOp) String() string {
	switch op {
	case OpRead:
		return "R"
	case OpWrite:
		return "W"
	case OpPing:
		return "P"
	}
	return "<unknown op>"
}

func (sample dataPoint) String() string {
	return fmt.Sprintf("%s: #%d %v[%4dkB] %8dus", sample.timestamp.Format(time.StampMicro), sample.target, sample.op, sample.size, sample.duration.Nanoseconds()/1000)
}

var (
	bufferSize = defaultBufferSize
	data       []dataPoint
	mutex      sync.Mutex
	head       = 0 // next sample index
	length     = 0
	unreported = 0 // count of not yet reported/processed samples
)

func initStats(size int) {
	bufferSize = size
	data = make([]dataPoint, size)
	head = 0
	length = 0
	unreported = 0
	log.Debug("Stats.init=", size)
}

func init() {
	initStats(bufferSize)
}

func wrapIndex(pos int) int {
	return (pos + bufferSize) % bufferSize
}

func storeSample(sample dataPoint) {
	mutex.Lock()
	log.Debug("Stats.sample[", head, "]=", sample)
	if length < bufferSize {
		length++
	}
	if unreported < bufferSize {
		unreported++
	}
	data[head] = sample
	head = wrapIndex(head + 1)
	mutex.Unlock()
}

// Sample to the cyclic buffer
func Sample(timestamp time.Time, duration time.Duration, target int, op SampleOp, size int) {
	storeSample(dataPoint{target, op, timestamp, duration, size})
}

// Process unreported samples
func Process(processor func(dataPoint)) chan struct{} {
	// Fetch unreported window
	mutex.Lock()
	items := unreported
	unreported = 0
	log.Debug("Stats.Processing unreported=", items)
	i := wrapIndex(head - items)
	dataCopy := make([]dataPoint, items)
	if i+items <= bufferSize {
		copy(dataCopy, data[i:i+items])
	} else {
		copy(dataCopy, data[i:])
		items -= bufferSize - i
		copy(dataCopy[bufferSize-i:], data[:items])
	}
	mutex.Unlock()

	done := make(chan struct{})
	go func(data []dataPoint, done chan struct{}) {
		for _, sample := range data {
			log.Debug("Stats.Processing=", sample)
			processor(sample)
		}
		close(done)
	}(dataCopy, done)
	return done
}

func printSample(sample dataPoint) {
	fmt.Println(sample)
}

// Print samples
func Print() chan struct{} {
	return Process(printSample)
}

// Test helper to exercise small buffer sizes
func resetStats(size int) {
	log.Debug("Stats.reset")
	initStats(size)
}
<commit_msg>stats: fixed size format<commit_after>package stats

import (
	"fmt"
	"time"

	"github.com/rancher/sparse-tools/log"
)

import "sync"

const (
	defaultBufferSize = 100 * 1000 // sample buffer size (cyclic)
)

//SampleOp operation
type SampleOp int

const (
	// OpRead read from replica
	OpRead = SampleOp(0)
	// OpWrite write to replica
	OpWrite = SampleOp(1)
	// OpPing ping replica
	OpPing = SampleOp(2)
)

type dataPoint struct {
	target    int // e.g replica index
	op        SampleOp
	timestamp time.Time
	duration  time.Duration
	size      int // i/o operation size
}

// String conversions
func (op SampleOp) String() string {
	switch op {
	case OpRead:
		return "R"
	case OpWrite:
		return "W"
	case OpPing:
		return "P"
	}
	return "<unknown op>"
}

func (sample dataPoint) String() string {
	return fmt.Sprintf("%s: #%d %v[%3dkB] %8dus", sample.timestamp.Format(time.StampMicro), sample.target, sample.op, sample.size/1024, sample.duration.Nanoseconds()/1000)
}

var (
	bufferSize = defaultBufferSize
	data       []dataPoint
	mutex      sync.Mutex
	head       = 0 // next sample index
	length     = 0
	unreported = 0 // count of not yet reported/processed samples
)

func initStats(size int) {
	bufferSize = size
	data = make([]dataPoint, size)
	head = 0
	length = 0
	unreported = 0
	log.Debug("Stats.init=", size)
}

func init() {
	initStats(bufferSize)
}

func wrapIndex(pos int) int {
	return (pos + bufferSize) % bufferSize
}

func storeSample(sample dataPoint) {
	mutex.Lock()
	log.Debug("Stats.sample[", head, "]=", sample)
	if length < bufferSize {
		length++
	}
	if unreported < bufferSize {
		unreported++
	}
	data[head] = sample
	head = wrapIndex(head + 1)
	mutex.Unlock()
}

// Sample to the cyclic buffer
func Sample(timestamp time.Time, duration time.Duration, target int, op SampleOp, size int) {
	storeSample(dataPoint{target, op, timestamp, duration, size})
}

// Process unreported samples
func Process(processor func(dataPoint)) chan struct{} {
	// Fetch unreported window
	mutex.Lock()
	items := unreported
	unreported = 0
	log.Debug("Stats.Processing unreported=", items)
	i := wrapIndex(head - items)
	dataCopy := make([]dataPoint, items)
	if i+items <= bufferSize {
		copy(dataCopy, data[i:i+items])
	} else {
		copy(dataCopy, data[i:])
		items -= bufferSize - i
		copy(dataCopy[bufferSize-i:], data[:items])
	}
	mutex.Unlock()

	done := make(chan struct{})
	go func(data []dataPoint, done chan struct{}) {
		for _, sample := range data {
			log.Debug("Stats.Processing=", sample)
			processor(sample)
		}
		close(done)
	}(dataCopy, done)
	return done
}

func printSample(sample dataPoint) {
	fmt.Println(sample)
}

// Print samples
func Print() chan struct{} {
	return Process(printSample)
}

// Test helper to exercise small buffer sizes
func resetStats(size int) {
	log.Debug("Stats.reset")
	initStats(size)
}
<|endoftext|>


<commit_before>package web

import (
	"errors"
	"math/rand"
	"net/http"
	"regexp"
	"strings"

	"github.com/micro/micro/v3/internal/api/resolver"
	res "github.com/micro/micro/v3/internal/api/resolver"
	"github.com/micro/micro/v3/service/router"
)

var re = regexp.MustCompile("^[a-zA-Z0-9]+([a-zA-Z0-9-]*[a-zA-Z0-9]*)?$")

type Resolver struct {
	// Options
	Options resolver.Options
	// selector to choose from a pool of nodes
	// Selector selector.Selector
	// router to lookup routes
	Router router.Router
}

func (r *Resolver) String() string {
	return "web/resolver"
}

// Resolve replaces the values of Host, Path, Scheme to calla backend service
// It accounts for subdomains for service names based on namespace
func (r *Resolver) Resolve(req *http.Request, opts ...res.ResolveOption) (*res.Endpoint, error) {
	// parse the options
	options := resolver.NewResolveOptions(opts...)

	parts := strings.Split(req.URL.Path, "/")
	if len(parts) < 2 {
		return nil, errors.New("unknown service")
	}

	if !re.MatchString(parts[1]) {
		return nil, res.ErrInvalidPath
	}

	name := parts[1]
	if len(r.Options.ServicePrefix) > 0 {
		name = r.Options.ServicePrefix + "." + name
	}

	// lookup the routes for the service
	query := []router.LookupOption{
		router.LookupNetwork(options.Domain),
	}

	routes, err := r.Router.Lookup(name, query...)
	if err == router.ErrRouteNotFound {
		return nil, res.ErrNotFound
	} else if err != nil {
		return nil, err
	} else if len(routes) == 0 {
		return nil, res.ErrNotFound
	}

	// select a random route to use
	// todo: update to use selector once go-micro has updated the interface
	// route, err := r.Selector.Select(routes...)
	// if err != nil {
	// 	return nil, err
	// }
	route := routes[rand.Intn(len(routes))]

	// we're done
	return &res.Endpoint{
		Name:   name,
		Method: req.Method,
		Host:   route.Address,
		Path:   "/" + strings.Join(parts[2:], "/"),
		Domain: options.Domain,
	}, nil
}
<commit_msg>remove duplicate import "api/resolver" (#1556)<commit_after>package web

import (
	"errors"
	"math/rand"
	"net/http"
	"regexp"
	"strings"

	"github.com/micro/micro/v3/internal/api/resolver"
	"github.com/micro/micro/v3/service/router"
)

var re = regexp.MustCompile("^[a-zA-Z0-9]+([a-zA-Z0-9-]*[a-zA-Z0-9]*)?$")

type Resolver struct {
	// Options
	Options resolver.Options
	// selector to choose from a pool of nodes
	// Selector selector.Selector
	// router to lookup routes
	Router router.Router
}

func (r *Resolver) String() string {
	return "web/resolver"
}

// Resolve replaces the values of Host, Path, Scheme to calla backend service
// It accounts for subdomains for service names based on namespace
func (r *Resolver) Resolve(req *http.Request, opts ...resolver.ResolveOption) (*resolver.Endpoint, error) {
	// parse the options
	options := resolver.NewResolveOptions(opts...)

	parts := strings.Split(req.URL.Path, "/")
	if len(parts) < 2 {
		return nil, errors.New("unknown service")
	}

	if !re.MatchString(parts[1]) {
		return nil, resolver.ErrInvalidPath
	}

	name := parts[1]
	if len(r.Options.ServicePrefix) > 0 {
		name = r.Options.ServicePrefix + "." + name
	}

	// lookup the routes for the service
	query := []router.LookupOption{
		router.LookupNetwork(options.Domain),
	}

	routes, err := r.Router.Lookup(name, query...)
	if err == router.ErrRouteNotFound {
		return nil, resolver.ErrNotFound
	} else if err != nil {
		return nil, err
	} else if len(routes) == 0 {
		return nil, resolver.ErrNotFound
	}

	// select a random route to use
	// todo: update to use selector once go-micro has updated the interface
	// route, err := r.Selector.Select(routes...)
	// if err != nil {
	// 	return nil, err
	// }
	route := routes[rand.Intn(len(routes))]

	// we're done
	return &resolver.Endpoint{
		Name:   name,
		Method: req.Method,
		Host:   route.Address,
		Path:   "/" + strings.Join(parts[2:], "/"),
		Domain: options.Domain,
	}, nil
}
<|endoftext|>


<commit_before>package adhier

import (
	"fmt"
	"math/rand"
	"testing"

	"github.com/ready-steady/numeric/basis/linhat"
	"github.com/ready-steady/numeric/grid/newcot"
	"github.com/ready-steady/support/assert"
)

func TestComputeStep(t *testing.T) {
	interpolator := prepare(&fixtureStep)
	surrogate := interpolator.Compute(step)
	assert.Equal(surrogate, fixtureStep.surrogate, t)
}

func TestEvaluateStep(t *testing.T) {
	interpolator := prepare(&fixtureStep)
	values := interpolator.Evaluate(fixtureStep.surrogate, fixtureStep.points)
	assert.Equal(values, fixtureStep.values, t)
}

func TestComputeHat(t *testing.T) {
	interpolator := prepare(&fixtureHat)
	surrogate := interpolator.Compute(hat)
	assert.Equal(surrogate, fixtureHat.surrogate, t)
}

func TestEvaluateHat(t *testing.T) {
	interpolator := prepare(&fixtureHat)
	values := interpolator.Evaluate(fixtureHat.surrogate, fixtureHat.points)
	assert.EqualWithin(values, fixtureHat.values, 1e-15, t)
}

func TestComputeCube(t *testing.T) {
	interpolator := prepare(&fixtureCube)
	surrogate := interpolator.Compute(cube)
	assert.Equal(surrogate, fixtureCube.surrogate, t)
}

func TestComputeBox(t *testing.T) {
	interpolator := prepare(&fixtureBox)
	surrogate := interpolator.Compute(box)
	assert.Equal(surrogate, fixtureBox.surrogate, t)
}

func TestEvaluateBox(t *testing.T) {
	interpolator := prepare(&fixtureBox)
	values := interpolator.Evaluate(fixtureBox.surrogate, fixtureBox.points)
	assert.EqualWithin(values, fixtureBox.values, 1e-15, t)
}

func BenchmarkComputeHat(b *testing.B) {
	interpolator := prepare(&fixtureHat)

	for i := 0; i < b.N; i++ {
		interpolator.Compute(hat)
	}
}

func BenchmarkComputeCube(b *testing.B) {
	interpolator := prepare(&fixtureCube, func(config *Config) {
		config.MaxLevel = 9
	})

	for i := 0; i < b.N; i++ {
		interpolator.Compute(cube)
	}
}

func BenchmarkComputeBox(b *testing.B) {
	interpolator := prepare(&fixtureBox, func(config *Config) {
		config.MaxLevel = 9
	})

	for i := 0; i < b.N; i++ {
		interpolator.Compute(box)
	}
}

func BenchmarkComputeMany(b *testing.B) {
	const (
		inputs  = 2
		outputs = 1000
	)

	interpolator := prepare(&fixture{
		surrogate: &Surrogate{
			Inputs:  inputs,
			Outputs: outputs,

			Level: 9,
		},
	})
	function := many(inputs, outputs)

	for i := 0; i < b.N; i++ {
		interpolator.Compute(function)
	}
}

func BenchmarkEvaluateHat(b *testing.B) {
	interpolator := prepare(&fixtureHat)
	surrogate := interpolator.Compute(hat)
	points := generate(surrogate)

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		interpolator.Evaluate(surrogate, points)
	}
}

func BenchmarkEvaluateCube(b *testing.B) {
	interpolator := prepare(&fixtureCube, func(config *Config) {
		config.MaxLevel = 9
	})
	surrogate := interpolator.Compute(cube)
	points := generate(surrogate)

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		interpolator.Evaluate(surrogate, points)
	}
}

func BenchmarkEvaluateBox(b *testing.B) {
	interpolator := prepare(&fixtureBox, func(config *Config) {
		config.MaxLevel = 9
	})
	surrogate := interpolator.Compute(box)
	points := generate(surrogate)

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		interpolator.Evaluate(surrogate, points)
	}
}

func BenchmarkEvaluateMany(b *testing.B) {
	const (
		inputs  = 2
		outputs = 1000
	)

	interpolator := prepare(&fixture{
		surrogate: &Surrogate{
			Inputs:  inputs,
			Outputs: outputs,

			Level: 9,
		},
	})
	function := many(inputs, outputs)
	surrogate := interpolator.Compute(function)
	points := generate(surrogate)

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		interpolator.Evaluate(surrogate, points)
	}
}

// A one-input-one-output scenario with a non-smooth function.
func ExampleInterpolator_step() {
	const (
		inputs  = 1
		outputs = 1
	)

	grid := newcot.NewClosed(inputs)
	basis := linhat.NewClosed(inputs)

	config := DefaultConfig(inputs, outputs)
	config.MaxLevel = 19
	interpolator, _ := New(grid, basis, config)

	surrogate := interpolator.Compute(step)
	fmt.Println(surrogate)

	// Output:
	// Surrogate{inputs: 1, outputs: 1, level: 19, nodes: 38}
}

// A one-input-one-output scenario with a smooth function.
func ExampleInterpolator_hat() {
	const (
		inputs  = 1
		outputs = 1
	)

	grid := newcot.NewClosed(inputs)
	basis := linhat.NewClosed(inputs)

	config := DefaultConfig(inputs, outputs)
	config.MaxLevel = 9
	interpolator, _ := New(grid, basis, config)

	surrogate := interpolator.Compute(hat)
	fmt.Println(surrogate)

	// Output:
	// Surrogate{inputs: 1, outputs: 1, level: 9, nodes: 305}
}

// A multiple-input-one-output scenario with a non-smooth function.
func ExampleInterpolator_cube() {
	const (
		inputs  = 2
		outputs = 1
	)

	grid := newcot.NewClosed(inputs)
	basis := linhat.NewClosed(inputs)

	config := DefaultConfig(inputs, outputs)
	config.MaxLevel = 9
	interpolator, _ := New(grid, basis, config)

	surrogate := interpolator.Compute(cube)
	fmt.Println(surrogate)

	// Output:
	// Surrogate{inputs: 2, outputs: 1, level: 9, nodes: 377}
}

// A multiple-input-many-output scenario with a non-smooth function.
func ExampleInterpolator_many() {
	const (
		inputs  = 2
		outputs = 1000
	)

	grid := newcot.NewClosed(inputs)
	basis := linhat.NewClosed(inputs)
	config := DefaultConfig(inputs, outputs)
	config.MaxNodes = 300

	interpolator, _ := New(grid, basis, config)

	surrogate := interpolator.Compute(many(inputs, outputs))
	fmt.Println(surrogate)

	// Output:
	// Surrogate{inputs: 2, outputs: 1000, level: 9, nodes: 300}
}

func prepare(fixture *fixture, arguments ...interface{}) *Interpolator {
	surrogate := fixture.surrogate

	ni, no := surrogate.Inputs, surrogate.Outputs

	config := DefaultConfig(ni, no)
	config.MaxLevel = surrogate.Level

	if len(arguments) > 0 {
		process, _ := arguments[0].(func(*Config))
		process(config)
	}

	interpolator, _ := New(newcot.NewClosed(ni), linhat.NewClosed(ni), config)

	return interpolator
}

func generate(surrogate *Surrogate) []float64 {
	const (
		count = 10000
	)

	generator := rand.New(rand.NewSource(0))
	points := make([]float64, count*surrogate.Inputs)
	for i := range points {
		points[i] = generator.Float64()
	}

	return points
}
<commit_msg>Cosmetic changes to the tests in adhier<commit_after>package adhier

import (
	"fmt"
	"math/rand"
	"testing"

	"github.com/ready-steady/numeric/basis/linhat"
	"github.com/ready-steady/numeric/grid/newcot"
	"github.com/ready-steady/support/assert"
)

func TestComputeStep(t *testing.T) {
	fixture := &fixtureStep

	interpolator := prepare(fixture)
	surrogate := interpolator.Compute(step)

	assert.Equal(surrogate, fixture.surrogate, t)
}

func TestEvaluateStep(t *testing.T) {
	fixture := &fixtureStep

	interpolator := prepare(fixture)
	values := interpolator.Evaluate(fixture.surrogate, fixture.points)

	assert.Equal(values, fixture.values, t)
}

func TestComputeHat(t *testing.T) {
	fixture := &fixtureHat

	interpolator := prepare(fixture)
	surrogate := interpolator.Compute(hat)

	assert.Equal(surrogate, fixture.surrogate, t)
}

func TestEvaluateHat(t *testing.T) {
	fixture := &fixtureHat

	interpolator := prepare(fixture)
	values := interpolator.Evaluate(fixture.surrogate, fixture.points)

	assert.EqualWithin(values, fixture.values, 1e-15, t)
}

func TestComputeCube(t *testing.T) {
	fixture := &fixtureCube

	interpolator := prepare(fixture)
	surrogate := interpolator.Compute(cube)

	assert.Equal(surrogate, fixture.surrogate, t)
}

func TestComputeBox(t *testing.T) {
	fixture := &fixtureBox

	interpolator := prepare(fixture)
	surrogate := interpolator.Compute(box)

	assert.Equal(surrogate, fixture.surrogate, t)
}

func TestEvaluateBox(t *testing.T) {
	fixture := &fixtureBox

	interpolator := prepare(fixture)
	values := interpolator.Evaluate(fixture.surrogate, fixture.points)

	assert.EqualWithin(values, fixture.values, 1e-15, t)
}

func BenchmarkComputeHat(b *testing.B) {
	interpolator := prepare(&fixtureHat)

	for i := 0; i < b.N; i++ {
		interpolator.Compute(hat)
	}
}

func BenchmarkComputeCube(b *testing.B) {
	interpolator := prepare(&fixtureCube, func(config *Config) {
		config.MaxLevel = 9
	})

	for i := 0; i < b.N; i++ {
		interpolator.Compute(cube)
	}
}

func BenchmarkComputeBox(b *testing.B) {
	interpolator := prepare(&fixtureBox, func(config *Config) {
		config.MaxLevel = 9
	})

	for i := 0; i < b.N; i++ {
		interpolator.Compute(box)
	}
}

func BenchmarkComputeMany(b *testing.B) {
	const (
		inputs  = 2
		outputs = 1000
	)

	interpolator := prepare(&fixture{
		surrogate: &Surrogate{
			Inputs:  inputs,
			Outputs: outputs,

			Level: 9,
		},
	})
	function := many(inputs, outputs)

	for i := 0; i < b.N; i++ {
		interpolator.Compute(function)
	}
}

func BenchmarkEvaluateHat(b *testing.B) {
	interpolator := prepare(&fixtureHat)
	surrogate := interpolator.Compute(hat)
	points := generate(surrogate)

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		interpolator.Evaluate(surrogate, points)
	}
}

func BenchmarkEvaluateCube(b *testing.B) {
	interpolator := prepare(&fixtureCube, func(config *Config) {
		config.MaxLevel = 9
	})
	surrogate := interpolator.Compute(cube)
	points := generate(surrogate)

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		interpolator.Evaluate(surrogate, points)
	}
}

func BenchmarkEvaluateBox(b *testing.B) {
	interpolator := prepare(&fixtureBox, func(config *Config) {
		config.MaxLevel = 9
	})
	surrogate := interpolator.Compute(box)
	points := generate(surrogate)

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		interpolator.Evaluate(surrogate, points)
	}
}

func BenchmarkEvaluateMany(b *testing.B) {
	const (
		inputs  = 2
		outputs = 1000
	)

	interpolator := prepare(&fixture{
		surrogate: &Surrogate{
			Inputs:  inputs,
			Outputs: outputs,

			Level: 9,
		},
	})
	function := many(inputs, outputs)
	surrogate := interpolator.Compute(function)
	points := generate(surrogate)

	b.ResetTimer()

	for i := 0; i < b.N; i++ {
		interpolator.Evaluate(surrogate, points)
	}
}

// A one-input-one-output scenario with a non-smooth function.
func ExampleInterpolator_step() {
	const (
		inputs  = 1
		outputs = 1
	)

	grid := newcot.NewClosed(inputs)
	basis := linhat.NewClosed(inputs)

	config := DefaultConfig(inputs, outputs)
	config.MaxLevel = 19
	interpolator, _ := New(grid, basis, config)

	surrogate := interpolator.Compute(step)
	fmt.Println(surrogate)

	// Output:
	// Surrogate{inputs: 1, outputs: 1, level: 19, nodes: 38}
}

// A one-input-one-output scenario with a smooth function.
func ExampleInterpolator_hat() {
	const (
		inputs  = 1
		outputs = 1
	)

	grid := newcot.NewClosed(inputs)
	basis := linhat.NewClosed(inputs)

	config := DefaultConfig(inputs, outputs)
	config.MaxLevel = 9
	interpolator, _ := New(grid, basis, config)

	surrogate := interpolator.Compute(hat)
	fmt.Println(surrogate)

	// Output:
	// Surrogate{inputs: 1, outputs: 1, level: 9, nodes: 305}
}

// A multiple-input-one-output scenario with a non-smooth function.
func ExampleInterpolator_cube() {
	const (
		inputs  = 2
		outputs = 1
	)

	grid := newcot.NewClosed(inputs)
	basis := linhat.NewClosed(inputs)

	config := DefaultConfig(inputs, outputs)
	config.MaxLevel = 9
	interpolator, _ := New(grid, basis, config)

	surrogate := interpolator.Compute(cube)
	fmt.Println(surrogate)

	// Output:
	// Surrogate{inputs: 2, outputs: 1, level: 9, nodes: 377}
}

// A multiple-input-many-output scenario with a non-smooth function.
func ExampleInterpolator_many() {
	const (
		inputs  = 2
		outputs = 1000
	)

	grid := newcot.NewClosed(inputs)
	basis := linhat.NewClosed(inputs)
	config := DefaultConfig(inputs, outputs)
	config.MaxNodes = 300

	interpolator, _ := New(grid, basis, config)

	surrogate := interpolator.Compute(many(inputs, outputs))
	fmt.Println(surrogate)

	// Output:
	// Surrogate{inputs: 2, outputs: 1000, level: 9, nodes: 300}
}

func prepare(fixture *fixture, arguments ...interface{}) *Interpolator {
	surrogate := fixture.surrogate

	ni, no := surrogate.Inputs, surrogate.Outputs

	config := DefaultConfig(ni, no)
	config.MaxLevel = surrogate.Level

	if len(arguments) > 0 {
		process, _ := arguments[0].(func(*Config))
		process(config)
	}

	interpolator, _ := New(newcot.NewClosed(ni), linhat.NewClosed(ni), config)

	return interpolator
}

func generate(surrogate *Surrogate) []float64 {
	const (
		count = 10000
	)

	generator := rand.New(rand.NewSource(0))
	points := make([]float64, count*surrogate.Inputs)
	for i := range points {
		points[i] = generator.Float64()
	}

	return points
}
<|endoftext|>


<commit_before><commit_msg>fix length of the error code<commit_after><|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 manager

import (
	"sync"

	"k8s.io/client-go/informers"
	clientset "k8s.io/client-go/kubernetes"

	vcclient "sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/client/clientset/versioned"
	vcinformers "sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/client/informers/externalversions/tenancy/v1alpha1"
	"sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/syncer/apis/config"
	"sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/syncer/listener"
	mc "sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/syncer/mccontroller"
	pa "sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/syncer/patrol"
	"sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/syncer/reconciler"
	uw "sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/syncer/uwcontroller"
)

// ControllerManager manages number of resource syncers. It starts their caches, waits for those to sync,
// then starts the controllers.
type ControllerManager struct {
	resourceSyncers map[ResourceSyncer]struct{}
}

type ResourceSyncerOptions struct {
	MCOptions     *mc.Options
	UWOptions     *uw.Options
	PatrolOptions *pa.Options
	IsFake        bool
}

func New() *ControllerManager {
	return &ControllerManager{resourceSyncers: make(map[ResourceSyncer]struct{})}
}

// ResourceSyncer is the interface used by ControllerManager to manage multiple resource syncers.
type ResourceSyncer interface {
	listener.ClusterChangeListener
	StartUWS(stopCh <-chan struct{}) error
	StartDWS(stopCh <-chan struct{}) error
	StartPatrol(stopCh <-chan struct{}) error
	Reconcile(request reconciler.Request) (reconciler.Result, error)
	BackPopulate(string) error
	PatrollerDo()
}

// AddController adds a resource syncer to the ControllerManager.
func (m *ControllerManager) AddResourceSyncer(s ResourceSyncer) {
	m.resourceSyncers[s] = struct{}{}
	listener.AddListener(s)
}

type ResourceSyncerNew func(*config.SyncerConfiguration,
	clientset.Interface,
	informers.SharedInformerFactory,
	vcclient.Interface,
	vcinformers.VirtualClusterInformer, *ResourceSyncerOptions) (ResourceSyncer, *mc.MultiClusterController, *uw.UpwardController, error)

// Start gets all the unique caches of the controllers it manages, starts them,
// then starts the controllers as soon as their respective caches are synced.
// Start blocks until an error or stop is received.
func (m *ControllerManager) Start(stop <-chan struct{}) error {
	errCh := make(chan error)

	wg := &sync.WaitGroup{}
	wg.Add(len(m.resourceSyncers) * 3)

	for s := range m.resourceSyncers {
		go func(s ResourceSyncer) {
			defer wg.Done()
			if err := s.StartDWS(stop); err != nil {
				errCh <- err
			}
		}(s)
		// start UWS syncer
		go func(s ResourceSyncer) {
			defer wg.Done()
			if err := s.StartUWS(stop); err != nil {
				errCh <- err
			}
		}(s)
		// start periodic checker
		go func(s ResourceSyncer) {
			defer wg.Done()
			if err := s.StartPatrol(stop); err != nil {
				errCh <- err
			}
		}(s)
	}

	doneCh := make(chan struct{})
	go func() {
		wg.Wait()
		close(doneCh)
	}()

	select {
	case <-doneCh:
		return nil
	case <-stop:
		return nil
	case err := <-errCh:
		return err
	}
}
<commit_msg>unify reconciler interface<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 manager

import (
	"sync"

	"k8s.io/client-go/informers"
	clientset "k8s.io/client-go/kubernetes"

	vcclient "sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/client/clientset/versioned"
	vcinformers "sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/client/informers/externalversions/tenancy/v1alpha1"
	"sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/syncer/apis/config"
	"sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/syncer/listener"
	mc "sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/syncer/mccontroller"
	pa "sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/syncer/patrol"
	"sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/syncer/reconciler"
	uw "sigs.k8s.io/multi-tenancy/incubator/virtualcluster/pkg/syncer/uwcontroller"
)

// ControllerManager manages number of resource syncers. It starts their caches, waits for those to sync,
// then starts the controllers.
type ControllerManager struct {
	resourceSyncers map[ResourceSyncer]struct{}
}

type ResourceSyncerOptions struct {
	MCOptions     *mc.Options
	UWOptions     *uw.Options
	PatrolOptions *pa.Options
	IsFake        bool
}

func New() *ControllerManager {
	return &ControllerManager{resourceSyncers: make(map[ResourceSyncer]struct{})}
}

// ResourceSyncer is the interface used by ControllerManager to manage multiple resource syncers.
type ResourceSyncer interface {
	listener.ClusterChangeListener
	reconciler.DWReconciler
	reconciler.UWReconciler
	reconciler.PatrolReconciler
	StartUWS(stopCh <-chan struct{}) error
	StartDWS(stopCh <-chan struct{}) error
	StartPatrol(stopCh <-chan struct{}) error
}

// AddController adds a resource syncer to the ControllerManager.
func (m *ControllerManager) AddResourceSyncer(s ResourceSyncer) {
	m.resourceSyncers[s] = struct{}{}
	listener.AddListener(s)
}

type ResourceSyncerNew func(*config.SyncerConfiguration,
	clientset.Interface,
	informers.SharedInformerFactory,
	vcclient.Interface,
	vcinformers.VirtualClusterInformer, *ResourceSyncerOptions) (ResourceSyncer, *mc.MultiClusterController, *uw.UpwardController, error)

// Start gets all the unique caches of the controllers it manages, starts them,
// then starts the controllers as soon as their respective caches are synced.
// Start blocks until an error or stop is received.
func (m *ControllerManager) Start(stop <-chan struct{}) error {
	errCh := make(chan error)

	wg := &sync.WaitGroup{}
	wg.Add(len(m.resourceSyncers) * 3)

	for s := range m.resourceSyncers {
		go func(s ResourceSyncer) {
			defer wg.Done()
			if err := s.StartDWS(stop); err != nil {
				errCh <- err
			}
		}(s)
		// start UWS syncer
		go func(s ResourceSyncer) {
			defer wg.Done()
			if err := s.StartUWS(stop); err != nil {
				errCh <- err
			}
		}(s)
		// start periodic checker
		go func(s ResourceSyncer) {
			defer wg.Done()
			if err := s.StartPatrol(stop); err != nil {
				errCh <- err
			}
		}(s)
	}

	doneCh := make(chan struct{})
	go func() {
		wg.Wait()
		close(doneCh)
	}()

	select {
	case <-doneCh:
		return nil
	case <-stop:
		return nil
	case err := <-errCh:
		return err
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The OpenEBS 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 cstorpoolit

import (
	"testing"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	citf "github.com/openebs/CITF"
	citfoptions "github.com/openebs/CITF/citf_options"
	apis "github.com/openebs/CITF/pkg/apis/openebs.io/v1alpha1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// TestIntegrationCstorPool function instantiate the cstor pool test suite.
func TestIntegrationCstorPool(t *testing.T) {
	// RegisterFailHandler is used to register failed test cases and produce readable output.
	RegisterFailHandler(Fail)
	// RunSpecs runs all the test cases in the suite.
	RunSpecs(t, "Cstor pool integration test suite")
}

// Create an instance of CITF to use the inbuilt functions that will help
// communicating with the kube-apiserver.
var citfInstance, err = citf.NewCITF(&citfoptions.CreateOptions{
	// K8SInclude is true to get the kube-config from the machine where the suite is running.
	// Kube-config is a config file that establishes communication to the k8s cluster.
	K8SInclude: true,
})

// ToDo: Set up cluster environment before runninng all test cases ( i.e. BeforeSuite)
// The environment set up by BeforeSuite is going to persist for all
// the test cases under run

//var _ = BeforeSuite(func() {
//	//var err error
//	//
//	//Expect(err).NotTo(HaveOccurred())
//})

// ToDo: Set up tear down of cluster environment ( i.e Aftersuite)

// ToDo: Set up cluster environment before every test cases that will be run (i.e. preRunHook)
// ToDo: Reset cluster environment after every test cases that will be run  ( i.e postRunHook)
var _ = Describe("Integration Test", func() {
	// Test Case #1 (sparse-striped-auto-spc). Type : Positive
	When("We apply sparse-striped-auto spc yaml with maxPool count equal to 3 on a k8s cluster having at least 3 capable node", func() {
		It("pool resources count should be 3 with no error and online status", func() {
			// TODO: Create a generic util function in utils.go to convert yaml into go object.
			// ToDo: More POC regarding this util converter function.
			// Functions generic to both cstor-pool and cstor-vol should go inside common directory

			// 1.Read SPC yaml form a file.
			// 2.Convert SPC yaml to json.
			// 3.Marshall json to SPC go object.

			// Create a storage pool claim object
			spcObject := &apis.StoragePoolClaim{
				ObjectMeta: metav1.ObjectMeta{
					Name: "disk-claim-auto",
				},
				Spec: apis.StoragePoolClaimSpec{
					Name:     "sparse-claim-auto",
					Type:     "sparse",
					MaxPools: 3,
					PoolSpec: apis.CStorPoolAttr{
						PoolType: "striped",
					},
				},
			}
			// Call CITF to create StoragePoolClaim in k8s.
			spcGot, err := citfInstance.K8S.CreateStoragePoolClaim(spcObject)
			Expect(err).To(BeNil())
			// We expect nil error.

			// We expect 3 cstorPool objects.
			var maxRetry int
			var cspCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				cspCount, err = getCstorPoolCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if cspCount == 3 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(cspCount).To(Equal(3))
			// We expect 3 pool deployments.
			var deployCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				deployCount, err = getPoolDeployCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if deployCount == 3 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(cspCount).To(Equal(3))
			// We expect 3 storagePool objects.
			var spCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				spCount, err = getStoragePoolCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if spCount == 3 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(spCount).To(Equal(3))

			// We expect 'online' status on all the three cstorPool objects(i.e. 3 online counts)
			var onlineCspCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				onlineCspCount, err = getCstorPoolStatus(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if onlineCspCount == 3 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(onlineCspCount).To(Equal(3))

		})
	})

	// Test Case #2 (sparse-mirrored-auto-spc). Type : Negative
	When("We apply sparse-mirrored-auto spc yaml with maxPool count equal to 0 on a k8s cluster", func() {
		It("pool resources count should be 0 with no error and online status", func() {
			// TODO: Create a generic util function in utils.go to convert yaml into go object.
			// ToDo: More POC regarding this util converter function.
			// Functions generic to both cstor-pool and cstor-vol should go inside common directory

			// 1.Read SPC yaml form a file.
			// 2.Convert SPC yaml to json.
			// 3.Marshall json to SPC go object.

			// Create a storage pool claim object
			spcObject := &apis.StoragePoolClaim{
				ObjectMeta: metav1.ObjectMeta{
					Name: "disk-claim-auto",
				},
				Spec: apis.StoragePoolClaimSpec{
					Name:     "sparse-claim-auto",
					Type:     "sparse",
					MaxPools: 0,
					PoolSpec: apis.CStorPoolAttr{
						PoolType: "mirrored",
					},
				},
			}
			// Call CITF to create StoragePoolClaim in k8s.
			spcGot, err := citfInstance.K8S.CreateStoragePoolClaim(spcObject)
			Expect(err).To(BeNil())
			// We expect nil error.

			// We expect 0 cstorPool objects.
			var maxRetry int
			var cspCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				cspCount, err = getCstorPoolCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if cspCount == 0 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(cspCount).To(Equal(0))
			// We expect 0 pool deployments.
			var deployCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				deployCount, err = getPoolDeployCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if deployCount == 0 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(cspCount).To(Equal(0))
			// We expect 0 storagePool objects.
			var spCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				spCount, err = getStoragePoolCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if spCount == 0 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(spCount).To(Equal(0))

			// We don't expect 'online' status on any of the cstorPool objects.
			var onlineCspCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				onlineCspCount, err = getCstorPoolStatus(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if onlineCspCount == 0 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(onlineCspCount).To(Equal(0))

		})
	})

	// TODo: Add more test cases. Refer to following design doc
	// https://docs.google.com/document/d/1QAYK-Bsehc7v66kscXCiMJ7_pTIjzNmwyl43tF92gWA/edit
})
<commit_msg>Adds IT for sparse-mirrored-auto(dynamic) spc with maxpool count 3 (2187) (#736)<commit_after>/*
Copyright 2018 The OpenEBS 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 cstorpoolit

import (
	"testing"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	citf "github.com/openebs/CITF"
	citfoptions "github.com/openebs/CITF/citf_options"
	apis "github.com/openebs/CITF/pkg/apis/openebs.io/v1alpha1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// TestIntegrationCstorPool function instantiate the cstor pool test suite.
func TestIntegrationCstorPool(t *testing.T) {
	// RegisterFailHandler is used to register failed test cases and produce readable output.
	RegisterFailHandler(Fail)
	// RunSpecs runs all the test cases in the suite.
	RunSpecs(t, "Cstor pool integration test suite")
}

// Create an instance of CITF to use the inbuilt functions that will help
// communicating with the kube-apiserver.
var citfInstance, err = citf.NewCITF(&citfoptions.CreateOptions{
	// K8SInclude is true to get the kube-config from the machine where the suite is running.
	// Kube-config is a config file that establishes communication to the k8s cluster.
	K8SInclude: true,
})

// ToDo: Set up cluster environment before runninng all test cases ( i.e. BeforeSuite)
// The environment set up by BeforeSuite is going to persist for all
// the test cases under run

//var _ = BeforeSuite(func() {
//	//var err error
//	//
//	//Expect(err).NotTo(HaveOccurred())
//})

// ToDo: Set up tear down of cluster environment ( i.e Aftersuite)

// ToDo: Set up cluster environment before every test cases that will be run (i.e. preRunHook)
// ToDo: Reset cluster environment after every test cases that will be run  ( i.e postRunHook)
var _ = Describe("Integration Test", func() {
	// Test Case #1 (sparse-striped-auto-spc). Type : Positive
	When("We apply sparse-striped-auto spc yaml with maxPool count equal to 3 on a k8s cluster having at least 3 capable node", func() {
		It("pool resources count should be 3 with no error and online status", func() {
			// TODO: Create a generic util function in utils.go to convert yaml into go object.
			// ToDo: More POC regarding this util converter function.
			// Functions generic to both cstor-pool and cstor-vol should go inside common directory

			// 1.Read SPC yaml form a file.
			// 2.Convert SPC yaml to json.
			// 3.Marshall json to SPC go object.

			// Create a storage pool claim object
			spcObject := &apis.StoragePoolClaim{
				ObjectMeta: metav1.ObjectMeta{
					Name: "disk-claim-auto",
				},
				Spec: apis.StoragePoolClaimSpec{
					Name:     "sparse-claim-auto",
					Type:     "sparse",
					MaxPools: 3,
					PoolSpec: apis.CStorPoolAttr{
						PoolType: "striped",
					},
				},
			}
			// Call CITF to create StoragePoolClaim in k8s.
			spcGot, err := citfInstance.K8S.CreateStoragePoolClaim(spcObject)
			Expect(err).To(BeNil())
			// We expect nil error.

			// We expect 3 cstorPool objects.
			var maxRetry int
			var cspCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				cspCount, err = getCstorPoolCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if cspCount == 3 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(cspCount).To(Equal(3))
			// We expect 3 pool deployments.
			var deployCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				deployCount, err = getPoolDeployCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if deployCount == 3 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(cspCount).To(Equal(3))
			// We expect 3 storagePool objects.
			var spCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				spCount, err = getStoragePoolCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if spCount == 3 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(spCount).To(Equal(3))

			// We expect 'online' status on all the three cstorPool objects(i.e. 3 online counts)
			var onlineCspCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				onlineCspCount, err = getCstorPoolStatus(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if onlineCspCount == 3 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(onlineCspCount).To(Equal(3))

		})
	})

	// Test Case #2 (sparse-mirrored-auto-spc). Type : Negative
	When("We apply sparse-mirrored-auto spc yaml with maxPool count equal to 0 on a k8s cluster", func() {
		It("pool resources count should be 0 with no error and online status", func() {
			// TODO: Create a generic util function in utils.go to convert yaml into go object.
			// ToDo: More POC regarding this util converter function.
			// Functions generic to both cstor-pool and cstor-vol should go inside common directory

			// 1.Read SPC yaml form a file.
			// 2.Convert SPC yaml to json.
			// 3.Marshall json to SPC go object.

			// Create a storage pool claim object
			spcObject := &apis.StoragePoolClaim{
				ObjectMeta: metav1.ObjectMeta{
					Name: "disk-claim-auto",
				},
				Spec: apis.StoragePoolClaimSpec{
					Name:     "sparse-claim-auto",
					Type:     "sparse",
					MaxPools: 0,
					PoolSpec: apis.CStorPoolAttr{
						PoolType: "mirrored",
					},
				},
			}
			// Call CITF to create StoragePoolClaim in k8s.
			spcGot, err := citfInstance.K8S.CreateStoragePoolClaim(spcObject)
			Expect(err).To(BeNil())
			// We expect nil error.

			// We expect 0 cstorPool objects.
			var maxRetry int
			var cspCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				cspCount, err = getCstorPoolCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if cspCount == 0 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(cspCount).To(Equal(0))
			// We expect 0 pool deployments.
			var deployCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				deployCount, err = getPoolDeployCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if deployCount == 0 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(cspCount).To(Equal(0))
			// We expect 0 storagePool objects.
			var spCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				spCount, err = getStoragePoolCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if spCount == 0 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(spCount).To(Equal(0))

			// We don't expect 'online' status on any of the cstorPool objects.
			var onlineCspCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				onlineCspCount, err = getCstorPoolStatus(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if onlineCspCount == 0 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(onlineCspCount).To(Equal(0))

		})
	})

	// TODo: Add more test cases. Refer to following design doc
	// https://docs.google.com/document/d/1QAYK-Bsehc7v66kscXCiMJ7_pTIjzNmwyl43tF92gWA/edit

	// Test Case #5 (sparse-mirrored-auto-spc). Type : Positive
	When("We apply sparse-mirrored-auto spc yaml with maxPool count equal to 3 on a k8s cluster having at least 3 capable node", func() {
		It("pool resources count should be 3 with no error and online status", func() {
			// TODO: Create a generic util function in utils.go to convert yaml into go object.
			// ToDo: More POC regarding this util converter function.
			// Functions generic to both cstor-pool and cstor-vol should go inside common directory

			// 1.Read SPC yaml form a file.
			// 2.Convert SPC yaml to json.
			// 3.Marshall json to SPC go object.

			// Create a storage pool claim object
			spcObject := &apis.StoragePoolClaim{
				ObjectMeta: metav1.ObjectMeta{
					Name: "disk-claim-auto",
				},
				Spec: apis.StoragePoolClaimSpec{
					Name:     "sparse-claim-auto",
					Type:     "sparse",
					MaxPools: 3,
					PoolSpec: apis.CStorPoolAttr{
						PoolType: "mirrored",
					},
				},
			}
			// Call CITF to create StoragePoolClaim in k8s.
			spcGot, err := citfInstance.K8S.CreateStoragePoolClaim(spcObject)
			Expect(err).To(BeNil())
			// We expect nil error.

			// We expect 3 cstorPool objects.
			var maxRetry int
			var cspCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				cspCount, err = getCstorPoolCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if cspCount == 3 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(cspCount).To(Equal(3))
			// We expect 3 pool deployments.
			var deployCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				deployCount, err = getPoolDeployCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if deployCount == 3 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(cspCount).To(Equal(3))
			// We expect 3 storagePool objects.
			var spCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				spCount, err = getStoragePoolCount(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if spCount == 3 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(spCount).To(Equal(3))

			// We expect 'online' status on all the three cstorPool objects(i.e. 3 online counts)
			var onlineCspCount int
			maxRetry = 10
			for i := 0; i < maxRetry; i++ {
				onlineCspCount, err = getCstorPoolStatus(spcGot.Name, citfInstance)
				if err != nil {
					break
				}
				if onlineCspCount == 3 {
					break
				}
				time.Sleep(time.Second * 5)
			}
			Expect(onlineCspCount).To(Equal(3))

		})
	})
})
<|endoftext|>


<commit_before>/*
 * Minio Go Library for Amazon S3 Compatible Cloud Storage
 * Copyright 2015-2017 Minio, Inc.
 *
 * 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 minio

// Non exhaustive list of AWS S3 standard error responses -
// http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
var s3ErrorResponseMap = map[string]string{
	"AccessDenied":                      "Access Denied.",
	"BadDigest":                         "The Content-Md5 you specified did not match what we received.",
	"EntityTooSmall":                    "Your proposed upload is smaller than the minimum allowed object size.",
	"EntityTooLarge":                    "Your proposed upload exceeds the maximum allowed object size.",
	"IncompleteBody":                    "You did not provide the number of bytes specified by the Content-Length HTTP header.",
	"InternalError":                     "We encountered an internal error, please try again.",
	"InvalidAccessKeyId":                "The access key ID you provided does not exist in our records.",
	"InvalidBucketName":                 "The specified bucket is not valid.",
	"InvalidDigest":                     "The Content-Md5 you specified is not valid.",
	"InvalidRange":                      "The requested range is not satisfiable",
	"MalformedXML":                      "The XML you provided was not well-formed or did not validate against our published schema.",
	"MissingContentLength":              "You must provide the Content-Length HTTP header.",
	"MissingContentMD5":                 "Missing required header for this request: Content-Md5.",
	"MissingRequestBodyError":           "Request body is empty.",
	"NoSuchBucket":                      "The specified bucket does not exist",
	"NoSuchBucketPolicy":                "The bucket policy does not exist",
	"NoSuchKey":                         "The specified key does not exist.",
	"NoSuchUpload":                      "The specified multipart upload does not exist. The upload ID may be invalid, or the upload may have been aborted or completed.",
	"NotImplemented":                    "A header you provided implies functionality that is not implemented",
	"PreconditionFailed":                "At least one of the pre-conditions you specified did not hold",
	"RequestTimeTooSkewed":              "The difference between the request time and the server's time is too large.",
	"SignatureDoesNotMatch":             "The request signature we calculated does not match the signature you provided. Check your key and signing method.",
	"MethodNotAllowed":                  "The specified method is not allowed against this resource.",
	"InvalidPart":                       "One or more of the specified parts could not be found.",
	"InvalidPartOrder":                  "The list of parts was not in ascending order. The parts list must be specified in order by part number.",
	"InvalidObjectState":                "The operation is not valid for the current state of the object.",
	"AuthorizationHeaderMalformed":      "The authorization header is malformed; the region is wrong.",
	"MalformedPOSTRequest":              "The body of your POST request is not well-formed multipart/form-data.",
	"BucketNotEmpty":                    "The bucket you tried to delete is not empty",
	"AllAccessDisabled":                 "All access to this bucket has been disabled.",
	"MalformedPolicy":                   "Policy has invalid resource.",
	"MissingFields":                     "Missing fields in request.",
	"AuthorizationQueryParametersError": "Error parsing the X-Amz-Credential parameter; the Credential is mal-formed; expecting \"<YOUR-AKID>/YYYYMMDD/REGION/SERVICE/aws4_request\".",
	"MalformedDate":                     "Invalid date format header, expected to be in ISO8601, RFC1123 or RFC1123Z time format.",
	"BucketAlreadyOwnedByYou":           "Your previous request to create the named bucket succeeded and you already own it.",
	"InvalidDuration":                   "Duration provided in the request is invalid.",
	"XAmzContentSHA256Mismatch":         "The provided 'x-amz-content-sha256' header does not match what was computed.",
	// Add new API errors here.
}
<commit_msg>fix NoSuchBucket logic in BucketExists function (#1035)<commit_after>/*
 * Minio Go Library for Amazon S3 Compatible Cloud Storage
 * Copyright 2015-2017 Minio, Inc.
 *
 * 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 minio

// Non exhaustive list of AWS S3 standard error responses -
// http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
var s3ErrorResponseMap = map[string]string{
	"AccessDenied":                      "Access Denied.",
	"BadDigest":                         "The Content-Md5 you specified did not match what we received.",
	"EntityTooSmall":                    "Your proposed upload is smaller than the minimum allowed object size.",
	"EntityTooLarge":                    "Your proposed upload exceeds the maximum allowed object size.",
	"IncompleteBody":                    "You did not provide the number of bytes specified by the Content-Length HTTP header.",
	"InternalError":                     "We encountered an internal error, please try again.",
	"InvalidAccessKeyId":                "The access key ID you provided does not exist in our records.",
	"InvalidBucketName":                 "The specified bucket is not valid.",
	"InvalidDigest":                     "The Content-Md5 you specified is not valid.",
	"InvalidRange":                      "The requested range is not satisfiable",
	"MalformedXML":                      "The XML you provided was not well-formed or did not validate against our published schema.",
	"MissingContentLength":              "You must provide the Content-Length HTTP header.",
	"MissingContentMD5":                 "Missing required header for this request: Content-Md5.",
	"MissingRequestBodyError":           "Request body is empty.",
	"NoSuchBucket":                      "The specified bucket does not exist.",
	"NoSuchBucketPolicy":                "The bucket policy does not exist",
	"NoSuchKey":                         "The specified key does not exist.",
	"NoSuchUpload":                      "The specified multipart upload does not exist. The upload ID may be invalid, or the upload may have been aborted or completed.",
	"NotImplemented":                    "A header you provided implies functionality that is not implemented",
	"PreconditionFailed":                "At least one of the pre-conditions you specified did not hold",
	"RequestTimeTooSkewed":              "The difference between the request time and the server's time is too large.",
	"SignatureDoesNotMatch":             "The request signature we calculated does not match the signature you provided. Check your key and signing method.",
	"MethodNotAllowed":                  "The specified method is not allowed against this resource.",
	"InvalidPart":                       "One or more of the specified parts could not be found.",
	"InvalidPartOrder":                  "The list of parts was not in ascending order. The parts list must be specified in order by part number.",
	"InvalidObjectState":                "The operation is not valid for the current state of the object.",
	"AuthorizationHeaderMalformed":      "The authorization header is malformed; the region is wrong.",
	"MalformedPOSTRequest":              "The body of your POST request is not well-formed multipart/form-data.",
	"BucketNotEmpty":                    "The bucket you tried to delete is not empty",
	"AllAccessDisabled":                 "All access to this bucket has been disabled.",
	"MalformedPolicy":                   "Policy has invalid resource.",
	"MissingFields":                     "Missing fields in request.",
	"AuthorizationQueryParametersError": "Error parsing the X-Amz-Credential parameter; the Credential is mal-formed; expecting \"<YOUR-AKID>/YYYYMMDD/REGION/SERVICE/aws4_request\".",
	"MalformedDate":                     "Invalid date format header, expected to be in ISO8601, RFC1123 or RFC1123Z time format.",
	"BucketAlreadyOwnedByYou":           "Your previous request to create the named bucket succeeded and you already own it.",
	"InvalidDuration":                   "Duration provided in the request is invalid.",
	"XAmzContentSHA256Mismatch":         "The provided 'x-amz-content-sha256' header does not match what was computed.",
	// Add new API errors here.
}
<|endoftext|>