<commit_before>// Publish a fixed report.
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"time"

	"github.com/ugorji/go/codec"

	"github.com/weaveworks/scope/common/xfer"
	"github.com/weaveworks/scope/probe/appclient"
	"github.com/weaveworks/scope/report"
)

func main() {
	var (
		publish         = flag.String("publish", fmt.Sprintf("localhost:%d", xfer.AppPort), "publish target")
		publishInterval = flag.Duration("publish.interval", 1*time.Second, "publish (output) interval")
		publishToken    = flag.String("publish.token", "fixprobe", "publish token, for if we are talking to the service")
		publishID       = flag.String("publish.id", "fixprobe", "publisher ID used to identify publishers")
	)
	flag.Parse()

	if len(flag.Args()) != 1 {
		log.Fatal("usage: fixprobe [--args] report.json")
	}

	b, err := ioutil.ReadFile(flag.Arg(0))
	if err != nil {
		log.Fatal(err)
	}

	var fixedReport report.Report
	decoder := codec.NewDecoderBytes(b, &codec.JsonHandle{})
	if err := decoder.Decode(&fixedReport); err != nil {
		log.Fatal(err)
	}

	client, err := appclient.NewAppClient(appclient.ProbeConfig{
		Token:    *publishToken,
		ProbeID:  *publishID,
		Insecure: false,
	}, *publish, *publish, nil)
	if err != nil {
		log.Fatal(err)
	}

	rp := appclient.NewReportPublisher(client)
	for range time.Tick(*publishInterval) {
		rp.Publish(fixedReport)
	}
}
<commit_msg>Add ability for fixprobe to send the report from test/fixture<commit_after>// Publish a fixed report.
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"time"

	"github.com/ugorji/go/codec"

	"github.com/weaveworks/scope/common/xfer"
	"github.com/weaveworks/scope/probe/appclient"
	"github.com/weaveworks/scope/report"
	"github.com/weaveworks/scope/test/fixture"
)

func main() {
	var (
		publish         = flag.String("publish", fmt.Sprintf("localhost:%d", xfer.AppPort), "publish target")
		publishInterval = flag.Duration("publish.interval", 1*time.Second, "publish (output) interval")
		publishToken    = flag.String("publish.token", "fixprobe", "publish token, for if we are talking to the service")
		publishID       = flag.String("publish.id", "fixprobe", "publisher ID used to identify publishers")
		useFixture      = flag.Bool("fixture", false, "Use the embedded fixture report.")
	)
	flag.Parse()

	if len(flag.Args()) != 1 && !*useFixture {
		log.Fatal("usage: fixprobe [--args] report.json")
	}

	var fixedReport report.Report
	if *useFixture {
		fixedReport = fixture.Report
	} else {
		b, err := ioutil.ReadFile(flag.Arg(0))
		if err != nil {
			log.Fatal(err)
		}

		decoder := codec.NewDecoderBytes(b, &codec.JsonHandle{})
		if err := decoder.Decode(&fixedReport); err != nil {
			log.Fatal(err)
		}
	}

	client, err := appclient.NewAppClient(appclient.ProbeConfig{
		Token:    *publishToken,
		ProbeID:  *publishID,
		Insecure: false,
	}, *publish, *publish, nil)
	if err != nil {
		log.Fatal(err)
	}

	rp := appclient.NewReportPublisher(client)
	for range time.Tick(*publishInterval) {
		rp.Publish(fixedReport)
	}
}
<|endoftext|>


<commit_before>package rardecode

import (
	"bytes"
	"encoding/binary"
	"hash/crc32"
	"io"
)

const (
	fileSize = 0x1000000

	vmGlobalAddr      = 0x3C000
	vmGlobalSize      = 0x02000
	vmFixedGlobalSize = 0x40
)

// v3Filter is the interface type for RAR V3 filters.
// v3Filter performs the same function as the filter type, except that it also takes
// the initial register values r, and global data as input for the RAR V3 VM.
type v3Filter func(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error)

var (
	// standardV3Filters is a list of known filters. We can replace the use of a vm
	// filter with a custom filter function.
	standardV3Filters = []struct {
		crc uint32   // crc of code byte slice for filter
		len int      // length of code byte slice for filter
		f   v3Filter // replacement filter function
	}{
		{0xad576887, 53, e8FilterV3},
		{0x3cd7e57e, 57, e8e9FilterV3},
		{0x0e06077d, 29, deltaFilterV3},
		{0x1c2c5dc8, 149, filterRGBV3},
		{0xbc85e701, 216, filterAudioV3},
	}
)

func filterE8(c byte, v5 bool, buf []byte, offset int64) ([]byte, error) {
	off := int32(offset)
	for b := buf; len(b) >= 5; {
		ch := b[0]
		b = b[1:]
		off++
		if ch != 0xe8 && ch != c {
			continue
		}
		if v5 {
			off %= fileSize
		}
		addr := int32(binary.LittleEndian.Uint32(b))
		if addr < 0 {
			if addr+off >= 0 {
				binary.LittleEndian.PutUint32(b, uint32(addr+fileSize))
			}
		} else if addr < fileSize {
			binary.LittleEndian.PutUint32(b, uint32(addr-off))
		}
		off += 4
		b = b[4:]
	}
	return buf, nil
}

func e8FilterV3(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	return filterE8(0xe8, false, buf, offset)
}

func e8e9FilterV3(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	return filterE8(0xe9, false, buf, offset)
}

func filterDelta(n int, buf []byte) ([]byte, error) {
	var res []byte
	l := len(buf)
	if cap(buf) >= 2*l {
		res = buf[l : 2*l] // use unused capacity
	} else {
		res = make([]byte, l, 2*l)
	}

	i := 0
	for j := 0; j < n; j++ {
		var c byte
		for k := j; k < len(res); k += n {
			c -= buf[i]
			i++
			res[k] = c
		}
	}
	return res, nil
}

func deltaFilterV3(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	return filterDelta(int(r[0]), buf)
}

func abs(n int) int {
	if n < 0 {
		n = -n
	}
	return n
}

func filterRGBV3(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	width := int(r[0] - 3)
	posR := int(r[1])
	if posR < 0 || width < 0 {
		return buf, nil
	}

	var res []byte
	l := len(buf)
	if cap(buf) >= 2*l {
		res = buf[l : 2*l] // use unused capacity
	} else {
		res = make([]byte, l, 2*l)
	}

	for c := 0; c < 3; c++ {
		var prevByte int
		for i := c; i < len(res); i += 3 {
			var predicted int
			upperPos := i - width
			if upperPos >= 3 {
				upperByte := int(res[upperPos])
				upperLeftByte := int(res[upperPos-3])
				predicted = prevByte + upperByte - upperLeftByte
				pa := abs(predicted - prevByte)
				pb := abs(predicted - upperByte)
				pc := abs(predicted - upperLeftByte)
				if pa <= pb && pa <= pc {
					predicted = prevByte
				} else if pb <= pc {
					predicted = upperByte
				} else {
					predicted = upperLeftByte
				}
			} else {
				predicted = prevByte
			}
			prevByte = (predicted - int(buf[0])) & 0xFF
			res[i] = uint8(prevByte)
			buf = buf[1:]
		}

	}
	for i := posR; i < len(res)-2; i += 3 {
		c := res[i+1]
		res[i] += c
		res[i+2] += c
	}
	return res, nil
}

func filterAudioV3(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	var res []byte
	l := len(buf)
	if cap(buf) >= 2*l {
		res = buf[l : 2*l] // use unused capacity
	} else {
		res = make([]byte, l, 2*l)
	}

	chans := int(r[0])
	for c := 0; c < chans; c++ {
		var prevByte, byteCount int
		var diff [7]int
		var d, k [3]int

		for i := c; i < len(res); i += chans {
			predicted := prevByte<<3 + k[0]*d[0] + k[1]*d[1] + k[2]*d[2]
			predicted = int(int8(predicted >> 3))

			curByte := int(int8(buf[0]))
			buf = buf[1:]
			predicted -= curByte
			res[i] = uint8(predicted)

			dd := curByte << 3
			diff[0] += abs(dd)
			diff[1] += abs(dd - d[0])
			diff[2] += abs(dd + d[0])
			diff[3] += abs(dd - d[1])
			diff[4] += abs(dd + d[1])
			diff[5] += abs(dd - d[2])
			diff[6] += abs(dd + d[2])

			prevDelta := int(int8(predicted - prevByte))
			prevByte = predicted
			d[2] = d[1]
			d[1] = prevDelta - d[0]
			d[0] = prevDelta

			if byteCount&0x1f == 0 {
				min := diff[0]
				diff[0] = 0
				n := 0
				for j := 1; j < len(diff); j++ {
					if diff[j] < min {
						min = diff[j]
						n = j
					}
					diff[j] = 0
				}
				n--
				if n >= 0 {
					m := n / 2
					if n%2 == 0 {
						if k[m] >= -16 {
							k[m]--
						}
					} else {
						if k[m] < 16 {
							k[m]++
						}
					}
				}
			}
			byteCount++
		}

	}
	return res, nil
}

func filterArm(buf []byte, offset int64) ([]byte, error) {
	for i := 0; len(buf)-i > 3; i += 4 {
		if buf[i+3] == 0xeb {
			n := uint(buf[i])
			n += uint(buf[i+1]) * 0x100
			n += uint(buf[i+2]) * 0x10000
			n -= (uint(offset) + uint(i)) / 4
			buf[i] = byte(n)
			buf[i+1] = byte(n >> 8)
			buf[i+2] = byte(n >> 16)
		}
	}
	return buf, nil
}

type vmFilter struct {
	execCount uint32
	global    []byte
	static    []byte
	code      []command
}

// execute implements v3filter type for VM based RAR 3 filters.
func (f *vmFilter) execute(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	if len(buf) > vmGlobalAddr {
		return buf, errInvalidFilter
	}
	v := newVM(buf)

	// register setup
	v.r[3] = vmGlobalAddr
	v.r[4] = uint32(len(buf))
	v.r[5] = f.execCount
	for i, n := range r {
		v.r[i] = n
	}

	// vm global data memory block
	vg := v.m[vmGlobalAddr : vmGlobalAddr+vmGlobalSize]

	// initialize fixed global memory
	for i, n := range v.r[:vmRegs-1] {
		binary.LittleEndian.PutUint32(vg[i*4:], n)
	}
	binary.LittleEndian.PutUint32(vg[0x1c:], uint32(len(buf)))
	binary.LittleEndian.PutUint64(vg[0x24:], uint64(offset))
	binary.LittleEndian.PutUint32(vg[0x2c:], f.execCount)

	// registers
	v.r[6] = uint32(offset)

	// copy program global memory
	var n int
	if len(f.global) > 0 {
		n = copy(vg[vmFixedGlobalSize:], f.global) // use saved global instead
	} else {
		n = copy(vg[vmFixedGlobalSize:], global)
	}
	copy(vg[vmFixedGlobalSize+n:], f.static)

	v.execute(f.code)

	f.execCount++

	// keep largest global buffer
	if cap(global) > cap(f.global) {
		f.global = global[:0]
	} else if len(f.global) > 0 {
		f.global = f.global[:0]
	}

	// check for global data to be saved for next program execution
	globalSize := binary.LittleEndian.Uint32(vg[0x30:])
	if globalSize > 0 {
		if globalSize > vmGlobalSize-vmFixedGlobalSize {
			globalSize = vmGlobalSize - vmFixedGlobalSize
		}
		if cap(f.global) < int(globalSize) {
			f.global = make([]byte, globalSize)
		} else {
			f.global = f.global[:globalSize]
		}
		copy(f.global, vg[vmFixedGlobalSize:])
	}

	// find program output
	length := binary.LittleEndian.Uint32(vg[0x1c:]) & vmMask
	start := binary.LittleEndian.Uint32(vg[0x20:]) & vmMask
	if start+length > vmSize {
		// TODO: error
		start = 0
		length = 0
	}
	if start != 0 && cap(v.m) > cap(buf) {
		// Initial buffer was to small for vm.
		// Copy output to beginning of vm memory so that decodeReader
		// will re-use the newly allocated vm memory and we will not
		// have to reallocate again next time.
		copy(v.m, v.m[start:start+length])
		start = 0
	}
	return v.m[start : start+length], nil
}

// getV3Filter returns a V3 filter function from a code byte slice.
func getV3Filter(code []byte) (v3Filter, error) {
	// check if filter is a known standard filter
	c := crc32.ChecksumIEEE(code)
	for _, f := range standardV3Filters {
		if f.crc == c && f.len == len(code) {
			return f.f, nil
		}
	}

	// create new vm filter
	f := new(vmFilter)
	r := newRarBitReader(bytes.NewReader(code[1:])) // skip first xor byte check

	// read static data
	n, err := r.readBits(1)
	if err != nil {
		return nil, err
	}
	if n > 0 {
		m, err := r.readUint32()
		if err != nil {
			return nil, err
		}
		f.static = make([]byte, m+1)
		err = r.readFull(f.static)
		if err != nil {
			return nil, err
		}
	}

	f.code, err = readCommands(r)
	if err == io.EOF {
		err = nil
	}

	return f.execute, err
}
<commit_msg>add native implementation of itanium filter.<commit_after>package rardecode

