<commit_before>///bin/true; exec /usr/bin/env go run "$0" "$@"

package main

import (
	_ "bufio"
	"flag"
	"fmt"
	"github.com/omakoto/mlib"
	_ "io"
	"io/ioutil"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var (
	// Patterns to extract PIDs from logs.
	pidPatterns = []*regexp.Regexp{
		// brief
		regexp.MustCompile(`^[A-Z]/.+?\(\s*(\d+)`),
		// process or thread
		regexp.MustCompile(`^[A-Z]\(\s*(\d+)`),
		// threadtime
		regexp.MustCompile(`^\d{2}-\d{2}\s+[\d\:\.]+\s+(\d+)`),
		// time
		regexp.MustCompile(`^\d{2}-\d{2} [\d\:\.]+ [A-Z]\/.*?\(\s*(\d+)`),
		// regexp.MustCompile(`^.*?\(\s*(\d+)`),
		// long
		regexp.MustCompile(`^\[\s*\d{2}-\d{2}\s+[\d\:\.]+\s+(\d+)`),
	}

	// Patterns to extract PIDs for process deaths logs.
	diePatterns = []*regexp.Regexp{
		regexp.MustCompile(`ActivityManager.*?Process .*?\(pid (\d+)\) has died`),
		regexp.MustCompile(`ActivityManager.*?Killing (\d+)`),
		// Any more?
	}

	whiteSpaces = regexp.MustCompile(`\s+`)

	// Flags
	width = flag.Int("w", 40, "formatting width")
	// autoflush = flag.Bool("f", false, "autoflush") // Stdout seems like always flushing

	// Output line format
	outFormat string

	// Process info cache.
	procecces = make(map[int]processInfo)

	cacheExpiration = time.Minute * 10
)

const (
	PRE_INITIALIZED                       = "<pre-initialized>"
	MAX_PRE_INITIALIZED_RETRY             = 5
	MAX_PRE_INITIALIZED_RETRY_INTERVAL_MS = 200
)

type processInfo struct {
	name       string
	expiration time.Time
}

func getProcessNameFromAdbRaw(pid int) string {
	cmd := exec.Command("adb", "shell", fmt.Sprintf("cat /proc/%d/cmdline 2>/dev/null", pid))
	stdout, err := cmd.StdoutPipe()
	mlib.Check(err)

	err = cmd.Start()
	mlib.Check(err)
	defer cmd.Wait()

	cmdline, err := ioutil.ReadAll(stdout)
	mlib.Check(err)

	procname := string(cmdline)
	procname = strings.TrimRight(procname, "\000")
	procname = strings.Replace(procname, "\000", " ", -1)
	return procname
}

// Same as getProcessNameFromAdbRaw, but retries when getting PRE_INITIALIZED
func getProcessNameFromAdb(pid int) string {
	var pname string = "(unknown)"

	mlib.Debug("Getting process name for %d\n", pid)

	for i := 0; i <= MAX_PRE_INITIALIZED_RETRY; i++ {
		rawName := getProcessNameFromAdbRaw(pid)
		if rawName == PRE_INITIALIZED {
			mlib.Debug("%s detected\n", PRE_INITIALIZED)
			time.Sleep(MAX_PRE_INITIALIZED_RETRY_INTERVAL_MS * time.Millisecond)
			continue
		}
		if rawName != "" {
			pname = rawName
		}
		break
	}
	return fmt.Sprintf("%s %d", pname, pid)
}

func getProcessNameWithCache(pid int) string {
	now := time.Now()
	pinfo, ok := procecces[pid]
	if !ok || now.After(pinfo.expiration) {
		name := getProcessNameFromAdb(pid)
		procecces[pid] = processInfo{name: name, expiration: now.Add(cacheExpiration)}
	}
	return pinfo.name
}

// Run for each line
func processLine(line string) {
	var pid = 0
	var processName = ""

	// Find the pid from the line and get the process name
	for _, re := range pidPatterns {
		s := re.FindStringSubmatch(line)
		if s != nil {
			pid, _ = strconv.Atoi(s[1])
			// mlib.Debug("pid=%d\n", pid)
			processName = getProcessNameWithCache(pid)
			break
		}
	}

	// Any process died?
	for _, re := range diePatterns {
		s := re.FindStringSubmatch(line)
		if s != nil {
			diedPid, _ := strconv.Atoi(s[1])
			mlib.Debug("Process %d died\n", diedPid)
			delete(procecces, diedPid)
			break
		}
	}

	fmt.Printf(outFormat, processName, line)
}

func main() {
	flag.Parse()

	outFormat = fmt.Sprintf("[%%-%ds] %%s", *width)

	for line := range mlib.ReadFilesFromArgs() {
		processLine(line)
	}
}
<commit_msg>clean up<commit_after>///bin/true; exec /usr/bin/env go run "$0" "$@"

package main

import (
	"flag"
	"fmt"
	"github.com/omakoto/mlib"
	"io/ioutil"
	"os/exec"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var (
	// Patterns to extract PIDs from logs.
	pidPatterns = []*regexp.Regexp{
		// brief
		regexp.MustCompile(`^[A-Z]/.+?\(\s*(\d+)`),
		// process or thread
		regexp.MustCompile(`^[A-Z]\(\s*(\d+)`),
		// threadtime
		regexp.MustCompile(`^\d{2}-\d{2}\s+[\d\:\.]+\s+(\d+)`),
		// time
		regexp.MustCompile(`^\d{2}-\d{2} [\d\:\.]+ [A-Z]\/.*?\(\s*(\d+)`),
		// regexp.MustCompile(`^.*?\(\s*(\d+)`),
		// long
		regexp.MustCompile(`^\[\s*\d{2}-\d{2}\s+[\d\:\.]+\s+(\d+)`),
	}

	// Patterns to extract PIDs for process deaths logs.
	diePatterns = []*regexp.Regexp{
		regexp.MustCompile(`ActivityManager.*?Process .*?\(pid (\d+)\) has died`),
		regexp.MustCompile(`ActivityManager.*?Killing (\d+)`),
		// Any more?
	}

	whiteSpaces = regexp.MustCompile(`\s+`)

	// Flags
	width = flag.Int("w", 40, "formatting width")
	// autoflush = flag.Bool("f", false, "autoflush") // Stdout seems like always flushing

	// Output line format
	outFormat string

	// Process info cache.
	procecces = make(map[int]processInfo)

	cacheExpiration = time.Minute * 10
)

const (
	PRE_INITIALIZED                       = "<pre-initialized>"
	MAX_PRE_INITIALIZED_RETRY             = 5
	MAX_PRE_INITIALIZED_RETRY_INTERVAL_MS = 200
)

type processInfo struct {
	name       string
	expiration time.Time
}

func getProcessNameFromAdbRaw(pid int) string {
	cmd := exec.Command("adb", "shell", fmt.Sprintf("cat /proc/%d/cmdline 2>/dev/null", pid))
	stdout, err := cmd.StdoutPipe()
	mlib.Check(err)

	err = cmd.Start()
	mlib.Check(err)
	defer cmd.Wait()

	cmdline, err := ioutil.ReadAll(stdout)
	mlib.Check(err)

	procname := string(cmdline)
	procname = strings.TrimRight(procname, "\000")
	procname = strings.Replace(procname, "\000", " ", -1)
	return procname
}

// Same as getProcessNameFromAdbRaw, but retries when getting PRE_INITIALIZED
func getProcessNameFromAdb(pid int) string {
	var pname string = "(unknown)"

	mlib.Debug("Getting process name for %d\n", pid)

	for i := 0; i <= MAX_PRE_INITIALIZED_RETRY; i++ {
		rawName := getProcessNameFromAdbRaw(pid)
		if rawName == PRE_INITIALIZED {
			mlib.Debug("%s detected\n", PRE_INITIALIZED)
			time.Sleep(MAX_PRE_INITIALIZED_RETRY_INTERVAL_MS * time.Millisecond)
			continue
		}
		if rawName != "" {
			pname = rawName
		}
		break
	}
	return fmt.Sprintf("%s %d", pname, pid)
}

func getProcessNameWithCache(pid int) string {
	now := time.Now()
	pinfo, ok := procecces[pid]
	if !ok || now.After(pinfo.expiration) {
		name := getProcessNameFromAdb(pid)
		procecces[pid] = processInfo{name: name, expiration: now.Add(cacheExpiration)}
	}
	return pinfo.name
}

// Run for each line
func processLine(line string) {
	var pid = 0
	var processName = ""

	// Find the pid from the line and get the process name
	for _, re := range pidPatterns {
		s := re.FindStringSubmatch(line)
		if s != nil {
			pid, _ = strconv.Atoi(s[1])
			// mlib.Debug("pid=%d\n", pid)
			processName = getProcessNameWithCache(pid)
			break
		}
	}

	// Any process died?
	for _, re := range diePatterns {
		s := re.FindStringSubmatch(line)
		if s != nil {
			diedPid, _ := strconv.Atoi(s[1])
			mlib.Debug("Process %d died\n", diedPid)
			delete(procecces, diedPid)
			break
		}
	}

	fmt.Printf(outFormat, processName, line)
}

func main() {
	flag.Parse()

	outFormat = fmt.Sprintf("[%%-%ds] %%s", *width)

	for line := range mlib.ReadFilesFromArgs() {
		processLine(line)
	}
}
<|endoftext|>


<commit_before>// Package logging implements a lightweight and configurable logging system.
package logging

import (
	"fmt"
	"runtime"
	"strings"
	"sync"
	"time"
)

// A Level describes the priority of a log message. Higher values are considered to have a higher priority. The default
// levels are negative, except for Fatal (the highest) which is zero.
type Level int

const (
	Undefined Level = 0
	Fatal           = (-iota * 100) - 1 // Unrecoverable error.
	Error                               // Error condition, but possibly recoverable.
	Warn                                // Warning condition, program can still operate.
	Notice                              // Normal but significant condition.
	Info                                // Informational message.
	Debug                               // Debug-level message.
	Trace                               // More verbose debug-level message.
)

var levelStrings = map[Level]string{
	Fatal:  "FATAL",
	Error:  "ERROR",
	Warn:   "WARN",
	Notice: "NOTICE",
	Info:   "INFO",
	Debug:  "DEBUG",
	Trace:  "TRACE",
}
var reverseLevelStrings = make(map[string]Level)

func init() {
	for level, key := range levelStrings {
		reverseLevelStrings[key] = level
	}
}

// Returns a string representation of the Level, in uppercase.
func (l Level) String() string {
	if s := levelStrings[l]; s != "" {
		return s
	}
	return fmt.Sprintf("LEVEL:%d", l)
}

// A Message contains information about a logging event.
type Message struct {
	// The priority of the message.
	Level Level
	// The string part of the message, as passed by the user when the log statement was called.
	Msg string
	// The time the message was logged.
	Time time.Time
	// The name of the file where the logging statement originated.
	File string
	// The line number in the file where the logging statement originated.
	Line int
	// The Logger which logged the message.
	Logger *Logger
}

// An Outputter is responsible for logging a message to some destination.
type Outputter interface {
	Output(msg *Message)
}

type OutputterFunc func(msg *Message)

// Implements Outputter.
func (o OutputterFunc) Output(msg *Message) {
	o(msg)
}

// A Formatter is responsible for converting a Message into a string representation. See BasicFormatter.
type Formatter interface {
	Format(msg *Message) string
}

// Loggers are the point-of-entry for logging events.
type Logger struct {
	// The full name of the logger.
	Name string
	// The minimum level a log message can have to be logged.
	Threshold Level
	// If true, log messages will not be propagated to the parent Logger's outputs. If false, log messages will be sent up
	// the hierarchy until a Logger is found with the NoPropagate property set to true.
	NoPropagate bool
	parent      *Logger
	children    map[string]*Logger
	outputs     []Outputter
}

func newLogger(name string, parent *Logger) *Logger {
	return &Logger{
		Name:     name,
		parent:   parent,
		children: make(map[string]*Logger),
	}
}

func (l *Logger) log(level Level, msgstr string, stack int) {
	msg := &Message{
		Level:  level,
		Msg:    msgstr,
		Time:   time.Now(),
		Logger: l,
	}
	_, msg.File, msg.Line, _ = runtime.Caller(stack)
	l.doLog(msg)
}

func (l *Logger) doLog(msg *Message) {
	for _, output := range l.outputs {
		output.Output(msg)
	}
	if !l.NoPropagate && l.parent != nil {
		l.parent.doLog(msg)
	}
}

// Adds an Outputter to the Logger. Subsequent Messages that exceed the logger's Threshold will be sent to the
// Outputter.
func (l *Logger) AddOutput(o Outputter) {
	l.outputs = append(l.outputs, o)
}

// Recursively makes child loggers with Undefined thresholds inherit their threshold from their parents.
func (l *Logger) configure() {
	for _, child := range l.children {
		if child.Threshold == Undefined {
			child.Threshold = l.Threshold
		}
		child.configure()
	}
}

/* Global logger hierarchy */

var lock sync.Mutex
var configured bool

// The root Logger. This is the ancestor of all loggers.
var Root = newLogger("root", nil)

// Returns a Logger instance for the given logger name. A logger name consists of dot-separated parts, and is the basis
// of the logger hierarchy. When loggers are created (implicitly by Get) they inherit their Threshold from
func Get(fullname string) *Logger {
	lock.Lock()
	defer lock.Unlock()
	// Go down the hierarchy, creating loggers where needed
	parts := strings.Split(fullname, ".")
	logger := Root
	for _, part := range parts {
		child := logger.children[part]
		if child == nil {
			child = newLogger(fullname, logger)
			if configured {
				child.Threshold = logger.Threshold
			}
			logger.children[part] = child
		}
		logger = child
	}
	return logger
}

/* Logging methods */

func (l *Logger) Log(level Level, msgstr string) {
	if l.Threshold > level {
		return
	}
	l.log(level, msgstr, 2)
}
func (l *Logger) Logf(level Level, format string, args ...interface{}) {
	if l.Threshold > level {
		return
	}
	l.log(level, fmt.Sprintf(format, args...), 2)
}

func (l *Logger) Fatal(msg string) {
	if l.Threshold > Fatal {
		return
	}
	l.log(Fatal, msg, 2)
}
func (l *Logger) Fatalf(format string, args ...interface{}) {
	if l.Threshold > Fatal {
		return
	}
	l.log(Fatal, fmt.Sprintf(format, args...), 2)
}
func (l *Logger) Error(msg string) {
	if l.Threshold > Error {
		return
	}
	l.log(Error, msg, 2)
}
func (l *Logger) Errorf(format string, args ...interface{}) {
	if l.Threshold > Error {
		return
	}
	l.log(Error, fmt.Sprintf(format, args...), 2)
}
func (l *Logger) Warn(msg string) {
	if l.Threshold > Warn {
		return
	}
	l.log(Warn, msg, 2)
}
func (l *Logger) Warnf(format string, args ...interface{}) {
	if l.Threshold > Warn {
		return
	}
	l.log(Warn, fmt.Sprintf(format, args...), 2)
}
func (l *Logger) Notice(msg string) {
	if l.Threshold > Notice {
		return
	}
	l.log(Notice, msg, 2)
}
func (l *Logger) Noticef(format string, args ...interface{}) {
	if l.Threshold > Notice {
		return
	}
	l.log(Notice, fmt.Sprintf(format, args...), 2)
}
func (l *Logger) Info(msg string) {
	if l.Threshold > Info {
		return
	}
	l.log(Info, msg, 2)
}
func (l *Logger) Infof(format string, args ...interface{}) {
	if l.Threshold > Info {
		return
	}
	l.log(Info, fmt.Sprintf(format, args...), 2)
}
func (l *Logger) Debug(msg string) {
	if l.Threshold > Debug {
		return
	}
	l.log(Debug, msg, 2)
}
func (l *Logger) Debugf(format string, args ...interface{}) {
	if l.Threshold > Debug {
		return
	}
	l.log(Debug, fmt.Sprintf(format, args...), 2)
}
func (l *Logger) Trace(msg string) {
	if l.Threshold > Trace {
		return
	}
	l.log(Trace, msg, 2)
}
func (l *Logger) Tracef(format string, args ...interface{}) {
	if l.Threshold > Trace {
		return
	}
	l.log(Trace, fmt.Sprintf(format, args...), 2)
}
<commit_msg>Made logging functions take arguments in a fmt.Println style<commit_after>// Package logging implements a lightweight and configurable logging system.
package logging

import (
	"fmt"
	"runtime"
	"strings"
	"sync"
	"time"
)

// A Level describes the priority of a log message. Higher values are considered to have a higher priority. The default
// levels are negative, except for Fatal (the highest) which is zero.
type Level int

const (
	Undefined Level = 0
	Fatal           = (-iota * 100) - 1 // Unrecoverable error.
	Error                               // Error condition, but possibly recoverable.
	Warn                                // Warning condition, program can still operate.
	Notice                              // Normal but significant condition.
	Info                                // Informational message.
	Debug                               // Debug-level message.
	Trace                               // More verbose debug-level message.
)

var levelStrings = map[Level]string{
	Fatal:  "FATAL",
	Error:  "ERROR",
	Warn:   "WARN",
	Notice: "NOTICE",
	Info:   "INFO",
	Debug:  "DEBUG",
	Trace:  "TRACE",
}
var reverseLevelStrings = make(map[string]Level)

func init() {
	for level, key := range levelStrings {
		reverseLevelStrings[key] = level
	}
}

// Returns a string representation of the Level, in uppercase.
func (l Level) String() string {
	if s := levelStrings[l]; s != "" {
		return s
	}
	return fmt.Sprintf("LEVEL:%d", l)
}

// A Message contains information about a logging event.
type Message struct {
	// The priority of the message.
	Level Level
	// The string part of the message, as passed by the user when the log statement was called.
	Msg string
	// The time the message was logged.
	Time time.Time
	// The name of the file where the logging statement originated.
	File string
	// The line number in the file where the logging statement originated.
	Line int
	// The Logger which logged the message.
	Logger *Logger
}

// An Outputter is responsible for logging a message to some destination.
type Outputter interface {
	Output(msg *Message)
}

type OutputterFunc func(msg *Message)

// Implements Outputter.
func (o OutputterFunc) Output(msg *Message) {
	o(msg)
}

// A Formatter is responsible for converting a Message into a string representation. See BasicFormatter.
type Formatter interface {
	Format(msg *Message) string
}

// Loggers are the point-of-entry for logging events.
type Logger struct {
	// The full name of the logger.
	Name string
	// The minimum level a log message can have to be logged.
	Threshold Level
	// If true, log messages will not be propagated to the parent Logger's outputs. If false, log messages will be sent up
	// the hierarchy until a Logger is found with the NoPropagate property set to true.
	NoPropagate bool
	parent      *Logger
	children    map[string]*Logger
	outputs     []Outputter
}

func newLogger(name string, parent *Logger) *Logger {
	return &Logger{
		Name:     name,
		parent:   parent,
		children: make(map[string]*Logger),
	}
}

func (l *Logger) log(level Level, msgstr string, stack int) {
	msg := &Message{
		Level:  level,
		Msg:    msgstr,
		Time:   time.Now(),
		Logger: l,
	}
	_, msg.File, msg.Line, _ = runtime.Caller(stack)
	l.doLog(msg)
}

func (l *Logger) doLog(msg *Message) {
	for _, output := range l.outputs {
		output.Output(msg)
	}
	if !l.NoPropagate && l.parent != nil {
		l.parent.doLog(msg)
	}
}

// Adds an Outputter to the Logger. Subsequent Messages that exceed the logger's Threshold will be sent to the
// Outputter.
func (l *Logger) AddOutput(o Outputter) {
	l.outputs = append(l.outputs, o)
}

// Recursively makes child loggers with Undefined thresholds inherit their threshold from their parents.
func (l *Logger) configure() {
	for _, child := range l.children {
		if child.Threshold == Undefined {
			child.Threshold = l.Threshold
		}
		child.configure()
	}
}

/* Global logger hierarchy */

var lock sync.Mutex
var configured bool

// The root Logger. This is the ancestor of all loggers.
var Root = newLogger("root", nil)

// Returns a Logger instance for the given logger name. A logger name consists of dot-separated parts, and is the basis
// of the logger hierarchy. When loggers are created (implicitly by Get) they inherit their Threshold from
func Get(fullname string) *Logger {
	lock.Lock()
	defer lock.Unlock()
	// Go down the hierarchy, creating loggers where needed
	parts := strings.Split(fullname, ".")
	logger := Root
	for _, part := range parts {
		child := logger.children[part]
		if child == nil {
			child = newLogger(fullname, logger)
			if configured {
				child.Threshold = logger.Threshold
			}
			logger.children[part] = child
		}
		logger = child
	}
	return logger
}

/* Logging methods */

func (l *Logger) Log(level Level, msgparts ...interface{}) {
	if l.Threshold > level {
		return
	}
	l.log(level, fmt.Sprint(msgparts...), 2)
}
func (l *Logger) Logf(level Level, format string, args ...interface{}) {
	if l.Threshold > level {
		return
	}
	l.log(level, fmt.Sprintf(format, args...), 2)
}

func (l *Logger) Fatal(msgparts ...interface{}) {
	if l.Threshold > Fatal {
		return
	}
	l.log(Fatal, fmt.Sprint(msgparts...), 2)
}
func (l *Logger) Fatalf(format string, args ...interface{}) {
	if l.Threshold > Fatal {
		return
	}
	l.log(Fatal, fmt.Sprintf(format, args...), 2)
}
func (l *Logger) Error(msgparts ...interface{}) {
	if l.Threshold > Error {
		return
	}
	l.log(Error, fmt.Sprint(msgparts...), 2)
}
func (l *Logger) Errorf(format string, args ...interface{}) {
	if l.Threshold > Error {
		return
	}
	l.log(Error, fmt.Sprintf(format, args...), 2)
}
func (l *Logger) Warn(msgparts ...interface{}) {
	if l.Threshold > Warn {
		return
	}
	l.log(Warn, fmt.Sprint(msgparts...), 2)
}
func (l *Logger) Warnf(format string, args ...interface{}) {
	if l.Threshold > Warn {
		return
	}
	l.log(Warn, fmt.Sprintf(format, args...), 2)
}
func (l *Logger) Notice(msgparts ...interface{}) {
	if l.Threshold > Notice {
		return
	}
	l.log(Notice, fmt.Sprint(msgparts...), 2)
}
func (l *Logger) Noticef(format string, args ...interface{}) {
	if l.Threshold > Notice {
		return
	}
	l.log(Notice, fmt.Sprintf(format, args...), 2)
}
func (l *Logger) Info(msgparts ...interface{}) {
	if l.Threshold > Info {
		return
	}
	l.log(Info, fmt.Sprint(msgparts...), 2)
}
func (l *Logger) Infof(format string, args ...interface{}) {
	if l.Threshold > Info {
		return
	}
	l.log(Info, fmt.Sprintf(format, args...), 2)
}
func (l *Logger) Debug(msgparts ...interface{}) {
	if l.Threshold > Debug {
		return
	}
	l.log(Debug, fmt.Sprint(msgparts...), 2)
}
func (l *Logger) Debugf(format string, args ...interface{}) {
	if l.Threshold > Debug {
		return
	}
	l.log(Debug, fmt.Sprintf(format, args...), 2)
}
func (l *Logger) Trace(msgparts ...interface{}) {
	if l.Threshold > Trace {
		return
	}
	l.log(Trace, fmt.Sprint(msgparts...), 2)
}
func (l *Logger) Tracef(format string, args ...interface{}) {
	if l.Threshold > Trace {
		return
	}
	l.log(Trace, fmt.Sprintf(format, args...), 2)
}
<|endoftext|>


<commit_before>// go-logging - Logging library for Go
//
// Copyright (c) 2014 Dmitry Prazdnichnov <dp@bambucha.org>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package logging

var loggers = make(map[string]*Logger)

var root = GetLogger("root")

func GetLogger(name string) *Logger {
	if logger, ok := loggers[name]; ok {
		return logger
	}

	logger := &Logger{
		name:    name,
		level:   DEBUG,
		format:  "[{date}][{level}][{file}:{line}] {message}\n",
		datefmt: "2006-01-02 15:04:05", // http://golang.org/pkg/time/#pkg-constants
	}

	loggers[name] = logger
	return logger
}

func GetName() string {
	return root.GetName()
}

func SetLevel(level int) {
	root.SetLevel(level)
}

func GetLevel() int {
	return root.GetLevel()
}

func SetFormat(format string) {
	root.SetFormat(format)
}

func GetFormat() string {
	return root.GetFormat()
}

func SetDateFormat(datefmt string) {
	root.SetDateFormat(datefmt)
}

func GetDateFormat() string {
	return root.GetDateFormat()
}

func Print(format string, args ...interface{}) {
	root.Print(format, args...)
}

func Trace(format string, args ...interface{}) {
	root.Trace(format, args...)
}

func Debug(format string, args ...interface{}) {
	root.Debug(format, args...)
}

func Informational(format string, args ...interface{}) {
	root.Informational(format, args...)
}

func Info(format string, args ...interface{}) {
	root.Info(format, args...)
}

func Notice(format string, args ...interface{}) {
	root.Notice(format, args...)
}

func Warning(format string, args ...interface{}) {
	root.Warning(format, args...)
}

func Warn(format string, args ...interface{}) {
	root.Warn(format, args...)
}

func Error(format string, args ...interface{}) {
	root.Error(format, args...)
}

func Err(format string, args ...interface{}) {
	root.Err(format, args...)
}

// Critical is equivalent to Printf() followed by a call to os.Exit(1).
func Critical(format string, args ...interface{}) {
	root.Critical(format, args...)
}

// Crit is equivalent to Printf() followed by a call to os.Exit(1).
func Crit(format string, args ...interface{}) {
	root.Crit(format, args...)
}

// Fatal is equivalent to Printf() followed by a call to os.Exit(1).
func Fatal(format string, args ...interface{}) {
	root.Fatal(format, args...)
}

// Alert is equivalent to Printf() followed by a call to os.Exit(1).
func Alert(format string, args ...interface{}) {
	root.Alert(format, args...)
}

// Emergency is equivalent to Printf() followed by a call to panic().
func Emergency(format string, args ...interface{}) {
	root.Emergency(format, args...)
}

// Emerg is equivalent to Printf() followed by a call to panic().
func Emerg(format string, args ...interface{}) {
	root.Emerg(format, args...)
}

// Panic is equivalent to Printf() followed by a call to panic().
func Panic(format string, args ...interface{}) {
	root.Panic(format, args...)
}
<commit_msg>Change default log level<commit_after>// go-logging - Logging library for Go
//
// Copyright (c) 2014 Dmitry Prazdnichnov <dp@bambucha.org>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package logging

var loggers = make(map[string]*Logger)

var root = GetLogger("root")

func GetLogger(name string) *Logger {
	if logger, ok := loggers[name]; ok {
		return logger
	}

	logger := &Logger{
		name:    name,
		level:   NOTSET,
		format:  "[{date}][{level}][{file}:{line}] {message}\n",
		datefmt: "2006-01-02 15:04:05", // http://golang.org/pkg/time/#pkg-constants
	}

	loggers[name] = logger
	return logger
}

func GetName() string {
	return root.GetName()
}

func SetLevel(level int) {
	root.SetLevel(level)
}

func GetLevel() int {
	return root.GetLevel()
}

func SetFormat(format string) {
	root.SetFormat(format)
}

func GetFormat() string {
	return root.GetFormat()
}

func SetDateFormat(datefmt string) {
	root.SetDateFormat(datefmt)
}

func GetDateFormat() string {
	return root.GetDateFormat()
}

func Print(format string, args ...interface{}) {
	root.Print(format, args...)
}

func Trace(format string, args ...interface{}) {
	root.Trace(format, args...)
}

func Debug(format string, args ...interface{}) {
	root.Debug(format, args...)
}

func Informational(format string, args ...interface{}) {
	root.Informational(format, args...)
}

func Info(format string, args ...interface{}) {
	root.Info(format, args...)
}

func Notice(format string, args ...interface{}) {
	root.Notice(format, args...)
}

func Warning(format string, args ...interface{}) {
	root.Warning(format, args...)
}

func Warn(format string, args ...interface{}) {
	root.Warn(format, args...)
}

func Error(format string, args ...interface{}) {
	root.Error(format, args...)
}

func Err(format string, args ...interface{}) {
	root.Err(format, args...)
}

// Critical is equivalent to Printf() followed by a call to os.Exit(1).
func Critical(format string, args ...interface{}) {
	root.Critical(format, args...)
}

// Crit is equivalent to Printf() followed by a call to os.Exit(1).
func Crit(format string, args ...interface{}) {
	root.Crit(format, args...)
}

// Fatal is equivalent to Printf() followed by a call to os.Exit(1).
func Fatal(format string, args ...interface{}) {
	root.Fatal(format, args...)
}

// Alert is equivalent to Printf() followed by a call to os.Exit(1).
func Alert(format string, args ...interface{}) {
	root.Alert(format, args...)
}

// Emergency is equivalent to Printf() followed by a call to panic().
func Emergency(format string, args ...interface{}) {
	root.Emergency(format, args...)
}

// Emerg is equivalent to Printf() followed by a call to panic().
func Emerg(format string, args ...interface{}) {
	root.Emerg(format, args...)
}

// Panic is equivalent to Printf() followed by a call to panic().
func Panic(format string, args ...interface{}) {
	root.Panic(format, args...)
}
<|endoftext|>


<commit_before>package nsf

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"testing"

	"github.com/mjibson/mog/codec/nsf/cpu6502"
)

func loadNES(fname string) *NSF {
	var err error
	n := New()
	n.b, err = ioutil.ReadFile("roms/nestest/nestest.nes")
	if err != nil {
		panic(err)
	}
	if string(n.b[:4]) != "NES\u001a" {
		panic("not a NES file")
	}
	prg := n.b[4]
	//chr := n.b[5]
	n.Data = n.b[16:]
	mapper := n.b[6]>>4 | n.b[7]&0xF0
	if mapper != 0 {
		panic("unknown mapper")
	}
Loop:
	for a := 0; true; {
		for i := 0; i < int(prg); i++ {
			a += 0x4000
			if a > 0xffff {
				break Loop
			}
			copy(n.Ram.M[a:a+0x4000], n.Data[i*0x4000:(i+1)*0x4000])
		}
	}
	n.Cpu.Reset()
	if n.Cpu.PC == 0 {
		panic("PC == 0")
	}
	return n
}

func TestNesTest(t *testing.T) {
	f, _ := os.Open("roms/nestest/nestest.log")
	s := bufio.NewScanner(f)
	n := loadNES("roms/nestest/nestest.nes")
	n.Cpu.L = make([]cpu6502.Log, 10)
	i := 0
	n.Cpu.PC = 0xC000
	defer func() {
		t.Log("instructions", i)
		t.Log(strings.Fields(s.Text()))
		t.Log(n.Cpu.StringLog())
		t.Log(n.Cpu)
	}()
	for {
		i++
		if !s.Scan() {
			if i == 8992 {
				return
			}
			t.Fatal("expected scan")
		} else if s.Err() != nil {
			t.Fatal(s.Err())
		}
		l := s.Text()
		if l[0:4] != fmt.Sprintf("%04X", n.Cpu.PC) {
			t.Fatal("bad pc")
		}
		if l[6:8] != fmt.Sprintf("%02X", n.Read(n.Cpu.PC)) {
			t.Fatal("bad i")
		}
		if l[50:52] != fmt.Sprintf("%02X", n.Cpu.A) {
			t.Fatal("bad a")
		}
		if l[55:57] != fmt.Sprintf("%02X", n.Cpu.X) {
			t.Fatal("bad x")
		}
		if l[60:62] != fmt.Sprintf("%02X", n.Cpu.Y) {
			t.Fatal("bad y")
		}
		if l[65:67] != fmt.Sprintf("%02X", n.Cpu.P) {
			t.Fatal("bad p")
		}
		if l[71:73] != fmt.Sprintf("%02X", n.Cpu.S) {
			t.Fatal("bad s")
		}
		n.Cpu.Step()
	}
}
<commit_msg>PRG section starts at 0x8000, not 0x4000<commit_after>package nsf

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
	"testing"

	"github.com/mjibson/mog/codec/nsf/cpu6502"
)

