<commit_before>// Package icmp provides icmp enhanced methods based on the golang icmp package
package icmp

import (
	"errors"
	"fmt"
	"golang.org/x/net/icmp"
	"golang.org/x/net/ipv4"
	"golang.org/x/net/ipv6"
	"log"
	"math/rand"
	"net"
	"os"
	"os/signal"
	"regexp"
	"sync"
	"syscall"
	"time"

	"github.com/mehrdadrad/mylg/cli"
)

// IANA ICMP
const (
	ProtocolIPv4ICMP = 1  // IANA ICMP for IPv4
	ProtocolIPv6ICMP = 58 // IANA ICMP for IPv6
)

// packet represents ping packet
type packet struct {
	bytes []byte
	addr  net.Addr
	err   error
}

// Ping represents ping request
type Ping struct {
	m         icmp.Message
	id        int
	seq       int
	pSize     int
	count     int
	addr      *net.IPAddr
	isV4Avail bool
	isV6Avail bool
	network   string
	source    string
	timeout   time.Duration
	interval  time.Duration
	MaxRTT    time.Duration
	mu        sync.RWMutex
}

// Response represent ping response
type Response struct {
	RTT      float64
	Size     int
	Sequence int
	Addr     string
	Timeout  bool
	Error    error
}

// NewPing creates a new ping object
func NewPing(args string) (*Ping, error) {
	var (
		timeout  time.Duration
		interval time.Duration
		err      error
	)
	target, flag := cli.Flag(args)

	// show help
	if _, ok := flag["help"]; ok || len(target) < 3 {
		help()
		return nil, nil
	}
	// resolve host
	ra, err := net.ResolveIPAddr("ip", target)
	if err != nil {
		return nil, err
	}
	// timeout
	timeoutStr := cli.SetFlag(flag, "t", "2s").(string)
	timeoutStr = NormalizeDuration(timeoutStr)
	if timeout, err = time.ParseDuration(timeoutStr); err != nil {
		return nil, fmt.Errorf("timeout options is not valid")
	}
	// interval
	intervalStr := cli.SetFlag(flag, "i", "1s").(string)
	intervalStr = NormalizeDuration(intervalStr)
	if interval, err = time.ParseDuration(intervalStr); err != nil {
		return nil, fmt.Errorf("interval options is not valid")
	}

	p := Ping{
		id:        rand.Intn(0xffff),
		seq:       -1,
		pSize:     64,
		count:     cli.SetFlag(flag, "c", 4).(int),
		timeout:   timeout,
		interval:  interval,
		isV4Avail: false,
		isV6Avail: false,
		network:   "ip",
		source:    "",
		MaxRTT:    time.Second,
	}

	p.SetIP(ra.String())
	return &p, nil
}

// Run loops the ping and print it out
func (p *Ping) Run() chan Response {
	var r = make(chan Response, 1)
	go func() {
		for n := 0; n < p.count; n++ {
			p.Ping(r)
			time.Sleep(p.interval)
		}
		close(r)
	}()
	return r
}

// IsIPv4 returns true if ip version is v4
func IsIPv4(ip net.IP) bool {
	return len(ip.To4()) == net.IPv4len
}

// IsIPv6 returns true if ip version is v6
func IsIPv6(ip net.IP) bool {
	return len(ip) == net.IPv6len
}

func (p *Ping) parseMessage(m *packet) (*ipv4.Header, *icmp.Message, error) {
	var proto = ProtocolIPv4ICMP
	if p.isV6Avail {
		proto = ProtocolIPv6ICMP
	}
	msg, err := icmp.ParseMessage(proto, m.bytes)
	if err != nil {
		return nil, nil, err
	}
	bytes, _ := msg.Body.Marshal(msg.Type.Protocol())
	h, err := icmp.ParseIPv4Header(bytes)
	return h, msg, err
}

// SetIP set ip address
func (p *Ping) SetIP(ipAddr string) {
	ip := net.ParseIP(ipAddr)
	p.mu.Lock()
	defer p.mu.Unlock()
	p.addr = &net.IPAddr{IP: ip}
	if IsIPv4(ip) {
		p.isV4Avail = true
	} else {
		p.isV6Avail = true
	}
}

// DelIP removes ip adrress
func (p *Ping) DelIP(ipAddr string) {
	//todo
}

// PacketSize set packet size
func (p *Ping) PacketSize(s int) {
	p.pSize = s
}

// listen starts to listen incoming icmp
func (p *Ping) listen(network string) *icmp.PacketConn {
	c, err := icmp.ListenPacket(network, p.source)
	if err != nil {
		log.Fatalf("listen err, %s", err)
	}
	return c
}

// recv reads icmp message
func (p *Ping) recv(conn *icmp.PacketConn, rcvdChan chan<- *packet) {
	var err error
	bytes := make([]byte, 1500)
	conn.SetReadDeadline(time.Now().Add(p.timeout))
	n, dest, err := conn.ReadFrom(bytes)
	if err != nil {
		if neterr, ok := err.(*net.OpError); ok {
			if neterr.Timeout() {
				err = errors.New("Request timeout")
			}
		}
	}

	bytes = bytes[:n]
	select {
	case rcvdChan <- &packet{bytes: bytes, addr: dest, err: err}:
	}
}

func (p *Ping) payload() []byte {
	timeBytes := make([]byte, 8)
	ts := time.Now().UnixNano()
	for i := uint8(0); i < 8; i++ {
		timeBytes[i] = byte((ts >> (i * 8)) & 0xff)
	}
	payload := make([]byte, p.pSize-16)
	payload = append(payload, timeBytes...)
	return payload
}
func (p *Ping) send(conn *icmp.PacketConn) {
	var (
		wg sync.WaitGroup
	)
	var icmpType icmp.Type
	if IsIPv4(p.addr.IP) {
		icmpType = ipv4.ICMPTypeEcho
	} else if IsIPv6(p.addr.IP) {
		icmpType = ipv6.ICMPTypeEchoRequest
	}

	p.seq++
	bytes, err := (&icmp.Message{
		Type: icmpType, Code: 0,
		Body: &icmp.Echo{
			ID:   p.id,
			Seq:  p.seq,
			Data: p.payload(),
		},
	}).Marshal(nil)
	if err != nil {
		println(err)
	}

	wg.Add(1)
	go func(conn *icmp.PacketConn, dest net.Addr, b []byte) {
		defer wg.Done()
		for {
			if _, err := conn.WriteTo(bytes, dest); err != nil {
				println(err)
				if neterr, ok := err.(*net.OpError); ok {
					if neterr.Err == syscall.ENOBUFS {
						continue
					}
				}
			}
			break
		}
	}(conn, p.addr, bytes)

	wg.Wait()
}

// Ping tries to send and receive a packet
func (p *Ping) Ping(out chan Response) {
	var (
		conn     *icmp.PacketConn
		rcvdChan chan *packet = make(chan *packet, 1)
	)

	if p.isV4Avail {
		if conn = p.listen("ip4:icmp"); conn == nil {
			return
		}
		defer conn.Close()
	}

	if p.isV6Avail {
		if conn = p.listen("ip6:ipv6-icmp"); conn == nil {
			return
		}
		defer conn.Close()
	}

	p.send(conn)
	p.recv(conn, rcvdChan)
	rm := <-rcvdChan

	if rm.err != nil {
		out <- Response{Error: rm.err}
		return
	}
	_, m, err := p.parseMessage(rm)
	if err != nil {
		out <- Response{Error: err}
		return
	}

	switch m.Body.(type) {
	case *icmp.TimeExceeded:
		log.Println("time exceeded")
	case *icmp.PacketTooBig:
		log.Println("packet too big")
	case *icmp.DstUnreach:
		log.Println("unreachable")
	case *icmp.Echo:
		rtt := float64(time.Now().UnixNano()-getTimeStamp(rm.bytes)) / 1000000
		out <- Response{
			Size:     len(rm.bytes),
			Addr:     rm.addr.String(),
			RTT:      rtt,
			Sequence: p.seq,
			Error:    nil,
		}
	default:
		log.Println("error")
	}

}

// PrintPretty prints out the result pretty format
func (p *Ping) PrintPretty() {
	var (
		loop  = true
		sigCh = make(chan os.Signal, 1)
		pFmt  = "%d bytes from %s icmp_seq=%d time=%f ms"
		resp  = p.Run()
	)

	// capture interrupt w/ s channel
	signal.Notify(sigCh, os.Interrupt)
	defer signal.Stop(sigCh)

	for loop {
		select {
		case r, ok := <-resp:
			if !ok {
				loop = false
				break
			}
			if r.Error != nil {
				println(r.Error.Error())
				continue
			}
			msg := fmt.Sprintf(pFmt, r.Size, r.Addr, r.Sequence, r.RTT)
			println(msg)
		case <-sigCh:
			loop = false
		}
	}
}

// getTimeStamp
func getTimeStamp(m []byte) int64 {
	var ts int64
	for i := uint(0); i < 8; i++ {
		ts += int64(m[uint(len(m))-8+i]) << (i * 8)
	}
	return ts
}

// NormalizeDuration adds default unit (seconds) as needed
func NormalizeDuration(d string) string {
	if match, _ := regexp.MatchString(`^\d+\.{0,1}\d*$`, d); match {
		return d + "s"
	}
	return d
}

// help represents ping help
func help() {
	fmt.Println(`
    usage:
          ping IP address / domain name
    options:
          -c count       Send 'count' requests (default: 4)
          -t timeout     Specifiy a timeout in format "ms", "s", "m" (default: 2s)
          -i interval    Specifiy a interval in format "ms", "s", "m" (default: 1s)
    Example:
          ping 8.8.8.8
          ping 8.8.8.8 -c 10
          ping mylg.io
	`)
}
<commit_msg>minor change at help<commit_after>// Package icmp provides icmp enhanced methods based on the golang icmp package
package icmp

import (
	"errors"
	"fmt"
	"golang.org/x/net/icmp"
	"golang.org/x/net/ipv4"
	"golang.org/x/net/ipv6"
	"log"
	"math/rand"
	"net"
	"os"
	"os/signal"
	"regexp"
	"sync"
	"syscall"
	"time"

	"github.com/mehrdadrad/mylg/cli"
)

// IANA ICMP
const (
	ProtocolIPv4ICMP = 1  // IANA ICMP for IPv4
	ProtocolIPv6ICMP = 58 // IANA ICMP for IPv6
)

// packet represents ping packet
type packet struct {
	bytes []byte
	addr  net.Addr
	err   error
}

// Ping represents ping request
type Ping struct {
	m         icmp.Message
	id        int
	seq       int
	pSize     int
	count     int
	addr      *net.IPAddr
	isV4Avail bool
	isV6Avail bool
	network   string
	source    string
	timeout   time.Duration
	interval  time.Duration
	MaxRTT    time.Duration
	mu        sync.RWMutex
}

// Response represent ping response
type Response struct {
	RTT      float64
	Size     int
	Sequence int
	Addr     string
	Timeout  bool
	Error    error
}

// NewPing creates a new ping object
func NewPing(args string) (*Ping, error) {
	var (
		timeout  time.Duration
		interval time.Duration
		err      error
	)
	target, flag := cli.Flag(args)

	// show help
	if _, ok := flag["help"]; ok || len(target) < 3 {
		help()
		return nil, nil
	}
	// resolve host
	ra, err := net.ResolveIPAddr("ip", target)
	if err != nil {
		return nil, err
	}
	// timeout
	timeoutStr := cli.SetFlag(flag, "t", "2s").(string)
	timeoutStr = NormalizeDuration(timeoutStr)
	if timeout, err = time.ParseDuration(timeoutStr); err != nil {
		return nil, fmt.Errorf("timeout options is not valid")
	}
	// interval
	intervalStr := cli.SetFlag(flag, "i", "1s").(string)
	intervalStr = NormalizeDuration(intervalStr)
	if interval, err = time.ParseDuration(intervalStr); err != nil {
		return nil, fmt.Errorf("interval options is not valid")
	}

	p := Ping{
		id:        rand.Intn(0xffff),
		seq:       -1,
		pSize:     64,
		count:     cli.SetFlag(flag, "c", 4).(int),
		timeout:   timeout,
		interval:  interval,
		isV4Avail: false,
		isV6Avail: false,
		network:   "ip",
		source:    "",
		MaxRTT:    time.Second,
	}

	p.SetIP(ra.String())
	return &p, nil
}