import (
	"bytes"
	"encoding/binary"
	"hash/crc32"
	"io"
)

const (
	fileSize = 0x1000000

	vmGlobalAddr      = 0x3C000
	vmGlobalSize      = 0x02000
	vmFixedGlobalSize = 0x40

	maxUint32 = 1<<32 - 1
)

// v3Filter is the interface type for RAR V3 filters.
// v3Filter performs the same function as the filter type, except that it also takes
// the initial register values r, and global data as input for the RAR V3 VM.
type v3Filter func(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error)

var (
	// standardV3Filters is a list of known filters. We can replace the use of a vm
	// filter with a custom filter function.
	standardV3Filters = []struct {
		crc uint32   // crc of code byte slice for filter
		len int      // length of code byte slice for filter
		f   v3Filter // replacement filter function
	}{
		{0xad576887, 53, e8FilterV3},
		{0x3cd7e57e, 57, e8e9FilterV3},
		{0x3769893f, 120, itaniumFilterV3},
		{0x0e06077d, 29, deltaFilterV3},
		{0x1c2c5dc8, 149, filterRGBV3},
		{0xbc85e701, 216, filterAudioV3},
	}

	// itanium filter byte masks
	byteMask = []int{4, 4, 6, 6, 0, 0, 7, 7, 4, 4, 0, 0, 4, 4, 0, 0}
)

func filterE8(c byte, v5 bool, buf []byte, offset int64) ([]byte, error) {
	off := int32(offset)
	for b := buf; len(b) >= 5; {
		ch := b[0]
		b = b[1:]
		off++
		if ch != 0xe8 && ch != c {
			continue
		}
		if v5 {
			off %= fileSize
		}
		addr := int32(binary.LittleEndian.Uint32(b))
		if addr < 0 {
			if addr+off >= 0 {
				binary.LittleEndian.PutUint32(b, uint32(addr+fileSize))
			}
		} else if addr < fileSize {
			binary.LittleEndian.PutUint32(b, uint32(addr-off))
		}
		off += 4
		b = b[4:]
	}
	return buf, nil
}

func e8FilterV3(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	return filterE8(0xe8, false, buf, offset)
}

func e8e9FilterV3(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	return filterE8(0xe9, false, buf, offset)
}

func getBits(buf []byte, pos, count uint) uint32 {
	n := binary.LittleEndian.Uint32(buf[pos/8:])
	n >>= pos & 7
	mask := uint32(maxUint32) >> (32 - count)
	return n & mask
}

func setBits(buf []byte, pos, count uint, bits uint32) {
	mask := uint32(maxUint32) >> (32 - count)
	mask <<= pos & 7
	bits <<= pos & 7
	n := binary.LittleEndian.Uint32(buf[pos/8:])
	n = (n & ^mask) | (bits & mask)
	binary.LittleEndian.PutUint32(buf[pos/8:], n)
}

func itaniumFilterV3(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	fileOffset := uint32(offset) >> 4

	for b := buf; len(b) > 21; b = b[16:] {
		c := int(b[0]&0x1f) - 0x10
		if c >= 0 {
			mask := byteMask[c]
			if mask != 0 {
				for i := uint(0); i <= 2; i++ {
					if mask&(1<<i) == 0 {
						continue
					}
					pos := i*41 + 18
					if getBits(b, pos+24, 4) == 5 {
						n := getBits(b, pos, 20)
						n -= fileOffset
						setBits(b, pos, 20, n)
					}
				}
			}
		}
		fileOffset++
	}
	return buf, nil
}

func filterDelta(n int, buf []byte) ([]byte, error) {
	var res []byte
	l := len(buf)
	if cap(buf) >= 2*l {
		res = buf[l : 2*l] // use unused capacity
	} else {
		res = make([]byte, l, 2*l)
	}

	i := 0
	for j := 0; j < n; j++ {
		var c byte
		for k := j; k < len(res); k += n {
			c -= buf[i]
			i++
			res[k] = c
		}
	}
	return res, nil
}

func deltaFilterV3(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	return filterDelta(int(r[0]), buf)
}

func abs(n int) int {
	if n < 0 {
		n = -n
	}
	return n
}

func filterRGBV3(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	width := int(r[0] - 3)
	posR := int(r[1])
	if posR < 0 || width < 0 {
		return buf, nil
	}

	var res []byte
	l := len(buf)
	if cap(buf) >= 2*l {
		res = buf[l : 2*l] // use unused capacity
	} else {
		res = make([]byte, l, 2*l)
	}

	for c := 0; c < 3; c++ {
		var prevByte int
		for i := c; i < len(res); i += 3 {
			var predicted int
			upperPos := i - width
			if upperPos >= 3 {
				upperByte := int(res[upperPos])
				upperLeftByte := int(res[upperPos-3])
				predicted = prevByte + upperByte - upperLeftByte
				pa := abs(predicted - prevByte)
				pb := abs(predicted - upperByte)
				pc := abs(predicted - upperLeftByte)
				if pa <= pb && pa <= pc {
					predicted = prevByte
				} else if pb <= pc {
					predicted = upperByte
				} else {
					predicted = upperLeftByte
				}
			} else {
				predicted = prevByte
			}
			prevByte = (predicted - int(buf[0])) & 0xFF
			res[i] = uint8(prevByte)
			buf = buf[1:]
		}

	}
	for i := posR; i < len(res)-2; i += 3 {
		c := res[i+1]
		res[i] += c
		res[i+2] += c
	}
	return res, nil
}

func filterAudioV3(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	var res []byte
	l := len(buf)
	if cap(buf) >= 2*l {
		res = buf[l : 2*l] // use unused capacity
	} else {
		res = make([]byte, l, 2*l)
	}

	chans := int(r[0])
	for c := 0; c < chans; c++ {
		var prevByte, byteCount int
		var diff [7]int
		var d, k [3]int

		for i := c; i < len(res); i += chans {
			predicted := prevByte<<3 + k[0]*d[0] + k[1]*d[1] + k[2]*d[2]
			predicted = int(int8(predicted >> 3))

			curByte := int(int8(buf[0]))
			buf = buf[1:]
			predicted -= curByte
			res[i] = uint8(predicted)

			dd := curByte << 3
			diff[0] += abs(dd)
			diff[1] += abs(dd - d[0])
			diff[2] += abs(dd + d[0])
			diff[3] += abs(dd - d[1])
			diff[4] += abs(dd + d[1])
			diff[5] += abs(dd - d[2])
			diff[6] += abs(dd + d[2])

			prevDelta := int(int8(predicted - prevByte))
			prevByte = predicted
			d[2] = d[1]
			d[1] = prevDelta - d[0]
			d[0] = prevDelta

			if byteCount&0x1f == 0 {
				min := diff[0]
				diff[0] = 0
				n := 0
				for j := 1; j < len(diff); j++ {
					if diff[j] < min {
						min = diff[j]
						n = j
					}
					diff[j] = 0
				}
				n--
				if n >= 0 {
					m := n / 2
					if n%2 == 0 {
						if k[m] >= -16 {
							k[m]--
						}
					} else {
						if k[m] < 16 {
							k[m]++
						}
					}
				}
			}
			byteCount++
		}

	}
	return res, nil
}

func filterArm(buf []byte, offset int64) ([]byte, error) {
	for i := 0; len(buf)-i > 3; i += 4 {
		if buf[i+3] == 0xeb {
			n := uint(buf[i])
			n += uint(buf[i+1]) * 0x100
			n += uint(buf[i+2]) * 0x10000
			n -= (uint(offset) + uint(i)) / 4
			buf[i] = byte(n)
			buf[i+1] = byte(n >> 8)
			buf[i+2] = byte(n >> 16)
		}
	}
	return buf, nil
}

type vmFilter struct {
	execCount uint32
	global    []byte
	static    []byte
	code      []command
}

// execute implements v3filter type for VM based RAR 3 filters.
func (f *vmFilter) execute(r map[int]uint32, global, buf []byte, offset int64) ([]byte, error) {
	if len(buf) > vmGlobalAddr {
		return buf, errInvalidFilter
	}
	v := newVM(buf)

	// register setup
	v.r[3] = vmGlobalAddr
	v.r[4] = uint32(len(buf))
	v.r[5] = f.execCount
	for i, n := range r {
		v.r[i] = n
	}

	// vm global data memory block
	vg := v.m[vmGlobalAddr : vmGlobalAddr+vmGlobalSize]

	// initialize fixed global memory
	for i, n := range v.r[:vmRegs-1] {
		binary.LittleEndian.PutUint32(vg[i*4:], n)
	}
	binary.LittleEndian.PutUint32(vg[0x1c:], uint32(len(buf)))
	binary.LittleEndian.PutUint64(vg[0x24:], uint64(offset))
	binary.LittleEndian.PutUint32(vg[0x2c:], f.execCount)

	// registers
	v.r[6] = uint32(offset)

	// copy program global memory
	var n int
	if len(f.global) > 0 {
		n = copy(vg[vmFixedGlobalSize:], f.global) // use saved global instead
	} else {
		n = copy(vg[vmFixedGlobalSize:], global)
	}
	copy(vg[vmFixedGlobalSize+n:], f.static)

	v.execute(f.code)

	f.execCount++

	// keep largest global buffer
	if cap(global) > cap(f.global) {
		f.global = global[:0]
	} else if len(f.global) > 0 {
		f.global = f.global[:0]
	}

	// check for global data to be saved for next program execution
	globalSize := binary.LittleEndian.Uint32(vg[0x30:])
	if globalSize > 0 {
		if globalSize > vmGlobalSize-vmFixedGlobalSize {
			globalSize = vmGlobalSize - vmFixedGlobalSize
		}
		if cap(f.global) < int(globalSize) {
			f.global = make([]byte, globalSize)
		} else {
			f.global = f.global[:globalSize]
		}
		copy(f.global, vg[vmFixedGlobalSize:])
	}

	// find program output
	length := binary.LittleEndian.Uint32(vg[0x1c:]) & vmMask
	start := binary.LittleEndian.Uint32(vg[0x20:]) & vmMask
	if start+length > vmSize {
		// TODO: error
		start = 0
		length = 0
	}
	if start != 0 && cap(v.m) > cap(buf) {
		// Initial buffer was to small for vm.
		// Copy output to beginning of vm memory so that decodeReader
		// will re-use the newly allocated vm memory and we will not
		// have to reallocate again next time.
		copy(v.m, v.m[start:start+length])
		start = 0
	}
	return v.m[start : start+length], nil
}

// getV3Filter returns a V3 filter function from a code byte slice.
func getV3Filter(code []byte) (v3Filter, error) {
	// check if filter is a known standard filter
	c := crc32.ChecksumIEEE(code)
	for _, f := range standardV3Filters {
		if f.crc == c && f.len == len(code) {
			return f.f, nil
		}
	}

	// create new vm filter
	f := new(vmFilter)
	r := newRarBitReader(bytes.NewReader(code[1:])) // skip first xor byte check

	// read static data
	n, err := r.readBits(1)
	if err != nil {
		return nil, err
	}
	if n > 0 {
		m, err := r.readUint32()
		if err != nil {
			return nil, err
		}
		f.static = make([]byte, m+1)
		err = r.readFull(f.static)
		if err != nil {
			return nil, err
		}
	}

	f.code, err = readCommands(r)
	if err == io.EOF {
		err = nil
	}

	return f.execute, err
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors.

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

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

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

package versioning

import (
	"io"

	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

// NewCodecForScheme is a convenience method for callers that are using a scheme.
func NewCodecForScheme(
	// TODO: I should be a scheme interface?
	scheme *runtime.Scheme,
	encoder runtime.Encoder,
	decoder runtime.Decoder,
	encodeVersion runtime.GroupVersioner,
	decodeVersion runtime.GroupVersioner,
) runtime.Codec {
	return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, nil, encodeVersion, decodeVersion)
}

// NewDefaultingCodecForScheme is a convenience method for callers that are using a scheme.
func NewDefaultingCodecForScheme(
	// TODO: I should be a scheme interface?
	scheme *runtime.Scheme,
	encoder runtime.Encoder,
	decoder runtime.Decoder,
	encodeVersion runtime.GroupVersioner,
	decodeVersion runtime.GroupVersioner,
) runtime.Codec {
	return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, scheme, encodeVersion, decodeVersion)
}

