<commit_before>// Copyright 2011 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.

package main

import (
	"syscall"
	"unsafe"
)

func loadDll(fname string) uint32 {
	h, e := syscall.LoadLibrary(fname)
	if e != 0 {
		abortf("LoadLibrary(%s) failed with err=%d.\n", fname, e)
	}
	return h
}

func getSysProcAddr(m uint32, pname string) uintptr {
	p, e := syscall.GetProcAddress(m, pname)
	if e != 0 {
		abortf("GetProcAddress(%s) failed with err=%d.\n", pname, e)
	}
	return uintptr(p)
}

type Wndclassex struct {
	Size       uint32
	Style      uint32
	WndProc    uintptr
	ClsExtra   int32
	WndExtra   int32
	Instance   uint32
	Icon       uint32
	Cursor     uint32
	Background uint32
	MenuName   *uint16
	ClassName  *uint16
	IconSm     uint32
}

type Point struct {
	X int32
	Y int32
}

type Msg struct {
	Hwnd    uint32
	Message uint32
	Wparam  int32
	Lparam  int32
	Time    uint32
	Pt      Point
}

const (
	// Window styles
	WS_OVERLAPPED   = 0
	WS_POPUP        = 0x80000000
	WS_CHILD        = 0x40000000
	WS_MINIMIZE     = 0x20000000
	WS_VISIBLE      = 0x10000000
	WS_DISABLED     = 0x8000000
	WS_CLIPSIBLINGS = 0x4000000
	WS_CLIPCHILDREN = 0x2000000
	WS_MAXIMIZE     = 0x1000000
	WS_CAPTION      = WS_BORDER | WS_DLGFRAME
	WS_BORDER       = 0x800000
	WS_DLGFRAME     = 0x400000
	WS_VSCROLL      = 0x200000
	WS_HSCROLL      = 0x100000
	WS_SYSMENU      = 0x80000
	WS_THICKFRAME   = 0x40000
	WS_GROUP        = 0x20000
	WS_TABSTOP      = 0x10000
	WS_MINIMIZEBOX  = 0x20000
	WS_MAXIMIZEBOX  = 0x10000
	WS_TILED        = WS_OVERLAPPED
	WS_ICONIC       = WS_MINIMIZE
	WS_SIZEBOX      = WS_THICKFRAME
	// Common Window Styles
	WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
	WS_TILEDWINDOW      = WS_OVERLAPPEDWINDOW
	WS_POPUPWINDOW      = WS_POPUP | WS_BORDER | WS_SYSMENU
	WS_CHILDWINDOW      = WS_CHILD

	WS_EX_CLIENTEDGE = 0x200

	// Some windows messages
	WM_CREATE  = 1
	WM_DESTROY = 2
	WM_CLOSE   = 16
	WM_COMMAND = 273

	// Some button control styles
	BS_DEFPUSHBUTTON = 1

	// Some color constants
	COLOR_WINDOW  = 5
	COLOR_BTNFACE = 15

	// Default window position
	CW_USEDEFAULT = 0x80000000 - 0x100000000

	// Show window default style
	SW_SHOWDEFAULT = 10
)

var (
	// Some globally known cursors
	IDC_ARROW = MakeIntResource(32512)
	IDC_IBEAM = MakeIntResource(32513)
	IDC_WAIT  = MakeIntResource(32514)
	IDC_CROSS = MakeIntResource(32515)

	// Some globally known icons
	IDI_APPLICATION = MakeIntResource(32512)
	IDI_HAND        = MakeIntResource(32513)
	IDI_QUESTION    = MakeIntResource(32514)
	IDI_EXCLAMATION = MakeIntResource(32515)
	IDI_ASTERISK    = MakeIntResource(32516)
	IDI_WINLOGO     = MakeIntResource(32517)
	IDI_WARNING     = IDI_EXCLAMATION
	IDI_ERROR       = IDI_HAND
	IDI_INFORMATION = IDI_ASTERISK
)

//sys	GetModuleHandle(modname *uint16) (handle uint32, errno int) = GetModuleHandleW
//sys	RegisterClassEx(wndclass *Wndclassex) (atom uint16, errno int) = user32.RegisterClassExW
//sys	CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent uint32, menu uint32, instance uint32, param uintptr) (hwnd uint32, errno int) = user32.CreateWindowExW
//sys	DefWindowProc(hwnd uint32, msg uint32, wparam int32, lparam int32) (lresult int32) = user32.DefWindowProcW
//sys	DestroyWindow(hwnd uint32) (errno int) = user32.DestroyWindow
//sys	PostQuitMessage(exitcode int32) = user32.PostQuitMessage
//sys	ShowWindow(hwnd uint32, cmdshow int32) (wasvisible bool) = user32.ShowWindow
//sys	UpdateWindow(hwnd uint32) (errno int) = user32.UpdateWindow
//sys	GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, errno int) [failretval==-1] = user32.GetMessageW
//sys	TranslateMessage(msg *Msg) (done bool) = user32.TranslateMessage
//sys	DispatchMessage(msg *Msg) (ret int32) = user32.DispatchMessageW
//sys	LoadIcon(instance uint32, iconname *uint16) (icon uint32, errno int) = user32.LoadIconW
//sys	LoadCursor(instance uint32, cursorname *uint16) (cursor uint32, errno int) = user32.LoadCursorW
//sys	SetCursor(cursor uint32) (precursor uint32, errno int) = user32.SetCursor
//sys	SendMessage(hwnd uint32, msg uint32, wparam int32, lparam int32) (lresult int32) = user32.SendMessageW
//sys	PostMessage(hwnd uint32, msg uint32, wparam int32, lparam int32) (errno int) = user32.PostMessageW

func MakeIntResource(id uint16) *uint16 {
	return (*uint16)(unsafe.Pointer(uintptr(id)))
}
<commit_msg>exp/wingui: make sure it builds again<commit_after>// Copyright 2011 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.

package main

import (
	"syscall"
	"unsafe"
)

func loadDll(fname string) syscall.Handle {
	h, e := syscall.LoadLibrary(fname)
	if e != 0 {
		abortf("LoadLibrary(%s) failed with err=%d.\n", fname, e)
	}
	return h
}

func getSysProcAddr(m syscall.Handle, pname string) uintptr {
	p, e := syscall.GetProcAddress(m, pname)
	if e != 0 {
		abortf("GetProcAddress(%s) failed with err=%d.\n", pname, e)
	}
	return uintptr(p)
}

type Wndclassex struct {
	Size       uint32
	Style      uint32
	WndProc    uintptr
	ClsExtra   int32
	WndExtra   int32
	Instance   uint32
	Icon       uint32
	Cursor     uint32
	Background uint32
	MenuName   *uint16
	ClassName  *uint16
	IconSm     uint32
}

type Point struct {
	X int32
	Y int32
}

type Msg struct {
	Hwnd    uint32
	Message uint32
	Wparam  int32
	Lparam  int32
	Time    uint32
	Pt      Point
}

const (
	// Window styles
	WS_OVERLAPPED   = 0
	WS_POPUP        = 0x80000000
	WS_CHILD        = 0x40000000
	WS_MINIMIZE     = 0x20000000
	WS_VISIBLE      = 0x10000000
	WS_DISABLED     = 0x8000000
	WS_CLIPSIBLINGS = 0x4000000
	WS_CLIPCHILDREN = 0x2000000
	WS_MAXIMIZE     = 0x1000000
	WS_CAPTION      = WS_BORDER | WS_DLGFRAME
	WS_BORDER       = 0x800000
	WS_DLGFRAME     = 0x400000
	WS_VSCROLL      = 0x200000
	WS_HSCROLL      = 0x100000
	WS_SYSMENU      = 0x80000
	WS_THICKFRAME   = 0x40000
	WS_GROUP        = 0x20000
	WS_TABSTOP      = 0x10000
	WS_MINIMIZEBOX  = 0x20000
	WS_MAXIMIZEBOX  = 0x10000
	WS_TILED        = WS_OVERLAPPED
	WS_ICONIC       = WS_MINIMIZE
	WS_SIZEBOX      = WS_THICKFRAME
	// Common Window Styles
	WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
	WS_TILEDWINDOW      = WS_OVERLAPPEDWINDOW
	WS_POPUPWINDOW      = WS_POPUP | WS_BORDER | WS_SYSMENU
	WS_CHILDWINDOW      = WS_CHILD

	WS_EX_CLIENTEDGE = 0x200

	// Some windows messages
	WM_CREATE  = 1
	WM_DESTROY = 2
	WM_CLOSE   = 16
	WM_COMMAND = 273

	// Some button control styles
	BS_DEFPUSHBUTTON = 1

	// Some color constants
	COLOR_WINDOW  = 5
	COLOR_BTNFACE = 15

	// Default window position
	CW_USEDEFAULT = 0x80000000 - 0x100000000

	// Show window default style
	SW_SHOWDEFAULT = 10
)

var (
	// Some globally known cursors
	IDC_ARROW = MakeIntResource(32512)
	IDC_IBEAM = MakeIntResource(32513)
	IDC_WAIT  = MakeIntResource(32514)
	IDC_CROSS = MakeIntResource(32515)

	// Some globally known icons
	IDI_APPLICATION = MakeIntResource(32512)
	IDI_HAND        = MakeIntResource(32513)
	IDI_QUESTION    = MakeIntResource(32514)
	IDI_EXCLAMATION = MakeIntResource(32515)
	IDI_ASTERISK    = MakeIntResource(32516)
	IDI_WINLOGO     = MakeIntResource(32517)
	IDI_WARNING     = IDI_EXCLAMATION
	IDI_ERROR       = IDI_HAND
	IDI_INFORMATION = IDI_ASTERISK
)

//sys	GetModuleHandle(modname *uint16) (handle uint32, errno int) = GetModuleHandleW
//sys	RegisterClassEx(wndclass *Wndclassex) (atom uint16, errno int) = user32.RegisterClassExW
//sys	CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent uint32, menu uint32, instance uint32, param uintptr) (hwnd uint32, errno int) = user32.CreateWindowExW
//sys	DefWindowProc(hwnd uint32, msg uint32, wparam int32, lparam int32) (lresult int32) = user32.DefWindowProcW
//sys	DestroyWindow(hwnd uint32) (errno int) = user32.DestroyWindow
//sys	PostQuitMessage(exitcode int32) = user32.PostQuitMessage
//sys	ShowWindow(hwnd uint32, cmdshow int32) (wasvisible bool) = user32.ShowWindow
//sys	UpdateWindow(hwnd uint32) (errno int) = user32.UpdateWindow
//sys	GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, errno int) [failretval==-1] = user32.GetMessageW
//sys	TranslateMessage(msg *Msg) (done bool) = user32.TranslateMessage
//sys	DispatchMessage(msg *Msg) (ret int32) = user32.DispatchMessageW
//sys	LoadIcon(instance uint32, iconname *uint16) (icon uint32, errno int) = user32.LoadIconW
//sys	LoadCursor(instance uint32, cursorname *uint16) (cursor uint32, errno int) = user32.LoadCursorW
//sys	SetCursor(cursor uint32) (precursor uint32, errno int) = user32.SetCursor
//sys	SendMessage(hwnd uint32, msg uint32, wparam int32, lparam int32) (lresult int32) = user32.SendMessageW
//sys	PostMessage(hwnd uint32, msg uint32, wparam int32, lparam int32) (errno int) = user32.PostMessageW

func MakeIntResource(id uint16) *uint16 {
	return (*uint16)(unsafe.Pointer(uintptr(id)))
}
<|endoftext|>


<commit_before>package llvm

/*
#include <llvm-c/Target.h>
#include <llvm-c/TargetMachine.h>
#include <stdlib.h>
*/
import "C"
import "unsafe"
import "errors"

type (
	TargetData struct {
		C C.LLVMTargetDataRef
	}
	StructLayout struct {
		C C.LLVMStructLayoutRef
	}
	Target struct {
		C C.LLVMTargetRef
	}
	TargetMachine struct {
		C C.LLVMTargetMachineRef
	}
	ByteOrdering    C.enum_LLVMByteOrdering
	RelocMode       C.LLVMRelocMode
	CodeGenOptLevel C.LLVMCodeGenOptLevel
	CodeGenFileType C.LLVMCodeGenFileType
	CodeModel       C.LLVMCodeModel
)

const (
	DefaultTargetTriple string = C.LLVM_DEFAULT_TARGET_TRIPLE
)

const (
	BigEndian    = C.LLVMBigEndian
	LittleEndian = C.LLVMLittleEndian
)

const (
	RelocDefault      RelocMode = C.LLVMRelocDefault
	RelocStatic       RelocMode = C.LLVMRelocStatic
	RelocPIC          RelocMode = C.LLVMRelocPIC
	RelocDynamicNoPic RelocMode = C.LLVMRelocDynamicNoPic
)

const (
	CodeGenLevelNone       CodeGenOptLevel = C.LLVMCodeGenLevelNone
	CodeGenLevelLess       CodeGenOptLevel = C.LLVMCodeGenLevelLess
	CodeGenLevelDefault    CodeGenOptLevel = C.LLVMCodeGenLevelDefault
	CodeGenLevelAggressive CodeGenOptLevel = C.LLVMCodeGenLevelAggressive
)

