<commit_before>// TwoWire - TWI/I2C library for Wiring
package wire

import (
	"fmt"
	"os"
	"syscall"
	"unsafe"

	. "github.com/conclave/pcduino/core"
)

const I2CCLOCK_CHANGE = 0x0740

const (
	I2C_RETRIES = 0x0701 /* number of times a device address should be polled when not acknowledging */
	I2C_TIMEOUT = 0x0702 /* set timeout in units of 10 ms */
	/* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses
	 * are NOT supported! (due to code brokenness)
	 */
	I2C_SLAVE       = 0x0703 /* Use this slave address */
	I2C_SLAVE_FORCE = 0x0706 /* Use this slave address, even if it is already in use by a driver! */
	I2C_TENBIT      = 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */
	I2C_FUNCS       = 0x0705 /* Get the adapter functionality mask */
	I2C_RDWR        = 0x0707 /* Combined R/W transfer (one STOP only) */
	I2C_PEC         = 0x0708 /* != 0 to use PEC with SMBus */
	I2C_SMBUS       = 0x0720 /* SMBus transfer */
) // from <linux/i2c-dev.h>

type TwoWire struct {
	I2CHandle     int
	rxBuffer      []byte
	rxBufferIndex int
	txBuffer      []byte
	txBufferIndex int
	transmitting  byte
}

func NewTwoWire() *TwoWire {
	r := TwoWire{}
	r.rxBuffer = make([]byte, 32)
	r.txBuffer = make([]byte, 32)
	return &r
}

func (this *TwoWire) Close() {
	if this.I2CHandle != 0 {
		syscall.Close(this.I2CHandle)
		this.I2CHandle = 0
	}
}

// NOT IMPLEMENTED
func (this *TwoWire) onRequest() {
}

// NOT IMPLEMENTED
func (this *TwoWire) onReceive(arg int) {
}

// NOT IMPLEMENTED
// behind the scenes function that is called when data is received
func (this *TwoWire) onRequestService() {
}

// NOT IMPLEMENTED
// behind the scenes function that is called when data is received
func (this *TwoWire) onReceiveService(a []byte, b int) {
}

func (this *TwoWire) Begin() {
	this.rxBufferIndex = 0
	this.txBufferIndex = 0
	if this.I2CHandle == 0 {
		var err error
		if this.I2CHandle, err = syscall.Open("/dev/i2c-2", syscall.O_RDWR|syscall.O_CLOEXEC, 0666); err != nil {
			panic("can't open i2c device: " + err.Error())
		}
	}
}

// bus freq range 10kHz-400kHz
func (this *TwoWire) SetBusFreq(speed_hz uint) {
	if speed_hz > 400000 || speed_hz < 10000 {
		fmt.Fprintf(os.Stderr, "invalid bus freq, range[10000,400000]; freq=%d\n", speed_hz)
		return
	}
	fd, err := syscall.Open("/dev/hwi2c", syscall.O_RDWR|syscall.O_CLOEXEC, 0666)
	if err != nil {
		panic("can't open i2c device: " + err.Error())
	}
	if err = Ioctl(fd, I2CCLOCK_CHANGE, uintptr(unsafe.Pointer(&speed_hz))); err != nil {
		panic("change i2c bus freq fail: " + err.Error())
	}
	syscall.Close(fd)
}

func (this *TwoWire) BeginTransmission(address int) {
	if this.I2CHandle == 0 {
		return
	}
	this.transmitting = 1
	this.txBufferIndex = 0
	var err error
	if address <= 0x7F {
		if err = Ioctl(this.I2CHandle, I2C_TENBIT, 0); err != nil {
			panic("set i2c 7-bits address flag fail: " + err.Error())
		}
	} else if address <= 0x3FF {
		if err = Ioctl(this.I2CHandle, I2C_TENBIT, 1); err != nil {
			panic("set i2c 10-bits address flag fail: " + err.Error())
		}
	}
	if err = Ioctl(this.I2CHandle, I2C_SLAVE, uintptr(address)); err != nil {
		panic("set i2c slave address fail: " + err.Error())
	}
}

func (this *TwoWire) EndTransmission() int {
	if this.I2CHandle == 0 {
		return 0
	}
	var ret int
	file := os.NewFile(uintptr(this.I2CHandle), "/dev/i2c-2")
	n, err := file.Write(this.txBuffer)
	if err != nil || n != len(this.txBuffer) {
		fmt.Fprintf(os.Stderr, "i2c transaction failed\n")
		ret = 4
	} else {
		ret = 0
	}
	this.txBufferIndex = 0
	this.transmitting = 0
	return ret
}

func (this *TwoWire) RequestFrom(address, quantity int) int {
	if this.I2CHandle == 0 {
		return 0
	}
	if quantity > 32 {
		quantity = 32
	}
	var err error
	if address <= 0x7F {
		if err = Ioctl(this.I2CHandle, I2C_TENBIT, 0); err != nil {
			panic("set i2c 7-bits address flag fail: " + err.Error())
		}
	} else if address <= 0x3FF {
		if err = Ioctl(this.I2CHandle, I2C_TENBIT, 1); err != nil {
			panic("set i2c 10-bits address flag fail: " + err.Error())
		}
	}
	if err = Ioctl(this.I2CHandle, I2C_SLAVE, uintptr(address)); err != nil {
		panic("set i2c slave address fail: " + err.Error())
	}
	this.rxBufferIndex = 0
	file := os.NewFile(uintptr(this.I2CHandle), "/dev/i2c-2")
	n, err := file.Read(this.rxBuffer[:quantity])
	if err != nil {
		return 0
	}
	this.rxBuffer = this.rxBuffer[:n]
	return n
}

// must be called in:
// slave tx event callback
// or after BeginTransmission(address)
func (this *TwoWire) Write(data []byte) int {
	if this.txBufferIndex >= 32 {
		return 0
	}
	ret := len(data)
	if this.transmitting == 1 {
		if this.txBufferIndex+ret > 32 {
			ret = 32 - this.txBufferIndex
			data = data[:ret]
		}
		copy(this.txBuffer[this.txBufferIndex:], data)
		this.txBufferIndex += ret
		this.txBuffer = this.txBuffer[:this.txBufferIndex]
	}
	return ret
}

// must be called in:
// slave rx event callback
// or after RequestFrom(address, numBytes)
func (this *TwoWire) Available() int {
	return len(this.rxBuffer) - this.rxBufferIndex
}

// must be called in:
// slave rx event callback
// or after RequestFrom(address, numBytes)
func (this *TwoWire) Read() int {
	value := -1
	if this.rxBufferIndex < len(this.rxBuffer) {
		value = int(this.rxBuffer[this.rxBufferIndex])
		this.rxBufferIndex++
	}
	return value
}

// must be called in:
// slave rx event callback
// or after RequestFrom(address, numBytes)
func (this *TwoWire) Peek() int {
	return 0
}

// NOT IMPLEMENTED
func (this *TwoWire) Flush() {
}

// NOT IMPLEMENTED
// sets function called on slave write
func (this *TwoWire) OnRequest(fn func(arg int)) {
}

// NOT IMPLEMENTED
// sets function called on slave read
func (this *TwoWire) OnReceive(fn func()) {
}

// Preinstantiate Objects
var Wire *TwoWire

func init() {
	Wire = NewTwoWire()
}
<commit_msg>update wire<commit_after>// TwoWire - TWI/I2C library for Wiring
package wire

import (
	"fmt"
	"os"
	"syscall"
	"unsafe"

	. "github.com/conclave/pcduino/core"
)

const I2CCLOCK_CHANGE = 0x0740

const (
	I2C_RETRIES = 0x0701 /* number of times a device address should be polled when not acknowledging */
	I2C_TIMEOUT = 0x0702 /* set timeout in units of 10 ms */
	/* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses
	 * are NOT supported! (due to code brokenness)
	 */
	I2C_SLAVE       = 0x0703 /* Use this slave address */
	I2C_SLAVE_FORCE = 0x0706 /* Use this slave address, even if it is already in use by a driver! */
	I2C_TENBIT      = 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */
	I2C_FUNCS       = 0x0705 /* Get the adapter functionality mask */
	I2C_RDWR        = 0x0707 /* Combined R/W transfer (one STOP only) */
	I2C_PEC         = 0x0708 /* != 0 to use PEC with SMBus */
	I2C_SMBUS       = 0x0720 /* SMBus transfer */
) // from <linux/i2c-dev.h>

type TwoWire struct {
	I2CHandle     int
	rxBuffer      []byte
	rxBufferIndex int
	txBuffer      []byte
	txBufferIndex int
	transmitting  byte
}

func NewTwoWire() *TwoWire {
	r := TwoWire{}
	r.rxBuffer = make([]byte, 32)
	r.txBuffer = make([]byte, 32)
	return &r
}

func (this *TwoWire) Close() {
	if this.I2CHandle != 0 {
		syscall.Close(this.I2CHandle)
		this.I2CHandle = 0
	}
}

// NOT IMPLEMENTED
func (this *TwoWire) onRequest() {
}

// NOT IMPLEMENTED
func (this *TwoWire) onReceive(arg int) {
}

// NOT IMPLEMENTED
// behind the scenes function that is called when data is received
func (this *TwoWire) onRequestService() {
}

// NOT IMPLEMENTED
// behind the scenes function that is called when data is received
func (this *TwoWire) onReceiveService(a []byte, b int) {
}

func (this *TwoWire) Begin() {
	this.rxBufferIndex = 0
	this.txBufferIndex = 0
	if this.I2CHandle == 0 {
		var err error
		if this.I2CHandle, err = syscall.Open("/dev/i2c-2", syscall.O_RDWR|syscall.O_CLOEXEC, 0666); err != nil {
			panic("can't open i2c device: " + err.Error())
		}
	}
}

// bus freq range 10kHz-400kHz
func (this *TwoWire) SetBusFreq(speed_hz uint) {
	if speed_hz > 400000 || speed_hz < 10000 {
		fmt.Fprintf(os.Stderr, "invalid bus freq, range[10000,400000]; freq=%d\n", speed_hz)
		return
	}
	fd, err := syscall.Open("/dev/hwi2c", syscall.O_RDWR|syscall.O_CLOEXEC, 0666)
	if err != nil {
		panic("can't open i2c device: " + err.Error())
	}
	if err = Ioctl(fd, I2CCLOCK_CHANGE, uintptr(unsafe.Pointer(&speed_hz))); err != nil {
		panic("change i2c bus freq fail: " + err.Error())
	}
	syscall.Close(fd)
}

func (this *TwoWire) BeginTransmission(address int) {
	if this.I2CHandle == 0 {
		return
	}
	this.transmitting = 1
	this.txBufferIndex = 0
	var err error
	if address <= 0x7F {
		if err = Ioctl(this.I2CHandle, I2C_TENBIT, 0); err != nil {
			panic("set i2c 7-bits address flag fail: " + err.Error())
		}
	} else if address <= 0x3FF {
		if err = Ioctl(this.I2CHandle, I2C_TENBIT, 1); err != nil {
			panic("set i2c 10-bits address flag fail: " + err.Error())
		}
	}
	if err = Ioctl(this.I2CHandle, I2C_SLAVE, uintptr(address)); err != nil {
		panic("set i2c slave address fail: " + err.Error())
	}
}

func (this *TwoWire) EndTransmission() int {
	if this.I2CHandle == 0 {
		return 0
	}
	var ret int
	file := os.NewFile(uintptr(this.I2CHandle), "/dev/i2c-2")
	n, err := file.Write(this.txBuffer)
	if err != nil || n != len(this.txBuffer) {
		fmt.Fprintf(os.Stderr, "i2c transaction failed. %d/%d written.\n", n, len(this.txBuffer))
		ret = 4
	} else {
		ret = 0
	}
	this.txBufferIndex = 0
	this.transmitting = 0
	return ret
}

func (this *TwoWire) RequestFrom(address, quantity int) int {
	if this.I2CHandle == 0 {
		return 0
	}
	if quantity > 32 {
		quantity = 32
	}
	var err error
	if address <= 0x7F {
		if err = Ioctl(this.I2CHandle, I2C_TENBIT, 0); err != nil {
			panic("set i2c 7-bits address flag fail: " + err.Error())
		}
	} else if address <= 0x3FF {
		if err = Ioctl(this.I2CHandle, I2C_TENBIT, 1); err != nil {
			panic("set i2c 10-bits address flag fail: " + err.Error())
		}
	}
	if err = Ioctl(this.I2CHandle, I2C_SLAVE, uintptr(address)); err != nil {
		panic("set i2c slave address fail: " + err.Error())
	}
	this.rxBufferIndex = 0
	file := os.NewFile(uintptr(this.I2CHandle), "/dev/i2c-2")
	n, err := file.Read(this.rxBuffer[:quantity])
	if err != nil {
		return 0
	}
	this.rxBuffer = this.rxBuffer[:n]
	return n
}