// NewCodec takes objects in their internal versions and converts them to external versions before
// serializing them. It assumes the serializer provided to it only deals with external versions.
// This class is also a serializer, but is generally used with a specific version.
func NewCodec(
	encoder runtime.Encoder,
	decoder runtime.Decoder,
	convertor runtime.ObjectConvertor,
	creater runtime.ObjectCreater,
	typer runtime.ObjectTyper,
	defaulter runtime.ObjectDefaulter,
	encodeVersion runtime.GroupVersioner,
	decodeVersion runtime.GroupVersioner,
) runtime.Codec {
	internal := &codec{
		encoder:   encoder,
		decoder:   decoder,
		convertor: convertor,
		creater:   creater,
		typer:     typer,
		defaulter: defaulter,

		encodeVersion: encodeVersion,
		decodeVersion: decodeVersion,
	}
	return internal
}

type codec struct {
	encoder   runtime.Encoder
	decoder   runtime.Decoder
	convertor runtime.ObjectConvertor
	creater   runtime.ObjectCreater
	typer     runtime.ObjectTyper
	defaulter runtime.ObjectDefaulter

	encodeVersion runtime.GroupVersioner
	decodeVersion runtime.GroupVersioner
}

// Decode attempts a decode of the object, then tries to convert it to the internal version. If into is provided and the decoding is
// successful, the returned runtime.Object will be the value passed as into. Note that this may bypass conversion if you pass an
// into that matches the serialized version.
func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
	versioned, isVersioned := into.(*runtime.VersionedObjects)
	if isVersioned {
		into = versioned.Last()
	}

	obj, gvk, err := c.decoder.Decode(data, defaultGVK, into)
	if err != nil {
		return nil, gvk, err
	}

	if d, ok := obj.(runtime.NestedObjectDecoder); ok {
		if err := d.DecodeNestedObjects(DirectDecoder{c.decoder}); err != nil {
			return nil, gvk, err
		}
	}

	// if we specify a target, use generic conversion.
	if into != nil {
		if into == obj {
			if isVersioned {
				return versioned, gvk, nil
			}
			return into, gvk, nil
		}

		// perform defaulting if requested
		if c.defaulter != nil {
			// create a copy to ensure defaulting is not applied to the original versioned objects
			if isVersioned {
				versioned.Objects = []runtime.Object{obj.DeepCopyObject()}
			}
			c.defaulter.Default(obj)
		} else {
			if isVersioned {
				versioned.Objects = []runtime.Object{obj}
			}
		}

		if err := c.convertor.Convert(obj, into, c.decodeVersion); err != nil {
			return nil, gvk, err
		}

		if isVersioned {
			versioned.Objects = append(versioned.Objects, into)
			return versioned, gvk, nil
		}
		return into, gvk, nil
	}

	// Convert if needed.
	if isVersioned {
		// create a copy, because ConvertToVersion does not guarantee non-mutation of objects
		versioned.Objects = []runtime.Object{obj.DeepCopyObject()}
	}

	// perform defaulting if requested
	if c.defaulter != nil {
		c.defaulter.Default(obj)
	}

	out, err := c.convertor.ConvertToVersion(obj, c.decodeVersion)
	if err != nil {
		return nil, gvk, err
	}
	if isVersioned {
		if versioned.Last() != out {
			versioned.Objects = append(versioned.Objects, out)
		}
		return versioned, gvk, nil
	}
	return out, gvk, nil
}

