<commit_before>// +build windows

package main

import (
	"fmt"
	"log"
	"net"
	"os"
	"strings"

	"github.com/google/gopacket/pcap"
)

type Interface struct {
	Name         string
	Description  string
	Flags        uint32
	Addresses    []pcap.InterfaceAddress
	FriendlyName string
}

type InterfaceAddress struct {
	IP        net.IP
	Netmask   net.IPMask
	Broadaddr net.IP
	P2P       net.IP
}

func displayFriendlyInterfaceName() {
	devices, err := pcap.FindAllDevs()
	if err != nil {
		log.Fatal(err)
	}
	var deviceList = compare(devices)
	displayDevices(deviceList)
	os.Exit(0)
}

func displayDevices(devices []Interface) {
	fmt.Println("Devices found:")
	fmt.Printf("\n")
	for _, device := range devices {
		fmt.Println("Name: ", device.Name)
		fmt.Println("FriendlyName: ", device.FriendlyName)
		fmt.Println("Description: ", device.Description)
		fmt.Println("Devices addresses: ")
		for _, address := range device.Addresses {
			fmt.Println("\t- IP address: ", address.IP)
			fmt.Println("\t- Subnet mask: ", address.Netmask)
		}
		fmt.Printf("\n")
	}
}

func compare(devices []pcap.Interface) []Interface {
	interfaceList := []Interface{}
	var mac = getmac()
	var ni = networkInterfaceList()
	for key, element := range mac {
		for _, d := range ni {
			if strings.ReplaceAll(strings.ToUpper(d.HardwareAddr.String()), ":", "-") == key {
				for _, device := range devices {
					if strings.Contains(device.Name, match(element[0])) {
						var interfaceElement = Interface{
							Name:         device.Name,
							FriendlyName: d.Name,
							Description:  device.Description,
							Flags:        device.Flags,
							Addresses:    device.Addresses,
						}
						interfaceList = append(interfaceList, interfaceElement)
					}
				}
			}
		}
	}
	return interfaceList
}

func match(s string) string {
	i := strings.Index(s, "{")
	if i >= 0 {
		j := strings.Index(s, "}")
		if j >= 0 {
			return s[i+1 : j]
		}
	}
	return ""
}

func getmac() map[string][]string {

	ch := make(chan string)
	go func() {
		err := RunCommandCh(ch, "\r\n", "getmac")
		if err != nil {
			log.Fatal(err)
		}
	}()

	var getmacarray []string

	for v := range ch {
		if strings.Count(v, "-") == 5 {
			getmacarray = append(getmacarray, v)
		}
		if strings.Contains(v, "\\Device") {
			getmacarray = append(getmacarray, v)
		}
	}

	x := make(map[string][]string)

	for i := 0; i <= len(getmacarray)-1; {
		if i+1 <= len(getmacarray)-1 && strings.Contains(getmacarray[i+1], "\\Device") {
			x[getmacarray[i]] = append(x[getmacarray[i]], getmacarray[i+1])
		}
		i = i + 1
	}

	return x
}

func networkInterfaceList() []net.Interface {
	ifaces, err := net.Interfaces()
	if err != nil {
		fmt.Print(fmt.Errorf("localAddresses: %+v\n", err.Error()))
		return nil
	}
	return ifaces
}

func display() {
	displayFriendlyInterfaceName()
}
<commit_msg>setInterfaceFriendlyName<commit_after>// +build windows

package main

import (
	"fmt"
	"log"
	"net"
	"os"
	"strings"

	"github.com/google/gopacket/pcap"
)

type Interface struct {
	Name         string
	Description  string
	Flags        uint32
	Addresses    []pcap.InterfaceAddress
	FriendlyName string
}

type InterfaceAddress struct {
	IP        net.IP
	Netmask   net.IPMask
	Broadaddr net.IP
	P2P       net.IP
}

var deviceListGlobal []Interface

func (p *packiffer) setInterfaceFriendlyName() {
	devices, err := pcap.FindAllDevs()
	if err != nil {
		log.Fatal(err)
	}
	var deviceList = compare(devices)
	deviceListGlobal = deviceList
	for _, element := range deviceListGlobal {
		if element.Name == p.interfaceName {
			p.interfaceFriendlyName = element.FriendlyName
		}
	}
}

func displayFriendlyInterfaceName() {
	devices, err := pcap.FindAllDevs()
	if err != nil {
		log.Fatal(err)
	}
	var deviceList = compare(devices)
	deviceListGlobal = deviceList
	displayDevices(deviceList)
	os.Exit(0)
}

func displayDevices(devices []Interface) {
	fmt.Println("Devices found:")
	fmt.Printf("\n")
	for _, device := range devices {
		fmt.Println("Name: ", device.Name)
		fmt.Println("FriendlyName: ", device.FriendlyName)
		fmt.Println("Description: ", device.Description)
		fmt.Println("Devices addresses: ")
		for _, address := range device.Addresses {
			fmt.Println("\t- IP address: ", address.IP)
			fmt.Println("\t- Subnet mask: ", address.Netmask)
		}
		fmt.Printf("\n")
	}
}

func compare(devices []pcap.Interface) []Interface {
	interfaceList := []Interface{}
	var mac = getmac()
	var ni = networkInterfaceList()
	for key, element := range mac {
		for _, d := range ni {
			if strings.ReplaceAll(strings.ToUpper(d.HardwareAddr.String()), ":", "-") == key {
				for _, device := range devices {
					if strings.Contains(device.Name, match(element[0])) {
						var interfaceElement = Interface{
							Name:         device.Name,
							FriendlyName: d.Name,
							Description:  device.Description,
							Flags:        device.Flags,
							Addresses:    device.Addresses,
						}
						interfaceList = append(interfaceList, interfaceElement)
					}
				}
			}
		}
	}
	return interfaceList
}

func match(s string) string {
	i := strings.Index(s, "{")
	if i >= 0 {
		j := strings.Index(s, "}")
		if j >= 0 {
			return s[i+1 : j]
		}
	}
	return ""
}

func getmac() map[string][]string {

	ch := make(chan string)
	go func() {
		err := RunCommandCh(ch, "\r\n", "getmac")
		if err != nil {
			log.Fatal(err)
		}
	}()

	var getmacarray []string

	for v := range ch {
		if strings.Count(v, "-") == 5 {
			getmacarray = append(getmacarray, v)
		}
		if strings.Contains(v, "\\Device") {
			getmacarray = append(getmacarray, v)
		}
	}

	x := make(map[string][]string)

	for i := 0; i <= len(getmacarray)-1; {
		if i+1 <= len(getmacarray)-1 && strings.Contains(getmacarray[i+1], "\\Device") {
			x[getmacarray[i]] = append(x[getmacarray[i]], getmacarray[i+1])
		}
		i = i + 1
	}

	return x
}

func networkInterfaceList() []net.Interface {
	ifaces, err := net.Interfaces()
	if err != nil {
		fmt.Println(fmt.Errorf("localAddresses: %+v", err.Error()))
		return nil
	}
	return ifaces
}

func display() {
	displayFriendlyInterfaceName()
}
<|endoftext|>


<commit_before>package dsc

import (
	"reflect"
	"strings"

	"github.com/viant/toolbox"
)

//metaDmlProvider represents tag mapping base dml provider.
type metaDmlProvider struct {
	dmlBuilder           *DmlBuilder
	columnToFieldNameMap map[string](map[string]string)
}

func (p *metaDmlProvider) pkColumns() []string {
	return p.dmlBuilder.TableDescriptor.PkColumns
}

//Key returns primary key values
func (p *metaDmlProvider) Key(instance interface{}) []interface{} {
	result := p.readValues(instance, p.pkColumns())
	return result
}

//SetKey sets a key on passed in instance pointer
func (p *metaDmlProvider) SetKey(instancePointer interface{}, seq int64) {
	toolbox.AssertPointerKind(instancePointer, reflect.Struct, "instance")
	key := p.pkColumns()[0]
	columnSetting := p.columnToFieldNameMap[strings.ToLower(key)]
	if field, found := columnSetting["fieldName"]; found {
		var reflectable = reflect.ValueOf(instancePointer)
		if reflectable.Kind() == reflect.Ptr {
			field := reflectable.Elem().FieldByName(field)
			field.SetInt(seq)
		}

	}
}

func (p *metaDmlProvider) readValues(instance interface{}, columns []string) []interface{} {
	var result = make([]interface{}, len(columns))
	var reflectable = reflect.ValueOf(instance)
	for i, column := range columns {
		result[i] = p.readValue(reflectable, column)
	}
	return result
}

func (p *metaDmlProvider) mapValueIfNeeded(value interface{}, column string, columnSetting map[string]string) interface{} {
	if mapping, found := columnSetting["valueMap"]; found {
		stringValue := toolbox.AsString(value)
		reverseMapValue := toolbox.MakeReverseStringMap(mapping, ":", ",")
		if mappedValue, ok := reverseMapValue[stringValue]; ok {
			return mappedValue
		}
	}
	return value
}

func (p *metaDmlProvider) readValue(source reflect.Value, column string) interface{} {
	columnSetting := p.columnToFieldNameMap[strings.ToLower(column)]
	if fieldName, ok := columnSetting["fieldName"]; ok {
		field := source.FieldByName(fieldName)
		value := toolbox.UnwrapValue(&field)
		if toolbox.IsZero(field) {
			value = nil
		}
		return p.mapValueIfNeeded(value, column, columnSetting)
	}
	return nil
}

//Get returns a ParametrizedSQL for specified sqlType and target instance.
func (p *metaDmlProvider) Get(sqlType int, instance interface{}) *ParametrizedSQL {
	toolbox.AssertKind(instance, reflect.Struct, "instance")
	var reflectable = reflect.ValueOf(instance)
	return p.dmlBuilder.GetParametrizedSQL(sqlType, func(column string) interface{} {
		return p.readValue(reflectable, column)
	})
}

func newMetaDmlProvider(table string, targetType reflect.Type) DmlProvider {
	descriptor := NewTableDescriptor(table, targetType)
	dmlBuilder := NewDmlBuilder(descriptor)
	return &metaDmlProvider{dmlBuilder: dmlBuilder,
		columnToFieldNameMap: toolbox.NewFieldSettingByKey(targetType, "column")}
}

//NewDmlProviderIfNeeded returns a new NewDmlProvider for a table and target type if passed provider was nil.
func NewDmlProviderIfNeeded(provider DmlProvider, table string, targetType reflect.Type) DmlProvider {
	if provider != nil {
		return provider
	}
	var result DmlProvider
	result = newMetaDmlProvider(table, targetType)
	return result
}

//NewKeyGetterIfNeeded returns a new ketter if passedin keyGetter was nil for the target type
func NewKeyGetterIfNeeded(keyGetter KeyGetter, table string, targetType reflect.Type) KeyGetter {
	if keyGetter != nil {
		return keyGetter
	}
	var result KeyGetter
	result = newMetaDmlProvider(table, targetType)
	return result
}
<commit_msg>patched update on pointer to struct<commit_after>package dsc

import (
	"reflect"
	"strings"

	"github.com/viant/toolbox"
)

//metaDmlProvider represents tag mapping base dml provider.
type metaDmlProvider struct {
	dmlBuilder           *DmlBuilder
	columnToFieldNameMap map[string](map[string]string)
}

func (p *metaDmlProvider) pkColumns() []string {
	return p.dmlBuilder.TableDescriptor.PkColumns
}

//Key returns primary key values
func (p *metaDmlProvider) Key(instance interface{}) []interface{} {
	result := p.readValues(instance, p.pkColumns())
	return result
}

//SetKey sets a key on passed in instance pointer
func (p *metaDmlProvider) SetKey(instancePointer interface{}, seq int64) {
	toolbox.AssertPointerKind(instancePointer, reflect.Struct, "instance")
	key := p.pkColumns()[0]
	columnSetting := p.columnToFieldNameMap[strings.ToLower(key)]
	if field, found := columnSetting["fieldName"]; found {
		var reflectable = reflect.ValueOf(instancePointer)
		if reflectable.Kind() == reflect.Ptr {
			field := reflectable.Elem().FieldByName(field)
			field.SetInt(seq)
		}

	}
}

func (p *metaDmlProvider) readValues(instance interface{}, columns []string) []interface{} {
	var result = make([]interface{}, len(columns))
	var reflectable = reflect.ValueOf(instance)
	if reflectable.Kind() == reflect.Ptr {
		reflectable = reflectable.Elem()
	}
	for i, column := range columns {
		result[i] = p.readValue(reflectable, column)
	}
	return result
}

func (p *metaDmlProvider) mapValueIfNeeded(value interface{}, column string, columnSetting map[string]string) interface{} {
	if mapping, found := columnSetting["valueMap"]; found {
		stringValue := toolbox.AsString(value)
		reverseMapValue := toolbox.MakeReverseStringMap(mapping, ":", ",")
		if mappedValue, ok := reverseMapValue[stringValue]; ok {
			return mappedValue
		}
	}
	return value
}