// must be called in:
// slave tx event callback
// or after BeginTransmission(address)
func (this *TwoWire) Write(data []byte) int {
	if this.txBufferIndex >= 32 {
		return 0
	}
	ret := len(data)
	if this.transmitting == 1 {
		if this.txBufferIndex+ret > 32 {
			ret = 32 - this.txBufferIndex
			data = data[:ret]
		}
		copy(this.txBuffer[this.txBufferIndex:], data)
		this.txBufferIndex += ret
		this.txBuffer = this.txBuffer[:this.txBufferIndex]
	}
	return ret
}

// must be called in:
// slave rx event callback
// or after RequestFrom(address, numBytes)
func (this *TwoWire) Available() int {
	return len(this.rxBuffer) - this.rxBufferIndex
}

// must be called in:
// slave rx event callback
// or after RequestFrom(address, numBytes)
func (this *TwoWire) Read() int {
	value := -1
	if this.rxBufferIndex < len(this.rxBuffer) {
		value = int(this.rxBuffer[this.rxBufferIndex])
		this.rxBufferIndex++
	}
	return value
}

// must be called in:
// slave rx event callback
// or after RequestFrom(address, numBytes)
func (this *TwoWire) Peek() int {
	return 0
}

// NOT IMPLEMENTED
func (this *TwoWire) Flush() {
}

// NOT IMPLEMENTED
// sets function called on slave write
func (this *TwoWire) OnRequest(fn func(arg int)) {
}

// NOT IMPLEMENTED
// sets function called on slave read
func (this *TwoWire) OnReceive(fn func()) {
}

// Preinstantiate Objects
var Wire *TwoWire

func init() {
	Wire = NewTwoWire()
}
<|endoftext|>


<commit_before>package libstns

import (
	"os"

	"github.com/shirou/gopsutil/host"
)

func AfterOsBoot() int {
	if _, err := os.FindProcess(1); err != nil {
		return NSS_STATUS_UNAVAIL
	}

	if os.Args[0] == "/sbin/init" || os.Args[0] == "dbus-daemon" {
		host, err := host.Info()

		if err != nil {
			return NSS_STATUS_UNAVAIL
		}

		if host.PlatformFamily == "debian" {
			return NSS_STATUS_NOTFOUND
		}
	}
	return NSS_STATUS_SUCCESS
}
<commit_msg>check networks<commit_after>package libstns

import (
	"net"
	"os"
	"strings"

	"github.com/shirou/gopsutil/host"
)

func AfterOsBoot() int {
	if _, err := os.FindProcess(1); err != nil {
		return NSS_STATUS_UNAVAIL
	}

	if strings.HasSuffix(pn, "/sbin/init") {
		host, err := host.Info()

		if err != nil {
			return NSS_STATUS_UNAVAIL
		}

		if host.PlatformFamily == "debian" {
			return NSS_STATUS_NOTFOUND
		}
	}

	pn := os.Args[0]
	if strings.HasSuffix(pn, "dbus-daemon") {
		interfaces, err := net.Interfaces()

		if err != nil {
			return NSS_STATUS_UNAVAIL
		}

		for _, i := range interfaces {
			if strings.Contains(i.Flags.String(), "up") {
				return NSS_STATUS_SUCCESS
			}
		}
	}

	return NSS_STATUS_SUCCESS
}
<|endoftext|>


<commit_before>package link

import (
	"errors"

	"github.com/cilium/ebpf"
	"github.com/cilium/ebpf/asm"
	"github.com/cilium/ebpf/internal"
	"github.com/cilium/ebpf/internal/sys"
	"github.com/cilium/ebpf/internal/unix"
)

// Type is the kind of link.
type Type = sys.LinkType

// Valid link types.
const (
	UnspecifiedType   = sys.BPF_LINK_TYPE_UNSPEC
	RawTracepointType = sys.BPF_LINK_TYPE_RAW_TRACEPOINT
	TracingType       = sys.BPF_LINK_TYPE_TRACING
	CgroupType        = sys.BPF_LINK_TYPE_CGROUP
	IterType          = sys.BPF_LINK_TYPE_ITER
	NetNsType         = sys.BPF_LINK_TYPE_NETNS
	XDPType           = sys.BPF_LINK_TYPE_XDP
)

var haveProgAttach = internal.FeatureTest("BPF_PROG_ATTACH", "4.10", func() error {
	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
		Type:       ebpf.CGroupSKB,
		AttachType: ebpf.AttachCGroupInetIngress,
		License:    "MIT",
		Instructions: asm.Instructions{
			asm.Mov.Imm(asm.R0, 0),
			asm.Return(),
		},
	})
	if err != nil {
		return internal.ErrNotSupported
	}

	// BPF_PROG_ATTACH was introduced at the same time as CGgroupSKB,
	// so being able to load the program is enough to infer that we
	// have the syscall.
	prog.Close()
	return nil
})

var haveProgAttachReplace = internal.FeatureTest("BPF_PROG_ATTACH atomic replacement", "5.5", func() error {
	if err := haveProgAttach(); err != nil {
		return err
	}

	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
		Type:       ebpf.CGroupSKB,
		AttachType: ebpf.AttachCGroupInetIngress,
		License:    "MIT",
		Instructions: asm.Instructions{
			asm.Mov.Imm(asm.R0, 0),
			asm.Return(),
		},
	})
	if err != nil {
		return internal.ErrNotSupported
	}
	defer prog.Close()

	// We know that we have BPF_PROG_ATTACH since we can load CGroupSKB programs.
	// If passing BPF_F_REPLACE gives us EINVAL we know that the feature isn't
	// present.
	attr := sys.ProgAttachAttr{
		// We rely on this being checked after attachFlags.
		TargetFd:    ^uint32(0),
		AttachBpfFd: uint32(prog.FD()),
		AttachType:  uint32(ebpf.AttachCGroupInetIngress),
		AttachFlags: uint32(flagReplace),
	}

	err = sys.ProgAttach(&attr)
	if errors.Is(err, unix.EINVAL) {
		return internal.ErrNotSupported
	}
	if errors.Is(err, unix.EBADF) {
		return nil
	}
	return err
})

var haveBPFLink = internal.FeatureTest("bpf_link", "5.7", func() error {
	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
		Type:       ebpf.CGroupSKB,
		AttachType: ebpf.AttachCGroupInetIngress,
		License:    "MIT",
		Instructions: asm.Instructions{
			asm.Mov.Imm(asm.R0, 0),
			asm.Return(),
		},
	})
	if err != nil {
		return internal.ErrNotSupported
	}
	defer prog.Close()

	attr := sys.LinkCreateAttr{
		// This is a hopefully invalid file descriptor, which triggers EBADF.
		TargetFd:   ^uint32(0),
		ProgFd:     uint32(prog.FD()),
		AttachType: sys.AttachType(ebpf.AttachCGroupInetIngress),
	}
	_, err = sys.LinkCreate(&attr)
	if errors.Is(err, unix.EINVAL) {
		return internal.ErrNotSupported
	}
	if errors.Is(err, unix.EBADF) {
		return nil
	}
	return err
})
<commit_msg>link: simplify link feature test<commit_after>package link

import (
	"errors"

	"github.com/cilium/ebpf"
	"github.com/cilium/ebpf/asm"
	"github.com/cilium/ebpf/internal"
	"github.com/cilium/ebpf/internal/sys"
	"github.com/cilium/ebpf/internal/unix"
)

// Type is the kind of link.
type Type = sys.LinkType

// Valid link types.
const (
	UnspecifiedType   = sys.BPF_LINK_TYPE_UNSPEC
	RawTracepointType = sys.BPF_LINK_TYPE_RAW_TRACEPOINT
	TracingType       = sys.BPF_LINK_TYPE_TRACING
	CgroupType        = sys.BPF_LINK_TYPE_CGROUP
	IterType          = sys.BPF_LINK_TYPE_ITER
	NetNsType         = sys.BPF_LINK_TYPE_NETNS
	XDPType           = sys.BPF_LINK_TYPE_XDP
)

var haveProgAttach = internal.FeatureTest("BPF_PROG_ATTACH", "4.10", func() error {
	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
		Type:       ebpf.CGroupSKB,
		AttachType: ebpf.AttachCGroupInetIngress,
		License:    "MIT",
		Instructions: asm.Instructions{
			asm.Mov.Imm(asm.R0, 0),
			asm.Return(),
		},
	})
	if err != nil {
		return internal.ErrNotSupported
	}

	// BPF_PROG_ATTACH was introduced at the same time as CGgroupSKB,
	// so being able to load the program is enough to infer that we
	// have the syscall.
	prog.Close()
	return nil
})

var haveProgAttachReplace = internal.FeatureTest("BPF_PROG_ATTACH atomic replacement", "5.5", func() error {
	if err := haveProgAttach(); err != nil {
		return err
	}

	prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
		Type:       ebpf.CGroupSKB,
		AttachType: ebpf.AttachCGroupInetIngress,
		License:    "MIT",
		Instructions: asm.Instructions{
			asm.Mov.Imm(asm.R0, 0),
			asm.Return(),
		},
	})
	if err != nil {
		return internal.ErrNotSupported
	}
	defer prog.Close()

	// We know that we have BPF_PROG_ATTACH since we can load CGroupSKB programs.
	// If passing BPF_F_REPLACE gives us EINVAL we know that the feature isn't
	// present.
	attr := sys.ProgAttachAttr{
		// We rely on this being checked after attachFlags.
		TargetFd:    ^uint32(0),
		AttachBpfFd: uint32(prog.FD()),
		AttachType:  uint32(ebpf.AttachCGroupInetIngress),
		AttachFlags: uint32(flagReplace),
	}

	err = sys.ProgAttach(&attr)
	if errors.Is(err, unix.EINVAL) {
		return internal.ErrNotSupported
	}
	if errors.Is(err, unix.EBADF) {
		return nil
	}
	return err
})

var haveBPFLink = internal.FeatureTest("bpf_link", "5.7", func() error {
	attr := sys.LinkCreateAttr{
		// This is a hopefully invalid file descriptor, which triggers EBADF.
		TargetFd:   ^uint32(0),
		ProgFd:     ^uint32(0),
		AttachType: sys.AttachType(ebpf.AttachCGroupInetIngress),
	}
	_, err := sys.LinkCreate(&attr)
	if errors.Is(err, unix.EINVAL) {
		return internal.ErrNotSupported
	}
	if errors.Is(err, unix.EBADF) {
		return nil
	}
	return err
})
<|endoftext|>