// Encode ensures the provided object is output in the appropriate group and version, invoking
// conversion if necessary. Unversioned objects (according to the ObjectTyper) are output as is.
func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
	switch obj.(type) {
	case *runtime.Unknown:
		return c.encoder.Encode(obj, w)
	}

	// Note: for runtime.Unstructured, the typer will return the GVK in the object and we will do conversion as normal below.
	// For the normal runtime.Scheme converter the conversion will be a no-op for Unstructured. For CustomResources
	// the conversion will actually do something.

	gvks, isUnversioned, err := c.typer.ObjectKinds(obj)
	if err != nil {
		return err
	}

	if c.encodeVersion == nil || isUnversioned {
		if e, ok := obj.(runtime.NestedObjectEncoder); ok {
			if err := e.EncodeNestedObjects(DirectEncoder{Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
				return err
			}
		}
		objectKind := obj.GetObjectKind()
		old := objectKind.GroupVersionKind()
		objectKind.SetGroupVersionKind(gvks[0])
		err = c.encoder.Encode(obj, w)
		objectKind.SetGroupVersionKind(old)
		return err
	}

	// Perform a conversion if necessary
	objectKind := obj.GetObjectKind()
	old := objectKind.GroupVersionKind()
	out, err := c.convertor.ConvertToVersion(obj, c.encodeVersion)
	if err != nil {
		return err
	}

	if e, ok := out.(runtime.NestedObjectEncoder); ok {
		if err := e.EncodeNestedObjects(DirectEncoder{Version: c.encodeVersion, Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
			return err
		}
	}

	// Conversion is responsible for setting the proper group, version, and kind onto the outgoing object
	err = c.encoder.Encode(out, w)
	// restore the old GVK, in case conversion returned the same object
	objectKind.SetGroupVersionKind(old)
	return err
}

// DirectEncoder serializes an object and ensures the GVK is set.
type DirectEncoder struct {
	Version runtime.GroupVersioner
	runtime.Encoder
	runtime.ObjectTyper
}

// Encode does not do conversion. It sets the gvk during serialization.
func (e DirectEncoder) Encode(obj runtime.Object, stream io.Writer) error {
	gvks, _, err := e.ObjectTyper.ObjectKinds(obj)
	if err != nil {
		if runtime.IsNotRegisteredError(err) {
			return e.Encoder.Encode(obj, stream)
		}
		return err
	}
	kind := obj.GetObjectKind()
	oldGVK := kind.GroupVersionKind()
	gvk := gvks[0]
	if e.Version != nil {
		preferredGVK, ok := e.Version.KindForGroupVersionKinds(gvks)
		if ok {
			gvk = preferredGVK
		}
	}
	kind.SetGroupVersionKind(gvk)
	err = e.Encoder.Encode(obj, stream)
	kind.SetGroupVersionKind(oldGVK)
	return err
}

// DirectDecoder clears the group version kind of a deserialized object.
type DirectDecoder struct {
	runtime.Decoder
}

// Decode does not do conversion. It removes the gvk during deserialization.
func (d DirectDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
	obj, gvk, err := d.Decoder.Decode(data, defaults, into)
	if obj != nil {
		kind := obj.GetObjectKind()
		// clearing the gvk is just a convention of a codec
		kind.SetGroupVersionKind(schema.GroupVersionKind{})
	}
	return obj, gvk, err
}
<commit_msg>apimachinery duct tape: in versioning codec avoid conversion roundtrip for same GVK<commit_after>/*
Copyright 2014 The Kubernetes Authors.

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

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

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

package versioning

import (
	"io"
	"reflect"

	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

// NewCodecForScheme is a convenience method for callers that are using a scheme.
func NewCodecForScheme(
	// TODO: I should be a scheme interface?
	scheme *runtime.Scheme,
	encoder runtime.Encoder,
	decoder runtime.Decoder,
	encodeVersion runtime.GroupVersioner,
	decodeVersion runtime.GroupVersioner,
) runtime.Codec {
	return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, nil, encodeVersion, decodeVersion)
}

// NewDefaultingCodecForScheme is a convenience method for callers that are using a scheme.
func NewDefaultingCodecForScheme(
	// TODO: I should be a scheme interface?
	scheme *runtime.Scheme,
	encoder runtime.Encoder,
	decoder runtime.Decoder,
	encodeVersion runtime.GroupVersioner,
	decodeVersion runtime.GroupVersioner,
) runtime.Codec {
	return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, scheme, encodeVersion, decodeVersion)
}

// NewCodec takes objects in their internal versions and converts them to external versions before
// serializing them. It assumes the serializer provided to it only deals with external versions.
// This class is also a serializer, but is generally used with a specific version.
func NewCodec(
	encoder runtime.Encoder,
	decoder runtime.Decoder,
	convertor runtime.ObjectConvertor,
	creater runtime.ObjectCreater,
	typer runtime.ObjectTyper,
	defaulter runtime.ObjectDefaulter,
	encodeVersion runtime.GroupVersioner,
	decodeVersion runtime.GroupVersioner,
) runtime.Codec {
	internal := &codec{
		encoder:   encoder,
		decoder:   decoder,
		convertor: convertor,
		creater:   creater,
		typer:     typer,
		defaulter: defaulter,

		encodeVersion: encodeVersion,
		decodeVersion: decodeVersion,
	}
	return internal
}

type codec struct {
	encoder   runtime.Encoder
	decoder   runtime.Decoder
	convertor runtime.ObjectConvertor
	creater   runtime.ObjectCreater
	typer     runtime.ObjectTyper
	defaulter runtime.ObjectDefaulter

	encodeVersion runtime.GroupVersioner
	decodeVersion runtime.GroupVersioner
}

// Decode attempts a decode of the object, then tries to convert it to the internal version. If into is provided and the decoding is
// successful, the returned runtime.Object will be the value passed as into. Note that this may bypass conversion if you pass an
// into that matches the serialized version.
func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
	versioned, isVersioned := into.(*runtime.VersionedObjects)
	if isVersioned {
		into = versioned.Last()
	}

	obj, gvk, err := c.decoder.Decode(data, defaultGVK, into)
	if err != nil {
		return nil, gvk, err
	}

	if d, ok := obj.(runtime.NestedObjectDecoder); ok {
		if err := d.DecodeNestedObjects(DirectDecoder{c.decoder}); err != nil {
			return nil, gvk, err
		}
	}

	// if we specify a target, use generic conversion.
	if into != nil {
		if into == obj {
			if isVersioned {
				return versioned, gvk, nil
			}
			return into, gvk, nil
		}

		// perform defaulting if requested
		if c.defaulter != nil {
			// create a copy to ensure defaulting is not applied to the original versioned objects
			if isVersioned {
				versioned.Objects = []runtime.Object{obj.DeepCopyObject()}
			}
			c.defaulter.Default(obj)
		} else {
			if isVersioned {
				versioned.Objects = []runtime.Object{obj}
			}
		}

		if err := c.convertor.Convert(obj, into, c.decodeVersion); err != nil {
			return nil, gvk, err
		}

		if isVersioned {
			versioned.Objects = append(versioned.Objects, into)
			return versioned, gvk, nil
		}
		return into, gvk, nil
	}

	// Convert if needed.
	if isVersioned {
		// create a copy, because ConvertToVersion does not guarantee non-mutation of objects
		versioned.Objects = []runtime.Object{obj.DeepCopyObject()}
	}

	// perform defaulting if requested
	if c.defaulter != nil {
		c.defaulter.Default(obj)
	}

	out, err := c.convertor.ConvertToVersion(obj, c.decodeVersion)
	if err != nil {
		return nil, gvk, err
	}
	if isVersioned {
		if versioned.Last() != out {
			versioned.Objects = append(versioned.Objects, out)
		}
		return versioned, gvk, nil
	}
	return out, gvk, nil
}

// Encode ensures the provided object is output in the appropriate group and version, invoking
// conversion if necessary. Unversioned objects (according to the ObjectTyper) are output as is.
func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
	switch obj := obj.(type) {
	case *runtime.Unknown:
		return c.encoder.Encode(obj, w)
	case runtime.Unstructured:
		// avoid conversion roundtrip if GVK is the right one already
		objGVK := obj.GetObjectKind().GroupVersionKind()
		targetGVK, ok := c.encodeVersion.KindForGroupVersionKinds([]schema.GroupVersionKind{objGVK})
		if !ok {
			return runtime.NewNotRegisteredErrForTarget(reflect.TypeOf(obj).Elem(), c.encodeVersion)
		}
		if targetGVK == objGVK {
			return c.encoder.Encode(obj, w)
		}
	}

	gvks, isUnversioned, err := c.typer.ObjectKinds(obj)
	if err != nil {
		return err
	}

	if c.encodeVersion == nil || isUnversioned {
		if e, ok := obj.(runtime.NestedObjectEncoder); ok {
			if err := e.EncodeNestedObjects(DirectEncoder{Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
				return err
			}
		}
		objectKind := obj.GetObjectKind()
		old := objectKind.GroupVersionKind()
		objectKind.SetGroupVersionKind(gvks[0])
		err = c.encoder.Encode(obj, w)
		objectKind.SetGroupVersionKind(old)
		return err
	}

	// Perform a conversion if necessary
	objectKind := obj.GetObjectKind()
	old := objectKind.GroupVersionKind()
	out, err := c.convertor.ConvertToVersion(obj, c.encodeVersion)
	if err != nil {
		return err
	}

	if e, ok := out.(runtime.NestedObjectEncoder); ok {
		if err := e.EncodeNestedObjects(DirectEncoder{Version: c.encodeVersion, Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
			return err
		}
	}

	// Conversion is responsible for setting the proper group, version, and kind onto the outgoing object
	err = c.encoder.Encode(out, w)
	// restore the old GVK, in case conversion returned the same object
	objectKind.SetGroupVersionKind(old)
	return err
}

// DirectEncoder serializes an object and ensures the GVK is set.
type DirectEncoder struct {
	Version runtime.GroupVersioner
	runtime.Encoder
	runtime.ObjectTyper
}

// Encode does not do conversion. It sets the gvk during serialization.
func (e DirectEncoder) Encode(obj runtime.Object, stream io.Writer) error {
	gvks, _, err := e.ObjectTyper.ObjectKinds(obj)
	if err != nil {
		if runtime.IsNotRegisteredError(err) {
			return e.Encoder.Encode(obj, stream)
		}
		return err
	}
	kind := obj.GetObjectKind()
	oldGVK := kind.GroupVersionKind()
	gvk := gvks[0]
	if e.Version != nil {
		preferredGVK, ok := e.Version.KindForGroupVersionKinds(gvks)
		if ok {
			gvk = preferredGVK
		}
	}
	kind.SetGroupVersionKind(gvk)
	err = e.Encoder.Encode(obj, stream)
	kind.SetGroupVersionKind(oldGVK)
	return err
}

// DirectDecoder clears the group version kind of a deserialized object.
type DirectDecoder struct {
	runtime.Decoder
}

// Decode does not do conversion. It removes the gvk during deserialization.
func (d DirectDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
	obj, gvk, err := d.Decoder.Decode(data, defaults, into)
	if obj != nil {
		kind := obj.GetObjectKind()
		// clearing the gvk is just a convention of a codec
		kind.SetGroupVersionKind(schema.GroupVersionKind{})
	}
	return obj, gvk, err
}
<|endoftext|>


<commit_before>package main

import (
	"firempq/common"
	"firempq/conf"
	"firempq/defs"
	"firempq/facade"
	"firempq/features/pqueue"
	"firempq/iface"
	"firempq/log"
	"firempq/server"
	"fmt"
	"strconv"
)

func main() {
	// Initialize logging to a default INFO level to be able to log config error.
	log.InitLogging()

	err := conf.ReadConfig()
	if err != nil {
		log.Error(err.Error())
		return
	}
	// Reinitialize log level according to the config data.
	log.InitLogging()

	iface := fmt.Sprintf("%s:%d", conf.CFG.Interface, conf.CFG.Port)
	srv, err := server.GetServer(server.SIMPLE_SERVER, iface)
	if err != nil {
		log.Critical("Error: %s", err.Error())
		return
	}
	srv.Start()

}

func addMessages(pq iface.ISvc) {
	payload := "0000"
	v := []string{defs.PRM_PRIORITY, "1", defs.PRM_PAYLOAD, payload}
	for i := 0; i < 10000000; i++ {
		pq.Call(pqueue.ACTION_PUSH, v)
	}
}

func main1() {
	//	f, _ := os.Create("pp.dat")
	//	pprof.StartCPUProfile(f)
	//	defer pprof.StopCPUProfile()

	fc := facade.CreateFacade()
	defer fc.Close()
	for i := 0; i < 1; i++ {
		qid := "tst_queue_" + strconv.Itoa(i)
		err := fc.CreateService(common.STYPE_PRIORITY_QUEUE, qid, nil)
		if err != nil {
			log.Notice("%s: %s", err, qid)
		}
	}
	start_ts := common.Uts()
	log.Notice("Started")
	for i := 0; i < 1; i++ {
		qid := "tst_queue_" + strconv.Itoa(i)
		q, _ := fc.GetService(qid)
		addMessages(q)
	}
	log.Notice("Finished. Elapsed: %d", common.Uts()-start_ts)
}
<commit_msg>minor naming style fix.<commit_after>package main

import (
	"firempq/common"
	"firempq/conf"
	"firempq/defs"
	"firempq/facade"
	"firempq/features/pqueue"
	"firempq/iface"
	"firempq/log"
	"firempq/server"
	"fmt"
	"strconv"
)

func main() {
	// Initialize logging to a default INFO level to be able to log config error.
	log.InitLogging()

	err := conf.ReadConfig()
	if err != nil {
		log.Error(err.Error())
		return
	}
	// Reinitialize log level according to the config data.
	log.InitLogging()

	iface := fmt.Sprintf("%s:%d", conf.CFG.Interface, conf.CFG.Port)
	srv, err := server.GetServer(server.SIMPLE_SERVER, iface)
	if err != nil {
		log.Critical("Error: %s", err.Error())
		return
	}
	srv.Start()

}

func addMessages(pq iface.ISvc) {
	payload := "0000"
	v := []string{defs.PRM_PRIORITY, "1", defs.PRM_PAYLOAD, payload}
	for i := 0; i < 10000000; i++ {
		pq.Call(pqueue.ACTION_PUSH, v)
	}
}

func main1() {
	//	f, _ := os.Create("pp.dat")
	//	pprof.StartCPUProfile(f)
	//	defer pprof.StopCPUProfile()

	fc := facade.CreateFacade()
	defer fc.Close()
	for i := 0; i < 1; i++ {
		qid := "tst_queue_" + strconv.Itoa(i)
		err := fc.CreateService(common.STYPE_PRIORITY_QUEUE, qid, nil)
		if err != nil {
			log.Notice("%s: %s", err, qid)
		}
	}
	startTs := common.Uts()
	log.Notice("Started")
	for i := 0; i < 1; i++ {
		qid := "tst_queue_" + strconv.Itoa(i)
		q, _ := fc.GetService(qid)
		addMessages(q)
	}
	log.Notice("Finished. Elapsed: %d", common.Uts()-startTs)
}
<|endoftext|>


<commit_before>package dns

import (
	"fmt"

	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	aws_elb "github.com/aws/aws-sdk-go/service/elb"
	aws_alb "github.com/aws/aws-sdk-go/service/elbv2"
	"github.com/aws/aws-sdk-go/service/route53"
	"github.com/sky-uk/feed/controller"
	"github.com/sky-uk/feed/dns/r53"
	"github.com/sky-uk/feed/elb"
)

type hostToIngress map[string]controller.IngressEntry
type findELBsFunc func(elb.ELB, string) (map[string]elb.LoadBalancerDetails, error)
type dnsDetails struct {
	dnsName      string
	hostedZoneID string
}

type updater struct {
	r53           r53.Route53Client
	hostedZoneID  string
	elb           elb.ELB
	alb           ALB
	schemeToDNS   map[string]dnsDetails
	albNames      []string
	elbLabelValue string
	domain        string
	findELBs      findELBsFunc
}

// ALB represents the subset of AWS operations needed for dns_updater.go
type ALB interface {
	DescribeLoadBalancers(input *aws_alb.DescribeLoadBalancersInput) (*aws_alb.DescribeLoadBalancersOutput, error)
}

// New creates an updater for dns
func New(hostedZoneID, region string, elbLabelValue string, albNames []string, retries int) controller.Updater {
	initMetrics()
	session := session.New(&aws.Config{Region: &region})
	return &updater{
		r53:           r53.New(region, hostedZoneID, retries),
		hostedZoneID:  hostedZoneID,
		elb:           aws_elb.New(session),
		alb:           aws_alb.New(session),
		albNames:      albNames,
		elbLabelValue: elbLabelValue,
		findELBs:      elb.FindFrontEndElbs,
	}
}

func (u *updater) String() string {
	return "route53 updater"
}

func (u *updater) Start() error {
	log.Info("Starting dns updater")

	if u.elbLabelValue != "" && len(u.albNames) > 0 {
		return fmt.Errorf("can't specify both elb label value (%s) and alb names (%v) - only one or the other may be"+
			" specified", u.elbLabelValue, u.albNames)
	}

	if err := u.initELBs(); err != nil {
		return err
	}

	if err := u.initALBs(); err != nil {
		return err
	}

	domain, err := u.r53.GetHostedZoneDomain()
	if err != nil {
		return fmt.Errorf("unable to get domain for hosted zone: %v", err)
	}
	u.domain = domain

	log.Info("Dns updater started")
	return nil
}

func (u *updater) initELBs() error {
	if u.elbLabelValue == "" {
		return nil
	}

	elbs, err := u.findELBs(u.elb, u.elbLabelValue)
	if err != nil {
		return fmt.Errorf("unable to find front end load balancers: %v", err)
	}

	u.schemeToDNS = make(map[string]dnsDetails)
	for scheme, lbDetails := range elbs {
		u.schemeToDNS[scheme] = dnsDetails{dnsName: lbDetails.DNSName, hostedZoneID: lbDetails.DNSName}
	}

	return nil
}

func (u *updater) initALBs() error {
	if len(u.albNames) == 0 {
		return nil
	}

	u.schemeToDNS = make(map[string]dnsDetails)
	req := &aws_alb.DescribeLoadBalancersInput{Names: aws.StringSlice(u.albNames)}

	for {
		resp, err := u.alb.DescribeLoadBalancers(req)
		if err != nil {
			return err
		}

		for _, lb := range resp.LoadBalancers {
			u.schemeToDNS[*lb.Scheme] = dnsDetails{dnsName: *lb.DNSName, hostedZoneID: *lb.CanonicalHostedZoneId}
		}

		if resp.NextMarker == nil {
			break
		}

		req.Marker = resp.NextMarker
	}

	return nil
}

func (u *updater) Stop() error {
	return nil
}

func (u *updater) Health() error {
	return nil
}

func (u *updater) Update(update controller.IngressUpdate) error {
	aRecords, err := u.r53.GetARecords()
	if err != nil {
		log.Warn("Unable to get A records from Route53. Not updating Route53.", err)
		failedCount.Inc()
		return err
	}
	recordsGauge.Set(float64(len(aRecords)))

	changes := u.calculateChanges(aRecords, update)

	updateCount.Add(float64(len(changes)))

	err = u.r53.UpdateRecordSets(changes)
	if err != nil {
		failedCount.Inc()
		return fmt.Errorf("unable to update record sets: %v", err)
	}

	return nil
}

func (u *updater) calculateChanges(originalRecords []*route53.ResourceRecordSet,
	update controller.IngressUpdate) []*route53.Change {

	log.Infof("Current %s records: %v", u.domain, originalRecords)
	log.Debug("Processing ingress update: ", update)

	hostToIngress, skipped := u.indexByHost(update.Entries)
	changes, skipped2 := u.createChanges(hostToIngress, originalRecords)

	skipped = append(skipped, skipped2...)

	if len(skipped) > 0 {
		log.Warnf("%d skipped entries for zone '%s': %v",
			len(skipped), u.domain, skipped)
	}

	log.Debug("Host to ingress entry: ", hostToIngress)
	log.Infof("Calculated changes to dns: %v", changes)
	return changes
}

func (u *updater) indexByHost(entries []controller.IngressEntry) (hostToIngress, []string) {
	var skipped []string
	mapping := make(hostToIngress)

	for _, entry := range entries {
		log.Debugf("Processing entry %v", entry)
		// Ingress entries in k8s aren't allowed to have the . on the end.
		// AWS adds it regardless of whether you specify it.
		hostNameWithPeriod := entry.Host + "."

		log.Debugf("Checking if ingress entry hostname %s is in domain %s", hostNameWithPeriod, u.domain)
		if !strings.HasSuffix(hostNameWithPeriod, "."+u.domain) {
			skipped = append(skipped, entry.NamespaceName()+":host:"+hostNameWithPeriod)
			skippedCount.Inc()
			continue
		}

		if previous, exists := mapping[hostNameWithPeriod]; exists {
			if previous.ELbScheme != entry.ELbScheme {
				skipped = append(skipped, entry.NamespaceName()+":conflicting-scheme:"+entry.ELbScheme)
				skippedCount.Inc()
			}
		} else {
			mapping[hostNameWithPeriod] = entry
		}
	}

	return mapping, skipped
}

func (u *updater) createChanges(hostToIngress hostToIngress,
	originalRecords []*route53.ResourceRecordSet) ([]*route53.Change, []string) {

	var skipped []string
	changes := []*route53.Change{}

	for host, entry := range hostToIngress {
		dnsDetails, exists := u.schemeToDNS[entry.ELbScheme]
		if !exists {
			skipped = append(skipped, entry.NamespaceName()+":scheme:"+entry.ELbScheme)
			skippedCount.Inc()
			continue
		}

		changes = append(changes, newChange("UPSERT", host, dnsDetails.dnsName, dnsDetails.hostedZoneID))
	}

	for _, recordSet := range originalRecords {
		if _, contains := hostToIngress[*recordSet.Name]; !contains {
			changes = append(changes, newChange(
				"DELETE",
				*recordSet.Name,
				*recordSet.AliasTarget.DNSName,
				*recordSet.AliasTarget.HostedZoneId))
		}
	}

	return changes, skipped
}

func newChange(action string, host string, targetElbDNSName string, targetElbHostedZoneID string) *route53.Change {
	return &route53.Change{
		Action: aws.String(action),
		ResourceRecordSet: &route53.ResourceRecordSet{
			Name: aws.String(host),
			Type: aws.String("A"),
			AliasTarget: &route53.AliasTarget{
				DNSName:      aws.String(targetElbDNSName),
				HostedZoneId: aws.String(targetElbHostedZoneID),
				// disable this since we only point to a single load balancer
				EvaluateTargetHealth: aws.Bool(false),
			},
		},
	}
}
<commit_msg>Use HostedZoneID not DNSName for LB hosted zone<commit_after>package dns

import (
	"fmt"

	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	aws_elb "github.com/aws/aws-sdk-go/service/elb"
	aws_alb "github.com/aws/aws-sdk-go/service/elbv2"
	"github.com/aws/aws-sdk-go/service/route53"
	"github.com/sky-uk/feed/controller"
	"github.com/sky-uk/feed/dns/r53"
	"github.com/sky-uk/feed/elb"
)

type hostToIngress map[string]controller.IngressEntry
type findELBsFunc func(elb.ELB, string) (map[string]elb.LoadBalancerDetails, error)
type dnsDetails struct {
	dnsName      string
	hostedZoneID string
}

type updater struct {
	r53           r53.Route53Client
	hostedZoneID  string
	elb           elb.ELB
	alb           ALB
	schemeToDNS   map[string]dnsDetails
	albNames      []string
	elbLabelValue string
	domain        string
	findELBs      findELBsFunc
}

// ALB represents the subset of AWS operations needed for dns_updater.go
type ALB interface {
	DescribeLoadBalancers(input *aws_alb.DescribeLoadBalancersInput) (*aws_alb.DescribeLoadBalancersOutput, error)
}

// New creates an updater for dns
func New(hostedZoneID, region string, elbLabelValue string, albNames []string, retries int) controller.Updater {
	initMetrics()
	session := session.New(&aws.Config{Region: &region})
	return &updater{
		r53:           r53.New(region, hostedZoneID, retries),
		hostedZoneID:  hostedZoneID,
		elb:           aws_elb.New(session),
		alb:           aws_alb.New(session),
		albNames:      albNames,
		elbLabelValue: elbLabelValue,
		findELBs:      elb.FindFrontEndElbs,
	}
}

func (u *updater) String() string {
	return "route53 updater"
}

func (u *updater) Start() error {
	log.Info("Starting dns updater")

	if u.elbLabelValue != "" && len(u.albNames) > 0 {
		return fmt.Errorf("can't specify both elb label value (%s) and alb names (%v) - only one or the other may be"+
			" specified", u.elbLabelValue, u.albNames)
	}

	if err := u.initELBs(); err != nil {
		return err
	}

	if err := u.initALBs(); err != nil {
		return err
	}

	domain, err := u.r53.GetHostedZoneDomain()
	if err != nil {
		return fmt.Errorf("unable to get domain for hosted zone: %v", err)
	}
	u.domain = domain

	log.Info("Dns updater started")
	return nil
}

func (u *updater) initELBs() error {
	if u.elbLabelValue == "" {
		return nil
	}

	elbs, err := u.findELBs(u.elb, u.elbLabelValue)
	if err != nil {
		return fmt.Errorf("unable to find front end load balancers: %v", err)
	}

	u.schemeToDNS = make(map[string]dnsDetails)
	for scheme, lbDetails := range elbs {
		u.schemeToDNS[scheme] = dnsDetails{dnsName: lbDetails.DNSName, hostedZoneID: lbDetails.HostedZoneID}
	}

	return nil
}

func (u *updater) initALBs() error {
	if len(u.albNames) == 0 {
		return nil
	}

	u.schemeToDNS = make(map[string]dnsDetails)
	req := &aws_alb.DescribeLoadBalancersInput{Names: aws.StringSlice(u.albNames)}

	for {
		resp, err := u.alb.DescribeLoadBalancers(req)
		if err != nil {
			return err
		}

		for _, lb := range resp.LoadBalancers {
			u.schemeToDNS[*lb.Scheme] = dnsDetails{dnsName: *lb.DNSName, hostedZoneID: *lb.CanonicalHostedZoneId}
		}

		if resp.NextMarker == nil {
			break
		}

		req.Marker = resp.NextMarker
	}

	return nil
}

func (u *updater) Stop() error {
	return nil
}

func (u *updater) Health() error {
	return nil
}

func (u *updater) Update(update controller.IngressUpdate) error {
	aRecords, err := u.r53.GetARecords()
	if err != nil {
		log.Warn("Unable to get A records from Route53. Not updating Route53.", err)
		failedCount.Inc()
		return err
	}
	recordsGauge.Set(float64(len(aRecords)))

	changes := u.calculateChanges(aRecords, update)

	updateCount.Add(float64(len(changes)))

	err = u.r53.UpdateRecordSets(changes)
	if err != nil {
		failedCount.Inc()
		return fmt.Errorf("unable to update record sets: %v", err)
	}

	return nil
}

func (u *updater) calculateChanges(originalRecords []*route53.ResourceRecordSet,
	update controller.IngressUpdate) []*route53.Change {

	log.Infof("Current %s records: %v", u.domain, originalRecords)
	log.Debug("Processing ingress update: ", update)

	hostToIngress, skipped := u.indexByHost(update.Entries)
	changes, skipped2 := u.createChanges(hostToIngress, originalRecords)

	skipped = append(skipped, skipped2...)

	if len(skipped) > 0 {
		log.Warnf("%d skipped entries for zone '%s': %v",
			len(skipped), u.domain, skipped)
	}

	log.Debug("Host to ingress entry: ", hostToIngress)
	log.Infof("Calculated changes to dns: %v", changes)
	return changes
}

func (u *updater) indexByHost(entries []controller.IngressEntry) (hostToIngress, []string) {
	var skipped []string
	mapping := make(hostToIngress)

	for _, entry := range entries {
		log.Debugf("Processing entry %v", entry)
		// Ingress entries in k8s aren't allowed to have the . on the end.
		// AWS adds it regardless of whether you specify it.
		hostNameWithPeriod := entry.Host + "."

		log.Debugf("Checking if ingress entry hostname %s is in domain %s", hostNameWithPeriod, u.domain)
		if !strings.HasSuffix(hostNameWithPeriod, "."+u.domain) {
			skipped = append(skipped, entry.NamespaceName()+":host:"+hostNameWithPeriod)
			skippedCount.Inc()
			continue
		}

		if previous, exists := mapping[hostNameWithPeriod]; exists {
			if previous.ELbScheme != entry.ELbScheme {
				skipped = append(skipped, entry.NamespaceName()+":conflicting-scheme:"+entry.ELbScheme)
				skippedCount.Inc()
			}
		} else {
			mapping[hostNameWithPeriod] = entry
		}
	}

	return mapping, skipped
}

func (u *updater) createChanges(hostToIngress hostToIngress,
	originalRecords []*route53.ResourceRecordSet) ([]*route53.Change, []string) {

	var skipped []string
	changes := []*route53.Change{}

	for host, entry := range hostToIngress {
		dnsDetails, exists := u.schemeToDNS[entry.ELbScheme]
		if !exists {
			skipped = append(skipped, entry.NamespaceName()+":scheme:"+entry.ELbScheme)
			skippedCount.Inc()
			continue
		}

		changes = append(changes, newChange("UPSERT", host, dnsDetails.dnsName, dnsDetails.hostedZoneID))
	}

	for _, recordSet := range originalRecords {
		if _, contains := hostToIngress[*recordSet.Name]; !contains {
			changes = append(changes, newChange(
				"DELETE",
				*recordSet.Name,
				*recordSet.AliasTarget.DNSName,
				*recordSet.AliasTarget.HostedZoneId))
		}
	}

	return changes, skipped
}

func newChange(action string, host string, targetElbDNSName string, targetElbHostedZoneID string) *route53.Change {
	return &route53.Change{
		Action: aws.String(action),
		ResourceRecordSet: &route53.ResourceRecordSet{
			Name: aws.String(host),
			Type: aws.String("A"),
			AliasTarget: &route53.AliasTarget{
				DNSName:      aws.String(targetElbDNSName),
				HostedZoneId: aws.String(targetElbHostedZoneID),
				// disable this since we only point to a single load balancer
				EvaluateTargetHealth: aws.Bool(false),
			},
		},
	}
}
<|endoftext|>


<commit_before>package action

import (
	"sort"
	"strings"

	"fmt"
	"github.com/Aptomi/aptomi/pkg/util"
	"github.com/davecgh/go-spew/spew"
)

// PlanAsText is a plan of actions, represented as text
type PlanAsText struct {
	Actions []util.NestedParameterMap
}

// NewPlanAsText returns new PlanAsText
func NewPlanAsText() *PlanAsText {
	return &PlanAsText{}
}

type keySorter []util.NestedParameterMap

func (ks keySorter) Len() int {
	return len(ks)
}

func (ks keySorter) Swap(i, j int) {
	ks[i], ks[j] = ks[j], ks[i]
}

func (ks keySorter) Less(i, j int) bool {
	return ks[i]["pretty"].(string) < ks[j]["pretty"].(string)
}

// ToString returns human-readable version of the plan
func (t *PlanAsText) String() string {
	// sort actions by pretty text
	sort.Sort(keySorter(t.Actions))

	// action map
	actionDescriptionMap := map[string]string{
		"[+]": "Create Instances",
		"[-]": "Destroy Instances",
		"[*]": "Update Instances",
		"[>]": "Add Consumers",
		"[<]": "Remove Consumers",
		"[@]": "Query Endpoints",
	}

	// combine actions into a string
	result := ""
	actionDescriptionPrev := ""
	for _, pMap := range t.Actions {
		if _, ok := pMap["prettyOmit"]; ok {
			// do not print lines which are indicated as "prettyOmit" by DescribeChanges() in actions
			continue
		}
		if strings.Contains(pMap["key"].(string), "#root") {
			// do not print lines corresponding to root components
			continue
		}

		// get pretty string
		pretty, prettyOk := pMap["pretty"].(string)
		if !prettyOk {
			cs := spew.ConfigState{Indent: "\t"}
			panic(fmt.Sprintf("action doesn't have 'pretty' key in it: %s", cs.Sdump(pMap)))
		}

		// add action category if needed
		actionDescription := actionDescriptionMap[pretty[:3]]
		if actionDescriptionPrev != actionDescription {
			actionDescriptionPrev = actionDescription
			result += actionDescription + "\n"
		}

		// add pretty action
		result += "  " + pretty + "\n"
	}
	return result
}
<commit_msg>fixed goimports<commit_after>package action

import (
	"sort"
	"strings"

	"fmt"

	"github.com/Aptomi/aptomi/pkg/util"
	"github.com/davecgh/go-spew/spew"
)

// PlanAsText is a plan of actions, represented as text
type PlanAsText struct {
	Actions []util.NestedParameterMap
}

// NewPlanAsText returns new PlanAsText
func NewPlanAsText() *PlanAsText {
	return &PlanAsText{}
}

type keySorter []util.NestedParameterMap

func (ks keySorter) Len() int {
	return len(ks)
}

func (ks keySorter) Swap(i, j int) {
	ks[i], ks[j] = ks[j], ks[i]
}

func (ks keySorter) Less(i, j int) bool {
	return ks[i]["pretty"].(string) < ks[j]["pretty"].(string)
}

// ToString returns human-readable version of the plan
func (t *PlanAsText) String() string {
	// sort actions by pretty text
	sort.Sort(keySorter(t.Actions))

	// action map
	actionDescriptionMap := map[string]string{
		"[+]": "Create Instances",
		"[-]": "Destroy Instances",
		"[*]": "Update Instances",
		"[>]": "Add Consumers",
		"[<]": "Remove Consumers",
		"[@]": "Query Endpoints",
	}

	// combine actions into a string
	result := ""
	actionDescriptionPrev := ""
	for _, pMap := range t.Actions {
		if _, ok := pMap["prettyOmit"]; ok {
			// do not print lines which are indicated as "prettyOmit" by DescribeChanges() in actions
			continue
		}
		if strings.Contains(pMap["key"].(string), "#root") {
			// do not print lines corresponding to root components
			continue
		}

		// get pretty string
		pretty, prettyOk := pMap["pretty"].(string)
		if !prettyOk {
			cs := spew.ConfigState{Indent: "\t"}
			panic(fmt.Sprintf("action doesn't have 'pretty' key in it: %s", cs.Sdump(pMap)))
		}

		// add action category if needed
		actionDescription := actionDescriptionMap[pretty[:3]]
		if actionDescriptionPrev != actionDescription {
			actionDescriptionPrev = actionDescription
			result += actionDescription + "\n"
		}

		// add pretty action
		result += "  " + pretty + "\n"
	}
	return result
}
<|endoftext|>


<commit_before>package notifiers

import (
	"fmt"

	"github.com/grafana/grafana/pkg/bus"
	"github.com/grafana/grafana/pkg/components/simplejson"
	"github.com/grafana/grafana/pkg/log"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/services/alerting"
)

func init() {
	alerting.RegisterNotifier(&alerting.NotifierPlugin{
		Type:        "dingding",
		Name:        "DingDing",
		Description: "Sends HTTP POST request to DingDing",
		Factory:     NewDingDingNotifier,
		OptionsTemplate: `

DingDing settings

        Url
        <input type="text" required class="gf-form-input max-width-26" ng-model="ctrl.model.settings.url" placeholder="https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxx"></input>

    `,
	})

}

func NewDingDingNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
	url := model.Settings.Get("url").MustString()
	if url == "" {
		return nil, alerting.ValidationError{Reason: "Could not find url property in settings"}
	}

	return &DingDingNotifier{
		NotifierBase: NewNotifierBase(model),
		Url:          url,
		log:          log.New("alerting.notifier.dingding"),
	}, nil
}

type DingDingNotifier struct {
	NotifierBase
	Url string
	log log.Logger
}

func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error {
	this.log.Info("Sending dingding")

	messageUrl, err := evalContext.GetRuleUrl()
	if err != nil {
		this.log.Error("Failed to get messageUrl", "error", err, "dingding", this.Name)
		messageUrl = ""
	}
	this.log.Info("messageUrl:" + messageUrl)

	message := evalContext.Rule.Message
	picUrl := evalContext.ImagePublicUrl
	title := evalContext.GetNotificationTitle()
	if message == "" {
		message = title
	}

	for i, match := range evalContext.EvalMatches {
		message += fmt.Sprintf("\\n%2d. %s value %s", i+1, match.Metric, match.Value)
	}

	bodyJSON, err := simplejson.NewJson([]byte(`{
		"msgtype": "link",
		"link": {
			"text": "` + message + `",
			"title": "` + title + `",
			"picUrl": "` + picUrl + `",
			"messageUrl": "` + messageUrl + `"
		}
	}`))

	if err != nil {
		this.log.Error("Failed to create Json data", "error", err, "dingding", this.Name)
	}

	body, err := bodyJSON.MarshalJSON()
	if err != nil {
		return err
	}

	cmd := &m.SendWebhookSync{
		Url:  this.Url,
		Body: string(body),
	}

	if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
		this.log.Error("Failed to send DingDing", "error", err, "dingding", this.Name)
		return err
	}

	return nil
}
<commit_msg>Split text template into variable<commit_after>package notifiers

import (
	"fmt"

	"github.com/grafana/grafana/pkg/bus"
	"github.com/grafana/grafana/pkg/components/simplejson"
	"github.com/grafana/grafana/pkg/log"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/services/alerting"
)

const DingdingOptionsTemplate = `

DingDing settings

        Url
        <input type="text" required class="gf-form-input max-width-26" ng-model="ctrl.model.settings.url" placeholder="https://oapi.dingtalk.com/robot/send?access_token=xxxxxxxxx"></input>

`

func init() {
	alerting.RegisterNotifier(&alerting.NotifierPlugin{
		Type:            "dingding",
		Name:            "DingDing",
		Description:     "Sends HTTP POST request to DingDing",
		Factory:         NewDingDingNotifier,
		OptionsTemplate: DingdingOptionsTemplate,
	})

}

func NewDingDingNotifier(model *m.AlertNotification) (alerting.Notifier, error) {
	url := model.Settings.Get("url").MustString()
	if url == "" {
		return nil, alerting.ValidationError{Reason: "Could not find url property in settings"}
	}

	return &DingDingNotifier{
		NotifierBase: NewNotifierBase(model),
		Url:          url,
		log:          log.New("alerting.notifier.dingding"),
	}, nil
}

type DingDingNotifier struct {
	NotifierBase
	Url string
	log log.Logger
}

func (this *DingDingNotifier) Notify(evalContext *alerting.EvalContext) error {
	this.log.Info("Sending dingding")

	messageUrl, err := evalContext.GetRuleUrl()
	if err != nil {
		this.log.Error("Failed to get messageUrl", "error", err, "dingding", this.Name)
		messageUrl = ""
	}
	this.log.Info("messageUrl:" + messageUrl)

	message := evalContext.Rule.Message
	picUrl := evalContext.ImagePublicUrl
	title := evalContext.GetNotificationTitle()
	if message == "" {
		message = title
	}

	for i, match := range evalContext.EvalMatches {
		message += fmt.Sprintf("\\n%2d. %s value %s", i+1, match.Metric, match.Value)
	}

	bodyStr := `{
		"msgtype": "link",
		"link": {
			"text": "` + message + `",
			"title": "` + title + `",
			"picUrl": "` + picUrl + `",
			"messageUrl": "` + messageUrl + `"
		}
	}`
	bodyJSON, err := simplejson.NewJson([]byte(bodyStr))

	if err != nil {
		this.log.Error("Failed to create Json data", "error", err, "dingding", this.Name)
	}

	body, err := bodyJSON.MarshalJSON()
	if err != nil {
		return err
	}

	cmd := &m.SendWebhookSync{
		Url:  this.Url,
		Body: string(body),
	}

	if err := bus.DispatchCtx(evalContext.Ctx, cmd); err != nil {
		this.log.Error("Failed to send DingDing", "error", err, "dingding", this.Name)
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package cloudwatch

import (
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/cloudwatch"
	"github.com/grafana/grafana/pkg/components/null"
	. "github.com/smartystreets/goconvey/convey"
)

func TestCloudWatchResponseParser(t *testing.T) {
	Convey("TestCloudWatchResponseParser", t, func() {
		Convey("can expand dimension value using exact match", func() {
			timestamp := time.Unix(0, 0)
			resp := map[string]*cloudwatch.MetricDataResult{
				"lb1": {
					Id:    aws.String("id1"),
					Label: aws.String("lb1"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
				"lb2": {
					Id:    aws.String("id2"),
					Label: aws.String("lb2"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
			}

			query := &cloudWatchQuery{
				RefId:      "refId1",
				Region:     "us-east-1",
				Namespace:  "AWS/ApplicationELB",
				MetricName: "TargetResponseTime",
				Dimensions: map[string][]string{
					"LoadBalancer": {"lb2"},
					"TargetGroup":  {"tg"},
				},
				Stats:  "Average",
				Period: 60,
				Alias:  "{{LoadBalancer}} Expanded",
			}
			series, _, err := parseGetMetricDataTimeSeries(resp, query)
			timeSeries := (*series)[0]

			So(err, ShouldBeNil)
			So(timeSeries.Name, ShouldEqual, "lb2 Expanded")
			So(timeSeries.Tags["LoadBalancer"], ShouldEqual, "lb2")
		})

		Convey("can expand dimension value using substring", func() {
			timestamp := time.Unix(0, 0)
			resp := map[string]*cloudwatch.MetricDataResult{
				"lb1 Sum": {
					Id:    aws.String("id1"),
					Label: aws.String("lb1 Sum"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
				"lb2 Average": {
					Id:    aws.String("id2"),
					Label: aws.String("lb2 Average"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
			}

			query := &cloudWatchQuery{
				RefId:      "refId1",
				Region:     "us-east-1",
				Namespace:  "AWS/ApplicationELB",
				MetricName: "TargetResponseTime",
				Dimensions: map[string][]string{
					"LoadBalancer": {"lb1"},
					"TargetGroup":  {"tg"},
				},
				Stats:  "Average",
				Period: 60,
				Alias:  "{{LoadBalancer}} Expanded",
			}
			series, _, err := parseGetMetricDataTimeSeries(resp, query)
			timeSeries := (*series)[0]

			So(err, ShouldBeNil)
			So(timeSeries.Name, ShouldEqual, "lb1 Expanded")
			So(timeSeries.Tags["LoadBalancer"], ShouldEqual, "lb1")
		})

		Convey("can expand dimension value using wildcard", func() {
			timestamp := time.Unix(0, 0)
			resp := map[string]*cloudwatch.MetricDataResult{
				"lb3": {
					Id:    aws.String("lb3"),
					Label: aws.String("lb3"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
				"lb4": {
					Id:    aws.String("lb4"),
					Label: aws.String("lb4"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
			}

			query := &cloudWatchQuery{
				RefId:      "refId1",
				Region:     "us-east-1",
				Namespace:  "AWS/ApplicationELB",
				MetricName: "TargetResponseTime",
				Dimensions: map[string][]string{
					"LoadBalancer": {"*"},
					"TargetGroup":  {"tg"},
				},
				Stats:  "Average",
				Period: 60,
				Alias:  "{{LoadBalancer}} Expanded",
			}
			series, _, err := parseGetMetricDataTimeSeries(resp, query)

			So(err, ShouldBeNil)
			So((*series)[0].Name, ShouldEqual, "lb3 Expanded")
			So((*series)[1].Name, ShouldEqual, "lb4 Expanded")
		})

		Convey("can parse cloudwatch response", func() {
			timestamp := time.Unix(0, 0)
			resp := map[string]*cloudwatch.MetricDataResult{
				"lb": {
					Id:    aws.String("id1"),
					Label: aws.String("lb"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
			}

			query := &cloudWatchQuery{
				RefId:      "refId1",
				Region:     "us-east-1",
				Namespace:  "AWS/ApplicationELB",
				MetricName: "TargetResponseTime",
				Dimensions: map[string][]string{
					"LoadBalancer": {"lb"},
					"TargetGroup":  {"tg"},
				},
				Stats:  "Average",
				Period: 60,
				Alias:  "{{namespace}}_{{metric}}_{{stat}}",
			}
			series, _, err := parseGetMetricDataTimeSeries(resp, query)
			timeSeries := (*series)[0]

			So(err, ShouldBeNil)
			So(timeSeries.Name, ShouldEqual, "AWS/ApplicationELB_TargetResponseTime_Average")
			So(timeSeries.Tags["LoadBalancer"], ShouldEqual, "lb")
			So(timeSeries.Points[0][0].String(), ShouldEqual, null.FloatFrom(10.0).String())
			So(timeSeries.Points[1][0].String(), ShouldEqual, null.FloatFrom(20.0).String())
			So(timeSeries.Points[2][0].String(), ShouldEqual, null.FloatFromPtr(nil).String())
			So(timeSeries.Points[3][0].String(), ShouldEqual, null.FloatFrom(30.0).String())
		})
	})
}
<commit_msg>Chore: Fix go vet problem (#21568)<commit_after>package cloudwatch

import (
	"testing"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/cloudwatch"
	"github.com/grafana/grafana/pkg/components/null"
	. "github.com/smartystreets/goconvey/convey"
)

func TestCloudWatchResponseParser(t *testing.T) {
	Convey("TestCloudWatchResponseParser", t, func() {
		Convey("can expand dimension value using exact match", func() {
			timestamp := time.Unix(0, 0)
			resp := map[string]*cloudwatch.MetricDataResult{
				"lb1": {
					Id:    aws.String("id1"),
					Label: aws.String("lb1"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
				"lb2": {
					Id:    aws.String("id2"),
					Label: aws.String("lb2"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
			}

			query := &cloudWatchQuery{
				RefId:      "refId1",
				Region:     "us-east-1",
				Namespace:  "AWS/ApplicationELB",
				MetricName: "TargetResponseTime",
				Dimensions: map[string][]string{
					"LoadBalancer": {"lb2"},
					"TargetGroup":  {"tg"},
				},
				Stats:  "Average",
				Period: 60,
				Alias:  "{{LoadBalancer}} Expanded",
			}
			series, partialData, err := parseGetMetricDataTimeSeries(resp, query)
			timeSeries := (*series)[0]

			So(err, ShouldBeNil)
			So(partialData, ShouldBeFalse)
			So(timeSeries.Name, ShouldEqual, "lb2 Expanded")
			So(timeSeries.Tags["LoadBalancer"], ShouldEqual, "lb2")
		})

		Convey("can expand dimension value using substring", func() {
			timestamp := time.Unix(0, 0)
			resp := map[string]*cloudwatch.MetricDataResult{
				"lb1 Sum": {
					Id:    aws.String("id1"),
					Label: aws.String("lb1 Sum"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
				"lb2 Average": {
					Id:    aws.String("id2"),
					Label: aws.String("lb2 Average"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
			}

			query := &cloudWatchQuery{
				RefId:      "refId1",
				Region:     "us-east-1",
				Namespace:  "AWS/ApplicationELB",
				MetricName: "TargetResponseTime",
				Dimensions: map[string][]string{
					"LoadBalancer": {"lb1"},
					"TargetGroup":  {"tg"},
				},
				Stats:  "Average",
				Period: 60,
				Alias:  "{{LoadBalancer}} Expanded",
			}
			series, partialData, err := parseGetMetricDataTimeSeries(resp, query)
			timeSeries := (*series)[0]

			So(err, ShouldBeNil)
			So(partialData, ShouldBeFalse)
			So(timeSeries.Name, ShouldEqual, "lb1 Expanded")
			So(timeSeries.Tags["LoadBalancer"], ShouldEqual, "lb1")
		})

		Convey("can expand dimension value using wildcard", func() {
			timestamp := time.Unix(0, 0)
			resp := map[string]*cloudwatch.MetricDataResult{
				"lb3": {
					Id:    aws.String("lb3"),
					Label: aws.String("lb3"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
				"lb4": {
					Id:    aws.String("lb4"),
					Label: aws.String("lb4"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
			}

			query := &cloudWatchQuery{
				RefId:      "refId1",
				Region:     "us-east-1",
				Namespace:  "AWS/ApplicationELB",
				MetricName: "TargetResponseTime",
				Dimensions: map[string][]string{
					"LoadBalancer": {"*"},
					"TargetGroup":  {"tg"},
				},
				Stats:  "Average",
				Period: 60,
				Alias:  "{{LoadBalancer}} Expanded",
			}
			series, partialData, err := parseGetMetricDataTimeSeries(resp, query)

			So(err, ShouldBeNil)
			So(partialData, ShouldBeFalse)
			So((*series)[0].Name, ShouldEqual, "lb3 Expanded")
			So((*series)[1].Name, ShouldEqual, "lb4 Expanded")
		})

		Convey("can parse cloudwatch response", func() {
			timestamp := time.Unix(0, 0)
			resp := map[string]*cloudwatch.MetricDataResult{
				"lb": {
					Id:    aws.String("id1"),
					Label: aws.String("lb"),
					Timestamps: []*time.Time{
						aws.Time(timestamp),
						aws.Time(timestamp.Add(60 * time.Second)),
						aws.Time(timestamp.Add(180 * time.Second)),
					},
					Values: []*float64{
						aws.Float64(10),
						aws.Float64(20),
						aws.Float64(30),
					},
					StatusCode: aws.String("Complete"),
				},
			}

			query := &cloudWatchQuery{
				RefId:      "refId1",
				Region:     "us-east-1",
				Namespace:  "AWS/ApplicationELB",
				MetricName: "TargetResponseTime",
				Dimensions: map[string][]string{
					"LoadBalancer": {"lb"},
					"TargetGroup":  {"tg"},
				},
				Stats:  "Average",
				Period: 60,
				Alias:  "{{namespace}}_{{metric}}_{{stat}}",
			}
			series, partialData, err := parseGetMetricDataTimeSeries(resp, query)
			timeSeries := (*series)[0]

			So(err, ShouldBeNil)
			So(partialData, ShouldBeFalse)
			So(timeSeries.Name, ShouldEqual, "AWS/ApplicationELB_TargetResponseTime_Average")
			So(timeSeries.Tags["LoadBalancer"], ShouldEqual, "lb")
			So(timeSeries.Points[0][0].String(), ShouldEqual, null.FloatFrom(10.0).String())
			So(timeSeries.Points[1][0].String(), ShouldEqual, null.FloatFrom(20.0).String())
			So(timeSeries.Points[2][0].String(), ShouldEqual, null.FloatFromPtr(nil).String())
			So(timeSeries.Points[3][0].String(), ShouldEqual, null.FloatFrom(30.0).String())
		})
	})
}
<|endoftext|>


<commit_before>package pq

import (
	"fmt"
	"io"
	"sync"

	"github.com/flynn/go-sql"
	"github.com/flynn/pq/oid"
)

type LargeObjects struct {
	Has64 bool
	mtx   sync.Locker
	fp    *fastpath
}

const largeObjectFns = `select proname, oid from pg_catalog.pg_proc
where proname in (
'lo_open',
'lo_close',
'lo_create',
'lo_unlink',
'lo_lseek',
'lo_lseek64',
'lo_tell',
'lo_tell64',
'lo_truncate',
'lo_truncate64',
'loread',
'lowrite')
and pronamespace = (select oid from pg_catalog.pg_namespace where nspname = 'pg_catalog')`

func NewLargeObjects(tx *sql.Tx) (*LargeObjects, error) {
	c, err := tx.Conn()
	if err != nil {
		return nil, err
	}
	c.Lock()
	defer c.Unlock()

	cn, ok := c.Conn.(*conn)
	if !ok {
		return nil, fmt.Errorf("pq: Expected driver.Conn to be *pq.conn, got %T", c.Conn)
	}
	if cn.fp == nil {
		cn.fp = newFastpath(cn)
	}
	if _, exists := cn.fp.fns["lo_open"]; !exists {
		c.Unlock()
		res, err := tx.Query(largeObjectFns)
		if err != nil {
			c.Lock()
			return nil, err
		}
		if err := cn.fp.addFunctions(res); err != nil {
			c.Lock()
			return nil, err
		}
		c.Lock()
	}

	lo := &LargeObjects{
		mtx: c.Locker,
		fp:  cn.fp,
	}
	_, lo.Has64 = cn.fp.fns["lo_lseek64"]

	return lo, nil
}

type LargeObjectMode int32

const (
	LargeObjectModeWrite LargeObjectMode = 0x20000
	LargeObjectModeRead  LargeObjectMode = 0x40000
)

func (o *LargeObjects) Create(id oid.Oid) (oid.Oid, error) {
	o.mtx.Lock()
	defer o.mtx.Unlock()

	newOid, err := fpInt32(o.fp.CallFn("lo_create", []fpArg{fpIntArg(int32(id))}))
	return oid.Oid(newOid), err
}

func (o *LargeObjects) Open(oid oid.Oid, mode LargeObjectMode) (*LargeObject, error) {
	o.mtx.Lock()
	defer o.mtx.Unlock()

	fd, err := fpInt32(o.fp.CallFn("lo_open", []fpArg{fpIntArg(int32(oid)), fpIntArg(int32(mode))}))
	return &LargeObject{fd: fd, lo: o}, err
}

func (o *LargeObjects) Unlink(oid oid.Oid) error {
	o.mtx.Lock()
	defer o.mtx.Unlock()

	_, err := o.fp.CallFn("lo_unlink", []fpArg{fpIntArg(int32(oid))})
	return err
}

type LargeObject struct {
	fd int32
	lo *LargeObjects
}

func (o *LargeObject) Write(p []byte) (int, error) {
	o.lo.mtx.Lock()
	defer o.lo.mtx.Unlock()

	n, err := fpInt32(o.lo.fp.CallFn("lowrite", []fpArg{fpIntArg(o.fd), p}))
	return int(n), err
}

func (o *LargeObject) Read(p []byte) (int, error) {
	o.lo.mtx.Lock()
	defer o.lo.mtx.Unlock()

	res, err := o.lo.fp.CallFn("loread", []fpArg{fpIntArg(o.fd), fpIntArg(int32(len(p)))})
	if len(res) < len(p) {
		err = io.EOF
	}
	return copy(p, res), err
}

func (o *LargeObject) Seek(offset int64, whence int) (n int64, err error) {
	o.lo.mtx.Lock()
	defer o.lo.mtx.Unlock()

	if o.lo.Has64 {
		n, err = fpInt64(o.lo.fp.CallFn("lo_lseek64", []fpArg{fpIntArg(o.fd), fpInt64Arg(offset), fpIntArg(int32(whence))}))
	} else {
		var n32 int32
		n32, err = fpInt32(o.lo.fp.CallFn("lo_lseek", []fpArg{fpIntArg(o.fd), fpIntArg(int32(offset)), fpIntArg(int32(whence))}))
		n = int64(n32)
	}
	return
}

func (o *LargeObject) Tell() (n int64, err error) {
	o.lo.mtx.Lock()
	defer o.lo.mtx.Unlock()

	if o.lo.Has64 {
		n, err = fpInt64(o.lo.fp.CallFn("lo_tell64", []fpArg{fpIntArg(o.fd)}))
	} else {
		var n32 int32
		n32, err = fpInt32(o.lo.fp.CallFn("lo_tell", []fpArg{fpIntArg(o.fd)}))
		n = int64(n32)
	}
	return
}

func (o *LargeObject) Truncate(size int64) (err error) {
	o.lo.mtx.Lock()
	defer o.lo.mtx.Unlock()

	if o.lo.Has64 {
		_, err = o.lo.fp.CallFn("lo_truncate64", []fpArg{fpIntArg(o.fd), fpInt64Arg(size)})
	} else {
		_, err = o.lo.fp.CallFn("lo_truncate", []fpArg{fpIntArg(o.fd), fpIntArg(int32(size))})
	}
	return
}

func (o *LargeObject) Close() error {
	o.lo.mtx.Lock()
	defer o.lo.mtx.Unlock()

	_, err := o.lo.fp.CallFn("lo_close", []fpArg{fpIntArg(o.fd)})
	return err
}
<commit_msg>Simplify locking in NewLargeObjects<commit_after>package pq

import (
	"fmt"
	"io"
	"sync"

	"github.com/flynn/go-sql"
	"github.com/flynn/pq/oid"
)

type LargeObjects struct {
	Has64 bool
	mtx   sync.Locker
	fp    *fastpath
}

const largeObjectFns = `select proname, oid from pg_catalog.pg_proc
where proname in (
'lo_open',
'lo_close',
'lo_create',
'lo_unlink',
'lo_lseek',
'lo_lseek64',
'lo_tell',
'lo_tell64',
'lo_truncate',
'lo_truncate64',
'loread',
'lowrite')
and pronamespace = (select oid from pg_catalog.pg_namespace where nspname = 'pg_catalog')`

func NewLargeObjects(tx *sql.Tx) (*LargeObjects, error) {
	c, err := tx.Conn()
	if err != nil {
		return nil, err
	}

	c.Lock()
	cn, ok := c.Conn.(*conn)
	if !ok {
		c.Unlock()
		return nil, fmt.Errorf("pq: Expected driver.Conn to be *pq.conn, got %T", c.Conn)
	}
	if cn.fp == nil {
		cn.fp = newFastpath(cn)
	}
	if _, exists := cn.fp.fns["lo_open"]; !exists {
		c.Unlock()
		res, err := tx.Query(largeObjectFns)
		if err != nil {
			return nil, err
		}
		if err := cn.fp.addFunctions(res); err != nil {
			return nil, err
		}
		c.Lock()
	}

	lo := &LargeObjects{
		mtx: c.Locker,
		fp:  cn.fp,
	}
	_, lo.Has64 = cn.fp.fns["lo_lseek64"]

	c.Unlock()
	return lo, nil
}

type LargeObjectMode int32

const (
	LargeObjectModeWrite LargeObjectMode = 0x20000
	LargeObjectModeRead  LargeObjectMode = 0x40000
)

func (o *LargeObjects) Create(id oid.Oid) (oid.Oid, error) {
	o.mtx.Lock()
	defer o.mtx.Unlock()

	newOid, err := fpInt32(o.fp.CallFn("lo_create", []fpArg{fpIntArg(int32(id))}))
	return oid.Oid(newOid), err
}

func (o *LargeObjects) Open(oid oid.Oid, mode LargeObjectMode) (*LargeObject, error) {
	o.mtx.Lock()
	defer o.mtx.Unlock()

	fd, err := fpInt32(o.fp.CallFn("lo_open", []fpArg{fpIntArg(int32(oid)), fpIntArg(int32(mode))}))
	return &LargeObject{fd: fd, lo: o}, err
}

func (o *LargeObjects) Unlink(oid oid.Oid) error {
	o.mtx.Lock()
	defer o.mtx.Unlock()

	_, err := o.fp.CallFn("lo_unlink", []fpArg{fpIntArg(int32(oid))})
	return err
}

type LargeObject struct {
	fd int32
	lo *LargeObjects
}

func (o *LargeObject) Write(p []byte) (int, error) {
	o.lo.mtx.Lock()
	defer o.lo.mtx.Unlock()

	n, err := fpInt32(o.lo.fp.CallFn("lowrite", []fpArg{fpIntArg(o.fd), p}))
	return int(n), err
}

func (o *LargeObject) Read(p []byte) (int, error) {
	o.lo.mtx.Lock()
	defer o.lo.mtx.Unlock()

	res, err := o.lo.fp.CallFn("loread", []fpArg{fpIntArg(o.fd), fpIntArg(int32(len(p)))})
	if len(res) < len(p) {
		err = io.EOF
	}
	return copy(p, res), err
}

func (o *LargeObject) Seek(offset int64, whence int) (n int64, err error) {
	o.lo.mtx.Lock()
	defer o.lo.mtx.Unlock()

	if o.lo.Has64 {
		n, err = fpInt64(o.lo.fp.CallFn("lo_lseek64", []fpArg{fpIntArg(o.fd), fpInt64Arg(offset), fpIntArg(int32(whence))}))
	} else {
		var n32 int32
		n32, err = fpInt32(o.lo.fp.CallFn("lo_lseek", []fpArg{fpIntArg(o.fd), fpIntArg(int32(offset)), fpIntArg(int32(whence))}))
		n = int64(n32)
	}
	return
}

func (o *LargeObject) Tell() (n int64, err error) {
	o.lo.mtx.Lock()
	defer o.lo.mtx.Unlock()

	if o.lo.Has64 {
		n, err = fpInt64(o.lo.fp.CallFn("lo_tell64", []fpArg{fpIntArg(o.fd)}))
	} else {
		var n32 int32
		n32, err = fpInt32(o.lo.fp.CallFn("lo_tell", []fpArg{fpIntArg(o.fd)}))
		n = int64(n32)
	}
	return
}

func (o *LargeObject) Truncate(size int64) (err error) {
	o.lo.mtx.Lock()
	defer o.lo.mtx.Unlock()

	if o.lo.Has64 {
		_, err = o.lo.fp.CallFn("lo_truncate64", []fpArg{fpIntArg(o.fd), fpInt64Arg(size)})
	} else {
		_, err = o.lo.fp.CallFn("lo_truncate", []fpArg{fpIntArg(o.fd), fpIntArg(int32(size))})
	}
	return
}

func (o *LargeObject) Close() error {
	o.lo.mtx.Lock()
	defer o.lo.mtx.Unlock()

	_, err := o.lo.fp.CallFn("lo_close", []fpArg{fpIntArg(o.fd)})
	return err
}
<|endoftext|>


<commit_before>package v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// AccProvisionInput is a specification for a AccProvisionInput resource
type AccProvisionInput struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   AccProvisionInputSpec   `json:"spec,omitempty"`
	Status AccProvisionInputStatus `json:"status,omitempty"`
}

// AccProvisionInputSpec defines the desired state of AccProvisionInput
type AccProvisionInputSpec struct {
	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
	// Important: Run "acioperator-sdk generate k8s" to regenerate code after modifying this file
	// Add custom validation using kubebuilder tags: https://book.kubebuilder.io/beyond_basics/generating_crd.html
	Flavor            string           `json:"flavor"`
	Config            string           `json:"config"`
	AccProvisionInput AccProvisionSpec `json:"acc_provision_input"`
}

type AccProvisionSpec struct {
	AciConfig       AciConfigSpec       `json:"aci_config,omitempty"`
	NetConfig       NetConfigSpec       `json:"net_config,omitempty"`
	Registry        RegistrySpec        `json:"registry,omitempty"`
	Logging         LoggingSpec         `json:"logging,omitempty"`
	IstioConfig     IstioConfigSpec     `json:"istio_config,omitempty"`
	DropLogConfig   DropLogConfigSpec   `json:"drop_log_config,omitempty"`
	Multus          MultusSpec          `json:"multus,omitempty"`
	KubeConfig      KubeConfigSpec      `json:"kube_config,omitempty"`
	SriovConfig     SriovConfigSpec     `json:"sriov_config,omitempty"`
	NodePodIFConfig NodePodIFConfigSpec `json:"nodepodif_config,omitempty"`
}

type AciConfigSpec struct {
	ClusterTenant string         `json:"cluster_tenant,omitempty"`
	SyncLogin     *SyncLoginSpec `json:"sync_login,omitempty"`
	ClientSSL     bool           `json:"client_ssl,omitempty"`
}

type SyncLoginSpec struct {
	CertFile string `json:"certfile,omitempty"`
	KeyFile  string `json:"keyfile,omitempty"`
}

type NetConfigSpec struct {
	InterfaceMTU           int  `json:"interface_mtu,omitempty"`
	SvcMonitorInterval     int  `json:"service_monitor_interval,omitempty"`
	PBRTrackingNonSNAT     bool `json:"pbr_tracking_non_snat,omitempty"`
	PodSubnetChunkSize     int  `json:"pod_subnet_chunk_size,omitempty"`
	DisableWaitForNetwork  bool `json:"disable_wait_for_network,omitempty"`
	DurationWaitForNetwork int  `json:"duration_wait_for_network,omitempty"`
}

type RegistrySpec struct {
	ImagePrefix                    string `json:"image_prefix,omitempty"`
	ImagePullSecret                string `json:"image_pull_secret,omitempty"`
	AciContainersOperatorVersion   string `json:"aci_containers_operator_version,omitempty"`
	AciContainersControllerVersion string `json:"aci_containers_controller_version,omitempty"`
	AciContainersHostVersion       string `json:"aci_containers_host_version,omitempty"`
	CNIDeployVersion               string `json:"cnideploy_version,omitempty"`
	OpflexAgentVersion             string `json:"opflex_agent_version,omitempty"`
	OpenVSwitchVersion             string `json:"openvswitch_version,omitempty"`
	GBPVersion                     string `json:"gbp_version,omitempty"`
}

type LoggingSpec struct {
	ControllerLogLevel  string `json:"controller_log_level,omitempty"`
	HostagentLogLevel   string `json:"hostagent_log_level,omitempty"`
	OpflexagentLogLevel string `json:"opflexagent_log_level,omitempty"`
}

type IstioConfigSpec struct {
	InstallIstio   bool   `json:"install_istio,omitempty"`
	InstallProfile string `json:"install_profile,omitempty"`
}

type MultusSpec struct {
	Disable bool `json:"disable,omitempty"`
}

type DropLogConfigSpec struct {
	Enable bool `json:"enable,omitempty"`
}

type KubeConfigSpec struct {
	OVSMemoryLimit          string    `json:"ovs_memory_limit,omitempty"`
	UsePrivilegedContainers bool      `json:"use_privileged_containers,omitempty"`
	ImagePullPolicy         string    `json:"image_pull_policy,omitempty"`
	RebootOpflexWithOvs     string    `json:"reboot_opflex_with_ovs,omitempty"`
	SnatOperator            *SnatSpec `json:"snat_operator,omitempty"`
}

type SnatSpec struct {
	PortRange                         *PortRangeSpec `json:"port_range,omitempty"`
	ContractScope                     string         `json:"contract_scope,omitempty"`
	DisablePeriodicSnatGlobalInfoSync bool           `json:disable_periodic_snat_global_info_sync,omitempty"`
}

type PortRangeSpec struct {
	Start        int `json:"start,omitempty"`
	End          int `json:"end,omitempty"`
	PortsPerNode int `json:"ports_per_node,omitempty"`
}

type SriovConfigSpec struct {
	Enable bool `json:"enable,omitempty"`
}

type NodePodIFConfigSpec struct {
	Enable bool `json:"enable,omitempty"`
}

// AccProvisionInputStatus defines the observed state of AccProvisionInput
type AccProvisionInputStatus struct {
	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
	// Important: Run "acioperator-sdk generate k8s" to regenerate code after modifying this file
	// Add custom validation using kubebuilder tags: https://book.kubebuilder.io/beyond_basics/generating_crd.html
	Status bool `json:"status"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// AccProvisionInput list
type AccProvisionInputList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []AccProvisionInput `json:"items"`
}
<commit_msg>Include accprovision operator image in CRD This enables user to upgrade the cluster by changing the acc-provision-operator image<commit_after>package v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// AccProvisionInput is a specification for a AccProvisionInput resource
type AccProvisionInput struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   AccProvisionInputSpec   `json:"spec,omitempty"`
	Status AccProvisionInputStatus `json:"status,omitempty"`
}

// AccProvisionInputSpec defines the desired state of AccProvisionInput
type AccProvisionInputSpec struct {
	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
	// Important: Run "acioperator-sdk generate k8s" to regenerate code after modifying this file
	// Add custom validation using kubebuilder tags: https://book.kubebuilder.io/beyond_basics/generating_crd.html
	Flavor            string           `json:"flavor"`
	Config            string           `json:"config"`
	AccProvisionInput AccProvisionSpec `json:"acc_provision_input"`
}

type AccProvisionSpec struct {
	AciConfig       AciConfigSpec       `json:"aci_config,omitempty"`
	NetConfig       NetConfigSpec       `json:"net_config,omitempty"`
	Registry        RegistrySpec        `json:"registry,omitempty"`
	Logging         LoggingSpec         `json:"logging,omitempty"`
	IstioConfig     IstioConfigSpec     `json:"istio_config,omitempty"`
	DropLogConfig   DropLogConfigSpec   `json:"drop_log_config,omitempty"`
	Multus          MultusSpec          `json:"multus,omitempty"`
	KubeConfig      KubeConfigSpec      `json:"kube_config,omitempty"`
	SriovConfig     SriovConfigSpec     `json:"sriov_config,omitempty"`
	NodePodIFConfig NodePodIFConfigSpec `json:"nodepodif_config,omitempty"`
}

type AciConfigSpec struct {
	ClusterTenant string         `json:"cluster_tenant,omitempty"`
	SyncLogin     *SyncLoginSpec `json:"sync_login,omitempty"`
	ClientSSL     bool           `json:"client_ssl,omitempty"`
}

type SyncLoginSpec struct {
	CertFile string `json:"certfile,omitempty"`
	KeyFile  string `json:"keyfile,omitempty"`
}

type NetConfigSpec struct {
	InterfaceMTU           int  `json:"interface_mtu,omitempty"`
	SvcMonitorInterval     int  `json:"service_monitor_interval,omitempty"`
	PBRTrackingNonSNAT     bool `json:"pbr_tracking_non_snat,omitempty"`
	PodSubnetChunkSize     int  `json:"pod_subnet_chunk_size,omitempty"`
	DisableWaitForNetwork  bool `json:"disable_wait_for_network,omitempty"`
	DurationWaitForNetwork int  `json:"duration_wait_for_network,omitempty"`
}

type RegistrySpec struct {
	ImagePrefix                    string `json:"image_prefix,omitempty"`
	ImagePullSecret                string `json:"image_pull_secret,omitempty"`
	AccProvisionOperatorVersion    string `json:"acc_provision_operator_version,omitempty"`
	AciContainersOperatorVersion   string `json:"aci_containers_operator_version,omitempty"`
	AciContainersControllerVersion string `json:"aci_containers_controller_version,omitempty"`
	AciContainersHostVersion       string `json:"aci_containers_host_version,omitempty"`
	CNIDeployVersion               string `json:"cnideploy_version,omitempty"`
	OpflexAgentVersion             string `json:"opflex_agent_version,omitempty"`
	OpenVSwitchVersion             string `json:"openvswitch_version,omitempty"`
	GBPVersion                     string `json:"gbp_version,omitempty"`
}

type LoggingSpec struct {
	ControllerLogLevel  string `json:"controller_log_level,omitempty"`
	HostagentLogLevel   string `json:"hostagent_log_level,omitempty"`
	OpflexagentLogLevel string `json:"opflexagent_log_level,omitempty"`
}

type IstioConfigSpec struct {
	InstallIstio   bool   `json:"install_istio,omitempty"`
	InstallProfile string `json:"install_profile,omitempty"`
}

type MultusSpec struct {
	Disable bool `json:"disable,omitempty"`
}

type DropLogConfigSpec struct {
	Enable bool `json:"enable,omitempty"`
}

type KubeConfigSpec struct {
	OVSMemoryLimit          string    `json:"ovs_memory_limit,omitempty"`
	UsePrivilegedContainers bool      `json:"use_privileged_containers,omitempty"`
	ImagePullPolicy         string    `json:"image_pull_policy,omitempty"`
	RebootOpflexWithOvs     string    `json:"reboot_opflex_with_ovs,omitempty"`
	SnatOperator            *SnatSpec `json:"snat_operator,omitempty"`
}

type SnatSpec struct {
	PortRange                         *PortRangeSpec `json:"port_range,omitempty"`
	ContractScope                     string         `json:"contract_scope,omitempty"`
	DisablePeriodicSnatGlobalInfoSync bool           `json:disable_periodic_snat_global_info_sync,omitempty"`
}

type PortRangeSpec struct {
	Start        int `json:"start,omitempty"`
	End          int `json:"end,omitempty"`
	PortsPerNode int `json:"ports_per_node,omitempty"`
}

type SriovConfigSpec struct {
	Enable bool `json:"enable,omitempty"`
}

type NodePodIFConfigSpec struct {
	Enable bool `json:"enable,omitempty"`
}

// AccProvisionInputStatus defines the observed state of AccProvisionInput
type AccProvisionInputStatus struct {
	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
	// Important: Run "acioperator-sdk generate k8s" to regenerate code after modifying this file
	// Add custom validation using kubebuilder tags: https://book.kubebuilder.io/beyond_basics/generating_crd.html
	Status bool `json:"status"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// AccProvisionInput list
type AccProvisionInputList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []AccProvisionInput `json:"items"`
}
<|endoftext|>