// Run loops the ping and print it out
func (p *Ping) Run() chan Response {
	var r = make(chan Response, 1)
	go func() {
		for n := 0; n < p.count; n++ {
			p.Ping(r)
			time.Sleep(p.interval)
		}
		close(r)
	}()
	return r
}

// IsIPv4 returns true if ip version is v4
func IsIPv4(ip net.IP) bool {
	return len(ip.To4()) == net.IPv4len
}

// IsIPv6 returns true if ip version is v6
func IsIPv6(ip net.IP) bool {
	return len(ip) == net.IPv6len
}

func (p *Ping) parseMessage(m *packet) (*ipv4.Header, *icmp.Message, error) {
	var proto = ProtocolIPv4ICMP
	if p.isV6Avail {
		proto = ProtocolIPv6ICMP
	}
	msg, err := icmp.ParseMessage(proto, m.bytes)
	if err != nil {
		return nil, nil, err
	}
	bytes, _ := msg.Body.Marshal(msg.Type.Protocol())
	h, err := icmp.ParseIPv4Header(bytes)
	return h, msg, err
}

// SetIP set ip address
func (p *Ping) SetIP(ipAddr string) {
	ip := net.ParseIP(ipAddr)
	p.mu.Lock()
	defer p.mu.Unlock()
	p.addr = &net.IPAddr{IP: ip}
	if IsIPv4(ip) {
		p.isV4Avail = true
	} else {
		p.isV6Avail = true
	}
}

// DelIP removes ip adrress
func (p *Ping) DelIP(ipAddr string) {
	//todo
}

// PacketSize set packet size
func (p *Ping) PacketSize(s int) {
	p.pSize = s
}

// listen starts to listen incoming icmp
func (p *Ping) listen(network string) *icmp.PacketConn {
	c, err := icmp.ListenPacket(network, p.source)
	if err != nil {
		log.Fatalf("listen err, %s", err)
	}
	return c
}

// recv reads icmp message
func (p *Ping) recv(conn *icmp.PacketConn, rcvdChan chan<- *packet) {
	var err error
	bytes := make([]byte, 1500)
	conn.SetReadDeadline(time.Now().Add(p.timeout))
	n, dest, err := conn.ReadFrom(bytes)
	if err != nil {
		if neterr, ok := err.(*net.OpError); ok {
			if neterr.Timeout() {
				err = errors.New("Request timeout")
			}
		}
	}

	bytes = bytes[:n]
	select {
	case rcvdChan <- &packet{bytes: bytes, addr: dest, err: err}:
	}
}

func (p *Ping) payload() []byte {
	timeBytes := make([]byte, 8)
	ts := time.Now().UnixNano()
	for i := uint8(0); i < 8; i++ {
		timeBytes[i] = byte((ts >> (i * 8)) & 0xff)
	}
	payload := make([]byte, p.pSize-16)
	payload = append(payload, timeBytes...)
	return payload
}
func (p *Ping) send(conn *icmp.PacketConn) {
	var (
		wg sync.WaitGroup
	)
	var icmpType icmp.Type
	if IsIPv4(p.addr.IP) {
		icmpType = ipv4.ICMPTypeEcho
	} else if IsIPv6(p.addr.IP) {
		icmpType = ipv6.ICMPTypeEchoRequest
	}

	p.seq++
	bytes, err := (&icmp.Message{
		Type: icmpType, Code: 0,
		Body: &icmp.Echo{
			ID:   p.id,
			Seq:  p.seq,
			Data: p.payload(),
		},
	}).Marshal(nil)
	if err != nil {
		println(err)
	}

	wg.Add(1)
	go func(conn *icmp.PacketConn, dest net.Addr, b []byte) {
		defer wg.Done()
		for {
			if _, err := conn.WriteTo(bytes, dest); err != nil {
				println(err)
				if neterr, ok := err.(*net.OpError); ok {
					if neterr.Err == syscall.ENOBUFS {
						continue
					}
				}
			}
			break
		}
	}(conn, p.addr, bytes)

	wg.Wait()
}

// Ping tries to send and receive a packet
func (p *Ping) Ping(out chan Response) {
	var (
		conn     *icmp.PacketConn
		rcvdChan chan *packet = make(chan *packet, 1)
	)

	if p.isV4Avail {
		if conn = p.listen("ip4:icmp"); conn == nil {
			return
		}
		defer conn.Close()
	}

	if p.isV6Avail {
		if conn = p.listen("ip6:ipv6-icmp"); conn == nil {
			return
		}
		defer conn.Close()
	}

	p.send(conn)
	p.recv(conn, rcvdChan)
	rm := <-rcvdChan

	if rm.err != nil {
		out <- Response{Error: rm.err}
		return
	}
	_, m, err := p.parseMessage(rm)
	if err != nil {
		out <- Response{Error: err}
		return
	}

	switch m.Body.(type) {
	case *icmp.TimeExceeded:
		log.Println("time exceeded")
	case *icmp.PacketTooBig:
		log.Println("packet too big")
	case *icmp.DstUnreach:
		log.Println("unreachable")
	case *icmp.Echo:
		rtt := float64(time.Now().UnixNano()-getTimeStamp(rm.bytes)) / 1000000
		out <- Response{
			Size:     len(rm.bytes),
			Addr:     rm.addr.String(),
			RTT:      rtt,
			Sequence: p.seq,
			Error:    nil,
		}
	default:
		log.Println("error")
	}

}

// PrintPretty prints out the result pretty format
func (p *Ping) PrintPretty() {
	var (
		loop  = true
		sigCh = make(chan os.Signal, 1)
		pFmt  = "%d bytes from %s icmp_seq=%d time=%f ms"
		resp  = p.Run()
	)

	// capture interrupt w/ s channel
	signal.Notify(sigCh, os.Interrupt)
	defer signal.Stop(sigCh)

	for loop {
		select {
		case r, ok := <-resp:
			if !ok {
				loop = false
				break
			}
			if r.Error != nil {
				println(r.Error.Error())
				continue
			}
			msg := fmt.Sprintf(pFmt, r.Size, r.Addr, r.Sequence, r.RTT)
			println(msg)
		case <-sigCh:
			loop = false
		}
	}
}

// getTimeStamp
func getTimeStamp(m []byte) int64 {
	var ts int64
	for i := uint(0); i < 8; i++ {
		ts += int64(m[uint(len(m))-8+i]) << (i * 8)
	}
	return ts
}

// NormalizeDuration adds default unit (seconds) as needed
func NormalizeDuration(d string) string {
	if match, _ := regexp.MatchString(`^\d+\.{0,1}\d*$`, d); match {
		return d + "s"
	}
	return d
}

// help represents ping help
func help() {
	fmt.Println(`
    usage:
          ping IP address / domain name
    options:
          -c count       Send 'count' requests (default: 4)
          -t timeout     Specifiy a timeout in format "ms", "s", "m" (default: 2s)
          -i interval    Wait interval between sending each packet (default: 1s)
    Example:
          ping 8.8.8.8
          ping 8.8.8.8 -c 10
          ping mylg.io
	`)
}
<|endoftext|>


<commit_before>package helper

type Helper interface {
	GetTablesQuery() string
	TruncateTablesCommand(tableNames []string) string
}
<commit_msg>add comment to Helper<commit_after>package helper

// Helper provides a way for the cleaner to find out list of tables to work on,
// also how to perform truncate on them
type Helper interface {
	GetTablesQuery() string
	TruncateTablesCommand(tableNames []string) string
}
<|endoftext|>


<commit_before>package engine

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/proullon/ramsql/engine/log"
	"github.com/proullon/ramsql/engine/parser"
	"github.com/proullon/ramsql/engine/protocol"
)

/*
|-> INSERT
    |-> INTO
        |-> user
            |-> last_name
            |-> first_name
            |-> email
    |-> VALUES
        |-> (
            |-> Roullon
            |-> Pierre
            |-> pierre.roullon@gmail.com
    |-> RETURNING
            |-> email

*/
func insertIntoTableExecutor(e *Engine, insertDecl *parser.Decl, conn protocol.EngineConn) error {
	// Get table and concerned attributes and write lock it
	intoDecl := insertDecl.Decl[0]
	r, attributes, err := getRelation(e, intoDecl)
	if err != nil {
		return err
	}
	r.Lock()
	defer r.Unlock()

	// Check for RETURNING clause
	var returnedID string
	if len(insertDecl.Decl) > 2 {
		for i := range insertDecl.Decl {
			if insertDecl.Decl[i].Token == parser.ReturningToken {
				returningDecl := insertDecl.Decl[i]
				returnedID = returningDecl.Lexeme
				break
			}
		}
	}

	// Create a new tuple with values
	ids := []int64{}
	valuesDecl := insertDecl.Decl[1]
	for _, valueListDecl := range valuesDecl.Decl {
		// TODO handle all inserts atomically
		id, err := insert(r, attributes, valueListDecl.Decl, returnedID)
		if err != nil {
			return err
		}

		ids = append(ids, id)
	}

	// if RETURNING decl is not present
	if returnedID != "" {
		conn.WriteRowHeader([]string{returnedID})
		for _, id := range ids {
			conn.WriteRow([]string{fmt.Sprintf("%v", id)})
		}
		conn.WriteRowEnd()
	} else {
		conn.WriteResult(ids[len(ids)-1], (int64)(len(ids)))
	}
	return nil
}

/*
|-> INTO
    |-> user
        |-> last_name
        |-> first_name
        |-> email
*/
func getRelation(e *Engine, intoDecl *parser.Decl) (*Relation, []*parser.Decl, error) {

	// Decl[0] is the table name
	r := e.relation(intoDecl.Decl[0].Lexeme)
	if r == nil {
		return nil, nil, errors.New("table " + intoDecl.Decl[0].Lexeme + " does not exists")
	}

	for i := range intoDecl.Decl[0].Decl {
		err := attributeExistsInTable(e, intoDecl.Decl[0].Decl[i].Lexeme, intoDecl.Decl[0].Lexeme)
		if err != nil {
			return nil, nil, err
		}
	}

	return r, intoDecl.Decl[0].Decl, nil
}

