<commit_before>package outbound

import (
	"io"
	"sync"

	"v2ray.com/core/app"
	"v2ray.com/core/common/alloc"
	v2io "v2ray.com/core/common/io"
	"v2ray.com/core/common/loader"
	"v2ray.com/core/common/log"
	v2net "v2ray.com/core/common/net"
	"v2ray.com/core/common/protocol"
	"v2ray.com/core/common/retry"
	"v2ray.com/core/proxy"
	"v2ray.com/core/proxy/registry"
	"v2ray.com/core/proxy/vmess/encoding"
	vmessio "v2ray.com/core/proxy/vmess/io"
	"v2ray.com/core/transport/internet"
	"v2ray.com/core/transport/ray"
)

type VMessOutboundHandler struct {
	serverList   *protocol.ServerList
	serverPicker protocol.ServerPicker
	meta         *proxy.OutboundHandlerMeta
}

func (this *VMessOutboundHandler) Dispatch(target v2net.Destination, payload *alloc.Buffer, ray ray.OutboundRay) error {
	defer ray.OutboundInput().Release()
	defer ray.OutboundOutput().Close()

	var rec *protocol.ServerSpec
	var conn internet.Connection

	err := retry.Timed(5, 100).On(func() error {
		rec = this.serverPicker.PickServer()
		rawConn, err := internet.Dial(this.meta.Address, rec.Destination(), this.meta.GetDialerOptions())
		if err != nil {
			return err
		}
		conn = rawConn

		return nil
	})
	if err != nil {
		log.Error("VMess|Outbound: Failed to find an available destination:", err)
		return err
	}
	log.Info("VMess|Outbound: Tunneling request to ", target, " via ", rec.Destination())

	command := protocol.RequestCommandTCP
	if target.Network == v2net.Network_UDP {
		command = protocol.RequestCommandUDP
	}
	request := &protocol.RequestHeader{
		Version: encoding.Version,
		User:    rec.PickUser(),
		Command: command,
		Address: target.Address,
		Port:    target.Port,
		Option:  protocol.RequestOptionChunkStream,
	}

	defer conn.Close()

	conn.SetReusable(true)
	if conn.Reusable() { // Conn reuse may be disabled on transportation layer
		request.Option.Set(protocol.RequestOptionConnectionReuse)
	}

	input := ray.OutboundInput()
	output := ray.OutboundOutput()

	var requestFinish, responseFinish sync.Mutex
	requestFinish.Lock()
	responseFinish.Lock()

	session := encoding.NewClientSession(protocol.DefaultIDHash)

	go this.handleRequest(session, conn, request, payload, input, &requestFinish)
	go this.handleResponse(session, conn, request, rec.Destination(), output, &responseFinish)

	requestFinish.Lock()
	responseFinish.Lock()
	return nil
}

func (this *VMessOutboundHandler) handleRequest(session *encoding.ClientSession, conn internet.Connection, request *protocol.RequestHeader, payload *alloc.Buffer, input v2io.Reader, finish *sync.Mutex) {
	defer finish.Unlock()

	writer := v2io.NewBufferedWriter(conn)
	defer writer.Release()
	session.EncodeRequestHeader(request, writer)

	bodyWriter := session.EncodeRequestBody(writer)
	var streamWriter v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter)
	if request.Option.Has(protocol.RequestOptionChunkStream) {
		streamWriter = vmessio.NewAuthChunkWriter(streamWriter)
	}
	if !payload.IsEmpty() {
		if err := streamWriter.Write(payload); err != nil {
			log.Info("VMess|Outbound: Failed to write payload. Disabling connection reuse.")
			conn.SetReusable(false)
		}
	}
	writer.SetCached(false)

	err := v2io.Pipe(input, streamWriter)
	if err != io.EOF {
		conn.SetReusable(false)
	}

	if request.Option.Has(protocol.RequestOptionChunkStream) {
		err := streamWriter.Write(alloc.NewLocalBuffer(32).Clear())
		if err != nil {
			conn.SetReusable(false)
		}
	}
	streamWriter.Release()
	return
}

func (this *VMessOutboundHandler) handleResponse(session *encoding.ClientSession, conn internet.Connection, request *protocol.RequestHeader, dest v2net.Destination, output v2io.Writer, finish *sync.Mutex) {
	defer finish.Unlock()

	reader := v2io.NewBufferedReader(conn)
	defer reader.Release()

	header, err := session.DecodeResponseHeader(reader)
	if err != nil {
		conn.SetReusable(false)
		log.Warning("VMess|Outbound: Failed to read response from ", request.Destination(), ": ", err)
		return
	}
	go this.handleCommand(dest, header.Command)

	if !header.Option.Has(protocol.ResponseOptionConnectionReuse) {
		conn.SetReusable(false)
	}

	reader.SetCached(false)
	decryptReader := session.DecodeResponseBody(reader)

	var bodyReader v2io.Reader
	if request.Option.Has(protocol.RequestOptionChunkStream) {
		bodyReader = vmessio.NewAuthChunkReader(decryptReader)
	} else {
		bodyReader = v2io.NewAdaptiveReader(decryptReader)
	}

	err = v2io.Pipe(bodyReader, output)
	if err != io.EOF {
		conn.SetReusable(false)
	}

	bodyReader.Release()
	return
}

type Factory struct{}

func (this *Factory) StreamCapability() v2net.NetworkList {
	return v2net.NetworkList{
		Network: []v2net.Network{v2net.Network_TCP, v2net.Network_KCP, v2net.Network_WebSocket},
	}
}

func (this *Factory) Create(space app.Space, rawConfig interface{}, meta *proxy.OutboundHandlerMeta) (proxy.OutboundHandler, error) {
	vOutConfig := rawConfig.(*Config)

	serverList := protocol.NewServerList()
	for _, rec := range vOutConfig.Receiver {
		serverList.AddServer(protocol.NewServerSpecFromPB(*rec))
	}
	handler := &VMessOutboundHandler{
		serverList:   serverList,
		serverPicker: protocol.NewRoundRobinServerPicker(serverList),
		meta:         meta,
	}

	return handler, nil
}

func init() {
	registry.MustRegisterOutboundHandlerCreator(loader.GetType(new(Config)), new(Factory))
}
<commit_msg>release payload after writting<commit_after>package outbound

import (
	"io"
	"sync"

	"v2ray.com/core/app"
	"v2ray.com/core/common/alloc"
	v2io "v2ray.com/core/common/io"
	"v2ray.com/core/common/loader"
	"v2ray.com/core/common/log"
	v2net "v2ray.com/core/common/net"
	"v2ray.com/core/common/protocol"
	"v2ray.com/core/common/retry"
	"v2ray.com/core/proxy"
	"v2ray.com/core/proxy/registry"
	"v2ray.com/core/proxy/vmess/encoding"
	vmessio "v2ray.com/core/proxy/vmess/io"
	"v2ray.com/core/transport/internet"
	"v2ray.com/core/transport/ray"
)

type VMessOutboundHandler struct {
	serverList   *protocol.ServerList
	serverPicker protocol.ServerPicker
	meta         *proxy.OutboundHandlerMeta
}

func (this *VMessOutboundHandler) Dispatch(target v2net.Destination, payload *alloc.Buffer, ray ray.OutboundRay) error {
	defer ray.OutboundInput().Release()
	defer ray.OutboundOutput().Close()

	var rec *protocol.ServerSpec
	var conn internet.Connection

	err := retry.Timed(5, 100).On(func() error {
		rec = this.serverPicker.PickServer()
		rawConn, err := internet.Dial(this.meta.Address, rec.Destination(), this.meta.GetDialerOptions())
		if err != nil {
			return err
		}
		conn = rawConn

		return nil
	})
	if err != nil {
		log.Error("VMess|Outbound: Failed to find an available destination:", err)
		return err
	}
	log.Info("VMess|Outbound: Tunneling request to ", target, " via ", rec.Destination())

	command := protocol.RequestCommandTCP
	if target.Network == v2net.Network_UDP {
		command = protocol.RequestCommandUDP
	}
	request := &protocol.RequestHeader{
		Version: encoding.Version,
		User:    rec.PickUser(),
		Command: command,
		Address: target.Address,
		Port:    target.Port,
		Option:  protocol.RequestOptionChunkStream,
	}

	defer conn.Close()

	conn.SetReusable(true)
	if conn.Reusable() { // Conn reuse may be disabled on transportation layer
		request.Option.Set(protocol.RequestOptionConnectionReuse)
	}

	input := ray.OutboundInput()
	output := ray.OutboundOutput()

	var requestFinish, responseFinish sync.Mutex
	requestFinish.Lock()
	responseFinish.Lock()

	session := encoding.NewClientSession(protocol.DefaultIDHash)

	go this.handleRequest(session, conn, request, payload, input, &requestFinish)
	go this.handleResponse(session, conn, request, rec.Destination(), output, &responseFinish)

	requestFinish.Lock()
	responseFinish.Lock()
	return nil
}

func (this *VMessOutboundHandler) handleRequest(session *encoding.ClientSession, conn internet.Connection, request *protocol.RequestHeader, payload *alloc.Buffer, input v2io.Reader, finish *sync.Mutex) {
	defer finish.Unlock()

	writer := v2io.NewBufferedWriter(conn)
	defer writer.Release()
	session.EncodeRequestHeader(request, writer)

	bodyWriter := session.EncodeRequestBody(writer)
	var streamWriter v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter)
	if request.Option.Has(protocol.RequestOptionChunkStream) {
		streamWriter = vmessio.NewAuthChunkWriter(streamWriter)
	}
	if !payload.IsEmpty() {
		if err := streamWriter.Write(payload); err != nil {
			log.Info("VMess|Outbound: Failed to write payload. Disabling connection reuse.", err)
			conn.SetReusable(false)
		}
		payload.Release()
	}
	writer.SetCached(false)

	err := v2io.Pipe(input, streamWriter)
	if err != io.EOF {
		conn.SetReusable(false)
	}

	if request.Option.Has(protocol.RequestOptionChunkStream) {
		err := streamWriter.Write(alloc.NewLocalBuffer(32).Clear())
		if err != nil {
			conn.SetReusable(false)
		}
	}
	streamWriter.Release()
	return
}

func (this *VMessOutboundHandler) handleResponse(session *encoding.ClientSession, conn internet.Connection, request *protocol.RequestHeader, dest v2net.Destination, output v2io.Writer, finish *sync.Mutex) {
	defer finish.Unlock()

	reader := v2io.NewBufferedReader(conn)
	defer reader.Release()

	header, err := session.DecodeResponseHeader(reader)
	if err != nil {
		conn.SetReusable(false)
		log.Warning("VMess|Outbound: Failed to read response from ", request.Destination(), ": ", err)
		return
	}
	go this.handleCommand(dest, header.Command)

	if !header.Option.Has(protocol.ResponseOptionConnectionReuse) {
		conn.SetReusable(false)
	}

	reader.SetCached(false)
	decryptReader := session.DecodeResponseBody(reader)

	var bodyReader v2io.Reader
	if request.Option.Has(protocol.RequestOptionChunkStream) {
		bodyReader = vmessio.NewAuthChunkReader(decryptReader)
	} else {
		bodyReader = v2io.NewAdaptiveReader(decryptReader)
	}

	err = v2io.Pipe(bodyReader, output)
	if err != io.EOF {
		conn.SetReusable(false)
	}

	bodyReader.Release()
	return
}

type Factory struct{}

func (this *Factory) StreamCapability() v2net.NetworkList {
	return v2net.NetworkList{
		Network: []v2net.Network{v2net.Network_TCP, v2net.Network_KCP, v2net.Network_WebSocket},
	}
}

func (this *Factory) Create(space app.Space, rawConfig interface{}, meta *proxy.OutboundHandlerMeta) (proxy.OutboundHandler, error) {
	vOutConfig := rawConfig.(*Config)

	serverList := protocol.NewServerList()
	for _, rec := range vOutConfig.Receiver {
		serverList.AddServer(protocol.NewServerSpecFromPB(*rec))
	}
	handler := &VMessOutboundHandler{
		serverList:   serverList,
		serverPicker: protocol.NewRoundRobinServerPicker(serverList),
		meta:         meta,
	}

	return handler, nil
}

func init() {
	registry.MustRegisterOutboundHandlerCreator(loader.GetType(new(Config)), new(Factory))
}
<|endoftext|>


<commit_before>package db

import "fmt"

func (context *PollyContext) remainingMonths(month uint) uint {
	endmonth := context.Config.App.Proposals.StartMonth + context.Config.App.Proposals.TotalRuntimeMonths

	i := endmonth - month
	if i < 0 {
		return 0
	}

	return i
}

func (context *PollyContext) sumAcceptedLargeGrants() uint {
	return 0
}

func (context *PollyContext) sumAcceptedSmallGrants(month uint) uint {
	proposals, _ := context.LoadAllProposals()

	i := uint(0)
	for _, p := range proposals {
		if month > 0 && uint(p.Ends(context).Month()) != month {
			continue
		}
		if !p.Ended(context) {
			continue
		}
		if p.Value >= uint64(context.Config.App.Proposals.SmallGrantValueThreshold) {
			continue
		}
		fmt.Println("FOUND:", p.Title, p.Starts, p.Value, p.Votes)
		if !p.Accepted(context) {
			continue
		}
		fmt.Println("ACCEPTING:", p.Title, p.Starts, p.Value, p.Votes)

		i += uint(p.Value)
	}

	return i
}