func loadNES(fname string) *NSF {
	var err error
	n := New()
	n.b, err = ioutil.ReadFile("roms/nestest/nestest.nes")
	if err != nil {
		panic(err)
	}
	if string(n.b[:4]) != "NES\u001a" {
		panic("not a NES file")
	}
	prg := n.b[4]
	//chr := n.b[5]
	n.Data = n.b[16:]
	mapper := n.b[6]>>4 | n.b[7]&0xF0
	if mapper != 0 {
		panic("unknown mapper")
	}
Loop:
	for a := 0x4000; true; {
		for i := 0; i < int(prg); i++ {
			a += 0x4000
			if a > 0xffff {
				break Loop
			}
			copy(n.Ram.M[a:a+0x4000], n.Data[i*0x4000:(i+1)*0x4000])
		}
	}
	n.Cpu.Reset()
	if n.Cpu.PC == 0 {
		panic("PC == 0")
	}
	return n
}

func TestNesTest(t *testing.T) {
	f, _ := os.Open("roms/nestest/nestest.log")
	s := bufio.NewScanner(f)
	n := loadNES("roms/nestest/nestest.nes")
	n.Cpu.L = make([]cpu6502.Log, 10)
	i := 0
	n.Cpu.PC = 0xC000
	defer func() {
		t.Log("instructions", i)
		t.Log(strings.Fields(s.Text()))
		t.Log(n.Cpu.StringLog())
		t.Log(n.Cpu)
	}()
	for {
		i++
		if !s.Scan() {
			if i == 8992 {
				return
			}
			t.Fatal("expected scan")
		} else if s.Err() != nil {
			t.Fatal(s.Err())
		}
		l := s.Text()
		if l[0:4] != fmt.Sprintf("%04X", n.Cpu.PC) {
			t.Fatal("bad pc")
		}
		if l[6:8] != fmt.Sprintf("%02X", n.Read(n.Cpu.PC)) {
			t.Fatal("bad i")
		}
		if l[50:52] != fmt.Sprintf("%02X", n.Cpu.A) {
			t.Fatal("bad a")
		}
		if l[55:57] != fmt.Sprintf("%02X", n.Cpu.X) {
			t.Fatal("bad x")
		}
		if l[60:62] != fmt.Sprintf("%02X", n.Cpu.Y) {
			t.Fatal("bad y")
		}
		if l[65:67] != fmt.Sprintf("%02X", n.Cpu.P) {
			t.Fatal("bad p")
		}
		if l[71:73] != fmt.Sprintf("%02X", n.Cpu.S) {
			t.Fatal("bad s")
		}
		n.Cpu.Step()
	}
}
<|endoftext|>