const (
	CodeModelDefault    CodeModel = C.LLVMCodeModelDefault
	CodeModelJITDefault CodeModel = C.LLVMCodeModelJITDefault
	CodeModelSmall      CodeModel = C.LLVMCodeModelSmall
	CodeModelKernel     CodeModel = C.LLVMCodeModelKernel
	CodeModelMedium     CodeModel = C.LLVMCodeModelMedium
	CodeModelLarge      CodeModel = C.LLVMCodeModelLarge
)

const (
	AssemblyFile CodeGenFileType = C.LLVMAssemblyFile
	ObjectFile   CodeGenFileType = C.LLVMObjectFile
)

// Declare all of the target-initialization functions that are available.

//#define LLVM_TARGET(TargetName) \
//  func Initialize##TargetName##TargetInfo() { C.LLVMInitialize##TargetName##TargetInfo() }
//#include "llvm/Config/Targets.def"
//#undef LLVM_TARGET  // Explicit undef to make SWIG happier
func InitializeMBlazeTargetInfo()     { C.LLVMInitializeMBlazeTargetInfo() }
func InitializeCppBackendTargetInfo() { C.LLVMInitializeCppBackendTargetInfo() }
func InitializeMSP430TargetInfo()     { C.LLVMInitializeMSP430TargetInfo() }
func InitializeXCoreTargetInfo()      { C.LLVMInitializeXCoreTargetInfo() }
func InitializeCellSPUTargetInfo()    { C.LLVMInitializeCellSPUTargetInfo() }
func InitializeMipsTargetInfo()       { C.LLVMInitializeMipsTargetInfo() }
func InitializeARMTargetInfo()        { C.LLVMInitializeARMTargetInfo() }
func InitializePowerPCTargetInfo()    { C.LLVMInitializePowerPCTargetInfo() }
func InitializeSparcTargetInfo()      { C.LLVMInitializeSparcTargetInfo() }
func InitializeX86TargetInfo()        { C.LLVMInitializeX86TargetInfo() }

//#define LLVM_TARGET(TargetName) \
//  func Initialize##TargetName##Target() { C.LLVMInitialize##TargetName##Target() }
//#include "llvm/Config/Targets.def"
//#undef LLVM_TARGET  // Explicit undef to make SWIG happier
func InitializeMBlazeTarget()     { C.LLVMInitializeMBlazeTarget() }
func InitializeCppBackendTarget() { C.LLVMInitializeCppBackendTarget() }
func InitializeMSP430Target()     { C.LLVMInitializeMSP430Target() }
func InitializeXCoreTarget()      { C.LLVMInitializeXCoreTarget() }
func InitializeCellSPUTarget()    { C.LLVMInitializeCellSPUTarget() }
func InitializeMipsTarget()       { C.LLVMInitializeMipsTarget() }
func InitializeARMTarget()        { C.LLVMInitializeARMTarget() }
func InitializePowerPCTarget()    { C.LLVMInitializePowerPCTarget() }
func InitializeSparcTarget()      { C.LLVMInitializeSparcTarget() }
func InitializeX86Target()        { C.LLVMInitializeX86Target() }

// LLVMInitializeAllTargetInfos - The main program should call this function if
// it wants access to all available targets that LLVM is configured to
// support.
func InitializeAllTargetInfos() { C.LLVMInitializeAllTargetInfos() }

// LLVMInitializeAllTargets - The main program should call this function if it
// wants to link in all available targets that LLVM is configured to
// support.
func InitializeAllTargets() { C.LLVMInitializeAllTargets() }

func InitializeAllTargetMCs() { C.LLVMInitializeAllTargetMCs() }

// LLVMInitializeNativeTarget - The main program should call this function to
// initialize the native target corresponding to the host. This is useful
// for JIT applications to ensure that the target gets linked in correctly.
var initializeNativeTargetError = errors.New("Failed to initialize native target")

func InitializeNativeTarget() error {
	fail := C.LLVMInitializeNativeTarget()
	if fail == 0 {
		return nil
	}
	return initializeNativeTargetError
}

//-------------------------------------------------------------------------
// llvm.TargetData
//-------------------------------------------------------------------------

// Creates target data from a target layout string.
// See the constructor llvm::TargetData::TargetData.
func NewTargetData(rep string) (td TargetData) {
	crep := C.CString(rep)
	td.C = C.LLVMCreateTargetData(crep)
	C.free(unsafe.Pointer(crep))
	return
}

// Adds target data information to a pass manager. This does not take ownership
// of the target data.
// See the method llvm::PassManagerBase::add.
func (pm PassManager) Add(td TargetData) {
	C.LLVMAddTargetData(td.C, pm.C)
}

// Converts target data to a target layout string. The string must be disposed
// with LLVMDisposeMessage.
// See the constructor llvm::TargetData::TargetData.
func (td TargetData) String() (s string) {
	cmsg := C.LLVMCopyStringRepOfTargetData(td.C)
	s = C.GoString(cmsg)
	C.LLVMDisposeMessage(cmsg)
	return
}

// Returns the byte order of a target, either LLVMBigEndian or
// LLVMLittleEndian.
// See the method llvm::TargetData::isLittleEndian.
func (td TargetData) ByteOrder() ByteOrdering { return ByteOrdering(C.LLVMByteOrder(td.C)) }

// Returns the pointer size in bytes for a target.
// See the method llvm::TargetData::getPointerSize.
func (td TargetData) PointerSize() int { return int(C.LLVMPointerSize(td.C)) }

// Returns the integer type that is the same size as a pointer on a target.
// See the method llvm::TargetData::getIntPtrType.
func (td TargetData) IntPtrType() (t Type) { t.C = C.LLVMIntPtrType(td.C); return }

// Computes the size of a type in bytes for a target.
// See the method llvm::TargetData::getTypeSizeInBits.
func (td TargetData) TypeSizeInBits(t Type) uint64 {
	return uint64(C.LLVMSizeOfTypeInBits(td.C, t.C))
}

// Computes the storage size of a type in bytes for a target.
// See the method llvm::TargetData::getTypeStoreSize.
func (td TargetData) TypeStoreSize(t Type) uint64 {
	return uint64(C.LLVMStoreSizeOfType(td.C, t.C))
}

// Computes the ABI size of a type in bytes for a target.
// See the method llvm::TargetData::getTypeAllocSize.
func (td TargetData) TypeAllocSize(t Type) uint64 {
	return uint64(C.LLVMABISizeOfType(td.C, t.C))
}

// Computes the ABI alignment of a type in bytes for a target.
// See the method llvm::TargetData::getABITypeAlignment.
func (td TargetData) ABITypeAlignment(t Type) int {
	return int(C.LLVMABIAlignmentOfType(td.C, t.C))
}

// Computes the call frame alignment of a type in bytes for a target.
// See the method llvm::TargetData::getCallFrameTypeAlignment.
func (td TargetData) CallFrameTypeAlignment(t Type) int {
	return int(C.LLVMCallFrameAlignmentOfType(td.C, t.C))
}

// Computes the preferred alignment of a type in bytes for a target.
// See the method llvm::TargetData::getPrefTypeAlignment.
func (td TargetData) PrefTypeAlignment(t Type) int {
	return int(C.LLVMPreferredAlignmentOfType(td.C, t.C))
}

// Computes the preferred alignment of a global variable in bytes for a target.
// See the method llvm::TargetData::getPreferredAlignment.
func (td TargetData) PreferredAlignment(g Value) int {
	return int(C.LLVMPreferredAlignmentOfGlobal(td.C, g.C))
}

// Computes the structure element that contains the byte offset for a target.
// See the method llvm::StructLayout::getElementContainingOffset.
func (td TargetData) ElementContainingOffset(t Type, offset uint64) int {
	return int(C.LLVMElementAtOffset(td.C, t.C, C.ulonglong(offset)))
}

// Computes the byte offset of the indexed struct element for a target.
// See the method llvm::StructLayout::getElementOffset.
func (td TargetData) ElementOffset(t Type, element int) uint64 {
	return uint64(C.LLVMOffsetOfElement(td.C, t.C, C.unsigned(element)))
}

// Deallocates a TargetData.
// See the destructor llvm::TargetData::~TargetData.
func (td TargetData) Dispose() { C.LLVMDisposeTargetData(td.C) }

///////////////////////////////////////////////////////////////////////////////
// Target

func FirstTarget() Target {
	return Target{C.LLVMGetFirstTarget()}
}

func (t Target) NextTarget() Target {
	return Target{C.LLVMGetNextTarget(t.C)}
}

func (t Target) Name() string {
	return C.GoString(C.LLVMGetTargetName(t.C))
}

func (t Target) Description() string {
	return C.GoString(C.LLVMGetTargetDescription(t.C))
}

///////////////////////////////////////////////////////////////////////////////
// TargetMachine

// CreateTargetMachine creates a new TargetMachine.
func (t Target) CreateTargetMachine(Triple string, CPU string, Features string,
	Level CodeGenOptLevel, Reloc RelocMode,
	CodeModel CodeModel) (tm TargetMachine) {
	cTriple := C.CString(Triple)
	cCPU := C.CString(CPU)
	cFeatures := C.CString(Features)
	tm.C = C.LLVMCreateTargetMachine(t.C, cTriple, cCPU, cFeatures,
		C.LLVMCodeGenOptLevel(Level),
		C.LLVMRelocMode(Reloc),
		C.LLVMCodeModel(CodeModel))
	C.free(unsafe.Pointer(cTriple))
	C.free(unsafe.Pointer(cCPU))
	C.free(unsafe.Pointer(cFeatures))
	return
}

// Triple returns the triple describing the machine (arch-vendor-os).
func (tm TargetMachine) Triple() string {
	cstr := C.LLVMGetTargetMachineTriple(tm.C)
	return C.GoString(cstr)
}

// TargetData returns the TargetData for the machine.
func (tm TargetMachine) TargetData() TargetData {
	return TargetData{C.LLVMGetTargetMachineData(tm.C)}
}

// Dispose releases resources related to the TargetMachine.
func (tm TargetMachine) Dispose() {
	C.LLVMDisposeTargetMachine(tm.C)
}
<commit_msg>Remove target-specific InitializeXYZTarget functions.<commit_after>package llvm

/*
#include <llvm-c/Target.h>
#include <llvm-c/TargetMachine.h>
#include <stdlib.h>
*/
import "C"
import "unsafe"
import "errors"

type (
	TargetData struct {
		C C.LLVMTargetDataRef
	}
	StructLayout struct {
		C C.LLVMStructLayoutRef
	}
	Target struct {
		C C.LLVMTargetRef
	}
	TargetMachine struct {
		C C.LLVMTargetMachineRef
	}
	ByteOrdering    C.enum_LLVMByteOrdering
	RelocMode       C.LLVMRelocMode
	CodeGenOptLevel C.LLVMCodeGenOptLevel
	CodeGenFileType C.LLVMCodeGenFileType
	CodeModel       C.LLVMCodeModel
)

const (
	DefaultTargetTriple string = C.LLVM_DEFAULT_TARGET_TRIPLE
)

const (
	BigEndian    = C.LLVMBigEndian
	LittleEndian = C.LLVMLittleEndian
)

const (
	RelocDefault      RelocMode = C.LLVMRelocDefault
	RelocStatic       RelocMode = C.LLVMRelocStatic
	RelocPIC          RelocMode = C.LLVMRelocPIC
	RelocDynamicNoPic RelocMode = C.LLVMRelocDynamicNoPic
)

const (
	CodeGenLevelNone       CodeGenOptLevel = C.LLVMCodeGenLevelNone
	CodeGenLevelLess       CodeGenOptLevel = C.LLVMCodeGenLevelLess
	CodeGenLevelDefault    CodeGenOptLevel = C.LLVMCodeGenLevelDefault
	CodeGenLevelAggressive CodeGenOptLevel = C.LLVMCodeGenLevelAggressive
)

const (
	CodeModelDefault    CodeModel = C.LLVMCodeModelDefault
	CodeModelJITDefault CodeModel = C.LLVMCodeModelJITDefault
	CodeModelSmall      CodeModel = C.LLVMCodeModelSmall
	CodeModelKernel     CodeModel = C.LLVMCodeModelKernel
	CodeModelMedium     CodeModel = C.LLVMCodeModelMedium
	CodeModelLarge      CodeModel = C.LLVMCodeModelLarge
)

const (
	AssemblyFile CodeGenFileType = C.LLVMAssemblyFile
	ObjectFile   CodeGenFileType = C.LLVMObjectFile
)

// LLVMInitializeAllTargetInfos - The main program should call this function if
// it wants access to all available targets that LLVM is configured to
// support.
func InitializeAllTargetInfos() { C.LLVMInitializeAllTargetInfos() }

// LLVMInitializeAllTargets - The main program should call this function if it
// wants to link in all available targets that LLVM is configured to
// support.
func InitializeAllTargets() { C.LLVMInitializeAllTargets() }