func (context *PollyContext) remainingLargeGrantValue(month uint) uint {
	return context.remainingMonths(month) * context.Config.App.Proposals.MaxGrantValue * (context.Config.App.Proposals.MaxLargeGrantsPerMonth / 2)
}

func (context *PollyContext) remainingSmallGrantValue(month uint) uint {
	return context.Config.App.Proposals.TotalGrantValue - context.remainingLargeGrantValue(month) - context.sumAcceptedLargeGrants() - context.sumAcceptedSmallGrants(0)
}

func (context *PollyContext) SmallGrantMaxValue(month uint) uint {
	/* fmt.Println("remaining months:", context.remainingMonths(month))
	fmt.Println("rem-SMALL:", context.remainingSmallGrantValue(month))
	fmt.Println("rem-LARGE:", context.remainingLargeGrantValue(month))
	fmt.Println("sum-SMALL:", context.sumAcceptedSmallGrants(0))
	fmt.Println("sum-SMALL-MONTH:", context.sumAcceptedSmallGrants(month)) */

	i := int(context.remainingSmallGrantValue(month)/context.remainingMonths(month)) -
		int(context.sumAcceptedSmallGrants(month))

	// fmt.Println("smallgrantmax:", i)

	if i < 0 {
		return 0
	}
	if i >= int(context.Config.App.Proposals.SmallGrantValueThreshold) {
		return context.Config.App.Proposals.SmallGrantValueThreshold
	}

	return uint(i)
}

func (context *PollyContext) GrantMaxValue() uint {
	return context.Config.App.Proposals.MaxGrantValue
}
<commit_msg>Return correct max-value for micro grants<commit_after>package db

import "fmt"

func (context *PollyContext) remainingMonths(month uint) uint {
	endmonth := context.Config.App.Proposals.StartMonth + context.Config.App.Proposals.TotalRuntimeMonths

	i := endmonth - month
	if i < 0 {
		return 0
	}

	return i
}

func (context *PollyContext) sumAcceptedLargeGrants() uint {
	return 0
}

func (context *PollyContext) sumAcceptedSmallGrants(month uint) uint {
	proposals, _ := context.LoadAllProposals()

	i := uint(0)
	for _, p := range proposals {
		if month > 0 && uint(p.Ends(context).Month()) != month {
			continue
		}
		if !p.Ended(context) {
			continue
		}
		if p.Value >= uint64(context.Config.App.Proposals.SmallGrantValueThreshold) {
			continue
		}
		fmt.Println("FOUND:", p.Title, p.Starts, p.Value, p.Votes)
		if !p.Accepted(context) {
			continue
		}
		fmt.Println("ACCEPTING:", p.Title, p.Starts, p.Value, p.Votes)

		i += uint(p.Value)
	}

	return i
}

func (context *PollyContext) remainingLargeGrantValue(month uint) uint {
	return context.remainingMonths(month) * context.Config.App.Proposals.MaxGrantValue * (context.Config.App.Proposals.MaxLargeGrantsPerMonth / 2)
}

func (context *PollyContext) remainingSmallGrantValue(month uint) uint {
	return context.Config.App.Proposals.TotalGrantValue - context.remainingLargeGrantValue(month) - context.sumAcceptedLargeGrants() - context.sumAcceptedSmallGrants(0)
}

func (context *PollyContext) SmallGrantMaxValue(month uint) uint {
	/* fmt.Println("remaining months:", context.remainingMonths(month))
	fmt.Println("rem-SMALL:", context.remainingSmallGrantValue(month))
	fmt.Println("rem-LARGE:", context.remainingLargeGrantValue(month))
	fmt.Println("sum-SMALL:", context.sumAcceptedSmallGrants(0))
	fmt.Println("sum-SMALL-MONTH:", context.sumAcceptedSmallGrants(month)) */

	i := int(context.remainingSmallGrantValue(month)/context.remainingMonths(month)) -
		int(context.sumAcceptedSmallGrants(month))

	// fmt.Println("smallgrantmax:", i)

	if i < 0 {
		return 0
	}
	if i >= int(context.Config.App.Proposals.SmallGrantValueThreshold) {
		return context.Config.App.Proposals.SmallGrantValueThreshold - 1
	}

	return uint(i)
}

func (context *PollyContext) GrantMaxValue() uint {
	return context.Config.App.Proposals.MaxGrantValue
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	"time"

	"github.com/docker/machine/libmachine/log"
)

// DeploymentRequest represents a new deployment request
type DeploymentRequest struct {
	Nodes       []string `json:"nodes"`
	Environment string   `json:"environment"`
	Key         string   `json:"key"`
}

// Deployment represents a deployment response
type Deployment struct {
	Nodes  []string `json:"nodes"`
	Site   string   `json:"site_uid"`
	Status string   `json:"status"`
	UID    string   `json:"uid"`
}

// SubmitDeployment submits a new deployment request to g5k api
func (c *Client) SubmitDeployment(deploymentReq DeploymentRequest) (string, error) {
	// create url for API call
	url := fmt.Sprintf("%s/sites/%s/deployments", G5kAPIFrontend, c.Site)

	log.Infof("Submitting a new deployment... (image: '%s')", deploymentReq.Environment)

	// send deployment request
	deploymentRes, err := c.Request().
		SetHeader("Content-Type", "application/json").
		SetBody(deploymentReq).
		SetResult(&Deployment{}).
		Post(url)

	if err != nil {
		return "", fmt.Errorf("Error while sending the deployment request: '%s'", err)
	}

	// check HTTP error code (expected: 201 Created)
	if deploymentRes.StatusCode() != 201 {
		return "", fmt.Errorf("The server returned an error (code: %d) after sending Deployment request: '%s'", deploymentRes.StatusCode(), deploymentRes.Status())
	}

	// unmarshal result
	deployment, ok := deploymentRes.Result().(*Deployment)
	if !ok {
		return "", fmt.Errorf("Error in the response of the Deployment request (unexpected type)")
	}

	log.Infof("Deployment submitted successfully (id: '%s')", deployment.UID)
	return deployment.UID, nil
}

// GetDeployment get the deployment from its id
func (c *Client) GetDeployment(deploymentID string) (*Deployment, error) {
	// create url for API call
	url := fmt.Sprintf("%s/sites/%s/deployments/%s", G5kAPIFrontend, c.Site, deploymentID)

	// send request
	deploymentRes, err := c.Request().
		SetResult(&Deployment{}).
		Get(url)

	if err != nil {
		return nil, fmt.Errorf("Error while retrieving Deployment informations: '%s'", err)
	}

	// check HTTP error code (expected: 200 OK)
	if deploymentRes.StatusCode() != 200 {
		return nil, fmt.Errorf("The server returned an error (code: %d) after requesting Deployment informations: '%s'", deploymentRes.StatusCode(), deploymentRes.Status())
	}

	// unmarshal result
	deployment, ok := deploymentRes.Result().(*Deployment)
	if !ok {
		return nil, fmt.Errorf("Error in the Deployment retrieving (unexpected type)")
	}

	return deployment, nil
}

// WaitUntilDeploymentIsFinished will wait until the deployment reach the 'terminated' state (no timeout)
func (c *Client) WaitUntilDeploymentIsFinished(deploymentID string) error {
	log.Info("Waiting for deployment to finish, it will take a few minutes...")

	// refresh deployment status
	for deployment, err := c.GetDeployment(deploymentID); deployment.Status != "terminated"; deployment, err = c.GetDeployment(deploymentID) {
		// check if GetDeployment returned an error
		if err != nil {
			return err
		}

		// stop if the deployment is in 'canceled' or 'error' state
		if deployment.Status == "canceled" || deployment.Status == "error" {
			return fmt.Errorf("Can't wait for a deployment in '%s' state", deployment.Status)
		}

		// wait 10 seconds before making another API call
		time.Sleep(10 * time.Second)
	}

	log.Info("Deployment finished successfully")
	return nil
}
<commit_msg>feat: Remove wait deployment function, sort nodes of deployment<commit_after>package api

import (
	"fmt"
	"sort"

	"github.com/docker/machine/libmachine/log"
)

// DeploymentRequest represents a new deployment request
type DeploymentRequest struct {
	Nodes       []string `json:"nodes"`
	Environment string   `json:"environment"`
	Key         string   `json:"key"`
}

// Deployment represents a deployment response
type Deployment struct {
	Nodes  []string `json:"nodes"`
	Site   string   `json:"site_uid"`
	Status string   `json:"status"`
	UID    string   `json:"uid"`
}

// SubmitDeployment submits a new deployment request to g5k api
func (c *Client) SubmitDeployment(deploymentReq DeploymentRequest) (string, error) {
	// create url for API call
	url := fmt.Sprintf("%s/sites/%s/deployments", G5kAPIFrontend, c.Site)

	log.Infof("Submitting a new deployment... (image: '%s')", deploymentReq.Environment)

	// send deployment request
	deploymentRes, err := c.Request().
		SetHeader("Content-Type", "application/json").
		SetBody(deploymentReq).
		SetResult(&Deployment{}).
		Post(url)

	if err != nil {
		return "", fmt.Errorf("Error while sending the deployment request: '%s'", err)
	}

	// check HTTP error code (expected: 201 Created)
	if deploymentRes.StatusCode() != 201 {
		return "", fmt.Errorf("The server returned an error (code: %d) after sending Deployment request: '%s'", deploymentRes.StatusCode(), deploymentRes.Status())
	}

	// unmarshal result
	deployment, ok := deploymentRes.Result().(*Deployment)
	if !ok {
		return "", fmt.Errorf("Error in the response of the Deployment request (unexpected type)")
	}

	log.Infof("Deployment submitted successfully (id: '%s')", deployment.UID)
	return deployment.UID, nil
}

// GetDeployment get the deployment from its id
func (c *Client) GetDeployment(deploymentID string) (*Deployment, error) {
	// create url for API call
	url := fmt.Sprintf("%s/sites/%s/deployments/%s", G5kAPIFrontend, c.Site, deploymentID)

	// send request
	deploymentRes, err := c.Request().
		SetResult(&Deployment{}).
		Get(url)

	if err != nil {
		return nil, fmt.Errorf("Error while retrieving Deployment informations: '%s'", err)
	}

	// check HTTP error code (expected: 200 OK)
	if deploymentRes.StatusCode() != 200 {
		return nil, fmt.Errorf("The server returned an error (code: %d) after requesting Deployment informations: '%s'", deploymentRes.StatusCode(), deploymentRes.Status())
	}

	// unmarshal result
	deployment, ok := deploymentRes.Result().(*Deployment)
	if !ok {
		return nil, fmt.Errorf("Error in the Deployment retrieving (unexpected type)")
	}

	sort.Strings(deployment.Nodes)
	return deployment, nil
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	"reflect"
	"sort"
	"strings"
	"testing"
	"time"

	"github.com/hashicorp/nomad/helper/uuid"
	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/hashicorp/nomad/testutil"
	"github.com/stretchr/testify/require"
)

func TestNodes_List(t *testing.T) {
	t.Parallel()
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		c.DevMode = true
	})
	defer s.Stop()
	nodes := c.Nodes()

	var qm *QueryMeta
	var out []*NodeListStub
	var err error

	testutil.WaitForResult(func() (bool, error) {
		out, qm, err = nodes.List(nil)
		if err != nil {
			return false, err
		}
		if n := len(out); n != 1 {
			return false, fmt.Errorf("expected 1 node, got: %d", n)
		}
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})

	// Check that we got valid QueryMeta.
	assertQueryMeta(t, qm)
}

func TestNodes_PrefixList(t *testing.T) {
	t.Parallel()
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		c.DevMode = true
	})
	defer s.Stop()
	nodes := c.Nodes()

	var qm *QueryMeta
	var out []*NodeListStub
	var err error

	// Get the node ID
	var nodeID string
	testutil.WaitForResult(func() (bool, error) {
		out, _, err := nodes.List(nil)
		if err != nil {
			return false, err
		}
		if n := len(out); n != 1 {
			return false, fmt.Errorf("expected 1 node, got: %d", n)
		}
		nodeID = out[0].ID
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})

	// Find node based on four character prefix
	out, qm, err = nodes.PrefixList(nodeID[:4])
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if n := len(out); n != 1 {
		t.Fatalf("expected 1 node, got: %d ", n)
	}

	// Check that we got valid QueryMeta.
	assertQueryMeta(t, qm)
}