<commit_before>/*
Copyright 2021 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 node

import (
	"time"

	v1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/kubernetes/pkg/kubelet/util/format"
	"k8s.io/kubernetes/test/e2e/framework"
	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
	imageutils "k8s.io/kubernetes/test/utils/image"

	"github.com/onsi/ginkgo"
)

var _ = SIGDescribe("Ephemeral Containers", func() {
	f := framework.NewDefaultFramework("ephemeral-containers-test")
	var podClient *framework.PodClient
	ginkgo.BeforeEach(func() {
		podClient = f.PodClient()
	})

	ginkgo.It("will start an ephemeral container in an existing pod", func() {
		ginkgo.By("creating a target pod")
		pod := podClient.CreateSync(&v1.Pod{
			ObjectMeta: metav1.ObjectMeta{Name: "ephemeral-containers-target-pod"},
			Spec: v1.PodSpec{
				Containers: []v1.Container{
					{
						Name:    "test-container-1",
						Image:   imageutils.GetE2EImage(imageutils.BusyBox),
						Command: []string{"/bin/sleep"},
						Args:    []string{"10000"},
					},
				},
			},
		})

		ginkgo.By("adding an ephemeral container")
		ecName := "debugger"
		ec := &v1.EphemeralContainer{
			EphemeralContainerCommon: v1.EphemeralContainerCommon{
				Name:    ecName,
				Image:   imageutils.GetE2EImage(imageutils.BusyBox),
				Command: e2epod.GenerateScriptCmd("while true; do sleep 2; echo polo; done"),
				Stdin:   true,
				TTY:     true,
			},
		}
		err := podClient.AddEphemeralContainerSync(pod, ec, time.Minute)
		// BEGIN TODO: Remove when EphemeralContainers feature gate is retired.
		if apierrors.IsNotFound(err) {
			e2eskipper.Skipf("Skipping test because EphemeralContainers feature disabled (error: %q)", err)
		}
		// END TODO: Remove when EphemeralContainers feature gate is retired.
		framework.ExpectNoError(err, "Failed to patch ephemeral containers in pod %q", format.Pod(pod))

		ginkgo.By("checking pod container endpoints")
		_, err = framework.LookForStringInPodExecToContainer(pod.Namespace, pod.Name, ecName, []string{"/bin/echo", "marco"}, "marco", time.Minute)
		framework.ExpectNoError(err, "Failed to exec in pod %q ephemeral container %q", format.Pod(pod), ecName)
		_, err = framework.LookForStringInLog(pod.Namespace, pod.Name, ecName, "polo", time.Minute)
		framework.ExpectNoError(err, "Failed to find logs in pod %q ephemeral container %q", format.Pod(pod), ecName)
	})
})
<commit_msg>Add NodeFeature tag to ephemeral containers e2e<commit_after>/*
Copyright 2021 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 node

import (
	"time"

	v1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/kubernetes/pkg/kubelet/util/format"
	"k8s.io/kubernetes/test/e2e/framework"
	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
	imageutils "k8s.io/kubernetes/test/utils/image"

	"github.com/onsi/ginkgo"
)

var _ = SIGDescribe("Ephemeral Containers [NodeFeature:EphemeralContainers]", func() {
	f := framework.NewDefaultFramework("ephemeral-containers-test")
	var podClient *framework.PodClient
	ginkgo.BeforeEach(func() {
		podClient = f.PodClient()
	})

	ginkgo.It("will start an ephemeral container in an existing pod", func() {
		ginkgo.By("creating a target pod")
		pod := podClient.CreateSync(&v1.Pod{
			ObjectMeta: metav1.ObjectMeta{Name: "ephemeral-containers-target-pod"},
			Spec: v1.PodSpec{
				Containers: []v1.Container{
					{
						Name:    "test-container-1",
						Image:   imageutils.GetE2EImage(imageutils.BusyBox),
						Command: []string{"/bin/sleep"},
						Args:    []string{"10000"},
					},
				},
			},
		})

		ginkgo.By("adding an ephemeral container")
		ecName := "debugger"
		ec := &v1.EphemeralContainer{
			EphemeralContainerCommon: v1.EphemeralContainerCommon{
				Name:    ecName,
				Image:   imageutils.GetE2EImage(imageutils.BusyBox),
				Command: e2epod.GenerateScriptCmd("while true; do sleep 2; echo polo; done"),
				Stdin:   true,
				TTY:     true,
			},
		}
		err := podClient.AddEphemeralContainerSync(pod, ec, time.Minute)
		// BEGIN TODO: Remove when EphemeralContainers feature gate is retired.
		if apierrors.IsNotFound(err) {
			e2eskipper.Skipf("Skipping test because EphemeralContainers feature disabled (error: %q)", err)
		}
		// END TODO: Remove when EphemeralContainers feature gate is retired.
		framework.ExpectNoError(err, "Failed to patch ephemeral containers in pod %q", format.Pod(pod))

		ginkgo.By("checking pod container endpoints")
		_, err = framework.LookForStringInPodExecToContainer(pod.Namespace, pod.Name, ecName, []string{"/bin/echo", "marco"}, "marco", time.Minute)
		framework.ExpectNoError(err, "Failed to exec in pod %q ephemeral container %q", format.Pod(pod), ecName)
		_, err = framework.LookForStringInLog(pod.Namespace, pod.Name, ecName, "polo", time.Minute)
		framework.ExpectNoError(err, "Failed to find logs in pod %q ephemeral container %q", format.Pod(pod), ecName)
	})
})
<|endoftext|>


<commit_before>/*
Copyright 2015 Google Inc. All rights reserved.

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

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

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

/*
This soak tests places a specified number of pods on each node and then
repeatedly sends queries to a service running on these pods via
a serivce
*/

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"math/rand"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
	"github.com/golang/glog"
)

var (
	queriesAverage = flag.Int("queries", 10, "Number of hostname queries to make in each iteration per pod on average")
	podsPerNode    = flag.Int("pods_per_node", 1, "Number of serve_hostname pods per node")
	upTo           = flag.Int("up_to", 1, "Number of iterations or -1 for no limit")
)

const (
	deleteTimeout        = 2 * time.Minute
	endpointTimeout      = 5 * time.Minute
	podCreateTimeout     = 2 * time.Minute
	podStartTimeout      = 30 * time.Minute
	serviceCreateTimeout = 2 * time.Minute
)

func main() {
	flag.Parse()

	glog.Infof("Starting serve_hostnames soak test with queries=%d and podsPerNode=%d upTo=%d",
		*queriesAverage, *podsPerNode, *upTo)

	settings, err := clientcmd.LoadFromFile(filepath.Join(os.Getenv("HOME"), ".kube", ".kubeconfig"))
	if err != nil {
		glog.Fatalf("Error loading configuration: %v", err.Error())
	}
	config, err := clientcmd.NewDefaultClientConfig(*settings, &clientcmd.ConfigOverrides{}).ClientConfig()
	if err != nil {
		glog.Fatalf("Failed to construct config: %v", err)
	}

	c, err := client.New(config)
	if err != nil {
		glog.Fatalf("Failed to make client: %v", err)
	}

	nodes, err := c.Nodes().List()
	if err != nil {
		glog.Fatalf("Failed to list nodes: %v", err)
	}

	if len(nodes.Items) == 0 {
		glog.Fatalf("Failed to find any nodes.")
	}

	glog.Infof("Nodes found on this cluster:")
	for i, node := range nodes.Items {
		glog.Infof("%d: %s", i, node.Name)
	}

	queries := *queriesAverage * len(nodes.Items) * *podsPerNode

	// Make a unique namespace for this test.
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	ns := "serve-hostnames-" + strconv.Itoa(r.Int()%10000)
	glog.Infof("Using namespace %s for this test.", ns)

	// Create a service for these pods.
	glog.Infof("Creating service %s/serve-hostnames", ns)
	// Make several attempts to create a service.
	var svc *api.Service
	for start := time.Now(); time.Since(start) < serviceCreateTimeout; time.Sleep(2 * time.Second) {
		t := time.Now()
		svc, err = c.Services(ns).Create(&api.Service{
			ObjectMeta: api.ObjectMeta{
				Name: "serve-hostnames",
				Labels: map[string]string{
					"name": "serve-hostname",
				},
			},
			Spec: api.ServiceSpec{
				Port:       9376,
				TargetPort: util.NewIntOrStringFromInt(9376),
				Selector: map[string]string{
					"name": "serve-hostname",
				},
			},
		})
		glog.V(4).Infof("Service create %s/server-hostnames took %v", ns, time.Since(t))
		if err == nil {
			break
		}
		glog.Warningf("After %v failed to create service %s/serve-hostnames: %v", time.Since(start), ns, err)
	}
	if err != nil {
		glog.Warningf("Unable to create service %s/%s: %v", ns, svc.Name, err)
		return
	}
	// Clean up service
	defer func() {
		glog.Infof("Cleaning up service %s/server-hostnames", ns)
		// Make several attempts to delete the service.
		for start := time.Now(); time.Since(start) < deleteTimeout; time.Sleep(1 * time.Second) {
			if err := c.Services(ns).Delete(svc.Name); err == nil {
				return
			}
			glog.Warningf("After %v unable to delete service %s/%s: %v", time.Since(start), ns, svc.Name, err)
		}
	}()

	// Put serve-hostname pods on each node.
	podNames := []string{}
	for i, node := range nodes.Items {
		for j := 0; j < *podsPerNode; j++ {
			podName := fmt.Sprintf("serve-hostname-%d-%d", i, j)
			podNames = append(podNames, podName)
			// Make several attempts
			for start := time.Now(); time.Since(start) < podCreateTimeout; time.Sleep(2 * time.Second) {
				glog.Infof("Creating pod %s/%s on node %s", ns, podName, node.Name)
				t := time.Now()
				_, err = c.Pods(ns).Create(&api.Pod{
					ObjectMeta: api.ObjectMeta{
						Name: podName,
						Labels: map[string]string{
							"name": "serve-hostname",
						},
					},
					Spec: api.PodSpec{
						Containers: []api.Container{
							{
								Name:  "serve-hostname",
								Image: "kubernetes/serve_hostname:1.1",
								Ports: []api.ContainerPort{{ContainerPort: 9376}},
							},
						},
						Host: node.Name,
					},
				})
				glog.V(4).Infof("Pod create %s/%s request took %v", ns, podName, time.Since(t))
				if err == nil {
					break
				}
				glog.Warningf("After %s failed to create pod %s/%s: %v", time.Since(start), ns, podName, err)
			}
			if err != nil {
				glog.Warningf("Failed to create pod %s/%s: %v", ns, podName, err)
				return
			}
		}
	}
	// Clean up the pods
	defer func() {
		glog.Info("Cleaning up pods")
		// Make several attempts to delete the pods.
		for _, podName := range podNames {
			for start := time.Now(); time.Since(start) < deleteTimeout; time.Sleep(1 * time.Second) {
				if err = c.Pods(ns).Delete(podName); err == nil {
					break
				}
				glog.Warningf("After %v failed to delete pod %s/%s: %v", time.Since(start), ns, podName, err)
			}
		}
	}()

	glog.Info("Waiting for the serve-hostname pods to be ready")
	for _, podName := range podNames {
		var pod *api.Pod
		for start := time.Now(); time.Since(start) < podStartTimeout; time.Sleep(5 * time.Second) {
			pod, err = c.Pods(ns).Get(podName)
			if err != nil {
				glog.Infof("Get pod %s/%s failed, ignoring for %v: %v", ns, podName, err, podStartTimeout)
				continue
			}
			if pod.Status.Phase == api.PodRunning {
				break
			}
		}
		if pod.Status.Phase != api.PodRunning {
			glog.Warningf("Gave up waiting on pod %s/%s to be running (saw %v)", ns, podName, pod.Status.Phase)
			return
		}
		glog.Infof("%s/%s is running", ns, podName)
	}

	// Wait for the endpoints to propagate.
	for start := time.Now(); time.Since(start) < endpointTimeout; time.Sleep(10 * time.Second) {
		hostname, err := c.Get().
			Namespace(ns).
			Prefix("proxy").
			Resource("services").
			Name("serve-hostnames").
			DoRaw()
		if err != nil {
			glog.Infof("After %v while making a proxy call got error %v", time.Since(start), err)
			continue
		}
		var r api.Status
		if err := json.Unmarshal(hostname, &r); err != nil {
			break
		}
		if r.Status == api.StatusFailure {
			glog.Infof("After %v got status %v", time.Since(start), string(hostname))
			continue
		}
		break
	}

	// Repeatedly make requests.
	for iteration := 0; iteration != *upTo; iteration++ {
		responses := make(map[string]int, *podsPerNode*len(nodes.Items))
		start := time.Now()
		for q := 0; q < queries; q++ {
			t := time.Now()
			hostname, err := c.Get().
				Namespace(ns).
				Prefix("proxy").
				Resource("services").
				Name("serve-hostnames").
				DoRaw()
			glog.V(4).Infof("Proxy call in namespace %s took %v", ns, time.Since(t))
			if err != nil {
				glog.Infof("Call failed during iteration %d query %d : %v", iteration, q, err)
			} else {
				responses[string(hostname)]++
			}

		}
		for k, v := range responses {
			glog.V(4).Infof("%s: %d  ", k, v)
		}
		// Report any nodes that did not respond.
		for n, node := range nodes.Items {
			for i := 0; i < *podsPerNode; i++ {
				name := fmt.Sprintf("serve-hostname-%d-%d", n, i)
				if _, ok := responses[name]; !ok {
					glog.Warningf("No response from pod %s on node %s at iteration %d", name, node.Name, iteration)
				}
			}
		}
		glog.Infof("Iteration %d took %v for %d queries (%.2f QPS)", iteration, time.Since(start), queries, float64(queries)/time.Since(start).Seconds())
	}
}
<commit_msg>Change soak test to pull image from gcr.io<commit_after>/*
Copyright 2015 Google Inc. All rights reserved.

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

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

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

/*
This soak tests places a specified number of pods on each node and then
repeatedly sends queries to a service running on these pods via
a serivce
*/

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"math/rand"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
	"github.com/golang/glog"
)

var (
	queriesAverage = flag.Int("queries", 10, "Number of hostname queries to make in each iteration per pod on average")
	podsPerNode    = flag.Int("pods_per_node", 1, "Number of serve_hostname pods per node")
	upTo           = flag.Int("up_to", 1, "Number of iterations or -1 for no limit")
)

const (
	deleteTimeout        = 2 * time.Minute
	endpointTimeout      = 5 * time.Minute
	podCreateTimeout     = 2 * time.Minute
	podStartTimeout      = 30 * time.Minute
	serviceCreateTimeout = 2 * time.Minute
)