func InitializeAllTargetMCs() { C.LLVMInitializeAllTargetMCs() }

// LLVMInitializeNativeTarget - The main program should call this function to
// initialize the native target corresponding to the host. This is useful
// for JIT applications to ensure that the target gets linked in correctly.
var initializeNativeTargetError = errors.New("Failed to initialize native target")

func InitializeNativeTarget() error {
	fail := C.LLVMInitializeNativeTarget()
	if fail == 0 {
		return nil
	}
	return initializeNativeTargetError
}

//-------------------------------------------------------------------------
// llvm.TargetData
//-------------------------------------------------------------------------

// Creates target data from a target layout string.
// See the constructor llvm::TargetData::TargetData.
func NewTargetData(rep string) (td TargetData) {
	crep := C.CString(rep)
	td.C = C.LLVMCreateTargetData(crep)
	C.free(unsafe.Pointer(crep))
	return
}

// Adds target data information to a pass manager. This does not take ownership
// of the target data.
// See the method llvm::PassManagerBase::add.
func (pm PassManager) Add(td TargetData) {
	C.LLVMAddTargetData(td.C, pm.C)
}

// Converts target data to a target layout string. The string must be disposed
// with LLVMDisposeMessage.
// See the constructor llvm::TargetData::TargetData.
func (td TargetData) String() (s string) {
	cmsg := C.LLVMCopyStringRepOfTargetData(td.C)
	s = C.GoString(cmsg)
	C.LLVMDisposeMessage(cmsg)
	return
}

// Returns the byte order of a target, either LLVMBigEndian or
// LLVMLittleEndian.
// See the method llvm::TargetData::isLittleEndian.
func (td TargetData) ByteOrder() ByteOrdering { return ByteOrdering(C.LLVMByteOrder(td.C)) }

// Returns the pointer size in bytes for a target.
// See the method llvm::TargetData::getPointerSize.
func (td TargetData) PointerSize() int { return int(C.LLVMPointerSize(td.C)) }

// Returns the integer type that is the same size as a pointer on a target.
// See the method llvm::TargetData::getIntPtrType.
func (td TargetData) IntPtrType() (t Type) { t.C = C.LLVMIntPtrType(td.C); return }

// Computes the size of a type in bytes for a target.
// See the method llvm::TargetData::getTypeSizeInBits.
func (td TargetData) TypeSizeInBits(t Type) uint64 {
	return uint64(C.LLVMSizeOfTypeInBits(td.C, t.C))
}

// Computes the storage size of a type in bytes for a target.
// See the method llvm::TargetData::getTypeStoreSize.
func (td TargetData) TypeStoreSize(t Type) uint64 {
	return uint64(C.LLVMStoreSizeOfType(td.C, t.C))
}

// Computes the ABI size of a type in bytes for a target.
// See the method llvm::TargetData::getTypeAllocSize.
func (td TargetData) TypeAllocSize(t Type) uint64 {
	return uint64(C.LLVMABISizeOfType(td.C, t.C))
}

// Computes the ABI alignment of a type in bytes for a target.
// See the method llvm::TargetData::getABITypeAlignment.
func (td TargetData) ABITypeAlignment(t Type) int {
	return int(C.LLVMABIAlignmentOfType(td.C, t.C))
}

// Computes the call frame alignment of a type in bytes for a target.
// See the method llvm::TargetData::getCallFrameTypeAlignment.
func (td TargetData) CallFrameTypeAlignment(t Type) int {
	return int(C.LLVMCallFrameAlignmentOfType(td.C, t.C))
}

// Computes the preferred alignment of a type in bytes for a target.
// See the method llvm::TargetData::getPrefTypeAlignment.
func (td TargetData) PrefTypeAlignment(t Type) int {
	return int(C.LLVMPreferredAlignmentOfType(td.C, t.C))
}

// Computes the preferred alignment of a global variable in bytes for a target.
// See the method llvm::TargetData::getPreferredAlignment.
func (td TargetData) PreferredAlignment(g Value) int {
	return int(C.LLVMPreferredAlignmentOfGlobal(td.C, g.C))
}

// Computes the structure element that contains the byte offset for a target.
// See the method llvm::StructLayout::getElementContainingOffset.
func (td TargetData) ElementContainingOffset(t Type, offset uint64) int {
	return int(C.LLVMElementAtOffset(td.C, t.C, C.ulonglong(offset)))
}

// Computes the byte offset of the indexed struct element for a target.
// See the method llvm::StructLayout::getElementOffset.
func (td TargetData) ElementOffset(t Type, element int) uint64 {
	return uint64(C.LLVMOffsetOfElement(td.C, t.C, C.unsigned(element)))
}

// Deallocates a TargetData.
// See the destructor llvm::TargetData::~TargetData.
func (td TargetData) Dispose() { C.LLVMDisposeTargetData(td.C) }

///////////////////////////////////////////////////////////////////////////////
// Target

func FirstTarget() Target {
	return Target{C.LLVMGetFirstTarget()}
}

func (t Target) NextTarget() Target {
	return Target{C.LLVMGetNextTarget(t.C)}
}

func (t Target) Name() string {
	return C.GoString(C.LLVMGetTargetName(t.C))
}

func (t Target) Description() string {
	return C.GoString(C.LLVMGetTargetDescription(t.C))
}

///////////////////////////////////////////////////////////////////////////////
// TargetMachine

// CreateTargetMachine creates a new TargetMachine.
func (t Target) CreateTargetMachine(Triple string, CPU string, Features string,
	Level CodeGenOptLevel, Reloc RelocMode,
	CodeModel CodeModel) (tm TargetMachine) {
	cTriple := C.CString(Triple)
	cCPU := C.CString(CPU)
	cFeatures := C.CString(Features)
	tm.C = C.LLVMCreateTargetMachine(t.C, cTriple, cCPU, cFeatures,
		C.LLVMCodeGenOptLevel(Level),
		C.LLVMRelocMode(Reloc),
		C.LLVMCodeModel(CodeModel))
	C.free(unsafe.Pointer(cTriple))
	C.free(unsafe.Pointer(cCPU))
	C.free(unsafe.Pointer(cFeatures))
	return
}

// Triple returns the triple describing the machine (arch-vendor-os).
func (tm TargetMachine) Triple() string {
	cstr := C.LLVMGetTargetMachineTriple(tm.C)
	return C.GoString(cstr)
}

// TargetData returns the TargetData for the machine.
func (tm TargetMachine) TargetData() TargetData {
	return TargetData{C.LLVMGetTargetMachineData(tm.C)}
}

// Dispose releases resources related to the TargetMachine.
func (tm TargetMachine) Dispose() {
	C.LLVMDisposeTargetMachine(tm.C)
}
<|endoftext|>


<commit_before>package junta

import (
	"os"
	"net"

	"junta/util"
	"junta/proto"
)

func ListenAndServe(addr string) os.Error {
	logger := util.NewLogger("main")

	logger.Logf("binding to %s", addr)
	lisn, err := net.Listen("tcp", addr)
	if err != nil {
		logger.Log("unable to listen on %s: %s", addr, err)
		os.Exit(1)
	}

	logger.Logf("listening on %s", addr)

	for {
		conn, err := lisn.Accept()
		if err != nil {
			logger.Log("unable to accept on %s: %s", addr, err)
			continue
		}
		go serveConn(conn)
	}

	return nil
}

func serveConn(conn net.Conn) {
	c := proto.NewConn(conn)
	logger := util.NewLogger("%v", conn.RemoteAddr())
	logger.Logf("accepted connection")
	for {
		rid, parts, err := c.ReadRequest()
		if err != nil {
			if err == os.EOF {
				logger.Log("connection closed by peer")
			} else {
				logger.Log(err)
			}
			return
		}

		rlogger := util.NewLogger("%v - req [%d]", conn.RemoteAddr(), rid)
		rlogger.Logf("received <%v>", parts)

		if len(parts) == 0 {
			rlogger.Logf("len(parts) == 0")
			rlogger.Logf("before error")
			c.SendError(rid, proto.InvalidCommand)
			rlogger.Logf("after error")
			continue
		}

		switch parts[0] {
		default:
			rlogger.Logf("unknown command <%s>", parts[0])
			c.SendError(rid, proto.InvalidCommand)
		case "set":
			//go set(c, rid, parts[1:])
			rlogger.Logf("set %q=%q", parts[1], parts[2])
			c.SendResponse(rid, "OK")
		}
		rlogger.Logf("bottom")
	}
}

<commit_msg>create server object<commit_after>package junta

import (
	"os"
	"net"
	"log"

	"junta/util"
	"junta/proto"
)

type server struct {
	net.Listener
	logger *log.Logger
}

func (s server) acceptAndServe() {
	for {
		conn, err := s.Accept()
		if err != nil {
			s.logger.Logf("%s: %s", s.Listener, err)
			continue
		}
		go s.serve(conn)
	}
}

func (server) serve(conn net.Conn) {
	c := proto.NewConn(conn)
	logger := util.NewLogger("%v", conn.RemoteAddr())
	logger.Log("accepted connection")
	for {
		rid, parts, err := c.ReadRequest()
		if err != nil {
			if err == os.EOF {
				logger.Log("connection closed by peer")
			} else {
				logger.Log(err)
			}
			return
		}

		rlogger := util.NewLogger("%v - req [%d]", conn.RemoteAddr(), rid)
		rlogger.Logf("received <%v>", parts)

		if len(parts) == 0 {
			rlogger.Log("len(parts) == 0")
			rlogger.Log("before error")
			c.SendError(rid, proto.InvalidCommand)
			rlogger.Log("after error")
			continue
		}

		switch parts[0] {
		default:
			rlogger.Logf("unknown command <%s>", parts[0])
			c.SendError(rid, proto.InvalidCommand)
		case "set":
			//go set(c, rid, parts[1:])
			rlogger.Logf("set %q=%q", parts[1], parts[2])
			c.SendResponse(rid, "OK")
		}
		rlogger.Log("bottom")
	}
}

func ListenAndServe(addr string) os.Error {
	logger := util.NewLogger("server %s", addr)

	logger.Logf("binding to %s", addr)
	lisn, err := net.Listen("tcp", addr)
	if err != nil {
		logger.Log(err)
		return err
	}

	logger.Logf("listening on %s", addr)

	server := &server{lisn, logger}
	server.acceptAndServe()

	return nil
}
<|endoftext|>


<commit_before>// +build local