<commit_before>package main

import (
        "errors"
        "fmt"

        "encoding/json"
        "github.com/hyperledger/fabric/core/chaincode/shim"
)

// CrowdFundChaincode implementation
type CrowdFundChaincode struct {
}
type studentInfo struct {
        studentRollNo     string  `json:"studentrollno"`
        studentName        string   `json:"studentname"`
        studentBadge       []string  `json:"studentbadge"`
        studentMarks       []string   `json:"studentmarks"`
        studentSem         []string   `json:"studentsem"`
        issuedBy        []string   `json:"issuedby"`

}
type BadgeInfo struct {

        badgeName       []string   `json:"rollno"`
        badgeUrl        []string `json:"name"`
        badgeIssuedBy   []string   `json:"sem"`
        badgeIssuedTo   []string `json:"marks"`
        //time
}

type Issuer struct {

        issuerInfo      []string   `json:"rollno"`
        issuerName        string `json:"name"`
       // time            string   `json:"sem"`

}
//
// Init creates the state variable with name "account" and stores the value
// from the incoming request into this variable. We now have a key/value pair
// for account --> accountValue.
//
func (t *CrowdFundChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {

        var err error

        if len(args) != 2 {
                return nil, errors.New("Incorrect number of arguments. Expecting 2.")
        }

     if err!=nil {
                        return nil, err
                }
         record := studentInfo{}

       record.studentRollNo ="MT2916"
       record.studentName ="aarushi"

        //record.studentRollNo=append(record.studentRollNo,"MT2016001");
        //record.studentName=append(record.studentName,"Aarushi");
        record.studentBadge=append(record.studentBadge,"Mtech");
        record.studentMarks=append(record.studentMarks,"78");
        record.studentSem=append(record.studentMarks,"1st");
        record.issuedBy=append(record.issuedBy,"RC Sir");

        newrecordByte, err := json.Marshal(record);
        if err!=nil {

            return nil, err
        }
                err=stub.PutState("default",newrecordByte);
         if err!=nil {
                        return nil, err
                }

        return nil, nil
}

func (t *CrowdFundChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {

var account string

fmt.Printf(" the function which has been recieved as input is : %s" , function)
fmt.Printf(" the function which has been recieved as input is : %s" , args[0])
fmt.Printf(" the function which has been recieved as input is : %s" , args[1])
fmt.Printf(" the function which has been recieved as input is : %s" , args[2])
fmt.Printf(" the function which has been recieved as input is : %s" , args[3])

        var err error

        if len(args) != 6 {
                return nil, errors.New("Incorrect number of arguments. Expecting 6.")
        }
          account = args[0]
          fmt.Printf(" key is : %s" , account)

         recordByte, err := stub.GetState(account);
        fmt.Println(recordByte);
        if err != nil {

            return nil, err
        }
        record := studentInfo{}
        if recordByte != nil {
        errrecordmarshal := json.Unmarshal(recordByte,&record);
        fmt.Printf(" the unmarshall function output is : %s" , errrecordmarshal)

        if errrecordmarshal != nil {
            return nil, errrecordmarshal
        }

        }

        record.studentRollNo=args[0];
        record.studentName=args[1];
        record.studentBadge=append(record.studentBadge,args[2]);
        record.studentMarks=append(record.studentMarks,args[3]);
        record.studentSem=append(record.studentMarks,args[4]);
        record.issuedBy=append(record.issuedBy,args[5]);

        /*record.Rollno = append(record.Rollno,args[0]);
        record.Name = append(record.Name,args[1]);
        record.Sem=append(record.Sem,args[2]);
        record.Marks=append(record.Marks,args[3]);
*/
        fmt.Printf(" record structure rollno is : %s" ,  record.studentRollNo)
        fmt.Printf(" record structure name is   : %s" ,  record.studentName)
        fmt.Printf(" record structure badge is : %s" ,   record.studentBadge)
        fmt.Printf(" record structure marks is : : %s" , record.studentMarks)
        fmt.Printf(" record structure sem is : %s" ,     record.studentSem)
        fmt.Printf(" record structure issuedby is : %s" ,record.issuedBy)

        newrecordByte, err := json.Marshal(record);

        stringNewRecordByte := string(newrecordByte)

        fmt.Printf(" the marshall function output is : %s" , stringNewRecordByte)

        if err!=nil {

            return nil, err
        }
        err =stub.PutState(account,newrecordByte);
        if err != nil {

            return nil, err;
        }
        return nil, nil
}

func (t *CrowdFundChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
  if function != "query" {
                return nil, errors.New("Invalid query function name. Expecting \"query\".")
        }

       var err error

         if len(args) != 1 {
                return nil, errors.New("Incorrect number of arguments. Expecting name of the state variable to query.")
        }

     var   account = args[0]

        accountValueBytes ,err := stub.GetState(account)
        if err != nil {

                 return nil, err
        }

        return accountValueBytes, nil
}

func main() {
        err := shim.Start(new(CrowdFundChaincode))

        if err != nil {
                fmt.Printf("Error starting CrowdFundChaincode: %s", err)
        }
}
<commit_msg>Update chaincode_start.go<commit_after>package main

import (
        "errors"
        "fmt"

        "encoding/json"
        "github.com/hyperledger/fabric/core/chaincode/shim"
)

// CrowdFundChaincode implementation
type CrowdFundChaincode struct {
}
type studentInfo struct {
        studentRollNo     string  `json:"studentrollno"`
        studentName        string   `json:"studentname"`
        studentBadge       []string  `json:"studentbadge"`
        studentMarks       []string   `json:"studentmarks"`
        studentSem         []string   `json:"studentsem"`
        issuedBy        []string   `json:"issuedby"`

}
type BadgeInfo struct {

        badgeName       []string   `json:"rollno"`
        badgeUrl        []string `json:"name"`
        badgeIssuedBy   []string   `json:"sem"`
        badgeIssuedTo   []string `json:"marks"`
        //time
}

type Issuer struct {

        issuerInfo      []string   `json:"rollno"`
        issuerName        string `json:"name"`
       // time            string   `json:"sem"`

}
//
// Init creates the state variable with name "account" and stores the value
// from the incoming request into this variable. We now have a key/value pair
// for account --> accountValue.
//
func (t *CrowdFundChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {

        var err error

        if len(args) != 2 {
                return nil, errors.New("Incorrect number of arguments. Expecting 2.")
        }

     if err!=nil {
                        return nil, err
                }
         record := studentInfo{}

       record.studentRollNo ="MT2916"
       record.studentName ="aarushi"

        //record.studentRollNo=append(record.studentRollNo,"MT2016001");
        //record.studentName=append(record.studentName,"Aarushi");
        record.studentBadge=append(record.studentBadge,"Mtech");
        record.studentMarks=append(record.studentMarks,"78");
        record.studentSem=append(record.studentMarks,"1st");
        record.issuedBy=append(record.issuedBy,"RC Sir");

        newrecordByte, err := json.Marshal(record);
        if err!=nil {

            return nil, err
        }
                err=stub.PutState("default",newrecordByte);
         if err!=nil {
                        return nil, err
                }

        return nil, nil
}

func (t *CrowdFundChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
    if function != "invoke" {
                return nil, errors.New("Invalid query function name. Expecting \"query\".")
        }

var account string

fmt.Printf(" the function which has been recieved as input is : %s" , function)
fmt.Printf(" the function which has been recieved as input is : %s" , args[0])
fmt.Printf(" the function which has been recieved as input is : %s" , args[1])
fmt.Printf(" the function which has been recieved as input is : %s" , args[2])
fmt.Printf(" the function which has been recieved as input is : %s" , args[3])

        var err error

        if len(args) != 6 {
                return nil, errors.New("Incorrect number of arguments. Expecting 6.")
        }
          account = args[0]
          fmt.Printf(" key is : %s" , account)

         recordByte, err := stub.GetState(account);
        fmt.Println(recordByte);
        if err != nil {

            return nil, err
        }
        record := studentInfo{}
        if recordByte != nil {
        errrecordmarshal := json.Unmarshal(recordByte,&record);
        fmt.Printf(" the unmarshall function output is : %s" , errrecordmarshal)

        if errrecordmarshal != nil {
            return nil, errrecordmarshal
        }

        }

        record.studentRollNo=args[0];
        record.studentName=args[1];
        record.studentBadge=append(record.studentBadge,args[2]);
        record.studentMarks=append(record.studentMarks,args[3]);
        record.studentSem=append(record.studentMarks,args[4]);
        record.issuedBy=append(record.issuedBy,args[5]);

        /*record.Rollno = append(record.Rollno,args[0]);
        record.Name = append(record.Name,args[1]);
        record.Sem=append(record.Sem,args[2]);
        record.Marks=append(record.Marks,args[3]);
*/
        fmt.Printf(" record structure rollno is : %s" ,  record.studentRollNo)
        fmt.Printf(" record structure name is   : %s" ,  record.studentName)
        fmt.Printf(" record structure badge is : %s" ,   record.studentBadge)
        fmt.Printf(" record structure marks is : : %s" , record.studentMarks)
        fmt.Printf(" record structure sem is : %s" ,     record.studentSem)
        fmt.Printf(" record structure issuedby is : %s" ,record.issuedBy)

        newrecordByte, err := json.Marshal(record);

        stringNewRecordByte := string(newrecordByte)

        fmt.Printf(" the marshall function output is : %s" , stringNewRecordByte)

        if err!=nil {

            return nil, err
        }
        err =stub.PutState(account,newrecordByte);
        if err != nil {

            return nil, err;
        }
        return nil, nil
}

func (t *CrowdFundChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
  if function != "query" {
                return nil, errors.New("Invalid query function name. Expecting \"query\".")
        }

       var err error

         if len(args) != 1 {
                return nil, errors.New("Incorrect number of arguments. Expecting name of the state variable to query.")
        }

     var   account = args[0]

        accountValueBytes ,err := stub.GetState(account)
        if err != nil {

                 return nil, err
        }

        return accountValueBytes, nil
}

func main() {
        err := shim.Start(new(CrowdFundChaincode))

        if err != nil {
                fmt.Printf("Error starting CrowdFundChaincode: %s", err)
        }
}
<|endoftext|>


<commit_before>// Copyright 2012-2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package testing

import (
	"time"

	jc "github.com/juju/testing/checkers"
	"github.com/juju/utils/set"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/apiserver/params"
	"github.com/juju/juju/testing"
)

type Stopper interface {
	Stop() error
}

func AssertStop(c *gc.C, stopper Stopper) {
	c.Assert(stopper.Stop(), gc.IsNil)
}

type KillWaiter interface {
	Kill()
	Wait() error
}

func AssertKillAndWait(c *gc.C, killWaiter KillWaiter) {
	killWaiter.Kill()
	c.Assert(killWaiter.Wait(), gc.IsNil)
}

// AssertCanStopWhenSending ensures even when there are changes
// pending to be delivered by the watcher it can still stop
// cleanly. This is necessary to check for deadlocks in case the
// watcher's inner loop is blocked trying to send and its tomb is
// already dying.
func AssertCanStopWhenSending(c *gc.C, stopper Stopper) {
	// Leave some time for the event to be delivered and the watcher
	// to block on sending it.
	<-time.After(testing.ShortWait)
	stopped := make(chan bool)
	// Stop() blocks, so we need to call it in a separate goroutine.
	go func() {
		c.Check(stopper.Stop(), gc.IsNil)
		stopped <- true
	}()
	select {
	case <-time.After(testing.LongWait):
		// NOTE: If this test fails here it means we have a deadlock
		// in the client-side watcher implementation.
		c.Fatalf("watcher did not stop as expected")
	case <-stopped:
	}
}

type NotifyWatcher interface {
	Stop() error
	Changes() <-chan struct{}
}

// NotifyWatcherC embeds a gocheck.C and adds methods to help verify
// the behaviour of any watcher that uses a <-chan struct{}.
type NotifyWatcherC struct {
	*gc.C
	State   SyncStarter
	Watcher NotifyWatcher
}

// SyncStarter is an interface that watcher checkers will use to ensure
// that changes to the watched object have been synchronized. This is
// primarily implemented by state.State.
type SyncStarter interface {
	StartSync()
}

// NewNotifyWatcherC returns a NotifyWatcherC that checks for aggressive
// event coalescence.
func NewNotifyWatcherC(c *gc.C, st SyncStarter, w NotifyWatcher) NotifyWatcherC {
	return NotifyWatcherC{
		C:       c,
		State:   st,
		Watcher: w,
	}
}

func (c NotifyWatcherC) AssertNoChange() {
	c.State.StartSync()
	select {
	case _, ok := <-c.Watcher.Changes():
		c.Fatalf("watcher sent unexpected change: (_, %v)", ok)
	case <-time.After(testing.ShortWait):
	}
}

func (c NotifyWatcherC) AssertOneChange() {
	c.State.StartSync()
	select {
	case _, ok := <-c.Watcher.Changes():
		c.Assert(ok, jc.IsTrue)
	case <-time.After(testing.LongWait):
		c.Fatalf("watcher did not send change")
	}
	c.AssertNoChange()
}

func (c NotifyWatcherC) AssertClosed() {
	select {
	case _, ok := <-c.Watcher.Changes():
		c.Assert(ok, jc.IsFalse)
	default:
		c.Fatalf("watcher not closed")
	}
}

// StringsWatcherC embeds a gocheck.C and adds methods to help verify
// the behaviour of any watcher that uses a <-chan []string.
type StringsWatcherC struct {
	*gc.C
	State   SyncStarter
	Watcher StringsWatcher
}

// NewStringsWatcherC returns a StringsWatcherC that checks for aggressive
// event coalescence.
func NewStringsWatcherC(c *gc.C, st SyncStarter, w StringsWatcher) StringsWatcherC {
	return StringsWatcherC{
		C:       c,
		State:   st,
		Watcher: w,
	}
}

type StringsWatcher interface {
	Stop() error
	Changes() <-chan []string
}

func (c StringsWatcherC) AssertNoChange() {
	c.State.StartSync()
	select {
	case actual, ok := <-c.Watcher.Changes():
		c.Fatalf("watcher sent unexpected change: (%v, %v)", actual, ok)
	case <-time.After(testing.ShortWait):
	}
}

func (c StringsWatcherC) AssertChanges() {
	c.State.StartSync()
	select {
	case <-c.Watcher.Changes():
	case <-time.After(testing.LongWait):
		c.Fatalf("watcher did not send change")
	}
}

func (c StringsWatcherC) AssertChange(expect ...string) {
	c.assertChange(false, expect...)
}

func (c StringsWatcherC) AssertChangeInSingleEvent(expect ...string) {
	c.assertChange(true, expect...)
}

// AssertChangeMaybeIncluding verifies that there is a change that may
// contain zero to all of the passed in strings, and no other changes.
func (c StringsWatcherC) AssertChangeMaybeIncluding(expect ...string) {
	maxCount := len(expect)
	actual := c.collectChanges(true, maxCount)

	if maxCount == 0 {
		c.Assert(actual, gc.HasLen, 0)
	} else {
		actualCount := len(actual)
		c.Assert(actualCount <= maxCount, jc.IsTrue, gc.Commentf("expected at most %d, got %d", maxCount, actualCount))
		unexpected := set.NewStrings(actual...).Difference(set.NewStrings(expect...))
		c.Assert(unexpected.Values(), gc.HasLen, 0)
	}
}

// assertChange asserts the given list of changes was reported by
// the watcher, but does not assume there are no following changes.
func (c StringsWatcherC) assertChange(single bool, expect ...string) {
	actual := c.collectChanges(single, len(expect))
	if len(expect) == 0 {
		c.Assert(actual, gc.HasLen, 0)
	} else {
		c.Assert(actual, jc.SameContents, expect)
	}
}

// collectChanges gets up to the max number of changes within the
// testing.LongWait period.
func (c StringsWatcherC) collectChanges(single bool, max int) []string {
	c.State.StartSync()
	timeout := time.After(testing.LongWait)
	var actual []string
	gotOneChange := false
loop:
	for {
		select {
		case changes, ok := <-c.Watcher.Changes():
			c.Assert(ok, jc.IsTrue)
			gotOneChange = true
			actual = append(actual, changes...)
			if single || len(actual) >= max {
				break loop
			}
		case <-timeout:
			if !gotOneChange {
				c.Fatalf("watcher did not send change")
			}
		}
	}
	return actual
}

func (c StringsWatcherC) AssertClosed() {
	select {
	case _, ok := <-c.Watcher.Changes():
		c.Assert(ok, jc.IsFalse)
	default:
		c.Fatalf("watcher not closed")
	}
}

// RelationUnitsWatcherC embeds a gocheck.C and adds methods to help
// verify the behaviour of any watcher that uses a <-chan
// params.RelationUnitsChange.
type RelationUnitsWatcherC struct {
	*gc.C
	State   SyncStarter
	Watcher RelationUnitsWatcher
	// settingsVersions keeps track of the settings version of each
	// changed unit since the last received changes to ensure version
	// always increases.
	settingsVersions map[string]int64
}

// NewRelationUnitsWatcherC returns a RelationUnitsWatcherC that
// checks for aggressive event coalescence.
func NewRelationUnitsWatcherC(c *gc.C, st SyncStarter, w RelationUnitsWatcher) RelationUnitsWatcherC {
	return RelationUnitsWatcherC{
		C:                c,
		State:            st,
		Watcher:          w,
		settingsVersions: make(map[string]int64),
	}
}

type RelationUnitsWatcher interface {
	Stop() error
	Changes() <-chan params.RelationUnitsChange
}

func (c RelationUnitsWatcherC) AssertNoChange() {
	c.State.StartSync()
	select {
	case actual, ok := <-c.Watcher.Changes():
		c.Fatalf("watcher sent unexpected change: (%v, %v)", actual, ok)
	case <-time.After(testing.ShortWait):
	}
}

// AssertChange asserts the given changes was reported by the watcher,
// but does not assume there are no following changes.
func (c RelationUnitsWatcherC) AssertChange(changed []string, departed []string) {
	// Get all items in changed in a map for easy lookup.
	changedNames := make(map[string]bool)
	for _, name := range changed {
		changedNames[name] = true
	}
	c.State.StartSync()
	timeout := time.After(testing.LongWait)
	select {
	case actual, ok := <-c.Watcher.Changes():
		c.Assert(ok, jc.IsTrue)
		c.Assert(actual.Changed, gc.HasLen, len(changed))
		// Because the versions can change, we only need to make sure
		// the keys match, not the contents (UnitSettings == txnRevno).
		for k, settings := range actual.Changed {
			_, ok := changedNames[k]
			c.Assert(ok, jc.IsTrue)
			oldVer, ok := c.settingsVersions[k]
			if !ok {
				// This is the first time we see this unit, so
				// save the settings version for later.
				c.settingsVersions[k] = settings.Version
			} else {
				// Already seen; make sure the version increased.
				if settings.Version <= oldVer {
					c.Fatalf("expected unit settings version > %d (got %d)", oldVer, settings.Version)
				}
			}
		}
		c.Assert(actual.Departed, jc.SameContents, departed)
	case <-timeout:
		c.Fatalf("watcher did not send change")
	}
}

func (c RelationUnitsWatcherC) AssertClosed() {
	select {
	case _, ok := <-c.Watcher.Changes():
		c.Assert(ok, jc.IsFalse)
	default:
		c.Fatalf("watcher not closed")
	}
}
<commit_msg>Add state sync and correct logic when reading changes in watcher.<commit_after>// Copyright 2012-2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package testing

import (
	"time"

	jc "github.com/juju/testing/checkers"
	"github.com/juju/utils/set"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/apiserver/params"
	"github.com/juju/juju/testing"
)

type Stopper interface {
	Stop() error
}

func AssertStop(c *gc.C, stopper Stopper) {
	c.Assert(stopper.Stop(), gc.IsNil)
}

type KillWaiter interface {
	Kill()
	Wait() error
}

func AssertKillAndWait(c *gc.C, killWaiter KillWaiter) {
	killWaiter.Kill()
	c.Assert(killWaiter.Wait(), gc.IsNil)
}

// AssertCanStopWhenSending ensures even when there are changes
// pending to be delivered by the watcher it can still stop
// cleanly. This is necessary to check for deadlocks in case the
// watcher's inner loop is blocked trying to send and its tomb is
// already dying.
func AssertCanStopWhenSending(c *gc.C, stopper Stopper) {
	// Leave some time for the event to be delivered and the watcher
	// to block on sending it.
	<-time.After(testing.ShortWait)
	stopped := make(chan bool)
	// Stop() blocks, so we need to call it in a separate goroutine.
	go func() {
		c.Check(stopper.Stop(), gc.IsNil)
		stopped <- true
	}()
	select {
	case <-time.After(testing.LongWait):
		// NOTE: If this test fails here it means we have a deadlock
		// in the client-side watcher implementation.
		c.Fatalf("watcher did not stop as expected")
	case <-stopped:
	}
}

type NotifyWatcher interface {
	Stop() error
	Changes() <-chan struct{}
}

// NotifyWatcherC embeds a gocheck.C and adds methods to help verify
// the behaviour of any watcher that uses a <-chan struct{}.
type NotifyWatcherC struct {
	*gc.C
	State   SyncStarter
	Watcher NotifyWatcher
}

// SyncStarter is an interface that watcher checkers will use to ensure
// that changes to the watched object have been synchronized. This is
// primarily implemented by state.State.
type SyncStarter interface {
	StartSync()
}

// NewNotifyWatcherC returns a NotifyWatcherC that checks for aggressive
// event coalescence.
func NewNotifyWatcherC(c *gc.C, st SyncStarter, w NotifyWatcher) NotifyWatcherC {
	return NotifyWatcherC{
		C:       c,
		State:   st,
		Watcher: w,
	}
}

func (c NotifyWatcherC) AssertNoChange() {
	c.State.StartSync()
	select {
	case _, ok := <-c.Watcher.Changes():
		c.Fatalf("watcher sent unexpected change: (_, %v)", ok)
	case <-time.After(testing.ShortWait):
	}
}

func (c NotifyWatcherC) AssertOneChange() {
	c.State.StartSync()
	select {
	case _, ok := <-c.Watcher.Changes():
		c.Assert(ok, jc.IsTrue)
	case <-time.After(testing.LongWait):
		c.Fatalf("watcher did not send change")
	}
	c.AssertNoChange()
}

func (c NotifyWatcherC) AssertClosed() {
	select {
	case _, ok := <-c.Watcher.Changes():
		c.Assert(ok, jc.IsFalse)
	default:
		c.Fatalf("watcher not closed")
	}
}

// StringsWatcherC embeds a gocheck.C and adds methods to help verify
// the behaviour of any watcher that uses a <-chan []string.
type StringsWatcherC struct {
	*gc.C
	State   SyncStarter
	Watcher StringsWatcher
}

// NewStringsWatcherC returns a StringsWatcherC that checks for aggressive
// event coalescence.
func NewStringsWatcherC(c *gc.C, st SyncStarter, w StringsWatcher) StringsWatcherC {
	return StringsWatcherC{
		C:       c,
		State:   st,
		Watcher: w,
	}
}

type StringsWatcher interface {
	Stop() error
	Changes() <-chan []string
}

func (c StringsWatcherC) AssertNoChange() {
	c.State.StartSync()
	select {
	case actual, ok := <-c.Watcher.Changes():
		c.Fatalf("watcher sent unexpected change: (%v, %v)", actual, ok)
	case <-time.After(testing.ShortWait):
	}
}

func (c StringsWatcherC) AssertChanges() {
	c.State.StartSync()
	select {
	case <-c.Watcher.Changes():
	case <-time.After(testing.LongWait):
		c.Fatalf("watcher did not send change")
	}
}

func (c StringsWatcherC) AssertChange(expect ...string) {
	// Fixes lp#1589641: some time, under race & stress testing,
	// reads of changes from watcher chan seem to get out of order.
	// This additional Sync, ensures that the changes are processed correctly.
	c.State.StartSync()
	// We should assert for either a single or multiple changes,
	// based on the number of `expect` changes.
	c.assertChange(len(expect) == 1, expect...)
}

func (c StringsWatcherC) AssertChangeInSingleEvent(expect ...string) {
	c.assertChange(true, expect...)
}

// AssertChangeMaybeIncluding verifies that there is a change that may
// contain zero to all of the passed in strings, and no other changes.
func (c StringsWatcherC) AssertChangeMaybeIncluding(expect ...string) {
	maxCount := len(expect)
	actual := c.collectChanges(true, maxCount)

	if maxCount == 0 {
		c.Assert(actual, gc.HasLen, 0)
	} else {
		actualCount := len(actual)
		c.Assert(actualCount <= maxCount, jc.IsTrue, gc.Commentf("expected at most %d, got %d", maxCount, actualCount))
		unexpected := set.NewStrings(actual...).Difference(set.NewStrings(expect...))
		c.Assert(unexpected.Values(), gc.HasLen, 0)
	}
}

// assertChange asserts the given list of changes was reported by
// the watcher, but does not assume there are no following changes.
func (c StringsWatcherC) assertChange(single bool, expect ...string) {
	actual := c.collectChanges(single, len(expect))
	if len(expect) == 0 {
		c.Assert(actual, gc.HasLen, 0)
	} else {
		c.Assert(actual, jc.SameContents, expect)
	}
}

// collectChanges gets up to the max number of changes within the
// testing.LongWait period.
func (c StringsWatcherC) collectChanges(single bool, max int) []string {
	c.State.StartSync()
	timeout := time.After(testing.LongWait)
	var actual []string
	gotOneChange := false
loop:
	for {
		select {
		case changes, ok := <-c.Watcher.Changes():
			c.Assert(ok, jc.IsTrue)
			gotOneChange = true
			actual = append(actual, changes...)
			if single || len(actual) >= max {
				break loop
			}
		case <-timeout:
			if !gotOneChange {
				c.Fatalf("watcher did not send change")
			}
		}
	}
	return actual
}

func (c StringsWatcherC) AssertClosed() {
	select {
	case _, ok := <-c.Watcher.Changes():
		c.Assert(ok, jc.IsFalse)
	default:
		c.Fatalf("watcher not closed")
	}
}

// RelationUnitsWatcherC embeds a gocheck.C and adds methods to help
// verify the behaviour of any watcher that uses a <-chan
// params.RelationUnitsChange.
type RelationUnitsWatcherC struct {
	*gc.C
	State   SyncStarter
	Watcher RelationUnitsWatcher
	// settingsVersions keeps track of the settings version of each
	// changed unit since the last received changes to ensure version
	// always increases.
	settingsVersions map[string]int64
}

// NewRelationUnitsWatcherC returns a RelationUnitsWatcherC that
// checks for aggressive event coalescence.
func NewRelationUnitsWatcherC(c *gc.C, st SyncStarter, w RelationUnitsWatcher) RelationUnitsWatcherC {
	return RelationUnitsWatcherC{
		C:                c,
		State:            st,
		Watcher:          w,
		settingsVersions: make(map[string]int64),
	}
}

type RelationUnitsWatcher interface {
	Stop() error
	Changes() <-chan params.RelationUnitsChange
}

func (c RelationUnitsWatcherC) AssertNoChange() {
	c.State.StartSync()
	select {
	case actual, ok := <-c.Watcher.Changes():
		c.Fatalf("watcher sent unexpected change: (%v, %v)", actual, ok)
	case <-time.After(testing.ShortWait):
	}
}

// AssertChange asserts the given changes was reported by the watcher,
// but does not assume there are no following changes.
func (c RelationUnitsWatcherC) AssertChange(changed []string, departed []string) {
	// Get all items in changed in a map for easy lookup.
	changedNames := make(map[string]bool)
	for _, name := range changed {
		changedNames[name] = true
	}
	c.State.StartSync()
	timeout := time.After(testing.LongWait)
	select {
	case actual, ok := <-c.Watcher.Changes():
		c.Assert(ok, jc.IsTrue)
		c.Assert(actual.Changed, gc.HasLen, len(changed))
		// Because the versions can change, we only need to make sure
		// the keys match, not the contents (UnitSettings == txnRevno).
		for k, settings := range actual.Changed {
			_, ok := changedNames[k]
			c.Assert(ok, jc.IsTrue)
			oldVer, ok := c.settingsVersions[k]
			if !ok {
				// This is the first time we see this unit, so
				// save the settings version for later.
				c.settingsVersions[k] = settings.Version
			} else {
				// Already seen; make sure the version increased.
				if settings.Version <= oldVer {
					c.Fatalf("expected unit settings version > %d (got %d)", oldVer, settings.Version)
				}
			}
		}
		c.Assert(actual.Departed, jc.SameContents, departed)
	case <-timeout:
		c.Fatalf("watcher did not send change")
	}
}

func (c RelationUnitsWatcherC) AssertClosed() {
	select {
	case _, ok := <-c.Watcher.Changes():
		c.Assert(ok, jc.IsFalse)
	default:
		c.Fatalf("watcher not closed")
	}
}
<|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 options

import (
	"runtime"
	"time"

	"github.com/spf13/pflag"

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

const (
	// When these values are updated, also update test/e2e/framework/util.go
	defaultPodSandboxImageName    = "gcr.io/google_containers/pause"
	defaultPodSandboxImageVersion = "3.0"
	// From pkg/kubelet/rkt/rkt.go to avoid circular import
	defaultRktAPIServiceEndpoint = "localhost:15441"
)

var (
	defaultPodSandboxImage = defaultPodSandboxImageName +
		"-" + runtime.GOARCH + ":" +
		defaultPodSandboxImageVersion
)

type ContainerRuntimeOptions struct {
	// Docker-specific options.

	// DockershimRootDirectory is the path to the dockershim root directory. Defaults to
	// /var/lib/dockershim if unset. Exposed for integration testing (e.g. in OpenShift).
	DockershimRootDirectory string
	// Enable dockershim only mode.
	ExperimentalDockershim bool
	// This flag, if set, disables use of a shared PID namespace for pods running in the docker CRI runtime.
	// A shared PID namespace is the only option in non-docker runtimes and is required by the CRI. The ability to
	// disable it for docker will be removed unless a compelling use case is discovered with widespread use.
	// TODO: Remove once we no longer support disabling shared PID namespace (https://issues.k8s.io/41938)
	DockerDisableSharedPID bool
	// PodSandboxImage is the image whose network/ipc namespaces
	// containers in each pod will use.
	PodSandboxImage string
	// DockerEndpoint is the path to the docker endpoint to communicate with.
	DockerEndpoint string
	// DockerExecHandlerName is the handler to use when executing a command
	// in a container. Valid values are 'native' and 'nsenter'. Defaults to
	// 'native'.
	DockerExecHandlerName string
	// If no pulling progress is made before the deadline imagePullProgressDeadline,
	// the image pulling will be cancelled. Defaults to 1m0s.
	// +optional
	ImagePullProgressDeadline metav1.Duration

	// Network plugin options.

	// networkPluginName is the name of the network plugin to be invoked for
	// various events in kubelet/pod lifecycle
	NetworkPluginName string
	// NetworkPluginMTU is the MTU to be passed to the network plugin,
	// and overrides the default MTU for cases where it cannot be automatically
	// computed (such as IPSEC).
	NetworkPluginMTU int32
	// NetworkPluginDir is the full path of the directory in which to search
	// for network plugins (and, for backwards-compat, CNI config files)
	NetworkPluginDir string
	// CNIConfDir is the full path of the directory in which to search for
	// CNI config files
	CNIConfDir string
	// CNIBinDir is the full path of the directory in which to search for
	// CNI plugin binaries
	CNIBinDir string

	// rkt-specific options.

	// rktPath is the path of rkt binary. Leave empty to use the first rkt in $PATH.
	RktPath string
	// rktApiEndpoint is the endpoint of the rkt API service to communicate with.
	RktAPIEndpoint string
	// rktStage1Image is the image to use as stage1. Local paths and
	// http/https URLs are supported.
	RktStage1Image string
}

// NewContainerRuntimeOptions will create a new ContainerRuntimeOptions with
// default values.
func NewContainerRuntimeOptions() *ContainerRuntimeOptions {
	dockerEndpoint := ""
	if runtime.GOOS != "windows" {
		dockerEndpoint = "unix:///var/run/docker.sock"
	}

	return &ContainerRuntimeOptions{
		DockerEndpoint:            dockerEndpoint,
		DockershimRootDirectory:   "/var/lib/dockershim",
		DockerExecHandlerName:     "native",
		PodSandboxImage:           defaultPodSandboxImage,
		ImagePullProgressDeadline: metav1.Duration{Duration: 1 * time.Minute},
		RktAPIEndpoint:            defaultRktAPIServiceEndpoint,
		ExperimentalDockershim:    false,
	}
}

func (s *ContainerRuntimeOptions) AddFlags(fs *pflag.FlagSet) {
	// Docker-specific settings.
	fs.BoolVar(&s.ExperimentalDockershim, "experimental-dockershim", s.ExperimentalDockershim, "Enable dockershim only mode. In this mode, kubelet will only start dockershim without any other functionalities. This flag only serves test purpose, please do not use it unless you are conscious of what you are doing. [default=false]")
	fs.MarkHidden("experimental-dockershim")
	fs.StringVar(&s.DockershimRootDirectory, "experimental-dockershim-root-directory", s.DockershimRootDirectory, "Path to the dockershim root directory.")
	fs.MarkHidden("experimental-dockershim-root-directory")
	fs.BoolVar(&s.DockerDisableSharedPID, "docker-disable-shared-pid", s.DockerDisableSharedPID, "The Container Runtime Interface (CRI) defaults to using a shared PID namespace for containers in a pod when running with Docker 1.13.1 or higher. Setting this flag reverts to the previous behavior of isolated PID namespaces. This ability will be removed in a future Kubernetes release.")
	fs.StringVar(&s.PodSandboxImage, "pod-infra-container-image", s.PodSandboxImage, "The image whose network/ipc namespaces containers in each pod will use.")
	fs.StringVar(&s.DockerEndpoint, "docker-endpoint", s.DockerEndpoint, "Use this for the docker endpoint to communicate with")
	// TODO(#40229): Remove the docker-exec-handler flag.
	fs.StringVar(&s.DockerExecHandlerName, "docker-exec-handler", s.DockerExecHandlerName, "Handler to use when executing a command in a container. Valid values are 'native' and 'nsenter'. Defaults to 'native'.")
	fs.MarkDeprecated("docker-exec-handler", "this flag will be removed and only the 'native' handler will be supported in the future.")
	fs.DurationVar(&s.ImagePullProgressDeadline.Duration, "image-pull-progress-deadline", s.ImagePullProgressDeadline.Duration, "If no pulling progress is made before this deadline, the image pulling will be cancelled.")

	// Network plugin settings. Shared by both docker and rkt.
	fs.StringVar(&s.NetworkPluginName, "network-plugin", s.NetworkPluginName, "<Warning: Alpha feature> The name of the network plugin to be invoked for various events in kubelet/pod lifecycle")
	//TODO(#46410): Remove the network-plugin-dir flag.
	fs.StringVar(&s.NetworkPluginDir, "network-plugin-dir", s.NetworkPluginDir, "<Warning: Alpha feature> The full path of the directory in which to search for network plugins or CNI config")
	fs.MarkDeprecated("network-plugin-dir", "Use --cni-bin-dir instead. This flag will be removed in a future version.")
	fs.StringVar(&s.CNIConfDir, "cni-conf-dir", s.CNIConfDir, "<Warning: Alpha feature> The full path of the directory in which to search for CNI config files. Default: /etc/cni/net.d")
	fs.StringVar(&s.CNIBinDir, "cni-bin-dir", s.CNIBinDir, "<Warning: Alpha feature> The full path of the directory in which to search for CNI plugin binaries. Default: /opt/cni/bin")
	fs.Int32Var(&s.NetworkPluginMTU, "network-plugin-mtu", s.NetworkPluginMTU, "<Warning: Alpha feature> The MTU to be passed to the network plugin, to override the default. Set to 0 to use the default 1460 MTU.")

	// Rkt-specific settings.
	fs.StringVar(&s.RktPath, "rkt-path", s.RktPath, "Path of rkt binary. Leave empty to use the first rkt in $PATH.  Only used if --container-runtime='rkt'.")
	fs.StringVar(&s.RktAPIEndpoint, "rkt-api-endpoint", s.RktAPIEndpoint, "The endpoint of the rkt API service to communicate with. Only used if --container-runtime='rkt'.")
	fs.StringVar(&s.RktStage1Image, "rkt-stage1-image", s.RktStage1Image, "image to use as stage1. Local paths and http/https URLs are supported. If empty, the 'stage1.aci' in the same directory as '--rkt-path' will be used.")
	fs.MarkDeprecated("rkt-stage1-image", "Will be removed in a future version. The default stage1 image will be specified by the rkt configurations, see https://github.com/coreos/rkt/blob/master/Documentation/configuration.md for more details.")

}
<commit_msg>Revert to using isolated PID namespaces in Docker<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 options

import (
	"runtime"
	"time"

	"github.com/spf13/pflag"

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

const (
	// When these values are updated, also update test/e2e/framework/util.go
	defaultPodSandboxImageName    = "gcr.io/google_containers/pause"
	defaultPodSandboxImageVersion = "3.0"
	// From pkg/kubelet/rkt/rkt.go to avoid circular import
	defaultRktAPIServiceEndpoint = "localhost:15441"
)

var (
	defaultPodSandboxImage = defaultPodSandboxImageName +
		"-" + runtime.GOARCH + ":" +
		defaultPodSandboxImageVersion
)

type ContainerRuntimeOptions struct {
	// Docker-specific options.

	// DockershimRootDirectory is the path to the dockershim root directory. Defaults to
	// /var/lib/dockershim if unset. Exposed for integration testing (e.g. in OpenShift).
	DockershimRootDirectory string
	// Enable dockershim only mode.
	ExperimentalDockershim bool
	// This flag, if set, disables use of a shared PID namespace for pods running in the docker CRI runtime.
	// A shared PID namespace is the only option in non-docker runtimes and is required by the CRI. The ability to
	// disable it for docker will be removed unless a compelling use case is discovered with widespread use.
	// TODO: Remove once we no longer support disabling shared PID namespace (https://issues.k8s.io/41938)
	DockerDisableSharedPID bool
	// PodSandboxImage is the image whose network/ipc namespaces
	// containers in each pod will use.
	PodSandboxImage string
	// DockerEndpoint is the path to the docker endpoint to communicate with.
	DockerEndpoint string
	// DockerExecHandlerName is the handler to use when executing a command
	// in a container. Valid values are 'native' and 'nsenter'. Defaults to
	// 'native'.
	DockerExecHandlerName string
	// If no pulling progress is made before the deadline imagePullProgressDeadline,
	// the image pulling will be cancelled. Defaults to 1m0s.
	// +optional
	ImagePullProgressDeadline metav1.Duration

	// Network plugin options.

	// networkPluginName is the name of the network plugin to be invoked for
	// various events in kubelet/pod lifecycle
	NetworkPluginName string
	// NetworkPluginMTU is the MTU to be passed to the network plugin,
	// and overrides the default MTU for cases where it cannot be automatically
	// computed (such as IPSEC).
	NetworkPluginMTU int32
	// NetworkPluginDir is the full path of the directory in which to search
	// for network plugins (and, for backwards-compat, CNI config files)
	NetworkPluginDir string
	// CNIConfDir is the full path of the directory in which to search for
	// CNI config files
	CNIConfDir string
	// CNIBinDir is the full path of the directory in which to search for
	// CNI plugin binaries
	CNIBinDir string

	// rkt-specific options.

	// rktPath is the path of rkt binary. Leave empty to use the first rkt in $PATH.
	RktPath string
	// rktApiEndpoint is the endpoint of the rkt API service to communicate with.
	RktAPIEndpoint string
	// rktStage1Image is the image to use as stage1. Local paths and
	// http/https URLs are supported.
	RktStage1Image string
}

// NewContainerRuntimeOptions will create a new ContainerRuntimeOptions with
// default values.
func NewContainerRuntimeOptions() *ContainerRuntimeOptions {
	dockerEndpoint := ""
	if runtime.GOOS != "windows" {
		dockerEndpoint = "unix:///var/run/docker.sock"
	}

	return &ContainerRuntimeOptions{
		DockerEndpoint:            dockerEndpoint,
		DockershimRootDirectory:   "/var/lib/dockershim",
		DockerExecHandlerName:     "native",
		DockerDisableSharedPID:    true,
		PodSandboxImage:           defaultPodSandboxImage,
		ImagePullProgressDeadline: metav1.Duration{Duration: 1 * time.Minute},
		RktAPIEndpoint:            defaultRktAPIServiceEndpoint,
		ExperimentalDockershim:    false,
	}
}

func (s *ContainerRuntimeOptions) AddFlags(fs *pflag.FlagSet) {
	// Docker-specific settings.
	fs.BoolVar(&s.ExperimentalDockershim, "experimental-dockershim", s.ExperimentalDockershim, "Enable dockershim only mode. In this mode, kubelet will only start dockershim without any other functionalities. This flag only serves test purpose, please do not use it unless you are conscious of what you are doing. [default=false]")
	fs.MarkHidden("experimental-dockershim")
	fs.StringVar(&s.DockershimRootDirectory, "experimental-dockershim-root-directory", s.DockershimRootDirectory, "Path to the dockershim root directory.")
	fs.MarkHidden("experimental-dockershim-root-directory")
	fs.BoolVar(&s.DockerDisableSharedPID, "docker-disable-shared-pid", s.DockerDisableSharedPID, "The Container Runtime Interface (CRI) defaults to using a shared PID namespace for containers in a pod when running with Docker 1.13.1 or higher. Setting this flag reverts to the previous behavior of isolated PID namespaces. This ability will be removed in a future Kubernetes release.")
	fs.StringVar(&s.PodSandboxImage, "pod-infra-container-image", s.PodSandboxImage, "The image whose network/ipc namespaces containers in each pod will use.")
	fs.StringVar(&s.DockerEndpoint, "docker-endpoint", s.DockerEndpoint, "Use this for the docker endpoint to communicate with")
	// TODO(#40229): Remove the docker-exec-handler flag.
	fs.StringVar(&s.DockerExecHandlerName, "docker-exec-handler", s.DockerExecHandlerName, "Handler to use when executing a command in a container. Valid values are 'native' and 'nsenter'. Defaults to 'native'.")
	fs.MarkDeprecated("docker-exec-handler", "this flag will be removed and only the 'native' handler will be supported in the future.")
	fs.DurationVar(&s.ImagePullProgressDeadline.Duration, "image-pull-progress-deadline", s.ImagePullProgressDeadline.Duration, "If no pulling progress is made before this deadline, the image pulling will be cancelled.")

	// Network plugin settings. Shared by both docker and rkt.
	fs.StringVar(&s.NetworkPluginName, "network-plugin", s.NetworkPluginName, "<Warning: Alpha feature> The name of the network plugin to be invoked for various events in kubelet/pod lifecycle")
	//TODO(#46410): Remove the network-plugin-dir flag.
	fs.StringVar(&s.NetworkPluginDir, "network-plugin-dir", s.NetworkPluginDir, "<Warning: Alpha feature> The full path of the directory in which to search for network plugins or CNI config")
	fs.MarkDeprecated("network-plugin-dir", "Use --cni-bin-dir instead. This flag will be removed in a future version.")
	fs.StringVar(&s.CNIConfDir, "cni-conf-dir", s.CNIConfDir, "<Warning: Alpha feature> The full path of the directory in which to search for CNI config files. Default: /etc/cni/net.d")
	fs.StringVar(&s.CNIBinDir, "cni-bin-dir", s.CNIBinDir, "<Warning: Alpha feature> The full path of the directory in which to search for CNI plugin binaries. Default: /opt/cni/bin")
	fs.Int32Var(&s.NetworkPluginMTU, "network-plugin-mtu", s.NetworkPluginMTU, "<Warning: Alpha feature> The MTU to be passed to the network plugin, to override the default. Set to 0 to use the default 1460 MTU.")

	// Rkt-specific settings.
	fs.StringVar(&s.RktPath, "rkt-path", s.RktPath, "Path of rkt binary. Leave empty to use the first rkt in $PATH.  Only used if --container-runtime='rkt'.")
	fs.StringVar(&s.RktAPIEndpoint, "rkt-api-endpoint", s.RktAPIEndpoint, "The endpoint of the rkt API service to communicate with. Only used if --container-runtime='rkt'.")
	fs.StringVar(&s.RktStage1Image, "rkt-stage1-image", s.RktStage1Image, "image to use as stage1. Local paths and http/https URLs are supported. If empty, the 'stage1.aci' in the same directory as '--rkt-path' will be used.")
	fs.MarkDeprecated("rkt-stage1-image", "Will be removed in a future version. The default stage1 image will be specified by the rkt configurations, see https://github.com/coreos/rkt/blob/master/Documentation/configuration.md for more details.")

}
<|endoftext|>


<commit_before>package inspect

import (
	"bytes"
	"flag"
	"fmt"
	"os"
	"text/tabwriter"

	"github.com/hashicorp/consul/command/flags"
	"github.com/hashicorp/consul/snapshot"
	"github.com/mitchellh/cli"
)

func New(ui cli.Ui) *cmd {
	c := &cmd{UI: ui}
	c.init()
	return c
}

type cmd struct {
	UI    cli.Ui
	flags *flag.FlagSet
	help  string
}

func (c *cmd) init() {
	c.flags = flag.NewFlagSet("", flag.ContinueOnError)
	c.help = flags.Usage(help, c.flags)
}

func (c *cmd) Run(args []string) int {
	if err := c.flags.Parse(args); err != nil {
		return 1
	}

	var file string

	args = c.flags.Args()
	switch len(args) {
	case 0:
		c.UI.Error("Missing FILE argument")
		return 1
	case 1:
		file = args[0]
	default:
		c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
		return 1
	}

	// Open the file.
	f, err := os.Open(file)
	if err != nil {
		c.UI.Error(fmt.Sprintf("Error opening snapshot file: %s", err))
		return 1
	}
	defer f.Close()

	meta, err := snapshot.Verify(f)
	if err != nil {
		c.UI.Error(fmt.Sprintf("Error verifying snapshot: %s", err))
	}

	var b bytes.Buffer
	tw := tabwriter.NewWriter(&b, 0, 2, 6, ' ', 0)
	fmt.Fprintf(tw, "ID\t%s\n", meta.ID)
	fmt.Fprintf(tw, "Size\t%d\n", meta.Size)
	fmt.Fprintf(tw, "Index\t%d\n", meta.Index)
	fmt.Fprintf(tw, "Term\t%d\n", meta.Term)
	fmt.Fprintf(tw, "Version\t%d\n", meta.Version)
	if err = tw.Flush(); err != nil {
		c.UI.Error(fmt.Sprintf("Error rendering snapshot info: %s", err))
	}

	c.UI.Info(b.String())

	return 0
}

func (c *cmd) Synopsis() string {
	return synopsis
}

func (c *cmd) Help() string {
	return c.help
}

const synopsis = "Displays information about a Consul snapshot file"
const help = `
Usage: consul snapshot inspect [options] FILE

  Displays information about a snapshot file on disk.

  To inspect the file "backup.snap":

    $ consul snapshot inspect backup.snap

  For a full list of options and examples, please see the Consul documentation.
`
<commit_msg>Fix a panic in snapshot inspect command<commit_after>package inspect

import (
	"bytes"
	"flag"
	"fmt"
	"os"
	"text/tabwriter"

	"github.com/hashicorp/consul/command/flags"
	"github.com/hashicorp/consul/snapshot"
	"github.com/mitchellh/cli"
)

func New(ui cli.Ui) *cmd {
	c := &cmd{UI: ui}
	c.init()
	return c
}

type cmd struct {
	UI    cli.Ui
	flags *flag.FlagSet
	help  string
}

func (c *cmd) init() {
	c.flags = flag.NewFlagSet("", flag.ContinueOnError)
	c.help = flags.Usage(help, c.flags)
}

func (c *cmd) Run(args []string) int {
	if err := c.flags.Parse(args); err != nil {
		return 1
	}

	var file string

	args = c.flags.Args()
	switch len(args) {
	case 0:
		c.UI.Error("Missing FILE argument")
		return 1
	case 1:
		file = args[0]
	default:
		c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
		return 1
	}

	// Open the file.
	f, err := os.Open(file)
	if err != nil {
		c.UI.Error(fmt.Sprintf("Error opening snapshot file: %s", err))
		return 1
	}
	defer f.Close()

	meta, err := snapshot.Verify(f)
	if err != nil {
		c.UI.Error(fmt.Sprintf("Error verifying snapshot: %s", err))
		return 1
	}

	var b bytes.Buffer
	tw := tabwriter.NewWriter(&b, 0, 2, 6, ' ', 0)
	fmt.Fprintf(tw, "ID\t%s\n", meta.ID)
	fmt.Fprintf(tw, "Size\t%d\n", meta.Size)
	fmt.Fprintf(tw, "Index\t%d\n", meta.Index)
	fmt.Fprintf(tw, "Term\t%d\n", meta.Term)
	fmt.Fprintf(tw, "Version\t%d\n", meta.Version)
	if err = tw.Flush(); err != nil {
		c.UI.Error(fmt.Sprintf("Error rendering snapshot info: %s", err))
		return 1
	}

	c.UI.Info(b.String())

	return 0
}

func (c *cmd) Synopsis() string {
	return synopsis
}

func (c *cmd) Help() string {
	return c.help
}

const synopsis = "Displays information about a Consul snapshot file"
const help = `
Usage: consul snapshot inspect [options] FILE

  Displays information about a snapshot file on disk.

  To inspect the file "backup.snap":

    $ consul snapshot inspect backup.snap

  For a full list of options and examples, please see the Consul documentation.
`
<|endoftext|>


<commit_before>// Package mailgun provides methods for interacting with the Mailgun API.
// For further information please see the Mailgun documentation at
// http://documentation.mailgun.com/
//
// Author: Michael Banzon
package mailgun

import (
	"fmt"
	"time"
)

const (
	apiBase                 = "https://api.mailgun.net/v2"
	messagesEndpoint        = "messages"
	addressValidateEndpoint = "address/validate"
	addressParseEndpoint    = "address/parse"
	bouncesEndpoint         = "bounces"
	statsEndpoint           = "stats"
	domainsEndpoint         = "domains"
	deleteTagEndpoint       = "tags"
	campaignsEndpoint       = "campaigns"
	basicAuthUser           = "api"
)

// Mailgun defines the supported subset of the Mailgun API.
type Mailgun interface {
	Domain() string
	ApiKey() string
	PublicApiKey() string
	Send(m *Message) (string, string, error)
	ValidateEmail(email string) (EmailVerification, error)
	ParseAddresses(addresses ...string) ([]string, []string, error)
	GetBounces(limit, skip int) (int, []Bounce, error)
	GetSingleBounce(address string) (Bounce, error)
	AddBounce(address, code, error string) error
	DeleteBounce(address string) error
	GetStats(limit int, skip int, startDate time.Time, event ...string) (int, []Stat, error)
	DeleteTag(tag string) error
	GetDomains(limit, skip int) (int, []Domain, error)
	GetSingleDomain(domain string) (Domain, []DNSRecord, []DNSRecord, error)
	CreateDomain(name string, smtpPassword string, spamAction bool, wildcard bool) error
	DeleteDomain(name string) error
	GetCampaigns() (int, []Campaign, error)
	CreateCampaign(name, id string) error
	UpdateCampaign(oldId, name, newId string) error
	DeleteCampaign(id string) error
	GetComplaints(limit, skip int) (int, []Complaint, error)
	GetSingleComplaint(address string) (Complaint, error)
}

// Imagine some data needed by a large set of methods in order to interact with the Mailgun API.
// mailgunImpl bundles these data together in a convenient place.
// Colloquially, we refer to instances of this structure as "clients."
type mailgunImpl struct {
	domain       string
	apiKey       string
	publicApiKey string
}

// Creates a new Mailgun client instance.
func NewMailgun(domain, apiKey, publicApiKey string) Mailgun {
	m := mailgunImpl{domain: domain, apiKey: apiKey, publicApiKey: publicApiKey}
	return &m
}

// Returns the domain configured for this client.
func (m *mailgunImpl) Domain() string {
	return m.domain
}

// Returns the API key configured for this client.
func (m *mailgunImpl) ApiKey() string {
	return m.apiKey
}

// Returns the public API key configured for this client.
func (m *mailgunImpl) PublicApiKey() string {
	return m.publicApiKey
}

// Generates the URL for the API using the domain and endpoint.
func generateApiUrl(m Mailgun, endpoint string) string {
	return fmt.Sprintf("%s/%s/%s", apiBase, m.Domain(), endpoint)
}

// As with generateApiUrl, except that generatePublicApiUrl has no need for the domain.
func generatePublicApiUrl(endpoint string) string {
	return fmt.Sprintf("%s/%s", apiBase, endpoint)
}

// parseMailgunTime translates a timestamp as returned by Mailgun into a Go standard timestamp.
func parseMailgunTime(ts string) (t time.Time, err error) {
	t, err = time.Parse("Mon, 2 Jan 2006 15:04:05 MST", ts)
	return
}
<commit_msg>go fmt<commit_after>// Package mailgun provides methods for interacting with the Mailgun API.
// For further information please see the Mailgun documentation at
// http://documentation.mailgun.com/
//
// Author: Michael Banzon
package mailgun

import (
	"fmt"
	"time"
)

const (
	apiBase                 = "https://api.mailgun.net/v2"
	messagesEndpoint        = "messages"
	addressValidateEndpoint = "address/validate"
	addressParseEndpoint    = "address/parse"
	bouncesEndpoint         = "bounces"
	statsEndpoint           = "stats"
	domainsEndpoint         = "domains"
	deleteTagEndpoint       = "tags"
	campaignsEndpoint       = "campaigns"
	basicAuthUser           = "api"
)

// Mailgun defines the supported subset of the Mailgun API.
type Mailgun interface {
	Domain() string
	ApiKey() string
	PublicApiKey() string
	Send(m *Message) (string, string, error)
	ValidateEmail(email string) (EmailVerification, error)
	ParseAddresses(addresses ...string) ([]string, []string, error)
	GetBounces(limit, skip int) (int, []Bounce, error)
	GetSingleBounce(address string) (Bounce, error)
	AddBounce(address, code, error string) error
	DeleteBounce(address string) error
	GetStats(limit int, skip int, startDate time.Time, event ...string) (int, []Stat, error)
	DeleteTag(tag string) error
	GetDomains(limit, skip int) (int, []Domain, error)
	GetSingleDomain(domain string) (Domain, []DNSRecord, []DNSRecord, error)
	CreateDomain(name string, smtpPassword string, spamAction bool, wildcard bool) error
	DeleteDomain(name string) error
	GetCampaigns() (int, []Campaign, error)
	CreateCampaign(name, id string) error
	UpdateCampaign(oldId, name, newId string) error
	DeleteCampaign(id string) error
	GetComplaints(limit, skip int) (int, []Complaint, error)
	GetSingleComplaint(address string) (Complaint, error)
}

// Imagine some data needed by a large set of methods in order to interact with the Mailgun API.
// mailgunImpl bundles these data together in a convenient place.
// Colloquially, we refer to instances of this structure as "clients."
type mailgunImpl struct {
	domain       string
	apiKey       string
	publicApiKey string
}

// Creates a new Mailgun client instance.
func NewMailgun(domain, apiKey, publicApiKey string) Mailgun {
	m := mailgunImpl{domain: domain, apiKey: apiKey, publicApiKey: publicApiKey}
	return &m
}

// Returns the domain configured for this client.
func (m *mailgunImpl) Domain() string {
	return m.domain
}

// Returns the API key configured for this client.
func (m *mailgunImpl) ApiKey() string {
	return m.apiKey
}

// Returns the public API key configured for this client.
func (m *mailgunImpl) PublicApiKey() string {
	return m.publicApiKey
}

// Generates the URL for the API using the domain and endpoint.
func generateApiUrl(m Mailgun, endpoint string) string {
	return fmt.Sprintf("%s/%s/%s", apiBase, m.Domain(), endpoint)
}

// As with generateApiUrl, except that generatePublicApiUrl has no need for the domain.
func generatePublicApiUrl(endpoint string) string {
	return fmt.Sprintf("%s/%s", apiBase, endpoint)
}

// parseMailgunTime translates a timestamp as returned by Mailgun into a Go standard timestamp.
func parseMailgunTime(ts string) (t time.Time, err error) {
	t, err = time.Parse("Mon, 2 Jan 2006 15:04:05 MST", ts)
	return
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/iam"
	microerror "github.com/giantswarm/microkit/error"
)

const (
	RoleNameTemplate         = "EC2-K8S-Role"
	PolicyNameTemplate       = "EC2-K8S-Policy"
	ProfileNameTemplate      = "EC2-K8S-Role"
	AssumeRolePolicyDocument = `{
		"Version": "2012-10-17",
		"Statement": {
			"Effect": "Allow",
			"Principal": {
				"Service": "ec2.amazonaws.com"
			},
			"Action": "sts:AssumeRole"
		}
	}`
	PolicyDocumentTempl = `{
		"Version": "2012-10-17",
		"Statement": [
			{
            	"Action": "ec2:*",
            	"Effect": "Allow",
                "Resource": "*"
            },
			{
				"Effect": "Allow",
				"Action": "kms:Decrypt",
				"Resource": %q
			},
			{
				"Effect": "Allow",
				"Action": [
					"s3:GetBucketLocation",
					"s3:ListAllMyBuckets"
				],
				"Resource": "*"
			},
			{
				"Effect": "Allow",
				"Action": [
					"s3:ListBucket"
				],
				"Resource": "arn:aws:s3:::%s"
			},
			{
				"Effect": "Allow",
				"Action": "s3:GetObject",
				"Resource": "arn:aws:s3:::%s/*"
			}
		]
	}`
)

type Policy struct {
	ClusterID string
	KMSKeyArn string
	S3Bucket  string
	name      string
	AWSEntity
}

func (p *Policy) clusterPolicyName() string {
	return fmt.Sprintf("%s-%s", p.ClusterID, PolicyNameTemplate)
}

func (p *Policy) clusterProfileName() string {
	return fmt.Sprintf("%s-%s", p.ClusterID, ProfileNameTemplate)
}

func (p *Policy) clusterRoleName() string {
	return fmt.Sprintf("%s-%s", p.ClusterID, RoleNameTemplate)
}

func (p *Policy) CreateIfNotExists() (bool, error) {
	return false, fmt.Errorf("instance profiles cannot be reused")
}

func (p *Policy) createRole() error {
	// TODO switch to using a file and Go templates
	policyDocument := fmt.Sprintf(PolicyDocumentTempl, p.KMSKeyArn, p.S3Bucket, p.S3Bucket)

	clusterRoleName := fmt.Sprintf("%s-%s", p.ClusterID, RoleNameTemplate)

	if _, err := p.Clients.IAM.CreateRole(&iam.CreateRoleInput{
		RoleName:                 aws.String(clusterRoleName),
		AssumeRolePolicyDocument: aws.String(AssumeRolePolicyDocument),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	clusterPolicyName := fmt.Sprintf("%s-%s", p.ClusterID, PolicyNameTemplate)

	if _, err := p.Clients.IAM.PutRolePolicy(&iam.PutRolePolicyInput{
		PolicyName:     aws.String(clusterPolicyName),
		RoleName:       aws.String(clusterRoleName),
		PolicyDocument: aws.String(policyDocument),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p *Policy) createInstanceProfile() error {
	if _, err := p.Clients.IAM.CreateInstanceProfile(&iam.CreateInstanceProfileInput{
		InstanceProfileName: aws.String(p.clusterProfileName()),
	}); err != nil {
		return microerror.MaskAny(err)
	} else {
		if _, err := p.Clients.IAM.AddRoleToInstanceProfile(&iam.AddRoleToInstanceProfileInput{
			InstanceProfileName: aws.String(p.clusterProfileName()),
			RoleName:            aws.String(p.clusterRoleName()),
		}); err != nil {
			return microerror.MaskAny(err)
		}
	}

	if err := p.Clients.IAM.WaitUntilInstanceProfileExists(&iam.GetInstanceProfileInput{
		InstanceProfileName: aws.String(p.clusterProfileName()),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p *Policy) CreateOrFail() error {
	if err := p.createRole(); err != nil {
		return microerror.MaskAny(err)
	}

	if err := p.createInstanceProfile(); err != nil {
		return microerror.MaskAny(err)
	}

	p.name = p.clusterProfileName()

	return nil
}

func (p *Policy) removeRoleFromInstanceProfile() error {
	if _, err := p.Clients.IAM.RemoveRoleFromInstanceProfile(&iam.RemoveRoleFromInstanceProfileInput{
		InstanceProfileName: aws.String(p.clusterProfileName()),
		RoleName:            aws.String(p.clusterRoleName()),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p *Policy) deleteInstanceProfile() error {
	if _, err := p.Clients.IAM.DeleteInstanceProfile(&iam.DeleteInstanceProfileInput{
		InstanceProfileName: aws.String(p.clusterProfileName()),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p *Policy) deletePolicy() error {
	if _, err := p.Clients.IAM.DeleteRolePolicy(&iam.DeleteRolePolicyInput{
		RoleName:   aws.String(p.clusterRoleName()),
		PolicyName: aws.String(p.clusterPolicyName()),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p *Policy) deleteRole() error {
	if _, err := p.Clients.IAM.DeleteRole(&iam.DeleteRoleInput{
		RoleName: aws.String(p.clusterRoleName()),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p *Policy) Delete() error {
	if err := p.removeRoleFromInstanceProfile(); err != nil {
		return microerror.MaskAny(err)
	}

	if err := p.deleteInstanceProfile(); err != nil {
		return microerror.MaskAny(err)
	}

	if err := p.deletePolicy(); err != nil {
		return microerror.MaskAny(err)
	}

	if err := p.deleteRole(); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p Policy) GetName() string {
	return p.name
}
<commit_msg>Add IAM policy allowing authenticated pull from ECR (#364)<commit_after>package aws

import (
	"fmt"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/iam"
	microerror "github.com/giantswarm/microkit/error"
)

const (
	RoleNameTemplate         = "EC2-K8S-Role"
	PolicyNameTemplate       = "EC2-K8S-Policy"
	ProfileNameTemplate      = "EC2-K8S-Role"
	AssumeRolePolicyDocument = `{
		"Version": "2012-10-17",
		"Statement": {
			"Effect": "Allow",
			"Principal": {
				"Service": "ec2.amazonaws.com"
			},
			"Action": "sts:AssumeRole"
		}
	}`
	PolicyDocumentTempl = `{
		"Version": "2012-10-17",
		"Statement": [
			{
            	"Action": "ec2:*",
            	"Effect": "Allow",
                "Resource": "*"
            },
			{
				"Effect": "Allow",
				"Action": "kms:Decrypt",
				"Resource": %q
			},
			{
				"Effect": "Allow",
				"Action": [
					"s3:GetBucketLocation",
					"s3:ListAllMyBuckets"
				],
				"Resource": "*"
			},
			{
				"Effect": "Allow",
				"Action": [
					"s3:ListBucket"
				],
				"Resource": "arn:aws:s3:::%s"
			},
			{
				"Effect": "Allow",
				"Action": "s3:GetObject",
				"Resource": "arn:aws:s3:::%s/*"
			},
			{
				"Effect": "Allow",
				"Action": [
					"ecr:GetAuthorizationToken",
					"ecr:BatchCheckLayerAvailability",
					"ecr:GetDownloadUrlForLayer",
					"ecr:GetRepositoryPolicy",
					"ecr:DescribeRepositories",
					"ecr:ListImages",
					"ecr:BatchGetImage"
				],
				"Resource": "*"
			}
		]
	}`
)

type Policy struct {
	ClusterID string
	KMSKeyArn string
	S3Bucket  string
	name      string
	AWSEntity
}

func (p *Policy) clusterPolicyName() string {
	return fmt.Sprintf("%s-%s", p.ClusterID, PolicyNameTemplate)
}

func (p *Policy) clusterProfileName() string {
	return fmt.Sprintf("%s-%s", p.ClusterID, ProfileNameTemplate)
}

func (p *Policy) clusterRoleName() string {
	return fmt.Sprintf("%s-%s", p.ClusterID, RoleNameTemplate)
}

func (p *Policy) CreateIfNotExists() (bool, error) {
	return false, fmt.Errorf("instance profiles cannot be reused")
}

func (p *Policy) createRole() error {
	// TODO switch to using a file and Go templates
	policyDocument := fmt.Sprintf(PolicyDocumentTempl, p.KMSKeyArn, p.S3Bucket, p.S3Bucket)

	clusterRoleName := fmt.Sprintf("%s-%s", p.ClusterID, RoleNameTemplate)

	if _, err := p.Clients.IAM.CreateRole(&iam.CreateRoleInput{
		RoleName:                 aws.String(clusterRoleName),
		AssumeRolePolicyDocument: aws.String(AssumeRolePolicyDocument),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	clusterPolicyName := fmt.Sprintf("%s-%s", p.ClusterID, PolicyNameTemplate)

	if _, err := p.Clients.IAM.PutRolePolicy(&iam.PutRolePolicyInput{
		PolicyName:     aws.String(clusterPolicyName),
		RoleName:       aws.String(clusterRoleName),
		PolicyDocument: aws.String(policyDocument),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p *Policy) createInstanceProfile() error {
	if _, err := p.Clients.IAM.CreateInstanceProfile(&iam.CreateInstanceProfileInput{
		InstanceProfileName: aws.String(p.clusterProfileName()),
	}); err != nil {
		return microerror.MaskAny(err)
	} else {
		if _, err := p.Clients.IAM.AddRoleToInstanceProfile(&iam.AddRoleToInstanceProfileInput{
			InstanceProfileName: aws.String(p.clusterProfileName()),
			RoleName:            aws.String(p.clusterRoleName()),
		}); err != nil {
			return microerror.MaskAny(err)
		}
	}

	if err := p.Clients.IAM.WaitUntilInstanceProfileExists(&iam.GetInstanceProfileInput{
		InstanceProfileName: aws.String(p.clusterProfileName()),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p *Policy) CreateOrFail() error {
	if err := p.createRole(); err != nil {
		return microerror.MaskAny(err)
	}

	if err := p.createInstanceProfile(); err != nil {
		return microerror.MaskAny(err)
	}

	p.name = p.clusterProfileName()

	return nil
}

func (p *Policy) removeRoleFromInstanceProfile() error {
	if _, err := p.Clients.IAM.RemoveRoleFromInstanceProfile(&iam.RemoveRoleFromInstanceProfileInput{
		InstanceProfileName: aws.String(p.clusterProfileName()),
		RoleName:            aws.String(p.clusterRoleName()),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p *Policy) deleteInstanceProfile() error {
	if _, err := p.Clients.IAM.DeleteInstanceProfile(&iam.DeleteInstanceProfileInput{
		InstanceProfileName: aws.String(p.clusterProfileName()),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p *Policy) deletePolicy() error {
	if _, err := p.Clients.IAM.DeleteRolePolicy(&iam.DeleteRolePolicyInput{
		RoleName:   aws.String(p.clusterRoleName()),
		PolicyName: aws.String(p.clusterPolicyName()),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p *Policy) deleteRole() error {
	if _, err := p.Clients.IAM.DeleteRole(&iam.DeleteRoleInput{
		RoleName: aws.String(p.clusterRoleName()),
	}); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p *Policy) Delete() error {
	if err := p.removeRoleFromInstanceProfile(); err != nil {
		return microerror.MaskAny(err)
	}

	if err := p.deleteInstanceProfile(); err != nil {
		return microerror.MaskAny(err)
	}

	if err := p.deletePolicy(); err != nil {
		return microerror.MaskAny(err)
	}

	if err := p.deleteRole(); err != nil {
		return microerror.MaskAny(err)
	}

	return nil
}

func (p Policy) GetName() string {
	return p.name
}
<|endoftext|>