func main() {
	flag.Parse()

	glog.Infof("Starting serve_hostnames soak test with queries=%d and podsPerNode=%d upTo=%d",
		*queriesAverage, *podsPerNode, *upTo)

	settings, err := clientcmd.LoadFromFile(filepath.Join(os.Getenv("HOME"), ".kube", ".kubeconfig"))
	if err != nil {
		glog.Fatalf("Error loading configuration: %v", err.Error())
	}
	config, err := clientcmd.NewDefaultClientConfig(*settings, &clientcmd.ConfigOverrides{}).ClientConfig()
	if err != nil {
		glog.Fatalf("Failed to construct config: %v", err)
	}

	c, err := client.New(config)
	if err != nil {
		glog.Fatalf("Failed to make client: %v", err)
	}

	nodes, err := c.Nodes().List()
	if err != nil {
		glog.Fatalf("Failed to list nodes: %v", err)
	}

	if len(nodes.Items) == 0 {
		glog.Fatalf("Failed to find any nodes.")
	}

	glog.Infof("Nodes found on this cluster:")
	for i, node := range nodes.Items {
		glog.Infof("%d: %s", i, node.Name)
	}

	queries := *queriesAverage * len(nodes.Items) * *podsPerNode

	// Make a unique namespace for this test.
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	ns := "serve-hostnames-" + strconv.Itoa(r.Int()%10000)
	glog.Infof("Using namespace %s for this test.", ns)

	// Create a service for these pods.
	glog.Infof("Creating service %s/serve-hostnames", ns)
	// Make several attempts to create a service.
	var svc *api.Service
	for start := time.Now(); time.Since(start) < serviceCreateTimeout; time.Sleep(2 * time.Second) {
		t := time.Now()
		svc, err = c.Services(ns).Create(&api.Service{
			ObjectMeta: api.ObjectMeta{
				Name: "serve-hostnames",
				Labels: map[string]string{
					"name": "serve-hostname",
				},
			},
			Spec: api.ServiceSpec{
				Port:       9376,
				TargetPort: util.NewIntOrStringFromInt(9376),
				Selector: map[string]string{
					"name": "serve-hostname",
				},
			},
		})
		glog.V(4).Infof("Service create %s/server-hostnames took %v", ns, time.Since(t))
		if err == nil {
			break
		}
		glog.Warningf("After %v failed to create service %s/serve-hostnames: %v", time.Since(start), ns, err)
	}
	if err != nil {
		glog.Warningf("Unable to create service %s/%s: %v", ns, svc.Name, err)
		return
	}
	// Clean up service
	defer func() {
		glog.Infof("Cleaning up service %s/server-hostnames", ns)
		// Make several attempts to delete the service.
		for start := time.Now(); time.Since(start) < deleteTimeout; time.Sleep(1 * time.Second) {
			if err := c.Services(ns).Delete(svc.Name); err == nil {
				return
			}
			glog.Warningf("After %v unable to delete service %s/%s: %v", time.Since(start), ns, svc.Name, err)
		}
	}()

	// Put serve-hostname pods on each node.
	podNames := []string{}
	for i, node := range nodes.Items {
		for j := 0; j < *podsPerNode; j++ {
			podName := fmt.Sprintf("serve-hostname-%d-%d", i, j)
			podNames = append(podNames, podName)
			// Make several attempts
			for start := time.Now(); time.Since(start) < podCreateTimeout; time.Sleep(2 * time.Second) {
				glog.Infof("Creating pod %s/%s on node %s", ns, podName, node.Name)
				t := time.Now()
				_, err = c.Pods(ns).Create(&api.Pod{
					ObjectMeta: api.ObjectMeta{
						Name: podName,
						Labels: map[string]string{
							"name": "serve-hostname",
						},
					},
					Spec: api.PodSpec{
						Containers: []api.Container{
							{
								Name:  "serve-hostname",
								Image: "gcr.io/google-containers/serve_hostname:1.1",
								Ports: []api.ContainerPort{{ContainerPort: 9376}},
							},
						},
						Host: node.Name,
					},
				})
				glog.V(4).Infof("Pod create %s/%s request took %v", ns, podName, time.Since(t))
				if err == nil {
					break
				}
				glog.Warningf("After %s failed to create pod %s/%s: %v", time.Since(start), ns, podName, err)
			}
			if err != nil {
				glog.Warningf("Failed to create pod %s/%s: %v", ns, podName, err)
				return
			}
		}
	}
	// Clean up the pods
	defer func() {
		glog.Info("Cleaning up pods")
		// Make several attempts to delete the pods.
		for _, podName := range podNames {
			for start := time.Now(); time.Since(start) < deleteTimeout; time.Sleep(1 * time.Second) {
				if err = c.Pods(ns).Delete(podName); err == nil {
					break
				}
				glog.Warningf("After %v failed to delete pod %s/%s: %v", time.Since(start), ns, podName, err)
			}
		}
	}()

	glog.Info("Waiting for the serve-hostname pods to be ready")
	for _, podName := range podNames {
		var pod *api.Pod
		for start := time.Now(); time.Since(start) < podStartTimeout; time.Sleep(5 * time.Second) {
			pod, err = c.Pods(ns).Get(podName)
			if err != nil {
				glog.Infof("Get pod %s/%s failed, ignoring for %v: %v", ns, podName, err, podStartTimeout)
				continue
			}
			if pod.Status.Phase == api.PodRunning {
				break
			}
		}
		if pod.Status.Phase != api.PodRunning {
			glog.Warningf("Gave up waiting on pod %s/%s to be running (saw %v)", ns, podName, pod.Status.Phase)
			return
		}
		glog.Infof("%s/%s is running", ns, podName)
	}

	// Wait for the endpoints to propagate.
	for start := time.Now(); time.Since(start) < endpointTimeout; time.Sleep(10 * time.Second) {
		hostname, err := c.Get().
			Namespace(ns).
			Prefix("proxy").
			Resource("services").
			Name("serve-hostnames").
			DoRaw()
		if err != nil {
			glog.Infof("After %v while making a proxy call got error %v", time.Since(start), err)
			continue
		}
		var r api.Status
		if err := json.Unmarshal(hostname, &r); err != nil {
			break
		}
		if r.Status == api.StatusFailure {
			glog.Infof("After %v got status %v", time.Since(start), string(hostname))
			continue
		}
		break
	}

	// Repeatedly make requests.
	for iteration := 0; iteration != *upTo; iteration++ {
		responses := make(map[string]int, *podsPerNode*len(nodes.Items))
		start := time.Now()
		for q := 0; q < queries; q++ {
			t := time.Now()
			hostname, err := c.Get().
				Namespace(ns).
				Prefix("proxy").
				Resource("services").
				Name("serve-hostnames").
				DoRaw()
			glog.V(4).Infof("Proxy call in namespace %s took %v", ns, time.Since(t))
			if err != nil {
				glog.Infof("Call failed during iteration %d query %d : %v", iteration, q, err)
			} else {
				responses[string(hostname)]++
			}

		}
		for k, v := range responses {
			glog.V(4).Infof("%s: %d  ", k, v)
		}
		// Report any nodes that did not respond.
		for n, node := range nodes.Items {
			for i := 0; i < *podsPerNode; i++ {
				name := fmt.Sprintf("serve-hostname-%d-%d", n, i)
				if _, ok := responses[name]; !ok {
					glog.Warningf("No response from pod %s on node %s at iteration %d", name, node.Name, iteration)
				}
			}
		}
		glog.Infof("Iteration %d took %v for %d queries (%.2f QPS)", iteration, time.Since(start), queries, float64(queries)/time.Since(start).Seconds())
	}
}
<|endoftext|>


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

package core

import (
	"context"
	"database/sql"
	"errors"
	"reflect"
	"time"

	"github.com/xormplus/xorm/log"
)

// Stmt reprents a stmt objects
type Stmt struct {
	*sql.Stmt
	db    *DB
	names map[string]int
	query string
}

func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
	names := make(map[string]int)
	var i int
	query = re.ReplaceAllStringFunc(query, func(src string) string {
		names[src[1:]] = i
		i++
		return "?"
	})

	start := time.Now()
	showSQL := db.NeedLogSQL(ctx)
	if showSQL {
		db.Logger.BeforeSQL(log.LogContext{
			Ctx: ctx,
			SQL: "PREPARE",
		})
	}
	stmt, err := db.DB.PrepareContext(ctx, query)
	if showSQL {
		db.Logger.AfterSQL(log.LogContext{
			Ctx:         ctx,
			SQL:         "PREPARE",
			ExecuteTime: time.Now().Sub(start),
			Err:         err,
		})
	}
	if err != nil {
		return nil, err
	}

	return &Stmt{stmt, db, names, query}, nil
}

func (db *DB) Prepare(query string) (*Stmt, error) {
	return db.PrepareContext(context.Background(), query)
}

func (s *Stmt) ExecMapContext(ctx context.Context, mp interface{}) (sql.Result, error) {
	vv := reflect.ValueOf(mp)
	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
		return nil, errors.New("mp should be a map's pointer")
	}

	args := make([]interface{}, len(s.names))
	for k, i := range s.names {
		args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
	}
	return s.ExecContext(ctx, args...)
}

func (s *Stmt) ExecMap(mp interface{}) (sql.Result, error) {
	return s.ExecMapContext(context.Background(), mp)
}

func (s *Stmt) ExecStructContext(ctx context.Context, st interface{}) (sql.Result, error) {
	vv := reflect.ValueOf(st)
	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
		return nil, errors.New("mp should be a map's pointer")
	}

	args := make([]interface{}, len(s.names))
	for k, i := range s.names {
		args[i] = vv.Elem().FieldByName(k).Interface()
	}
	return s.ExecContext(ctx, args...)
}

func (s *Stmt) ExecStruct(st interface{}) (sql.Result, error) {
	return s.ExecStructContext(context.Background(), st)
}

func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error) {
	start := time.Now()
	showSQL := s.db.NeedLogSQL(ctx)
	if showSQL {
		s.db.Logger.BeforeSQL(log.LogContext{
			Ctx:  ctx,
			SQL:  s.query,
			Args: args,
		})
	}
	res, err := s.Stmt.ExecContext(ctx, args)
	if showSQL {
		s.db.Logger.AfterSQL(log.LogContext{
			Ctx:         ctx,
			SQL:         s.query,
			Args:        args,
			ExecuteTime: time.Now().Sub(start),
			Err:         err,
		})
	}
	return res, err
}

func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error) {
	start := time.Now()
	showSQL := s.db.NeedLogSQL(ctx)
	if showSQL {
		s.db.Logger.BeforeSQL(log.LogContext{
			Ctx:  ctx,
			SQL:  s.query,
			Args: args,
		})
	}
	rows, err := s.Stmt.QueryContext(ctx, args...)
	if showSQL {
		s.db.Logger.AfterSQL(log.LogContext{
			Ctx:         ctx,
			SQL:         s.query,
			Args:        args,
			ExecuteTime: time.Now().Sub(start),
			Err:         err,
		})
	}
	if err != nil {
		return nil, err
	}
	return &Rows{rows, s.db}, nil
}

func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
	return s.QueryContext(context.Background(), args...)
}

func (s *Stmt) QueryMapContext(ctx context.Context, mp interface{}) (*Rows, error) {
	vv := reflect.ValueOf(mp)
	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
		return nil, errors.New("mp should be a map's pointer")
	}

	args := make([]interface{}, len(s.names))
	for k, i := range s.names {
		args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
	}

	return s.QueryContext(ctx, args...)
}

func (s *Stmt) QueryMap(mp interface{}) (*Rows, error) {
	return s.QueryMapContext(context.Background(), mp)
}

func (s *Stmt) QueryStructContext(ctx context.Context, st interface{}) (*Rows, error) {
	vv := reflect.ValueOf(st)
	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
		return nil, errors.New("mp should be a map's pointer")
	}

	args := make([]interface{}, len(s.names))
	for k, i := range s.names {
		args[i] = vv.Elem().FieldByName(k).Interface()
	}

	return s.Query(args...)
}

func (s *Stmt) QueryStruct(st interface{}) (*Rows, error) {
	return s.QueryStructContext(context.Background(), st)
}

func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row {
	rows, err := s.QueryContext(ctx, args...)
	return &Row{rows, err}
}

func (s *Stmt) QueryRow(args ...interface{}) *Row {
	return s.QueryRowContext(context.Background(), args...)
}

func (s *Stmt) QueryRowMapContext(ctx context.Context, mp interface{}) *Row {
	vv := reflect.ValueOf(mp)
	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
		return &Row{nil, errors.New("mp should be a map's pointer")}
	}

	args := make([]interface{}, len(s.names))
	for k, i := range s.names {
		args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
	}

	return s.QueryRowContext(ctx, args...)
}

func (s *Stmt) QueryRowMap(mp interface{}) *Row {
	return s.QueryRowMapContext(context.Background(), mp)
}

func (s *Stmt) QueryRowStructContext(ctx context.Context, st interface{}) *Row {
	vv := reflect.ValueOf(st)
	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
		return &Row{nil, errors.New("st should be a struct's pointer")}
	}

	args := make([]interface{}, len(s.names))
	for k, i := range s.names {
		args[i] = vv.Elem().FieldByName(k).Interface()
	}

	return s.QueryRowContext(ctx, args...)
}

func (s *Stmt) QueryRowStruct(st interface{}) *Row {
	return s.QueryRowStructContext(context.Background(), st)
}
<commit_msg>fix context not deliver in QueryStructContext<commit_after>// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package core

import (
	"context"
	"database/sql"
	"errors"
	"reflect"
	"time"

	"github.com/xormplus/xorm/log"
)

// Stmt reprents a stmt objects
type Stmt struct {
	*sql.Stmt
	db    *DB
	names map[string]int
	query string
}