func TestNodes_Info(t *testing.T) {
	t.Parallel()
	startTime := time.Now().Unix()
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		c.DevMode = true
	})
	defer s.Stop()
	nodes := c.Nodes()

	// Retrieving a nonexistent node returns error
	_, _, err := nodes.Info("12345678-abcd-efab-cdef-123456789abc", nil)
	if err == nil || !strings.Contains(err.Error(), "not found") {
		t.Fatalf("expected not found error, got: %#v", err)
	}

	// Get the node ID
	var nodeID, dc string
	testutil.WaitForResult(func() (bool, error) {
		out, _, err := nodes.List(nil)
		if err != nil {
			return false, err
		}
		if n := len(out); n != 1 {
			return false, fmt.Errorf("expected 1 node, got: %d", n)
		}
		nodeID = out[0].ID
		dc = out[0].Datacenter
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})

	// Querying for existing nodes returns properly
	result, qm, err := nodes.Info(nodeID, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	assertQueryMeta(t, qm)

	// Check that the result is what we expect
	if result.ID != nodeID || result.Datacenter != dc {
		t.Fatalf("expected %s (%s), got: %s (%s)",
			nodeID, dc,
			result.ID, result.Datacenter)
	}

	// Check that the StatusUpdatedAt field is being populated correctly
	if result.StatusUpdatedAt < startTime {
		t.Fatalf("start time: %v, status updated: %v", startTime, result.StatusUpdatedAt)
	}

	if len(result.Events) < 1 {
		t.Fatalf("Expected at minimum the node register event to be populated: %+v", result)
	}
}

func TestNodes_ToggleDrain(t *testing.T) {
	t.Parallel()
	require := require.New(t)
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		c.DevMode = true
	})
	defer s.Stop()
	nodes := c.Nodes()

	// Wait for node registration and get the ID
	var nodeID string
	testutil.WaitForResult(func() (bool, error) {
		out, _, err := nodes.List(nil)
		if err != nil {
			return false, err
		}
		if n := len(out); n != 1 {
			return false, fmt.Errorf("expected 1 node, got: %d", n)
		}
		nodeID = out[0].ID
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})

	// Check for drain mode
	out, _, err := nodes.Info(nodeID, nil)
	require.Nil(err)
	if out.Drain {
		t.Fatalf("drain mode should be off")
	}

	// Toggle it on
	spec := &DrainSpec{
		Deadline: 10 * time.Second,
	}
	wm, err := nodes.UpdateDrain(nodeID, spec, false, nil)
	require.Nil(err)
	assertWriteMeta(t, wm)

	// Check again
	out, _, err = nodes.Info(nodeID, nil)
	require.Nil(err)
	if out.SchedulingEligibility != structs.NodeSchedulingIneligible {
		t.Fatalf("bad eligibility: %v vs %v", out.SchedulingEligibility, structs.NodeSchedulingIneligible)
	}

	// Toggle off again
	wm, err = nodes.UpdateDrain(nodeID, nil, true, nil)
	require.Nil(err)
	assertWriteMeta(t, wm)

	// Check again
	out, _, err = nodes.Info(nodeID, nil)
	require.Nil(err)
	if out.Drain {
		t.Fatalf("drain mode should be off")
	}
	if out.DrainStrategy != nil {
		t.Fatalf("drain strategy should be unset")
	}
	if out.SchedulingEligibility != structs.NodeSchedulingEligible {
		t.Fatalf("should be eligible")
	}
}

func TestNodes_ToggleEligibility(t *testing.T) {
	t.Parallel()
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		c.DevMode = true
	})
	defer s.Stop()
	nodes := c.Nodes()

	// Wait for node registration and get the ID
	var nodeID string
	testutil.WaitForResult(func() (bool, error) {
		out, _, err := nodes.List(nil)
		if err != nil {
			return false, err
		}
		if n := len(out); n != 1 {
			return false, fmt.Errorf("expected 1 node, got: %d", n)
		}
		nodeID = out[0].ID
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})

	// Check for eligibility
	out, _, err := nodes.Info(nodeID, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if out.SchedulingEligibility != structs.NodeSchedulingEligible {
		t.Fatalf("node should be eligible")
	}

	// Toggle it off
	wm, err := nodes.ToggleEligibility(nodeID, false, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	assertWriteMeta(t, wm)

	// Check again
	out, _, err = nodes.Info(nodeID, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if out.SchedulingEligibility != structs.NodeSchedulingIneligible {
		t.Fatalf("bad eligibility: %v vs %v", out.SchedulingEligibility, structs.NodeSchedulingIneligible)
	}

	// Toggle on
	wm, err = nodes.ToggleEligibility(nodeID, true, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	assertWriteMeta(t, wm)

	// Check again
	out, _, err = nodes.Info(nodeID, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if out.SchedulingEligibility != structs.NodeSchedulingEligible {
		t.Fatalf("bad eligibility: %v vs %v", out.SchedulingEligibility, structs.NodeSchedulingEligible)
	}
}

func TestNodes_Allocations(t *testing.T) {
	t.Parallel()
	c, s := makeClient(t, nil, nil)
	defer s.Stop()
	nodes := c.Nodes()

	// Looking up by a nonexistent node returns nothing. We
	// don't check the index here because it's possible the node
	// has already registered, in which case we will get a non-
	// zero result anyways.
	allocs, _, err := nodes.Allocations("nope", nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if n := len(allocs); n != 0 {
		t.Fatalf("expected 0 allocs, got: %d", n)
	}
}

func TestNodes_ForceEvaluate(t *testing.T) {
	t.Parallel()
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		c.DevMode = true
	})
	defer s.Stop()
	nodes := c.Nodes()

	// Force-eval on a nonexistent node fails
	_, _, err := nodes.ForceEvaluate("12345678-abcd-efab-cdef-123456789abc", nil)
	if err == nil || !strings.Contains(err.Error(), "not found") {
		t.Fatalf("expected not found error, got: %#v", err)
	}

	// Wait for node registration and get the ID
	var nodeID string
	testutil.WaitForResult(func() (bool, error) {
		out, _, err := nodes.List(nil)
		if err != nil {
			return false, err
		}
		if n := len(out); n != 1 {
			return false, fmt.Errorf("expected 1 node, got: %d", n)
		}
		nodeID = out[0].ID
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})

	// Try force-eval again. We don't check the WriteMeta because
	// there are no allocations to process, so we would get an index
	// of zero. Same goes for the eval ID.
	_, _, err = nodes.ForceEvaluate(nodeID, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
}

func TestNodes_Sort(t *testing.T) {
	t.Parallel()
	nodes := []*NodeListStub{
		{CreateIndex: 2},
		{CreateIndex: 1},
		{CreateIndex: 5},
	}
	sort.Sort(NodeIndexSort(nodes))

	expect := []*NodeListStub{
		{CreateIndex: 5},
		{CreateIndex: 2},
		{CreateIndex: 1},
	}
	if !reflect.DeepEqual(nodes, expect) {
		t.Fatalf("\n\n%#v\n\n%#v", nodes, expect)
	}
}

func TestNodes_GC(t *testing.T) {
	t.Parallel()
	require := require.New(t)
	c, s := makeClient(t, nil, nil)
	defer s.Stop()
	nodes := c.Nodes()

	err := nodes.GC(uuid.Generate(), nil)
	require.NotNil(err)
	require.True(structs.IsErrUnknownNode(err))
}

func TestNodes_GcAlloc(t *testing.T) {
	t.Parallel()
	require := require.New(t)
	c, s := makeClient(t, nil, nil)
	defer s.Stop()
	nodes := c.Nodes()

	err := nodes.GcAlloc(uuid.Generate(), nil)
	require.NotNil(err)
	require.True(structs.IsErrUnknownAllocation(err))
}
<commit_msg>Drain cli, api, http<commit_after>package api

import (
	"fmt"
	"reflect"
	"sort"
	"strings"
	"testing"
	"time"

	"github.com/hashicorp/nomad/helper/uuid"
	"github.com/hashicorp/nomad/nomad/structs"
	"github.com/hashicorp/nomad/testutil"
	"github.com/stretchr/testify/require"
)

func TestNodes_List(t *testing.T) {
	t.Parallel()
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		c.DevMode = true
	})
	defer s.Stop()
	nodes := c.Nodes()

	var qm *QueryMeta
	var out []*NodeListStub
	var err error

	testutil.WaitForResult(func() (bool, error) {
		out, qm, err = nodes.List(nil)
		if err != nil {
			return false, err
		}
		if n := len(out); n != 1 {
			return false, fmt.Errorf("expected 1 node, got: %d", n)
		}
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})

	// Check that we got valid QueryMeta.
	assertQueryMeta(t, qm)
}

func TestNodes_PrefixList(t *testing.T) {
	t.Parallel()
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		c.DevMode = true
	})
	defer s.Stop()
	nodes := c.Nodes()

	var qm *QueryMeta
	var out []*NodeListStub
	var err error

	// Get the node ID
	var nodeID string
	testutil.WaitForResult(func() (bool, error) {
		out, _, err := nodes.List(nil)
		if err != nil {
			return false, err
		}
		if n := len(out); n != 1 {
			return false, fmt.Errorf("expected 1 node, got: %d", n)
		}
		nodeID = out[0].ID
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})

	// Find node based on four character prefix
	out, qm, err = nodes.PrefixList(nodeID[:4])
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if n := len(out); n != 1 {
		t.Fatalf("expected 1 node, got: %d ", n)
	}

	// Check that we got valid QueryMeta.
	assertQueryMeta(t, qm)
}

func TestNodes_Info(t *testing.T) {
	t.Parallel()
	startTime := time.Now().Unix()
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		c.DevMode = true
	})
	defer s.Stop()
	nodes := c.Nodes()

	// Retrieving a nonexistent node returns error
	_, _, err := nodes.Info("12345678-abcd-efab-cdef-123456789abc", nil)
	if err == nil || !strings.Contains(err.Error(), "not found") {
		t.Fatalf("expected not found error, got: %#v", err)
	}

	// Get the node ID
	var nodeID, dc string
	testutil.WaitForResult(func() (bool, error) {
		out, _, err := nodes.List(nil)
		if err != nil {
			return false, err
		}
		if n := len(out); n != 1 {
			return false, fmt.Errorf("expected 1 node, got: %d", n)
		}
		nodeID = out[0].ID
		dc = out[0].Datacenter
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})

	// Querying for existing nodes returns properly
	result, qm, err := nodes.Info(nodeID, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	assertQueryMeta(t, qm)

	// Check that the result is what we expect
	if result.ID != nodeID || result.Datacenter != dc {
		t.Fatalf("expected %s (%s), got: %s (%s)",
			nodeID, dc,
			result.ID, result.Datacenter)
	}

	// Check that the StatusUpdatedAt field is being populated correctly
	if result.StatusUpdatedAt < startTime {
		t.Fatalf("start time: %v, status updated: %v", startTime, result.StatusUpdatedAt)
	}

	if len(result.Events) < 1 {
		t.Fatalf("Expected at minimum the node register event to be populated: %+v", result)
	}
}

func TestNodes_ToggleDrain(t *testing.T) {
	t.Parallel()
	require := require.New(t)
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		c.DevMode = true
	})
	defer s.Stop()
	nodes := c.Nodes()

	// Wait for node registration and get the ID
	var nodeID string
	testutil.WaitForResult(func() (bool, error) {
		out, _, err := nodes.List(nil)
		if err != nil {
			return false, err
		}
		if n := len(out); n != 1 {
			return false, fmt.Errorf("expected 1 node, got: %d", n)
		}
		nodeID = out[0].ID
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})

	// Check for drain mode
	out, _, err := nodes.Info(nodeID, nil)
	require.Nil(err)
	if out.Drain {
		t.Fatalf("drain mode should be off")
	}

	// Toggle it on
	spec := &DrainSpec{
		Deadline: 10 * time.Second,
	}
	wm, err := nodes.UpdateDrain(nodeID, spec, false, nil)
	require.Nil(err)
	assertWriteMeta(t, wm)

	// Check again
	out, _, err = nodes.Info(nodeID, nil)
	require.Nil(err)
	if out.SchedulingEligibility != structs.NodeSchedulingIneligible {
		t.Fatalf("bad eligibility: %v vs %v", out.SchedulingEligibility, structs.NodeSchedulingIneligible)
	}

	// Toggle off again
	wm, err = nodes.UpdateDrain(nodeID, nil, true, nil)
	require.Nil(err)
	assertWriteMeta(t, wm)

	// Check again
	out, _, err = nodes.Info(nodeID, nil)
	require.Nil(err)
	if out.Drain {
		t.Fatalf("drain mode should be off")
	}
	if out.DrainStrategy != nil {
		t.Fatalf("drain strategy should be unset")
	}
	if out.SchedulingEligibility != structs.NodeSchedulingEligible {
		t.Fatalf("should be eligible")
	}
}