/*
   Copyright 2020 Docker Compose CLI 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 local

import (
	"context"
	"fmt"
	"os"
	"path"
	"strings"

	"github.com/docker/docker/errdefs"

	"github.com/compose-spec/compose-go/types"
	"github.com/docker/buildx/build"
	"github.com/docker/buildx/driver"
	_ "github.com/docker/buildx/driver/docker" // required to get default driver registered
	"github.com/docker/buildx/util/progress"
)

func (s *composeService) ensureImagesExists(ctx context.Context, project *types.Project) error {
	opts := map[string]build.Options{}
	for _, service := range project.Services {
		if service.Image == "" && service.Build == nil {
			return fmt.Errorf("invalid service %q. Must specify either image or build", service.Name)
		}

		// TODO build vs pull should be controlled by pull policy, see https://github.com/compose-spec/compose-spec/issues/26
		if service.Image != "" {
			needPull, err := s.needPull(ctx, service)
			if err != nil {
				return err
			}
			if !needPull {
				continue
			}
		}
		if service.Build != nil {
			opts[service.Name] = s.toBuildOptions(service, project.WorkingDir)
			continue
		}

		// Buildx has no command to "just pull", see
		// so we bake a temporary dockerfile that will just pull and export pulled image
		opts[service.Name] = build.Options{
			Inputs: build.Inputs{
				ContextPath:    ".",
				DockerfilePath: "-",
				InStream:       strings.NewReader("FROM " + service.Image),
			},
			Tags: []string{service.Image},
			Pull: true,
		}

	}

	return s.build(ctx, project, opts)
}

func (s *composeService) needPull(ctx context.Context, service types.ServiceConfig) (bool, error) {
	_, _, err := s.apiClient.ImageInspectWithRaw(ctx, service.Image)
	if err != nil {
		if errdefs.IsNotFound(err) {
			return true, nil
		}
		return false, err
	}
	return false, nil
}

func (s *composeService) build(ctx context.Context, project *types.Project, opts map[string]build.Options) error {
	const drivername = "default"
	d, err := driver.GetDriver(ctx, drivername, nil, s.apiClient, nil, nil, "", nil, project.WorkingDir)
	if err != nil {
		return err
	}
	driverInfo := []build.DriverInfo{
		{
			Name:   "default",
			Driver: d,
		},
	}
	// We rely on buildx "docker" builder integrated in docker engine, so don't need a DockerAPI here
	w := progress.NewPrinter(ctx, os.Stdout, "auto")
	_, err = build.Build(ctx, driverInfo, opts, nil, nil, w)
	return err
}

func (s *composeService) toBuildOptions(service types.ServiceConfig, contextPath string) build.Options {
	var tags []string
	if service.Image != "" {
		tags = append(tags, service.Image)
	}

	if service.Build.Dockerfile == "" {
		service.Build.Dockerfile = "Dockerfile"
	}
	var buildArgs map[string]string

	return build.Options{
		Inputs: build.Inputs{
			ContextPath:    path.Join(contextPath, service.Build.Context),
			DockerfilePath: path.Join(contextPath, service.Build.Context, service.Build.Dockerfile),
		},
		BuildArgs: flatten(mergeArgs(service.Build.Args, buildArgs)),
		Tags:      tags,
	}
}

func flatten(in types.MappingWithEquals) map[string]string {
	if len(in) == 0 {
		return nil
	}
	out := make(map[string]string)
	for k, v := range in {
		if v == nil {
			continue
		}
		out[k] = *v
	}
	return out
}

func mergeArgs(src types.MappingWithEquals, values map[string]string) types.MappingWithEquals {
	for key := range src {
		if val, ok := values[key]; ok {
			if val == "" {
				src[key] = nil
			} else {
				src[key] = &val
			}
		}
	}
	return src
}
<commit_msg>Don't start buildx' build with empty opts<commit_after>// +build local

/*
   Copyright 2020 Docker Compose CLI 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 local

import (
	"context"
	"fmt"
	"os"
	"path"
	"strings"

	"github.com/docker/docker/errdefs"

	"github.com/compose-spec/compose-go/types"
	"github.com/docker/buildx/build"
	"github.com/docker/buildx/driver"
	_ "github.com/docker/buildx/driver/docker" // required to get default driver registered
	"github.com/docker/buildx/util/progress"
)

func (s *composeService) ensureImagesExists(ctx context.Context, project *types.Project) error {
	opts := map[string]build.Options{}
	for _, service := range project.Services {
		if service.Image == "" && service.Build == nil {
			return fmt.Errorf("invalid service %q. Must specify either image or build", service.Name)
		}

		// TODO build vs pull should be controlled by pull policy, see https://github.com/compose-spec/compose-spec/issues/26
		if service.Image != "" {
			needPull, err := s.needPull(ctx, service)
			if err != nil {
				return err
			}
			if !needPull {
				continue
			}
		}
		if service.Build != nil {
			opts[service.Name] = s.toBuildOptions(service, project.WorkingDir)
			continue
		}

		// Buildx has no command to "just pull", see
		// so we bake a temporary dockerfile that will just pull and export pulled image
		opts[service.Name] = build.Options{
			Inputs: build.Inputs{
				ContextPath:    ".",
				DockerfilePath: "-",
				InStream:       strings.NewReader("FROM " + service.Image),
			},
			Tags: []string{service.Image},
			Pull: true,
		}

	}

	return s.build(ctx, project, opts)
}

func (s *composeService) needPull(ctx context.Context, service types.ServiceConfig) (bool, error) {
	_, _, err := s.apiClient.ImageInspectWithRaw(ctx, service.Image)
	if err != nil {
		if errdefs.IsNotFound(err) {
			return true, nil
		}
		return false, err
	}
	return false, nil
}

func (s *composeService) build(ctx context.Context, project *types.Project, opts map[string]build.Options) error {
	if len(opts) == 0 {
		return nil
	}
	const drivername = "default"
	d, err := driver.GetDriver(ctx, drivername, nil, s.apiClient, nil, nil, "", nil, project.WorkingDir)
	if err != nil {
		return err
	}
	driverInfo := []build.DriverInfo{
		{
			Name:   "default",
			Driver: d,
		},
	}
	// We rely on buildx "docker" builder integrated in docker engine, so don't need a DockerAPI here
	w := progress.NewPrinter(ctx, os.Stdout, "auto")
	_, err = build.Build(ctx, driverInfo, opts, nil, nil, w)
	return err
}

func (s *composeService) toBuildOptions(service types.ServiceConfig, contextPath string) build.Options {
	var tags []string
	if service.Image != "" {
		tags = append(tags, service.Image)
	}

	if service.Build.Dockerfile == "" {
		service.Build.Dockerfile = "Dockerfile"
	}
	var buildArgs map[string]string

	return build.Options{
		Inputs: build.Inputs{
			ContextPath:    path.Join(contextPath, service.Build.Context),
			DockerfilePath: path.Join(contextPath, service.Build.Context, service.Build.Dockerfile),
		},
		BuildArgs: flatten(mergeArgs(service.Build.Args, buildArgs)),
		Tags:      tags,
	}
}

func flatten(in types.MappingWithEquals) map[string]string {
	if len(in) == 0 {
		return nil
	}
	out := make(map[string]string)
	for k, v := range in {
		if v == nil {
			continue
		}
		out[k] = *v
	}
	return out
}

func mergeArgs(src types.MappingWithEquals, values map[string]string) types.MappingWithEquals {
	for key := range src {
		if val, ok := values[key]; ok {
			if val == "" {
				src[key] = nil
			} else {
				src[key] = &val
			}
		}
	}
	return src
}
<|endoftext|>


<commit_before>package appdash

import (
	"errors"
	"fmt"
	"net/url"
	"reflect"
	"time"

	influxDBClient "github.com/influxdb/influxdb/client"
	influxDBServer "github.com/influxdb/influxdb/cmd/influxd/run"
	influxDBModels "github.com/influxdb/influxdb/models"
)

const (
	dbName               string = "appdash" // InfluxDB db name.
	spanMeasurementName  string = "spans"   // InfluxDB container name for trace spans.
	defaultTracesPerPage int    = 10        // Default number of traces per page.
)

// Compile-time "implements" check.
var _ interface {
	Store
	Queryer
} = (*InfluxDBStore)(nil)

// TODO: should be a constant.
var zeroID = fmt.Sprintf("%016x", uint64(0))

type InfluxDBStore struct {
	con           *influxDBClient.Client // InfluxDB client connection.
	server        *influxDBServer.Server // InfluxDB API server.
	tracesPerPage int                    // Number of traces per page.
}

func (in *InfluxDBStore) Collect(id SpanID, anns ...Annotation) error {
	// Current strategy is to remove existing span and save new one
	// instead of updating the existing one.
	// TODO: explore a more efficient alternative strategy.
	if err := in.removeSpanIfExists(id); err != nil {
		return err
	}
	// trace_id, span_id & parent_id are set as tags
	// because InfluxDB tags are indexed & those values
	// are uselater on queries.
	tags := make(map[string]string, 3)
	tags["trace_id"] = id.Trace.String()
	tags["span_id"] = id.Span.String()
	tags["parent_id"] = id.Parent.String()
	// Saving annotations as InfluxDB measurement spans fields
	// which are not indexed.
	fields := make(map[string]interface{}, len(anns))
	for _, ann := range anns {
		fields[ann.Key] = string(ann.Value)
	}
	// InfluxDB point represents a single span.
	pts := []influxDBClient.Point{
		influxDBClient.Point{
			Measurement: spanMeasurementName,
			Tags:        tags,   // indexed metadata.
			Fields:      fields, // non-indexed metadata.
			Time:        time.Now(),
			Precision:   "s",
		},
	}
	bps := influxDBClient.BatchPoints{
		Points:          pts,
		Database:        dbName,
		RetentionPolicy: "default",
	}
	_, err := in.con.Write(bps)
	if err != nil {
		return err
	}
	return nil
}

func (in *InfluxDBStore) Trace(id ID) (*Trace, error) {
	trace := &Trace{}
	// GROUP BY * -> meaning group by all tags(trace_id, span_id & parent_id)
	// grouping by all tags includes those and it's values on the query response.
	q := fmt.Sprintf("SELECT * FROM spans WHERE trace_id='%s' GROUP BY *", id)
	result, err := in.executeOneQuery(q)
	if err != nil {
		return nil, err
	}
	// result.Series -> A slice containing all the spans.
	if len(result.Series) == 0 {
		return nil, errors.New("trace not found")
	}
	var isRootSpan bool
	// Iterate over series(spans) to create trace children's & set trace fields.
	for _, s := range result.Series {
		span, err := newSpanFromRow(&s)
		if err != nil {
			return nil, err
		}
		if span.ID.Parent == 0 && isRootSpan {
			// Must be a single root span.
			return nil, errors.New("unexpected multiple root spans")
		}
		if span.ID.Parent == 0 && !isRootSpan {
			isRootSpan = true
		}
		annotations, err := annotationsFromRow(&s)
		if err != nil {
			return trace, nil
		}
		span.Annotations = *annotations
		if isRootSpan { // root span.
			trace.Span = *span
		} else { // children span.
			trace.Sub = append(trace.Sub, &Trace{Span: *span})
		}
	}
	return trace, nil
}

func (in *InfluxDBStore) Traces() ([]*Trace, error) {
	traces := make([]*Trace, 0)
	// GROUP BY * -> meaning group by all tags(trace_id, span_id & parent_id)
	// grouping by all tags includes those and it's values on the query response.
	rootSpansQuery := fmt.Sprintf("SELECT * FROM spans WHERE parent_id='%s' GROUP BY * LIMIT %d", zeroID, in.tracesPerPage)
	rootSpansResult, err := in.executeOneQuery(rootSpansQuery)
	if err != nil {
		return nil, err
	}
	// result.Series -> A slice containing all the spans.
	if len(rootSpansResult.Series) == 0 {
		return traces, nil
	}
	// Cache to keep track of traces to be returned.
	tracesCache := make(map[ID]*Trace, 0)
	// Iterate over series(spans) to create traces.
	for _, s := range rootSpansResult.Series {
		span, err := newSpanFromRow(&s)
		if err != nil {
			return nil, err
		}
		annotations, err := annotationsFromRow(&s)
		if err != nil {
			return nil, err
		}
		span.Annotations = *annotations
		_, present := tracesCache[span.ID.Trace]
		if !present {
			tracesCache[span.ID.Trace] = &Trace{Span: *span}
		} else {
			return nil, errors.New("duplicated root span")
		}
	}
	// Using 'OR' since 'IN' not supported yet.
	where := `WHERE `
	var i int = 1
	for _, trace := range tracesCache {
		where += fmt.Sprintf("(trace_id='%s' AND parent_id!='%s')", trace.Span.ID.Trace, zeroID)
		// Adds 'OR' except for last iteration.
		if i != len(tracesCache) && len(tracesCache) > 1 {
			where += " OR "
		}
		i += 1
	}
	// Queries for all children spans of the traces to be returned.
	childrenSpansQuery := fmt.Sprintf("SELECT * FROM spans %s GROUP BY *", where)
	childreSpansResult, err := in.executeOneQuery(childrenSpansQuery)
	if err != nil {
		return nil, err
	}
	// Iterate over series(children spans) to create sub-traces
	// and associates sub-traces with it's parent trace.
	for _, s := range childreSpansResult.Series {
		span, err := newSpanFromRow(&s)
		if err != nil {
			return nil, err
		}
		annotations, err := annotationsFromRow(&s)
		if err != nil {
			return nil, err
		}
		span.Annotations = *annotations
		trace, present := tracesCache[span.ID.Trace]
		if !present { // Root trace not added.
			return nil, errors.New("parent not found")
		} else { // Root trace already added so append a sub-trace.
			trace.Sub = append(trace.Sub, &Trace{Span: *span})
		}
	}
	for _, trace := range tracesCache {
		traces = append(traces, trace)
	}
	return traces, nil
}

func (in *InfluxDBStore) Close() {
	in.server.Close()
}

func (in *InfluxDBStore) createDBIfNotExists() error {
	// If no errors query execution was successfully - either DB was created or already exists.
	response, err := in.con.Query(influxDBClient.Query{
		Command: fmt.Sprintf("%s %s", "CREATE DATABASE IF NOT EXISTS", dbName),
	})
	if err != nil {
		return err
	}
	if response.Error() != nil {
		return response.Error()
	}
	return nil
}

func (in *InfluxDBStore) executeOneQuery(command string) (*influxDBClient.Result, error) {
	response, err := in.con.Query(influxDBClient.Query{
		Command:  command,
		Database: dbName,
	})
	if err != nil {
		return nil, err
	}
	if response.Error() != nil {
		return nil, response.Error()
	}
	// Expecting one result, since a single query is executed.
	if len(response.Results) != 1 {
		return nil, errors.New("unexpected number of results for an influxdb single query")
	}
	return &response.Results[0], nil
}

func (in *InfluxDBStore) init(server *influxDBServer.Server) error {
	in.server = server
	url, err := url.Parse(fmt.Sprintf("http://%s:%d", influxDBClient.DefaultHost, influxDBClient.DefaultPort))
	if err != nil {
		return err
	}
	con, err := influxDBClient.NewClient(influxDBClient.Config{URL: *url})
	if err != nil {
		return err
	}
	in.con = con
	if err := in.createDBIfNotExists(); err != nil {
		return err
	}
	in.tracesPerPage = defaultTracesPerPage
	return nil
}

func (in *InfluxDBStore) removeSpanIfExists(id SpanID) error {
	cmd := fmt.Sprintf(`
		DROP SERIES FROM spans WHERE trace_id = '%s' AND span_id = '%s' AND parent_id = '%s'
	`, id.Trace.String(), id.Span.String(), id.Parent.String())
	_, err := in.executeOneQuery(cmd)
	if err != nil {
		return err
	}
	return nil
}

func annotationsFromRow(r *influxDBModels.Row) (*Annotations, error) {
	// Actually an influxDBModels.Row represents a single InfluxDB serie.
	// r.Values[n] is a slice containing span's annotation values.
	var fields []interface{}
	if len(r.Values) == 1 {
		fields = r.Values[0]
	}
	// len(r.Values) might be greater than one - meaning there are
	// some spans to drop, see: InfluxDBStore.Collect(...).
	// If so last one is picked.
	if len(r.Values) > 1 {
		fields = r.Values[len(r.Values)-1]
	}
	annotations := make(Annotations, len(fields))
	// Iterates over fields which represent span's annotation values.
	for i, field := range fields {
		// It is safe to do column[0] (eg. 'Server.Request.Method')
		// matches fields[0] (eg. 'GET')
		key := r.Columns[i]
		var value []byte
		switch field.(type) {
		case string:
			value = []byte(field.(string))
		case nil:
		default:
			return nil, fmt.Errorf("unexpected field type: %v", reflect.TypeOf(field))
		}
		a := Annotation{
			Key:   key,
			Value: value,
		}
		annotations = append(annotations, a)
	}
	return &annotations, nil
}

func newSpanFromRow(r *influxDBModels.Row) (*Span, error) {
	span := &Span{}
	traceID, err := ParseID(r.Tags["trace_id"])
	if err != nil {
		return nil, err
	}
	spanID, err := ParseID(r.Tags["span_id"])
	if err != nil {
		return nil, err
	}
	parentID, err := ParseID(r.Tags["parent_id"])
	if err != nil {
		return nil, err
	}
	span.ID = SpanID{
		Trace:  ID(traceID),
		Span:   ID(spanID),
		Parent: ID(parentID),
	}
	return span, nil
}

func NewInfluxDBStore(c *influxDBServer.Config, bi *influxDBServer.BuildInfo) (*InfluxDBStore, error) {
	//TODO: add Authentication.
	s, err := influxDBServer.NewServer(c, bi)
	if err != nil {
		return nil, err
	}
	if err := s.Open(); err != nil {
		return nil, err
	}
	var in InfluxDBStore
	if err := in.init(s); err != nil {
		return nil, err
	}
	return &in, nil
}
<commit_msg>use map literals instead for readability<commit_after>package appdash

import (
	"errors"
	"fmt"
	"net/url"
	"reflect"
	"time"

	influxDBClient "github.com/influxdb/influxdb/client"
	influxDBServer "github.com/influxdb/influxdb/cmd/influxd/run"
	influxDBModels "github.com/influxdb/influxdb/models"
)

const (
	dbName               string = "appdash" // InfluxDB db name.
	spanMeasurementName  string = "spans"   // InfluxDB container name for trace spans.
	defaultTracesPerPage int    = 10        // Default number of traces per page.
)

// Compile-time "implements" check.
var _ interface {
	Store
	Queryer
} = (*InfluxDBStore)(nil)

// TODO: should be a constant.
var zeroID = fmt.Sprintf("%016x", uint64(0))

type InfluxDBStore struct {
	con           *influxDBClient.Client // InfluxDB client connection.
	server        *influxDBServer.Server // InfluxDB API server.
	tracesPerPage int                    // Number of traces per page.
}

func (in *InfluxDBStore) Collect(id SpanID, anns ...Annotation) error {
	// Current strategy is to remove existing span and save new one
	// instead of updating the existing one.
	// TODO: explore a more efficient alternative strategy.
	if err := in.removeSpanIfExists(id); err != nil {
		return err
	}
	// trace_id, span_id & parent_id are set as tags
	// because InfluxDB tags are indexed & those values
	// are uselater on queries.
	tags := map[string]string{
		"trace_id":  id.Trace.String(),
		"span_id":   id.Span.String(),
		"parent_id": id.Parent.String(),
	}
	// Saving annotations as InfluxDB measurement spans fields
	// which are not indexed.
	fields := make(map[string]interface{}, len(anns))
	for _, ann := range anns {
		fields[ann.Key] = string(ann.Value)
	}
	// InfluxDB point represents a single span.
	pts := []influxDBClient.Point{
		influxDBClient.Point{
			Measurement: spanMeasurementName,
			Tags:        tags,   // indexed metadata.
			Fields:      fields, // non-indexed metadata.
			Time:        time.Now(),
			Precision:   "s",
		},
	}
	bps := influxDBClient.BatchPoints{
		Points:          pts,
		Database:        dbName,
		RetentionPolicy: "default",
	}
	_, err := in.con.Write(bps)
	if err != nil {
		return err
	}
	return nil
}

func (in *InfluxDBStore) Trace(id ID) (*Trace, error) {
	trace := &Trace{}
	// GROUP BY * -> meaning group by all tags(trace_id, span_id & parent_id)
	// grouping by all tags includes those and it's values on the query response.
	q := fmt.Sprintf("SELECT * FROM spans WHERE trace_id='%s' GROUP BY *", id)
	result, err := in.executeOneQuery(q)
	if err != nil {
		return nil, err
	}
	// result.Series -> A slice containing all the spans.
	if len(result.Series) == 0 {
		return nil, errors.New("trace not found")
	}
	var isRootSpan bool
	// Iterate over series(spans) to create trace children's & set trace fields.
	for _, s := range result.Series {
		span, err := newSpanFromRow(&s)
		if err != nil {
			return nil, err
		}
		if span.ID.Parent == 0 && isRootSpan {
			// Must be a single root span.
			return nil, errors.New("unexpected multiple root spans")
		}
		if span.ID.Parent == 0 && !isRootSpan {
			isRootSpan = true
		}
		annotations, err := annotationsFromRow(&s)
		if err != nil {
			return trace, nil
		}
		span.Annotations = *annotations
		if isRootSpan { // root span.
			trace.Span = *span
		} else { // children span.
			trace.Sub = append(trace.Sub, &Trace{Span: *span})
		}
	}
	return trace, nil
}

func (in *InfluxDBStore) Traces() ([]*Trace, error) {
	traces := make([]*Trace, 0)
	// GROUP BY * -> meaning group by all tags(trace_id, span_id & parent_id)
	// grouping by all tags includes those and it's values on the query response.
	rootSpansQuery := fmt.Sprintf("SELECT * FROM spans WHERE parent_id='%s' GROUP BY * LIMIT %d", zeroID, in.tracesPerPage)
	rootSpansResult, err := in.executeOneQuery(rootSpansQuery)
	if err != nil {
		return nil, err
	}
	// result.Series -> A slice containing all the spans.
	if len(rootSpansResult.Series) == 0 {
		return traces, nil
	}
	// Cache to keep track of traces to be returned.
	tracesCache := make(map[ID]*Trace, 0)
	// Iterate over series(spans) to create traces.
	for _, s := range rootSpansResult.Series {
		span, err := newSpanFromRow(&s)
		if err != nil {
			return nil, err
		}
		annotations, err := annotationsFromRow(&s)
		if err != nil {
			return nil, err
		}
		span.Annotations = *annotations
		_, present := tracesCache[span.ID.Trace]
		if !present {
			tracesCache[span.ID.Trace] = &Trace{Span: *span}
		} else {
			return nil, errors.New("duplicated root span")
		}
	}
	// Using 'OR' since 'IN' not supported yet.
	where := `WHERE `
	var i int = 1
	for _, trace := range tracesCache {
		where += fmt.Sprintf("(trace_id='%s' AND parent_id!='%s')", trace.Span.ID.Trace, zeroID)
		// Adds 'OR' except for last iteration.
		if i != len(tracesCache) && len(tracesCache) > 1 {
			where += " OR "
		}
		i += 1
	}
	// Queries for all children spans of the traces to be returned.
	childrenSpansQuery := fmt.Sprintf("SELECT * FROM spans %s GROUP BY *", where)
	childreSpansResult, err := in.executeOneQuery(childrenSpansQuery)
	if err != nil {
		return nil, err
	}
	// Iterate over series(children spans) to create sub-traces
	// and associates sub-traces with it's parent trace.
	for _, s := range childreSpansResult.Series {
		span, err := newSpanFromRow(&s)
		if err != nil {
			return nil, err
		}
		annotations, err := annotationsFromRow(&s)
		if err != nil {
			return nil, err
		}
		span.Annotations = *annotations
		trace, present := tracesCache[span.ID.Trace]
		if !present { // Root trace not added.
			return nil, errors.New("parent not found")
		} else { // Root trace already added so append a sub-trace.
			trace.Sub = append(trace.Sub, &Trace{Span: *span})
		}
	}
	for _, trace := range tracesCache {
		traces = append(traces, trace)
	}
	return traces, nil
}

func (in *InfluxDBStore) Close() {
	in.server.Close()
}

func (in *InfluxDBStore) createDBIfNotExists() error {
	// If no errors query execution was successfully - either DB was created or already exists.
	response, err := in.con.Query(influxDBClient.Query{
		Command: fmt.Sprintf("%s %s", "CREATE DATABASE IF NOT EXISTS", dbName),
	})
	if err != nil {
		return err
	}
	if response.Error() != nil {
		return response.Error()
	}
	return nil
}

func (in *InfluxDBStore) executeOneQuery(command string) (*influxDBClient.Result, error) {
	response, err := in.con.Query(influxDBClient.Query{
		Command:  command,
		Database: dbName,
	})
	if err != nil {
		return nil, err
	}
	if response.Error() != nil {
		return nil, response.Error()
	}
	// Expecting one result, since a single query is executed.
	if len(response.Results) != 1 {
		return nil, errors.New("unexpected number of results for an influxdb single query")
	}
	return &response.Results[0], nil
}

func (in *InfluxDBStore) init(server *influxDBServer.Server) error {
	in.server = server
	url, err := url.Parse(fmt.Sprintf("http://%s:%d", influxDBClient.DefaultHost, influxDBClient.DefaultPort))
	if err != nil {
		return err
	}
	con, err := influxDBClient.NewClient(influxDBClient.Config{URL: *url})
	if err != nil {
		return err
	}
	in.con = con
	if err := in.createDBIfNotExists(); err != nil {
		return err
	}
	in.tracesPerPage = defaultTracesPerPage
	return nil
}

func (in *InfluxDBStore) removeSpanIfExists(id SpanID) error {
	cmd := fmt.Sprintf(`
		DROP SERIES FROM spans WHERE trace_id = '%s' AND span_id = '%s' AND parent_id = '%s'
	`, id.Trace.String(), id.Span.String(), id.Parent.String())
	_, err := in.executeOneQuery(cmd)
	if err != nil {
		return err
	}
	return nil
}

func annotationsFromRow(r *influxDBModels.Row) (*Annotations, error) {
	// Actually an influxDBModels.Row represents a single InfluxDB serie.
	// r.Values[n] is a slice containing span's annotation values.
	var fields []interface{}
	if len(r.Values) == 1 {
		fields = r.Values[0]
	}
	// len(r.Values) might be greater than one - meaning there are
	// some spans to drop, see: InfluxDBStore.Collect(...).
	// If so last one is picked.
	if len(r.Values) > 1 {
		fields = r.Values[len(r.Values)-1]
	}
	annotations := make(Annotations, len(fields))
	// Iterates over fields which represent span's annotation values.
	for i, field := range fields {
		// It is safe to do column[0] (eg. 'Server.Request.Method')
		// matches fields[0] (eg. 'GET')
		key := r.Columns[i]
		var value []byte
		switch field.(type) {
		case string:
			value = []byte(field.(string))
		case nil:
		default:
			return nil, fmt.Errorf("unexpected field type: %v", reflect.TypeOf(field))
		}
		a := Annotation{
			Key:   key,
			Value: value,
		}
		annotations = append(annotations, a)
	}
	return &annotations, nil
}

func newSpanFromRow(r *influxDBModels.Row) (*Span, error) {
	span := &Span{}
	traceID, err := ParseID(r.Tags["trace_id"])
	if err != nil {
		return nil, err
	}
	spanID, err := ParseID(r.Tags["span_id"])
	if err != nil {
		return nil, err
	}
	parentID, err := ParseID(r.Tags["parent_id"])
	if err != nil {
		return nil, err
	}
	span.ID = SpanID{
		Trace:  ID(traceID),
		Span:   ID(spanID),
		Parent: ID(parentID),
	}
	return span, nil
}

func NewInfluxDBStore(c *influxDBServer.Config, bi *influxDBServer.BuildInfo) (*InfluxDBStore, error) {
	//TODO: add Authentication.
	s, err := influxDBServer.NewServer(c, bi)
	if err != nil {
		return nil, err
	}
	if err := s.Open(); err != nil {
		return nil, err
	}
	var in InfluxDBStore
	if err := in.init(s); err != nil {
		return nil, err
	}
	return &in, nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"github.com/coreos/go-namespaces/namespace"
	"github.com/docker/libcontainer/security/capabilities"
	"os"
	"path"
	"strconv"
	"strings"
	"syscall"
)

func nsenterdetect() (found bool, err error) {
	// We've inlined the subset of nsenter code we need for amd64 :)
	return true, nil
}

// from /usr/include/linux/sched.h
const (
	CLONE_VFORK = 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
	SIGCHLD     = 0x14       /* Should set SIGCHLD for fork()-like behavior on Linux */
)