func insert(r *Relation, attributes []*parser.Decl, values []*parser.Decl, returnedID string) (int64, error) {
	var assigned = false
	var id int64
	var valuesindex int

	// Create tuple
	t := NewTuple()

	for attrindex, attr := range r.table.attributes {
		assigned = false

		for x, decl := range attributes {
			if attr.name == decl.Lexeme && attr.autoIncrement == false {
				// Before adding value in tuple, check it's not a builtin func or arithmetic operation
				switch values[x].Token {
				case parser.NowToken:
					t.Append(time.Now().Format(parser.DateLongFormat))
				default:
					switch strings.ToLower(attr.typeName) {
					case "int64", "int":
						val, err := strconv.ParseInt(values[x].Lexeme, 10, 64)
						if err != nil {
							return 0, err
						}
						t.Append(val)
					case "numeric", "decimal":
						val, err := strconv.ParseFloat(values[x].Lexeme, 64)
						if err != nil {
							return 0, err
						}
						t.Append(val)
					default:
						t.Append(values[x].Lexeme)
					}
				}
				valuesindex = x
				assigned = true
				if returnedID == attr.name {
					var err error
					id, err = strconv.ParseInt(values[x].Lexeme, 10, 64)
					if err != nil {
						return 0, err
					}
				}
			}
		}

		// If attribute is AUTO INCREMENT, compute it and assign it
		if attr.autoIncrement {
			assigned = true
			id = int64(len(r.rows) + 1)
			t.Append(id)
		}

		// Do we have a UNIQUE attribute ? if so
		if attr.unique {
			for i := range r.rows { // check all value already in relation (yup, no index tree)
				if r.rows[i].Values[attrindex].(string) == string(values[valuesindex].Lexeme) {
					return 0, fmt.Errorf("UNIQUE constraint violation")
				}
			}
		}

		// If values was not explictly given, set default value
		if assigned == false {
			switch val := attr.defaultValue.(type) {
			case func() interface{}:
				v := (func() interface{})(val)()
				log.Debug("Setting func value '%v' to %s\n", v, attr.name)
				t.Append(v)
			default:
				log.Debug("Setting default value '%v' to %s\n", val, attr.name)
				t.Append(attr.defaultValue)
			}
		}
	}

	log.Info("New tuple : %v", t)

	// Insert tuple
	err := r.Insert(t)
	if err != nil {
		return 0, err
	}

	return id, nil
}
<commit_msg>Fix typo<commit_after>package engine

import (
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/proullon/ramsql/engine/log"
	"github.com/proullon/ramsql/engine/parser"
	"github.com/proullon/ramsql/engine/protocol"
)

/*
|-> INSERT
    |-> INTO
        |-> user
            |-> last_name
            |-> first_name
            |-> email
    |-> VALUES
        |-> (
            |-> Roullon
            |-> Pierre
            |-> pierre.roullon@gmail.com
    |-> RETURNING
            |-> email

*/
func insertIntoTableExecutor(e *Engine, insertDecl *parser.Decl, conn protocol.EngineConn) error {
	// Get table and concerned attributes and write lock it
	intoDecl := insertDecl.Decl[0]
	r, attributes, err := getRelation(e, intoDecl)
	if err != nil {
		return err
	}
	r.Lock()
	defer r.Unlock()

	// Check for RETURNING clause
	var returnedID string
	if len(insertDecl.Decl) > 2 {
		for i := range insertDecl.Decl {
			if insertDecl.Decl[i].Token == parser.ReturningToken {
				returningDecl := insertDecl.Decl[i]
				returnedID = returningDecl.Lexeme
				break
			}
		}
	}

	// Create a new tuple with values
	ids := []int64{}
	valuesDecl := insertDecl.Decl[1]
	for _, valueListDecl := range valuesDecl.Decl {
		// TODO handle all inserts atomically
		id, err := insert(r, attributes, valueListDecl.Decl, returnedID)
		if err != nil {
			return err
		}

		ids = append(ids, id)
	}

	// if RETURNING decl is not present
	if returnedID != "" {
		conn.WriteRowHeader([]string{returnedID})
		for _, id := range ids {
			conn.WriteRow([]string{fmt.Sprintf("%v", id)})
		}
		conn.WriteRowEnd()
	} else {
		conn.WriteResult(ids[len(ids)-1], (int64)(len(ids)))
	}
	return nil
}

/*
|-> INTO
    |-> user
        |-> last_name
        |-> first_name
        |-> email
*/
func getRelation(e *Engine, intoDecl *parser.Decl) (*Relation, []*parser.Decl, error) {

	// Decl[0] is the table name
	r := e.relation(intoDecl.Decl[0].Lexeme)
	if r == nil {
		return nil, nil, errors.New("table " + intoDecl.Decl[0].Lexeme + " does not exist")
	}

	for i := range intoDecl.Decl[0].Decl {
		err := attributeExistsInTable(e, intoDecl.Decl[0].Decl[i].Lexeme, intoDecl.Decl[0].Lexeme)
		if err != nil {
			return nil, nil, err
		}
	}

	return r, intoDecl.Decl[0].Decl, nil
}

func insert(r *Relation, attributes []*parser.Decl, values []*parser.Decl, returnedID string) (int64, error) {
	var assigned = false
	var id int64
	var valuesindex int

	// Create tuple
	t := NewTuple()

	for attrindex, attr := range r.table.attributes {
		assigned = false

		for x, decl := range attributes {
			if attr.name == decl.Lexeme && attr.autoIncrement == false {
				// Before adding value in tuple, check it's not a builtin func or arithmetic operation
				switch values[x].Token {
				case parser.NowToken:
					t.Append(time.Now().Format(parser.DateLongFormat))
				default:
					switch strings.ToLower(attr.typeName) {
					case "int64", "int":
						val, err := strconv.ParseInt(values[x].Lexeme, 10, 64)
						if err != nil {
							return 0, err
						}
						t.Append(val)
					case "numeric", "decimal":
						val, err := strconv.ParseFloat(values[x].Lexeme, 64)
						if err != nil {
							return 0, err
						}
						t.Append(val)
					default:
						t.Append(values[x].Lexeme)
					}
				}
				valuesindex = x
				assigned = true
				if returnedID == attr.name {
					var err error
					id, err = strconv.ParseInt(values[x].Lexeme, 10, 64)
					if err != nil {
						return 0, err
					}
				}
			}
		}

		// If attribute is AUTO INCREMENT, compute it and assign it
		if attr.autoIncrement {
			assigned = true
			id = int64(len(r.rows) + 1)
			t.Append(id)
		}

		// Do we have a UNIQUE attribute ? if so
		if attr.unique {
			for i := range r.rows { // check all value already in relation (yup, no index tree)
				if r.rows[i].Values[attrindex].(string) == string(values[valuesindex].Lexeme) {
					return 0, fmt.Errorf("UNIQUE constraint violation")
				}
			}
		}

		// If values was not explictly given, set default value
		if assigned == false {
			switch val := attr.defaultValue.(type) {
			case func() interface{}:
				v := (func() interface{})(val)()
				log.Debug("Setting func value '%v' to %s\n", v, attr.name)
				t.Append(v)
			default:
				log.Debug("Setting default value '%v' to %s\n", val, attr.name)
				t.Append(attr.defaultValue)
			}
		}
	}

	log.Info("New tuple : %v", t)

	// Insert tuple
	err := r.Insert(t)
	if err != nil {
		return 0, err
	}

	return id, nil
}
<|endoftext|>


<commit_before>// Copyright 2014 Arne Roomann-Kurrik
//
// 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.

// Attempts to fetch a Tweet containing Emoji
package main

import (
	"fmt"
	"github.com/kurrik/oauth1a"
	"github.com/kurrik/twittergo"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"
)

func LoadCredentials() (client *twittergo.Client, err error) {
	credentials, err := ioutil.ReadFile("CREDENTIALS")
	if err != nil {
		return
	}
	lines := strings.Split(string(credentials), "\n")
	config := &oauth1a.ClientConfig{
		ConsumerKey:    lines[0],
		ConsumerSecret: lines[1],
	}
	client = twittergo.NewClient(config, nil)
	return
}

func main() {
	var (
		err    error
		client *twittergo.Client
		req    *http.Request
		resp   *twittergo.APIResponse
		tweet  *twittergo.Tweet
	)
	if client, err = LoadCredentials(); err != nil {
		fmt.Printf("Could not parse CREDENTIALS file: %v\n", err)
		os.Exit(1)
	}
	query := url.Values{
		"id": []string{"451453919017697280"},
	}
	url := fmt.Sprintf("/1.1/statuses/show.json?%v", query.Encode())
	if req, err = http.NewRequest("GET", url, nil); err != nil {
		fmt.Printf("Could not parse request: %v\n", err)
		os.Exit(1)
	}
	if resp, err = client.SendRequest(req); err != nil {
		fmt.Printf("Could not send request: %v\n", err)
		os.Exit(1)
	}
	tweet = &twittergo.Tweet{}
	if err = resp.Parse(tweet); err != nil {
		fmt.Printf("There was an error: %v\n", err)
		os.Exit(1)
	}
	fmt.Println(tweet.Text())
}
<commit_msg>Update the emoji sample to print all the emoji tweets.<commit_after>// Copyright 2014 Arne Roomann-Kurrik
//
// 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.

// Attempts to fetch a Tweet containing Emoji
package main

import (
	"fmt"
	"github.com/kurrik/oauth1a"
	"github.com/kurrik/twittergo"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"
)

func LoadCredentials() (client *twittergo.Client, err error) {
	credentials, err := ioutil.ReadFile("CREDENTIALS")
	if err != nil {
		return
	}
	lines := strings.Split(string(credentials), "\n")
	config := &oauth1a.ClientConfig{
		ConsumerKey:    lines[0],
		ConsumerSecret: lines[1],
	}
	client = twittergo.NewClient(config, nil)
	return
}

func GetTweet(client *twittergo.Client, id string) (tweet *twittergo.Tweet, err error) {
	var (
		query = url.Values{"id": []string{id}}
		url   = fmt.Sprintf("/1.1/statuses/show.json?%v", query.Encode())
		req   *http.Request
		resp  *twittergo.APIResponse
	)
	if req, err = http.NewRequest("GET", url, nil); err != nil {
		err = fmt.Errorf("Could not parse request: %v\n", err)
		return
	}
	if resp, err = client.SendRequest(req); err != nil {
		err = fmt.Errorf("Could not send request: %v\n", err)
		return
	}
	tweet = &twittergo.Tweet{}
	if err = resp.Parse(tweet); err != nil {
		err = fmt.Errorf("There was an error: %v\n", err)
	}
	return
}

func main() {
	var (
		err    error
		client *twittergo.Client
		tweet  *twittergo.Tweet
	)
	if client, err = LoadCredentials(); err != nil {
		fmt.Printf("Could not parse CREDENTIALS file: %v\n", err)
		os.Exit(1)
	}
	tweet_ids := []string{
		"451453919017697280",
		"451453883575848960",
		"451453847622262784",
		"451453811035357184",
		"451453775882899456",
		"451453738603909120",
		"451453703375953920",
		"451453667409817600",
		"451453613231964160",
		"451453567233040384",
		"451453517819949056",
		"451453478502539264",
		"451453436769218560",
	}

	for _, id := range tweet_ids {
		if tweet, err = GetTweet(client, id); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		fmt.Println(tweet.Text())
	}
}
<|endoftext|>


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

package ingress

import (
	"context"
	"testing"

	"k8s.io/api/networking/v1beta1"
	metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"

	meshconfig "istio.io/api/mesh/v1alpha1"
	"istio.io/istio/pilot/pkg/model"
	kubecontroller "istio.io/istio/pilot/pkg/serviceregistry/kube/controller"
	"istio.io/istio/pkg/config"
	"istio.io/istio/pkg/config/mesh"
	"istio.io/istio/pkg/config/schema/gvk"
	"istio.io/istio/pkg/kube"
)

func newFakeController() (model.ConfigStoreCache, kube.Client) {
	meshHolder := mesh.NewTestWatcher(&meshconfig.MeshConfig{
		IngressControllerMode: meshconfig.MeshConfig_DEFAULT,
	})
	fakeClient := kube.NewFakeClient()
	return NewController(fakeClient, meshHolder, kubecontroller.Options{}), fakeClient
}