func TestNodes_ToggleEligibility(t *testing.T) {
	t.Parallel()
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		c.DevMode = true
	})
	defer s.Stop()
	nodes := c.Nodes()

	// Wait for node registration and get the ID
	var nodeID string
	testutil.WaitForResult(func() (bool, error) {
		out, _, err := nodes.List(nil)
		if err != nil {
			return false, err
		}
		if n := len(out); n != 1 {
			return false, fmt.Errorf("expected 1 node, got: %d", n)
		}
		nodeID = out[0].ID
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})

	// Check for eligibility
	out, _, err := nodes.Info(nodeID, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if out.SchedulingEligibility != structs.NodeSchedulingEligible {
		t.Fatalf("node should be eligible")
	}

	// Toggle it off
	wm, err := nodes.ToggleEligibility(nodeID, false, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	assertWriteMeta(t, wm)

	// Check again
	out, _, err = nodes.Info(nodeID, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if out.SchedulingEligibility != structs.NodeSchedulingIneligible {
		t.Fatalf("bad eligibility: %v vs %v", out.SchedulingEligibility, structs.NodeSchedulingIneligible)
	}

	// Toggle on
	wm, err = nodes.ToggleEligibility(nodeID, true, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	assertWriteMeta(t, wm)

	// Check again
	out, _, err = nodes.Info(nodeID, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if out.SchedulingEligibility != structs.NodeSchedulingEligible {
		t.Fatalf("bad eligibility: %v vs %v", out.SchedulingEligibility, structs.NodeSchedulingEligible)
	}
	if out.DrainStrategy != nil {
		t.Fatalf("drain strategy should be unset")
	}
}

func TestNodes_Allocations(t *testing.T) {
	t.Parallel()
	c, s := makeClient(t, nil, nil)
	defer s.Stop()
	nodes := c.Nodes()

	// Looking up by a nonexistent node returns nothing. We
	// don't check the index here because it's possible the node
	// has already registered, in which case we will get a non-
	// zero result anyways.
	allocs, _, err := nodes.Allocations("nope", nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if n := len(allocs); n != 0 {
		t.Fatalf("expected 0 allocs, got: %d", n)
	}
}

func TestNodes_ForceEvaluate(t *testing.T) {
	t.Parallel()
	c, s := makeClient(t, nil, func(c *testutil.TestServerConfig) {
		c.DevMode = true
	})
	defer s.Stop()
	nodes := c.Nodes()

	// Force-eval on a nonexistent node fails
	_, _, err := nodes.ForceEvaluate("12345678-abcd-efab-cdef-123456789abc", nil)
	if err == nil || !strings.Contains(err.Error(), "not found") {
		t.Fatalf("expected not found error, got: %#v", err)
	}

	// Wait for node registration and get the ID
	var nodeID string
	testutil.WaitForResult(func() (bool, error) {
		out, _, err := nodes.List(nil)
		if err != nil {
			return false, err
		}
		if n := len(out); n != 1 {
			return false, fmt.Errorf("expected 1 node, got: %d", n)
		}
		nodeID = out[0].ID
		return true, nil
	}, func(err error) {
		t.Fatalf("err: %s", err)
	})

	// Try force-eval again. We don't check the WriteMeta because
	// there are no allocations to process, so we would get an index
	// of zero. Same goes for the eval ID.
	_, _, err = nodes.ForceEvaluate(nodeID, nil)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
}

func TestNodes_Sort(t *testing.T) {
	t.Parallel()
	nodes := []*NodeListStub{
		{CreateIndex: 2},
		{CreateIndex: 1},
		{CreateIndex: 5},
	}
	sort.Sort(NodeIndexSort(nodes))

	expect := []*NodeListStub{
		{CreateIndex: 5},
		{CreateIndex: 2},
		{CreateIndex: 1},
	}
	if !reflect.DeepEqual(nodes, expect) {
		t.Fatalf("\n\n%#v\n\n%#v", nodes, expect)
	}
}

func TestNodes_GC(t *testing.T) {
	t.Parallel()
	require := require.New(t)
	c, s := makeClient(t, nil, nil)
	defer s.Stop()
	nodes := c.Nodes()

	err := nodes.GC(uuid.Generate(), nil)
	require.NotNil(err)
	require.True(structs.IsErrUnknownNode(err))
}

func TestNodes_GcAlloc(t *testing.T) {
	t.Parallel()
	require := require.New(t)
	c, s := makeClient(t, nil, nil)
	defer s.Stop()
	nodes := c.Nodes()

	err := nodes.GcAlloc(uuid.Generate(), nil)
	require.NotNil(err)
	require.True(structs.IsErrUnknownAllocation(err))
}
<|endoftext|>


<commit_before>package api

import (
	"context"
	"errors"
)

func (c *Sys) Renew(id string, increment int) (*Secret, error) {
	r := c.c.NewRequest("PUT", "/v1/sys/leases/renew")

	body := map[string]interface{}{
		"increment": increment,
		"lease_id":  id,
	}
	if err := r.SetJSONBody(body); err != nil {
		return nil, err
	}

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	resp, err := c.c.RawRequestWithContext(ctx, r)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	return ParseSecret(resp.Body)
}

func (c *Sys) Revoke(id string) error {
	r := c.c.NewRequest("PUT", "/v1/sys/leases/revoke/"+id)

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	resp, err := c.c.RawRequestWithContext(ctx, r)
	if err == nil {
		defer resp.Body.Close()
	}
	return err
}

func (c *Sys) RevokePrefix(id string) error {
	r := c.c.NewRequest("PUT", "/v1/sys/leases/revoke-prefix/"+id)

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	resp, err := c.c.RawRequestWithContext(ctx, r)
	if err == nil {
		defer resp.Body.Close()
	}
	return err
}

func (c *Sys) RevokeForce(id string) error {
	r := c.c.NewRequest("PUT", "/v1/sys/leases/revoke-force/"+id)

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	resp, err := c.c.RawRequestWithContext(ctx, r)
	if err == nil {
		defer resp.Body.Close()
	}
	return err
}

func (c *Sys) RevokeWithOptions(opts *RevokeOptions) error {
	if opts == nil {
		return errors.New("nil options provided")
	}

	// Construct path
	path := "/v1/sys/leases/revoke/"
	switch {
	case opts.Force:
		path = "/v1/sys/leases/revoke-force/"
	case opts.Prefix:
		path = "/v1/sys/leases/revoke-prefix/"
	}
	path += opts.LeaseID

	r := c.c.NewRequest("PUT", path)
	if !opts.Force {
		body := map[string]interface{}{
			"sync": opts.Sync,
		}
		if err := r.SetJSONBody(body); err != nil {
			return err
		}
	}

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	resp, err := c.c.RawRequestWithContext(ctx, r)
	if err == nil {
		defer resp.Body.Close()
	}
	return err
}

type RevokeOptions struct {
	LeaseID string
	Force   bool
	Prefix  bool
	Sync    bool
}
<commit_msg>Update API to use lease_id in body of sys/leases/revoke call (#7777)<commit_after>package api

import (
	"context"
	"errors"
)

func (c *Sys) Renew(id string, increment int) (*Secret, error) {
	r := c.c.NewRequest("PUT", "/v1/sys/leases/renew")

	body := map[string]interface{}{
		"increment": increment,
		"lease_id":  id,
	}
	if err := r.SetJSONBody(body); err != nil {
		return nil, err
	}

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	resp, err := c.c.RawRequestWithContext(ctx, r)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	return ParseSecret(resp.Body)
}

func (c *Sys) Revoke(id string) error {
	r := c.c.NewRequest("PUT", "/v1/sys/leases/revoke")
	body := map[string]interface{}{
		"lease_id": id,
	}
	if err := r.SetJSONBody(body); err != nil {
		return err
	}

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	resp, err := c.c.RawRequestWithContext(ctx, r)
	if err == nil {
		defer resp.Body.Close()
	}
	return err
}

func (c *Sys) RevokePrefix(id string) error {
	r := c.c.NewRequest("PUT", "/v1/sys/leases/revoke-prefix/"+id)

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	resp, err := c.c.RawRequestWithContext(ctx, r)
	if err == nil {
		defer resp.Body.Close()
	}
	return err
}

func (c *Sys) RevokeForce(id string) error {
	r := c.c.NewRequest("PUT", "/v1/sys/leases/revoke-force/"+id)

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	resp, err := c.c.RawRequestWithContext(ctx, r)
	if err == nil {
		defer resp.Body.Close()
	}
	return err
}

func (c *Sys) RevokeWithOptions(opts *RevokeOptions) error {
	if opts == nil {
		return errors.New("nil options provided")
	}

	// Construct path
	path := "/v1/sys/leases/revoke/"
	switch {
	case opts.Force:
		path = "/v1/sys/leases/revoke-force/"
	case opts.Prefix:
		path = "/v1/sys/leases/revoke-prefix/"
	}
	path += opts.LeaseID

	r := c.c.NewRequest("PUT", path)
	if !opts.Force {
		body := map[string]interface{}{
			"sync": opts.Sync,
		}
		if err := r.SetJSONBody(body); err != nil {
			return err
		}
	}

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	resp, err := c.c.RawRequestWithContext(ctx, r)
	if err == nil {
		defer resp.Body.Close()
	}
	return err
}

type RevokeOptions struct {
	LeaseID string
	Force   bool
	Prefix  bool
	Sync    bool
}
<|endoftext|>


<commit_before>/*
Copyright 2018 Google Inc. All Rights Reserved.

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

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

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

import (
	"reflect"
	"testing"

	"github.com/spf13/cobra"
)

func TestConfigCommand(t *testing.T) {
	Version = "1.0.1"
	ConfigFile = "testdata/testConfig.json"
	testCommand := ContainerToolCommand{
		ContainerToolCommandBase: &ContainerToolCommandBase{
			Command: &cobra.Command{
				Use: "Hello Command",
			},
			Phase: "test",
		},
		Output: nil,
		RunO: func(command *cobra.Command, args []string) (interface{}, error) {
			return nil, nil
		},
	}

	testCommand.SetArgs([]string{"config"})
	Execute(&testCommand)
	expectedConfig := &ConfigOutput{
		Config: map[string]interface{}{
			"message":     "echo", // Make sure user defined config are also returned
			"updatecheck": "true", // inhertited from the Default Config
			"logdir":      "/tmp", // This overrides the default Config
		},
	}
	if reflect.DeepEqual(ConfigCommand.Output, expectedConfig) {
		t.Errorf("Expected to contain: \n %v\nGot:\n %v\n", expectedConfig, ConfigCommand.Output)
	}
}
<commit_msg>Add tests<commit_after>/*
Copyright 2018 Google Inc. All Rights Reserved.

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

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

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

import (
	"encoding/json"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"testing"

	"github.com/spf13/cobra"
)

func TestConfigCommandGet(t *testing.T) {
	var testConfigCommand = ContainerToolCommand{
		ContainerToolCommandBase: &ContainerToolCommandBase{
			Command: &cobra.Command{
				Use: "Hello Command",
			},
			Phase: "test",
		},
		Output: nil,
		RunO: func(command *cobra.Command, args []string) (interface{}, error) {
			return nil, nil
		},
	}

	Version = "1.0.1"
	ConfigFile = "testdata/testConfig.json"
	testConfigCommand.SetArgs([]string{"config"})
	Execute(&testConfigCommand)
	expectedConfig := &ConfigOutput{
		Config: map[string]interface{}{
			"message":     "echo", // Make sure user defined config are also returned
			"updatecheck": "true", // inhertited from the Default Config
			"logdir":      "/tmp", // This overrides the default Config
		},
	}
	if reflect.DeepEqual(ConfigCommand.Output, expectedConfig) {
		t.Errorf("Expected to contain: \n %v\nGot:\n %v\n", expectedConfig, ConfigCommand.Output)
	}
}

func TestConfigCommandSet(t *testing.T) {
	var testConfigCommand = ContainerToolCommand{
		ContainerToolCommandBase: &ContainerToolCommandBase{
			Command: &cobra.Command{
				Use: "Hello Command",
			},
			Phase: "test",
		},
		Output: nil,
		RunO: func(command *cobra.Command, args []string) (interface{}, error) {
			return nil, nil
		},
	}

	tmpDir, _ := ioutil.TempDir("", "tests")
	defer os.RemoveAll(tmpDir)

	Version = "1.0.1"
	ConfigFile = filepath.Join(tmpDir, "testConfig.json")
	jsonConfigData, _ := json.Marshal(map[string]interface{}{
		"logdir":  "/tmp",
		"message": "echo",
	})
	ioutil.WriteFile(ConfigFile, jsonConfigData, 0644)

	testConfigCommand.SetArgs([]string{"config", "set", "message", "hi"})
	Execute(&testConfigCommand)

	expectedConfig := map[string]interface{}{
		"logdir":  "/tmp", // This overrides the default Config
		"message": "hi",   // Make sure user defined config are also returned
	}
	//Actual Config
	var actualConfig map[string]interface{}
	raw, err := ioutil.ReadFile(ConfigFile)
	if err != nil {
		t.Errorf("Error Reading Test Config File %s", ConfigFile)
	}
	json.Unmarshal(raw, &actualConfig)
	if !reflect.DeepEqual(actualConfig, expectedConfig) {
		t.Errorf("Expected to contain: \n %v\nGot:\n %v\n", expectedConfig, actualConfig)
	}
}
<|endoftext|>


<commit_before>// Copyright 2015 PingCAP, 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package mysql

// MySQL type information.
const (
	TypeUnspecified byte = 0
	TypeTiny        byte = 1
	TypeShort       byte = 2
	TypeLong        byte = 3
	TypeFloat       byte = 4
	TypeDouble      byte = 5
	TypeNull        byte = 6
	TypeTimestamp   byte = 7
	TypeLonglong    byte = 8
	TypeInt24       byte = 9
	TypeDate        byte = 10
	/* TypeDuration original name was TypeTime, renamed to TypeDuration to resolve the conflict with Go type Time.*/
	TypeDuration byte = 11
	TypeDatetime byte = 12
	TypeYear     byte = 13
	TypeNewDate  byte = 14
	TypeVarchar  byte = 15
	TypeBit      byte = 16

	TypeJSON       byte = 0xf5
	TypeNewDecimal byte = 0xf6
	TypeEnum       byte = 0xf7
	TypeSet        byte = 0xf8
	TypeTinyBlob   byte = 0xf9
	TypeMediumBlob byte = 0xfa
	TypeLongBlob   byte = 0xfb
	TypeBlob       byte = 0xfc
	TypeVarString  byte = 0xfd
	TypeString     byte = 0xfe
	TypeGeometry   byte = 0xff
)

// Flag information.
const (
	NotNullFlag        uint = 1 << 0  /* Field can't be NULL */
	PriKeyFlag         uint = 1 << 1  /* Field is part of a primary key */
	UniqueKeyFlag      uint = 1 << 2  /* Field is part of a unique key */
	MultipleKeyFlag    uint = 1 << 3  /* Field is part of a key */
	BlobFlag           uint = 1 << 4  /* Field is a blob */
	UnsignedFlag       uint = 1 << 5  /* Field is unsigned */
	ZerofillFlag       uint = 1 << 6  /* Field is zerofill */
	BinaryFlag         uint = 1 << 7  /* Field is binary   */
	EnumFlag           uint = 1 << 8  /* Field is an enum */
	AutoIncrementFlag  uint = 1 << 9  /* Field is an auto increment field */
	TimestampFlag      uint = 1 << 10 /* Field is a timestamp */
	SetFlag            uint = 1 << 11 /* Field is a set */
	NoDefaultValueFlag uint = 1 << 12 /* Field doesn't have a default value */
	OnUpdateNowFlag    uint = 1 << 13 /* Field is set to NOW on UPDATE */
	PartKeyFlag        uint = 1 << 14 /* Intern: Part of some keys */
	NumFlag            uint = 1 << 15 /* Field is a num (for clients) */

	GroupFlag             uint = 1 << 15 /* Internal: Group field */
	UniqueFlag            uint = 1 << 16 /* Internal: Used by sql_yacc */
	BinCmpFlag            uint = 1 << 17 /* Internal: Used by sql_yacc */
	ParseToJSONFlag       uint = 1 << 18 /* Internal: Used when we want to parse string to JSON in CAST */
	IsBooleanFlag         uint = 1 << 19 /* Internal: Used for telling boolean literal from integer */
	PreventNullInsertFlag uint = 1 << 20 /* Prevent this Field from inserting NULL values */
	EnumSetAsIntFlag      uint = 1 << 21 /* Internal: Used for inferring enum eval type. */
)

// TypeInt24 bounds.
const (
	MaxUint24 = 1<<24 - 1
	MaxInt24  = 1<<23 - 1
	MinInt24  = -1 << 23
)

// HasNotNullFlag checks if NotNullFlag is set.
func HasNotNullFlag(flag uint) bool {
	return (flag & NotNullFlag) > 0
}

// HasNoDefaultValueFlag checks if NoDefaultValueFlag is set.
func HasNoDefaultValueFlag(flag uint) bool {
	return (flag & NoDefaultValueFlag) > 0
}

// HasAutoIncrementFlag checks if AutoIncrementFlag is set.
func HasAutoIncrementFlag(flag uint) bool {
	return (flag & AutoIncrementFlag) > 0
}

// HasUnsignedFlag checks if UnsignedFlag is set.
func HasUnsignedFlag(flag uint) bool {
	return (flag & UnsignedFlag) > 0
}

// HasZerofillFlag checks if ZerofillFlag is set.
func HasZerofillFlag(flag uint) bool {
	return (flag & ZerofillFlag) > 0
}

// HasBinaryFlag checks if BinaryFlag is set.
func HasBinaryFlag(flag uint) bool {
	return (flag & BinaryFlag) > 0
}

// HasPriKeyFlag checks if PriKeyFlag is set.
func HasPriKeyFlag(flag uint) bool {
	return (flag & PriKeyFlag) > 0
}

// HasUniKeyFlag checks if UniqueKeyFlag is set.
func HasUniKeyFlag(flag uint) bool {
	return (flag & UniqueKeyFlag) > 0
}

// HasMultipleKeyFlag checks if MultipleKeyFlag is set.
func HasMultipleKeyFlag(flag uint) bool {
	return (flag & MultipleKeyFlag) > 0
}

// HasTimestampFlag checks if HasTimestampFlag is set.
func HasTimestampFlag(flag uint) bool {
	return (flag & TimestampFlag) > 0
}

// HasOnUpdateNowFlag checks if OnUpdateNowFlag is set.
func HasOnUpdateNowFlag(flag uint) bool {
	return (flag & OnUpdateNowFlag) > 0
}

// HasParseToJSONFlag checks if ParseToJSONFlag is set.
func HasParseToJSONFlag(flag uint) bool {
	return (flag & ParseToJSONFlag) > 0
}

// HasIsBooleanFlag checks if IsBooleanFlag is set.
func HasIsBooleanFlag(flag uint) bool {
	return (flag & IsBooleanFlag) > 0
}

// HasPreventNullInsertFlag checks if PreventNullInsertFlag is set.
func HasPreventNullInsertFlag(flag uint) bool {
	return (flag & PreventNullInsertFlag) > 0
}

// HasEnumSetAsIntFlag checks if EnumSetAsIntFlag is set.
func HasEnumSetAsIntFlag(flag uint) bool {
	return (flag & EnumSetAsIntFlag) > 0
}
<commit_msg>[parser] add drop column with index flag (#1286)<commit_after>// Copyright 2015 PingCAP, 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package mysql

// MySQL type information.
const (
	TypeUnspecified byte = 0
	TypeTiny        byte = 1
	TypeShort       byte = 2
	TypeLong        byte = 3
	TypeFloat       byte = 4
	TypeDouble      byte = 5
	TypeNull        byte = 6
	TypeTimestamp   byte = 7
	TypeLonglong    byte = 8
	TypeInt24       byte = 9
	TypeDate        byte = 10
	/* TypeDuration original name was TypeTime, renamed to TypeDuration to resolve the conflict with Go type Time.*/
	TypeDuration byte = 11
	TypeDatetime byte = 12
	TypeYear     byte = 13
	TypeNewDate  byte = 14
	TypeVarchar  byte = 15
	TypeBit      byte = 16

	TypeJSON       byte = 0xf5
	TypeNewDecimal byte = 0xf6
	TypeEnum       byte = 0xf7
	TypeSet        byte = 0xf8
	TypeTinyBlob   byte = 0xf9
	TypeMediumBlob byte = 0xfa
	TypeLongBlob   byte = 0xfb
	TypeBlob       byte = 0xfc
	TypeVarString  byte = 0xfd
	TypeString     byte = 0xfe
	TypeGeometry   byte = 0xff
)

// Flag information.
const (
	NotNullFlag        uint = 1 << 0  /* Field can't be NULL */
	PriKeyFlag         uint = 1 << 1  /* Field is part of a primary key */
	UniqueKeyFlag      uint = 1 << 2  /* Field is part of a unique key */
	MultipleKeyFlag    uint = 1 << 3  /* Field is part of a key */
	BlobFlag           uint = 1 << 4  /* Field is a blob */
	UnsignedFlag       uint = 1 << 5  /* Field is unsigned */
	ZerofillFlag       uint = 1 << 6  /* Field is zerofill */
	BinaryFlag         uint = 1 << 7  /* Field is binary   */
	EnumFlag           uint = 1 << 8  /* Field is an enum */
	AutoIncrementFlag  uint = 1 << 9  /* Field is an auto increment field */
	TimestampFlag      uint = 1 << 10 /* Field is a timestamp */
	SetFlag            uint = 1 << 11 /* Field is a set */
	NoDefaultValueFlag uint = 1 << 12 /* Field doesn't have a default value */
	OnUpdateNowFlag    uint = 1 << 13 /* Field is set to NOW on UPDATE */
	PartKeyFlag        uint = 1 << 14 /* Intern: Part of some keys */
	NumFlag            uint = 1 << 15 /* Field is a num (for clients) */

	GroupFlag             uint = 1 << 15 /* Internal: Group field */
	UniqueFlag            uint = 1 << 16 /* Internal: Used by sql_yacc */
	BinCmpFlag            uint = 1 << 17 /* Internal: Used by sql_yacc */
	ParseToJSONFlag       uint = 1 << 18 /* Internal: Used when we want to parse string to JSON in CAST */
	IsBooleanFlag         uint = 1 << 19 /* Internal: Used for telling boolean literal from integer */
	PreventNullInsertFlag uint = 1 << 20 /* Prevent this Field from inserting NULL values */
	EnumSetAsIntFlag      uint = 1 << 21 /* Internal: Used for inferring enum eval type. */
	DropColumnIndexFlag   uint = 1 << 22 /* Internal: Used for indicate the column is being dropped with index */
)

// TypeInt24 bounds.
const (
	MaxUint24 = 1<<24 - 1
	MaxInt24  = 1<<23 - 1
	MinInt24  = -1 << 23
)

// HasDropColumnWithIndexFlag checks if DropColumnIndexFlag is set.
func HasDropColumnWithIndexFlag(flag uint) bool {
	return (flag & DropColumnIndexFlag) > 0
}

// HasNotNullFlag checks if NotNullFlag is set.
func HasNotNullFlag(flag uint) bool {
	return (flag & NotNullFlag) > 0
}

// HasNoDefaultValueFlag checks if NoDefaultValueFlag is set.
func HasNoDefaultValueFlag(flag uint) bool {
	return (flag & NoDefaultValueFlag) > 0
}

// HasAutoIncrementFlag checks if AutoIncrementFlag is set.
func HasAutoIncrementFlag(flag uint) bool {
	return (flag & AutoIncrementFlag) > 0
}

// HasUnsignedFlag checks if UnsignedFlag is set.
func HasUnsignedFlag(flag uint) bool {
	return (flag & UnsignedFlag) > 0
}

// HasZerofillFlag checks if ZerofillFlag is set.
func HasZerofillFlag(flag uint) bool {
	return (flag & ZerofillFlag) > 0
}

// HasBinaryFlag checks if BinaryFlag is set.
func HasBinaryFlag(flag uint) bool {
	return (flag & BinaryFlag) > 0
}

// HasPriKeyFlag checks if PriKeyFlag is set.
func HasPriKeyFlag(flag uint) bool {
	return (flag & PriKeyFlag) > 0
}

// HasUniKeyFlag checks if UniqueKeyFlag is set.
func HasUniKeyFlag(flag uint) bool {
	return (flag & UniqueKeyFlag) > 0
}

// HasMultipleKeyFlag checks if MultipleKeyFlag is set.
func HasMultipleKeyFlag(flag uint) bool {
	return (flag & MultipleKeyFlag) > 0
}

// HasTimestampFlag checks if HasTimestampFlag is set.
func HasTimestampFlag(flag uint) bool {
	return (flag & TimestampFlag) > 0
}

// HasOnUpdateNowFlag checks if OnUpdateNowFlag is set.
func HasOnUpdateNowFlag(flag uint) bool {
	return (flag & OnUpdateNowFlag) > 0
}

// HasParseToJSONFlag checks if ParseToJSONFlag is set.
func HasParseToJSONFlag(flag uint) bool {
	return (flag & ParseToJSONFlag) > 0
}

// HasIsBooleanFlag checks if IsBooleanFlag is set.
func HasIsBooleanFlag(flag uint) bool {
	return (flag & IsBooleanFlag) > 0
}

// HasPreventNullInsertFlag checks if PreventNullInsertFlag is set.
func HasPreventNullInsertFlag(flag uint) bool {
	return (flag & PreventNullInsertFlag) > 0
}

// HasEnumSetAsIntFlag checks if EnumSetAsIntFlag is set.
func HasEnumSetAsIntFlag(flag uint) bool {
	return (flag & EnumSetAsIntFlag) > 0
}
<|endoftext|>


<commit_before>package ksonnet

// NOTE: custom constructors will be removed at ksonnet 0.11

func locateConstructors(desc Description) []constructor {
	ctors, ok := customConstructors[desc]
	if !ok {
		return nil
	}

	return ctors
}

func makeDescriptor(codebase, group, kind string) Description {
	return Description{
		Codebase: codebase,
		Group:    group,
		Kind:     kind,
	}
}

var (
	customConstructors = map[Description][]constructor{
		makeDescriptor("api", "apps", "Deployment"):         deploymentCtor,
		makeDescriptor("api", "apps", "DeploymentList"):     objectList,
		makeDescriptor("api", "apps", "DeploymentRollback"): deploymentRollbackCtor,
		makeDescriptor("api", "apps", "Scale"):              scaleCtor,
		makeDescriptor("api", "apps", "StatefulSet"):        statefulSetCtor,
		makeDescriptor("api", "apps", "StatefulSetList"):    objectList,

		makeDescriptor("api", "extensions", "Deployment"):         deploymentCtor,
		makeDescriptor("api", "extensions", "DeploymentList"):     objectList,
		makeDescriptor("api", "extensions", "DeploymentRollback"): deploymentRollbackCtor,
		makeDescriptor("api", "extensions", "Scale"):              scaleCtor,
		makeDescriptor("api", "extensions", "StatefulSet"):        statefulSetCtor,
		makeDescriptor("api", "extensions", "StatefulSetList"):    objectList,

		makeDescriptor("api", "authentication", "TokenReview"): []constructor{
			*newConstructor(
				"new",
				*newConstructorParam("token", "mixin.spec.withToken", nil),
			),
		},

		makeDescriptor("api", "autoscaling", "HorizontalPodAutoscalerList"): objectList,
		makeDescriptor("api", "autoscaling", "Scale"):                       scaleCtor,

		makeDescriptor("api", "batch", "JobList"):     objectList,
		makeDescriptor("api", "batch", "CronJobList"): objectList,

		makeDescriptor("api", "certificates", "CertificateSigningRequestList"): objectList,

		makeDescriptor("api", "core", "ConfigMap"): []constructor{
			*newConstructor(
				"new",
				*newConstructorParam("name", "mixin.metadata.withName", nil),
			),
		},
		makeDescriptor("api", "core", "ConfigMapList"): objectList,
		makeDescriptor("api", "core", "Container"): []constructor{
			*newConstructor(
				"new",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("image", "withImage", nil),
			),
		},
		makeDescriptor("api", "core", "ContainerPort"): []constructor{
			*newConstructor("new", *newConstructorParam("containerPort", "withContainerPort", nil)),
			*newConstructor("newNamed",
				*newConstructorParam("containerPort", "withContainerPort", nil),
				*newConstructorParam("name", "withName", nil),
			),
		},
		makeDescriptor("api", "core", "EndpointsList"): objectList,
		makeDescriptor("api", "core", "EnvVar"): []constructor{
			*newConstructor("new",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("value", "withValue", nil)),
			*newConstructor("fromSecretRef",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("secretRefName", "mixin.valueFrom.secretKeyRef.withName", nil),
				*newConstructorParam("secretRefKey", "mixin.valueFrom.secretKeyRef.withKey", nil)),
			*newConstructor("fromFieldPath",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("fieldPath", "mixin.valueFrom.fieldRef.withFieldPath", nil)),
		},
		makeDescriptor("api", "core", "EventList"): objectList,
		makeDescriptor("api", "core", "KeyToPath"): []constructor{
			*newConstructor("new",
				*newConstructorParam("key", "withKey", nil),
				*newConstructorParam("path", "withPath", nil)),
		},
		makeDescriptor("api", "core", "LimitRangeList"): objectList,
		makeDescriptor("api", "core", "Namespace"): []constructor{
			*newConstructor("new",
				*newConstructorParam("name", "withName", nil)),
		},
		makeDescriptor("api", "core", "NamespaceList"):             objectList,
		makeDescriptor("api", "core", "NodeList"):                  objectList,
		makeDescriptor("api", "core", "PersistentVolumeClaimList"): objectList,
		makeDescriptor("api", "core", "PersistentVolumeList"):      objectList,
		makeDescriptor("api", "core", "PodList"):                   objectList,
		makeDescriptor("api", "core", "PodTemplateList"):           objectList,
		makeDescriptor("api", "core", "ReplicationControllerList"): objectList,
		makeDescriptor("api", "core", "ResourceQuotaList"):         objectList,
		makeDescriptor("api", "core", "Secret"): []constructor{
			*newConstructor("new",
				*newConstructorParam("name", "mixin.metadata.withName", nil),
				*newConstructorParam("data", "withData", nil),
				*newConstructorParam("type", "withType", "Opaque")),
			*newConstructor("new",
				*newConstructorParam("name", "mixin.metadata.withName", nil),
				*newConstructorParam("stringDate", "withStringData", nil),
				*newConstructorParam("type", "withType", "Opaque")),
		},
		makeDescriptor("api", "core", "SecretList"): objectList,
		makeDescriptor("api", "core", "Service"): []constructor{
			*newConstructor("new",
				*newConstructorParam("name", "mixin.metadata.withName", nil),
				*newConstructorParam("selector", "mixin.spec.withSelector", nil),
				*newConstructorParam("ports", "mixin.spec.withPorts", nil)),
		},
		makeDescriptor("api", "core", "ServiceAccount"): []constructor{
			*newConstructor("new",
				*newConstructorParam("name", "mixin.metadata.withName", nil)),
		},
		makeDescriptor("api", "core", "ServiceAccountList"): objectList,
		makeDescriptor("api", "core", "ServiceList"):        objectList,
		makeDescriptor("api", "core", "ServicePort"): []constructor{
			*newConstructor("new",
				*newConstructorParam("port", "withPort", nil),
				*newConstructorParam("targetPort", "withTargetPort", nil)),
			*newConstructor("newNamed",
				*newConstructorParam("name", "mixin.metadata.withName", nil),
				*newConstructorParam("port", "withPort", nil),
				*newConstructorParam("targetPort", "withTargetPort", nil)),
		},
		makeDescriptor("api", "core", "Volume"): []constructor{
			*newConstructor(
				"fromConfigMap",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("configMapName", "mixin.configMap.withName", nil),
				*newConstructorParam("configMapItems", "mixin.configMap.withItems", nil)),
			*newConstructor("fromEmptyDir",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("emptyDir", "mixin.emptyDir.mixinInstance",
					map[string]interface{}{})),
			*newConstructor("fromPersistentVolumeClaim",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("emptyDir", "mixin.persistentVolumeClaim.withClaimName", nil)),
			*newConstructor("fromHostPath",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("hostPath", "mixin.hostPath.withPath", nil)),
			*newConstructor("fromSecret",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("secretName", "mixin.secret.withSecretName", nil)),
		},
		makeDescriptor("api", "core", "VolumeMount"): []constructor{
			*newConstructor("new",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("mountPath", "withMountPath", nil),
				*newConstructorParam("readOnly", "withReadOnly", false)),
		},
	}

	// customConstructor definitions

	deploymentCtor = []constructor{
		*newConstructor(
			"new",
			*newConstructorParam("name", "mixin.metadata.withName", nil),
			*newConstructorParam("replicas", "mixin.spec.withReplicas", 1),
			*newConstructorParam("containers", "mixin.spec.template.spec.withContainers", nil),
			*newConstructorParam("podLabels", "mixin.spec.template.metadata.withLabels",
				map[string]interface{}{"app": "name"}),
		),
	}
	deploymentRollbackCtor = []constructor{
		*newConstructor(
			"new",
			*newConstructorParam("name", "withName", nil),
		),
	}
	objectList = []constructor{
		*newConstructor(
			"new",
			*newConstructorParam("items", "withItems", nil),
		),
	}
	scaleCtor = []constructor{
		*newConstructor(
			"new",
			*newConstructorParam("replicas", "mixin.spec.withReplicas", 1),
		),
	}
	statefulSetCtor = []constructor{
		*newConstructor(
			"new",
			*newConstructorParam("name", "mixin.metadata.withName", nil),
			*newConstructorParam("replicas", "mixin.spec.withReplicas", 1),
			*newConstructorParam("containers", "mixin.spec.template.spec.withContainers", nil),
			*newConstructorParam("volumeClaims", "mixin.spec.withVolumeClaimTemplates", nil),
			*newConstructorParam("podLabels", "mixin.spec.template.metadata.withLabels", map[string]interface{}{
				"app": "name",
			}),
		),
	}
	tokenReviewCtor = []constructor{
		*newConstructor(
			"new",
			*newConstructorParam("token", "mixin.spec.withToken", nil),
		),
	}
)
<commit_msg>add data parameter to configMap<commit_after>package ksonnet

// NOTE: custom constructors will be removed at ksonnet 0.11

func locateConstructors(desc Description) []constructor {
	ctors, ok := customConstructors[desc]
	if !ok {
		return nil
	}

	return ctors
}

func makeDescriptor(codebase, group, kind string) Description {
	return Description{
		Codebase: codebase,
		Group:    group,
		Kind:     kind,
	}
}

var (
	customConstructors = map[Description][]constructor{
		makeDescriptor("api", "apps", "Deployment"):         deploymentCtor,
		makeDescriptor("api", "apps", "DeploymentList"):     objectList,
		makeDescriptor("api", "apps", "DeploymentRollback"): deploymentRollbackCtor,
		makeDescriptor("api", "apps", "Scale"):              scaleCtor,
		makeDescriptor("api", "apps", "StatefulSet"):        statefulSetCtor,
		makeDescriptor("api", "apps", "StatefulSetList"):    objectList,

		makeDescriptor("api", "extensions", "Deployment"):         deploymentCtor,
		makeDescriptor("api", "extensions", "DeploymentList"):     objectList,
		makeDescriptor("api", "extensions", "DeploymentRollback"): deploymentRollbackCtor,
		makeDescriptor("api", "extensions", "Scale"):              scaleCtor,
		makeDescriptor("api", "extensions", "StatefulSet"):        statefulSetCtor,
		makeDescriptor("api", "extensions", "StatefulSetList"):    objectList,

		makeDescriptor("api", "authentication", "TokenReview"): []constructor{
			*newConstructor(
				"new",
				*newConstructorParam("token", "mixin.spec.withToken", nil),
			),
		},

		makeDescriptor("api", "autoscaling", "HorizontalPodAutoscalerList"): objectList,
		makeDescriptor("api", "autoscaling", "Scale"):                       scaleCtor,

		makeDescriptor("api", "batch", "JobList"):     objectList,
		makeDescriptor("api", "batch", "CronJobList"): objectList,

		makeDescriptor("api", "certificates", "CertificateSigningRequestList"): objectList,

		makeDescriptor("api", "core", "ConfigMap"): []constructor{
			*newConstructor(
				"new",
				*newConstructorParam("name", "mixin.metadata.withName", nil),
				*newConstructorParam("data", "withData", nil),
			),
		},
		makeDescriptor("api", "core", "ConfigMapList"): objectList,
		makeDescriptor("api", "core", "Container"): []constructor{
			*newConstructor(
				"new",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("image", "withImage", nil),
			),
		},
		makeDescriptor("api", "core", "ContainerPort"): []constructor{
			*newConstructor("new", *newConstructorParam("containerPort", "withContainerPort", nil)),
			*newConstructor("newNamed",
				*newConstructorParam("containerPort", "withContainerPort", nil),
				*newConstructorParam("name", "withName", nil),
			),
		},
		makeDescriptor("api", "core", "EndpointsList"): objectList,
		makeDescriptor("api", "core", "EnvVar"): []constructor{
			*newConstructor("new",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("value", "withValue", nil)),
			*newConstructor("fromSecretRef",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("secretRefName", "mixin.valueFrom.secretKeyRef.withName", nil),
				*newConstructorParam("secretRefKey", "mixin.valueFrom.secretKeyRef.withKey", nil)),
			*newConstructor("fromFieldPath",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("fieldPath", "mixin.valueFrom.fieldRef.withFieldPath", nil)),
		},
		makeDescriptor("api", "core", "EventList"): objectList,
		makeDescriptor("api", "core", "KeyToPath"): []constructor{
			*newConstructor("new",
				*newConstructorParam("key", "withKey", nil),
				*newConstructorParam("path", "withPath", nil)),
		},
		makeDescriptor("api", "core", "LimitRangeList"): objectList,
		makeDescriptor("api", "core", "Namespace"): []constructor{
			*newConstructor("new",
				*newConstructorParam("name", "withName", nil)),
		},
		makeDescriptor("api", "core", "NamespaceList"):             objectList,
		makeDescriptor("api", "core", "NodeList"):                  objectList,
		makeDescriptor("api", "core", "PersistentVolumeClaimList"): objectList,
		makeDescriptor("api", "core", "PersistentVolumeList"):      objectList,
		makeDescriptor("api", "core", "PodList"):                   objectList,
		makeDescriptor("api", "core", "PodTemplateList"):           objectList,
		makeDescriptor("api", "core", "ReplicationControllerList"): objectList,
		makeDescriptor("api", "core", "ResourceQuotaList"):         objectList,
		makeDescriptor("api", "core", "Secret"): []constructor{
			*newConstructor("new",
				*newConstructorParam("name", "mixin.metadata.withName", nil),
				*newConstructorParam("data", "withData", nil),
				*newConstructorParam("type", "withType", "Opaque")),
			*newConstructor("new",
				*newConstructorParam("name", "mixin.metadata.withName", nil),
				*newConstructorParam("stringDate", "withStringData", nil),
				*newConstructorParam("type", "withType", "Opaque")),
		},
		makeDescriptor("api", "core", "SecretList"): objectList,
		makeDescriptor("api", "core", "Service"): []constructor{
			*newConstructor("new",
				*newConstructorParam("name", "mixin.metadata.withName", nil),
				*newConstructorParam("selector", "mixin.spec.withSelector", nil),
				*newConstructorParam("ports", "mixin.spec.withPorts", nil)),
		},
		makeDescriptor("api", "core", "ServiceAccount"): []constructor{
			*newConstructor("new",
				*newConstructorParam("name", "mixin.metadata.withName", nil)),
		},
		makeDescriptor("api", "core", "ServiceAccountList"): objectList,
		makeDescriptor("api", "core", "ServiceList"):        objectList,
		makeDescriptor("api", "core", "ServicePort"): []constructor{
			*newConstructor("new",
				*newConstructorParam("port", "withPort", nil),
				*newConstructorParam("targetPort", "withTargetPort", nil)),
			*newConstructor("newNamed",
				*newConstructorParam("name", "mixin.metadata.withName", nil),
				*newConstructorParam("port", "withPort", nil),
				*newConstructorParam("targetPort", "withTargetPort", nil)),
		},
		makeDescriptor("api", "core", "Volume"): []constructor{
			*newConstructor(
				"fromConfigMap",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("configMapName", "mixin.configMap.withName", nil),
				*newConstructorParam("configMapItems", "mixin.configMap.withItems", nil)),
			*newConstructor("fromEmptyDir",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("emptyDir", "mixin.emptyDir.mixinInstance",
					map[string]interface{}{})),
			*newConstructor("fromPersistentVolumeClaim",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("emptyDir", "mixin.persistentVolumeClaim.withClaimName", nil)),
			*newConstructor("fromHostPath",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("hostPath", "mixin.hostPath.withPath", nil)),
			*newConstructor("fromSecret",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("secretName", "mixin.secret.withSecretName", nil)),
		},
		makeDescriptor("api", "core", "VolumeMount"): []constructor{
			*newConstructor("new",
				*newConstructorParam("name", "withName", nil),
				*newConstructorParam("mountPath", "withMountPath", nil),
				*newConstructorParam("readOnly", "withReadOnly", false)),
		},
	}

	// customConstructor definitions

	deploymentCtor = []constructor{
		*newConstructor(
			"new",
			*newConstructorParam("name", "mixin.metadata.withName", nil),
			*newConstructorParam("replicas", "mixin.spec.withReplicas", 1),
			*newConstructorParam("containers", "mixin.spec.template.spec.withContainers", nil),
			*newConstructorParam("podLabels", "mixin.spec.template.metadata.withLabels",
				map[string]interface{}{"app": "name"}),
		),
	}
	deploymentRollbackCtor = []constructor{
		*newConstructor(
			"new",
			*newConstructorParam("name", "withName", nil),
		),
	}
	objectList = []constructor{
		*newConstructor(
			"new",
			*newConstructorParam("items", "withItems", nil),
		),
	}
	scaleCtor = []constructor{
		*newConstructor(
			"new",
			*newConstructorParam("replicas", "mixin.spec.withReplicas", 1),
		),
	}
	statefulSetCtor = []constructor{
		*newConstructor(
			"new",
			*newConstructorParam("name", "mixin.metadata.withName", nil),
			*newConstructorParam("replicas", "mixin.spec.withReplicas", 1),
			*newConstructorParam("containers", "mixin.spec.template.spec.withContainers", nil),
			*newConstructorParam("volumeClaims", "mixin.spec.withVolumeClaimTemplates", nil),
			*newConstructorParam("podLabels", "mixin.spec.template.metadata.withLabels", map[string]interface{}{
				"app": "name",
			}),
		),
	}
	tokenReviewCtor = []constructor{
		*newConstructor(
			"new",
			*newConstructorParam("token", "mixin.spec.withToken", nil),
		),
	}
)
<|endoftext|>


<commit_before>package db

import (
	"database/sql"

	"github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

// SQLDB is a sql database repository implementing the DB interface.
type SQLDB struct {
	sqlx *sqlx.DB
}

// Ensure SQLDB implements DB.
var _ DB = (*SQLDB)(nil)

// NewSQLDB returns an SQLDB.
func NewSQLDB(sqlDB *sql.DB, driverName string) (*SQLDB, error) {
	db := &SQLDB{
		sqlx: sqlx.NewDb(sqlDB, driverName),
	}
	if err := db.sqlx.Ping(); err != nil {
		return nil, err
	}
	return db, nil
}

// AddGHInstallation implements the DB interface.
func (db *SQLDB) AddGHInstallation(installationID, accountID, senderID int) error {
	// INSERT IGNORE so any duplicates are ignored
	_, err := db.sqlx.Exec("INSERT IGNORE INTO gh_installations (installation_id, account_id, sender_id) VALUES (?, ?, ?)",
		installationID, accountID, senderID,
	)
	return err
}

// RemoveGHInstallation implements the DB interface.
func (db *SQLDB) RemoveGHInstallation(installationID int) error {
	_, err := db.sqlx.Exec("DELETE FROM gh_installations WHERE installation_id = ?", installationID)
	return err
}

// GetGHInstallation implements the DB interface.
func (db *SQLDB) GetGHInstallation(installationID int) (*GHInstallation, error) {
	var row struct {
		ID             int            `db:"id"`
		InstallationID int            `db:"installation_id"`
		AccountID      int            `db:"account_id"`
		SenderID       int            `db:"sender_id"`
		EnabledAt      mysql.NullTime `db:"enabled_at"`
	}
	err := db.sqlx.Get(&row, "SELECT id, installation_id, account_id, sender_id, enabled_at FROM gh_installations WHERE installation_id = ?", installationID)
	switch {
	case err == sql.ErrNoRows:
		return nil, nil
	case err != nil:
		return nil, err
	}
	ghi := &GHInstallation{
		ID:             row.ID,
		InstallationID: row.InstallationID,
		AccountID:      row.AccountID,
		SenderID:       row.SenderID,
	}
	if row.EnabledAt.Valid {
		ghi.enabledAt = row.EnabledAt.Time
	}
	return ghi, nil
}

// ListTools implements the DB interface.
func (db *SQLDB) ListTools() ([]Tool, error) {
	var tools []Tool
	err := db.sqlx.Select(&tools, "SELECT id, name, path, args, `regexp` FROM tools")
	return tools, err
}

// StartAnalysis implements the DB interface.
func (db *SQLDB) StartAnalysis(ghInstallationID, repositoryID int) (*Analysis, error) {
	analysis := NewAnalysis()
	result, err := db.sqlx.Exec("INSERT INTO analysis (gh_installation_id, repository_id) VALUES (?, ?)", ghInstallationID, repositoryID)
	if err != nil {
		return nil, err
	}
	analysisID, err := result.LastInsertId()
	analysis.ID = int(analysisID)
	return analysis, err
}

// FinishAnalysis implements the DB interface.
func (db *SQLDB) FinishAnalysis(analysisID int, status AnalysisStatus, analysis *Analysis) error {
	if analysis == nil {
		_, err := db.sqlx.Exec("UPDATE analysis SET status = ? WHERE id = ?", string(status), analysisID)
		return err
	}
	_, err := db.sqlx.Exec("UPDATE analysis SET status = ?, clone_duration = SEC_TO_TIME(?), deps_duration = SEC_TO_TIME(?), total_duration = SEC_TO_TIME(?) WHERE id = ?",
		string(status), analysis.CloneDuration, analysis.DepsDuration, analysis.TotalDuration, analysisID,
	)
	if err != nil {
		return err
	}
	for toolID, tool := range analysis.Tools {
		toolResult, err := db.sqlx.Exec("INSERT INTO analysis_tool (analysis_id, tool_id, SEC_TO_TIME(duration)) VALUES (?, ?, ?)", analysisID, toolID, tool.Duration)
		if err != nil {
			return err
		}

		toolAnalysisID, err := toolResult.LastInsertId()
		if err != nil {
			return err
		}

		for _, issue := range tool.Issues {
			_, err := db.sqlx.Exec("INSERT INTO issues (analysis_tool_id, path, line, hunk_pos, issue) VALUES(?, ?, ?, ?, ?)",
				toolAnalysisID, issue.Path, issue.Line, issue.HunkPos, issue.Issue,
			)
			if err != nil {
				return err
			}
		}

	}
	return nil
}

// GetAnalysis implements the DB interface.
func (db *SQLDB) GetAnalysis(analysisID int) (*Analysis, error) {
	analysis := NewAnalysis()

	err := db.sqlx.Get(analysis, `
SELECT id, gh_installation_id, repository_id, status, clone_duration, deps_duration, total_duration, created_at
FROM analysis WHERE id = ?`, analysisID)
	if err != nil {
		return nil, err
	}
	if analysis == nil {
		return nil, nil
	}

	var toolIssues []struct {
		ToolID   int            `db:"tool_id"`
		Name     string         `db:"name"`
		URL      string         `db:"url"`
		Duration Duration       `db:"duration"`
		Path     sql.NullString `db:"path"`
		Line     sql.NullInt64  `db:"line"`
		HunkPos  sql.NullInt64  `db:"hunk_pos"`
		Issue    sql.NullString `db:"issue"`
	}

	// get all the tools and issues if they have them
	err = db.sqlx.Select(&toolIssues, `
   SELECT at.tool_id, at.duration, i.path, i.line, i.hunk_pos, i.issue,
		  t.name, t.url
     FROM analysis_tool at
	 JOIN tools t ON (at.tool_id = t.id)
LEFT JOIN issues i ON (i.analysis_tool_id = at.id)
    WHERE at.analysis_id = ?`,
		analysisID,
	)
	if err != nil {
		return nil, err
	}

	for _, issue := range toolIssues {
		toolID := ToolID(issue.ToolID)
		if _, ok := analysis.Tools[toolID]; !ok {
			analysis.Tools[toolID] = AnalysisTool{
				Tool:     &Tool{ID: toolID, Name: issue.Name, URL: issue.URL},
				ToolID:   toolID,
				Duration: issue.Duration,
			}
		}

		if issue.Issue.Valid {
			at := analysis.Tools[toolID]
			at.Issues = append(at.Issues, Issue{
				Path:    issue.Path.String,
				Line:    int(issue.Line.Int64),
				HunkPos: int(issue.HunkPos.Int64),
				Issue:   issue.Issue.String,
			})
			analysis.Tools[toolID] = at
		}
	}

	return analysis, nil
}
<commit_msg>Bug fix prod vs dev sql differences<commit_after>package db

import (
	"database/sql"

	"github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

// SQLDB is a sql database repository implementing the DB interface.
type SQLDB struct {
	sqlx *sqlx.DB
}

// Ensure SQLDB implements DB.
var _ DB = (*SQLDB)(nil)

// NewSQLDB returns an SQLDB.
func NewSQLDB(sqlDB *sql.DB, driverName string) (*SQLDB, error) {
	db := &SQLDB{
		sqlx: sqlx.NewDb(sqlDB, driverName),
	}
	if err := db.sqlx.Ping(); err != nil {
		return nil, err
	}
	return db, nil
}

// AddGHInstallation implements the DB interface.
func (db *SQLDB) AddGHInstallation(installationID, accountID, senderID int) error {
	// INSERT IGNORE so any duplicates are ignored
	_, err := db.sqlx.Exec("INSERT IGNORE INTO gh_installations (installation_id, account_id, sender_id) VALUES (?, ?, ?)",
		installationID, accountID, senderID,
	)
	return err
}

// RemoveGHInstallation implements the DB interface.
func (db *SQLDB) RemoveGHInstallation(installationID int) error {
	_, err := db.sqlx.Exec("DELETE FROM gh_installations WHERE installation_id = ?", installationID)
	return err
}

// GetGHInstallation implements the DB interface.
func (db *SQLDB) GetGHInstallation(installationID int) (*GHInstallation, error) {
	var row struct {
		ID             int            `db:"id"`
		InstallationID int            `db:"installation_id"`
		AccountID      int            `db:"account_id"`
		SenderID       int            `db:"sender_id"`
		EnabledAt      mysql.NullTime `db:"enabled_at"`
	}
	err := db.sqlx.Get(&row, "SELECT id, installation_id, account_id, sender_id, enabled_at FROM gh_installations WHERE installation_id = ?", installationID)
	switch {
	case err == sql.ErrNoRows:
		return nil, nil
	case err != nil:
		return nil, err
	}
	ghi := &GHInstallation{
		ID:             row.ID,
		InstallationID: row.InstallationID,
		AccountID:      row.AccountID,
		SenderID:       row.SenderID,
	}
	if row.EnabledAt.Valid {
		ghi.enabledAt = row.EnabledAt.Time
	}
	return ghi, nil
}

// ListTools implements the DB interface.
func (db *SQLDB) ListTools() ([]Tool, error) {
	var tools []Tool
	err := db.sqlx.Select(&tools, "SELECT id, name, path, args, `regexp` FROM tools")
	return tools, err
}

// StartAnalysis implements the DB interface.
func (db *SQLDB) StartAnalysis(ghInstallationID, repositoryID int) (*Analysis, error) {
	analysis := NewAnalysis()
	result, err := db.sqlx.Exec("INSERT INTO analysis (gh_installation_id, repository_id) VALUES (?, ?)", ghInstallationID, repositoryID)
	if err != nil {
		return nil, err
	}
	analysisID, err := result.LastInsertId()
	analysis.ID = int(analysisID)
	return analysis, err
}

// FinishAnalysis implements the DB interface.
func (db *SQLDB) FinishAnalysis(analysisID int, status AnalysisStatus, analysis *Analysis) error {
	if analysis == nil {
		_, err := db.sqlx.Exec("UPDATE analysis SET status = ? WHERE id = ?", string(status), analysisID)
		return err
	}
	_, err := db.sqlx.Exec("UPDATE analysis SET status = ?, clone_duration = SEC_TO_TIME(?), deps_duration = SEC_TO_TIME(?), total_duration = SEC_TO_TIME(?) WHERE id = ?",
		string(status), analysis.CloneDuration, analysis.DepsDuration, analysis.TotalDuration, analysisID,
	)
	if err != nil {
		return err
	}
	for toolID, tool := range analysis.Tools {
		toolResult, err := db.sqlx.Exec("INSERT INTO analysis_tool (analysis_id, tool_id, duration) VALUES (?, ?, SEC_TO_TIME(?))", analysisID, toolID, tool.Duration)
		if err != nil {
			return err
		}

		toolAnalysisID, err := toolResult.LastInsertId()
		if err != nil {
			return err
		}

		for _, issue := range tool.Issues {
			_, err := db.sqlx.Exec("INSERT INTO issues (analysis_tool_id, path, line, hunk_pos, issue) VALUES(?, ?, ?, ?, ?)",
				toolAnalysisID, issue.Path, issue.Line, issue.HunkPos, issue.Issue,
			)
			if err != nil {
				return err
			}
		}

	}
	return nil
}

// GetAnalysis implements the DB interface.
func (db *SQLDB) GetAnalysis(analysisID int) (*Analysis, error) {
	analysis := NewAnalysis()

	err := db.sqlx.Get(analysis, `
SELECT id, gh_installation_id, repository_id, status, clone_duration, deps_duration, total_duration, created_at
FROM analysis WHERE id = ?`, analysisID)
	if err != nil {
		return nil, err
	}
	if analysis == nil {
		return nil, nil
	}

	var toolIssues []struct {
		ToolID   int            `db:"tool_id"`
		Name     string         `db:"name"`
		URL      string         `db:"url"`
		Duration Duration       `db:"duration"`
		Path     sql.NullString `db:"path"`
		Line     sql.NullInt64  `db:"line"`
		HunkPos  sql.NullInt64  `db:"hunk_pos"`
		Issue    sql.NullString `db:"issue"`
	}

	// get all the tools and issues if they have them
	err = db.sqlx.Select(&toolIssues, `
   SELECT at.tool_id, at.duration, i.path, i.line, i.hunk_pos, i.issue,
		  t.name, t.url
     FROM analysis_tool at
	 JOIN tools t ON (at.tool_id = t.id)
LEFT JOIN issues i ON (i.analysis_tool_id = at.id)
    WHERE at.analysis_id = ?`,
		analysisID,
	)
	if err != nil {
		return nil, err
	}

	for _, issue := range toolIssues {
		toolID := ToolID(issue.ToolID)
		if _, ok := analysis.Tools[toolID]; !ok {
			analysis.Tools[toolID] = AnalysisTool{
				Tool:     &Tool{ID: toolID, Name: issue.Name, URL: issue.URL},
				ToolID:   toolID,
				Duration: issue.Duration,
			}
		}

		if issue.Issue.Valid {
			at := analysis.Tools[toolID]
			at.Issues = append(at.Issues, Issue{
				Path:    issue.Path.String,
				Line:    int(issue.Line.Int64),
				HunkPos: int(issue.HunkPos.Int64),
				Issue:   issue.Issue.String,
			})
			analysis.Tools[toolID] = at
		}
	}

	return analysis, nil
}
<|endoftext|>


<commit_before>package v4

import (
	"net/http"
	"net/http/pprof"
	runtimepprof "runtime/pprof"
	"strings"
	"text/template"

	"github.com/juju/charmstore/internal/router"
)

type pprofHandler struct {
	mux  *http.ServeMux
	auth authenticator
}

type authenticator interface {
	authenticate(w http.ResponseWriter, req *http.Request) error
}

func newPprofHandler(auth authenticator) http.Handler {
	mux := http.NewServeMux()
	mux.HandleFunc("/cmdline", pprof.Cmdline)
	mux.HandleFunc("/profile", pprof.Profile)
	mux.HandleFunc("/symbol", pprof.Symbol)
	mux.HandleFunc("/", pprofIndex)
	return &pprofHandler{
		mux:  mux,
		auth: auth,
	}
}

func (h *pprofHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if err := h.auth.authenticate(w, req); err != nil {
		router.WriteError(w, err)
		return
	}
	h.mux.ServeHTTP(w, req)
}

// pprofIndex is copied from pprof.Index with minor modifications
// to make it work using a relative path.
func pprofIndex(w http.ResponseWriter, req *http.Request) {
	if req.URL.Path == "/" {
		profiles := runtimepprof.Profiles()
		if err := indexTmpl.Execute(w, profiles); err != nil {
			logger.Errorf("cannot execute pprof template: %v", err)
		}
		return
	}
	name := strings.TrimPrefix(req.URL.Path, "/")
	pprof.Handler(name).ServeHTTP(w, req)
}

var indexTmpl = template.Must(template.New("index").Parse(`

<title>pprof</title>

pprof

profiles:

{{range .}}

{{.Count}}{{.Name}}
{{end}}

full goroutine stack dump

`))
<commit_msg>Fix pprof generated index html.<commit_after>package v4

import (
	"net/http"
	"net/http/pprof"
	runtimepprof "runtime/pprof"
	"strings"
	"text/template"

	"github.com/juju/charmstore/internal/router"
)

type pprofHandler struct {
	mux  *http.ServeMux
	auth authenticator
}

type authenticator interface {
	authenticate(w http.ResponseWriter, req *http.Request) error
}

func newPprofHandler(auth authenticator) http.Handler {
	mux := http.NewServeMux()
	mux.HandleFunc("/cmdline", pprof.Cmdline)
	mux.HandleFunc("/profile", pprof.Profile)
	mux.HandleFunc("/symbol", pprof.Symbol)
	mux.HandleFunc("/", pprofIndex)
	return &pprofHandler{
		mux:  mux,
		auth: auth,
	}
}

func (h *pprofHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	if err := h.auth.authenticate(w, req); err != nil {
		router.WriteError(w, err)
		return
	}
	h.mux.ServeHTTP(w, req)
}

// pprofIndex is copied from pprof.Index with minor modifications
// to make it work using a relative path.
func pprofIndex(w http.ResponseWriter, req *http.Request) {
	if req.URL.Path == "/" {
		profiles := runtimepprof.Profiles()
		if err := indexTmpl.Execute(w, profiles); err != nil {
			logger.Errorf("cannot execute pprof template: %v", err)
		}
		return
	}
	name := strings.TrimPrefix(req.URL.Path, "/")
	pprof.Handler(name).ServeHTTP(w, req)
}

var indexTmpl = template.Must(template.New("index").Parse(`<!DOCTYPE html>

  <title>pprof</title>

pprof

profiles:

    {{range .}}

      {{.Count}}
      {{.Name}}

    {{end}}

full goroutine stack dump

`))
<|endoftext|>


<commit_before>// Copyright © 2016 NAME HERE <EMAIL ADDRESS>
//
// 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 cmd

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"github.com/tylerharter/open-lambda/lambda-generator/experimental/frontends"
	"github.com/tylerharter/open-lambda/lambda-generator/experimental/frontends/effe"
)

var (
	cfgFile     string
	frontendStr string
	fe          frontends.FrontEnd
)

// This represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "experimental",
	Short: "A brief description of your application",
	Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	// Uncomment the following line if your bare application
	// has an action associated with it:
	//	Run: func(cmd *cobra.Command, args []string) { },
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	cobra.OnInitialize(initConfig)

	// Here you will define your flags and configuration settings.
	// Cobra supports Persistent Flags, which, if defined here,
	// will be global for your application.

	RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.experimental.yaml)")
	RootCmd.PersistentFlags().StringVar(&frontendStr, "frontend", "effe", "OpenLambda frontend framework (default is effe)")
	// Cobra also supports local flags, which will only run
	// when this action is called directly.
	RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")

	// find the .openlambda folder or warn user if not found
	olDir := findOlDir()
	if olDir == "" {
		fmt.Printf("WARNING: no .openlambda directory found (Have you called %s init yet?)\n\n", os.Args[0])
		return
	}
	fmt.Printf("using .openlambda at %s\n", olDir)

	// Here we select the frontend, based on user configs found from above
	switch frontendStr {
	case "effe":
		fe = effe.NewFrontEnd(olDir)
	default:
		fmt.Println("frontend %s is unsupported\n")
		os.Exit(1)
	}
}

func findOlDir() string {
	wd, err := os.Getwd()
	if err != nil {
		fmt.Printf("failed to get wd with err %v\n", err)
		os.Exit(1)
	}

	curr, err := filepath.Abs(wd)
	if err != nil {
		fmt.Printf("failed to get create abs path with err %v\n", err)
		os.Exit(1)
	}

	// Walk one dir up each loop
	// TODO "/" is ommitted. Do we want this?
	for ; curr != "/"; curr = filepath.Dir(curr) {
		dir := filepath.Join(curr, ".openlambda")
		info, err := os.Stat(dir)
		if err != nil {
			if !os.IsNotExist(err) {
				fmt.Printf("failed to get info on %s with err %v\n", dir, err)
				os.Exit(1)
			}
			continue
		}
		if !info.IsDir() {
			fmt.Printf("warning: non-directory .openlambda at %s\n", dir)
			continue
		}
		// found dir
		return dir
	}
	// caller will log
	return ""
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	if cfgFile != "" { // enable ability to specify config file via flag
		viper.SetConfigFile(cfgFile)
	}

	viper.SetConfigName(".experimental") // name of config file (without extension)
	viper.AddConfigPath("$HOME")         // adding home directory as first search path
	viper.AutomaticEnv()                 // read in environment variables that match

	// If a config file is found, read it in.
	if err := viper.ReadInConfig(); err == nil {
		fmt.Println("Using config file:", viper.ConfigFileUsed())
	}
}
<commit_msg>Experimental Lambda Generator: sane root descriptions<commit_after>// Copyright © 2016 NAME HERE <EMAIL ADDRESS>
//
// 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 cmd

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"github.com/tylerharter/open-lambda/lambda-generator/experimental/frontends"
	"github.com/tylerharter/open-lambda/lambda-generator/experimental/frontends/effe"
)

var (
	cfgFile     string
	frontendStr string
	fe          frontends.FrontEnd
)

// This represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   fmt.Sprintf("%s", os.Args[0]),
	Short: "Helps to template, organize, build and deploy OpenLambda Lambdas",
	Long:  "Helps to template, organize, build and deploy OpenLambda Lambdas",
	// Uncomment the following line if your bare application
	// has an action associated with it:
	//	Run: func(cmd *cobra.Command, args []string) { },
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	cobra.OnInitialize(initConfig)

	// Here you will define your flags and configuration settings.
	// Cobra supports Persistent Flags, which, if defined here,
	// will be global for your application.

	RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.experimental.yaml)")
	RootCmd.PersistentFlags().StringVar(&frontendStr, "frontend", "effe", "OpenLambda frontend framework (default is effe)")
	// Cobra also supports local flags, which will only run
	// when this action is called directly.
	RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")

	// find the .openlambda folder or warn user if not found
	olDir := findOlDir()
	if olDir == "" {
		fmt.Printf("WARNING: no .openlambda directory found (Have you called %s init yet?)\n\n", os.Args[0])
		return
	}

	// Here we select the frontend, based on user configs found from above
	switch frontendStr {
	case "effe":
		fe = effe.NewFrontEnd(olDir)
	default:
		fmt.Println("frontend %s is unsupported\n")
		os.Exit(1)
	}
}

func findOlDir() string {
	wd, err := os.Getwd()
	if err != nil {
		fmt.Printf("failed to get wd with err %v\n", err)
		os.Exit(1)
	}

	curr, err := filepath.Abs(wd)
	if err != nil {
		fmt.Printf("failed to get create abs path with err %v\n", err)
		os.Exit(1)
	}

	// Walk one dir up each loop
	// TODO "/" is ommitted. Do we want this?
	for ; curr != "/"; curr = filepath.Dir(curr) {
		dir := filepath.Join(curr, ".openlambda")
		info, err := os.Stat(dir)
		if err != nil {
			if !os.IsNotExist(err) {
				fmt.Printf("failed to get info on %s with err %v\n", dir, err)
				os.Exit(1)
			}
			continue
		}
		if !info.IsDir() {
			fmt.Printf("warning: non-directory .openlambda at %s\n", dir)
			continue
		}
		// found dir
		return dir
	}
	// caller will log
	return ""
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	if cfgFile != "" { // enable ability to specify config file via flag
		viper.SetConfigFile(cfgFile)
	}

	viper.SetConfigName(".experimental") // name of config file (without extension)
	viper.AddConfigPath("$HOME")         // adding home directory as first search path
	viper.AutomaticEnv()                 // read in environment variables that match

	// If a config file is found, read it in.
	if err := viper.ReadInConfig(); err == nil {
		fmt.Println("Using config file:", viper.ConfigFileUsed())
	}
}
<|endoftext|>