func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
	names := make(map[string]int)
	var i int
	query = re.ReplaceAllStringFunc(query, func(src string) string {
		names[src[1:]] = i
		i++
		return "?"
	})

	start := time.Now()
	showSQL := db.NeedLogSQL(ctx)
	if showSQL {
		db.Logger.BeforeSQL(log.LogContext{
			Ctx: ctx,
			SQL: "PREPARE",
		})
	}
	stmt, err := db.DB.PrepareContext(ctx, query)
	if showSQL {
		db.Logger.AfterSQL(log.LogContext{
			Ctx:         ctx,
			SQL:         "PREPARE",
			ExecuteTime: time.Now().Sub(start),
			Err:         err,
		})
	}
	if err != nil {
		return nil, err
	}

	return &Stmt{stmt, db, names, query}, nil
}

func (db *DB) Prepare(query string) (*Stmt, error) {
	return db.PrepareContext(context.Background(), query)
}

func (s *Stmt) ExecMapContext(ctx context.Context, mp interface{}) (sql.Result, error) {
	vv := reflect.ValueOf(mp)
	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
		return nil, errors.New("mp should be a map's pointer")
	}

	args := make([]interface{}, len(s.names))
	for k, i := range s.names {
		args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
	}
	return s.ExecContext(ctx, args...)
}

func (s *Stmt) ExecMap(mp interface{}) (sql.Result, error) {
	return s.ExecMapContext(context.Background(), mp)
}

func (s *Stmt) ExecStructContext(ctx context.Context, st interface{}) (sql.Result, error) {
	vv := reflect.ValueOf(st)
	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
		return nil, errors.New("mp should be a map's pointer")
	}

	args := make([]interface{}, len(s.names))
	for k, i := range s.names {
		args[i] = vv.Elem().FieldByName(k).Interface()
	}
	return s.ExecContext(ctx, args...)
}

func (s *Stmt) ExecStruct(st interface{}) (sql.Result, error) {
	return s.ExecStructContext(context.Background(), st)
}

func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error) {
	start := time.Now()
	showSQL := s.db.NeedLogSQL(ctx)
	if showSQL {
		s.db.Logger.BeforeSQL(log.LogContext{
			Ctx:  ctx,
			SQL:  s.query,
			Args: args,
		})
	}
	res, err := s.Stmt.ExecContext(ctx, args)
	if showSQL {
		s.db.Logger.AfterSQL(log.LogContext{
			Ctx:         ctx,
			SQL:         s.query,
			Args:        args,
			ExecuteTime: time.Now().Sub(start),
			Err:         err,
		})
	}
	return res, err
}

func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error) {
	start := time.Now()
	showSQL := s.db.NeedLogSQL(ctx)
	if showSQL {
		s.db.Logger.BeforeSQL(log.LogContext{
			Ctx:  ctx,
			SQL:  s.query,
			Args: args,
		})
	}
	rows, err := s.Stmt.QueryContext(ctx, args...)
	if showSQL {
		s.db.Logger.AfterSQL(log.LogContext{
			Ctx:         ctx,
			SQL:         s.query,
			Args:        args,
			ExecuteTime: time.Now().Sub(start),
			Err:         err,
		})
	}
	if err != nil {
		return nil, err
	}
	return &Rows{rows, s.db}, nil
}

func (s *Stmt) Query(args ...interface{}) (*Rows, error) {
	return s.QueryContext(context.Background(), args...)
}

func (s *Stmt) QueryMapContext(ctx context.Context, mp interface{}) (*Rows, error) {
	vv := reflect.ValueOf(mp)
	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
		return nil, errors.New("mp should be a map's pointer")
	}

	args := make([]interface{}, len(s.names))
	for k, i := range s.names {
		args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
	}

	return s.QueryContext(ctx, args...)
}

func (s *Stmt) QueryMap(mp interface{}) (*Rows, error) {
	return s.QueryMapContext(context.Background(), mp)
}

func (s *Stmt) QueryStructContext(ctx context.Context, st interface{}) (*Rows, error) {
	vv := reflect.ValueOf(st)
	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
		return nil, errors.New("mp should be a map's pointer")
	}

	args := make([]interface{}, len(s.names))
	for k, i := range s.names {
		args[i] = vv.Elem().FieldByName(k).Interface()
	}

	return s.QueryContext(ctx, args...)
}

func (s *Stmt) QueryStruct(st interface{}) (*Rows, error) {
	return s.QueryStructContext(context.Background(), st)
}

func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row {
	rows, err := s.QueryContext(ctx, args...)
	return &Row{rows, err}
}

func (s *Stmt) QueryRow(args ...interface{}) *Row {
	return s.QueryRowContext(context.Background(), args...)
}

func (s *Stmt) QueryRowMapContext(ctx context.Context, mp interface{}) *Row {
	vv := reflect.ValueOf(mp)
	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
		return &Row{nil, errors.New("mp should be a map's pointer")}
	}

	args := make([]interface{}, len(s.names))
	for k, i := range s.names {
		args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
	}

	return s.QueryRowContext(ctx, args...)
}

func (s *Stmt) QueryRowMap(mp interface{}) *Row {
	return s.QueryRowMapContext(context.Background(), mp)
}

func (s *Stmt) QueryRowStructContext(ctx context.Context, st interface{}) *Row {
	vv := reflect.ValueOf(st)
	if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
		return &Row{nil, errors.New("st should be a struct's pointer")}
	}

	args := make([]interface{}, len(s.names))
	for k, i := range s.names {
		args[i] = vv.Elem().FieldByName(k).Interface()
	}

	return s.QueryRowContext(ctx, args...)
}

func (s *Stmt) QueryRowStruct(st interface{}) *Row {
	return s.QueryRowStructContext(context.Background(), st)
}
<|endoftext|>


<commit_before>//
// go-sonos
// ========
//
// Copyright (c) 2012, Ian T. Richards <ianr@panix.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

//
// A client to demonstrate controlling Sonos from the command line.
//
// cscl := (c)ontrol (s)onos from the (c)ommand (l)ine
//
package main

import (
	"errors"
	"flag"
	"fmt"
	"github.com/ianr0bkny/go-sonos"
	"github.com/ianr0bkny/go-sonos/config"
	"github.com/ianr0bkny/go-sonos/ssdp"
	"log"
	"os"
	"path"
)

var CONFIG *config.Config

func initConfig(dir string) {
	if "" == dir {
		dir = path.Join(os.Getenv("HOME"), ".go-sonos")
	}
	CONFIG = config.MakeConfig(dir)
	CONFIG.Init()
}

func cleanup() {
	CONFIG.Save()
}

func alias(flags *Args, args []string) (err error) {
	switch len(args) {
	case 0:
		for key, rec := range CONFIG.Bookmarks {
			if 0 < len(rec.Alias) {
				fmt.Printf("%s is an alias for %s\n", key, rec.UUID)
			}
		}
	case 1:
		key := args[0]
		if rec, has := CONFIG.Bookmarks[key]; has {
			if 0 < len(rec.Alias) {
				fmt.Printf("%s is an alias for %s\n", key, rec.UUID)
			} else {
				fmt.Printf("%s is not an alias\n", key)
			}
		} else {
			fmt.Printf("%s is not an alias\n", key)
		}
	case 2:
		CONFIG.AddAlias(ssdp.UUID(args[0]), args[1])
	default:
		err = errors.New("usage: alias [alias | {uuid alias}]")
	}
	return
}

func coverage(flags *Args, args []string) (err error) {
	return
}

func discover(flags *Args) {
	port := fmt.Sprintf("%d", *flags.discoveryPort)
	if mgr, err := sonos.Discover(*flags.discoveryDevice, port); nil != err {
		panic(err)
	} else {
		query := ssdp.ServiceQueryTerms{
			ssdp.ServiceKey(sonos.MUSIC_SERVICES): -1,
			ssdp.ServiceKey(sonos.RECIVA_RADIO):   -1,
		}
		res := mgr.QueryServices(query)
		if dev_list, has := res[sonos.MUSIC_SERVICES]; has {
			for _, dev := range dev_list {
				if sonos.SONOS == dev.Product() {
					fmt.Printf("%s %s\n", string(dev.UUID()), dev.Location())
					CONFIG.AddBookmark(string(dev.UUID()), dev.Product(), dev.ProductVersion(), dev.Location(), dev.UUID())
				}
			}
		}
		if dev_list, has := res[sonos.RECIVA_RADIO]; has {
			for _, dev := range dev_list {
				if sonos.RADIO == dev.Product() {
					fmt.Printf("%s %s\n", string(dev.UUID()), dev.Location())
					CONFIG.AddBookmark(string(dev.UUID()), dev.Product(), dev.ProductVersion(), dev.Location(), dev.UUID())
				}
			}
		}
	}
}

func devices(flags *Args, args []string) (err error) {
	port := fmt.Sprintf("%d", *flags.discoveryPort)
	if mgr, err := sonos.Discover(*flags.discoveryDevice, port); nil != err {
		panic(err)
	} else {
		dm := mgr.Devices()
		for uuid, dev := range dm {
			fmt.Printf("%s {\n\tProduct = %s\n\tName = %s\n\tLocation = %s\n}\n",
				uuid, dev.Product(), dev.Name(), dev.Location())
		}
	}
	return
}

func unalias(flags *Args, args []string) (err error) {
	switch len(args) {
	case 0:
		CONFIG.ClearAliases()
	case 1:
		CONFIG.ClearAlias(args[0])
	default:
		err = errors.New("usage: unalias [alias]")
	}
	return
}

type Args struct {
	alias           *string
	help, usage     *bool
	configDir       *string
	discoveryDevice *string
	discoveryPort   *int
}

func Usage() {
	fmt.Fprintf(os.Stderr, "usage: cscl [-S <uuid/alias>] [-C <configdir=~/.go-sonos/>] [-D <discovery device=eth0>]\n")
	fmt.Fprintf(os.Stderr, "            [-P <discovery port=13104>]\n")
	fmt.Fprintf(os.Stderr, "            [--help|--usage]\n")
	fmt.Fprintf(os.Stderr, "            <command> [args ...]\n\n")
	fmt.Fprintf(os.Stderr, "The available commands are:\n")
	fmt.Fprintf(os.Stderr, "   alias      Add an alias binding\n")
	fmt.Fprintf(os.Stderr, "   coverage   Report Sonos API coverage statistics\n")
	fmt.Fprintf(os.Stderr, "   devices    Report devices found during discovery\n")
	fmt.Fprintf(os.Stderr, "   discover   Start SSDP device discovery\n")
	fmt.Fprintf(os.Stderr, "   unalias    Remove an alias binding\n")
	fmt.Fprintf(os.Stderr, "\n")
}

func main() {
	log.SetFlags(log.Ltime | log.Lshortfile)

	args := Args{}
	args.alias = flag.String("S", "", "device alias name")
	args.configDir = flag.String("C", "", "go-sonos configuration directory")
	args.discoveryDevice = flag.String("D", "eth0", "discovery device")
	args.discoveryPort = flag.Int("P", 13104, "discovery response port")
	args.help = flag.Bool("help", false, "show the usage message")
	args.usage = flag.Bool("usage", false, "show the usage message")
	flag.Usage = Usage
	flag.Parse()

	if 0 == len(flag.Args()) {
		flag.Usage()
		os.Exit(0)
	}

	initConfig(*args.configDir)

	for _, cmd := range flag.Args() {
		switch cmd {
		case "alias":
			alias(&args, flag.Args()[1:])
		case "coverage":
			coverage(&args, flag.Args()[1:])
		case "devices":
			devices(&args, flag.Args()[1:])
		case "discover":
			discover(&args)
		case "unalias":
			unalias(&args, flag.Args()[1:])
		default:
			flag.Usage()
		}
		break
	}

	cleanup()
}
<commit_msg>adding queue command to cscl<commit_after>//
// go-sonos
// ========
//
// Copyright (c) 2012, Ian T. Richards <ianr@panix.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

//
// A client to demonstrate controlling Sonos from the command line.
//
// cscl := (c)ontrol (s)onos from the (c)ommand (l)ine
//
package main

import (
	"errors"
	"flag"
	"fmt"
	"github.com/ianr0bkny/go-sonos"
	"github.com/ianr0bkny/go-sonos/config"
	"github.com/ianr0bkny/go-sonos/ssdp"
	"log"
	"os"
	"path"
)

var CONFIG *config.Config

func initConfig(dir string) {
	if "" == dir {
		dir = path.Join(os.Getenv("HOME"), ".go-sonos")
	}
	CONFIG = config.MakeConfig(dir)
	CONFIG.Init()
}

func cleanup() {
	CONFIG.Save()
}