func nsenterexec(pid int, uid int, gid int, wd string, shell string) (err error) {
	rootfd, rooterr := os.Open(fmt.Sprintf("/proc/%s/root", strconv.Itoa(pid)))
	if rooterr != nil {
		panic(fmt.Sprintf("Could not open fd to root: %s", rooterr))
	}
	// Find the user's homw directory (which should be bound in as a volume) in the
	// container process namespace, so we can chdir there later.
	cwdfd, cwderr := os.Open(fmt.Sprintf("/proc/%s/root%s", strconv.Itoa(pid), wd))
	if cwderr != nil {
		return errors.New(fmt.Sprintf("Could not open fd to desired cwd: %s", wd))
	}
	if strings.HasPrefix(shell, "/") != true {
		return errors.New(fmt.Sprintf("Shell '%s' does not start with /, need an absolute path", shell))
	}
	shell = path.Clean(shell)
	_, shellerr := os.Open(fmt.Sprintf("/proc/%s/root%s", strconv.Itoa(pid), shell))
	if shellerr != nil {
		return errors.New(fmt.Sprintf("Cannot find ynur shell %s inside your container", shell))
	}

	/* FIXME: Make these an array and loop through them, as this is gross */

	/* --ipc */
	ipcfd, ipcerr := namespace.OpenProcess(pid, namespace.CLONE_NEWIPC)
	if ipcfd == 0 || ipcerr != nil {
		panic("namespace.OpenProcess(pid, namespace.CLONE_NEWIPC)")
	}

	/* --uts */
	utsfd, utserr := namespace.OpenProcess(pid, namespace.CLONE_NEWUTS)
	if utsfd == 0 || utserr != nil {
		panic("namespace.OpenProcess(pid, namespace.CLONE_NEWUTS)")
	}

	/* --net */
	netfd, neterr := namespace.OpenProcess(pid, namespace.CLONE_NEWNET)
	if netfd == 0 || neterr != nil {
		panic("namespace.OpenProcess(pid, namespace.CLONE_NEWNET)")
	}

	/* --pid */
	pidfd, piderr := namespace.OpenProcess(pid, namespace.CLONE_NEWPID)
	if pidfd == 0 || piderr != nil {
		panic("namespace.OpenProcess(pid, namespace.CLONE_NEWPID)")
	}

	/* --mount */
	mountfd, mounterr := namespace.OpenProcess(pid, namespace.CLONE_NEWNS)
	if mountfd == 0 || mounterr != nil {
		panic("namespace.OpenProcess(pid, namespace.CLONE_NEWNS)")
	}

	namespace.Setns(ipcfd, namespace.CLONE_NEWIPC)
	namespace.Setns(utsfd, namespace.CLONE_NEWUTS)
	namespace.Setns(netfd, namespace.CLONE_NEWNET)
	namespace.Setns(pidfd, namespace.CLONE_NEWPID)
	namespace.Setns(mountfd, namespace.CLONE_NEWNS)

	_, _, echrootdir := syscall.Syscall(syscall.SYS_FCHDIR, rootfd.Fd(), 0, 0)
	if echrootdir != 0 {
		panic("chdir to new root failed")
	}
	chrooterr := syscall.Chroot(".")
	if chrooterr != nil {
		panic(fmt.Sprintf("chroot failed: %s", chrooterr))
	}
	// FIXME - this cwds to the cwd of the 'root' process inside the container, we probably want to cwd to user's homedir instead?
	_, _, ecwd := syscall.Syscall(syscall.SYS_FCHDIR, cwdfd.Fd(), 0, 0)
	if ecwd != 0 {
		panic("cwd to working directory failed")
	}

	namespace.Close(ipcfd)
	namespace.Close(utsfd)
	namespace.Close(netfd)
	namespace.Close(pidfd)
	namespace.Close(mountfd)

	/* END FIXME */

	// see go/src/pkg/syscall/exec_unix.go - not sure if this is needed or not (or if we should lock a larger section)
	syscall.ForkLock.Lock()

	/* Stolen from https://github.com/tobert/lnxns/blob/master/src/lnxns/nsfork_linux.go
	   CLONE_VFORK implies that the parent process won't resume until the child calls Exec,
	   which fixes the potential race conditions */

	var flags int = SIGCHLD | CLONE_VFORK
	r1, _, err1 := syscall.RawSyscall(syscall.SYS_CLONE, uintptr(flags), 0, 0)

	syscall.ForkLock.Unlock()

	if err1 == syscall.EINVAL {
		panic("OS returned EINVAL. Make sure your kernel configuration includes all CONFIG_*_NS options.")
	} else if err1 != 0 {
		panic(err1)
	}

	// parent will get the pid, child will be 0
	if int(r1) != 0 {
		// Parent process here
		proc, procerr := os.FindProcess(int(r1))
		if procerr != nil {
			fmt.Fprintf(os.Stderr, "Failed waiting for child: %s\n", strconv.Itoa(int(r1)))
			panic(procerr)
		}
		_, _ := proc.Wait()
		// FIXME: Deal with SIGSTOP on the child in the same way nsenter does?
		/* FIXME: Wait can detect if the child (immediately) fails, but better to do
		that reporting in the child process? Not sure, don't like throwing away err */
		/*if !pstate.Exited() {
			panic("Child has NOT exited")
		}*/
		return nil
	}

	// We're definitely in the child process by the time we get here.

	// Drop capabilities except those in the whitelist, from https://github.com/docker/docker/blob/master/daemon/execdriver/native/template/default_template.go
	cape := capabilities.DropBoundingSet([]string{
		"CHOWN",
		"DAC_OVERRIDE",
		"FSETID",
		"FOWNER",
		//"MKNOD",
		//"NET_RAW",
		//"SETGID",
		//"SETUID",
		"SETFCAP",
		"SETPCAP",
		"NET_BIND_SERVICE",
		"SYS_CHROOT",
		"KILL",
		"AUDIT_WRITE",
	})
	if cape != nil {
		panic(cape)
	}

	// Drop groups, set to the primary group of the user.
	// TODO: Add user's other groups from /etc/group?
	if gid > 0 {
		err = syscall.Setgroups([]int{}) // drop supplementary groups
		if err != nil {
			panic("setgroups failed")
		}
		err = syscall.Setgid(gid)
		if err != nil {
			panic("setgid failed")
		}
	}
	// Change uid from root down to the actual user
	if uid > 0 {
		err = syscall.Setuid(uid)
		if err != nil {
			panic("setuid failed")
		}
	}

	// Exec their real shell
	// TODO: Add the ability to have arguments for the shell from config
	// TODO: Add the ability to trim environment and/or add to environment (kinda) like sudo does
	args := []string{shell}
	env := os.Environ()
	execErr := syscall.Exec(shell, args, env)
	if execErr != nil {
		panic(execErr)
	}
	return execErr
}
<commit_msg>Bugfix<commit_after>package main