func TestIngressController(t *testing.T) {
	ingress1 := v1beta1.Ingress{
		ObjectMeta: metaV1.ObjectMeta{
			Namespace: "mock", // goes into backend full name
			Name:      "test",
		},
		Spec: v1beta1.IngressSpec{
			Rules: []v1beta1.IngressRule{
				{
					Host: "my.host.com",
					IngressRuleValue: v1beta1.IngressRuleValue{
						HTTP: &v1beta1.HTTPIngressRuleValue{
							Paths: []v1beta1.HTTPIngressPath{
								{
									Path: "/test",
									Backend: v1beta1.IngressBackend{
										ServiceName: "foo",
										ServicePort: intstr.IntOrString{IntVal: 8000},
									},
								},
							},
						},
					},
				},
				{
					Host: "my2.host.com",
					IngressRuleValue: v1beta1.IngressRuleValue{
						HTTP: &v1beta1.HTTPIngressRuleValue{
							Paths: []v1beta1.HTTPIngressPath{
								{
									Path: "/test1.*",
									Backend: v1beta1.IngressBackend{
										ServiceName: "bar",
										ServicePort: intstr.IntOrString{IntVal: 8000},
									},
								},
							},
						},
					},
				},
				{
					Host: "my3.host.com",
					IngressRuleValue: v1beta1.IngressRuleValue{
						HTTP: &v1beta1.HTTPIngressRuleValue{
							Paths: []v1beta1.HTTPIngressPath{
								{
									Path: "/test/*",
									Backend: v1beta1.IngressBackend{
										ServiceName: "bar",
										ServicePort: intstr.IntOrString{IntVal: 8000},
									},
								},
							},
						},
					},
				},
			},
		},
	}

	ingress2 := v1beta1.Ingress{
		ObjectMeta: metaV1.ObjectMeta{
			Namespace: "mock",
			Name:      "test",
		},
		Spec: v1beta1.IngressSpec{
			Rules: []v1beta1.IngressRule{
				{
					Host: "my.host.com",
					IngressRuleValue: v1beta1.IngressRuleValue{
						HTTP: &v1beta1.HTTPIngressRuleValue{
							Paths: []v1beta1.HTTPIngressPath{
								{
									Path: "/test2",
									Backend: v1beta1.IngressBackend{
										ServiceName: "foo",
										ServicePort: intstr.IntOrString{IntVal: 8000},
									},
								},
							},
						},
					},
				},
			},
		},
	}

	controller, client := newFakeController()
	configCh := make(chan config.Config)

	configHandler := func(_, curr config.Config, event model.Event) {
		configCh <- curr
	}

	controller.RegisterEventHandler(gvk.VirtualService, configHandler)
	stopCh := make(chan struct{})
	go controller.Run(stopCh)
	defer close(stopCh)

	client.KubeInformer().Start(stopCh)

	client.NetworkingV1beta1().Ingresses(ingress1.Namespace).Create(context.TODO(), &ingress1, metaV1.CreateOptions{})

	vs := <-configCh
	if vs.Name != ingress1.Name+"-"+"virtualservice" || vs.Namespace != ingress1.Namespace {
		t.Errorf("received unecpected config %v/%v", vs.Namespace, vs.Name)
	}
	client.NetworkingV1beta1().Ingresses(ingress2.Namespace).Update(context.TODO(), &ingress2, metaV1.UpdateOptions{})
	vs = <-configCh
	if vs.Name != ingress1.Name+"-"+"virtualservice" || vs.Namespace != ingress1.Namespace {
		t.Errorf("received unecpected config %v/%v", vs.Namespace, vs.Name)
	}
}
<commit_msg>Fix TestIngressController flakes (#35669)<commit_after>// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ingress

import (
	"context"
	"testing"
	"time"

	"k8s.io/api/networking/v1beta1"
	metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"

	meshconfig "istio.io/api/mesh/v1alpha1"
	"istio.io/istio/pilot/pkg/model"
	kubecontroller "istio.io/istio/pilot/pkg/serviceregistry/kube/controller"
	"istio.io/istio/pkg/config"
	"istio.io/istio/pkg/config/mesh"
	"istio.io/istio/pkg/config/schema/gvk"
	"istio.io/istio/pkg/kube"
)

func newFakeController() (model.ConfigStoreCache, kube.Client) {
	meshHolder := mesh.NewTestWatcher(&meshconfig.MeshConfig{
		IngressControllerMode: meshconfig.MeshConfig_DEFAULT,
	})
	fakeClient := kube.NewFakeClient()
	return NewController(fakeClient, meshHolder, kubecontroller.Options{}), fakeClient
}

func TestIngressController(t *testing.T) {
	ingress1 := v1beta1.Ingress{
		ObjectMeta: metaV1.ObjectMeta{
			Namespace: "mock", // goes into backend full name
			Name:      "test",
		},
		Spec: v1beta1.IngressSpec{
			Rules: []v1beta1.IngressRule{
				{
					Host: "my.host.com",
					IngressRuleValue: v1beta1.IngressRuleValue{
						HTTP: &v1beta1.HTTPIngressRuleValue{
							Paths: []v1beta1.HTTPIngressPath{
								{
									Path: "/test",
									Backend: v1beta1.IngressBackend{
										ServiceName: "foo",
										ServicePort: intstr.IntOrString{IntVal: 8000},
									},
								},
							},
						},
					},
				},
				{
					Host: "my2.host.com",
					IngressRuleValue: v1beta1.IngressRuleValue{
						HTTP: &v1beta1.HTTPIngressRuleValue{
							Paths: []v1beta1.HTTPIngressPath{
								{
									Path: "/test1.*",
									Backend: v1beta1.IngressBackend{
										ServiceName: "bar",
										ServicePort: intstr.IntOrString{IntVal: 8000},
									},
								},
							},
						},
					},
				},
				{
					Host: "my3.host.com",
					IngressRuleValue: v1beta1.IngressRuleValue{
						HTTP: &v1beta1.HTTPIngressRuleValue{
							Paths: []v1beta1.HTTPIngressPath{
								{
									Path: "/test/*",
									Backend: v1beta1.IngressBackend{
										ServiceName: "bar",
										ServicePort: intstr.IntOrString{IntVal: 8000},
									},
								},
							},
						},
					},
				},
			},
		},
	}

	ingress2 := v1beta1.Ingress{
		ObjectMeta: metaV1.ObjectMeta{
			Namespace: "mock",
			Name:      "test",
		},
		Spec: v1beta1.IngressSpec{
			Rules: []v1beta1.IngressRule{
				{
					Host: "my.host.com",
					IngressRuleValue: v1beta1.IngressRuleValue{
						HTTP: &v1beta1.HTTPIngressRuleValue{
							Paths: []v1beta1.HTTPIngressPath{
								{
									Path: "/test2",
									Backend: v1beta1.IngressBackend{
										ServiceName: "foo",
										ServicePort: intstr.IntOrString{IntVal: 8000},
									},
								},
							},
						},
					},
				},
			},
		},
	}

	controller, client := newFakeController()
	configCh := make(chan config.Config)

	configHandler := func(_, curr config.Config, event model.Event) {
		configCh <- curr
	}

	wait := func() config.Config {
		select {
		case x := <-configCh:
			return x
		case <-time.After(time.Second * 10):
			t.Fatalf("timed out waiting for config")
		}
		return config.Config{}
	}

	controller.RegisterEventHandler(gvk.VirtualService, configHandler)
	stopCh := make(chan struct{})
	go controller.Run(stopCh)
	defer close(stopCh)

	client.RunAndWait(stopCh)

	client.NetworkingV1beta1().Ingresses(ingress1.Namespace).Create(context.TODO(), &ingress1, metaV1.CreateOptions{})

	vs := wait()
	if vs.Name != ingress1.Name+"-"+"virtualservice" || vs.Namespace != ingress1.Namespace {
		t.Errorf("received unecpected config %v/%v", vs.Namespace, vs.Name)
	}
	client.NetworkingV1beta1().Ingresses(ingress2.Namespace).Update(context.TODO(), &ingress2, metaV1.UpdateOptions{})
	vs = wait()
	if vs.Name != ingress1.Name+"-"+"virtualservice" || vs.Namespace != ingress1.Namespace {
		t.Errorf("received unecpected config %v/%v", vs.Namespace, vs.Name)
	}
}
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// 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
//
//     https://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 servicebindings

import (
	"github.com/google/kf/pkg/kf/commands/config"
	"github.com/google/kf/pkg/kf/commands/utils"
	servicebindings "github.com/google/kf/pkg/kf/service-bindings"
	"github.com/google/kf/pkg/kf/services"
	"github.com/spf13/cobra"
)

// NewBindServiceCommand allows users to bind apps to service instances.
func NewBindServiceCommand(p *config.KfParams, client servicebindings.ClientInterface) *cobra.Command {
	var (
		bindingName  string
		configAsJSON string
	)

	createCmd := &cobra.Command{
		Use:     "bind-service APP_NAME SERVICE_INSTANCE [-c PARAMETERS_AS_JSON] [--binding-name BINDING_NAME]",
		Aliases: []string{"bs"},
		Short:   "Bind a service instance to an app",
		Example: `  kf bind-service myapp mydb -c '{"permissions":"read-only"}'`,
		Args:    cobra.ExactArgs(2),
		RunE: func(cmd *cobra.Command, args []string) error {
			appName := args[0]
			instanceName := args[1]

			cmd.SilenceUsage = true

			if err := utils.ValidateNamespace(p); err != nil {
				return err
			}

			if bindingName == "" {
				bindingName = instanceName
			}

			params, err := services.ParseJSONOrFile(configAsJSON)
			if err != nil {
				return err
			}

			_, err = client.Create(instanceName, appName,
				servicebindings.WithCreateBindingName(bindingName),
				servicebindings.WithCreateParams(params),
				servicebindings.WithCreateNamespace(p.Namespace),
			)
			if err != nil {
				return err
			}

			return nil
		},
	}

	createCmd.Flags().StringVarP(
		&configAsJSON,
		"config",
		"c",
		"{}",
		"JSON object containing service-specific configuration parameters, provided in-line or in a file")

	createCmd.Flags().StringVarP(
		&bindingName,
		"binding-name",
		"b",
		"",
		"Name to expose service instance to app process with (default: service instance name)")

	return createCmd
}
<commit_msg>pkg/kf/commands/service-bindings: tip user to restart app (#573)<commit_after>// Copyright 2019 Google LLC
//
// 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
//
//     https://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 servicebindings

import (
	"fmt"

	"github.com/google/kf/pkg/kf/commands/config"
	"github.com/google/kf/pkg/kf/commands/utils"
	servicebindings "github.com/google/kf/pkg/kf/service-bindings"
	"github.com/google/kf/pkg/kf/services"
	"github.com/spf13/cobra"
)

// NewBindServiceCommand allows users to bind apps to service instances.
func NewBindServiceCommand(p *config.KfParams, client servicebindings.ClientInterface) *cobra.Command {
	var (
		bindingName  string
		configAsJSON string
	)

	createCmd := &cobra.Command{
		Use:     "bind-service APP_NAME SERVICE_INSTANCE [-c PARAMETERS_AS_JSON] [--binding-name BINDING_NAME]",
		Aliases: []string{"bs"},
		Short:   "Bind a service instance to an app",
		Example: `  kf bind-service myapp mydb -c '{"permissions":"read-only"}'`,
		Args:    cobra.ExactArgs(2),
		RunE: func(cmd *cobra.Command, args []string) error {
			appName := args[0]
			instanceName := args[1]

			cmd.SilenceUsage = true

			if err := utils.ValidateNamespace(p); err != nil {
				return err
			}

			if bindingName == "" {
				bindingName = instanceName
			}

			params, err := services.ParseJSONOrFile(configAsJSON)
			if err != nil {
				return err
			}

			_, err = client.Create(instanceName, appName,
				servicebindings.WithCreateBindingName(bindingName),
				servicebindings.WithCreateParams(params),
				servicebindings.WithCreateNamespace(p.Namespace),
			)
			if err != nil {
				return err
			}

			fmt.Fprintf(cmd.OutOrStderr(), "Use 'kf restart %s' to ensure your changes take effect\n", appName)

			return nil
		},
	}

	createCmd.Flags().StringVarP(
		&configAsJSON,
		"config",
		"c",
		"{}",
		"JSON object containing service-specific configuration parameters, provided in-line or in a file")

	createCmd.Flags().StringVarP(
		&bindingName,
		"binding-name",
		"b",
		"",
		"Name to expose service instance to app process with (default: service instance name)")

	return createCmd
}
<|endoftext|>


<commit_before>package annotationstest

import (
	"context"
	"sync"

	"github.com/grafana/grafana/pkg/services/annotations"
)

type fakeAnnotationsRepo struct {
	mtx         sync.Mutex
	annotations map[int64]annotations.Item
}

func NewFakeAnnotationsRepo() *fakeAnnotationsRepo {
	return &fakeAnnotationsRepo{
		annotations: map[int64]annotations.Item{},
	}
}

func (repo *fakeAnnotationsRepo) Delete(_ context.Context, params *annotations.DeleteParams) error {
	repo.mtx.Lock()
	defer repo.mtx.Unlock()

	if params.Id != 0 {
		delete(repo.annotations, params.Id)
	} else {
		for _, v := range repo.annotations {
			if params.DashboardId == v.DashboardId && params.PanelId == v.PanelId {
				delete(repo.annotations, v.Id)
			}
		}
	}

	return nil
}

func (repo *fakeAnnotationsRepo) Save(ctx context.Context, item *annotations.Item) error {
	repo.mtx.Lock()
	defer repo.mtx.Unlock()

	if item.Id == 0 {
		item.Id = int64(len(repo.annotations) + 1)
	}
	repo.annotations[item.Id] = *item

	return nil
}

func (repo *fakeAnnotationsRepo) SaveMany(ctx context.Context, items []annotations.Item) error {
	repo.mtx.Lock()
	defer repo.mtx.Unlock()

	for _, i := range items {
		if i.Id == 0 {
			i.Id = int64(len(repo.annotations) + 1)
		}
		repo.annotations[i.Id] = i
	}

	return nil
}

func (repo *fakeAnnotationsRepo) Update(_ context.Context, item *annotations.Item) error {
	return nil
}

func (repo *fakeAnnotationsRepo) Find(_ context.Context, query *annotations.ItemQuery) ([]*annotations.ItemDTO, error) {
	repo.mtx.Lock()
	defer repo.mtx.Unlock()

	if annotation, has := repo.annotations[query.AnnotationId]; has {
		return []*annotations.ItemDTO{{Id: annotation.Id, DashboardId: annotation.DashboardId}}, nil
	}
	annotations := []*annotations.ItemDTO{{Id: 1, DashboardId: 0}}
	return annotations, nil
}

func (repo *fakeAnnotationsRepo) FindTags(_ context.Context, query *annotations.TagsQuery) (annotations.FindTagsResult, error) {
	result := annotations.FindTagsResult{
		Tags: []*annotations.TagsDTO{},
	}
	return result, nil
}

func (repo *fakeAnnotationsRepo) Len() int {
	repo.mtx.Lock()
	defer repo.mtx.Unlock()

	return len(repo.annotations)
}

func (repo *fakeAnnotationsRepo) Items() map[int64]annotations.Item {
	repo.mtx.Lock()
	defer repo.mtx.Unlock()

	return repo.annotations
}
<commit_msg>chore(tests): return a copy of the map to avoid concurrency issues in tests (#58547)<commit_after>package annotationstest

import (
	"context"
	"sync"

	"github.com/grafana/grafana/pkg/services/annotations"
)

type fakeAnnotationsRepo struct {
	mtx         sync.Mutex
	annotations map[int64]annotations.Item
}

func NewFakeAnnotationsRepo() *fakeAnnotationsRepo {
	return &fakeAnnotationsRepo{
		annotations: map[int64]annotations.Item{},
	}
}

func (repo *fakeAnnotationsRepo) Delete(_ context.Context, params *annotations.DeleteParams) error {
	repo.mtx.Lock()
	defer repo.mtx.Unlock()

	if params.Id != 0 {
		delete(repo.annotations, params.Id)
	} else {
		for _, v := range repo.annotations {
			if params.DashboardId == v.DashboardId && params.PanelId == v.PanelId {
				delete(repo.annotations, v.Id)
			}
		}
	}

	return nil
}

func (repo *fakeAnnotationsRepo) Save(ctx context.Context, item *annotations.Item) error {
	repo.mtx.Lock()
	defer repo.mtx.Unlock()

	if item.Id == 0 {
		item.Id = int64(len(repo.annotations) + 1)
	}
	repo.annotations[item.Id] = *item

	return nil
}

func (repo *fakeAnnotationsRepo) SaveMany(ctx context.Context, items []annotations.Item) error {
	repo.mtx.Lock()
	defer repo.mtx.Unlock()

	for _, i := range items {
		if i.Id == 0 {
			i.Id = int64(len(repo.annotations) + 1)
		}
		repo.annotations[i.Id] = i
	}

	return nil
}

func (repo *fakeAnnotationsRepo) Update(_ context.Context, item *annotations.Item) error {
	return nil
}

func (repo *fakeAnnotationsRepo) Find(_ context.Context, query *annotations.ItemQuery) ([]*annotations.ItemDTO, error) {
	repo.mtx.Lock()
	defer repo.mtx.Unlock()

	if annotation, has := repo.annotations[query.AnnotationId]; has {
		return []*annotations.ItemDTO{{Id: annotation.Id, DashboardId: annotation.DashboardId}}, nil
	}
	annotations := []*annotations.ItemDTO{{Id: 1, DashboardId: 0}}
	return annotations, nil
}

func (repo *fakeAnnotationsRepo) FindTags(_ context.Context, query *annotations.TagsQuery) (annotations.FindTagsResult, error) {
	result := annotations.FindTagsResult{
		Tags: []*annotations.TagsDTO{},
	}
	return result, nil
}

func (repo *fakeAnnotationsRepo) Len() int {
	repo.mtx.Lock()
	defer repo.mtx.Unlock()

	return len(repo.annotations)
}

func (repo *fakeAnnotationsRepo) Items() map[int64]annotations.Item {
	repo.mtx.Lock()
	defer repo.mtx.Unlock()
	ret := make(map[int64]annotations.Item)
	for k, v := range repo.annotations {
		ret[k] = v
	}
	return ret
}
<|endoftext|>


<commit_before>package restpc

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"
	"time"

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

func Test_NewError_Twice(t *testing.T) {
	err := NewError(InvalidArgument, "something is missing", nil)
	assert.Equal(t, "something is missing", err.Message())
	assert.Equal(t, "something is missing", err.Error())
	assert.Equal(t, InvalidArgument, err.Code())

	err = NewError(Unavailable, "not sure what", err)
	assert.Equal(t, "something is missing", err.Message())
	assert.Equal(t, "something is missing", err.Error())
	assert.Equal(t, InvalidArgument, err.Code())
}

func unimplementedHandler(req Request) (*Response, error) {
	return nil, NewError(
		Unimplemented,
		"we didn't implement this",
		fmt.Errorf("just an unexposed message"),
	).Add("name", "June The Girl")
}

func TestErrorFull(t *testing.T) {
	pkgPath := "github.com/ilius/restpc"
	goPath := os.Getenv("GOPATH")
	expectedHandlerName := pkgPath + ".unimplementedHandler"
	expectedTracebackRecord := &tracebackRecordImp{
		file:     goPath + "/src/" + pkgPath + "/error_test.go",
		function: expectedHandlerName,
		line:     31,
	}

	origErrorDispatcher := errorDispatcher
	defer func() {
		errorDispatcher = origErrorDispatcher
	}()
	var rpcErr RPCError
	var request Request
	errorDispatcher = func(requestArg Request, rpcErrArg RPCError) {
		rpcErr = rpcErrArg
		request = requestArg
	}
	handlerFunc := TranslateHandler(unimplementedHandler)
	w := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "", nil)
	handlerFunc(w, r)
	assert.Equal(t, http.StatusNotImplemented, w.Code)
	time.Sleep(500 * time.Millisecond)
	if rpcErr == nil {
		panic("rpcErr == nil")
	}
	assert.Equal(t, expectedHandlerName, request.HandlerName())
	assert.Equal(t, Unimplemented, rpcErr.Code())
	assert.Equal(t, "we didn't implement this", rpcErr.Error())
	assert.Equal(t, "we didn't implement this", rpcErr.Message())
	assert.Equal(t, "just an unexposed message", rpcErr.Private().Error())
	assert.Equal(t, "June The Girl", rpcErr.Details()["name"])
	{
		tb := rpcErr.Traceback()
		records := tb.Records(expectedHandlerName)
		if len(records) != 1 {
			panic(fmt.Errorf("len(records) = %v", len(records)))
		}
		record := records[0]
		assert.Equal(t, expectedTracebackRecord, record)
		assert.Equal(t, expectedTracebackRecord.File(), record.File())
		assert.Equal(t, expectedTracebackRecord.Function(), record.Function())
		assert.Equal(t, expectedTracebackRecord.FunctionLocal(), record.FunctionLocal())
		assert.Equal(t, expectedTracebackRecord.Line(), record.Line())
		mapRecords := tb.MapRecords(expectedHandlerName)
		if len(mapRecords) != 1 {
			panic(fmt.Errorf("len(mapRecords) = %v", len(mapRecords)))
		}
		mapRecord := mapRecords[0]
		assert.Equal(t, expectedTracebackRecord.File(), mapRecord["file"])
		assert.Equal(t, expectedTracebackRecord.Function(), mapRecord["function"])
		assert.Equal(t, expectedTracebackRecord.FunctionLocal(), mapRecord["functionLocal"])
		assert.Equal(t, expectedTracebackRecord.Line(), mapRecord["line"])
	}
}
<commit_msg>TestErrorFull: make test independent of package import path<commit_after>package restpc

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"

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

func Test_NewError_Twice(t *testing.T) {
	err := NewError(InvalidArgument, "something is missing", nil)
	assert.Equal(t, "something is missing", err.Message())
	assert.Equal(t, "something is missing", err.Error())
	assert.Equal(t, InvalidArgument, err.Code())

	err = NewError(Unavailable, "not sure what", err)
	assert.Equal(t, "something is missing", err.Message())
	assert.Equal(t, "something is missing", err.Error())
	assert.Equal(t, InvalidArgument, err.Code())
}

func unimplementedHandler(req Request) (*Response, error) {
	return nil, NewError(
		Unimplemented,
		"we didn't implement this",
		fmt.Errorf("just an unexposed message"),
	).Add("name", "June The Girl")
}

func TestErrorFull(t *testing.T) {
	handlerName := "unimplementedHandler"

	origErrorDispatcher := errorDispatcher
	defer func() {
		errorDispatcher = origErrorDispatcher
	}()
	var rpcErr RPCError
	var request Request
	errorDispatcher = func(requestArg Request, rpcErrArg RPCError) {
		rpcErr = rpcErrArg
		request = requestArg
	}
	handlerFunc := TranslateHandler(unimplementedHandler)
	w := httptest.NewRecorder()
	r, _ := http.NewRequest("GET", "", nil)
	handlerFunc(w, r)
	assert.Equal(t, http.StatusNotImplemented, w.Code)
	time.Sleep(500 * time.Millisecond)
	if rpcErr == nil {
		panic("rpcErr == nil")
	}
	if !strings.HasSuffix(request.HandlerName(), "."+handlerName) {
		t.Errorf("request.HandlerName()=%v", request.HandlerName())
		return
	}
	handlerNameFull := request.HandlerName()
	assert.Equal(t, Unimplemented, rpcErr.Code())
	assert.Equal(t, "we didn't implement this", rpcErr.Error())
	assert.Equal(t, "we didn't implement this", rpcErr.Message())
	assert.Equal(t, "just an unexposed message", rpcErr.Private().Error())
	assert.Equal(t, "June The Girl", rpcErr.Details()["name"])
	{
		tb := rpcErr.Traceback()
		records := tb.Records(handlerNameFull)
		if len(records) != 1 {
			for _, record := range records {
				t.Log(record)
			}
			t.Errorf("len(records) = %v", len(records))
			return
		}
		record := records[0]
		if !strings.HasSuffix(record.File(), "/error_test.go") {
			t.Errorf("record.File()=%v", record.File())
		}
		assert.Equal(t, handlerNameFull, record.Function())
		assert.Equal(t, handlerName, record.FunctionLocal())
		assert.Equal(t, 31, record.Line())
		mapRecords := tb.MapRecords(handlerNameFull)
		if len(mapRecords) != 1 {
			t.Errorf("len(mapRecords) = %v", len(mapRecords))
			return
		}
		mapRecord := mapRecords[0]
		assert.Equal(t, record.File(), mapRecord["file"])
		assert.Equal(t, record.Function(), mapRecord["function"])
		assert.Equal(t, record.FunctionLocal(), mapRecord["functionLocal"])
		assert.Equal(t, record.Line(), mapRecord["line"])
	}
}
<|endoftext|>


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

// +build darwin freebsd linux netbsd

package tcp_test

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

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

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

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

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

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

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

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

// +build darwin freebsd linux netbsd

package tcp_test

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

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

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

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

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

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

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

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


<commit_before>// Package quadedge describes a quadedge object used to build up the triangulation
// A quadedge is made up of four directional edges
//
//          DO
//          ^*
//          ||
//    O*----++---->D
//  L D<----++----*O   R
//          ||
//          *V
//          OD
//
//  O represents the Origin
//  D represents the Destination
//
package quadedge

import "sync/atomic"

// QuadEdge describes a quadedge object. Which is made up of four directional edges
type QuadEdge struct {
	initialized bool
	e           [4]Edge
}

// NewQEdge create a new quad edge object
func NewQEdge() *QuadEdge {
	var gidx = atomic.AddUint64(&glbIdx, 1)
	var qe QuadEdge

	qe.e[0].glbIdx, qe.e[1].glbIdx, qe.e[2].glbIdx, qe.e[3].glbIdx = gidx, gidx, gidx, gidx
	qe.e[0].num, qe.e[1].num, qe.e[2].num, qe.e[3].num = 0, 1, 2, 3
	qe.e[0].qe, qe.e[1].qe, qe.e[2].qe, qe.e[3].qe = &qe, &qe, &qe, &qe

	qe.e[0].next = &(qe.e[0])
	qe.e[1].next = &(qe.e[3])
	qe.e[2].next = &(qe.e[2])
	qe.e[3].next = &(qe.e[1])

	qe.initialized = true

	return &qe
}
<commit_msg>[quadedge] refactor<commit_after>// Package quadedge describes a quadedge object used to build up the triangulation
// A quadedge is made up of four directional edges
//
//          DO
//          ^*
//          ||
//    O*----++---->D
//  L D<----++----*O   R
//          ||
//          *V
//          OD
//
//  O represents the Origin
//  D represents the Destination
//
package quadedge

import "sync/atomic"

// QuadEdge describes a quadedge object. Which is made up of four directional edges
type QuadEdge struct {
	initialized bool
	e           [4]Edge
}

func (qe *QuadEdge) Init() {
	var gidx = atomic.AddUint64(&glbIdx, 1)

	qe.e[0].glbIdx, qe.e[1].glbIdx, qe.e[2].glbIdx, qe.e[3].glbIdx = gidx, gidx, gidx, gidx
	qe.e[0].num, qe.e[1].num, qe.e[2].num, qe.e[3].num = 0, 1, 2, 3
	qe.e[0].qe, qe.e[1].qe, qe.e[2].qe, qe.e[3].qe = qe, qe, qe, qe

	qe.e[0].next = &(qe.e[0])
	qe.e[1].next = &(qe.e[3])
	qe.e[2].next = &(qe.e[2])
	qe.e[3].next = &(qe.e[1])

	qe.initialized = true
}

// NewQEdge create a new quad edge object
func NewQEdge() *QuadEdge {
	var qe QuadEdge
	qe.Init()
	return &qe
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors 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 app implements a Server object for running the scheduler.
package app

import (
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/http/pprof"
	"os"
	"strconv"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/latest"
	"k8s.io/kubernetes/pkg/api/meta"
	"k8s.io/kubernetes/pkg/client"
	"k8s.io/kubernetes/pkg/client/clientcmd"
	clientcmdapi "k8s.io/kubernetes/pkg/client/clientcmd/api"
	"k8s.io/kubernetes/pkg/client/record"
	"k8s.io/kubernetes/pkg/healthz"
	"k8s.io/kubernetes/pkg/master"
	"k8s.io/kubernetes/pkg/master/ports"
	"k8s.io/kubernetes/pkg/tools"
	"k8s.io/kubernetes/pkg/util"
	schedulerbuilder "k8s.io/kubernetes/plugin/cmd/kube-scheduler/app"
	"k8s.io/kubernetes/plugin/pkg/scheduler"
	_ "k8s.io/kubernetes/plugin/pkg/scheduler/algorithmprovider"
	schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"
	latestschedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api/latest"
	"k8s.io/kubernetes/plugin/pkg/scheduler/factory"

	"k8s.io/kubernetes/plugin/pkg/vmturbo"
	"k8s.io/kubernetes/plugin/pkg/vmturbo/conversion"
	"k8s.io/kubernetes/plugin/pkg/vmturbo/metadata"
	"k8s.io/kubernetes/plugin/pkg/vmturbo/registry"
	"k8s.io/kubernetes/plugin/pkg/vmturbo/storage"
	etcdhelper "k8s.io/kubernetes/plugin/pkg/vmturbo/storage/etcd"

	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/spf13/pflag"
)

var (
	defaultSchedulerInstance *scheduler.Scheduler
)

// VMTServer has all the context and params needed to run a Scheduler
type VMTServer struct {
	Port                  int
	Address               net.IP
	Master                string
	MetaConfigPath        string
	Kubeconfig            string
	BindPodsQPS           float32
	BindPodsBurst         int
	EtcdServerList        []string
	EtcdCA                string
	EtcdClientCertificate string
	EtcdClientKey         string
	EtcdConfigFile        string
	EtcdPathPrefix        string
}

// NewVMTServer creates a new VMTServer with default parameters
func NewVMTServer() *VMTServer {
	s := VMTServer{
		Port:    ports.VMTPort,
		Address: net.ParseIP("127.0.0.1"),
	}
	return &s
}

// AddFlags adds flags for a specific VMTServer to the specified FlagSet
func (s *VMTServer) AddFlags(fs *pflag.FlagSet) {
	fs.IntVar(&s.Port, "port", s.Port, "The port that the scheduler's http service runs on")
	fs.StringVar(&s.Master, "master", s.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig)")
	fs.StringVar(&s.MetaConfigPath, "config-path", s.MetaConfigPath, "The path to the vmt config file.")
	fs.StringVar(&s.Kubeconfig, "kubeconfig", s.Kubeconfig, "Path to kubeconfig file with authorization and master location information.")
	fs.StringSliceVar(&s.EtcdServerList, "etcd-servers", s.EtcdServerList, "List of etcd servers to watch (http://ip:port), comma separated. Mutually exclusive with -etcd-config")
	fs.StringVar(&s.EtcdCA, "cacert", s.EtcdCA, "Path to etcd ca.")
	fs.StringVar(&s.EtcdClientCertificate, "client-cert", s.EtcdClientCertificate, "Path to etcd client certificate")
	fs.StringVar(&s.EtcdClientKey, "client-key", s.EtcdClientKey, "Path to etcd client key")
}

// Run runs the specified VMTServer.  This should never exit.
func (s *VMTServer) Run(_ []string) error {
	if s.Kubeconfig == "" && s.Master == "" {
		glog.Warningf("Neither --kubeconfig nor --master was specified.  Using default API client.  This might not work.")
	}

	glog.V(3).Infof("Master is %s", s.Master)

	if s.MetaConfigPath == "" {
		glog.Fatalf("The path to the VMT config file is not provided.Exiting...")
		os.Exit(1)
	}

	if (s.EtcdConfigFile != "" && len(s.EtcdServerList) != 0) || (s.EtcdConfigFile == "" && len(s.EtcdServerList) == 0) {
		glog.Fatalf("specify either --etcd-servers or --etcd-config")
	}

	// This creates a client, first loading any specified kubeconfig
	// file, and then overriding the Master flag, if non-empty.
	kubeconfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		&clientcmd.ClientConfigLoadingRules{ExplicitPath: s.Kubeconfig},
		&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: s.Master}}).ClientConfig()
	if err != nil {
		glog.Errorf("Error getting kubeconfig:  %s", err)
		return err
	}
	// This specifies the number and the max number of query per second to the api server.
	kubeconfig.QPS = 20.0
	kubeconfig.Burst = 30

	kubeClient, err := client.New(kubeconfig)
	if err != nil {
		glog.Fatalf("Invalid API configuration: %v", err)
	}

	// TODO not clear
	// go func() {
	// 	mux := http.NewServeMux()
	// 	healthz.InstallHandler(mux)
	// 	if s.EnableProfiling {
	// 		mux.HandleFunc("/debug/pprof/", pprof.Index)
	// 		mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
	// 		mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
	// 	}
	// 	mux.Handle("/metrics", prometheus.Handler())

	// 	server := &http.Server{
	// 		Addr:    net.JoinHostPort(s.Address.String(), strconv.Itoa(s.Port)),
	// 		Handler: mux,
	// 	}
	// 	glog.Fatal(server.ListenAndServe())
	// }()

	// serverAddr, targetType, nameOrAddress, targetIdentifier, password
	vmtMeta, err := metadata.NewVMTMeta(s.MetaConfigPath)
	if err != nil {
		glog.Errorf("Get error when loading configurations: %s", err)
		os.Exit(1)
	}
	glog.V(3).Infof("Finished loading configuration from %s", s.MetaConfigPath)

	etcdclientBuilder := etcdhelper.NewEtcdClientBuilder().ServerList(s.EtcdServerList).SetTransport(s.EtcdCA, s.EtcdClientCertificate, s.EtcdClientKey)
	etcdClient, err := etcdclientBuilder.CreateAndTest()
	if err != nil {
		glog.Errorf("Error creating etcd client instance for vmt service: %s", err)
		return err
	}

	s.EtcdPathPrefix = master.DefaultEtcdPathPrefix
	etcdStorage, err := newEtcd(etcdClient, latest.InterfacesFor, latest.Version, "", s.EtcdPathPrefix)
	if err != nil {
		glog.Warningf("Error creating etcd storage instance for vmt service: %s", err)
		return err
	}

	vmtConfig := vmturbo.NewVMTConfig(kubeClient, etcdStorage, vmtMeta)

	vmtService := vmturbo.NewVMTurboService(vmtConfig)

	vmtService.TurboScheduler.SetDefaultScheduler(defaultSchedulerInstance)

	vmtService.Run()

	select {}
}