func alias(flags *Args, args []string) (err error) {
	switch len(args) {
	case 0:
		for key, rec := range CONFIG.Bookmarks {
			if 0 < len(rec.Alias) {
				fmt.Printf("%s is an alias for %s\n", key, rec.UUID)
			}
		}
	case 1:
		key := args[0]
		if rec, has := CONFIG.Bookmarks[key]; has {
			if 0 < len(rec.Alias) {
				fmt.Printf("%s is an alias for %s\n", key, rec.UUID)
			} else {
				fmt.Printf("%s is not an alias\n", key)
			}
		} else {
			fmt.Printf("%s is not an alias\n", key)
		}
	case 2:
		CONFIG.AddAlias(ssdp.UUID(args[0]), args[1])
	default:
		err = errors.New("usage: alias [alias | {uuid alias}]")
	}
	return
}

func coverage(flags *Args, args []string) (err error) {
	return
}

func discover(flags *Args) {
	port := fmt.Sprintf("%d", *flags.discoveryPort)
	if mgr, err := sonos.Discover(*flags.discoveryDevice, port); nil != err {
		panic(err)
	} else {
		query := ssdp.ServiceQueryTerms{
			ssdp.ServiceKey(sonos.MUSIC_SERVICES): -1,
			ssdp.ServiceKey(sonos.RECIVA_RADIO):   -1,
		}
		res := mgr.QueryServices(query)
		if dev_list, has := res[sonos.MUSIC_SERVICES]; has {
			for _, dev := range dev_list {
				if sonos.SONOS == dev.Product() {
					fmt.Printf("%s %s\n", string(dev.UUID()), dev.Location())
					CONFIG.AddBookmark(string(dev.UUID()), dev.Product(), dev.ProductVersion(), dev.Location(), dev.UUID())
				}
			}
		}
		if dev_list, has := res[sonos.RECIVA_RADIO]; has {
			for _, dev := range dev_list {
				if sonos.RADIO == dev.Product() {
					fmt.Printf("%s %s\n", string(dev.UUID()), dev.Location())
					CONFIG.AddBookmark(string(dev.UUID()), dev.Product(), dev.ProductVersion(), dev.Location(), dev.UUID())
				}
			}
		}
	}
}

func devices(flags *Args, args []string) (err error) {
	port := fmt.Sprintf("%d", *flags.discoveryPort)
	if mgr, err := sonos.Discover(*flags.discoveryDevice, port); nil != err {
		panic(err)
	} else {
		dm := mgr.Devices()
		for uuid, dev := range dm {
			fmt.Printf("%s {\n\tProduct = %s\n\tName = %s\n\tLocation = %s\n}\n",
				uuid, dev.Product(), dev.Name(), dev.Location())
		}
	}
	return
}

func queue(flags *Args, args []string) (err error) {
	if 1 != len(args) {
		log.Fatal("usage: cscl queue alias")
	}
	if dev := CONFIG.Lookup(args[0]); nil != dev {
		s := sonos.Connect(dev, nil, sonos.SVC_CONTENT_DIRECTORY)
		if q, err := s.GetQueueContents(); nil != err {
			log.Fatal("GetQueueContents: %#v", err)
		} else {
			for _, track := range q {
				log.Printf("%s\n", track.Title())
			}
		}
	} else {
		log.Fatal("unknown device")
	}
	return
}

func unalias(flags *Args, args []string) (err error) {
	switch len(args) {
	case 0:
		CONFIG.ClearAliases()
	case 1:
		CONFIG.ClearAlias(args[0])
	default:
		err = errors.New("usage: unalias [alias]")
	}
	return
}

type Args struct {
	alias           *string
	help, usage     *bool
	configDir       *string
	discoveryDevice *string
	discoveryPort   *int
}

func Usage() {
	fmt.Fprintf(os.Stderr, "usage: cscl [-S <uuid/alias>] [-C <configdir=~/.go-sonos/>] [-D <discovery device=eth0>]\n")
	fmt.Fprintf(os.Stderr, "            [-P <discovery port=13104>]\n")
	fmt.Fprintf(os.Stderr, "            [--help|--usage]\n")
	fmt.Fprintf(os.Stderr, "            <command> [args ...]\n\n")
	fmt.Fprintf(os.Stderr, "The available commands are:\n")
	fmt.Fprintf(os.Stderr, "   alias      Add an alias binding\n")
	fmt.Fprintf(os.Stderr, "   coverage   Report Sonos API coverage statistics\n")
	fmt.Fprintf(os.Stderr, "   devices    Report devices found during discovery\n")
	fmt.Fprintf(os.Stderr, "   discover   Start SSDP device discovery\n")
	fmt.Fprintf(os.Stderr, "   unalias    Remove an alias binding\n")
	fmt.Fprintf(os.Stderr, "\n")
}

func main() {
	log.SetFlags(log.Ltime | log.Lshortfile)

	args := Args{}
	args.alias = flag.String("S", "", "device alias name")
	args.configDir = flag.String("C", "", "go-sonos configuration directory")
	args.discoveryDevice = flag.String("D", "eth0", "discovery device")
	args.discoveryPort = flag.Int("P", 13104, "discovery response port")
	args.help = flag.Bool("help", false, "show the usage message")
	args.usage = flag.Bool("usage", false, "show the usage message")
	flag.Usage = Usage
	flag.Parse()

	if 0 == len(flag.Args()) {
		flag.Usage()
		os.Exit(0)
	}

	initConfig(*args.configDir)

	for _, cmd := range flag.Args() {
		switch cmd {
		case "alias":
			alias(&args, flag.Args()[1:])
		case "coverage":
			coverage(&args, flag.Args()[1:])
		case "devices":
			devices(&args, flag.Args()[1:])
		case "discover":
			discover(&args)
		case "queue":
			queue(&args, flag.Args()[1:])
		case "unalias":
			unalias(&args, flag.Args()[1:])
		default:
			flag.Usage()
		}
		break
	}

	cleanup()
}
<|endoftext|>


<commit_before>package modules

import (
	"fmt"
	"net/http"
	"regexp"
	"strings"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/context"

	"github.com/dockercn/wharf/models"
	"github.com/dockercn/wharf/utils"
)