import (
	"errors"
	"fmt"
	"github.com/coreos/go-namespaces/namespace"
	"github.com/docker/libcontainer/security/capabilities"
	"os"
	"path"
	"strconv"
	"strings"
	"syscall"
)

func nsenterdetect() (found bool, err error) {
	// We've inlined the subset of nsenter code we need for amd64 :)
	return true, nil
}

// from /usr/include/linux/sched.h
const (
	CLONE_VFORK = 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
	SIGCHLD     = 0x14       /* Should set SIGCHLD for fork()-like behavior on Linux */
)

func nsenterexec(pid int, uid int, gid int, wd string, shell string) (err error) {
	rootfd, rooterr := os.Open(fmt.Sprintf("/proc/%s/root", strconv.Itoa(pid)))
	if rooterr != nil {
		panic(fmt.Sprintf("Could not open fd to root: %s", rooterr))
	}
	// Find the user's homw directory (which should be bound in as a volume) in the
	// container process namespace, so we can chdir there later.
	cwdfd, cwderr := os.Open(fmt.Sprintf("/proc/%s/root%s", strconv.Itoa(pid), wd))
	if cwderr != nil {
		return errors.New(fmt.Sprintf("Could not open fd to desired cwd: %s", wd))
	}
	if strings.HasPrefix(shell, "/") != true {
		return errors.New(fmt.Sprintf("Shell '%s' does not start with /, need an absolute path", shell))
	}
	shell = path.Clean(shell)
	_, shellerr := os.Open(fmt.Sprintf("/proc/%s/root%s", strconv.Itoa(pid), shell))
	if shellerr != nil {
		return errors.New(fmt.Sprintf("Cannot find ynur shell %s inside your container", shell))
	}

	/* FIXME: Make these an array and loop through them, as this is gross */

	/* --ipc */
	ipcfd, ipcerr := namespace.OpenProcess(pid, namespace.CLONE_NEWIPC)
	if ipcfd == 0 || ipcerr != nil {
		panic("namespace.OpenProcess(pid, namespace.CLONE_NEWIPC)")
	}

	/* --uts */
	utsfd, utserr := namespace.OpenProcess(pid, namespace.CLONE_NEWUTS)
	if utsfd == 0 || utserr != nil {
		panic("namespace.OpenProcess(pid, namespace.CLONE_NEWUTS)")
	}

	/* --net */
	netfd, neterr := namespace.OpenProcess(pid, namespace.CLONE_NEWNET)
	if netfd == 0 || neterr != nil {
		panic("namespace.OpenProcess(pid, namespace.CLONE_NEWNET)")
	}

	/* --pid */
	pidfd, piderr := namespace.OpenProcess(pid, namespace.CLONE_NEWPID)
	if pidfd == 0 || piderr != nil {
		panic("namespace.OpenProcess(pid, namespace.CLONE_NEWPID)")
	}

	/* --mount */
	mountfd, mounterr := namespace.OpenProcess(pid, namespace.CLONE_NEWNS)
	if mountfd == 0 || mounterr != nil {
		panic("namespace.OpenProcess(pid, namespace.CLONE_NEWNS)")
	}

	namespace.Setns(ipcfd, namespace.CLONE_NEWIPC)
	namespace.Setns(utsfd, namespace.CLONE_NEWUTS)
	namespace.Setns(netfd, namespace.CLONE_NEWNET)
	namespace.Setns(pidfd, namespace.CLONE_NEWPID)
	namespace.Setns(mountfd, namespace.CLONE_NEWNS)

	_, _, echrootdir := syscall.Syscall(syscall.SYS_FCHDIR, rootfd.Fd(), 0, 0)
	if echrootdir != 0 {
		panic("chdir to new root failed")
	}
	chrooterr := syscall.Chroot(".")
	if chrooterr != nil {
		panic(fmt.Sprintf("chroot failed: %s", chrooterr))
	}
	// FIXME - this cwds to the cwd of the 'root' process inside the container, we probably want to cwd to user's homedir instead?
	_, _, ecwd := syscall.Syscall(syscall.SYS_FCHDIR, cwdfd.Fd(), 0, 0)
	if ecwd != 0 {
		panic("cwd to working directory failed")
	}

	namespace.Close(ipcfd)
	namespace.Close(utsfd)
	namespace.Close(netfd)
	namespace.Close(pidfd)
	namespace.Close(mountfd)

	/* END FIXME */

	// see go/src/pkg/syscall/exec_unix.go - not sure if this is needed or not (or if we should lock a larger section)
	syscall.ForkLock.Lock()

	/* Stolen from https://github.com/tobert/lnxns/blob/master/src/lnxns/nsfork_linux.go
	   CLONE_VFORK implies that the parent process won't resume until the child calls Exec,
	   which fixes the potential race conditions */

	var flags int = SIGCHLD | CLONE_VFORK
	r1, _, err1 := syscall.RawSyscall(syscall.SYS_CLONE, uintptr(flags), 0, 0)

	syscall.ForkLock.Unlock()

	if err1 == syscall.EINVAL {
		panic("OS returned EINVAL. Make sure your kernel configuration includes all CONFIG_*_NS options.")
	} else if err1 != 0 {
		panic(err1)
	}

	// parent will get the pid, child will be 0
	if int(r1) != 0 {
		// Parent process here
		proc, procerr := os.FindProcess(int(r1))
		if procerr != nil {
			fmt.Fprintf(os.Stderr, "Failed waiting for child: %s\n", strconv.Itoa(int(r1)))
			panic(procerr)
		}
		_, _ = proc.Wait()
		// FIXME: Deal with SIGSTOP on the child in the same way nsenter does?
		/* FIXME: Wait can detect if the child (immediately) fails, but better to do
		that reporting in the child process? Not sure, don't like throwing away err */
		/*if !pstate.Exited() {
			panic("Child has NOT exited")
		}*/
		return nil
	}

	// We're definitely in the child process by the time we get here.

	// Drop capabilities except those in the whitelist, from https://github.com/docker/docker/blob/master/daemon/execdriver/native/template/default_template.go
	cape := capabilities.DropBoundingSet([]string{
		"CHOWN",
		"DAC_OVERRIDE",
		"FSETID",
		"FOWNER",
		//"MKNOD",
		//"NET_RAW",
		//"SETGID",
		//"SETUID",
		"SETFCAP",
		"SETPCAP",
		"NET_BIND_SERVICE",
		"SYS_CHROOT",
		"KILL",
		"AUDIT_WRITE",
	})
	if cape != nil {
		panic(cape)
	}

	// Drop groups, set to the primary group of the user.
	// TODO: Add user's other groups from /etc/group?
	if gid > 0 {
		err = syscall.Setgroups([]int{}) // drop supplementary groups
		if err != nil {
			panic("setgroups failed")
		}
		err = syscall.Setgid(gid)
		if err != nil {
			panic("setgid failed")
		}
	}
	// Change uid from root down to the actual user
	if uid > 0 {
		err = syscall.Setuid(uid)
		if err != nil {
			panic("setuid failed")
		}
	}

	// Exec their real shell
	// TODO: Add the ability to have arguments for the shell from config
	// TODO: Add the ability to trim environment and/or add to environment (kinda) like sudo does
	args := []string{shell}
	env := os.Environ()
	execErr := syscall.Exec(shell, args, env)
	if execErr != nil {
		panic(execErr)
	}
	return execErr
}
<|endoftext|>