func newEtcd(client tools.EtcdClient, interfacesFunc meta.VersionInterfacesFunc, defaultVersion, storageVersion, pathPrefix string) (etcdStorage storage.Storage, err error) {
	if storageVersion == "" {
		storageVersion = defaultVersion
	}

	master.NewEtcdStorage(client, interfacesFunc, storageVersion, pathPrefix)

	simpleCodec := conversion.NewSimpleCodec()
	simpleCodec.AddKnownTypes(&registry.VMTEvent{})
	simpleCodec.AddKnownTypes(&registry.VMTEventList{})
	return etcdhelper.NewEtcdStorage(client, simpleCodec, pathPrefix), nil
}

type DefaultK8sSchedulerServer struct {
	*schedulerbuilder.SchedulerServer
}

func NewDefaultK8sSchedulerServer(vmtServer *VMTServer) *DefaultK8sSchedulerServer {
	s := schedulerbuilder.SchedulerServer{
		Port:              ports.VMTPort,
		Address:           net.ParseIP("127.0.0.1"),
		AlgorithmProvider: factory.DefaultProvider,
	}
	return &DefaultK8sSchedulerServer{&s}
}

// The same method defined in scheduler server. Create config file for the default kubernetes scheduler.
func (s DefaultK8sSchedulerServer) createConfig(configFactory *factory.ConfigFactory) (*scheduler.Config, error) {
	var policy schedulerapi.Policy
	var configData []byte

	if _, err := os.Stat(s.PolicyConfigFile); err == nil {
		configData, err = ioutil.ReadFile(s.PolicyConfigFile)
		if err != nil {
			return nil, fmt.Errorf("Unable to read policy config: %v", err)
		}
		err = latestschedulerapi.Codec.DecodeInto(configData, &policy)
		if err != nil {
			return nil, fmt.Errorf("Invalid configuration: %v", err)
		}

		return configFactory.CreateFromConfig(policy)
	}

	// if the config file isn't provided, use the specified (or default) provider
	// check of algorithm provider is registered and fail fast
	_, err := factory.GetAlgorithmProvider(s.AlgorithmProvider)
	if err != nil {
		return nil, err
	}

	return configFactory.CreateFromProvider(s.AlgorithmProvider)
}