func authBasic(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {

	if len(Ctx.Input.Header("Authorization")) == 0 {
		//不存在 Authorization 信息返回错误信息
		beego.Error("[API 用户] Docker 命令访问 HTTP API 的 Header 中没有 Authorization 信息: ")
		beego.Error(Ctx.Request.Header)

		ErrCode = http.StatusUnauthorized
		ErrInfo = []byte("{\"错误\":\"没有找到 Authorization 的认证信息\"}")
		IsAuth = false
		return
	}
	isBasicIndex := strings.Index(Ctx.Input.Header("Authorization"), "Basic")

	if isBasicIndex == -1 {
		beego.Error("[API 用户] Docker 命令访问 HTTP API 的 Header 中没有 Basic Auth 和 Token 的信息 ")
		beego.Error(Ctx.Request.Header)

		ErrCode = http.StatusUnauthorized
		ErrInfo = []byte("{\"错误\":\"没有找到 Authorization 的认证信息\"}")
		IsAuth = false
		return

	}
	//解码 Basic Auth 进行用户的判断
	username, passwd, err := utils.DecodeBasicAuth(Ctx.Input.Header("Authorization"))

	if err != nil {
		beego.Error(fmt.Sprintf("[API 用户] 解码 Header Authorization 的 Basic Auth [%s] 时遇到错误： %s", Ctx.Input.Header("Authorization"), err.Error()))
		ErrCode = http.StatusUnauthorized
		ErrInfo = []byte([]byte("{\"错误\":\"解码 Authorization 的 Basic Auth 信息错误\"}"))
		IsAuth = false
		return

	}

	//根据解码的数据，在数据库中查询用户
	user := new(models.User)
	err = user.Get(username, passwd)
	if err != nil {
		//查询用户数据失败，返回 401 错误
		beego.Error(fmt.Sprintf("[API 用户] 验证用户错误：%s", err.Error()))
		ErrCode = http.StatusUnauthorized
		ErrInfo = []byte(`{"错误":"验证用户错误"}`)
		IsAuth = false
		return
	}

	IsAuth = true
	ErrCode = 0
	ErrInfo = nil
	return

}

func authNamespace(Ctx *context.Context) (IsAuth bool, NamespaceType bool, ErrCode int, ErrInfo []byte, Read bool, Write bool) {

	//根据 Namespace 查询数据
	namespace := string(Ctx.Input.Param(":namespace"))
	repository := string(Ctx.Input.Param(":repository"))
	//	NamespaceType = false //默认用户为普通户用，不是组织

	//判断是用户还是组织

	org := new(models.Organization)
	orgIsHas, _, err := org.Has(namespace)
	if err != nil {
		beego.Error(fmt.Sprintf("[API 用户] 查询组织 %s 时错误 %s", namespace, err.Error()))
		ErrCode = http.StatusForbidden
		ErrInfo = []byte(`{"错误":"查询组织报错。"}`)
		IsAuth = false
		return
	}

	user := new(models.User)
	userIsHas, _, err := user.Has(namespace)
	if err != nil {
		beego.Error(fmt.Sprintf("[API 用户] 查询用户 %s 时错误 %s", namespace, err.Error()))
		ErrCode = http.StatusForbidden
		ErrInfo = []byte(`{"错误":"查询用户报错。"}`)
		IsAuth = false
		return
	}

	if !orgIsHas && !userIsHas {
		beego.Error(fmt.Sprintf("[API 用户] 没有查询到namespace: %s", namespace))
		ErrCode = http.StatusForbidden
		ErrInfo = []byte(`{"错误":"没有查询到namespace。"}`)
		IsAuth = false
		return
	}

	ErrCode = 0
	ErrInfo = nil
	IsAuth = true
	Read = false
	Write = false
	NamespaceType = false //默认用户为普通户用，不是组织

	if orgIsHas {
		//NamespaceType = true
		//判断用户所在NameSpace指定的组织
		//读取用户所有的组织
		for index, value := range user.Organizations {
			fmt.Printf("遍历第[%d]个切片\n", index)
			//查找
			organization := new(models.Organization)
			err = organization.Get(value)
			if err != nil {
				beego.Error(fmt.Sprintf("[API 用户] 验证用户所在组织namespace错误: %s", namespace))
				ErrCode = http.StatusForbidden
				ErrInfo = []byte(`{"错误":"验证用户所在组织namespace错误"}`)
				IsAuth = false
				return
			}
			if namespace == organization.Organization {
				//用户在namespace 指定的组织
				NamespaceType = true
			}
		}

		//用户不在指定的组织
		if !NamespaceType {
			beego.Error(fmt.Sprintf("[API 用户] 用户不在指定的组织: %s", namespace))
			ErrCode = http.StatusForbidden
			ErrInfo = []byte(`{"错误":"用户不在指定的组织"}`)
			IsAuth = false
			return
		}

		//判断用户所有Team 对于此仓库权限的集合
		for index, value := range user.Teams {
			fmt.Printf("遍历第[%d]个Team\n", index)
			team := new(models.Team)
			err = team.Get(value)
			if err != nil {
				beego.Error(fmt.Sprintf("[API 用户] 验证用户所在Team错误"))
				ErrCode = http.StatusForbidden
				ErrInfo = []byte(`{"错误":"验证用户所在Team错误"}`)
				IsAuth = false
				return
			}
			for Pindex, Pvalue := range team.TeamPrivileges {
				fmt.Printf("遍历第[%d]个TeamPrivileges\n", Pindex)
				privilege := new(models.Privilege)
				err = privilege.Get(Pvalue)

				if err != nil {
					beego.Error(fmt.Sprintf("[API 用户] 验证用户所在Team对应的仓库权限错误"))
					ErrCode = http.StatusForbidden
					ErrInfo = []byte(`{"错误":"验证用户所在Team对应的仓库权限错误"}`)
					IsAuth = false
					return
				}
				if privilege.Repository == repository {
					if privilege.Privilege {
						Read = true
						Write = true
					} else if Read == false {
						Read = true
						Write = false
					}

				}

			}

		}

	} else {
		ErrCode = 0
		ErrInfo = nil
		IsAuth = true
		Read = true
		Write = true
		NamespaceType = false //默认用户为普通户用，不是组织
	}

	return

}

func authToken(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {

	//非 Basic Auth ，检查 Token
	if strings.Index(Ctx.Input.Header("Authorization"), "Token") == -1 {
		beego.Error("[API 用户] Docker 命令访问 HTTP API 的 Header 中没有 Basic Auth 和 Token 的信息 ")
		beego.Error(Ctx.Request.Header)
		IsAuth = false
		ErrCode = http.StatusUnauthorized
		ErrInfo = []byte("{\"错误\":\"在 HTTP Header Authorization 中没有找到 Basic Auth 和 Token 信息\"}")
		return
	}

	//使用正则获取 Token 的值
	r, _ := regexp.Compile(`Token (?P<token>\w+)`)
	tokens := r.FindStringSubmatch(Ctx.Input.Header("Authorization"))
	_, token := tokens[0], tokens[1]

	beego.Debug("[Token in Header] " + token)

	t := Ctx.Input.Session("token")

	//用 Header 中的 Token 和 Session 中得 Token 值进行比较，不相等返回错误退出执行
	if token != t {
		IsAuth = false
		ErrCode = http.StatusUnauthorized
		ErrInfo = []byte("{\"错误\":\"HTTP Header 中的 Token 和 Session 的 Token 不同\"}")
		return
	}

	IsAuth = true
	ErrCode = 0
	ErrInfo = nil
	return
}

func AuthPutRepository(Ctx *context.Context) (bool, int, []byte) {
	if auth, code, message := authBasic(Ctx); auth == false {
		return auth, code, message
	}

	if auth, _, code, message, _, write := authNamespace(Ctx); auth == false {
		return auth, code, message
	} else if write == false {
		beego.Error("[REGISTRY API V1] Without write privilege for update the repository's json")
		return auth, http.StatusForbidden, []byte("Forbidden Push Repository")
	}

	return true, 0, nil
}

func AuthPutRepositoryTag(Ctx *context.Context) (bool, int, []byte) {
	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "write" {
		beego.Error("[REGISTRY API V1] Without write privilege for update the repository's tag")
		return false, http.StatusUnauthorized, []byte("Without write privilege for update the repository's tag")
	}

	return true, 0, nil
}

func AuthPutRepositoryImage(Ctx *context.Context) (bool, int, []byte) {
	if auth, code, message := authBasic(Ctx); auth == false {
		return auth, code, message
	}

	if auth, _, code, message, _, _ := authNamespace(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "write" {
		beego.Error("[REGISTRY API V1] Without write privilege for update the repository")
		return false, http.StatusUnauthorized, []byte("Without write privilege for update the repository")
	}

	return true, 0, nil
}

func AuthGetRepositoryImages(Ctx *context.Context) (bool, int, []byte) {
	if auth, code, message := authBasic(Ctx); auth == false {
		return auth, code, message
	}

	if auth, _, code, message, _, _ := authNamespace(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "read" {
		beego.Error("[REGISTRY API V1] Without read privilege for repository json")
		return false, http.StatusUnauthorized, []byte("REGISTRY API V1] Without read privilege for repository json")
	}

	return true, 0, nil
}

func AuthGetRepositoryTags(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {

	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "read" {
		beego.Error("[REGISTRY API V1] Without read privilege for repository images")
		return false, http.StatusUnauthorized, []byte("Without read privilege for repository images")
	}

	return true, 0, nil
}

func AuthGetImageJSON(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {

	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "write" && Ctx.Input.Session("access") != "read" {
		beego.Error("[REGISTRY API V1] Without read/write privilege in user session")
		return false, http.StatusUnauthorized, []byte("Without read/write privilege in user session")
	}

	imageId := string(Ctx.Input.Param(":image_id"))

	image := new(models.Image)

	if pushed, err := image.IsPushed(imageId); err != nil {
		return false, http.StatusBadRequest, []byte("Search Image Error")
	} else if pushed == false {
		return false, http.StatusBadRequest, []byte("Search Image None")
	}

	return true, 0, nil
}

func AuthPutImageJSON(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {
	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "write" {
		beego.Error("[REGISTRY API V1] Without write image json privilege in user session")
		return false, http.StatusUnauthorized, []byte("Without write image json privilege in user session")
	}

	return true, 0, nil
}

func AuthPutImageLayer(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {
	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "write" {
		beego.Error("[REGISTRY API V1] Without write image privilege in user session")
		return false, http.StatusUnauthorized, []byte("Without write image privilege in user session")
	}

	return true, 0, nil
}

func AuthPutChecksum(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {
	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "write" {
		beego.Error("[REGISTRY API V1] Without write image checksum privilege in user session")
		return false, http.StatusUnauthorized, []byte("Without write image checksum privilege in user session")
	}

	return true, 0, nil
}

func AuthGetImageAncestry(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {
	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "read" {
		beego.Error("[REGISTRY API V1] Without read image ancestry privilege in user session")
		return false, http.StatusUnauthorized, []byte("Without read image ancestry privilege in user session")
	}

	return true, 0, nil
}

func AuthGetImageLayer(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {
	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "read" {
		beego.Error("[REGISTRY API V1] Without read image layer privilege in user session")
		return false, http.StatusUnauthorized, []byte("Without read image layer privilege in user session")
	}

	return true, 0, nil
}
<commit_msg>重构 auth.go 代码<commit_after>package modules

import (
	"net/http"
	"regexp"
	"strings"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/context"

	"github.com/dockercn/wharf/models"
	"github.com/dockercn/wharf/utils"
)

func authBasic(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {
	if len(Ctx.Input.Header("Authorization")) == 0 {
		beego.Error("[REGISTRY API V1] Docker HTTP API Without Authorization In Header")
		beego.Error(Ctx.Request.Header)
		return false, http.StatusUnauthorized, []byte("Docker HTTP API Without Authorization In Header")
	}

	if strings.Index(Ctx.Input.Header("Authorization"), "Basic") == -1 {
		beego.Error("[REGISTRY API V1] Docker HTTP API Without Authorization And Token In Header")
		beego.Error(Ctx.Request.Header)
		return false, http.StatusUnauthorized, []byte("Docker HTTP API Without Authorization And Token In Header")
	}

	if username, passwd, err := utils.DecodeBasicAuth(Ctx.Input.Header("Authorization")); err != nil {
		beego.Error("[REGISTRY API V1] Decode Header Authorization Basic Auth Error: ", err.Error())
		return false, http.StatusUnauthorized, []byte("Decode Header Authorization Basic Auth Error")
	} else {
		user := new(models.User)
		if err = user.Get(username, passwd); err != nil {
			beego.Error("[REGISTRY API V1] User Authorization Error: ", err.Error())

			return false, http.StatusUnauthorized, []byte("User Authorization Error")
		}

		return true, 0, nil
	}
}

func authNamespace(Ctx *context.Context) (Auth bool, NamespaceType bool, Code int, Message []byte, Read bool, Write bool) {
	namespace := string(Ctx.Input.Param(":namespace"))
	repository := string(Ctx.Input.Param(":repository"))

	org := new(models.Organization)
	isOrg, _, err := org.Has(namespace)
	if err != nil {
		beego.Error("[REGISTRY API V1] Search Organization Error: ", err.Error())
		return false, false, http.StatusForbidden, []byte("Search Organization Error"), false, false
	}

	user := new(models.User)
	isUser, _, err := user.Has(namespace)
	if err != nil {
		beego.Error("[REGISTRY API V1] Search User Error: ", err.Error())
		return false, false, http.StatusForbidden, []byte("Search User Error"), false, false
	}

	if !isUser && !isOrg {
		beego.Error("[REGISTRY API V1] Search Namespace Error")
		return false, false, http.StatusForbidden, []byte("Search Namespace Error"), false, false
	}

	Auth, NamespaceType, Code, Message, Read, Write = false, false, 0, nil, false, false

	if isOrg == true {

		for _, value := range user.Organizations {
			organization := new(models.Organization)

			if err := organization.Get(value); err != nil {
				beego.Error("[REGISTRY API V1] Search Organization Error")
				return false, false, http.StatusForbidden, []byte("Search Organization Error"), false, false
			}

			if namespace == organization.Organization {
				NamespaceType = true
			}
		}

		if NamespaceType == false {
			return false, false, http.StatusForbidden, []byte("User not in the organization"), false, false
		}

		for _, value := range user.Teams {
			team := new(models.Team)

			if err := team.Get(value); err != nil {
				beego.Error("[REGISTRY API V1] Search Team Error")
				return false, false, http.StatusForbidden, []byte("Search Team Error"), false, false
			}

			for _, v := range team.TeamPrivileges {
				privilege := new(models.Privilege)
				if err := privilege.Get(v); err != nil {
					return false, false, http.StatusForbidden, []byte("Search Team Privilege Error"), false, false
				}

				if privilege.Repository == repository {
					if privilege.Privilege == true {
						Read = true
						Write = true
					} else if Read == false {
						Read = true
						Write = false
					}

					return true, NamespaceType, Code, Message, Read, Write
				}
			}
		}
	} else {
		if user.Username == namespace {
			Auth = true
		} else {
			Auth, Code, Message = false, http.StatusUnauthorized, []byte("Unauthorized Namespace")
		}
	}

	return Auth, NamespaceType, Code, Message, Read, Write
}

func authToken(Ctx *context.Context) (bool, int, []byte) {
	if strings.Index(Ctx.Input.Header("Authorization"), "Token") == -1 {
		return false, http.StatusUnauthorized, []byte("No Basic Auth And Token In HTTP Header Authorization")
	}

	r, _ := regexp.Compile(`Token (?P<token>\w+)`)
	tokens := r.FindStringSubmatch(Ctx.Input.Header("Authorization"))
	_, token := tokens[0], tokens[1]

	t := Ctx.Input.Session("token")

	if token != t {
		return false, http.StatusUnauthorized, []byte("Unauthorized Token")
	}

	return true, 0, []byte("")
}

func AuthPutRepository(Ctx *context.Context) (bool, int, []byte) {
	if auth, code, message := authBasic(Ctx); auth == false {
		return auth, code, message
	}

	if auth, _, code, message, _, write := authNamespace(Ctx); auth == false {
		return auth, code, message
	} else if write == false {
		beego.Error("[REGISTRY API V1] Without write privilege for update the repository's json")
		return auth, http.StatusForbidden, []byte("Forbidden Push Repository")
	}

	return true, 0, nil
}

func AuthPutRepositoryTag(Ctx *context.Context) (bool, int, []byte) {
	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "write" {
		beego.Error("[REGISTRY API V1] Without write privilege for update the repository's tag")
		return false, http.StatusUnauthorized, []byte("Without write privilege for update the repository's tag")
	}

	return true, 0, nil
}

func AuthPutRepositoryImage(Ctx *context.Context) (bool, int, []byte) {
	if auth, code, message := authBasic(Ctx); auth == false {
		return auth, code, message
	}

	if auth, _, code, message, _, _ := authNamespace(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "write" {
		beego.Error("[REGISTRY API V1] Without write privilege for update the repository")
		return false, http.StatusUnauthorized, []byte("Without write privilege for update the repository")
	}

	return true, 0, nil
}

func AuthGetRepositoryImages(Ctx *context.Context) (bool, int, []byte) {
	if auth, code, message := authBasic(Ctx); auth == false {
		return auth, code, message
	}

	if auth, _, code, message, _, _ := authNamespace(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "read" {
		beego.Error("[REGISTRY API V1] Without read privilege for repository json")
		return false, http.StatusUnauthorized, []byte("REGISTRY API V1] Without read privilege for repository json")
	}

	return true, 0, nil
}

func AuthGetRepositoryTags(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {

	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "read" {
		beego.Error("[REGISTRY API V1] Without read privilege for repository images")
		return false, http.StatusUnauthorized, []byte("Without read privilege for repository images")
	}

	return true, 0, nil
}

func AuthGetImageJSON(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {

	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "write" && Ctx.Input.Session("access") != "read" {
		beego.Error("[REGISTRY API V1] Without read/write privilege in user session")
		return false, http.StatusUnauthorized, []byte("Without read/write privilege in user session")
	}

	imageId := string(Ctx.Input.Param(":image_id"))

	image := new(models.Image)

	if pushed, err := image.IsPushed(imageId); err != nil {
		return false, http.StatusBadRequest, []byte("Search Image Error")
	} else if pushed == false {
		return false, http.StatusBadRequest, []byte("Search Image None")
	}

	return true, 0, nil
}

func AuthPutImageJSON(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {
	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "write" {
		beego.Error("[REGISTRY API V1] Without write image json privilege in user session")
		return false, http.StatusUnauthorized, []byte("Without write image json privilege in user session")
	}

	return true, 0, nil
}

func AuthPutImageLayer(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {
	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "write" {
		beego.Error("[REGISTRY API V1] Without write image privilege in user session")
		return false, http.StatusUnauthorized, []byte("Without write image privilege in user session")
	}

	return true, 0, nil
}

func AuthPutChecksum(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {
	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "write" {
		beego.Error("[REGISTRY API V1] Without write image checksum privilege in user session")
		return false, http.StatusUnauthorized, []byte("Without write image checksum privilege in user session")
	}

	return true, 0, nil
}

func AuthGetImageAncestry(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {
	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "read" {
		beego.Error("[REGISTRY API V1] Without read image ancestry privilege in user session")
		return false, http.StatusUnauthorized, []byte("Without read image ancestry privilege in user session")
	}

	return true, 0, nil
}

func AuthGetImageLayer(Ctx *context.Context) (IsAuth bool, ErrCode int, ErrInfo []byte) {
	if auth, code, message := authToken(Ctx); auth == false {
		return auth, code, message
	}

	if Ctx.Input.Session("access") != "read" {
		beego.Error("[REGISTRY API V1] Without read image layer privilege in user session")
		return false, http.StatusUnauthorized, []byte("Without read image layer privilege in user session")
	}

	return true, 0, nil
}
<|endoftext|>


<commit_before>package gokeepasslib

import (
	"testing"
	"time"

	"encoding/base64"
)

func TestNewTimeData(t *testing.T) {
	timeData := NewTimeData()
	if time.Since(*timeData.CreationTime) > time.Millisecond {
		t.Error("CreationTime not properly initialized: should be time.Now()")
	}
	if time.Since(*timeData.LastModificationTime) > time.Millisecond {
		t.Error("LastModificationTime not properly initialized: should be time.Now()")
	}
	if time.Since(*timeData.LastAccessTime) > time.Millisecond {
		t.Error("LastAccessTime not properly initialized: should be time.Now()")
	}
	if timeData.ExpiryTime != nil {
		t.Error("ExpiryTime not properly initialized: should be nil")
	}
	if time.Since(*timeData.LocationChanged) > time.Millisecond {
		t.Error("LocationChanged not properly initialized: should be time.Now()")
	}
}

func TestUUID(t *testing.T) {
	one := UUID{}
	err := one.UnmarshalText([]byte("rGnBe1gIikK89aZD6n/plA=="))
	if err != nil {
		t.Fatalf("Error unmarshaling uuid", err)
	}
	mar, err := one.MarshalText()
	if err != nil {
		t.Fatalf("Error marshaling uuid")
	}
	if string(mar) != "rGnBe1gIikK89aZD6n/plA==" {
		t.Fatalf("UUID marshaled incorrectly. Expececting %s, got %s", "rGnBe1gIikK89aZD6n/plA==", mar)
	}

	two := one
	if !two.Compare(one) {
		t.Fatalf("One and Two UUIDs should be equal, are not")
	}

	three := UUID{}
	err = three.UnmarshalText([]byte("rGnBe1gIikK89aZD6n/plABBBB=="))
	if err != ErrInvalidUUIDLength {
		t.Fatal("Expected invalid uuid error, got: %s",err)
	}
}
<commit_msg>remove unused dependency<commit_after>package gokeepasslib

import (
	"testing"
	"time"
)

func TestNewTimeData(t *testing.T) {
	timeData := NewTimeData()
	if time.Since(*timeData.CreationTime) > time.Millisecond {
		t.Error("CreationTime not properly initialized: should be time.Now()")
	}
	if time.Since(*timeData.LastModificationTime) > time.Millisecond {
		t.Error("LastModificationTime not properly initialized: should be time.Now()")
	}
	if time.Since(*timeData.LastAccessTime) > time.Millisecond {
		t.Error("LastAccessTime not properly initialized: should be time.Now()")
	}
	if timeData.ExpiryTime != nil {
		t.Error("ExpiryTime not properly initialized: should be nil")
	}
	if time.Since(*timeData.LocationChanged) > time.Millisecond {
		t.Error("LocationChanged not properly initialized: should be time.Now()")
	}
}

func TestUUID(t *testing.T) {
	one := UUID{}
	err := one.UnmarshalText([]byte("rGnBe1gIikK89aZD6n/plA=="))
	if err != nil {
		t.Fatalf("Error unmarshaling uuid", err)
	}
	mar, err := one.MarshalText()
	if err != nil {
		t.Fatalf("Error marshaling uuid")
	}
	if string(mar) != "rGnBe1gIikK89aZD6n/plA==" {
		t.Fatalf("UUID marshaled incorrectly. Expececting %s, got %s", "rGnBe1gIikK89aZD6n/plA==", mar)
	}

	two := one
	if !two.Compare(one) {
		t.Fatalf("One and Two UUIDs should be equal, are not")
	}

	three := UUID{}
	err = three.UnmarshalText([]byte("rGnBe1gIikK89aZD6n/plABBBB=="))
	if err != ErrInvalidUUIDLength {
		t.Fatal("Expected invalid uuid error, got: %s",err)
	}
}
<|endoftext|>


<commit_before>package endly_test

import (
	"github.com/stretchr/testify/assert"
	"github.com/viant/endly"
	"github.com/viant/toolbox"
	"github.com/viant/toolbox/url"
	"strings"
	"sync/atomic"
	"testing"
)

func TestNewDefaultState(t *testing.T) {
	state := endly.NewDefaultState()

	for _, expr := range []string{"$rand", "${env.HOME}", "$time", "$ts", "$tmpDir", "$uuid.get", "$uuid.next", "$timestamp.now", "$timestamp.tomorrow", "$timestamp.yesterday"} {
		var expanded = state.ExpandAsText(expr)
		assert.False(t, strings.Contains(expanded, expr))
		assert.True(t, len(expr) > 0)
	}

	var expanded = state.ExpandAsText("${tmpDir.subdir}")
	assert.Contains(t, expanded, "/subdir")

}

func TestContext_Expand_Resource(t *testing.T) {
	manager := endly.New()
	context := manager.NewContext(toolbox.NewContext())

	_, err := context.ExpandResource(nil)
	assert.NotNil(t, err)
	_, err = context.ExpandResource(&url.Resource{})
	assert.NotNil(t, err)

	{
		state := context.State()
		state.Put("host", "127.0.0.1")
		expanded, err := context.ExpandResource(url.NewResource("scp://${host}/as"))
		if assert.Nil(t, err) {
			assert.EqualValues(t, "scp://127.0.0.1/as", expanded.URL)
		}
	}
	{
		_, err := context.ExpandResource(url.NewResource("path"))
		assert.Nil(t, err)
	}

}

func TestContext_NewRequest(t *testing.T) {
	manager := endly.New()
	context := manager.NewContext(toolbox.NewContext())
	{
		request, err := context.NewRequest("nop", "nop")
		if assert.Nil(t, err) {
			assert.NotNil(t, request)
		}
	}
	{
		_, err := context.NewRequest("invalid", "nop")
		assert.NotNil(t, err)
	}
	{
		_, err := context.NewRequest("nop", "abc")
		assert.NotNil(t, err)
	}

}

func TestContext_AsRequest(t *testing.T) {
	manager := endly.New()
	context := manager.NewContext(toolbox.NewContext())
	{
		request, err := context.AsRequest("nop", "nop", map[string]interface{}{})
		if assert.Nil(t, err) {
			assert.NotNil(t, request)
		}
	}
	{
		_, err := context.AsRequest("zzz", "nop", map[string]interface{}{})
		assert.NotNil(t, err)
	}

}

func TestContext_Clone(t *testing.T) {
	manager := endly.New()
	{
		context := manager.NewContext(toolbox.NewContext())
		cloned := context.Clone()
		assert.NotNil(t, cloned)

	}
	{
		var deferredRun int32 = 0
		context := manager.NewContext(toolbox.NewContext())
		context.Deffer(func() {
			atomic.AddInt32(&deferredRun, 1)
		})
		cloned := context.Clone()
		assert.False(t, cloned.IsClosed())
		context.Close()
		assert.True(t, cloned.IsClosed())
		assert.EqualValues(t, int32(2), deferredRun)
	}

}
<commit_msg>updatd call<commit_after>package endly_test

import (
	"github.com/stretchr/testify/assert"
	"github.com/viant/endly"
	"github.com/viant/toolbox"
	"github.com/viant/toolbox/url"
	"strings"
	"sync/atomic"
	"testing"
)

func TestNewDefaultState(t *testing.T) {
	state := endly.NewDefaultState(nil)

	for _, expr := range []string{"$rand", "${env.HOME}", "$time", "$ts", "$tmpDir", "$uuid.get", "$uuid.next", "$timestamp.now", "$timestamp.tomorrow", "$timestamp.yesterday"} {
		var expanded = state.ExpandAsText(expr)
		assert.False(t, strings.Contains(expanded, expr))
		assert.True(t, len(expr) > 0)
	}

	var expanded = state.ExpandAsText("${tmpDir.subdir}")
	assert.Contains(t, expanded, "/subdir")

}

func TestContext_Expand_Resource(t *testing.T) {
	manager := endly.New()
	context := manager.NewContext(toolbox.NewContext())

	_, err := context.ExpandResource(nil)
	assert.NotNil(t, err)
	_, err = context.ExpandResource(&url.Resource{})
	assert.NotNil(t, err)

	{
		state := context.State()
		state.Put("host", "127.0.0.1")
		expanded, err := context.ExpandResource(url.NewResource("scp://${host}/as"))
		if assert.Nil(t, err) {
			assert.EqualValues(t, "scp://127.0.0.1/as", expanded.URL)
		}
	}
	{
		_, err := context.ExpandResource(url.NewResource("path"))
		assert.Nil(t, err)
	}

}

func TestContext_NewRequest(t *testing.T) {
	manager := endly.New()
	context := manager.NewContext(toolbox.NewContext())
	{
		request, err := context.NewRequest("nop", "nop")
		if assert.Nil(t, err) {
			assert.NotNil(t, request)
		}
	}
	{
		_, err := context.NewRequest("invalid", "nop")
		assert.NotNil(t, err)
	}
	{
		_, err := context.NewRequest("nop", "abc")
		assert.NotNil(t, err)
	}

}

func TestContext_AsRequest(t *testing.T) {
	manager := endly.New()
	context := manager.NewContext(toolbox.NewContext())
	{
		request, err := context.AsRequest("nop", "nop", map[string]interface{}{})
		if assert.Nil(t, err) {
			assert.NotNil(t, request)
		}
	}
	{
		_, err := context.AsRequest("zzz", "nop", map[string]interface{}{})
		assert.NotNil(t, err)
	}

}

func TestContext_Clone(t *testing.T) {
	manager := endly.New()
	{
		context := manager.NewContext(toolbox.NewContext())
		cloned := context.Clone()
		assert.NotNil(t, cloned)

	}
	{
		var deferredRun int32 = 0
		context := manager.NewContext(toolbox.NewContext())
		context.Deffer(func() {
			atomic.AddInt32(&deferredRun, 1)
		})
		cloned := context.Clone()
		assert.False(t, cloned.IsClosed())
		context.Close()
		assert.True(t, cloned.IsClosed())
		assert.EqualValues(t, int32(2), deferredRun)
	}

}
<|endoftext|>


<commit_before>package ace

import (
	"encoding/json"
	"github.com/stretchr/testify/assert"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestJSONResp(t *testing.T) {
	assert := assert.New(t)

	data := struct {
		s string `json:"s"`
		n int    `json:"n"`
		b bool   `json:"b"`
	}{
		s: "test",
		n: 123,
		b: true,
	}

	a := New()
	a.GET("/", func(c *C) {
		c.JSON(200, data)
	})

	result, _ := json.Marshal(data)

	r, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()
	a.ServeHTTP(w, r)
	assert.Equal(200, w.Code)
	assert.Equal(result, w.Body.String())
	assert.Equal("application/json; charset=UTF-8", w.Header().Get("Content-Type"))
}

func TestDownloadResp(t *testing.T) {
	assert := assert.New(t)
	a := New()
	a.GET("/", func(c *C) {
		c.Download(200, []byte("123"))
	})

	r, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()
	a.ServeHTTP(w, r)
	assert.Equal(200, w.Code)
	assert.Equal("123", w.Body.String())
	assert.Equal("application/octet-stream; charset=UTF-8", w.Header().Get("Content-Type"))
}

func TestCData(t *testing.T) {
	assert := assert.New(t)
	a := New()

	a.Use(func(c *C) {
		c.SetData("test", "123")
		c.Next()
	})

	a.GET("/", func(c *C) {
		c.GetAllData()
		c.String(200, c.GetData("test").(string))
	})

	r, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()
	a.ServeHTTP(w, r)
	assert.Equal(200, w.Code)
	assert.Equal("123", w.Body.String())
}
<commit_msg>update test<commit_after>package ace

import (
	"encoding/json"
	"github.com/stretchr/testify/assert"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestJSONResp(t *testing.T) {
	assert := assert.New(t)

	data := map[string]interface{}{
		"s": "test",
		"n": 123,
		"b": true,
	}

	a := New()
	a.GET("/", func(c *C) {
		c.JSON(200, data)
	})

	result, _ := json.Marshal(data)

	r, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()
	a.ServeHTTP(w, r)
	assert.Equal(200, w.Code)
	assert.Equal(string(result), w.Body.String())
	assert.Equal("application/json; charset=UTF-8", w.Header().Get("Content-Type"))
}

func TestDownloadResp(t *testing.T) {
	assert := assert.New(t)
	a := New()
	a.GET("/", func(c *C) {
		c.Download(200, []byte("123"))
	})

	r, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()
	a.ServeHTTP(w, r)
	assert.Equal(200, w.Code)
	assert.Equal("123", w.Body.String())
	assert.Equal("application/octet-stream; charset=UTF-8", w.Header().Get("Content-Type"))
}

func TestCData(t *testing.T) {
	assert := assert.New(t)
	a := New()

	a.Use(func(c *C) {
		c.SetData("test", "123")
		c.Next()
	})

	a.GET("/", func(c *C) {
		c.GetAllData()
		c.String(200, c.GetData("test").(string))
	})

	r, _ := http.NewRequest("GET", "/", nil)
	w := httptest.NewRecorder()
	a.ServeHTTP(w, r)
	assert.Equal(200, w.Code)
	assert.Equal("123", w.Body.String())
}
<|endoftext|>