<commit_before>/*
Copyright 2021 Gravitational, Inc.

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

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

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
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 main

import (
	"context"
	"fmt"
	"io/fs"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"
	"time"

	"github.com/gravitational/trace"
	log "github.com/sirupsen/logrus"

	"github.com/gravitational/teleport/.cloudbuild/scripts/internal/artifacts"
	"github.com/gravitational/teleport/.cloudbuild/scripts/internal/changes"
	"github.com/gravitational/teleport/.cloudbuild/scripts/internal/etcd"
	"github.com/gravitational/teleport/.cloudbuild/scripts/internal/git"
	"github.com/gravitational/teleport/.cloudbuild/scripts/internal/secrets"
)

const (
	gomodcacheDir = ".gomodcache-ci"
	nonrootUID    = 1000
	nonrootGID    = 1000
)

// main is just a stub that prints out an error message and sets a nonzero exit
// code on failure. All of the work happens in `innerMain()`.
func main() {
	if err := innerMain(); err != nil {
		log.Fatalf("FAILED: %s", err.Error())
	}
}

// innerMain parses the command line, performs the highlevel docs change check
// and creates the marker file if necessary
func innerMain() error {
	args, err := parseCommandLine()
	if err != nil {
		return trace.Wrap(err)
	}

	// If a github deploy key location was supplied...
	var deployKey []byte
	if args.githubKeySrc != "" {
		// fetch the deployment key from the GCB secret manager
		log.Infof("Fetching deploy key from %s", args.githubKeySrc)
		deployKey, err = secrets.Fetch(context.Background(), args.githubKeySrc)
		if err != nil {
			return trace.Wrap(err, "failed fetching deploy key")
		}
	}

	if !args.skipUnshallow {
		unshallowCtx, unshallowCancel := context.WithTimeout(context.Background(), 5*time.Minute)
		defer unshallowCancel()
		err = git.UnshallowRepository(unshallowCtx, args.workspace, deployKey)
		if err != nil {
			return trace.Wrap(err, "unshallow failed")
		}
	}

	moduleCacheDir := filepath.Join(os.TempDir(), gomodcacheDir)
	gomodcache := fmt.Sprintf("GOMODCACHE=%s", moduleCacheDir)

	log.Println("Analyzing code changes")
	ch, err := changes.Analyze(args.workspace, args.targetBranch, args.commitSHA)
	if err != nil {
		return trace.Wrap(err, "Failed analyzing code")
	}

	if !ch.Code {
		log.Println("No code changes detected. Skipping tests.")
		return nil
	}

	// From this point on, whatever happens we want to upload any artifacts
	// produced by the build
	defer func() {
		prefix := fmt.Sprintf("%s/artifacts", args.buildID)
		timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
		defer cancel()
		artifacts.FindAndUpload(timeoutCtx, args.bucket, prefix, args.artifactSearchPatterns)
	}()

	log.Printf("Running root-only integration tests...")
	err = runRootIntegrationTests(args.workspace, gomodcache)
	if err != nil {
		return trace.Wrap(err, "Root-only integration tests failed")
	}
	log.Println("Root-only integration tests passed.")

	if !args.skipChown {
		// We run some build steps as root and others as a non user, and we
		// want the nonroot user to be able to manipulate the artifacts
		// created by root, so we `chown -R` the whole workspace & module
		// cache to allow it.

		log.Printf("Reconfiguring workspace for nonroot user")
		err = chownR(args.workspace, nonrootUID, nonrootGID)
		if err != nil {
			return trace.Wrap(err, "failed reconfiguring workspace")
		}

		log.Printf("Reconfiguring module cache for nonroot user")
		err = chownR(moduleCacheDir, nonrootUID, nonrootGID)
		if err != nil {
			return trace.Wrap(err, "failed reconfiguring module cache")
		}
	}

	// Note that we run `etcd` as nonroot here. The files created by etcd live
	// inside the directory searched by `go list ./...` when generating the list
	// of packages to test, and so making them owned by root produces a heap of
	// diagnostic warnings that would pollute the build log and just confuse
	// people when they are trying to work out why their build failed.
	log.Printf("Starting etcd...")
	timeoutCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	etcdSvc, err := etcd.Start(timeoutCtx, args.workspace)
	if err != nil {
		return trace.Wrap(err, "failed starting etcd")
	}
	defer etcdSvc.Stop()

	log.Printf("Running nonroot integration tests...")
	err = runNonrootIntegrationTests(args.workspace, nonrootUID, nonrootGID, gomodcache)
	if err != nil {
		return trace.Wrap(err, "Nonroot integration tests failed")
	}

	log.Printf("Non-root integration tests passed.")

	return nil
}

func runRootIntegrationTests(workspace string, env ...string) error {
	// Run root integration tests
	cmd := exec.Command("make", "rdpclient", "integration-root")
	cmd.Dir = workspace
	if len(env) > 0 {
		cmd.Env = append(os.Environ(), env...)
	}
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	return cmd.Run()
}

func runNonrootIntegrationTests(workspace string, uid, gid int, env ...string) error {
	cmd := exec.Command("make", "integration")
	cmd.Dir = workspace
	cmd.Env = append(append(os.Environ(), "TELEPORT_ETCD_TEST=yes"), env...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	// make the command run under the supplied nonroot account
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Credential: &syscall.Credential{
			Uid: uint32(uid),
			Gid: uint32(gid),
		},
	}

	return cmd.Run()
}

// chownR changes the owner of each file in the workspace to the supplied
// uid:guid combo.
func chownR(workspace string, uid, gid int) error {
	err := filepath.WalkDir(workspace, func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}

		return os.Chown(path, uid, gid)
	})

	return trace.Wrap(err, "Failed changing file owner")
}
<commit_msg>Set and manage GOCACHE for integration tests (#16523)<commit_after>/*
Copyright 2021 Gravitational, Inc.

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

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

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
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 main

import (
	"context"
	"fmt"
	"io/fs"
	"os"
	"os/exec"
	"path/filepath"
	"syscall"
	"time"

	"github.com/gravitational/trace"
	log "github.com/sirupsen/logrus"

	"github.com/gravitational/teleport/.cloudbuild/scripts/internal/artifacts"
	"github.com/gravitational/teleport/.cloudbuild/scripts/internal/changes"
	"github.com/gravitational/teleport/.cloudbuild/scripts/internal/etcd"
	"github.com/gravitational/teleport/.cloudbuild/scripts/internal/git"
	"github.com/gravitational/teleport/.cloudbuild/scripts/internal/secrets"
)

const (
	goCachesRootName = "gocache"
	nonrootUID       = 1000
	nonrootGID       = 1000
)

// main is just a stub that prints out an error message and sets a nonzero exit
// code on failure. All of the work happens in `innerMain()`.
func main() {
	if err := innerMain(); err != nil {
		log.Fatalf("FAILED: %s", err.Error())
	}
}

// innerMain parses the command line, performs the highlevel docs change check
// and creates the marker file if necessary
func innerMain() error {
	args, err := parseCommandLine()
	if err != nil {
		return trace.Wrap(err)
	}

	// If a github deploy key location was supplied...
	var deployKey []byte
	if args.githubKeySrc != "" {
		// fetch the deployment key from the GCB secret manager
		log.Infof("Fetching deploy key from %s", args.githubKeySrc)
		deployKey, err = secrets.Fetch(context.Background(), args.githubKeySrc)
		if err != nil {
			return trace.Wrap(err, "failed fetching deploy key")
		}
	}

	if !args.skipUnshallow {
		unshallowCtx, unshallowCancel := context.WithTimeout(context.Background(), 5*time.Minute)
		defer unshallowCancel()
		err = git.UnshallowRepository(unshallowCtx, args.workspace, deployKey)
		if err != nil {
			return trace.Wrap(err, "unshallow failed")
		}
	}

	goCacheRoot := filepath.Join(os.TempDir(), goCachesRootName)
	env := map[string]string{
		"GOCACHE":    filepath.Join(goCacheRoot, "go-build"),
		"GOMODCACHE": filepath.Join(goCacheRoot, "pkg"),
	}

	log.Println("Analyzing code changes")
	ch, err := changes.Analyze(args.workspace, args.targetBranch, args.commitSHA)
	if err != nil {
		return trace.Wrap(err, "Failed analyzing code")
	}

	if !ch.Code {
		log.Println("No code changes detected. Skipping tests.")
		return nil
	}

	// From this point on, whatever happens we want to upload any artifacts
	// produced by the build
	defer func() {
		prefix := fmt.Sprintf("%s/artifacts", args.buildID)
		timeoutCtx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
		defer cancel()
		artifacts.FindAndUpload(timeoutCtx, args.bucket, prefix, args.artifactSearchPatterns)
	}()

	log.Printf("Running root-only integration tests...")
	err = runRootIntegrationTests(args.workspace, env)
	if err != nil {
		return trace.Wrap(err, "Root-only integration tests failed")
	}
	log.Println("Root-only integration tests passed.")

	if !args.skipChown {
		// We run some build steps as root and others as a non user, and we
		// want the nonroot user to be able to manipulate the artifacts
		// created by root, so we `chown -R` the whole workspace & module
		// cache to allow it.

		log.Printf("Reconfiguring workspace for nonroot user")
		err = chownR(args.workspace, nonrootUID, nonrootGID)
		if err != nil {
			return trace.Wrap(err, "failed reconfiguring workspace")
		}

		log.Printf("Reconfiguring module cache for nonroot user")
		err = chownR(goCacheRoot, nonrootUID, nonrootGID)
		if err != nil {
			return trace.Wrap(err, "failed reconfiguring module cache")
		}
	}

	// Note that we run `etcd` as nonroot here. The files created by etcd live
	// inside the directory searched by `go list ./...` when generating the list
	// of packages to test, and so making them owned by root produces a heap of
	// diagnostic warnings that would pollute the build log and just confuse
	// people when they are trying to work out why their build failed.
	log.Printf("Starting etcd...")
	timeoutCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	etcdSvc, err := etcd.Start(timeoutCtx, args.workspace)
	if err != nil {
		return trace.Wrap(err, "failed starting etcd")
	}
	defer etcdSvc.Stop()

	log.Printf("Running nonroot integration tests...")
	err = runNonrootIntegrationTests(args.workspace, nonrootUID, nonrootGID, env)
	if err != nil {
		return trace.Wrap(err, "Nonroot integration tests failed")
	}

	log.Printf("Non-root integration tests passed.")

	return nil
}

func runRootIntegrationTests(workspace string, env map[string]string) error {
	// Run root integration tests
	cmd := exec.Command("make", "rdpclient", "integration-root")
	cmd.Dir = workspace
	cmd.Env = os.Environ()
	for k, v := range env {
		cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", k, v))
	}
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	return cmd.Run()
}

func runNonrootIntegrationTests(workspace string, uid, gid int, env map[string]string) error {
	cmd := exec.Command("make", "integration")
	cmd.Dir = workspace
	cmd.Env = append(os.Environ(), "TELEPORT_ETCD_TEST=yes")
	for k, v := range env {
		cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", k, v))
	}
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	// make the command run under the supplied nonroot account
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Credential: &syscall.Credential{
			Uid: uint32(uid),
			Gid: uint32(gid),
		},
	}

	return cmd.Run()
}

// chownR changes the owner of each file in the workspace to the supplied
// uid:guid combo.
func chownR(workspace string, uid, gid int) error {
	err := filepath.WalkDir(workspace, func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}

		return os.Chown(path, uid, gid)
	})

	return trace.Wrap(err, "Failed changing file owner")
}
<|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 upgrade

import (
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"

	"k8s.io/apimachinery/pkg/util/errors"
	kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
	"k8s.io/kubernetes/cmd/kubeadm/app/constants"
	"k8s.io/kubernetes/pkg/util/version"
)

var v190 = version.MustParseSemantic("v1.9.0")

// backupAPIServerCertAndKey backups the old cert and key of kube-apiserver to a specified directory.
func backupAPIServerCertAndKey() error {
	subDir := "expired"
	filesToMove := map[string]string{
		filepath.Join(kubeadmapiext.DefaultCertificatesDir, constants.APIServerCertName): filepath.Join(kubeadmapiext.DefaultCertificatesDir, subDir, constants.APIServerCertName),
		filepath.Join(kubeadmapiext.DefaultCertificatesDir, constants.APIServerKeyName):  filepath.Join(kubeadmapiext.DefaultCertificatesDir, subDir, constants.APIServerKeyName),
	}

	return moveFiles(filesToMove)
}

// moveFiles moves files from one directory to another.
func moveFiles(files map[string]string) error {
	filesToRecover := map[string]string{}
	for from, to := range files {
		if err := os.Rename(from, to); err != nil {
			return rollbackFiles(filesToRecover, err)
		}
		filesToRecover[to] = from
	}
	return nil
}

// rollbackFiles moves the files back to the original directory.
func rollbackFiles(files map[string]string, originalErr error) error {
	errs := []error{originalErr}
	for from, to := range files {
		if err := os.Rename(from, to); err != nil {
			errs = append(errs, err)
		}
	}
	return fmt.Errorf("couldn't move these files: %v. Got errors: %v", files, errors.NewAggregate(errs))
}

// shouldBackupAPIServerCertAndKey check if the new k8s version is at least 1.9.0
// and kube-apiserver will be expired in 60 days.
func shouldBackupAPIServerCertAndKey(newK8sVer *version.Version) (bool, error) {
	if !newK8sVer.LessThan(v190) {
		return false, nil
	}

	apiServerCert := filepath.Join(kubeadmapiext.DefaultCertificatesDir, constants.APIServerCertName)
	data, err := ioutil.ReadFile(apiServerCert)
	if err != nil {
		return false, fmt.Errorf("failed to read kube-apiserver certificate from disk: %v", err)
	}

	block, _ := pem.Decode(data)
	if block == nil {
		return false, fmt.Errorf("expected the kube-apiserver certificate to be PEM encoded")
	}

	certs, err := x509.ParseCertificates(block.Bytes)
	if err != nil {
		return false, fmt.Errorf("unable to parse certificate data: %v", err)
	}
	if len(certs) == 0 {
		return false, fmt.Errorf("no certificate data found")
	}

	if certs[0].NotAfter.Sub(time.Now()) < 60*24*time.Hour {
		return true, nil
	}

	return false, nil
}
<commit_msg>Make expired cert check more clear.<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 upgrade

import (
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"

	"k8s.io/apimachinery/pkg/util/errors"
	kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
	"k8s.io/kubernetes/cmd/kubeadm/app/constants"
	"k8s.io/kubernetes/pkg/util/version"
)

var v190 = version.MustParseSemantic("v1.9.0")

// backupAPIServerCertAndKey backups the old cert and key of kube-apiserver to a specified directory.
func backupAPIServerCertAndKey() error {
	subDir := "expired"
	filesToMove := map[string]string{
		filepath.Join(kubeadmapiext.DefaultCertificatesDir, constants.APIServerCertName): filepath.Join(kubeadmapiext.DefaultCertificatesDir, subDir, constants.APIServerCertName),
		filepath.Join(kubeadmapiext.DefaultCertificatesDir, constants.APIServerKeyName):  filepath.Join(kubeadmapiext.DefaultCertificatesDir, subDir, constants.APIServerKeyName),
	}

	return moveFiles(filesToMove)
}

// moveFiles moves files from one directory to another.
func moveFiles(files map[string]string) error {
	filesToRecover := map[string]string{}
	for from, to := range files {
		if err := os.Rename(from, to); err != nil {
			return rollbackFiles(filesToRecover, err)
		}
		filesToRecover[to] = from
	}
	return nil
}

// rollbackFiles moves the files back to the original directory.
func rollbackFiles(files map[string]string, originalErr error) error {
	errs := []error{originalErr}
	for from, to := range files {
		if err := os.Rename(from, to); err != nil {
			errs = append(errs, err)
		}
	}
	return fmt.Errorf("couldn't move these files: %v. Got errors: %v", files, errors.NewAggregate(errs))
}

// shouldBackupAPIServerCertAndKey check if the new k8s version is at least 1.9.0
// and kube-apiserver will be expired in 60 days.
func shouldBackupAPIServerCertAndKey(newK8sVer *version.Version) (bool, error) {
	if newK8sVer.LessThan(v190) {
		return false, nil
	}

	apiServerCert := filepath.Join(kubeadmapiext.DefaultCertificatesDir, constants.APIServerCertName)
	data, err := ioutil.ReadFile(apiServerCert)
	if err != nil {
		return false, fmt.Errorf("failed to read kube-apiserver certificate from disk: %v", err)
	}

	block, _ := pem.Decode(data)
	if block == nil {
		return false, fmt.Errorf("expected the kube-apiserver certificate to be PEM encoded")
	}

	certs, err := x509.ParseCertificates(block.Bytes)
	if err != nil {
		return false, fmt.Errorf("unable to parse certificate data: %v", err)
	}
	if len(certs) == 0 {
		return false, fmt.Errorf("no certificate data found")
	}

	if time.Now().Sub(certs[0].NotBefore) > 180*24*time.Hour {
		return true, nil
	}

	return false, nil
}
<|endoftext|>


<commit_before>// vagrant implements the packer.PostProcessor interface and adds a
// post-processor that turns artifacts of known builders into Vagrant
// boxes.
package vagrant

import (
	"fmt"
	"github.com/mitchellh/mapstructure"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
	"log"
)

var builtins = map[string]string{
	"mitchellh.amazonebs":  "aws",
	"mitchellh.virtualbox": "virtualbox",
	"mitchellh.vmware":     "vmware",
}

type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	OutputPath string `mapstructure:"output"`
}

type PostProcessor struct {
	config     Config
	premade    map[string]packer.PostProcessor
	rawConfigs []interface{}
}

func (p *PostProcessor) Configure(raws ...interface{}) error {
	// Store the raw configs for usage later
	p.rawConfigs = raws

	md, err := common.DecodeConfig(&p.config, raws...)
	if err != nil {
		return err
	}

	tpl, err := packer.NewConfigTemplate()
	if err != nil {
		return err
	}
	tpl.UserVars = p.config.PackerUserVars

	// Accumulate any errors
	errs := common.CheckUnusedConfig(md)

	ppExtraConfig := make(map[string]interface{})
	if p.config.OutputPath == "" {
		p.config.OutputPath = "packer_{{ .BuildName }}_{{.Provider}}.box"
		ppExtraConfig["output"] = p.config.OutputPath
	}

	//	_, err := template.New("output").Parse(p.config.OutputPath)
	if err := tpl.Validate(p.config.OutputPath); err != nil {
		errs = packer.MultiErrorAppend(
			errs, fmt.Errorf("Error parsing output template: %s", err))
		return errs
	}

	// Store the extra configuration for post-processors
	p.rawConfigs = append(p.rawConfigs, ppExtraConfig)

	// TODO(mitchellh): Properly handle multiple raw configs
	var mapConfig map[string]interface{}
	if err := mapstructure.Decode(raws[0], &mapConfig); err != nil {
		return err
	}

	p.premade = make(map[string]packer.PostProcessor)
	errors := make([]error, 0)
	for k, raw := range mapConfig {
		pp := keyToPostProcessor(k)
		if pp == nil {
			continue
		}

		// Create the proper list of configurations
		ppConfigs := make([]interface{}, 0, len(p.rawConfigs)+1)
		copy(ppConfigs, p.rawConfigs)
		ppConfigs = append(ppConfigs, raw)

		if err := pp.Configure(ppConfigs...); err != nil {
			errors = append(errors, err)
		}

		p.premade[k] = pp
	}

	if len(errors) > 0 {
		return &packer.MultiError{errors}
	}

	return nil
}

func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
	ppName, ok := builtins[artifact.BuilderId()]
	if !ok {
		return nil, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId())
	}

	// Use the premade PostProcessor if we have one. Otherwise, we
	// create it and configure it here.
	pp, ok := p.premade[ppName]
	if !ok {
		log.Printf("Premade post-processor for '%s' not found. Creating.", ppName)
		pp = keyToPostProcessor(ppName)
		if pp == nil {
			return nil, false, fmt.Errorf("Vagrant box post-processor not found: %s", ppName)
		}

		if err := pp.Configure(p.rawConfigs...); err != nil {
			return nil, false, err
		}
	}

	ui.Say(fmt.Sprintf("Creating Vagrant box for '%s' provider", ppName))
	return pp.PostProcess(ui, artifact)
}

func keyToPostProcessor(key string) packer.PostProcessor {
	switch key {
	case "aws":
		return new(AWSBoxPostProcessor)
	case "virtualbox":
		return new(VBoxBoxPostProcessor)
	case "vmware":
		return new(VMwareBoxPostProcessor)
	default:
		return nil
	}
}
<commit_msg>post-processor/vagrant: don't error if unused<commit_after>// vagrant implements the packer.PostProcessor interface and adds a
// post-processor that turns artifacts of known builders into Vagrant
// boxes.
package vagrant

import (
	"fmt"
	"github.com/mitchellh/mapstructure"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
	"log"
)

var builtins = map[string]string{
	"mitchellh.amazonebs":  "aws",
	"mitchellh.virtualbox": "virtualbox",
	"mitchellh.vmware":     "vmware",
}

type Config struct {
	common.PackerConfig `mapstructure:",squash"`

	OutputPath string `mapstructure:"output"`
}

type PostProcessor struct {
	config     Config
	premade    map[string]packer.PostProcessor
	rawConfigs []interface{}
}

func (p *PostProcessor) Configure(raws ...interface{}) error {
	// Store the raw configs for usage later
	p.rawConfigs = raws

	_, err := common.DecodeConfig(&p.config, raws...)
	if err != nil {
		return err
	}

	tpl, err := packer.NewConfigTemplate()
	if err != nil {
		return err
	}
	tpl.UserVars = p.config.PackerUserVars

	// Defaults
	ppExtraConfig := make(map[string]interface{})
	if p.config.OutputPath == "" {
		p.config.OutputPath = "packer_{{ .BuildName }}_{{.Provider}}.box"
		ppExtraConfig["output"] = p.config.OutputPath
	}

	// Accumulate any errors
	errs := new(packer.MultiError)
	if err := tpl.Validate(p.config.OutputPath); err != nil {
		errs = packer.MultiErrorAppend(
			errs, fmt.Errorf("Error parsing output template: %s", err))
	}

	// Store the extra configuration for post-processors
	p.rawConfigs = append(p.rawConfigs, ppExtraConfig)

	// TODO(mitchellh): Properly handle multiple raw configs
	var mapConfig map[string]interface{}
	if err := mapstructure.Decode(raws[0], &mapConfig); err != nil {
		errs = packer.MultiErrorAppend(errs,
			fmt.Errorf("Failed to decode config: %s", err))
		return errs
	}

	p.premade = make(map[string]packer.PostProcessor)
	for k, raw := range mapConfig {
		pp := keyToPostProcessor(k)
		if pp == nil {
			continue
		}

		// Create the proper list of configurations
		ppConfigs := make([]interface{}, 0, len(p.rawConfigs)+1)
		copy(ppConfigs, p.rawConfigs)
		ppConfigs = append(ppConfigs, raw)

		if err := pp.Configure(ppConfigs...); err != nil {
			errs = packer.MultiErrorAppend(errs, err)
		}

		p.premade[k] = pp
	}

	if len(errs.Errors) > 0 {
		return errs
	}

	return nil
}

func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
	ppName, ok := builtins[artifact.BuilderId()]
	if !ok {
		return nil, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId())
	}

	// Use the premade PostProcessor if we have one. Otherwise, we
	// create it and configure it here.
	pp, ok := p.premade[ppName]
	if !ok {
		log.Printf("Premade post-processor for '%s' not found. Creating.", ppName)
		pp = keyToPostProcessor(ppName)
		if pp == nil {
			return nil, false, fmt.Errorf("Vagrant box post-processor not found: %s", ppName)
		}

		if err := pp.Configure(p.rawConfigs...); err != nil {
			return nil, false, err
		}
	}

	ui.Say(fmt.Sprintf("Creating Vagrant box for '%s' provider", ppName))
	return pp.PostProcess(ui, artifact)
}

func keyToPostProcessor(key string) packer.PostProcessor {
	switch key {
	case "aws":
		return new(AWSBoxPostProcessor)
	case "virtualbox":
		return new(VBoxBoxPostProcessor)
	case "vmware":
		return new(VMwareBoxPostProcessor)
	default:
		return nil
	}
}
<|endoftext|>