// Run runs the specified SchedulerServer.  This should never exit. Same code from schduler server.
func (s *DefaultK8sSchedulerServer) RunDefaultK8sScheduler(_ []string) error {
	if s.Kubeconfig == "" && s.Master == "" {
		glog.Warningf("Neither --kubeconfig nor --master was specified.  Using default API client.  This might not work.")
	}

	// This creates a client, first loading any specified kubeconfig
	// file, and then overriding the Master flag, if non-empty.
	kubeconfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		&clientcmd.ClientConfigLoadingRules{ExplicitPath: s.Kubeconfig},
		&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: s.Master}}).ClientConfig()
	if err != nil {
		return err
	}
	kubeconfig.QPS = 20.0
	kubeconfig.Burst = 30

	kubeClient, err := client.New(kubeconfig)
	if err != nil {
		glog.Fatalf("Invalid API configuration: %v", err)
	}

	go func() {
		mux := http.NewServeMux()
		healthz.InstallHandler(mux)
		if s.EnableProfiling {
			mux.HandleFunc("/debug/pprof/", pprof.Index)
			mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
			mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
		}
		mux.Handle("/metrics", prometheus.Handler())

		server := &http.Server{
			Addr:    net.JoinHostPort(s.Address.String(), strconv.Itoa(s.Port)),
			Handler: mux,
		}
		glog.Fatal(server.ListenAndServe())
	}()

	configFactory := factory.NewConfigFactory(kubeClient, util.NewTokenBucketRateLimiter(s.BindPodsQPS, s.BindPodsBurst))
	config, err := s.createConfig(configFactory)
	if err != nil {
		glog.Fatalf("Failed to create scheduler configuration: %v", err)
	}

	eventBroadcaster := record.NewBroadcaster()
	config.Recorder = eventBroadcaster.NewRecorder(api.EventSource{Component: "scheduler"})
	eventBroadcaster.StartLogging(glog.Infof)
	eventBroadcaster.StartRecordingToSink(kubeClient.Events(""))

	sched := scheduler.New(config)
	// vmturbo.SetSchedulerInstance(sched)

	defaultSchedulerInstance = sched

	select {}
}
<commit_msg>Added Code To Make Sure Default Scheduler Is Set When Kubeturbo Starts<commit_after>/*
Copyright 2014 The Kubernetes Authors 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 app implements a Server object for running the scheduler.
package app

import (
	"fmt"
	"io/ioutil"
	"math"
	"net"
	"net/http"
	"net/http/pprof"
	"os"
	"strconv"
	"time"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/latest"
	"k8s.io/kubernetes/pkg/api/meta"
	"k8s.io/kubernetes/pkg/client"
	"k8s.io/kubernetes/pkg/client/clientcmd"
	clientcmdapi "k8s.io/kubernetes/pkg/client/clientcmd/api"
	"k8s.io/kubernetes/pkg/client/record"
	"k8s.io/kubernetes/pkg/healthz"
	"k8s.io/kubernetes/pkg/master"
	"k8s.io/kubernetes/pkg/master/ports"
	"k8s.io/kubernetes/pkg/tools"
	"k8s.io/kubernetes/pkg/util"
	schedulerbuilder "k8s.io/kubernetes/plugin/cmd/kube-scheduler/app"
	"k8s.io/kubernetes/plugin/pkg/scheduler"
	_ "k8s.io/kubernetes/plugin/pkg/scheduler/algorithmprovider"
	schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"
	latestschedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api/latest"
	"k8s.io/kubernetes/plugin/pkg/scheduler/factory"

	"k8s.io/kubernetes/plugin/pkg/vmturbo"
	"k8s.io/kubernetes/plugin/pkg/vmturbo/conversion"
	"k8s.io/kubernetes/plugin/pkg/vmturbo/metadata"
	"k8s.io/kubernetes/plugin/pkg/vmturbo/registry"
	"k8s.io/kubernetes/plugin/pkg/vmturbo/storage"
	etcdhelper "k8s.io/kubernetes/plugin/pkg/vmturbo/storage/etcd"

	"github.com/golang/glog"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/spf13/pflag"
)

var (
	defaultSchedulerInstance *scheduler.Scheduler
)

// VMTServer has all the context and params needed to run a Scheduler
type VMTServer struct {
	Port                  int
	Address               net.IP
	Master                string
	MetaConfigPath        string
	Kubeconfig            string
	BindPodsQPS           float32
	BindPodsBurst         int
	EtcdServerList        []string
	EtcdCA                string
	EtcdClientCertificate string
	EtcdClientKey         string
	EtcdConfigFile        string
	EtcdPathPrefix        string
}

// NewVMTServer creates a new VMTServer with default parameters
func NewVMTServer() *VMTServer {
	s := VMTServer{
		Port:    ports.VMTPort,
		Address: net.ParseIP("127.0.0.1"),
	}
	return &s
}

// AddFlags adds flags for a specific VMTServer to the specified FlagSet
func (s *VMTServer) AddFlags(fs *pflag.FlagSet) {
	fs.IntVar(&s.Port, "port", s.Port, "The port that the scheduler's http service runs on")
	fs.StringVar(&s.Master, "master", s.Master, "The address of the Kubernetes API server (overrides any value in kubeconfig)")
	fs.StringVar(&s.MetaConfigPath, "config-path", s.MetaConfigPath, "The path to the vmt config file.")
	fs.StringVar(&s.Kubeconfig, "kubeconfig", s.Kubeconfig, "Path to kubeconfig file with authorization and master location information.")
	fs.StringSliceVar(&s.EtcdServerList, "etcd-servers", s.EtcdServerList, "List of etcd servers to watch (http://ip:port), comma separated. Mutually exclusive with -etcd-config")
	fs.StringVar(&s.EtcdCA, "cacert", s.EtcdCA, "Path to etcd ca.")
	fs.StringVar(&s.EtcdClientCertificate, "client-cert", s.EtcdClientCertificate, "Path to etcd client certificate")
	fs.StringVar(&s.EtcdClientKey, "client-key", s.EtcdClientKey, "Path to etcd client key")
}

// Run runs the specified VMTServer.  This should never exit.
func (s *VMTServer) Run(_ []string) error {
	if s.Kubeconfig == "" && s.Master == "" {
		glog.Warningf("Neither --kubeconfig nor --master was specified.  Using default API client.  This might not work.")
	}

	glog.V(3).Infof("Master is %s", s.Master)

	if s.MetaConfigPath == "" {
		glog.Fatalf("The path to the VMT config file is not provided.Exiting...")
		os.Exit(1)
	}

	if (s.EtcdConfigFile != "" && len(s.EtcdServerList) != 0) || (s.EtcdConfigFile == "" && len(s.EtcdServerList) == 0) {
		glog.Fatalf("specify either --etcd-servers or --etcd-config")
	}

	// This creates a client, first loading any specified kubeconfig
	// file, and then overriding the Master flag, if non-empty.
	kubeconfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		&clientcmd.ClientConfigLoadingRules{ExplicitPath: s.Kubeconfig},
		&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: s.Master}}).ClientConfig()
	if err != nil {
		glog.Errorf("Error getting kubeconfig:  %s", err)
		return err
	}
	// This specifies the number and the max number of query per second to the api server.
	kubeconfig.QPS = 20.0
	kubeconfig.Burst = 30

	kubeClient, err := client.New(kubeconfig)
	if err != nil {
		glog.Fatalf("Invalid API configuration: %v", err)
	}

	// TODO not clear
	// go func() {
	// 	mux := http.NewServeMux()
	// 	healthz.InstallHandler(mux)
	// 	if s.EnableProfiling {
	// 		mux.HandleFunc("/debug/pprof/", pprof.Index)
	// 		mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
	// 		mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
	// 	}
	// 	mux.Handle("/metrics", prometheus.Handler())

	// 	server := &http.Server{
	// 		Addr:    net.JoinHostPort(s.Address.String(), strconv.Itoa(s.Port)),
	// 		Handler: mux,
	// 	}
	// 	glog.Fatal(server.ListenAndServe())
	// }()

	// serverAddr, targetType, nameOrAddress, targetIdentifier, password
	vmtMeta, err := metadata.NewVMTMeta(s.MetaConfigPath)
	if err != nil {
		glog.Errorf("Get error when loading configurations: %s", err)
		os.Exit(1)
	}
	glog.V(3).Infof("Finished loading configuration from %s", s.MetaConfigPath)

	etcdclientBuilder := etcdhelper.NewEtcdClientBuilder().ServerList(s.EtcdServerList).SetTransport(s.EtcdCA, s.EtcdClientCertificate, s.EtcdClientKey)
	etcdClient, err := etcdclientBuilder.CreateAndTest()
	if err != nil {
		glog.Errorf("Error creating etcd client instance for vmt service: %s", err)
		return err
	}

	s.EtcdPathPrefix = master.DefaultEtcdPathPrefix
	etcdStorage, err := newEtcd(etcdClient, latest.InterfacesFor, latest.Version, "", s.EtcdPathPrefix)
	if err != nil {
		glog.Warningf("Error creating etcd storage instance for vmt service: %s", err)
		return err
	}

	vmtConfig := vmturbo.NewVMTConfig(kubeClient, etcdStorage, vmtMeta)

	vmtService := vmturbo.NewVMTurboService(vmtConfig)

	// Make sure default scheduler is set. If certain time is passed, then there is a fatal error.
	timeDelayFactor := 0
	for defaultSchedulerInstance == nil && timeDelayFactor < 10 {
		glog.V(3).Infof("Default scheduler is not set yet")
		time.Sleep(time.Millisecond * 100 * time.Duration(math.Pow(2, float64(timeDelayFactor))))
		timeDelayFactor += 1
	}
	if defaultSchedulerInstance == nil {
		glog.Fatalf("Failed to set Default Scheduler. Exiting..")
	}

	vmtService.TurboScheduler.SetDefaultScheduler(defaultSchedulerInstance)

	vmtService.Run()

	select {}
}

func newEtcd(client tools.EtcdClient, interfacesFunc meta.VersionInterfacesFunc, defaultVersion, storageVersion, pathPrefix string) (etcdStorage storage.Storage, err error) {
	if storageVersion == "" {
		storageVersion = defaultVersion
	}

	master.NewEtcdStorage(client, interfacesFunc, storageVersion, pathPrefix)

	simpleCodec := conversion.NewSimpleCodec()
	simpleCodec.AddKnownTypes(&registry.VMTEvent{})
	simpleCodec.AddKnownTypes(&registry.VMTEventList{})
	return etcdhelper.NewEtcdStorage(client, simpleCodec, pathPrefix), nil
}

type DefaultK8sSchedulerServer struct {
	*schedulerbuilder.SchedulerServer
}

func NewDefaultK8sSchedulerServer(vmtServer *VMTServer) *DefaultK8sSchedulerServer {
	s := schedulerbuilder.SchedulerServer{
		Port:              ports.VMTPort,
		Address:           net.ParseIP("127.0.0.1"),
		AlgorithmProvider: factory.DefaultProvider,
	}
	return &DefaultK8sSchedulerServer{&s}
}

// The same method defined in scheduler server. Create config file for the default kubernetes scheduler.
func (s DefaultK8sSchedulerServer) createConfig(configFactory *factory.ConfigFactory) (*scheduler.Config, error) {
	var policy schedulerapi.Policy
	var configData []byte

	if _, err := os.Stat(s.PolicyConfigFile); err == nil {
		configData, err = ioutil.ReadFile(s.PolicyConfigFile)
		if err != nil {
			return nil, fmt.Errorf("Unable to read policy config: %v", err)
		}
		err = latestschedulerapi.Codec.DecodeInto(configData, &policy)
		if err != nil {
			return nil, fmt.Errorf("Invalid configuration: %v", err)
		}

		return configFactory.CreateFromConfig(policy)
	}

	// if the config file isn't provided, use the specified (or default) provider
	// check of algorithm provider is registered and fail fast
	_, err := factory.GetAlgorithmProvider(s.AlgorithmProvider)
	if err != nil {
		return nil, err
	}

	return configFactory.CreateFromProvider(s.AlgorithmProvider)
}

// Run runs the specified SchedulerServer.  This should never exit. Same code from schduler server.
func (s *DefaultK8sSchedulerServer) RunDefaultK8sScheduler(_ []string) error {
	if s.Kubeconfig == "" && s.Master == "" {
		glog.Warningf("Neither --kubeconfig nor --master was specified.  Using default API client.  This might not work.")
	}

	// This creates a client, first loading any specified kubeconfig
	// file, and then overriding the Master flag, if non-empty.
	kubeconfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		&clientcmd.ClientConfigLoadingRules{ExplicitPath: s.Kubeconfig},
		&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: s.Master}}).ClientConfig()
	if err != nil {
		return err
	}
	kubeconfig.QPS = 20.0
	kubeconfig.Burst = 30

	kubeClient, err := client.New(kubeconfig)
	if err != nil {
		glog.Fatalf("Invalid API configuration: %v", err)
	}

	go func() {
		mux := http.NewServeMux()
		healthz.InstallHandler(mux)
		if s.EnableProfiling {
			mux.HandleFunc("/debug/pprof/", pprof.Index)
			mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
			mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
		}
		mux.Handle("/metrics", prometheus.Handler())

		server := &http.Server{
			Addr:    net.JoinHostPort(s.Address.String(), strconv.Itoa(s.Port)),
			Handler: mux,
		}
		glog.Fatal(server.ListenAndServe())
	}()

	configFactory := factory.NewConfigFactory(kubeClient, util.NewTokenBucketRateLimiter(s.BindPodsQPS, s.BindPodsBurst))
	config, err := s.createConfig(configFactory)
	if err != nil {
		glog.Fatalf("Failed to create scheduler configuration: %v", err)
	}

	eventBroadcaster := record.NewBroadcaster()
	config.Recorder = eventBroadcaster.NewRecorder(api.EventSource{Component: "scheduler"})
	eventBroadcaster.StartLogging(glog.Infof)
	eventBroadcaster.StartRecordingToSink(kubeClient.Events(""))

	sched := scheduler.New(config)
	// vmturbo.SetSchedulerInstance(sched)

	defaultSchedulerInstance = sched

	select {}
}
<|endoftext|>


<commit_before>package events

import (
	"crypto/hmac"
	"crypto/sha256"
	"fmt"
	"net/url"
	"time"
)

var OldEventLinkHMAC string

func OldEventToolLink(username string) string {
	mac := hmac.New(sha256.New, []byte(OldEventLinkHMAC))
	t := time.Now()
	fmt.Fprintln(mac, username, t.Unix())
	return fmt.Sprintf(
		"https://team.fofgaming.com/rest/login?username=%s&t=%d&signature=%s",
		url.QueryEscape(username),
		t.Unix(),
		fmt.Sprintf("%x", mac.Sum(nil)),
	)
}
<commit_msg>remove schema for http/s purposes<commit_after>package events

import (
	"crypto/hmac"
	"crypto/sha256"
	"fmt"
	"net/url"
	"time"
)

var OldEventLinkHMAC string

func OldEventToolLink(username string) string {
	mac := hmac.New(sha256.New, []byte(OldEventLinkHMAC))
	t := time.Now()
	fmt.Fprintln(mac, username, t.Unix())
	return fmt.Sprintf(
		"//team.fofgaming.com/rest/login?username=%s&t=%d&signature=%s",
		url.QueryEscape(username),
		t.Unix(),
		fmt.Sprintf("%x", mac.Sum(nil)),
	)
}
<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"strconv"
	"strings"
)

// GCPCloudRunDeployImage builds arguments for running a service on
// Cloud Run given an Artifact Registry image.
func GCPCloudRunDeployImage(f ConfigFile, image GCPArtifactRegistryContainerImage) []string {

	var (
		// Google Cloud Run Service Name
		serviceName = f.Config.GCP.CloudRun.ServiceName
		// Google Cloud SQL Instance Name
		gcpCloudSQLInstanceConnectionName = f.Config.GCP.CloudSQL.InstanceConnectionName
		// postgresql database name
	)

	args := []string{"run", "deploy", serviceName, "--image", image.String(), "--platform", "managed", "--no-allow-unauthenticated"}

	args = append(args, "--add-cloudsql-instances", gcpCloudSQLInstanceConnectionName)

	icn := fmt.Sprintf(`INSTANCE-CONNECTION-NAME=%s`, gcpCloudSQLInstanceConnectionName)
	dbName := fmt.Sprintf(`%s=%s`, dbNameEnv, f.Config.Database.Name)
	dbUser := fmt.Sprintf(`%s=%s`, dbUserEnv, f.Config.Database.User)
	dbPassword := fmt.Sprintf(`%s=%s`, dbPasswordEnv, f.Config.Database.Password)
	dbHost := fmt.Sprintf(`%s=%s`, dbHostEnv, f.Config.Database.Host)
	dbPort := fmt.Sprintf(`%s=%s`, dbPortEnv, strconv.Itoa(f.Config.Database.Port))
	dbSearchPath := fmt.Sprintf(`%s=%s`, dbSearchPathEnv, f.Config.Database.SearchPath)
	encryptKey := fmt.Sprintf(`%s=%s`, encryptKeyEnv, f.Config.EncryptionKey)

	envVars := []string{icn, dbName, dbUser, dbPassword, dbHost, dbPort, dbSearchPath, encryptKey}

	args = append(args, "--set-env-vars", strings.Join(envVars, ","))

	return args
}

// GCPArtifactRegistryContainerImage defines a GCP Artifact Registry
// build image according to https://cloud.google.com/artifact-registry/docs/docker/names
// The String method prints the build string needed to build to
// Artifact Registry using gcloud as well as deploy it to Cloud Run.
type GCPArtifactRegistryContainerImage struct {
	ProjectID          string
	RepositoryLocation string
	RepositoryName     string
	ImageName          string
	ImageTag           string
}

// String outputs the Google Artifact Registry image name.
// LOCATION-docker.pkg.dev/PROJECT-ID/REPOSITORY/IMAGE:TAG
func (i GCPArtifactRegistryContainerImage) String() string {
	if i.ImageTag != "" {
		return fmt.Sprintf("%s-docker.pkg.dev/%s/%s/%s:%s", i.RepositoryLocation, i.ProjectID, i.RepositoryName, i.ImageName, i.ImageTag)
	}
	return fmt.Sprintf("%s-docker.pkg.dev/%s/%s/%s", i.RepositoryLocation, i.ProjectID, i.RepositoryName, i.ImageName)
}
<commit_msg>updated env var names<commit_after>package command

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/gilcrest/go-api-basic/datastore"
)

// GCPCloudRunDeployImage builds arguments for running a service on
// Cloud Run given an Artifact Registry image.
func GCPCloudRunDeployImage(f ConfigFile, image GCPArtifactRegistryContainerImage) []string {

	var (
		// Google Cloud Run Service Name
		serviceName = f.Config.GCP.CloudRun.ServiceName
		// Google Cloud SQL Instance Name
		gcpCloudSQLInstanceConnectionName = f.Config.GCP.CloudSQL.InstanceConnectionName
		// postgresql database name
	)

	args := []string{"run", "deploy", serviceName, "--image", image.String(), "--platform", "managed", "--no-allow-unauthenticated"}

	args = append(args, "--add-cloudsql-instances", gcpCloudSQLInstanceConnectionName)

	icn := fmt.Sprintf(`INSTANCE-CONNECTION-NAME=%s`, gcpCloudSQLInstanceConnectionName)
	dbName := fmt.Sprintf(`%s=%s`, datastore.DBNameEnv, f.Config.Database.Name)
	dbUser := fmt.Sprintf(`%s=%s`, datastore.DBUserEnv, f.Config.Database.User)
	dbPassword := fmt.Sprintf(`%s=%s`, datastore.DBPasswordEnv, f.Config.Database.Password)
	dbHost := fmt.Sprintf(`%s=%s`, datastore.DBHostEnv, f.Config.Database.Host)
	dbPort := fmt.Sprintf(`%s=%s`, datastore.DBPortEnv, strconv.Itoa(f.Config.Database.Port))
	dbSearchPath := fmt.Sprintf(`%s=%s`, datastore.DBSearchPathEnv, f.Config.Database.SearchPath)
	encryptKey := fmt.Sprintf(`%s=%s`, encryptKeyEnv, f.Config.EncryptionKey)

	envVars := []string{icn, dbName, dbUser, dbPassword, dbHost, dbPort, dbSearchPath, encryptKey}

	args = append(args, "--set-env-vars", strings.Join(envVars, ","))

	return args
}

// GCPArtifactRegistryContainerImage defines a GCP Artifact Registry
// build image according to https://cloud.google.com/artifact-registry/docs/docker/names
// The String method prints the build string needed to build to
// Artifact Registry using gcloud as well as deploy it to Cloud Run.
type GCPArtifactRegistryContainerImage struct {
	ProjectID          string
	RepositoryLocation string
	RepositoryName     string
	ImageName          string
	ImageTag           string
}

// String outputs the Google Artifact Registry image name.
// LOCATION-docker.pkg.dev/PROJECT-ID/REPOSITORY/IMAGE:TAG
func (i GCPArtifactRegistryContainerImage) String() string {
	if i.ImageTag != "" {
		return fmt.Sprintf("%s-docker.pkg.dev/%s/%s/%s:%s", i.RepositoryLocation, i.ProjectID, i.RepositoryName, i.ImageName, i.ImageTag)
	}
	return fmt.Sprintf("%s-docker.pkg.dev/%s/%s/%s", i.RepositoryLocation, i.ProjectID, i.RepositoryName, i.ImageName)
}
<|endoftext|>