func (p *metaDmlProvider) readValue(source reflect.Value, column string) interface{} {
	columnSetting := p.columnToFieldNameMap[strings.ToLower(column)]
	if fieldName, ok := columnSetting["fieldName"]; ok {
		field := source.FieldByName(fieldName)
		value := toolbox.UnwrapValue(&field)
		if toolbox.IsZero(field) {
			value = nil
		}
		return p.mapValueIfNeeded(value, column, columnSetting)
	}
	return nil
}

//Get returns a ParametrizedSQL for specified sqlType and target instance.
func (p *metaDmlProvider) Get(sqlType int, instance interface{}) *ParametrizedSQL {
	var reflectable = reflect.ValueOf(instance)
	if reflectable.Kind() == reflect.Ptr {
		reflectable = reflectable.Elem()
	}
	//toolbox.AssertKind(instance, reflect.Struct, "instance")
	return p.dmlBuilder.GetParametrizedSQL(sqlType, func(column string) interface{} {
		return p.readValue(reflectable, column)
	})
}

func newMetaDmlProvider(table string, targetType reflect.Type) DmlProvider {
	descriptor := NewTableDescriptor(table, targetType)
	dmlBuilder := NewDmlBuilder(descriptor)
	return &metaDmlProvider{dmlBuilder: dmlBuilder,
		columnToFieldNameMap: toolbox.NewFieldSettingByKey(targetType, "column")}
}

//NewDmlProviderIfNeeded returns a new NewDmlProvider for a table and target type if passed provider was nil.
func NewDmlProviderIfNeeded(provider DmlProvider, table string, targetType reflect.Type) DmlProvider {
	if provider != nil {
		return provider
	}
	var result DmlProvider
	result = newMetaDmlProvider(table, targetType)
	return result
}

//NewKeyGetterIfNeeded returns a new ketter if passedin keyGetter was nil for the target type
func NewKeyGetterIfNeeded(keyGetter KeyGetter, table string, targetType reflect.Type) KeyGetter {
	if keyGetter != nil {
		return keyGetter
	}
	var result KeyGetter
	result = newMetaDmlProvider(table, targetType)
	return result
}
<|endoftext|>


<commit_before>package libct

// #cgo CFLAGS: -DCONFIG_X86_64 -DARCH="x86" -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
// #cgo LDFLAGS: -l:libct.a -l:libnl-route-3.a -l:libnl-3.a -lm
// #include "../src/include/uapi/libct.h"
// #include "../src/include/uapi/libct-errors.h"
import "C"
import "fmt"
import "os"
import "unsafe"
import "syscall"

const (
	LIBCT_OPT_AUTO_PROC_MOUNT = C.LIBCT_OPT_AUTO_PROC_MOUNT
	CAPS_BSET                 = C.CAPS_BSET
	CAPS_ALLCAPS              = C.CAPS_ALLCAPS
	CAPS_ALL                  = C.CAPS_ALL
)

type Session struct {
	s C.libct_session_t
}

type Container struct {
	ct C.ct_handler_t
}

type ProcessDesc struct {
	p C.ct_process_desc_t
}

type NetDev struct {
	dev C.ct_net_t
}

type NetRoute struct {
	route C.ct_net_route_t
}

type NetRouteNextHop struct {
	nh C.ct_net_route_nh_t
}

type LibctError struct {
	Code int
}

func (e LibctError) Error() string {
	return fmt.Sprintf("LibctError: %x", e.Code)
}

func (s *Session) OpenLocal() error {
	s.s = C.libct_session_open_local()

	if s.s == nil {
		return LibctError{-1}
	}

	return nil
}

func (s *Session) ContainerCreate(name string) (*Container, error) {
	ct := C.libct_container_create(s.s, C.CString(name))

	if ct == nil {
		return nil, LibctError{-1}
	}

	return &Container{ct}, nil
}

func (s *Session) ProcessCreateDesc() (*ProcessDesc, error) {
	p := C.libct_process_desc_create(s.s)
	if p == nil {
		return nil, LibctError{-1}
	}

	return &ProcessDesc{p}, nil
}

func (ct *Container) SetNsMask(nsmask uint64) error {
	ret := C.libct_container_set_nsmask(ct.ct, C.ulong(nsmask))

	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) Kill() error {
	ret := C.libct_container_kill(ct.ct)

	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) SetConsoleFd(f *os.File) error {
	ret := C.libct_container_set_console_fd(ct.ct, C.int(f.Fd()))

	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) SpawnExecve(p *ProcessDesc, path string, argv []string, env []string, fds *[3]uintptr) (int, error) {
	var cfdsp *C.int

	cargv := make([]*C.char, len(argv)+1)
	for i, arg := range argv {
		cargv[i] = C.CString(arg)
	}

	cenv := make([]*C.char, len(env)+1)
	for i, e := range env {
		cenv[i] = C.CString(e)
	}

	if fds != nil {
		cfds := make([]C.int, 3)
		for i, fd := range fds {
			cfds[i] = C.int(fd)
		}
		cfdsp = &cfds[0]
	}

	ret := int(C.libct_container_spawn_execvefds(ct.ct, p.p, C.CString(path), &cargv[0], &cenv[0], cfdsp))
	if ret < 0 {
		return -1, LibctError{int(ret)}
	}

	return ret, nil
}

func (ct *Container) Wait() error {
	ret := C.libct_container_wait(ct.ct)

	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) Uname(host *string, domain *string) error {
	var chost *C.char
	var cdomain *C.char

	if host != nil {
		chost = C.CString(*host)
	}

	if domain != nil {
		cdomain = C.CString(*domain)
	}

	ret := C.libct_container_uname(ct.ct, chost, cdomain)

	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) SetRoot(root string) error {

	if ret := C.libct_fs_set_root(ct.ct, C.CString(root)); ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

const (
	CT_FS_RDONLY      = C.CT_FS_RDONLY
	CT_FS_PRIVATE     = C.CT_FS_PRIVATE
	CT_FS_NOEXEC      = C.CT_FS_NOEXEC
	CT_FS_NOSUID      = C.CT_FS_NOSUID
	CT_FS_NODEV       = C.CT_FS_NODEV
	CT_FS_STRICTATIME = C.CT_FS_STRICTATIME
)

func (ct *Container) AddBindMount(src string, dst string, flags int) error {

	if ret := C.libct_fs_add_bind_mount(ct.ct, C.CString(src), C.CString(dst), C.int(flags)); ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) AddMount(src string, dst string, flags int, fstype string, data string) error {

	if ret := C.libct_fs_add_mount(ct.ct, C.CString(src), C.CString(dst), C.int(flags), C.CString(fstype), C.CString(data)); ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) SetOption(opt int32) error {
	if ret := C.libct_container_set_option(ct.ct, C.int(opt), nil); ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (p *ProcessDesc) SetCaps(mask uint64, apply_to int) error {
	ret := C.libct_process_desc_set_caps(p.p, C.ulong(mask), C.uint(apply_to))
	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (p *ProcessDesc) SetParentDeathSignal(sig syscall.Signal) error {
	if ret := C.libct_process_desc_set_pdeathsig(p.p, C.int(sig)); ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) AddDeviceNode(path string, mode int, major int, minor int) error {

	ret := C.libct_fs_add_devnode(ct.ct, C.CString(path), C.int(mode), C.int(major), C.int(minor))

	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (nd *NetDev) GetPeer() (*NetDev, error) {

	dev := C.libct_net_dev_get_peer(nd.dev)

	if C.libct_handle_is_err(unsafe.Pointer(dev)) != 0 {
		return nil, LibctError{int(C.libct_handle_to_err(unsafe.Pointer(dev)))}
	}

	return &NetDev{dev}, nil
}

func (ct *Container) AddNetVeth(host_name string, ct_name string) (*NetDev, error) {

	var args C.struct_ct_net_veth_arg

	args.host_name = C.CString(host_name)
	args.ct_name = C.CString(ct_name)

	dev := C.libct_net_add(ct.ct, C.CT_NET_VETH, unsafe.Pointer(&args))

	if C.libct_handle_is_err(unsafe.Pointer(dev)) != 0 {
		return nil, LibctError{int(C.libct_handle_to_err(unsafe.Pointer(dev)))}
	}

	return &NetDev{dev}, nil
}

func (dev *NetDev) AddIpAddr(addr string) error {
	err := C.libct_net_dev_add_ip_addr(dev.dev, C.CString(addr))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (dev *NetDev) SetMaster(master string) error {
	err := C.libct_net_dev_set_master(dev.dev, C.CString(master))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (dev *NetDev) SetMtu(mtu int) error {
	err := C.libct_net_dev_set_mtu(dev.dev, C.int(mtu))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (ct *Container) AddRoute() (*NetRoute, error) {
	r := C.libct_net_route_add(ct.ct)

	if C.libct_handle_is_err(unsafe.Pointer(r)) != 0 {
		return nil, LibctError{int(C.libct_handle_to_err(unsafe.Pointer(r)))}
	}

	return &NetRoute{r}, nil
}

func (route *NetRoute) SetSrc(src string) error {
	err := C.libct_net_route_set_src(route.route, C.CString(src))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (route *NetRoute) SetDst(dst string) error {
	err := C.libct_net_route_set_dst(route.route, C.CString(dst))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (route *NetRoute) SetDev(dev string) error {
	err := C.libct_net_route_set_dev(route.route, C.CString(dev))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (route *NetRoute) AddNextHop() (*NetRouteNextHop, error) {
	nh := C.libct_net_route_add_nh(route.route)
	if C.libct_handle_is_err(unsafe.Pointer(nh)) != 0 {
		return nil, LibctError{int(C.libct_handle_to_err(unsafe.Pointer(nh)))}
	}

	return &NetRouteNextHop{nh}, nil
}

func (nh *NetRouteNextHop) SetGateway(addr string) error {
	err := C.libct_net_route_nh_set_gw(nh.nh, C.CString(addr))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (nh *NetRouteNextHop) SetDev(dev string) error {
	err := C.libct_net_route_nh_set_dev(nh.nh, C.CString(dev))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}
<commit_msg>go: add SetLSMLabel<commit_after>package libct

// #cgo CFLAGS: -DCONFIG_X86_64 -DARCH="x86" -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
// #cgo LDFLAGS: -l:libct.a -l:libnl-route-3.a -l:libnl-3.a -l:libapparmor.a -l:libselinux.a -lm
// #include "../src/include/uapi/libct.h"
// #include "../src/include/uapi/libct-errors.h"
import "C"
import "fmt"
import "os"
import "unsafe"
import "syscall"

const (
	LIBCT_OPT_AUTO_PROC_MOUNT = C.LIBCT_OPT_AUTO_PROC_MOUNT
	CAPS_BSET                 = C.CAPS_BSET
	CAPS_ALLCAPS              = C.CAPS_ALLCAPS
	CAPS_ALL                  = C.CAPS_ALL
)

type Session struct {
	s C.libct_session_t
}

type Container struct {
	ct C.ct_handler_t
}

type ProcessDesc struct {
	p C.ct_process_desc_t
}

type NetDev struct {
	dev C.ct_net_t
}

type NetRoute struct {
	route C.ct_net_route_t
}

type NetRouteNextHop struct {
	nh C.ct_net_route_nh_t
}

type LibctError struct {
	Code int
}

func (e LibctError) Error() string {
	return fmt.Sprintf("LibctError: %x", e.Code)
}

func (s *Session) OpenLocal() error {
	s.s = C.libct_session_open_local()

	if s.s == nil {
		return LibctError{-1}
	}

	return nil
}

func (s *Session) ContainerCreate(name string) (*Container, error) {
	ct := C.libct_container_create(s.s, C.CString(name))

	if ct == nil {
		return nil, LibctError{-1}
	}

	return &Container{ct}, nil
}

func (s *Session) ProcessCreateDesc() (*ProcessDesc, error) {
	p := C.libct_process_desc_create(s.s)
	if p == nil {
		return nil, LibctError{-1}
	}

	return &ProcessDesc{p}, nil
}

func (ct *Container) SetNsMask(nsmask uint64) error {
	ret := C.libct_container_set_nsmask(ct.ct, C.ulong(nsmask))

	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) Kill() error {
	ret := C.libct_container_kill(ct.ct)

	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) SetConsoleFd(f *os.File) error {
	ret := C.libct_container_set_console_fd(ct.ct, C.int(f.Fd()))

	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) SpawnExecve(p *ProcessDesc, path string, argv []string, env []string, fds *[3]uintptr) (int, error) {
	var cfdsp *C.int

	cargv := make([]*C.char, len(argv)+1)
	for i, arg := range argv {
		cargv[i] = C.CString(arg)
	}

	cenv := make([]*C.char, len(env)+1)
	for i, e := range env {
		cenv[i] = C.CString(e)
	}

	if fds != nil {
		cfds := make([]C.int, 3)
		for i, fd := range fds {
			cfds[i] = C.int(fd)
		}
		cfdsp = &cfds[0]
	}

	ret := int(C.libct_container_spawn_execvefds(ct.ct, p.p, C.CString(path), &cargv[0], &cenv[0], cfdsp))
	if ret < 0 {
		return -1, LibctError{int(ret)}
	}

	return ret, nil
}

func (ct *Container) Wait() error {
	ret := C.libct_container_wait(ct.ct)

	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) Uname(host *string, domain *string) error {
	var chost *C.char
	var cdomain *C.char

	if host != nil {
		chost = C.CString(*host)
	}

	if domain != nil {
		cdomain = C.CString(*domain)
	}

	ret := C.libct_container_uname(ct.ct, chost, cdomain)

	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) SetRoot(root string) error {

	if ret := C.libct_fs_set_root(ct.ct, C.CString(root)); ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

const (
	CT_FS_RDONLY      = C.CT_FS_RDONLY
	CT_FS_PRIVATE     = C.CT_FS_PRIVATE
	CT_FS_NOEXEC      = C.CT_FS_NOEXEC
	CT_FS_NOSUID      = C.CT_FS_NOSUID
	CT_FS_NODEV       = C.CT_FS_NODEV
	CT_FS_STRICTATIME = C.CT_FS_STRICTATIME
)

func (ct *Container) AddBindMount(src string, dst string, flags int) error {

	if ret := C.libct_fs_add_bind_mount(ct.ct, C.CString(src), C.CString(dst), C.int(flags)); ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) AddMount(src string, dst string, flags int, fstype string, data string) error {

	if ret := C.libct_fs_add_mount(ct.ct, C.CString(src), C.CString(dst), C.int(flags), C.CString(fstype), C.CString(data)); ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) SetOption(opt int32) error {
	if ret := C.libct_container_set_option(ct.ct, C.int(opt), nil); ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (p *ProcessDesc) SetCaps(mask uint64, apply_to int) error {
	ret := C.libct_process_desc_set_caps(p.p, C.ulong(mask), C.uint(apply_to))
	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (p *ProcessDesc) SetParentDeathSignal(sig syscall.Signal) error {
	if ret := C.libct_process_desc_set_pdeathsig(p.p, C.int(sig)); ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (p *ProcessDesc) SetLSMLabel(label string) error {
	if ret := C.libct_process_desc_set_lsm_label(p.p, C.CString(label)); ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (ct *Container) AddDeviceNode(path string, mode int, major int, minor int) error {

	ret := C.libct_fs_add_devnode(ct.ct, C.CString(path), C.int(mode), C.int(major), C.int(minor))

	if ret != 0 {
		return LibctError{int(ret)}
	}

	return nil
}

func (nd *NetDev) GetPeer() (*NetDev, error) {

	dev := C.libct_net_dev_get_peer(nd.dev)

	if C.libct_handle_is_err(unsafe.Pointer(dev)) != 0 {
		return nil, LibctError{int(C.libct_handle_to_err(unsafe.Pointer(dev)))}
	}

	return &NetDev{dev}, nil
}

func (ct *Container) AddNetVeth(host_name string, ct_name string) (*NetDev, error) {

	var args C.struct_ct_net_veth_arg

	args.host_name = C.CString(host_name)
	args.ct_name = C.CString(ct_name)

	dev := C.libct_net_add(ct.ct, C.CT_NET_VETH, unsafe.Pointer(&args))

	if C.libct_handle_is_err(unsafe.Pointer(dev)) != 0 {
		return nil, LibctError{int(C.libct_handle_to_err(unsafe.Pointer(dev)))}
	}

	return &NetDev{dev}, nil
}

func (dev *NetDev) AddIpAddr(addr string) error {
	err := C.libct_net_dev_add_ip_addr(dev.dev, C.CString(addr))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (dev *NetDev) SetMaster(master string) error {
	err := C.libct_net_dev_set_master(dev.dev, C.CString(master))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (dev *NetDev) SetMtu(mtu int) error {
	err := C.libct_net_dev_set_mtu(dev.dev, C.int(mtu))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (ct *Container) AddRoute() (*NetRoute, error) {
	r := C.libct_net_route_add(ct.ct)

	if C.libct_handle_is_err(unsafe.Pointer(r)) != 0 {
		return nil, LibctError{int(C.libct_handle_to_err(unsafe.Pointer(r)))}
	}

	return &NetRoute{r}, nil
}

func (route *NetRoute) SetSrc(src string) error {
	err := C.libct_net_route_set_src(route.route, C.CString(src))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (route *NetRoute) SetDst(dst string) error {
	err := C.libct_net_route_set_dst(route.route, C.CString(dst))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (route *NetRoute) SetDev(dev string) error {
	err := C.libct_net_route_set_dev(route.route, C.CString(dev))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (route *NetRoute) AddNextHop() (*NetRouteNextHop, error) {
	nh := C.libct_net_route_add_nh(route.route)
	if C.libct_handle_is_err(unsafe.Pointer(nh)) != 0 {
		return nil, LibctError{int(C.libct_handle_to_err(unsafe.Pointer(nh)))}
	}

	return &NetRouteNextHop{nh}, nil
}

func (nh *NetRouteNextHop) SetGateway(addr string) error {
	err := C.libct_net_route_nh_set_gw(nh.nh, C.CString(addr))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}

func (nh *NetRouteNextHop) SetDev(dev string) error {
	err := C.libct_net_route_nh_set_dev(nh.nh, C.CString(dev))
	if err != 0 {
		return LibctError{int(err)}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/davidscholberg/go-i3barjson"
	"github.com/davidscholberg/goblocks/lib/modules"
	"os"
	"reflect"
)

func main() {
	var cfg modules.Config
	var selectCases modules.SelectCases
	var statusLine i3barjson.StatusLine
	err := modules.Init(&cfg, &selectCases, &statusLine)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err)
		return
	}

	h := i3barjson.Header{Version: 1}
	err = i3barjson.Init(os.Stdout, nil, h, cfg.Global.Debug)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err)
		return
	}

	// send the first statusLine
	err = i3barjson.Update(statusLine)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err)
		return
	}

	for {
		// select on all chans
		i, _, _ := reflect.Select(selectCases.Cases)
		refresh, exit := selectCases.Actions[i](selectCases.Blocks[i])
		if exit {
			break
		}
		if refresh {
			err = i3barjson.Update(statusLine)
			if err != nil {
				fmt.Fprintf(os.Stderr, "%s", err)
				break
			}
		}
	}

	selectCases.StopTickers()

	fmt.Println("\ndone")
}
<commit_msg>updated output on exit to be just a newline<commit_after>package main

import (
	"fmt"
	"github.com/davidscholberg/go-i3barjson"
	"github.com/davidscholberg/goblocks/lib/modules"
	"os"
	"reflect"
)

func main() {
	var cfg modules.Config
	var selectCases modules.SelectCases
	var statusLine i3barjson.StatusLine
	err := modules.Init(&cfg, &selectCases, &statusLine)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err)
		return
	}

	h := i3barjson.Header{Version: 1}
	err = i3barjson.Init(os.Stdout, nil, h, cfg.Global.Debug)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err)
		return
	}

	// send the first statusLine
	err = i3barjson.Update(statusLine)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err)
		return
	}

	for {
		// select on all chans
		i, _, _ := reflect.Select(selectCases.Cases)
		refresh, exit := selectCases.Actions[i](selectCases.Blocks[i])
		if exit {
			break
		}
		if refresh {
			err = i3barjson.Update(statusLine)
			if err != nil {
				fmt.Fprintf(os.Stderr, "%s", err)
				break
			}
		}
	}

	selectCases.StopTickers()

	fmt.Println("")
}
<|endoftext|>


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

package goes

import (
	"fmt"
	"reflect"
)

type invalidVersionError int

func (i invalidVersionError) Error() string {
	return fmt.Sprintf("%d is not a valid event number", i)
}

// NoMoreEventsError is returned when there are no events to return
// from a request to a stream.
type NoMoreEventsError struct{}

func (e NoMoreEventsError) Error() string {
	return "There are no more events to load."
}

// NotFoundError is returned when a stream is not found.
type NotFoundError struct {
	ErrorResponse *ErrorResponse
}

func (e NotFoundError) Error() string {
	return "The stream does not exist."
}

// UnauthorizedError is returned when a request to the eventstore is
// not authorized
type UnauthorizedError struct {
	ErrorResponse *ErrorResponse
}

func (e UnauthorizedError) Error() string {
	return "You are not authorised to access the stream or the stream does not exist."
}

// TemporarilyUnavailableError is returned when the server returns ServiceUnavailable.
//
// This error may be returned if a request is made to the server during startup. When
// the server starts up initially and the client is completely unable to connect to the
// server a *url.Error will be returned. Once the server is up but not ready to serve
// requests a ServiceUnavailable error will be returned for a brief period.
type TemporarilyUnavailableError struct {
	ErrorResponse *ErrorResponse
}

func (e TemporarilyUnavailableError) Error() string {
	return "Server Is Not Ready"
}

// UnexpectedError is returned when a request to the eventstore returns an error that
// is not explicitly represented by a goes Error type such as UnauthorisedError or
// NotFoundError
type UnexpectedError struct {
	ErrorResponse *ErrorResponse
}

func (e UnexpectedError) Error() string {
	return "An unexpected error occurred."
}

// BadRequestError is returned when the server returns a bad request error
type BadRequestError struct {
	ErrorResponse *ErrorResponse
}

func (e BadRequestError) Error() string {
	return "Bad request."
}

// ConcurrencyError is returned when the server returns a bad request error
type ConcurrencyError struct {
	ErrorResponse *ErrorResponse
}

func (e ConcurrencyError) Error() string {
	return "Concurrency Error."
}

// typeOf is a helper to get the names of types.
func typeOf(i interface{}) string {
	if i == nil {
		return ""
	}
	return reflect.TypeOf(i).Elem().Name()
}
<commit_msg>Added package level comments<commit_after>// Copyright 2016 Jet Basrawi. All rights reserved.
//
// Use of this source code is governed by a permissive MIT
// license that can be found in the LICENSE file.

// Package goes provides a client abstraction over GetEventStore's HTTP API.
package goes

import (
	"fmt"
	"reflect"
)

type invalidVersionError int

func (i invalidVersionError) Error() string {
	return fmt.Sprintf("%d is not a valid event number", i)
}

// NoMoreEventsError is returned when there are no events to return
// from a request to a stream.
type NoMoreEventsError struct{}

func (e NoMoreEventsError) Error() string {
	return "There are no more events to load."
}

// NotFoundError is returned when a stream is not found.
type NotFoundError struct {
	ErrorResponse *ErrorResponse
}

func (e NotFoundError) Error() string {
	return "The stream does not exist."
}

// UnauthorizedError is returned when a request to the eventstore is
// not authorized
type UnauthorizedError struct {
	ErrorResponse *ErrorResponse
}

func (e UnauthorizedError) Error() string {
	return "You are not authorised to access the stream or the stream does not exist."
}

// TemporarilyUnavailableError is returned when the server returns ServiceUnavailable.
//
// This error may be returned if a request is made to the server during startup. When
// the server starts up initially and the client is completely unable to connect to the
// server a *url.Error will be returned. Once the server is up but not ready to serve
// requests a ServiceUnavailable error will be returned for a brief period.
type TemporarilyUnavailableError struct {
	ErrorResponse *ErrorResponse
}

func (e TemporarilyUnavailableError) Error() string {
	return "Server Is Not Ready"
}

// UnexpectedError is returned when a request to the eventstore returns an error that
// is not explicitly represented by a goes Error type such as UnauthorisedError or
// NotFoundError
type UnexpectedError struct {
	ErrorResponse *ErrorResponse
}

func (e UnexpectedError) Error() string {
	return "An unexpected error occurred."
}

// BadRequestError is returned when the server returns a bad request error
type BadRequestError struct {
	ErrorResponse *ErrorResponse
}

func (e BadRequestError) Error() string {
	return "Bad request."
}

// ConcurrencyError is returned when the server returns a bad request error
type ConcurrencyError struct {
	ErrorResponse *ErrorResponse
}

func (e ConcurrencyError) Error() string {
	return "Concurrency Error."
}

// typeOf is a helper to get the names of types.
func typeOf(i interface{}) string {
	if i == nil {
		return ""
	}
	return reflect.TypeOf(i).Elem().Name()
}
<|endoftext|>


<commit_before>/*
Copyright 2017 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 stats

import (
	"fmt"
	"time"

	"github.com/golang/glog"
	cadvisorfs "github.com/google/cadvisor/fs"

	cadvisorapiv2 "github.com/google/cadvisor/info/v2"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	internalapi "k8s.io/kubernetes/pkg/kubelet/apis/cri"
	runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
	statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
	"k8s.io/kubernetes/pkg/kubelet/cadvisor"
	"k8s.io/kubernetes/pkg/kubelet/server/stats"
)

// criStatsProvider implements the containerStatsProvider interface by getting
// the container stats from CRI.
type criStatsProvider struct {
	// cadvisor is used to get the node root filesystem's stats (such as the
	// capacity/available bytes/inodes) that will be populated in per container
	// filesystem stats.
	cadvisor cadvisor.Interface
	// resourceAnalyzer is used to get the volume stats of the pods.
	resourceAnalyzer stats.ResourceAnalyzer
	// runtimeService is used to get the status and stats of the pods and its
	// managed containers.
	runtimeService internalapi.RuntimeService
	// imageService is used to get the stats of the image filesystem.
	imageService internalapi.ImageManagerService
}

// newCRIStatsProvider returns a containerStatsProvider implementation that
// provides container stats using CRI.
func newCRIStatsProvider(
	cadvisor cadvisor.Interface,
	resourceAnalyzer stats.ResourceAnalyzer,
	runtimeService internalapi.RuntimeService,
	imageService internalapi.ImageManagerService,
) containerStatsProvider {
	return &criStatsProvider{
		cadvisor:         cadvisor,
		resourceAnalyzer: resourceAnalyzer,
		runtimeService:   runtimeService,
		imageService:     imageService,
	}
}

// ListPodStats returns the stats of all the pod-managed containers.
func (p *criStatsProvider) ListPodStats() ([]statsapi.PodStats, error) {
	// Gets node root filesystem information, which will be used to populate
	// the available and capacity bytes/inodes in container stats.
	rootFsInfo, err := p.cadvisor.RootFsInfo()
	if err != nil {
		return nil, fmt.Errorf("failed to get rootFs info: %v", err)
	}

	// Creates container map.
	containerMap := make(map[string]*runtimeapi.Container)
	containers, err := p.runtimeService.ListContainers(&runtimeapi.ContainerFilter{})
	if err != nil {
		return nil, fmt.Errorf("failed to list all containers: %v", err)
	}
	for _, c := range containers {
		containerMap[c.Id] = c
	}

	// Creates pod sandbox map.
	podSandboxMap := make(map[string]*runtimeapi.PodSandbox)
	podSandboxes, err := p.runtimeService.ListPodSandbox(&runtimeapi.PodSandboxFilter{})
	if err != nil {
		return nil, fmt.Errorf("failed to list all pod sandboxes: %v", err)
	}
	for _, s := range podSandboxes {
		podSandboxMap[s.Id] = s
	}

	// uuidToFsInfo is a map from filesystem UUID to its stats. This will be
	// used as a cache to avoid querying cAdvisor for the filesystem stats with
	// the same UUID many times.
	uuidToFsInfo := make(map[runtimeapi.StorageIdentifier]*cadvisorapiv2.FsInfo)

	// sandboxIDToPodStats is a temporary map from sandbox ID to its pod stats.
	sandboxIDToPodStats := make(map[string]*statsapi.PodStats)

	resp, err := p.runtimeService.ListContainerStats(&runtimeapi.ListContainerStatsRequest{})
	if err != nil {
		return nil, fmt.Errorf("failed to list all container stats: %v", err)
	}
	for _, stats := range resp.Stats {
		containerID := stats.Attributes.Id
		container, found := containerMap[containerID]
		if !found {
			glog.Errorf("Unknown id %q in container map.", containerID)
			continue
		}

		podSandboxID := container.PodSandboxId
		podSandbox, found := podSandboxMap[podSandboxID]
		if !found {
			glog.Errorf("Unknown id %q in pod sandbox map.", podSandboxID)
			continue
		}

		// Creates the stats of the pod (if not created yet) which the
		// container belongs to.
		ps, found := sandboxIDToPodStats[podSandboxID]
		if !found {
			ps = p.makePodStats(podSandbox)
			sandboxIDToPodStats[podSandboxID] = ps
		}
		ps.Containers = append(ps.Containers, *p.makeContainerStats(stats, container, &rootFsInfo, uuidToFsInfo))
	}

	result := make([]statsapi.PodStats, 0, len(sandboxIDToPodStats))
	for _, s := range sandboxIDToPodStats {
		result = append(result, *s)
	}
	return result, nil
}

// ImageFsStats returns the stats of the image filesystem.
func (p *criStatsProvider) ImageFsStats() (*statsapi.FsStats, error) {
	resp, err := p.imageService.ImageFsInfo(&runtimeapi.ImageFsInfoRequest{})
	if err != nil {
		return nil, err
	}

	// CRI may return the stats of multiple image filesystems but we only
	// return the first one.
	//
	// TODO(yguo0905): Support returning stats of multiple image filesystems.
	for _, fs := range resp.ImageFilesystems {
		s := &statsapi.FsStats{
			Time:       metav1.NewTime(time.Unix(0, fs.Timestamp)),
			UsedBytes:  &fs.UsedBytes.Value,
			InodesUsed: &fs.InodesUsed.Value,
		}
		imageFsInfo := p.getFsInfo(fs.StorageId)
		if imageFsInfo != nil {
			// The image filesystem UUID is unknown to the local node or
			// there's an error on retrieving the stats. In these cases, we
			// omit those stats and return the best-effort partial result. See
			// https://github.com/kubernetes/heapster/issues/1793.
			s.AvailableBytes = &imageFsInfo.Available
			s.CapacityBytes = &imageFsInfo.Capacity
			s.InodesFree = imageFsInfo.InodesFree
			s.Inodes = imageFsInfo.Inodes
		}
		return s, nil
	}

	return nil, fmt.Errorf("imageFs information is unavailable")
}

// getFsInfo returns the information of the filesystem with the specified
// storageID. If any error occurs, this function logs the error and returns
// nil.
func (p *criStatsProvider) getFsInfo(storageID *runtimeapi.StorageIdentifier) *cadvisorapiv2.FsInfo {
	if storageID == nil {
		glog.V(2).Infof("Failed to get filesystem info: storageID is nil.")
		return nil
	}
	fsInfo, err := p.cadvisor.GetFsInfoByFsUUID(storageID.Uuid)
	if err != nil {
		msg := fmt.Sprintf("Failed to get the info of the filesystem with id %q: %v.", storageID.Uuid, err)
		if err == cadvisorfs.ErrNoSuchDevice {
			glog.V(2).Info(msg)
		} else {
			glog.Error(msg)
		}
		return nil
	}
	return &fsInfo
}

func (p *criStatsProvider) makePodStats(podSandbox *runtimeapi.PodSandbox) *statsapi.PodStats {
	s := &statsapi.PodStats{
		PodRef: statsapi.PodReference{
			Name:      podSandbox.Metadata.Name,
			UID:       podSandbox.Metadata.Uid,
			Namespace: podSandbox.Metadata.Namespace,
		},
		// The StartTime in the summary API is the pod creation time.
		StartTime: metav1.NewTime(time.Unix(0, podSandbox.CreatedAt)),
		// Network stats are not supported by CRI.
	}
	podUID := types.UID(s.PodRef.UID)
	if vstats, found := p.resourceAnalyzer.GetPodVolumeStats(podUID); found {
		s.VolumeStats = vstats.Volumes
	}
	return s
}

func (p *criStatsProvider) makeContainerStats(
	stats *runtimeapi.ContainerStats,
	container *runtimeapi.Container,
	rootFsInfo *cadvisorapiv2.FsInfo,
	uuidToFsInfo map[runtimeapi.StorageIdentifier]*cadvisorapiv2.FsInfo,
) *statsapi.ContainerStats {
	result := &statsapi.ContainerStats{
		Name: stats.Attributes.Metadata.Name,
		// The StartTime in the summary API is the container creation time.
		StartTime: metav1.NewTime(time.Unix(0, container.CreatedAt)),
		CPU:       &statsapi.CPUStats{},
		Memory:    &statsapi.MemoryStats{},
		Rootfs:    &statsapi.FsStats{},
		Logs: &statsapi.FsStats{
			Time:           metav1.NewTime(rootFsInfo.Timestamp),
			AvailableBytes: &rootFsInfo.Available,
			CapacityBytes:  &rootFsInfo.Capacity,
			InodesFree:     rootFsInfo.InodesFree,
			Inodes:         rootFsInfo.Inodes,
			// UsedBytes and InodesUsed are unavailable from CRI stats.
			//
			// TODO(yguo0905): Get this information from kubelet and
			// populate the two fields here.
		},
		// UserDefinedMetrics is not supported by CRI.
	}
	if stats.Cpu != nil {
		result.CPU.Time = metav1.NewTime(time.Unix(0, stats.Cpu.Timestamp))
		if stats.Cpu.UsageCoreNanoSeconds != nil {
			result.CPU.UsageCoreNanoSeconds = &stats.Cpu.UsageCoreNanoSeconds.Value
		}
	}
	if stats.Memory != nil {
		result.Memory.Time = metav1.NewTime(time.Unix(0, stats.Memory.Timestamp))
		if stats.Memory.WorkingSetBytes != nil {
			result.Memory.WorkingSetBytes = &stats.Memory.WorkingSetBytes.Value
		}
	}
	if stats.WritableLayer != nil {
		result.Rootfs.Time = metav1.NewTime(time.Unix(0, stats.WritableLayer.Timestamp))
		if stats.WritableLayer.UsedBytes != nil {
			result.Rootfs.UsedBytes = &stats.WritableLayer.UsedBytes.Value
		}
		if stats.WritableLayer.InodesUsed != nil {
			result.Rootfs.InodesUsed = &stats.WritableLayer.InodesUsed.Value
		}
	}
	storageID := stats.WritableLayer.StorageId
	if storageID != nil {
		imageFsInfo, found := uuidToFsInfo[*storageID]
		if !found {
			imageFsInfo = p.getFsInfo(storageID)
			uuidToFsInfo[*storageID] = imageFsInfo
		}
		if imageFsInfo != nil {
			// The image filesystem UUID is unknown to the local node or there's an
			// error on retrieving the stats. In these cases, we omit those stats
			// and return the best-effort partial result. See
			// https://github.com/kubernetes/heapster/issues/1793.
			result.Rootfs.AvailableBytes = &imageFsInfo.Available
			result.Rootfs.CapacityBytes = &imageFsInfo.Capacity
			result.Rootfs.InodesFree = imageFsInfo.InodesFree
			result.Rootfs.Inodes = imageFsInfo.Inodes
		}
	}

	return result
}
<commit_msg>Handle nil WritableLayer<commit_after>/*
Copyright 2017 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 stats

import (
	"fmt"
	"time"

	"github.com/golang/glog"
	cadvisorfs "github.com/google/cadvisor/fs"

	cadvisorapiv2 "github.com/google/cadvisor/info/v2"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	internalapi "k8s.io/kubernetes/pkg/kubelet/apis/cri"
	runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
	statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
	"k8s.io/kubernetes/pkg/kubelet/cadvisor"
	"k8s.io/kubernetes/pkg/kubelet/server/stats"
)

// criStatsProvider implements the containerStatsProvider interface by getting
// the container stats from CRI.
type criStatsProvider struct {
	// cadvisor is used to get the node root filesystem's stats (such as the
	// capacity/available bytes/inodes) that will be populated in per container
	// filesystem stats.
	cadvisor cadvisor.Interface
	// resourceAnalyzer is used to get the volume stats of the pods.
	resourceAnalyzer stats.ResourceAnalyzer
	// runtimeService is used to get the status and stats of the pods and its
	// managed containers.
	runtimeService internalapi.RuntimeService
	// imageService is used to get the stats of the image filesystem.
	imageService internalapi.ImageManagerService
}

// newCRIStatsProvider returns a containerStatsProvider implementation that
// provides container stats using CRI.
func newCRIStatsProvider(
	cadvisor cadvisor.Interface,
	resourceAnalyzer stats.ResourceAnalyzer,
	runtimeService internalapi.RuntimeService,
	imageService internalapi.ImageManagerService,
) containerStatsProvider {
	return &criStatsProvider{
		cadvisor:         cadvisor,
		resourceAnalyzer: resourceAnalyzer,
		runtimeService:   runtimeService,
		imageService:     imageService,
	}
}

// ListPodStats returns the stats of all the pod-managed containers.
func (p *criStatsProvider) ListPodStats() ([]statsapi.PodStats, error) {
	// Gets node root filesystem information, which will be used to populate
	// the available and capacity bytes/inodes in container stats.
	rootFsInfo, err := p.cadvisor.RootFsInfo()
	if err != nil {
		return nil, fmt.Errorf("failed to get rootFs info: %v", err)
	}

	// Creates container map.
	containerMap := make(map[string]*runtimeapi.Container)
	containers, err := p.runtimeService.ListContainers(&runtimeapi.ContainerFilter{})
	if err != nil {
		return nil, fmt.Errorf("failed to list all containers: %v", err)
	}
	for _, c := range containers {
		containerMap[c.Id] = c
	}

	// Creates pod sandbox map.
	podSandboxMap := make(map[string]*runtimeapi.PodSandbox)
	podSandboxes, err := p.runtimeService.ListPodSandbox(&runtimeapi.PodSandboxFilter{})
	if err != nil {
		return nil, fmt.Errorf("failed to list all pod sandboxes: %v", err)
	}
	for _, s := range podSandboxes {
		podSandboxMap[s.Id] = s
	}

	// uuidToFsInfo is a map from filesystem UUID to its stats. This will be
	// used as a cache to avoid querying cAdvisor for the filesystem stats with
	// the same UUID many times.
	uuidToFsInfo := make(map[runtimeapi.StorageIdentifier]*cadvisorapiv2.FsInfo)

	// sandboxIDToPodStats is a temporary map from sandbox ID to its pod stats.
	sandboxIDToPodStats := make(map[string]*statsapi.PodStats)

	resp, err := p.runtimeService.ListContainerStats(&runtimeapi.ListContainerStatsRequest{})
	if err != nil {
		return nil, fmt.Errorf("failed to list all container stats: %v", err)
	}
	for _, stats := range resp.Stats {
		containerID := stats.Attributes.Id
		container, found := containerMap[containerID]
		if !found {
			glog.Errorf("Unknown id %q in container map.", containerID)
			continue
		}

		podSandboxID := container.PodSandboxId
		podSandbox, found := podSandboxMap[podSandboxID]
		if !found {
			glog.Errorf("Unknown id %q in pod sandbox map.", podSandboxID)
			continue
		}

		// Creates the stats of the pod (if not created yet) which the
		// container belongs to.
		ps, found := sandboxIDToPodStats[podSandboxID]
		if !found {
			ps = p.makePodStats(podSandbox)
			sandboxIDToPodStats[podSandboxID] = ps
		}
		ps.Containers = append(ps.Containers, *p.makeContainerStats(stats, container, &rootFsInfo, uuidToFsInfo))
	}

	result := make([]statsapi.PodStats, 0, len(sandboxIDToPodStats))
	for _, s := range sandboxIDToPodStats {
		result = append(result, *s)
	}
	return result, nil
}

// ImageFsStats returns the stats of the image filesystem.
func (p *criStatsProvider) ImageFsStats() (*statsapi.FsStats, error) {
	resp, err := p.imageService.ImageFsInfo(&runtimeapi.ImageFsInfoRequest{})
	if err != nil {
		return nil, err
	}

	// CRI may return the stats of multiple image filesystems but we only
	// return the first one.
	//
	// TODO(yguo0905): Support returning stats of multiple image filesystems.
	for _, fs := range resp.ImageFilesystems {
		s := &statsapi.FsStats{
			Time:       metav1.NewTime(time.Unix(0, fs.Timestamp)),
			UsedBytes:  &fs.UsedBytes.Value,
			InodesUsed: &fs.InodesUsed.Value,
		}
		imageFsInfo := p.getFsInfo(fs.StorageId)
		if imageFsInfo != nil {
			// The image filesystem UUID is unknown to the local node or
			// there's an error on retrieving the stats. In these cases, we
			// omit those stats and return the best-effort partial result. See
			// https://github.com/kubernetes/heapster/issues/1793.
			s.AvailableBytes = &imageFsInfo.Available
			s.CapacityBytes = &imageFsInfo.Capacity
			s.InodesFree = imageFsInfo.InodesFree
			s.Inodes = imageFsInfo.Inodes
		}
		return s, nil
	}

	return nil, fmt.Errorf("imageFs information is unavailable")
}

// getFsInfo returns the information of the filesystem with the specified
// storageID. If any error occurs, this function logs the error and returns
// nil.
func (p *criStatsProvider) getFsInfo(storageID *runtimeapi.StorageIdentifier) *cadvisorapiv2.FsInfo {
	if storageID == nil {
		glog.V(2).Infof("Failed to get filesystem info: storageID is nil.")
		return nil
	}
	fsInfo, err := p.cadvisor.GetFsInfoByFsUUID(storageID.Uuid)
	if err != nil {
		msg := fmt.Sprintf("Failed to get the info of the filesystem with id %q: %v.", storageID.Uuid, err)
		if err == cadvisorfs.ErrNoSuchDevice {
			glog.V(2).Info(msg)
		} else {
			glog.Error(msg)
		}
		return nil
	}
	return &fsInfo
}

func (p *criStatsProvider) makePodStats(podSandbox *runtimeapi.PodSandbox) *statsapi.PodStats {
	s := &statsapi.PodStats{
		PodRef: statsapi.PodReference{
			Name:      podSandbox.Metadata.Name,
			UID:       podSandbox.Metadata.Uid,
			Namespace: podSandbox.Metadata.Namespace,
		},
		// The StartTime in the summary API is the pod creation time.
		StartTime: metav1.NewTime(time.Unix(0, podSandbox.CreatedAt)),
		// Network stats are not supported by CRI.
	}
	podUID := types.UID(s.PodRef.UID)
	if vstats, found := p.resourceAnalyzer.GetPodVolumeStats(podUID); found {
		s.VolumeStats = vstats.Volumes
	}
	return s
}

func (p *criStatsProvider) makeContainerStats(
	stats *runtimeapi.ContainerStats,
	container *runtimeapi.Container,
	rootFsInfo *cadvisorapiv2.FsInfo,
	uuidToFsInfo map[runtimeapi.StorageIdentifier]*cadvisorapiv2.FsInfo,
) *statsapi.ContainerStats {
	result := &statsapi.ContainerStats{
		Name: stats.Attributes.Metadata.Name,
		// The StartTime in the summary API is the container creation time.
		StartTime: metav1.NewTime(time.Unix(0, container.CreatedAt)),
		CPU:       &statsapi.CPUStats{},
		Memory:    &statsapi.MemoryStats{},
		Rootfs:    &statsapi.FsStats{},
		Logs: &statsapi.FsStats{
			Time:           metav1.NewTime(rootFsInfo.Timestamp),
			AvailableBytes: &rootFsInfo.Available,
			CapacityBytes:  &rootFsInfo.Capacity,
			InodesFree:     rootFsInfo.InodesFree,
			Inodes:         rootFsInfo.Inodes,
			// UsedBytes and InodesUsed are unavailable from CRI stats.
			//
			// TODO(yguo0905): Get this information from kubelet and
			// populate the two fields here.
		},
		// UserDefinedMetrics is not supported by CRI.
	}
	if stats.Cpu != nil {
		result.CPU.Time = metav1.NewTime(time.Unix(0, stats.Cpu.Timestamp))
		if stats.Cpu.UsageCoreNanoSeconds != nil {
			result.CPU.UsageCoreNanoSeconds = &stats.Cpu.UsageCoreNanoSeconds.Value
		}
	}
	if stats.Memory != nil {
		result.Memory.Time = metav1.NewTime(time.Unix(0, stats.Memory.Timestamp))
		if stats.Memory.WorkingSetBytes != nil {
			result.Memory.WorkingSetBytes = &stats.Memory.WorkingSetBytes.Value
		}
	}
	if stats.WritableLayer != nil {
		result.Rootfs.Time = metav1.NewTime(time.Unix(0, stats.WritableLayer.Timestamp))
		if stats.WritableLayer.UsedBytes != nil {
			result.Rootfs.UsedBytes = &stats.WritableLayer.UsedBytes.Value
		}
		if stats.WritableLayer.InodesUsed != nil {
			result.Rootfs.InodesUsed = &stats.WritableLayer.InodesUsed.Value
		}
	}
	storageID := stats.GetWritableLayer().GetStorageId()
	if storageID != nil {
		imageFsInfo, found := uuidToFsInfo[*storageID]
		if !found {
			imageFsInfo = p.getFsInfo(storageID)
			uuidToFsInfo[*storageID] = imageFsInfo
		}
		if imageFsInfo != nil {
			// The image filesystem UUID is unknown to the local node or there's an
			// error on retrieving the stats. In these cases, we omit those stats
			// and return the best-effort partial result. See
			// https://github.com/kubernetes/heapster/issues/1793.
			result.Rootfs.AvailableBytes = &imageFsInfo.Available
			result.Rootfs.CapacityBytes = &imageFsInfo.Capacity
			result.Rootfs.InodesFree = imageFsInfo.InodesFree
			result.Rootfs.Inodes = imageFsInfo.Inodes
		}
	}

	return result
}
<|endoftext|>


<commit_before>package payment_method

import (
	"database/sql"
	"github.com/fritzpay/paymentd/pkg/paymentd/principal"
	"github.com/fritzpay/paymentd/pkg/paymentd/project"
	"github.com/fritzpay/paymentd/pkg/paymentd/provider"
	"github.com/fritzpay/paymentd/pkg/testutil"
	. "github.com/smartystreets/goconvey/convey"
	"testing"
)

func TestPaymentMethodSQL(t *testing.T) {
	Convey("Given a payment DB connection", t, testutil.WithPaymentDB(t, func(db *sql.DB) {
		Reset(func() {
			db.Close()
		})
		Convey("Given a principal DB connection", testutil.WithPrincipalDB(t, func(prDB *sql.DB) {
			Reset(func() {
				prDB.Close()
			})
			Convey("Given a test principal", func() {
				princ := principal.Principal{}
				princ.Name = "payment_method_testprincipal"
				princ.CreatedBy = "test"
				err := principal.InsertPrincipalDB(prDB, &princ)
				So(err, ShouldBeNil)
				So(princ.ID, ShouldNotEqual, 0)
				So(princ.Empty(), ShouldBeFalse)

				Reset(func() {
					_, err = prDB.Exec("delete from principal where name = 'payment_method_testprincipal'")
					So(err, ShouldBeNil)
				})

				Convey("Given a test project", func() {
					proj := project.Project{}
					proj.PrincipalID = princ.ID
					proj.Name = "payment_method_testproject"
					proj.CreatedBy = "test"
					err := project.InsertProjectDB(prDB, &proj)
					So(err, ShouldBeNil)

					Reset(func() {
						_, err = prDB.Exec("delete from project where name = 'payment_method_testproject'")
						So(err, ShouldBeNil)
					})

					Convey("Given a transaction", func() {
						tx, err := db.Begin()
						So(err, ShouldBeNil)

						Reset(func() {
							err = tx.Rollback()
							So(err, ShouldBeNil)
						})

						Convey("Given a test provider exists", func() {
							pr, err := provider.ProviderByIDTx(tx, 1)
							So(err, ShouldBeNil)
							So(pr.ID, ShouldEqual, 1)

							Convey("When inserting a new payment method", func() {
								pm := PaymentMethod{}
								pm.ProjectID = proj.ID
								pm.Provider.ID = pr.ID
								pm.MethodKey = "test"
								pm.CreatedBy = "test"

								Convey("When trying to get it before adding it should return not found", func() {
									_, err = PaymentMethodByProjectIDProviderIDMethodKey(db, pm.ProjectID, pm.Provider.ID, pm.MethodKey)
									So(err, ShouldEqual, ErrPaymentMethodNotFound)
								})

								pm.ID, err = InsertPaymentMethodTx(tx, pm)
								So(err, ShouldBeNil)
								So(pm.ID, ShouldNotEqual, 0)

								Convey("When setting the status to active", func() {
									pm.Status = PaymentMethodStatusActive
									pm.CreatedBy = "test"

									err = InsertPaymentMethodStatusTx(tx, pm)
									So(err, ShouldBeNil)

									Convey("When retrieving the payment method", func() {
										newPm, err := PaymentMethodByIDTx(tx, pm.ID)
										So(err, ShouldBeNil)

										Convey("The retrieved payment method should match", func() {
											So(newPm.Status, ShouldEqual, PaymentMethodStatusActive)
										})
									})
								})

								Convey("When setting metadata", func() {
									pm.Metadata = map[string]string{
										"name": "value",
										"test": "check",
									}
									err = InsertPaymentMethodMetadataTx(tx, pm, "metatest")
									So(err, ShouldBeNil)

									Convey("When selecting metadata", func() {
										metadata, err := PaymentMethodMetadataTx(tx, pm)
										So(err, ShouldBeNil)

										Convey("It should match", func() {
											So(metadata, ShouldNotBeNil)
											So(metadata["name"], ShouldEqual, "value")
											So(metadata["test"], ShouldEqual, "check")
										})
									})
								})
							})
						})
					})
				})
			})
		}))
	}))
}
<commit_msg>fix test implementation, would lead to deadlock<commit_after>package payment_method

import (
	"database/sql"
	"github.com/fritzpay/paymentd/pkg/paymentd/principal"
	"github.com/fritzpay/paymentd/pkg/paymentd/project"
	"github.com/fritzpay/paymentd/pkg/paymentd/provider"
	"github.com/fritzpay/paymentd/pkg/testutil"
	. "github.com/smartystreets/goconvey/convey"
	"testing"
)

func TestPaymentMethodSQL(t *testing.T) {
	Convey("Given a payment DB connection", t, testutil.WithPaymentDB(t, func(db *sql.DB) {
		Reset(func() {
			db.Close()
		})
		Convey("Given a principal DB connection", testutil.WithPrincipalDB(t, func(prDB *sql.DB) {
			Reset(func() {
				prDB.Close()
			})
			Convey("Given a test principal", func() {
				princ := principal.Principal{}
				princ.Name = "payment_method_testprincipal"
				princ.CreatedBy = "test"
				err := principal.InsertPrincipalDB(prDB, &princ)
				So(err, ShouldBeNil)
				So(princ.ID, ShouldNotEqual, 0)
				So(princ.Empty(), ShouldBeFalse)

				Reset(func() {
					_, err = prDB.Exec("delete from principal where name = 'payment_method_testprincipal'")
					So(err, ShouldBeNil)
				})

				Convey("Given a test project", func() {
					proj := project.Project{}
					proj.PrincipalID = princ.ID
					proj.Name = "payment_method_testproject"
					proj.CreatedBy = "test"
					err := project.InsertProjectDB(prDB, &proj)
					So(err, ShouldBeNil)

					Reset(func() {
						_, err = prDB.Exec("delete from project where name = 'payment_method_testproject'")
						So(err, ShouldBeNil)
					})

					Convey("Given a transaction", func() {
						tx, err := db.Begin()
						So(err, ShouldBeNil)

						Reset(func() {
							err = tx.Rollback()
							So(err, ShouldBeNil)
						})

						Convey("Given a test provider exists", func() {
							pr, err := provider.ProviderByIDTx(tx, 1)
							So(err, ShouldBeNil)
							So(pr.ID, ShouldEqual, 1)

							Convey("When retrieving a nonexistent payment method", func() {
								_, err = PaymentMethodByProjectIDProviderIDMethodKey(db, proj.ID, pr.ID, "test")
								Convey("It should return a not found error", func() {
									So(err, ShouldEqual, ErrPaymentMethodNotFound)
								})
							})

							Convey("When inserting a new payment method", func() {
								pm := PaymentMethod{}
								pm.ProjectID = proj.ID
								pm.Provider.ID = pr.ID
								pm.MethodKey = "test"
								pm.CreatedBy = "test"

								pm.ID, err = InsertPaymentMethodTx(tx, pm)
								So(err, ShouldBeNil)
								So(pm.ID, ShouldNotEqual, 0)

								Convey("When setting the status to active", func() {
									pm.Status = PaymentMethodStatusActive
									pm.CreatedBy = "test"

									err = InsertPaymentMethodStatusTx(tx, pm)
									So(err, ShouldBeNil)

									Convey("When retrieving the payment method", func() {
										newPm, err := PaymentMethodByIDTx(tx, pm.ID)
										So(err, ShouldBeNil)

										Convey("The retrieved payment method should match", func() {
											So(newPm.Status, ShouldEqual, PaymentMethodStatusActive)
										})
									})
								})

								Convey("When setting metadata", func() {
									pm.Metadata = map[string]string{
										"name": "value",
										"test": "check",
									}
									err = InsertPaymentMethodMetadataTx(tx, pm, "metatest")
									So(err, ShouldBeNil)

									Convey("When selecting metadata", func() {
										metadata, err := PaymentMethodMetadataTx(tx, pm)
										So(err, ShouldBeNil)

										Convey("It should match", func() {
											So(metadata, ShouldNotBeNil)
											So(metadata["name"], ShouldEqual, "value")
											So(metadata["test"], ShouldEqual, "check")
										})
									})
								})
							})
						})
					})
				})
			})
		}))
	}))
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Skaffold 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 acr

import (
	"bytes"
	"fmt"
	"net/http"
	"time"

	"github.com/pkg/errors"
)

const VERSION = "2018-03-28"

type AzureBlobStorage struct {
	UploadURL string
	Buffer    *bytes.Buffer
}

func NewBlobStorage(url string) AzureBlobStorage {
	return AzureBlobStorage{
		UploadURL: url,
		Buffer:    new(bytes.Buffer),
	}
}

//Maximum supported file size is currently 256Mb
//as stated here https://docs.microsoft.com/en-us/rest/api/storageservices/put-blob#remarks
func (s AzureBlobStorage) UploadFileToBlob() error {
	req, err := http.NewRequest("PUT", s.UploadURL, s.Buffer)
	if err != nil {
		return err
	}
	req.Header.Add("x-ms-blob-type", "BlockBlob")
	req.Header.Add("x-ms-version", VERSION)
	req.Header.Add("x-ms-date", time.Now().String())
	req.Header.Add("Content-Length", fmt.Sprint(s.Buffer.Len()))

	client := http.Client{}
	response, err := client.Do(req)
	defer response.Body.Close()
	if err != nil {
		return err
	}

	if response.StatusCode != http.StatusCreated {
		return errors.New("couldn't push tar to blob")
	}
	return nil
}
<commit_msg>Closing blob upload response after checking if an error has occurred<commit_after>/*
Copyright 2018 The Skaffold 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 acr

import (
	"bytes"
	"fmt"
	"net/http"
	"time"

	"github.com/pkg/errors"
)

const VERSION = "2018-03-28"

type AzureBlobStorage struct {
	UploadURL string
	Buffer    *bytes.Buffer
}

func NewBlobStorage(url string) AzureBlobStorage {
	return AzureBlobStorage{
		UploadURL: url,
		Buffer:    new(bytes.Buffer),
	}
}

//Maximum supported file size is currently 256Mb
//as stated here https://docs.microsoft.com/en-us/rest/api/storageservices/put-blob#remarks
func (s AzureBlobStorage) UploadFileToBlob() error {
	req, err := http.NewRequest("PUT", s.UploadURL, s.Buffer)
	if err != nil {
		return err
	}
	req.Header.Add("x-ms-blob-type", "BlockBlob")
	req.Header.Add("x-ms-version", VERSION)
	req.Header.Add("x-ms-date", time.Now().String())
	req.Header.Add("Content-Length", fmt.Sprint(s.Buffer.Len()))

	client := http.Client{}
	response, err := client.Do(req)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusCreated {
		return errors.New("couldn't push tar to blob")
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2021 The Skaffold 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 inspect

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"testing"

	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/config"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/inspect"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/parser"
	sErrors "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/errors"
	v1 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest/v1"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
	"github.com/GoogleContainerTools/skaffold/testutil"
)

func TestPrintTestsList(t *testing.T) {
	tests := []struct {
		description string
		profiles    []string
		module      []string
		err         error
		expected    string
	}{
		{
			description: "print all tests",
			expected:    `{"tests":[{"testType":"structure-test","structureTest":"structure-test-i0","structureTestArgs":null},{"testType":"custom-test","Command":"custom-test-i0","TimeoutSeconds":0,"Dependencies":null}]}` + "\n",
		},
		{
			description: "print all tests for one module",
			expected:    `{"tests":[{"testType":"structure-test","structureTest":"structure-test-i0","structureTestArgs":null}]}` + "\n",
			module:      []string{"cfg1"},
		},
		{
			description: "print all tests for two activated profiles",

			expected: `{"tests":[{"testType":"structure-test","structureTest":"structure-test-i0","structureTestArgs":null},{"testType":"custom-test","Command":"custom-test-i0","TimeoutSeconds":0,"Dependencies":null}]}` + "\n",
			profiles: []string{"custom-test", "structure-test"},
		},
		{
			description: "print all tests for one module and an activated profile",

			expected: `{"tests":[{"testType":"structure-test","structureTest":"structure-test-i0","structureTestArgs":null}]}` + "\n",
			module:   []string{"cfg1"},
			profiles: []string{"custom-test"},
		},
		{
			description: "actionable error",
			err:         sErrors.MainConfigFileNotFoundErr("path/to/skaffold.yaml", fmt.Errorf("failed to read file : %q", "skaffold.yaml")),
			expected:    `{"errorCode":"CONFIG_FILE_NOT_FOUND_ERR","errorMessage":"unable to find configuration file \"path/to/skaffold.yaml\": failed to read file : \"skaffold.yaml\". Check that the specified configuration file exists at \"path/to/skaffold.yaml\"."}` + "\n",
		},
		{
			description: "generic error",
			err:         errors.New("some error occurred"),
			expected:    `{"errorCode":"INSPECT_UNKNOWN_ERR","errorMessage":"some error occurred"}` + "\n",
		},
	}

	for _, test := range tests {
		testutil.Run(t, test.description, func(t *testutil.T) {
			configSet := parser.SkaffoldConfigSet{
				&parser.SkaffoldConfigEntry{SkaffoldConfig: &v1.SkaffoldConfig{
					Metadata: v1.Metadata{Name: "cfg1"},
					Pipeline: v1.Pipeline{Test: []*v1.TestCase{{StructureTests: []string{"structure-test-i0"}}}},
					Profiles: []v1.Profile{
						{Name: "custom-test", Pipeline: v1.Pipeline{Test: []*v1.TestCase{{CustomTests: []v1.CustomTest{{Command: "custom-test-i0"}}}}}}},
				}, SourceFile: "path/to/cfg1"},
				&parser.SkaffoldConfigEntry{SkaffoldConfig: &v1.SkaffoldConfig{
					Metadata: v1.Metadata{Name: "cfg2"},
					Pipeline: v1.Pipeline{Test: []*v1.TestCase{{CustomTests: []v1.CustomTest{{Command: "custom-test-i0"}}}}},
					Profiles: []v1.Profile{
						{Name: "structure-test", Pipeline: v1.Pipeline{Test: []*v1.TestCase{{StructureTests: []string{"structure-test-i0"}}}}}},
				}, SourceFile: "path/to/cfg1"},
			}
			t.Override(&inspect.GetConfigSet, func(_ context.Context, opts config.SkaffoldOptions) (parser.SkaffoldConfigSet, error) {
				// mock profile activation
				var set parser.SkaffoldConfigSet
				for _, c := range configSet {
					if len(opts.ConfigurationFilter) > 0 && !util.StrSliceContains(opts.ConfigurationFilter, c.Metadata.Name) {
						continue
					}
					for _, pName := range opts.Profiles {
						for _, profile := range c.Profiles {
							if profile.Name != pName {
								continue
							}
							c.Test = profile.Test
						}
					}
					set = append(set, c)
				}
				return set, test.err
			})
			var buf bytes.Buffer
			err := PrintTestsList(context.Background(), &buf, inspect.Options{OutFormat: "json", Modules: test.module})
			t.CheckNoError(err)
			t.CheckDeepEqual(test.expected, buf.String())
		})
	}
}
<commit_msg>fix: fix unit test for skaffold inspect tests list (#6656)<commit_after>/*
Copyright 2021 The Skaffold 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 inspect

import (
	"bytes"
	"context"
	"errors"
	"fmt"
	"testing"

	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/config"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/inspect"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/parser"
	sErrors "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/errors"
	v1 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest/v1"
	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
	"github.com/GoogleContainerTools/skaffold/testutil"
)

func TestPrintTestsList(t *testing.T) {
	tests := []struct {
		description string
		profiles    []string
		module      []string
		err         error
		expected    string
	}{
		{
			description: "print all tests",
			expected:    `{"tests":[{"testType":"structure-test","structureTest":"structure-test-default","structureTestArgs":null},{"testType":"custom-test","Command":"custom-test-default","TimeoutSeconds":0,"Dependencies":null}]}` + "\n",
		},
		{
			description: "print all tests for one module",
			expected:    `{"tests":[{"testType":"structure-test","structureTest":"structure-test-default","structureTestArgs":null}]}` + "\n",
			module:      []string{"cfg1"},
		},
		{
			description: "print all tests for two activated profiles",
			expected:    `{"tests":[{"testType":"custom-test","Command":"custom-test-profile","TimeoutSeconds":0,"Dependencies":null},{"testType":"structure-test","structureTest":"structure-test-profile","structureTestArgs":null}]}` + "\n",
			profiles:    []string{"custom-test", "structure-test"},
		},
		{
			description: "print all tests for one module and an activated profile",
			expected:    `{"tests":[{"testType":"custom-test","Command":"custom-test-profile","TimeoutSeconds":0,"Dependencies":null}]}` + "\n",
			module:      []string{"cfg1"},
			profiles:    []string{"custom-test"},
		},
		{
			description: "actionable error",
			err:         sErrors.MainConfigFileNotFoundErr("path/to/skaffold.yaml", fmt.Errorf("failed to read file : %q", "skaffold.yaml")),
			expected:    `{"errorCode":"CONFIG_FILE_NOT_FOUND_ERR","errorMessage":"unable to find configuration file \"path/to/skaffold.yaml\": failed to read file : \"skaffold.yaml\". Check that the specified configuration file exists at \"path/to/skaffold.yaml\"."}` + "\n",
		},
		{
			description: "generic error",
			err:         errors.New("some error occurred"),
			expected:    `{"errorCode":"INSPECT_UNKNOWN_ERR","errorMessage":"some error occurred"}` + "\n",
		},
	}

	for _, test := range tests {
		testutil.Run(t, test.description, func(t *testutil.T) {
			configSet := parser.SkaffoldConfigSet{
				&parser.SkaffoldConfigEntry{SkaffoldConfig: &v1.SkaffoldConfig{
					Metadata: v1.Metadata{Name: "cfg1"},
					Pipeline: v1.Pipeline{Test: []*v1.TestCase{{StructureTests: []string{"structure-test-default"}}}},
					Profiles: []v1.Profile{
						{Name: "custom-test", Pipeline: v1.Pipeline{Test: []*v1.TestCase{{CustomTests: []v1.CustomTest{{Command: "custom-test-profile"}}}}}}},
				}, SourceFile: "path/to/cfg1"},
				&parser.SkaffoldConfigEntry{SkaffoldConfig: &v1.SkaffoldConfig{
					Metadata: v1.Metadata{Name: "cfg2"},
					Pipeline: v1.Pipeline{Test: []*v1.TestCase{{CustomTests: []v1.CustomTest{{Command: "custom-test-default"}}}}},
					Profiles: []v1.Profile{
						{Name: "structure-test", Pipeline: v1.Pipeline{Test: []*v1.TestCase{{StructureTests: []string{"structure-test-profile"}}}}}},
				}, SourceFile: "path/to/cfg2"},
			}
			t.Override(&inspect.GetConfigSet, func(_ context.Context, opts config.SkaffoldOptions) (parser.SkaffoldConfigSet, error) {
				// mock profile activation
				var set parser.SkaffoldConfigSet
				for _, c := range configSet {
					if len(opts.ConfigurationFilter) > 0 && !util.StrSliceContains(opts.ConfigurationFilter, c.Metadata.Name) {
						continue
					}
					for _, pName := range opts.Profiles {
						for _, profile := range c.Profiles {
							if profile.Name != pName {
								continue
							}
							c.Test = profile.Test
						}
					}
					set = append(set, c)
				}
				return set, test.err
			})
			var buf bytes.Buffer
			err := PrintTestsList(context.Background(), &buf, inspect.Options{
				OutFormat: "json", Modules: test.module, TestsOptions: inspect.TestsOptions{TestsProfiles: test.profiles}})
			t.CheckNoError(err)
			t.CheckDeepEqual(test.expected, buf.String())
		})
	}
}
<|endoftext|>


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

// Parse input AST and prepare Prog structure.

package main

import (
	"fmt"
	"go/ast"
	"go/doc"
	"go/parser"
	"go/scanner"
	"go/token"
	"os"
	"strings"
)

func parse(name string, flags uint) *ast.File {
	ast1, err := parser.ParseFile(fset, name, nil, flags)
	if err != nil {
		if list, ok := err.(scanner.ErrorList); ok {
			// If err is a scanner.ErrorList, its String will print just
			// the first error and then (+n more errors).
			// Instead, turn it into a new Error that will return
			// details for all the errors.
			for _, e := range list {
				fmt.Fprintln(os.Stderr, e)
			}
			os.Exit(2)
		}
		fatal("parsing %s: %s", name, err)
	}
	return ast1
}

func sourceLine(n ast.Node) int {
	return fset.Position(n.Pos()).Line
}

// ReadGo populates f with information learned from reading the
// Go source file with the given file name.  It gathers the C preamble
// attached to the import "C" comment, a list of references to C.xxx,
// a list of exported functions, and the actual AST, to be rewritten and
// printed.
func (f *File) ReadGo(name string) {
	// Two different parses: once with comments, once without.
	// The printer is not good enough at printing comments in the
	// right place when we start editing the AST behind its back,
	// so we use ast1 to look for the doc comments on import "C"
	// and on exported functions, and we use ast2 for translating
	// and reprinting.
	ast1 := parse(name, parser.ParseComments)
	ast2 := parse(name, 0)

	f.Package = ast1.Name.Name
	f.Name = make(map[string]*Name)

	// In ast1, find the import "C" line and get any extra C preamble.
	sawC := false
	for _, decl := range ast1.Decls {
		d, ok := decl.(*ast.GenDecl)
		if !ok {
			continue
		}
		for _, spec := range d.Specs {
			s, ok := spec.(*ast.ImportSpec)
			if !ok || string(s.Path.Value) != `"C"` {
				continue
			}
			sawC = true
			if s.Name != nil {
				error(s.Path.Pos(), `cannot rename import "C"`)
			}
			cg := s.Doc
			if cg == nil && len(d.Specs) == 1 {
				cg = d.Doc
			}
			if cg != nil {
				f.Preamble += fmt.Sprintf("#line %d %q\n", sourceLine(cg), name)
				f.Preamble += doc.CommentText(cg) + "\n"
			}
		}
	}
	if !sawC {
		error(token.NoPos, `cannot find import "C"`)
	}

	// In ast2, strip the import "C" line.
	w := 0
	for _, decl := range ast2.Decls {
		d, ok := decl.(*ast.GenDecl)
		if !ok {
			ast2.Decls[w] = decl
			w++
			continue
		}
		ws := 0
		for _, spec := range d.Specs {
			s, ok := spec.(*ast.ImportSpec)
			if !ok || string(s.Path.Value) != `"C"` {
				d.Specs[ws] = spec
				ws++
			}
		}
		if ws == 0 {
			continue
		}
		d.Specs = d.Specs[0:ws]
		ast2.Decls[w] = d
		w++
	}
	ast2.Decls = ast2.Decls[0:w]

	// Accumulate pointers to uses of C.x.
	if f.Ref == nil {
		f.Ref = make([]*Ref, 0, 8)
	}
	f.walk(ast2, "prog", (*File).saveRef)

	// Accumulate exported functions.
	// The comments are only on ast1 but we need to
	// save the function bodies from ast2.
	// The first walk fills in ExpFunc, and the
	// second walk changes the entries to
	// refer to ast2 instead.
	f.walk(ast1, "prog", (*File).saveExport)
	f.walk(ast2, "prog", (*File).saveExport2)

	f.AST = ast2
}

// Save references to C.xxx for later processing.
func (f *File) saveRef(x interface{}, context string) {
	n, ok := x.(*ast.Expr)
	if !ok {
		return
	}
	if sel, ok := (*n).(*ast.SelectorExpr); ok {
		// For now, assume that the only instance of capital C is
		// when used as the imported package identifier.
		// The parser should take care of scoping in the future,
		// so that we will be able to distinguish a "top-level C"
		// from a local C.
		if l, ok := sel.X.(*ast.Ident); ok && l.Name == "C" {
			if context == "as2" {
				context = "expr"
			}
			goname := sel.Sel.Name
			if goname == "errno" {
				error(sel.Pos(), "cannot refer to errno directly; see documentation")
				return
			}
			name := f.Name[goname]
			if name == nil {
				name = &Name{
					Go: goname,
				}
				f.Name[goname] = name
			}
			f.Ref = append(f.Ref, &Ref{
				Name:    name,
				Expr:    n,
				Context: context,
			})
			return
		}
	}
}

// If a function should be exported add it to ExpFunc.
func (f *File) saveExport(x interface{}, context string) {
	n, ok := x.(*ast.FuncDecl)
	if !ok {
		return
	}

	if n.Doc == nil {
		return
	}
	for _, c := range n.Doc.List {
		if string(c.Text[0:9]) != "//export " {
			continue
		}

		name := strings.TrimSpace(string(c.Text[9:]))
		if name == "" {
			error(c.Pos(), "export missing name")
		}

		f.ExpFunc = append(f.ExpFunc, &ExpFunc{
			Func:    n,
			ExpName: name,
		})
		break
	}
}

// Make f.ExpFunc[i] point at the Func from this AST instead of the other one.
func (f *File) saveExport2(x interface{}, context string) {
	n, ok := x.(*ast.FuncDecl)
	if !ok {
		return
	}

	for _, exp := range f.ExpFunc {
		if exp.Func.Name.Name == n.Name.Name {
			exp.Func = n
			break
		}
	}
}

// walk walks the AST x, calling visit(f, x, context) for each node.
func (f *File) walk(x interface{}, context string, visit func(*File, interface{}, string)) {
	visit(f, x, context)
	switch n := x.(type) {
	case *ast.Expr:
		f.walk(*n, context, visit)

	// everything else just recurs
	default:
		error(token.NoPos, "unexpected type %T in walk", x, visit)
		panic("unexpected type")

	case nil:

	// These are ordered and grouped to match ../../pkg/go/ast/ast.go
	case *ast.Field:
		f.walk(&n.Type, "type", visit)
	case *ast.FieldList:
		for _, field := range n.List {
			f.walk(field, context, visit)
		}
	case *ast.BadExpr:
	case *ast.Ident:
	case *ast.Ellipsis:
	case *ast.BasicLit:
	case *ast.FuncLit:
		f.walk(n.Type, "type", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.CompositeLit:
		f.walk(&n.Type, "type", visit)
		f.walk(n.Elts, "expr", visit)
	case *ast.ParenExpr:
		f.walk(&n.X, context, visit)
	case *ast.SelectorExpr:
		f.walk(&n.X, "selector", visit)
	case *ast.IndexExpr:
		f.walk(&n.X, "expr", visit)
		f.walk(&n.Index, "expr", visit)
	case *ast.SliceExpr:
		f.walk(&n.X, "expr", visit)
		if n.Low != nil {
			f.walk(&n.Low, "expr", visit)
		}
		if n.High != nil {
			f.walk(&n.High, "expr", visit)
		}
	case *ast.TypeAssertExpr:
		f.walk(&n.X, "expr", visit)
		f.walk(&n.Type, "type", visit)
	case *ast.CallExpr:
		if context == "as2" {
			f.walk(&n.Fun, "call2", visit)
		} else {
			f.walk(&n.Fun, "call", visit)
		}
		f.walk(n.Args, "expr", visit)
	case *ast.StarExpr:
		f.walk(&n.X, context, visit)
	case *ast.UnaryExpr:
		f.walk(&n.X, "expr", visit)
	case *ast.BinaryExpr:
		f.walk(&n.X, "expr", visit)
		f.walk(&n.Y, "expr", visit)
	case *ast.KeyValueExpr:
		f.walk(&n.Key, "expr", visit)
		f.walk(&n.Value, "expr", visit)

	case *ast.ArrayType:
		f.walk(&n.Len, "expr", visit)
		f.walk(&n.Elt, "type", visit)
	case *ast.StructType:
		f.walk(n.Fields, "field", visit)
	case *ast.FuncType:
		f.walk(n.Params, "field", visit)
		if n.Results != nil {
			f.walk(n.Results, "field", visit)
		}
	case *ast.InterfaceType:
		f.walk(n.Methods, "field", visit)
	case *ast.MapType:
		f.walk(&n.Key, "type", visit)
		f.walk(&n.Value, "type", visit)
	case *ast.ChanType:
		f.walk(&n.Value, "type", visit)

	case *ast.BadStmt:
	case *ast.DeclStmt:
		f.walk(n.Decl, "decl", visit)
	case *ast.EmptyStmt:
	case *ast.LabeledStmt:
		f.walk(n.Stmt, "stmt", visit)
	case *ast.ExprStmt:
		f.walk(&n.X, "expr", visit)
	case *ast.SendStmt:
		f.walk(&n.Chan, "expr", visit)
		f.walk(&n.Value, "expr", visit)
	case *ast.IncDecStmt:
		f.walk(&n.X, "expr", visit)
	case *ast.AssignStmt:
		f.walk(n.Lhs, "expr", visit)
		if len(n.Lhs) == 2 && len(n.Rhs) == 1 {
			f.walk(n.Rhs, "as2", visit)
		} else {
			f.walk(n.Rhs, "expr", visit)
		}
	case *ast.GoStmt:
		f.walk(n.Call, "expr", visit)
	case *ast.DeferStmt:
		f.walk(n.Call, "expr", visit)
	case *ast.ReturnStmt:
		f.walk(n.Results, "expr", visit)
	case *ast.BranchStmt:
	case *ast.BlockStmt:
		f.walk(n.List, context, visit)
	case *ast.IfStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(&n.Cond, "expr", visit)
		f.walk(n.Body, "stmt", visit)
		f.walk(n.Else, "stmt", visit)
	case *ast.CaseClause:
		if context == "typeswitch" {
			context = "type"
		} else {
			context = "expr"
		}
		f.walk(n.List, context, visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.SwitchStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(&n.Tag, "expr", visit)
		f.walk(n.Body, "switch", visit)
	case *ast.TypeSwitchStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(n.Assign, "stmt", visit)
		f.walk(n.Body, "typeswitch", visit)
	case *ast.CommClause:
		f.walk(n.Comm, "stmt", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.SelectStmt:
		f.walk(n.Body, "stmt", visit)
	case *ast.ForStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(&n.Cond, "expr", visit)
		f.walk(n.Post, "stmt", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.RangeStmt:
		f.walk(&n.Key, "expr", visit)
		f.walk(&n.Value, "expr", visit)
		f.walk(&n.X, "expr", visit)
		f.walk(n.Body, "stmt", visit)

	case *ast.ImportSpec:
	case *ast.ValueSpec:
		f.walk(&n.Type, "type", visit)
		f.walk(n.Values, "expr", visit)
	case *ast.TypeSpec:
		f.walk(&n.Type, "type", visit)

	case *ast.BadDecl:
	case *ast.GenDecl:
		f.walk(n.Specs, "spec", visit)
	case *ast.FuncDecl:
		if n.Recv != nil {
			f.walk(n.Recv, "field", visit)
		}
		f.walk(n.Type, "type", visit)
		if n.Body != nil {
			f.walk(n.Body, "stmt", visit)
		}

	case *ast.File:
		f.walk(n.Decls, "decl", visit)

	case *ast.Package:
		for _, file := range n.Files {
			f.walk(file, "file", visit)
		}

	case []ast.Decl:
		for _, d := range n {
			f.walk(d, context, visit)
		}
	case []ast.Expr:
		for i := range n {
			f.walk(&n[i], context, visit)
		}
	case []ast.Stmt:
		for _, s := range n {
			f.walk(s, context, visit)
		}
	case []ast.Spec:
		for _, s := range n {
			f.walk(s, context, visit)
		}
	}
}
<commit_msg>cgo: fix index-out-of-bounds bug<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Parse input AST and prepare Prog structure.

package main

import (
	"fmt"
	"go/ast"
	"go/doc"
	"go/parser"
	"go/scanner"
	"go/token"
	"os"
	"strings"
)

func parse(name string, flags uint) *ast.File {
	ast1, err := parser.ParseFile(fset, name, nil, flags)
	if err != nil {
		if list, ok := err.(scanner.ErrorList); ok {
			// If err is a scanner.ErrorList, its String will print just
			// the first error and then (+n more errors).
			// Instead, turn it into a new Error that will return
			// details for all the errors.
			for _, e := range list {
				fmt.Fprintln(os.Stderr, e)
			}
			os.Exit(2)
		}
		fatal("parsing %s: %s", name, err)
	}
	return ast1
}

func sourceLine(n ast.Node) int {
	return fset.Position(n.Pos()).Line
}

// ReadGo populates f with information learned from reading the
// Go source file with the given file name.  It gathers the C preamble
// attached to the import "C" comment, a list of references to C.xxx,
// a list of exported functions, and the actual AST, to be rewritten and
// printed.
func (f *File) ReadGo(name string) {
	// Two different parses: once with comments, once without.
	// The printer is not good enough at printing comments in the
	// right place when we start editing the AST behind its back,
	// so we use ast1 to look for the doc comments on import "C"
	// and on exported functions, and we use ast2 for translating
	// and reprinting.
	ast1 := parse(name, parser.ParseComments)
	ast2 := parse(name, 0)

	f.Package = ast1.Name.Name
	f.Name = make(map[string]*Name)

	// In ast1, find the import "C" line and get any extra C preamble.
	sawC := false
	for _, decl := range ast1.Decls {
		d, ok := decl.(*ast.GenDecl)
		if !ok {
			continue
		}
		for _, spec := range d.Specs {
			s, ok := spec.(*ast.ImportSpec)
			if !ok || string(s.Path.Value) != `"C"` {
				continue
			}
			sawC = true
			if s.Name != nil {
				error(s.Path.Pos(), `cannot rename import "C"`)
			}
			cg := s.Doc
			if cg == nil && len(d.Specs) == 1 {
				cg = d.Doc
			}
			if cg != nil {
				f.Preamble += fmt.Sprintf("#line %d %q\n", sourceLine(cg), name)
				f.Preamble += doc.CommentText(cg) + "\n"
			}
		}
	}
	if !sawC {
		error(token.NoPos, `cannot find import "C"`)
	}

	// In ast2, strip the import "C" line.
	w := 0
	for _, decl := range ast2.Decls {
		d, ok := decl.(*ast.GenDecl)
		if !ok {
			ast2.Decls[w] = decl
			w++
			continue
		}
		ws := 0
		for _, spec := range d.Specs {
			s, ok := spec.(*ast.ImportSpec)
			if !ok || string(s.Path.Value) != `"C"` {
				d.Specs[ws] = spec
				ws++
			}
		}
		if ws == 0 {
			continue
		}
		d.Specs = d.Specs[0:ws]
		ast2.Decls[w] = d
		w++
	}
	ast2.Decls = ast2.Decls[0:w]

	// Accumulate pointers to uses of C.x.
	if f.Ref == nil {
		f.Ref = make([]*Ref, 0, 8)
	}
	f.walk(ast2, "prog", (*File).saveRef)

	// Accumulate exported functions.
	// The comments are only on ast1 but we need to
	// save the function bodies from ast2.
	// The first walk fills in ExpFunc, and the
	// second walk changes the entries to
	// refer to ast2 instead.
	f.walk(ast1, "prog", (*File).saveExport)
	f.walk(ast2, "prog", (*File).saveExport2)

	f.AST = ast2
}

// Save references to C.xxx for later processing.
func (f *File) saveRef(x interface{}, context string) {
	n, ok := x.(*ast.Expr)
	if !ok {
		return
	}
	if sel, ok := (*n).(*ast.SelectorExpr); ok {
		// For now, assume that the only instance of capital C is
		// when used as the imported package identifier.
		// The parser should take care of scoping in the future,
		// so that we will be able to distinguish a "top-level C"
		// from a local C.
		if l, ok := sel.X.(*ast.Ident); ok && l.Name == "C" {
			if context == "as2" {
				context = "expr"
			}
			goname := sel.Sel.Name
			if goname == "errno" {
				error(sel.Pos(), "cannot refer to errno directly; see documentation")
				return
			}
			name := f.Name[goname]
			if name == nil {
				name = &Name{
					Go: goname,
				}
				f.Name[goname] = name
			}
			f.Ref = append(f.Ref, &Ref{
				Name:    name,
				Expr:    n,
				Context: context,
			})
			return
		}
	}
}

// If a function should be exported add it to ExpFunc.
func (f *File) saveExport(x interface{}, context string) {
	n, ok := x.(*ast.FuncDecl)
	if !ok {
		return
	}

	if n.Doc == nil {
		return
	}
	for _, c := range n.Doc.List {
		if !strings.HasPrefix(string(c.Text), "//export ") {
			continue
		}

		name := strings.TrimSpace(string(c.Text[9:]))
		if name == "" {
			error(c.Pos(), "export missing name")
		}

		f.ExpFunc = append(f.ExpFunc, &ExpFunc{
			Func:    n,
			ExpName: name,
		})
		break
	}
}

// Make f.ExpFunc[i] point at the Func from this AST instead of the other one.
func (f *File) saveExport2(x interface{}, context string) {
	n, ok := x.(*ast.FuncDecl)
	if !ok {
		return
	}

	for _, exp := range f.ExpFunc {
		if exp.Func.Name.Name == n.Name.Name {
			exp.Func = n
			break
		}
	}
}

// walk walks the AST x, calling visit(f, x, context) for each node.
func (f *File) walk(x interface{}, context string, visit func(*File, interface{}, string)) {
	visit(f, x, context)
	switch n := x.(type) {
	case *ast.Expr:
		f.walk(*n, context, visit)

	// everything else just recurs
	default:
		error(token.NoPos, "unexpected type %T in walk", x, visit)
		panic("unexpected type")

	case nil:

	// These are ordered and grouped to match ../../pkg/go/ast/ast.go
	case *ast.Field:
		f.walk(&n.Type, "type", visit)
	case *ast.FieldList:
		for _, field := range n.List {
			f.walk(field, context, visit)
		}
	case *ast.BadExpr:
	case *ast.Ident:
	case *ast.Ellipsis:
	case *ast.BasicLit:
	case *ast.FuncLit:
		f.walk(n.Type, "type", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.CompositeLit:
		f.walk(&n.Type, "type", visit)
		f.walk(n.Elts, "expr", visit)
	case *ast.ParenExpr:
		f.walk(&n.X, context, visit)
	case *ast.SelectorExpr:
		f.walk(&n.X, "selector", visit)
	case *ast.IndexExpr:
		f.walk(&n.X, "expr", visit)
		f.walk(&n.Index, "expr", visit)
	case *ast.SliceExpr:
		f.walk(&n.X, "expr", visit)
		if n.Low != nil {
			f.walk(&n.Low, "expr", visit)
		}
		if n.High != nil {
			f.walk(&n.High, "expr", visit)
		}
	case *ast.TypeAssertExpr:
		f.walk(&n.X, "expr", visit)
		f.walk(&n.Type, "type", visit)
	case *ast.CallExpr:
		if context == "as2" {
			f.walk(&n.Fun, "call2", visit)
		} else {
			f.walk(&n.Fun, "call", visit)
		}
		f.walk(n.Args, "expr", visit)
	case *ast.StarExpr:
		f.walk(&n.X, context, visit)
	case *ast.UnaryExpr:
		f.walk(&n.X, "expr", visit)
	case *ast.BinaryExpr:
		f.walk(&n.X, "expr", visit)
		f.walk(&n.Y, "expr", visit)
	case *ast.KeyValueExpr:
		f.walk(&n.Key, "expr", visit)
		f.walk(&n.Value, "expr", visit)

	case *ast.ArrayType:
		f.walk(&n.Len, "expr", visit)
		f.walk(&n.Elt, "type", visit)
	case *ast.StructType:
		f.walk(n.Fields, "field", visit)
	case *ast.FuncType:
		f.walk(n.Params, "field", visit)
		if n.Results != nil {
			f.walk(n.Results, "field", visit)
		}
	case *ast.InterfaceType:
		f.walk(n.Methods, "field", visit)
	case *ast.MapType:
		f.walk(&n.Key, "type", visit)
		f.walk(&n.Value, "type", visit)
	case *ast.ChanType:
		f.walk(&n.Value, "type", visit)

	case *ast.BadStmt:
	case *ast.DeclStmt:
		f.walk(n.Decl, "decl", visit)
	case *ast.EmptyStmt:
	case *ast.LabeledStmt:
		f.walk(n.Stmt, "stmt", visit)
	case *ast.ExprStmt:
		f.walk(&n.X, "expr", visit)
	case *ast.SendStmt:
		f.walk(&n.Chan, "expr", visit)
		f.walk(&n.Value, "expr", visit)
	case *ast.IncDecStmt:
		f.walk(&n.X, "expr", visit)
	case *ast.AssignStmt:
		f.walk(n.Lhs, "expr", visit)
		if len(n.Lhs) == 2 && len(n.Rhs) == 1 {
			f.walk(n.Rhs, "as2", visit)
		} else {
			f.walk(n.Rhs, "expr", visit)
		}
	case *ast.GoStmt:
		f.walk(n.Call, "expr", visit)
	case *ast.DeferStmt:
		f.walk(n.Call, "expr", visit)
	case *ast.ReturnStmt:
		f.walk(n.Results, "expr", visit)
	case *ast.BranchStmt:
	case *ast.BlockStmt:
		f.walk(n.List, context, visit)
	case *ast.IfStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(&n.Cond, "expr", visit)
		f.walk(n.Body, "stmt", visit)
		f.walk(n.Else, "stmt", visit)
	case *ast.CaseClause:
		if context == "typeswitch" {
			context = "type"
		} else {
			context = "expr"
		}
		f.walk(n.List, context, visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.SwitchStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(&n.Tag, "expr", visit)
		f.walk(n.Body, "switch", visit)
	case *ast.TypeSwitchStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(n.Assign, "stmt", visit)
		f.walk(n.Body, "typeswitch", visit)
	case *ast.CommClause:
		f.walk(n.Comm, "stmt", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.SelectStmt:
		f.walk(n.Body, "stmt", visit)
	case *ast.ForStmt:
		f.walk(n.Init, "stmt", visit)
		f.walk(&n.Cond, "expr", visit)
		f.walk(n.Post, "stmt", visit)
		f.walk(n.Body, "stmt", visit)
	case *ast.RangeStmt:
		f.walk(&n.Key, "expr", visit)
		f.walk(&n.Value, "expr", visit)
		f.walk(&n.X, "expr", visit)
		f.walk(n.Body, "stmt", visit)

	case *ast.ImportSpec:
	case *ast.ValueSpec:
		f.walk(&n.Type, "type", visit)
		f.walk(n.Values, "expr", visit)
	case *ast.TypeSpec:
		f.walk(&n.Type, "type", visit)

	case *ast.BadDecl:
	case *ast.GenDecl:
		f.walk(n.Specs, "spec", visit)
	case *ast.FuncDecl:
		if n.Recv != nil {
			f.walk(n.Recv, "field", visit)
		}
		f.walk(n.Type, "type", visit)
		if n.Body != nil {
			f.walk(n.Body, "stmt", visit)
		}

	case *ast.File:
		f.walk(n.Decls, "decl", visit)

	case *ast.Package:
		for _, file := range n.Files {
			f.walk(file, "file", visit)
		}

	case []ast.Decl:
		for _, d := range n {
			f.walk(d, context, visit)
		}
	case []ast.Expr:
		for i := range n {
			f.walk(&n[i], context, visit)
		}
	case []ast.Stmt:
		for _, s := range n {
			f.walk(s, context, visit)
		}
	case []ast.Spec:
		for _, s := range n {
			f.walk(s, context, visit)
		}
	}
}
<|endoftext|>