<commit_before>package http

import (
	"fmt"
	"net/http"
	"path"
	"runtime"
	"time"

	"github.com/getlantern/flashlight/config"
	"github.com/getlantern/flashlight/util"
	"github.com/getlantern/golog"
	"github.com/getlantern/proxiedsites"
	"github.com/getlantern/tarfs"
	"github.com/gorilla/websocket"
	"github.com/skratchdot/open-golang/open"
)

const (
	UIUrl          = "http://%s"
	LocalUIDir     = "../../../ui/app"
	MaxMessageSize = 1024
)

var (
	log      = golog.LoggerFor("http")
	upgrader = &websocket.Upgrader{ReadBufferSize: 1024, WriteBufferSize: MaxMessageSize}
	UIDir    string
)

type UIServer struct {
	Conn             *websocket.Conn
	ProxiedSites     *proxiedsites.ProxiedSites
	ProxiedSitesChan chan *proxiedsites.Config
	Addr             string
	ConfigUpdates    chan *config.Config
}

// Assume the default directory containing UI assets is
// a sibling directory to the current directory
func init() {
	_, curDir, _, ok := runtime.Caller(1)
	if !ok {
		log.Errorf("Unable to determine current directory")
		return
	}
	UIDir = path.Join(curDir, LocalUIDir)
}

// returns the Proxy auto-config file
func servePacFile(w http.ResponseWriter, r *http.Request) {
	pacFile := proxiedsites.GetPacFile()
	http.ServeFile(w, r, pacFile)
}

func serveHome(r *http.ServeMux) {
	UIDirExists, err := util.DirExists(UIDir)
	if err != nil {
		log.Debugf("UI Directory does not exist %s", err)
	}

	if UIDirExists {
		// UI directory found--serve assets directly from it
		log.Debugf("Serving UI assets from directory %s", UIDir)
		r.Handle("/", http.FileServer(http.Dir(UIDir)))
	} else {
		start := time.Now()
		fs, err := tarfs.New(Resources, "../ui/app")
		if err != nil {
			panic(err)
		}
		delta := time.Now().Sub(start)
		log.Debugf("tarfs startup time: %v", delta)
		r.Handle("/", http.FileServer(fs))
	}
}

// when websocket connection is first opened, we write
// proxied sites (global list + additions) - deletions
// the gorilla websocket module automatically
// chunks messages according to WriteBufferSize
func (srv UIServer) writeGlobalList() {
	initMsg := proxiedsites.Config{
		Additions: srv.ProxiedSites.GetEntries(),
	}
	// write the JSON encoding of the proxied sites to the
	// websocket connection
	if err := srv.Conn.WriteJSON(initMsg); err != nil {
		log.Errorf("Error writing initial proxied sites: %s", err)
	}
}

func (srv UIServer) writeProxiedSites() {
	for {
		// wait for YAML config updates to write to the websocket again
		cfg := <-srv.ConfigUpdates
		log.Debugf("Proxied sites updated in config file; applying changes")
		newPs := proxiedsites.New(cfg.Client.ProxiedSites)

		diff := srv.ProxiedSites.Diff(newPs)
		// write the JSON encoding of the proxied sites to the
		// websocket connection
		if err := srv.Conn.WriteJSON(diff); err != nil {
			log.Errorf("Error writing proxied sites: %s", err)
		}
	}
}

func (srv UIServer) readClientMessage() {
	defer srv.Conn.Close()
	for {
		var updates proxiedsites.Config
		err := srv.Conn.ReadJSON(&updates)
		if err != nil {
			break
		}
		log.Debugf("Received proxied sites update: %+v", &updates)
		srv.ProxiedSites.Update(&updates)
		srv.ProxiedSitesChan <- srv.ProxiedSites.GetConfig()
	}
}

// if the openui flag is specified, the UI is automatically
// opened in the default browser
func OpenUI(shouldOpen bool, uiAddr string) {

	uiAddr = fmt.Sprintf(UIUrl, uiAddr)

	if shouldOpen {
		err := open.Run(uiAddr)
		if err != nil {
			log.Errorf("Could not open UI! %s", err)
		}
	}
}

// handles websocket requests from the client
func (srv UIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var err error
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	// Upgrade with a HTTP request returns a websocket connection
	srv.Conn, err = upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Error(err)
		return
	}
	srv.writeGlobalList()
	// write initial proxied sites list
	go srv.writeProxiedSites()
	srv.readClientMessage()
}

// poll for config updates to the proxiedsites
// with this immediately see flashlight.yaml
// changes in the UI

func (srv UIServer) StartServer() {

	r := http.NewServeMux()
	r.Handle("/data", srv)
	r.HandleFunc("/proxy_on.pac", servePacFile)
	serveHome(r)

	httpServer := &http.Server{
		Addr:    srv.Addr,
		Handler: r,
	}

	log.Debugf("Starting UI HTTP server at %s", srv.Addr)
	go log.Fatal(httpServer.ListenAndServe())
}
<commit_msg>add support for multiple UI instances<commit_after>package http

import (
	"fmt"
	"net/http"
	"path"
	"runtime"
	"time"

	"github.com/getlantern/flashlight/config"
	"github.com/getlantern/flashlight/util"
	"github.com/getlantern/golog"
	"github.com/getlantern/proxiedsites"
	"github.com/getlantern/tarfs"
	"github.com/gorilla/websocket"
	"github.com/skratchdot/open-golang/open"
)

const (
	UIUrl = "http://%s"
	// Assume UI directory to be a sibling directory
	// of flashlight parent dir
	LocalUIDir = "../../../ui/app"
	// Determines the chunking size of messages used by gorilla
	MaxMessageSize = 1024
)

var (
	log      = golog.LoggerFor("http")
	upgrader = &websocket.Upgrader{ReadBufferSize: 1024, WriteBufferSize: MaxMessageSize}
	UIDir    string
)

// represents a UI instance
type Client struct {
	// UI websocket connection
	Conn *websocket.Conn

	// Buffered channel of proxied sites
	msg chan *proxiedsites.Config
}

type UIServer struct {
	connections map[*Client]bool // pool of UI client instances
	Addr        string
	// our current proxied sites instance
	ProxiedSites *proxiedsites.ProxiedSites

	requests         chan *Client
	connClose        chan *Client // handles client disconnects
	ProxiedSitesChan chan *proxiedsites.Config
	ConfigUpdates    chan *config.Config
}

// Assume the default directory containing UI assets is
// a sibling directory to the current directory
func init() {
	_, curDir, _, ok := runtime.Caller(1)
	if !ok {
		log.Errorf("Unable to determine current directory")
		return
	}
	UIDir = path.Join(curDir, LocalUIDir)
}

// returns the Proxy auto-config file
func servePacFile(w http.ResponseWriter, r *http.Request) {
	pacFile := proxiedsites.GetPacFile()
	http.ServeFile(w, r, pacFile)
}

func serveHome(r *http.ServeMux) {
	UIDirExists, err := util.DirExists(UIDir)
	if err != nil {
		log.Debugf("UI Directory does not exist %s", err)
	}

	if UIDirExists {
		// UI directory found--serve assets directly from it
		log.Debugf("Serving UI assets from directory %s", UIDir)
		r.Handle("/", http.FileServer(http.Dir(UIDir)))
	} else {
		start := time.Now()
		fs, err := tarfs.New(Resources, "../ui/app")
		if err != nil {
			panic(err)
		}
		delta := time.Now().Sub(start)
		log.Debugf("tarfs startup time: %v", delta)
		r.Handle("/", http.FileServer(fs))
	}
}

// when websocket connection is first opened, we write
// proxied sites (global list + additions) - deletions
// the gorilla websocket module automatically
// chunks messages according to WriteBufferSize
func (srv UIServer) writeGlobalList(client *Client) {
	initMsg := proxiedsites.Config{
		Additions: srv.ProxiedSites.GetEntries(),
	}
	// write the JSON encoding of the proxied sites to the
	// websocket connection
	if err := client.Conn.WriteJSON(initMsg); err != nil {
		log.Errorf("Error writing initial proxied sites: %s", err)
	}
}

func (srv UIServer) writeProxiedSites(client *Client) {
	defer client.Conn.Close()
	for {
		select {
		case msg, recv := <-client.msg:
			if !recv {
				// write empty message to close connection on error sending
				client.Conn.WriteMessage(websocket.CloseMessage, []byte{})
				return
			}
			if err := client.Conn.WriteJSON(msg); err != nil {
				srv.connClose <- client
				log.Errorf("Error writing proxied sites to UI instance: %s", err)
				return
			}
		}
	}
}

func (srv UIServer) readClientMessage(client *Client) {
	defer func() {
		srv.connClose <- client
		client.Conn.Close()
	}()
	for {
		var updates proxiedsites.Config
		err := client.Conn.ReadJSON(&updates)
		if err != nil {
			break
		}
		log.Debugf("Received proxied sites update from client: %+v", &updates)
		srv.ProxiedSites.Update(&updates)
		srv.ProxiedSitesChan <- srv.ProxiedSites.GetConfig()
	}
}

// if the openui flag is specified, the UI is automatically
// opened in the default browser
func OpenUI(shouldOpen bool, uiAddr string) {

	uiAddr = fmt.Sprintf(UIUrl, uiAddr)

	if shouldOpen {
		err := open.Run(uiAddr)
		if err != nil {
			log.Errorf("Could not open UI! %s", err)
		}
	}
}

// handles websocket requests from the client
func (srv UIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var err error

	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	// Upgrade with a HTTP request returns a websocket connection
	ws, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Error(err)
		return
	}
	client := &Client{Conn: ws, msg: make(chan *proxiedsites.Config)}
	srv.requests <- client
	// write initial proxied sites list
	srv.writeGlobalList(client)
	go srv.writeProxiedSites(client)
	srv.readClientMessage(client)
}

func (srv UIServer) processRequests() {
	for {
		select {
		// wait for YAML config updates
		case cfg := <-srv.ConfigUpdates:
			log.Debugf("Proxied sites updated in config file; applying changes %+v", cfg.Client.ProxiedSites)
			newPs := proxiedsites.New(cfg.Client.ProxiedSites)
			diff := srv.ProxiedSites.Diff(newPs)
			srv.ProxiedSites = newPs
			// write proxied sites update to every UI instance
			for c := range srv.connections {
				select {
				// write the JSON encoding of the proxied sites to the
				// websocket connections
				case c.msg <- diff:
				default:
					close(c.msg)
					delete(srv.connections, c)
				}
			}
		case c := <-srv.requests:
			log.Debug("Adding new UI instance..")
			srv.connections[c] = true
		case c := <-srv.connClose:
			log.Debug("Disconnecting UI instance..")
			if _, ok := srv.connections[c]; ok {
				delete(srv.connections, c)
				close(c.msg)
			}
		}
	}
}

// poll for config updates to the proxiedsites
// with this immediately see flashlight.yaml
// changes in the UI
func (srv UIServer) StartServer() {

	r := http.NewServeMux()

	// initial request, connection close and
	// connection pool for this UI server
	srv.connClose = make(chan *Client)
	srv.requests = make(chan *Client)
	srv.connections = make(map[*Client]bool)

	go srv.processRequests()

	r.Handle("/data", srv)
	r.HandleFunc("/proxy_on.pac", servePacFile)
	serveHome(r)

	log.Debugf("Starting UI HTTP server at %s", srv.Addr)
	httpServer := &http.Server{
		Addr:    srv.Addr,
		Handler: r,
	}

	// Run the UI websocket server asynchronously
	go log.Fatal(http.ListenAndServe(srv.Addr))
}
<|endoftext|>


<commit_before>// Copyright 2013 SteelSeries ApS. All rights reserved.
// No license is given for the use of this source code.

// This package impliments a basic LISP interpretor for embedding in a go program for scripting.
// This file implements json<->lisp conversions

package golisp

import (
    "encoding/json"
    "errors"
    "fmt"
)

func JsonToLisp(json interface{}) (result *Data) {
    mapValue, ok := json.(map[string]interface{})
    if ok {
        var alist *Data
        for key, val := range mapValue {
            value := JsonToLisp(val)
            alist = Acons(StringWithValue(key), value, alist)
        }
        return alist
    }

    arrayValue, ok := json.([]interface{})
    if ok {
        var ary *Data
        for _, val := range arrayValue {
            value := JsonToLisp(val)
            ary = Cons(value, ary)
        }
        return Reverse(ary)
    }

    intValue, ok := json.(float64)
    if ok {
        return NumberWithValue(uint32(intValue))
    }

    strValue, ok := json.(string)
    if ok {
        return StringWithValue(strValue)
    }

    return
}

func JsonStringToLisp(jsonData string) (result *Data) {
    b := []byte(jsonData)
    var data interface{}
    err := json.Unmarshal(b, &data)
    if err != nil {
        panic(errors.New(fmt.Sprintf("Badly formed json: %s", jsonData)))
    }
    return JsonToLisp(data)
}

func LispToJson(d *Data) (result interface{}) {
    if NilP(d) && !AlistP(d) && !PairP(d) {
        return ""
    }

    if NumberP(d) {
        return NumericValue(d)
    }

    if StringP(d) {
        return StringValue(d)
    }

    if PairP(d) {
        ary := make([]interface{}, 0, Length(d))
        for c := d; NotNilP(c); c = Cdr(c) {
            ary = append(ary, LispToJson(Car(c)))
        }
        return ary
    }

    if AlistP(d) {
        dict := make(map[string]interface{}, Length(d))
        for c := d; NotNilP(c); c = Cdr(c) {
            pair := Car(c)
            dict[StringValue(Car(pair))] = LispToJson(Cdr(pair))
        }
        return dict
    }

    return ""
}

func LispToJsonString(d *Data) (result string) {
    temp := LispToJson(d)
    j, err := json.Marshal(temp)
    if err == nil {
        return string(j)
    } else {
        return ""
    }
}

func TransformJson(xform *Data, jsonNode *Data, parentNode *Data) (xformedJson *Data, err error) {
    var transformFunction *Data
    var newData *Data

    args := InternalMakeList(jsonNode, parentNode)
    transformFunction, err = Eval(xform, Global)
    if err != nil {
        return
    }
    _, err = Apply(transformFunction, args, Global)
    if err != nil {
        return
    }
    xformedJson = newData
    return
}
<commit_msg>Added quotes around offending json<commit_after>// Copyright 2013 SteelSeries ApS. All rights reserved.
// No license is given for the use of this source code.

// This package impliments a basic LISP interpretor for embedding in a go program for scripting.
// This file implements json<->lisp conversions

package golisp

import (
    "encoding/json"
    "errors"
    "fmt"
)

func JsonToLisp(json interface{}) (result *Data) {
    mapValue, ok := json.(map[string]interface{})
    if ok {
        var alist *Data
        for key, val := range mapValue {
            value := JsonToLisp(val)
            alist = Acons(StringWithValue(key), value, alist)
        }
        return alist
    }

    arrayValue, ok := json.([]interface{})
    if ok {
        var ary *Data
        for _, val := range arrayValue {
            value := JsonToLisp(val)
            ary = Cons(value, ary)
        }
        return Reverse(ary)
    }

    intValue, ok := json.(float64)
    if ok {
        return NumberWithValue(uint32(intValue))
    }

    strValue, ok := json.(string)
    if ok {
        return StringWithValue(strValue)
    }

    return
}

func JsonStringToLisp(jsonData string) (result *Data) {
    b := []byte(jsonData)
    var data interface{}
    err := json.Unmarshal(b, &data)
    if err != nil {
        panic(errors.New(fmt.Sprintf("Badly formed json: '%s'", jsonData)))
    }
    return JsonToLisp(data)
}

func LispToJson(d *Data) (result interface{}) {
    if NilP(d) && !AlistP(d) && !PairP(d) {
        return ""
    }

    if NumberP(d) {
        return NumericValue(d)
    }

    if StringP(d) {
        return StringValue(d)
    }

    if PairP(d) {
        ary := make([]interface{}, 0, Length(d))
        for c := d; NotNilP(c); c = Cdr(c) {
            ary = append(ary, LispToJson(Car(c)))
        }
        return ary
    }

    if AlistP(d) {
        dict := make(map[string]interface{}, Length(d))
        for c := d; NotNilP(c); c = Cdr(c) {
            pair := Car(c)
            dict[StringValue(Car(pair))] = LispToJson(Cdr(pair))
        }
        return dict
    }

    return ""
}

func LispToJsonString(d *Data) (result string) {
    temp := LispToJson(d)
    j, err := json.Marshal(temp)
    if err == nil {
        return string(j)
    } else {
        return ""
    }
}

func TransformJson(xform *Data, jsonNode *Data, parentNode *Data) (xformedJson *Data, err error) {
    var transformFunction *Data
    var newData *Data

    args := InternalMakeList(jsonNode, parentNode)
    transformFunction, err = Eval(xform, Global)
    if err != nil {
        return
    }
    _, err = Apply(transformFunction, args, Global)
    if err != nil {
        return
    }
    xformedJson = newData
    return
}
<|endoftext|>


<commit_before>package shinylog

import (
	"fmt"
	"io"
	"log"
	"os"
	"strings"
	"sync"
	"syscall"
)

type ShinyLogger struct {
	mu             sync.Mutex
	happyLogger    log.Logger
	errorLogger    log.Logger
	sadLogger      log.Logger
	suppressOutput bool
	disableColor   bool
}

type loggerOptions struct {
	isError, printNewline, includeLocation bool
}

var errorOptions loggerOptions
var stdoutOptions loggerOptions
var stderrOptions loggerOptions

func init() {
	errorOptions = loggerOptions{isError: true, printNewline: true, includeLocation: true}
	stdoutOptions = loggerOptions{isError: false, printNewline: true, includeLocation: false}
	stderrOptions = loggerOptions{isError: false, printNewline: true, includeLocation: false}
}

func NewShinyLogger(out, err interface {
	io.Writer
}) *ShinyLogger {
	happyLogger := log.New(out, "", 0)
	errorLogger := log.New(err, "", 0)
	sadLogger := log.New(err, "", log.Lshortfile)
	var mu sync.Mutex
	return &ShinyLogger{mu, *happyLogger, *errorLogger, *sadLogger, false, false}
}

func NewTraceLogger(out interface {
	io.Writer
}) *log.Logger {
	return log.New(out, "", log.Ldate|log.Ltime|log.Lmicroseconds)
}

const (
	red         = "\x1b[31m"
	green       = "\x1b[32m"
	brightgreen = "\x1b[1;32m"
	yellow      = "\x1b[33m"
	blue        = "\x1b[34m"
	magenta     = "\x1b[35m"
	reset       = "\x1b[0m"
)

var dlm sync.RWMutex
var defaultLogger *ShinyLogger = NewShinyLogger(os.Stdout, os.Stderr)
var traceLogger *log.Logger = nil

func DefaultLogger() *ShinyLogger {
	dlm.RLock()
	defer dlm.RUnlock()
	return defaultLogger
}

func SetDefaultLogger(sl *ShinyLogger) {
	dlm.Lock()
	defaultLogger = sl
	dlm.Unlock()
}

func TraceLogger() *log.Logger {
	dlm.RLock()
	defer dlm.RUnlock()
	return traceLogger
}

func SetTraceLogger(sl *log.Logger) {
	dlm.Lock()
	traceLogger = sl
	dlm.Unlock()
}

func Suppress()                           { DefaultLogger().Suppress() }
func DisableColor()                       { DefaultLogger().DisableColor() }
func Colorized(msg string) (printed bool) { return DefaultLogger().Colorized(msg) }
func Error(err error) bool                { return DefaultLogger().Error(err) }
func FatalError(err error)                { DefaultLogger().FatalError(err) }
func FatalErrorString(msg string)         { DefaultLogger().FatalErrorString(msg) }
func ErrorString(msg string) bool         { return DefaultLogger().ErrorString(msg) }
func StdErrorString(msg string) bool      { return DefaultLogger().StdErrorString(msg) }
func Red(msg string) bool                 { return DefaultLogger().Red(msg) }
func Green(msg string) bool               { return DefaultLogger().Green(msg) }
func Brightgreen(msg string) bool         { return DefaultLogger().Brightgreen(msg) }
func Yellow(msg string) bool              { return DefaultLogger().Yellow(msg) }
func Blue(msg string) bool                { return DefaultLogger().Blue(msg) }
func Magenta(msg string) bool             { return DefaultLogger().Magenta(msg) }

func TraceEnabled() bool {
	return TraceLogger() != nil
}

func Trace(format string, v ...interface{}) bool {
	if TraceEnabled() {
		TraceLogger().Printf(format, v...)
		return true
	}
	return false
}

func (l *ShinyLogger) Suppress() {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.suppressOutput = true
}

func (l *ShinyLogger) DisableColor() {
	l.disableColor = true
}

func (l *ShinyLogger) Colorized(msg string) (printed bool) {
	return l.colorized(3, msg, stdoutOptions)
}

func (l *ShinyLogger) ColorizedSansNl(msg string) (printed bool) {
	return l.colorized(3, msg, loggerOptions{isError: false, printNewline: false, includeLocation: false})
}

// If we send SIGTERM rather than explicitly exiting,
// the signal can be handled and the master can clean up.
// This is a workaround for Go not having `atexit` :(.
func terminate() {
	proc, _ := os.FindProcess(os.Getpid())
	proc.Signal(syscall.SIGTERM)
}

func (l *ShinyLogger) FatalErrorString(msg string) {
	l.colorized(3, "{red}"+msg, errorOptions)
	terminate()
}

func (l *ShinyLogger) FatalError(err error) {
	l.colorized(3, "{red}"+err.Error(), errorOptions)
	terminate()
}

func (l *ShinyLogger) Error(err error) bool {
	return l.colorized(3, "{red}"+err.Error(), errorOptions)
}

func (l *ShinyLogger) ErrorString(msg string) bool {
	return l.colorized(3, "{red}"+msg, errorOptions)
}

func (l *ShinyLogger) StdErrorString(msg string) bool {
	return l.colorized(3, "{red}"+msg, stderrOptions)
}

func (l *ShinyLogger) Red(msg string) bool {
	return l.colorized(3, "{red}"+msg, stdoutOptions)
}

func (l *ShinyLogger) Green(msg string) bool {
	return l.colorized(3, "{green}"+msg, stdoutOptions)
}

func (l *ShinyLogger) Brightgreen(msg string) bool {
	return l.colorized(3, "{brightgreen}"+msg, stdoutOptions)
}

func (l *ShinyLogger) Yellow(msg string) bool {
	return l.colorized(3, "{yellow}"+msg, stdoutOptions)
}

func (l *ShinyLogger) Blue(msg string) bool {
	return l.colorized(3, "{blue}"+msg, stdoutOptions)
}

func (l *ShinyLogger) Magenta(msg string) bool {
	return l.colorized(3, "{magenta}"+msg, stdoutOptions)
}

func (l *ShinyLogger) formatColors(msg string) string {
	if l.disableColor {
		msg = strings.Replace(msg, "{red}", "", -1)
		msg = strings.Replace(msg, "{green}", "", -1)
		msg = strings.Replace(msg, "{brightgreen}", "", -1)
		msg = strings.Replace(msg, "{yellow}", "", -1)
		msg = strings.Replace(msg, "{blue}", "", -1)
		msg = strings.Replace(msg, "{magenta}", "", -1)
		msg = strings.Replace(msg, "{reset}", "", -1)
	} else {
		msg = strings.Replace(msg, "{red}", red, -1)
		msg = strings.Replace(msg, "{green}", green, -1)
		msg = strings.Replace(msg, "{brightgreen}", brightgreen, -1)
		msg = strings.Replace(msg, "{yellow}", yellow, -1)
		msg = strings.Replace(msg, "{blue}", blue, -1)
		msg = strings.Replace(msg, "{magenta}", magenta, -1)
		msg = strings.Replace(msg, "{reset}", reset, -1)
	}
	return msg
}

func (l *ShinyLogger) colorized(callDepth int, msg string, options loggerOptions) (printed bool) {
	l.mu.Lock()
	defer l.mu.Unlock()

	if !l.suppressOutput {
		msg = l.formatColors(msg)

		if l == DefaultLogger() {
			callDepth += 1 // this was called through a proxy method
		}
		if options.isError {
			if options.includeLocation {
				l.sadLogger.Output(callDepth, msg+reset)
			} else {
				l.errorLogger.Output(callDepth, msg+reset)
			}
		} else {
			if options.printNewline {
				fmt.Println(msg + reset)
			} else {
				fmt.Print(msg + reset)
			}
		}
	}
	return !l.suppressOutput
}
<commit_msg>remove unused happyLogger<commit_after>package shinylog

import (
	"fmt"
	"io"
	"log"
	"os"
	"strings"
	"sync"
	"syscall"
)

type ShinyLogger struct {
	mu                  sync.Mutex
	errorLogger         log.Logger
	locationErrorLogger log.Logger
	suppressOutput      bool
	disableColor        bool
}

type loggerOptions struct {
	isError, printNewline, includeLocation bool
}

var errorOptions loggerOptions
var stdoutOptions loggerOptions
var stderrOptions loggerOptions

func init() {
	errorOptions = loggerOptions{isError: true, printNewline: true, includeLocation: true}
	stdoutOptions = loggerOptions{isError: false, printNewline: true, includeLocation: false}
	stderrOptions = loggerOptions{isError: false, printNewline: true, includeLocation: false}
}

func NewShinyLogger(out, err interface {
	io.Writer
}) *ShinyLogger {
	errorLogger := log.New(err, "", 0)
	locationErrorLogger := log.New(err, "", log.Lshortfile)
	var mu sync.Mutex
	return &ShinyLogger{mu, *errorLogger, *locationErrorLogger, false, false}
}

func NewTraceLogger(out interface {
	io.Writer
}) *log.Logger {
	return log.New(out, "", log.Ldate|log.Ltime|log.Lmicroseconds)
}

const (
	red         = "\x1b[31m"
	green       = "\x1b[32m"
	brightgreen = "\x1b[1;32m"
	yellow      = "\x1b[33m"
	blue        = "\x1b[34m"
	magenta     = "\x1b[35m"
	reset       = "\x1b[0m"
)

var dlm sync.RWMutex
var defaultLogger *ShinyLogger = NewShinyLogger(os.Stdout, os.Stderr)
var traceLogger *log.Logger = nil

func DefaultLogger() *ShinyLogger {
	dlm.RLock()
	defer dlm.RUnlock()
	return defaultLogger
}

func SetDefaultLogger(sl *ShinyLogger) {
	dlm.Lock()
	defaultLogger = sl
	dlm.Unlock()
}

func TraceLogger() *log.Logger {
	dlm.RLock()
	defer dlm.RUnlock()
	return traceLogger
}

func SetTraceLogger(sl *log.Logger) {
	dlm.Lock()
	traceLogger = sl
	dlm.Unlock()
}

func Suppress()                           { DefaultLogger().Suppress() }
func DisableColor()                       { DefaultLogger().DisableColor() }
func Colorized(msg string) (printed bool) { return DefaultLogger().Colorized(msg) }
func Error(err error) bool                { return DefaultLogger().Error(err) }
func FatalError(err error)                { DefaultLogger().FatalError(err) }
func FatalErrorString(msg string)         { DefaultLogger().FatalErrorString(msg) }
func ErrorString(msg string) bool         { return DefaultLogger().ErrorString(msg) }
func StdErrorString(msg string) bool      { return DefaultLogger().StdErrorString(msg) }
func Red(msg string) bool                 { return DefaultLogger().Red(msg) }
func Green(msg string) bool               { return DefaultLogger().Green(msg) }
func Brightgreen(msg string) bool         { return DefaultLogger().Brightgreen(msg) }
func Yellow(msg string) bool              { return DefaultLogger().Yellow(msg) }
func Blue(msg string) bool                { return DefaultLogger().Blue(msg) }
func Magenta(msg string) bool             { return DefaultLogger().Magenta(msg) }

func TraceEnabled() bool {
	return TraceLogger() != nil
}

func Trace(format string, v ...interface{}) bool {
	if TraceEnabled() {
		TraceLogger().Printf(format, v...)
		return true
	}
	return false
}

func (l *ShinyLogger) Suppress() {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.suppressOutput = true
}

func (l *ShinyLogger) DisableColor() {
	l.disableColor = true
}

func (l *ShinyLogger) Colorized(msg string) (printed bool) {
	return l.colorized(3, msg, stdoutOptions)
}

func (l *ShinyLogger) ColorizedSansNl(msg string) (printed bool) {
	return l.colorized(3, msg, loggerOptions{isError: false, printNewline: false, includeLocation: false})
}

// If we send SIGTERM rather than explicitly exiting,
// the signal can be handled and the master can clean up.
// This is a workaround for Go not having `atexit` :(.
func terminate() {
	proc, _ := os.FindProcess(os.Getpid())
	proc.Signal(syscall.SIGTERM)
}

func (l *ShinyLogger) FatalErrorString(msg string) {
	l.colorized(3, "{red}"+msg, errorOptions)
	terminate()
}

func (l *ShinyLogger) FatalError(err error) {
	l.colorized(3, "{red}"+err.Error(), errorOptions)
	terminate()
}

func (l *ShinyLogger) Error(err error) bool {
	return l.colorized(3, "{red}"+err.Error(), errorOptions)
}

func (l *ShinyLogger) ErrorString(msg string) bool {
	return l.colorized(3, "{red}"+msg, errorOptions)
}

func (l *ShinyLogger) StdErrorString(msg string) bool {
	return l.colorized(3, "{red}"+msg, stderrOptions)
}

func (l *ShinyLogger) Red(msg string) bool {
	return l.colorized(3, "{red}"+msg, stdoutOptions)
}

func (l *ShinyLogger) Green(msg string) bool {
	return l.colorized(3, "{green}"+msg, stdoutOptions)
}

func (l *ShinyLogger) Brightgreen(msg string) bool {
	return l.colorized(3, "{brightgreen}"+msg, stdoutOptions)
}

func (l *ShinyLogger) Yellow(msg string) bool {
	return l.colorized(3, "{yellow}"+msg, stdoutOptions)
}

func (l *ShinyLogger) Blue(msg string) bool {
	return l.colorized(3, "{blue}"+msg, stdoutOptions)
}

func (l *ShinyLogger) Magenta(msg string) bool {
	return l.colorized(3, "{magenta}"+msg, stdoutOptions)
}

func (l *ShinyLogger) formatColors(msg string) string {
	if l.disableColor {
		msg = strings.Replace(msg, "{red}", "", -1)
		msg = strings.Replace(msg, "{green}", "", -1)
		msg = strings.Replace(msg, "{brightgreen}", "", -1)
		msg = strings.Replace(msg, "{yellow}", "", -1)
		msg = strings.Replace(msg, "{blue}", "", -1)
		msg = strings.Replace(msg, "{magenta}", "", -1)
		msg = strings.Replace(msg, "{reset}", "", -1)
	} else {
		msg = strings.Replace(msg, "{red}", red, -1)
		msg = strings.Replace(msg, "{green}", green, -1)
		msg = strings.Replace(msg, "{brightgreen}", brightgreen, -1)
		msg = strings.Replace(msg, "{yellow}", yellow, -1)
		msg = strings.Replace(msg, "{blue}", blue, -1)
		msg = strings.Replace(msg, "{magenta}", magenta, -1)
		msg = strings.Replace(msg, "{reset}", reset, -1)
	}
	return msg
}

func (l *ShinyLogger) colorized(callDepth int, msg string, options loggerOptions) bool {
	l.mu.Lock()
	defer l.mu.Unlock()

	if !l.suppressOutput {
		msg = l.formatColors(msg)

		if l == DefaultLogger() {
			callDepth += 1 // this was called through a proxy method
		}
		if options.isError {
			if options.includeLocation {
				l.locationErrorLogger.Output(callDepth, msg+reset)
			} else {
				l.errorLogger.Output(callDepth, msg+reset)
			}
		} else {
			if options.printNewline {
				fmt.Println(msg + reset)
			} else {
				fmt.Print(msg + reset)
			}
		}
	}
	return !l.suppressOutput
}
<|endoftext|>


<commit_before>// Copyright 2017 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package systests

import (
	"context"
	"fmt"
	"strings"
	"testing"

	"github.com/keybase/client/go/git"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/client/go/teams"
	"github.com/stretchr/testify/require"
)

func TestGitTeamer(t *testing.T) {
	tt := newTeamTester(t)
	defer tt.cleanup()

	alice := tt.addUser("abc")
	g := tt.users[0].tc.G

	teamer := git.NewTeamer(g)

	t.Logf("team that doesn't exist")
	res, err := teamer.LookupOrCreate(context.Background(), keybase1.Folder{
		Name:       "notateamxxx",
		Private:    true,
		FolderType: keybase1.FolderType_TEAM,
	})
	require.Error(t, err)
	require.IsType(t, teams.TeamDoesNotExistError{}, err, "%v", err)

	t.Logf("team that exists")
	teamID, teamName := tt.users[0].createTeam2()
	res, err = teamer.LookupOrCreate(context.Background(), keybase1.Folder{
		Name:       teamName.String(),
		Private:    true,
		FolderType: keybase1.FolderType_TEAM,
	})
	require.NoError(t, err)
	require.Equal(t, res.TeamID, teamID)
	require.Equal(t, res.Visibility, keybase1.TLFVisibility_PRIVATE)

	t.Logf("public team")
	teamID, teamName = tt.users[0].createTeam2()
	res, err = teamer.LookupOrCreate(context.Background(), keybase1.Folder{
		Name:       teamName.String(),
		Private:    false,
		FolderType: keybase1.FolderType_TEAM,
	})
	require.Error(t, err)
	require.Regexp(t, `not supported`, err.Error())

	for _, public := range []bool{false, true} {
		t.Logf("public:%v", public)

		visibility := keybase1.TLFVisibility_PRIVATE
		if public {
			visibility = keybase1.TLFVisibility_PUBLIC
		}

		folderType := keybase1.FolderType_PRIVATE
		if public {
			folderType = keybase1.FolderType_PUBLIC
		}

		t.Logf("iteam that doesn't exist (gets created)")
		bob := tt.addUser("bob")
		gil := tt.addUser("gil")
		frag := fmt.Sprintf("%v,%v#%v", alice.username, bob.username, gil.username)
		res, err = teamer.LookupOrCreate(context.Background(), keybase1.Folder{
			Name:       frag,
			Private:    !public,
			FolderType: folderType,
		})
		require.NoError(t, err)
		expectedTeamID, _, _, err := teams.LookupImplicitTeam(context.Background(), g, frag, public)
		require.NoError(t, err)
		require.Equal(t, public, expectedTeamID.IsPublic())
		require.Equal(t, expectedTeamID, res.TeamID, "teamer should have created a team that was then looked up")
		require.Equal(t, visibility, res.Visibility)

		t.Logf("iteam that already exists")
		bob = tt.addUser("bob")
		gil = tt.addUser("gil")
		frag = fmt.Sprintf("%v,%v#%v", alice.username, bob.username, gil.username)
		teamID, _, _, err = teams.LookupOrCreateImplicitTeam(context.Background(), g, frag, public)
		require.NoError(t, err)
		require.Equal(t, public, teamID.IsPublic())
		res, err = teamer.LookupOrCreate(context.Background(), keybase1.Folder{
			Name:       frag,
			Private:    !public,
			FolderType: folderType,
		})
		require.NoError(t, err)
		require.Equal(t, res.TeamID, teamID, "teamer should return the same team that was created earlier")
		require.Equal(t, visibility, res.Visibility)

		t.Logf("iteam conflict")
		alice.drainGregor()
		bob = tt.addUser("bob")
		iTeamNameCreate1 := strings.Join([]string{alice.username, bob.username}, ",")
		iTeamNameCreate2 := strings.Join([]string{alice.username, bob.username + "@rooter"}, ",")
		_, _, _, err = teams.LookupOrCreateImplicitTeam(context.TODO(), g, iTeamNameCreate1, public)
		require.NoError(t, err)
		iTeamID2, _, _, err := teams.LookupOrCreateImplicitTeam(context.TODO(), g, iTeamNameCreate2, public)
		require.NoError(t, err)
		require.Equal(t, public, iTeamID2.IsPublic())
		t.Logf("prove to create the conflict")
		bob.proveRooter()
		alice.waitForTeamIDChangedGregor(iTeamID2, alice.getTeamSeqno(iTeamID2)+1)
		t.Logf("find out the conflict suffix")
		_, _, _, conflicts, err := teams.LookupImplicitTeamAndConflicts(context.TODO(), g, iTeamNameCreate1, public)
		require.NoError(t, err)
		require.Len(t, conflicts, 1)
		t.Logf("check")
		res, err = teamer.LookupOrCreate(context.Background(), keybase1.Folder{
			Name:       iTeamNameCreate1 + " " + libkb.FormatImplicitTeamDisplayNameSuffix(conflicts[0]),
			Private:    !public,
			FolderType: folderType,
		})
		require.NoError(t, err)
		require.Equal(t, res.TeamID, iTeamID2, "teamer should return the old conflicted team")
		require.Equal(t, visibility, res.Visibility)
	}
}
<commit_msg>change how TestGitTeamer waits<commit_after>// Copyright 2017 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package systests

import (
	"context"
	"fmt"
	"strings"
	"testing"
	"time"

	"github.com/keybase/client/go/git"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/client/go/teams"
	"github.com/stretchr/testify/require"
)

func TestGitTeamer(t *testing.T) {
	tt := newTeamTester(t)
	defer tt.cleanup()

	alice := tt.addUser("abc")
	g := tt.users[0].tc.G

	teamer := git.NewTeamer(g)

	t.Logf("team that doesn't exist")
	res, err := teamer.LookupOrCreate(context.Background(), keybase1.Folder{
		Name:       "notateamxxx",
		Private:    true,
		FolderType: keybase1.FolderType_TEAM,
	})
	require.Error(t, err)
	require.IsType(t, teams.TeamDoesNotExistError{}, err, "%v", err)

	t.Logf("team that exists")
	teamID, teamName := tt.users[0].createTeam2()
	res, err = teamer.LookupOrCreate(context.Background(), keybase1.Folder{
		Name:       teamName.String(),
		Private:    true,
		FolderType: keybase1.FolderType_TEAM,
	})
	require.NoError(t, err)
	require.Equal(t, res.TeamID, teamID)
	require.Equal(t, res.Visibility, keybase1.TLFVisibility_PRIVATE)

	t.Logf("public team")
	teamID, teamName = tt.users[0].createTeam2()
	res, err = teamer.LookupOrCreate(context.Background(), keybase1.Folder{
		Name:       teamName.String(),
		Private:    false,
		FolderType: keybase1.FolderType_TEAM,
	})
	require.Error(t, err)
	require.Regexp(t, `not supported`, err.Error())

	for _, public := range []bool{false, true} {
		t.Logf("public:%v", public)

		visibility := keybase1.TLFVisibility_PRIVATE
		if public {
			visibility = keybase1.TLFVisibility_PUBLIC
		}

		folderType := keybase1.FolderType_PRIVATE
		if public {
			folderType = keybase1.FolderType_PUBLIC
		}

		t.Logf("iteam that doesn't exist (gets created)")
		bob := tt.addUser("bob")
		gil := tt.addUser("gil")
		frag := fmt.Sprintf("%v,%v#%v", alice.username, bob.username, gil.username)
		res, err = teamer.LookupOrCreate(context.Background(), keybase1.Folder{
			Name:       frag,
			Private:    !public,
			FolderType: folderType,
		})
		require.NoError(t, err)
		expectedTeamID, _, _, err := teams.LookupImplicitTeam(context.Background(), g, frag, public)
		require.NoError(t, err)
		require.Equal(t, public, expectedTeamID.IsPublic())
		require.Equal(t, expectedTeamID, res.TeamID, "teamer should have created a team that was then looked up")
		require.Equal(t, visibility, res.Visibility)

		t.Logf("iteam that already exists")
		bob = tt.addUser("bob")
		gil = tt.addUser("gil")
		frag = fmt.Sprintf("%v,%v#%v", alice.username, bob.username, gil.username)
		teamID, _, _, err = teams.LookupOrCreateImplicitTeam(context.Background(), g, frag, public)
		require.NoError(t, err)
		require.Equal(t, public, teamID.IsPublic())
		res, err = teamer.LookupOrCreate(context.Background(), keybase1.Folder{
			Name:       frag,
			Private:    !public,
			FolderType: folderType,
		})
		require.NoError(t, err)
		require.Equal(t, res.TeamID, teamID, "teamer should return the same team that was created earlier")
		require.Equal(t, visibility, res.Visibility)

		t.Logf("iteam conflict")
		alice.drainGregor()
		bob = tt.addUser("bob")
		iTeamNameCreate1 := strings.Join([]string{alice.username, bob.username}, ",")
		iTeamNameCreate2 := strings.Join([]string{alice.username, bob.username + "@rooter"}, ",")
		_, _, _, err = teams.LookupOrCreateImplicitTeam(context.TODO(), g, iTeamNameCreate1, public)
		require.NoError(t, err)
		iTeamID2, _, _, err := teams.LookupOrCreateImplicitTeam(context.TODO(), g, iTeamNameCreate2, public)
		require.NoError(t, err)
		require.Equal(t, public, iTeamID2.IsPublic())

		t.Logf("prove to create the conflict")
		bob.proveRooter()

		t.Logf("wait for someone to add bob")
		pollForConditionWithTimeout(t, 20*time.Second, "bob to be added to the team after rooter proof", func(ctx context.Context) bool {
			team, err := teams.Load(ctx, alice.tc.G, keybase1.LoadTeamArg{
				ID:          iTeamID2,
				Public:      public,
				ForceRepoll: true,
			})
			require.NoError(t, err)
			role, err := team.MemberRole(ctx, bob.userVersion())
			require.NoError(t, err)
			return role != keybase1.TeamRole_NONE
		})

		t.Logf("find out the conflict suffix")
		_, _, _, conflicts, err := teams.LookupImplicitTeamAndConflicts(context.TODO(), g, iTeamNameCreate1, public)
		require.NoError(t, err)
		require.Len(t, conflicts, 1)
		t.Logf("check")
		res, err = teamer.LookupOrCreate(context.Background(), keybase1.Folder{
			Name:       iTeamNameCreate1 + " " + libkb.FormatImplicitTeamDisplayNameSuffix(conflicts[0]),
			Private:    !public,
			FolderType: folderType,
		})
		require.NoError(t, err)
		require.Equal(t, res.TeamID, iTeamID2, "teamer should return the old conflicted team")
		require.Equal(t, visibility, res.Visibility)
	}
}
<|endoftext|>


<commit_before>package main

import "flag"
import "fmt"
import "os"

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

import "strings"

type Request struct {
	id int
	access_time int
	ip_address string
	url string
	cookes string
	user_agent string
	referer string
}

func partition(s string, sep string) (string, string, string) {
	parts := strings.SplitN(s, sep, 2)
	if len(parts) == 1 {
		return parts[0], "", ""
	}
	return parts[0], sep, parts[1]
}

func connectDb(fulldsn string) *sql.DB {
	dbtype, _, dsn := partition(fulldsn, ":")
	db, err := sql.Open(dbtype, dsn)
	if err != nil {
		panic(err.Error())
	}
	err = db.Ping()
	if err != nil {
		panic(err.Error())
	}
	return db
}

// Creates an analysis table and returns whether the table was already present and its final name.
func makeTable(name string, definitions string) (bool, string) {
	tableName := "analysis_" + name
	sql := "CREATE TABLE " + tableName + " " + definitions;
	println("TODO" + sql)

	return false, tableName
}

func allRequests() <- chan Request {
	res := make(chan Request)
	return res
}

// Map from user name to user id
func userIds(db *sql.DB) map[string]int {
	rows, err := db.Query("SELECT id, user_name FROM user")
	if err != nil {
		panic(err.Error())
	}

	res := map[string]int{}
	for rows.Next() {
		var id int
		var name string

		err = rows.Scan(&id, &name)
		if err != nil {
			panic(err.Error())
		}
		res[name] = id
	}
	return res
}

func tagRequestUsers(db *sql.DB) {
	user_ids := userIds(db)
	fmt.Println(user_ids)

	/*
	done, tableName := makeTable("request_users", "INT request_id, INT user_id")
	if (done) {
		return
	}
	println(tableName)

	stmtIns, err := db.Prepare("INSERT INTO squareNum VALUES( ?, ? )")
	if err != nil {
		panic(err.Error())
	}
	defer stmtIns.Close()*/

}

func main() {
	fulldsn := flag.String("dsn", "mysql:normsetzung@/normsetzung", "The database connection string")
	flag.Parse()

	positional_args := flag.Args()
	if len(positional_args) < 1 {
		println("No action specified")
		flag.Usage()
		os.Exit(2)
	}
	action := positional_args[0]

	db := connectDb(*fulldsn)
	defer db.Close()

	switch action {
	case "tagRequestUsers":
		tagRequestUsers(db)
	default:
		fmt.Fprintf(os.Stderr, "Unknown action %s\n", action)
		os.Exit(2)
	}
}
<commit_msg>Proper request parsing<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"
)

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

type Request struct {
	id int
	access_time int64
	ip_address string
	request_url string
	cookies string
	user_agent string
	referer string
}

func partition(s string, sep string) (string, string, string) {
	parts := strings.SplitN(s, sep, 2)
	if len(parts) == 1 {
		return parts[0], "", ""
	}
	return parts[0], sep, parts[1]
}

func connectDb(fulldsn string) *sql.DB {
	dbtype, _, dsn := partition(fulldsn, ":")
	db, err := sql.Open(dbtype, dsn)
	if err != nil {
		panic(err.Error())
	}
	err = db.Ping()
	if err != nil {
		panic(err.Error())
	}
	return db
}

// Creates an analysis table and returns whether the table was already present and its final name.
func makeTable(name string, definitions string) (bool, string) {
	tableName := "analysis_" + name
	sql := "CREATE TABLE " + tableName + " " + definitions;
	println("TODO" + sql)

	return false, tableName
}

func allRequests(db *sql.DB) <-chan Request {
	c := make(chan Request, 1000)
	go func() {
		rows, err := db.Query("SELECT id, access_time, ip_address, request_url, cookies, user_agent, referer FROM requestlog")
		if err != nil {
			panic(err.Error())
		}
		for rows.Next() {
			var req Request
			var datestr string
			var user_agent sql.NullString
			var referer sql.NullString
			var cookies sql.NullString

			err = rows.Scan(&req.id, &datestr, &req.ip_address, &req.request_url, &cookies, &user_agent, &referer)
			if err != nil {
				panic(err.Error())
			}
			if user_agent.Valid {
				req.user_agent = user_agent.String
			} else {
				req.user_agent = "(unspecified)"
			}
			if referer.Valid {
				req.referer = referer.String
			} else {
				req.referer = "(none)"
			}
			if cookies.Valid {
				req.cookies = cookies.String
			} else {
				req.cookies = "(none)"
			}
			t, err := time.Parse("2006-01-02 15:04:05", datestr)
			if err != nil {
				panic(err.Error())
			}
			req.access_time = t.Unix()
			c <- req
		}
		close(c)
	} ()

	return c
}

// Map from user name to user id
func getUserIds(db *sql.DB) map[string]int {
	rows, err := db.Query("SELECT id, user_name FROM user")
	if err != nil {
		panic(err.Error())
	}

	res := map[string]int{}
	for rows.Next() {
		var id int
		var name string

		err = rows.Scan(&id, &name)
		if err != nil {
			panic(err.Error())
		}
		res[name] = id
	}
	return res
}

func tagRequestUsers(db *sql.DB) {
	userIds := getUserIds(db)

	for req := range allRequests(db) {
		fmt.Println(req)
	}

	println(userIds) // TODO do something with them
	/*
	done, tableName := makeTable("request_users", "INT request_id, INT user_id")
	if (done) {
		return
	}
	println(tableName)

	stmtIns, err := db.Prepare("INSERT INTO squareNum VALUES( ?, ? )")
	if err != nil {
		panic(err.Error())
	}
	defer stmtIns.Close()*/

}

func main() {
	fulldsn := flag.String("dsn", "mysql:normsetzung@/normsetzung", "The database connection string")
	flag.Parse()

	positional_args := flag.Args()
	if len(positional_args) < 1 {
		println("No action specified")
		flag.Usage()
		os.Exit(2)
	}
	action := positional_args[0]

	db := connectDb(*fulldsn)
	defer db.Close()

	switch action {
	case "tagRequestUsers":
		tagRequestUsers(db)
	default:
		fmt.Fprintf(os.Stderr, "Unknown action %s\n", action)
		os.Exit(2)
	}
}
<|endoftext|>


<commit_before>package renderweb

import (
	"bytes"
	"net/http"
	"reflect"
	"testing"

	"github.com/rs/xhandler"
	"golang.org/x/net/context"
	"gopkg.in/yaml.v2"

	"bitbucket.org/moovie/util/template"

	"github.com/crackcomm/renderer/components"
	"github.com/crackcomm/renderer/web"
)

var data = `
GET /test/:test_id:
  component:
    name: dashboard.components
    context:
      components:
      - name: test1
      - name: test2
      - name: test3
  middlewares:
  - name: my_test_middleware
    opts:
      opts1: test_value
`

var expected = Routes{
	Route{Method: "GET", Path: "/test/:test_id"}: Handler{
		Component: components.Component{
			Name: "dashboard.components",
			Context: template.Context{
				"components": []interface{}{
					map[interface{}]interface{}{"name": "test1"},
					map[interface{}]interface{}{"name": "test2"},
					map[interface{}]interface{}{"name": "test3"},
				},
			},
		},
		Middlewares: []Middleware{
			{
				Name: "my_test_middleware",
				Opts: map[string]interface{}{"opts1": "test_value"},
			},
		},
	},
}

func TestRoutesUnmarshal(t *testing.T) {
	RegisterMiddleware(MiddlewareDescriptor{
		Name: "my_test_middleware",
	}, func(o Options) (web.Middleware, error) {
		return func(next xhandler.HandlerC) xhandler.HandlerC {
			return xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
				ctx = components.WithTemplateKey(ctx, "some1", "test1")
				ctx = components.WithTemplateKey(ctx, "some2", "test2")
				next.ServeHTTPC(ctx, w, r)
			})
		}, nil
	})

	m := make(yamlRoutes)
	err := yaml.Unmarshal([]byte(data), &m)
	if err != nil {
		t.Fatal(err)
	}

	r, err := m.toRoutes()
	if err != nil {
		t.Fatal(err)
	}

	if !reflect.DeepEqual(r, expected) {
		t.Errorf("Got: \n%#v\n Expected: \n%#v\n", r, expected)
	}

	t.Logf("Got: %#v", r)

	_, err = r.Construct()
	if err != nil {
		t.Fatal(err)
	}
}

func TestRoutesYamlMarshal(t *testing.T) {
	m := make(yamlRoutes)
	err := yaml.Unmarshal([]byte(data), &m)
	if err != nil {
		t.Fatal(err)
	}

	d, err := yaml.Marshal(&m)
	if err != nil {
		t.Fatal(err)
	}

	if !bytes.Equal(bytes.TrimSpace(d), bytes.TrimSpace([]byte(data))) {
		t.Errorf("Got: \n%s\n", d)
	}
}
<commit_msg>renderweb: fix tests<commit_after>package renderweb

import (
	"bytes"
	"net/http"
	"reflect"
	"testing"

	"github.com/rs/xhandler"
	"golang.org/x/net/context"
	"gopkg.in/yaml.v2"

	"bitbucket.org/moovie/util/template"

	"github.com/crackcomm/renderer/components"
	"github.com/crackcomm/renderer/middlewares"
)

var data = `
GET /test/:test_id:
  component:
    name: dashboard.components
    context:
      components:
      - name: test1
      - name: test2
      - name: test3
  middlewares:
  - name: my_test_middleware
    options:
      opts1: test_value
`

var expected = Routes{
	Route{Method: "GET", Path: "/test/:test_id"}: &Handler{
		Component: &components.Component{
			Name: "dashboard.components",
			Context: template.Context{
				"components": []interface{}{
					map[interface{}]interface{}{"name": "test1"},
					map[interface{}]interface{}{"name": "test2"},
					map[interface{}]interface{}{"name": "test3"},
				},
			},
		},
		Middlewares: []*middlewares.Middleware{
			{
				Name:    "my_test_middleware",
				Options: middlewares.Options{"opts1": "test_value"},
			},
		},
	},
}

func TestRoutesUnmarshal(t *testing.T) {
	middlewares.Register(middlewares.Descriptor{
		Name: "my_test_middleware",
	}, func(o middlewares.Options) (middlewares.Handler, error) {
		return ToMiddleware(func(ctx context.Context, w http.ResponseWriter, r *http.Request, next xhandler.HandlerC) {
			ctx = components.WithTemplateKey(ctx, "some1", "test1")
			ctx = components.WithTemplateKey(ctx, "some2", "test2")
			next.ServeHTTPC(ctx, w, r)
		}), nil
	})

	m := make(routesFile)
	err := yaml.Unmarshal([]byte(data), &m)
	if err != nil {
		t.Fatal(err)
	}

	r, err := m.toRoutes()
	if err != nil {
		t.Fatal(err)
	}

	if !reflect.DeepEqual(r, expected) {
		t.Errorf("Got: \n%#v\n Expected: \n%#v\n", r, expected)
	}

	t.Logf("Got: %#v", r)

	_, err = r.Construct()
	if err != nil {
		t.Fatal(err)
	}
}

func TestRoutesYamlMarshal(t *testing.T) {
	m := make(routesFile)
	err := yaml.Unmarshal([]byte(data), &m)
	if err != nil {
		t.Fatal(err)
	}

	d, err := yaml.Marshal(&m)
	if err != nil {
		t.Fatal(err)
	}

	if !bytes.Equal(bytes.TrimSpace(d), bytes.TrimSpace([]byte(data))) {
		t.Errorf("Got: \n%s\n", d)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"

	"github.com/Cox-Automotive/alks-go"
	"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func resourceAlksIamRole() *schema.Resource {
	return &schema.Resource{
		CreateContext: resourceAlksIamRoleCreate,
		ReadContext:   resourceAlksIamRoleRead,
		UpdateContext: resourceAlksIamRoleUpdate,
		DeleteContext: resourceAlksIamRoleDelete,
		Importer: &schema.ResourceImporter{
			StateContext: schema.ImportStatePassthroughContext,
		},
		SchemaVersion: 1,
		MigrateState:  migrateState,
		Schema: map[string]*schema.Schema{
			"name": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"name_prefix"},
				ValidateFunc:  ValidRoleName,
			},
			"name_prefix": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"name"},
				ValidateFunc:  ValidRolePrefix,
			},
			"type": {
				Type:         schema.TypeString,
				Optional:     true,
				ForceNew:     true,
				ExactlyOneOf: []string{"assume_role_policy", "type"},
			},
			"assume_role_policy": {
				Type:             schema.TypeString,
				Optional:         true,
				ForceNew:         true,
				ExactlyOneOf:     []string{"assume_role_policy", "type"},
				DiffSuppressFunc: SuppressEquivalentTrustPolicyDiffs,
			},
			"include_default_policies": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
				ForceNew: true,
			},
			"role_added_to_ip": {
				Type:     schema.TypeBool,
				Computed: true,
			},
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"ip_arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"enable_alks_access": {
				Type:     schema.TypeBool,
				Default:  false,
				Optional: true,
				ForceNew: true,
			},
			"template_fields": {
				Type:     schema.TypeMap,
				Elem:     schema.TypeString,
				ForceNew: true,
				Optional: true,
			},
			"max_session_duration_in_seconds": {
				Type:     schema.TypeInt,
				Default:  3600,
				Optional: true,
				ForceNew: true,
			},
			"tags":     TagsSchema(),
			"tags_all": TagsSchemaComputed(),
		},
		CustomizeDiff: customdiff.All(
			SetTagsDiff,
			trustPoliciesWithIncludeDefaultPolicies,
		),
	}
}

func resourceAlksIamRoleCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
	log.Printf("[INFO] ALKS IAM Role Create")
	var roleName = NameWithPrefix(d.Get("name").(string), d.Get("name_prefix").(string))
	var incDefPol = d.Get("include_default_policies").(bool)
	var enableAlksAccess = d.Get("enable_alks_access").(bool)
	var rawTemplateFields = d.Get("template_fields").(map[string]interface{})
	var maxSessionDurationInSeconds = d.Get("max_session_duration_in_seconds").(int)
	var tags = d.Get("tags").(map[string]interface{})

	templateFields := make(map[string]string)
	for k, v := range rawTemplateFields {
		templateFields[k] = v.(string)
	}

	include := false
	if incDefPol {
		include = true
	}

	providerStruct := meta.(*AlksClient)
	client := providerStruct.client

	//Role Specific tags will overwrite default tags if value is defined in both maps
	allTags := tagMapToSlice(combineTagMaps(providerStruct.defaultTags, tags))

	if err := validateIAMEnabled(client); err != nil {
		return diag.FromErr(err)
	}

	options := &alks.CreateIamRoleOptions{
		RoleName:                    &roleName,
		IncludeDefaultPolicies:      &include,
		AlksAccess:                  &enableAlksAccess,
		TemplateFields:              &templateFields,
		MaxSessionDurationInSeconds: &maxSessionDurationInSeconds,
		Tags:                        &allTags,
	}

	if roleType, ok := d.GetOk("type"); ok {
		roleTypeString := roleType.(string)
		options.RoleType = &roleTypeString
	} else {
		trustPolicyString := d.Get("assume_role_policy").(string)

		trustPolicy := new(map[string]interface{})

		json.Unmarshal([]byte(trustPolicyString), trustPolicy)

		options.TrustPolicy = trustPolicy
	}

	resp, err := client.CreateIamRole(options)
	if err != nil {
		return diag.FromErr(err)
	}

	d.SetId(resp.RoleName)
	_ = d.Set("role_added_to_ip", resp.RoleAddedToIP)

	log.Printf("[INFO] alks_iamrole.id: %v", d.Id())

	return resourceAlksIamRoleRead(ctx, d, meta)
}

func resourceAlksIamRoleDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
	log.Printf("[INFO] ALKS IAM Role Delete")

	providerStruct := meta.(*AlksClient)
	client := providerStruct.client
	if err := validateIAMEnabled(client); err != nil {
		return diag.FromErr(err)
	}

	if err := client.DeleteIamRole(d.Id()); err != nil {
		return diag.FromErr(err)
	}

	return nil
}

func resourceAlksIamRoleRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
	log.Printf("[INFO] ALKS IAM Role Read")
	providerStruct := meta.(*AlksClient)
	client := providerStruct.client

	defaultTags := providerStruct.defaultTags
	ignoreTags := providerStruct.ignoreTags

	// Check if role exists.
	if d.Id() == "" || d.Id() == "none" {
		return nil
	}

	foundRole, err := client.GetIamRole(d.Id())

	if err != nil {
		//If error is 404, RoleNotFound, we log it and let terraform decide how to handle it.
		//All other errors cause a failure
		if err.StatusCode == 404 {
			log.Printf("[Error] %s", err)
			d.SetId("")
			return nil
		}
		return diag.FromErr(err)
	}

	log.Printf("[INFO] alks_iamrole.id %v", d.Id())

	_ = d.Set("name", foundRole.RoleName)
	_ = d.Set("name_prefix", NamePrefixFromName(foundRole.RoleName))
	_ = d.Set("arn", foundRole.RoleArn)
	_ = d.Set("ip_arn", foundRole.RoleIPArn)
	_ = d.Set("enable_alks_access", foundRole.AlksAccess)
	_ = d.Set("role_added_to_ip", foundRole.RoleAddedToIP)

	var roleType = d.Get("type")
	if (roleType == nil) || (roleType == "") {
		jsonStrPolicy, err := json.Marshal(foundRole.TrustPolicy)
		if err == nil {
			_ = d.Set("assume_role_policy", string(jsonStrPolicy))
		}
		_ = d.Set("include_default_policies", false)
	}
	_ = d.Set("max_session_duration_in_seconds", foundRole.MaxSessionDurationInSeconds)

	allTags := tagSliceToMap(foundRole.Tags)
	localTags := removeIgnoredTags(allTags, *ignoreTags)

	if err := d.Set("tags_all", localTags); err != nil {
		return diag.FromErr(err)
	}

	roleSpecificTags := removeDefaultTags(localTags, defaultTags)

	if err := d.Set("tags", roleSpecificTags); err != nil {
		return diag.FromErr(err)
	}

	// TODO: In the future, our API or tags need to dynamically grab these values.
	//  Till then, all imports require a destroy + create.
	//_ = d.Set("type", foundrole.RoleType)
	//_ = d.Set("include_default_policies", foundrole.InclDefaultPolicies)

	return nil
}

func resourceAlksIamRoleUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
	log.Printf("[INFO] ALKS IAM Role Update")

	// enable partial state mode
	d.Partial(true)

	if d.HasChange("enable_alks_access") {
		// try updating enable_alks_access
		if err := updateAlksAccess(d, meta); err != nil {
			return diag.FromErr(err)
		}
	}

	if d.HasChange("tags_all") {
		// try updating enable_alks_access
		if err := updateIamRoleTags(d, meta); err != nil {
			return diag.FromErr(err)
		}
	}

	d.Partial(false)

	return resourceAlksIamRoleRead(ctx, d, meta)
}

func updateAlksAccess(d *schema.ResourceData, meta interface{}) error {
	var alksAccess = d.Get("enable_alks_access").(bool)
	var roleArn = d.Get("arn").(string)
	providerStruct := meta.(*AlksClient)
	client := providerStruct.client
	if err := validateIAMEnabled(client); err != nil {
		return err
	}
	// create the machine identity
	if alksAccess {
		_, err := client.AddRoleMachineIdentity(roleArn)
		if err != nil {
			return err
		}
	} else {
		// delete the machine identity
		_, err := client.DeleteRoleMachineIdentity(roleArn)
		if err != nil {
			return err
		}
	}
	return nil
}

func updateIamRoleTags(d *schema.ResourceData, meta interface{}) error {
	providerStruct := meta.(*AlksClient)
	client := providerStruct.client

	if err := validateIAMEnabled(client); err != nil {
		return err
	}

	//Do a read to get existing tags.  If any of those are in ignore_tags, then they are externally managed
	//and they should be included in the update so they don't get removed.
	foundRole, err := client.GetIamRole(d.Id())

	if err != nil {
		return err
	}

	existingTags := tagSliceToMap(foundRole.Tags)
	externalTags := getExternalyManagedTags(existingTags, *providerStruct.ignoreTags)
	internalTags := d.Get("tags_all").(map[string]interface{})

	//Tags includes default tags, role specific tags, and tags that exist externally on the role itself and are specified in ignored_tags
	tags := tagMapToSlice(combineTagMaps(internalTags, externalTags))

	options := alks.UpdateIamRoleRequest{
		RoleName: &foundRole.RoleName,
		Tags:     &tags,
	}

	if _, err := client.UpdateIamRole(&options); err != nil {
		return err
	}
	return nil
}

func migrateState(version int, state *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) {
	switch version {
	case 0:
		log.Println("[INFO] Found Instance State v0, migrating to v1")
		return migrateV0toV1(state)
	default:
		return state, fmt.Errorf("Unrecognized version '%d' in schema for instance of ALKS IAM role '%s'", version, state.Attributes["name"])
	}
}

func migrateV0toV1(state *terraform.InstanceState) (*terraform.InstanceState, error) {
	if state.Empty() {
		log.Println("[DEBUG] Empty InstanceState, nothing to migrate")
		return state, nil
	}

	if _, ok := state.Attributes["enable_alks_access"]; !ok {
		log.Printf("[DEBUG] Attributes before migration: %#v", state.Attributes)
		state.Attributes["enable_alks_access"] = "false"
		log.Printf("[DEBUG] Attributes after migration: %#v", state.Attributes)
	}

	return state, nil
}
<commit_msg>fix err to return string not error object<commit_after>package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"

	"github.com/Cox-Automotive/alks-go"
	"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func resourceAlksIamRole() *schema.Resource {
	return &schema.Resource{
		CreateContext: resourceAlksIamRoleCreate,
		ReadContext:   resourceAlksIamRoleRead,
		UpdateContext: resourceAlksIamRoleUpdate,
		DeleteContext: resourceAlksIamRoleDelete,
		Importer: &schema.ResourceImporter{
			StateContext: schema.ImportStatePassthroughContext,
		},
		SchemaVersion: 1,
		MigrateState:  migrateState,
		Schema: map[string]*schema.Schema{
			"name": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"name_prefix"},
				ValidateFunc:  ValidRoleName,
			},
			"name_prefix": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ForceNew:      true,
				ConflictsWith: []string{"name"},
				ValidateFunc:  ValidRolePrefix,
			},
			"type": {
				Type:         schema.TypeString,
				Optional:     true,
				ForceNew:     true,
				ExactlyOneOf: []string{"assume_role_policy", "type"},
			},
			"assume_role_policy": {
				Type:             schema.TypeString,
				Optional:         true,
				ForceNew:         true,
				ExactlyOneOf:     []string{"assume_role_policy", "type"},
				DiffSuppressFunc: SuppressEquivalentTrustPolicyDiffs,
			},
			"include_default_policies": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
				ForceNew: true,
			},
			"role_added_to_ip": {
				Type:     schema.TypeBool,
				Computed: true,
			},
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"ip_arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"enable_alks_access": {
				Type:     schema.TypeBool,
				Default:  false,
				Optional: true,
				ForceNew: true,
			},
			"template_fields": {
				Type:     schema.TypeMap,
				Elem:     schema.TypeString,
				ForceNew: true,
				Optional: true,
			},
			"max_session_duration_in_seconds": {
				Type:     schema.TypeInt,
				Default:  3600,
				Optional: true,
				ForceNew: true,
			},
			"tags":     TagsSchema(),
			"tags_all": TagsSchemaComputed(),
		},
		CustomizeDiff: customdiff.All(
			SetTagsDiff,
			trustPoliciesWithIncludeDefaultPolicies,
		),
	}
}

func resourceAlksIamRoleCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
	log.Printf("[INFO] ALKS IAM Role Create")
	var roleName = NameWithPrefix(d.Get("name").(string), d.Get("name_prefix").(string))
	var incDefPol = d.Get("include_default_policies").(bool)
	var enableAlksAccess = d.Get("enable_alks_access").(bool)
	var rawTemplateFields = d.Get("template_fields").(map[string]interface{})
	var maxSessionDurationInSeconds = d.Get("max_session_duration_in_seconds").(int)
	var tags = d.Get("tags").(map[string]interface{})

	templateFields := make(map[string]string)
	for k, v := range rawTemplateFields {
		templateFields[k] = v.(string)
	}

	include := false
	if incDefPol {
		include = true
	}

	providerStruct := meta.(*AlksClient)
	client := providerStruct.client

	//Role Specific tags will overwrite default tags if value is defined in both maps
	allTags := tagMapToSlice(combineTagMaps(providerStruct.defaultTags, tags))

	if err := validateIAMEnabled(client); err != nil {
		return diag.FromErr(err)
	}

	options := &alks.CreateIamRoleOptions{
		RoleName:                    &roleName,
		IncludeDefaultPolicies:      &include,
		AlksAccess:                  &enableAlksAccess,
		TemplateFields:              &templateFields,
		MaxSessionDurationInSeconds: &maxSessionDurationInSeconds,
		Tags:                        &allTags,
	}

	if roleType, ok := d.GetOk("type"); ok {
		roleTypeString := roleType.(string)
		options.RoleType = &roleTypeString
	} else {
		trustPolicyString := d.Get("assume_role_policy").(string)

		trustPolicy := new(map[string]interface{})

		json.Unmarshal([]byte(trustPolicyString), trustPolicy)

		options.TrustPolicy = trustPolicy
	}

	resp, err := client.CreateIamRole(options)
	if err != nil {
		return diag.FromErr(err)
	}

	d.SetId(resp.RoleName)
	_ = d.Set("role_added_to_ip", resp.RoleAddedToIP)

	log.Printf("[INFO] alks_iamrole.id: %v", d.Id())

	return resourceAlksIamRoleRead(ctx, d, meta)
}

func resourceAlksIamRoleDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
	log.Printf("[INFO] ALKS IAM Role Delete")

	providerStruct := meta.(*AlksClient)
	client := providerStruct.client
	if err := validateIAMEnabled(client); err != nil {
		return diag.FromErr(err)
	}

	if err := client.DeleteIamRole(d.Id()); err != nil {
		return diag.FromErr(err)
	}

	return nil
}

func resourceAlksIamRoleRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
	log.Printf("[INFO] ALKS IAM Role Read")
	providerStruct := meta.(*AlksClient)
	client := providerStruct.client

	defaultTags := providerStruct.defaultTags
	ignoreTags := providerStruct.ignoreTags

	// Check if role exists.
	if d.Id() == "" || d.Id() == "none" {
		return nil
	}

	foundRole, err := client.GetIamRole(d.Id())

	if err != nil {
		//If error is 404, RoleNotFound, we log it and let terraform decide how to handle it.
		//All other errors cause a failure
		if err.StatusCode == 404 {
			log.Printf("[Error] %s", err.Error())
			d.SetId("")
			return nil
		}
		return diag.FromErr(err)
	}

	log.Printf("[INFO] alks_iamrole.id %v", d.Id())

	_ = d.Set("name", foundRole.RoleName)
	_ = d.Set("name_prefix", NamePrefixFromName(foundRole.RoleName))
	_ = d.Set("arn", foundRole.RoleArn)
	_ = d.Set("ip_arn", foundRole.RoleIPArn)
	_ = d.Set("enable_alks_access", foundRole.AlksAccess)
	_ = d.Set("role_added_to_ip", foundRole.RoleAddedToIP)

	var roleType = d.Get("type")
	if (roleType == nil) || (roleType == "") {
		jsonStrPolicy, err := json.Marshal(foundRole.TrustPolicy)
		if err == nil {
			_ = d.Set("assume_role_policy", string(jsonStrPolicy))
		}
		_ = d.Set("include_default_policies", false)
	}
	_ = d.Set("max_session_duration_in_seconds", foundRole.MaxSessionDurationInSeconds)

	allTags := tagSliceToMap(foundRole.Tags)
	localTags := removeIgnoredTags(allTags, *ignoreTags)

	if err := d.Set("tags_all", localTags); err != nil {
		return diag.FromErr(err)
	}

	roleSpecificTags := removeDefaultTags(localTags, defaultTags)

	if err := d.Set("tags", roleSpecificTags); err != nil {
		return diag.FromErr(err)
	}

	// TODO: In the future, our API or tags need to dynamically grab these values.
	//  Till then, all imports require a destroy + create.
	//_ = d.Set("type", foundrole.RoleType)
	//_ = d.Set("include_default_policies", foundrole.InclDefaultPolicies)

	return nil
}

func resourceAlksIamRoleUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
	log.Printf("[INFO] ALKS IAM Role Update")

	// enable partial state mode
	d.Partial(true)

	if d.HasChange("enable_alks_access") {
		// try updating enable_alks_access
		if err := updateAlksAccess(d, meta); err != nil {
			return diag.FromErr(err)
		}
	}

	if d.HasChange("tags_all") {
		// try updating enable_alks_access
		if err := updateIamRoleTags(d, meta); err != nil {
			return diag.FromErr(err)
		}
	}

	d.Partial(false)

	return resourceAlksIamRoleRead(ctx, d, meta)
}

func updateAlksAccess(d *schema.ResourceData, meta interface{}) error {
	var alksAccess = d.Get("enable_alks_access").(bool)
	var roleArn = d.Get("arn").(string)
	providerStruct := meta.(*AlksClient)
	client := providerStruct.client
	if err := validateIAMEnabled(client); err != nil {
		return err
	}
	// create the machine identity
	if alksAccess {
		_, err := client.AddRoleMachineIdentity(roleArn)
		if err != nil {
			return err
		}
	} else {
		// delete the machine identity
		_, err := client.DeleteRoleMachineIdentity(roleArn)
		if err != nil {
			return err
		}
	}
	return nil
}

func updateIamRoleTags(d *schema.ResourceData, meta interface{}) error {
	providerStruct := meta.(*AlksClient)
	client := providerStruct.client

	if err := validateIAMEnabled(client); err != nil {
		return err
	}

	//Do a read to get existing tags.  If any of those are in ignore_tags, then they are externally managed
	//and they should be included in the update so they don't get removed.
	foundRole, err := client.GetIamRole(d.Id())

	if err != nil {
		return err
	}

	existingTags := tagSliceToMap(foundRole.Tags)
	externalTags := getExternalyManagedTags(existingTags, *providerStruct.ignoreTags)
	internalTags := d.Get("tags_all").(map[string]interface{})

	//Tags includes default tags, role specific tags, and tags that exist externally on the role itself and are specified in ignored_tags
	tags := tagMapToSlice(combineTagMaps(internalTags, externalTags))

	options := alks.UpdateIamRoleRequest{
		RoleName: &foundRole.RoleName,
		Tags:     &tags,
	}

	if _, err := client.UpdateIamRole(&options); err != nil {
		return err
	}
	return nil
}

func migrateState(version int, state *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) {
	switch version {
	case 0:
		log.Println("[INFO] Found Instance State v0, migrating to v1")
		return migrateV0toV1(state)
	default:
		return state, fmt.Errorf("Unrecognized version '%d' in schema for instance of ALKS IAM role '%s'", version, state.Attributes["name"])
	}
}

func migrateV0toV1(state *terraform.InstanceState) (*terraform.InstanceState, error) {
	if state.Empty() {
		log.Println("[DEBUG] Empty InstanceState, nothing to migrate")
		return state, nil
	}

	if _, ok := state.Attributes["enable_alks_access"]; !ok {
		log.Printf("[DEBUG] Attributes before migration: %#v", state.Attributes)
		state.Attributes["enable_alks_access"] = "false"
		log.Printf("[DEBUG] Attributes after migration: %#v", state.Attributes)
	}

	return state, nil
}
<|endoftext|>


<commit_before>package grafana_test

import (
	"encoding/json"
	"fmt"

	"github.com/grafov/autograf/grafana"
)

func ExampleNewBoard() {
	board := grafana.NewBoard("Sample dashboard title")
	row1 := board.AddRow("Sample row title")
	row1.AddGraph(grafana.NewGraph("Sample graph title"))
	data, _ := json.MarshalIndent(board, "", "  ")
	fmt.Printf("%s", data)
	// Output:
	// {
	//   "id": 1,
	//   "title": "Sample dashboard title",
	//   "originalTitle": "",
	//   "tags": null,
	//   "style": "dark",
	//   "timezone": "browser",
	//   "editable": true,
	//   "hideControls": false,
	//   "sharedCrosshair": false,
	//   "rows": [
	//     {
	//       "title": "Sample row title",
	//       "collapse": false,
	//       "editable": true,
	//       "height": "250px",
	//       "panels": [
	//         {
	//           "id": 1,
	//           "title": "Sample graph title",
	//           "type": "graph",
	//           "error": false,
	//           "isNew": true,
	//           "renderer": "flot",
	//           "aliasColors": null,
	//           "bars": false,
	//           "fill": 0,
	//           "grid": {
	//             "leftLogBase": null,
	//             "leftMax": null,
	//             "leftMin": null,
	//             "rightLogBase": null,
	//             "rightMax": null,
	//             "rightMin": null,
	//             "threshold1": null,
	//             "threshold1Color": "",
	//             "threshold2": null,
	//             "threshold2Color": "",
	//             "thresholdLine": false
	//           },
	//           "legend": {
	//             "avg": false,
	//             "current": false,
	//             "max": false,
	//             "min": false,
	//             "show": false,
	//             "total": false,
	//             "values": false
	//           },
	//           "lines": false,
	//           "linewidth": 0,
	//           "nullPointMode": "connected",
	//           "percentage": false,
	//           "pointradius": 5,
	//           "points": false,
	//           "seriesOverrides": null,
	//           "span": 12,
	//           "stack": false,
	//           "steppedLine": false,
	//           "timeFrom": null,
	//           "timeShift": null,
	//           "tooltip": {
	//             "shared": false,
	//             "value_type": ""
	//           },
	//           "x-axis": true,
	//           "y-axis": true,
	//           "y_formats": null
	//         }
	//       ]
	//     }
	//   ],
	//   "templating": {
	//     "list": null
	//   },
	//   "annotations": {
	//     "list": null
	//   },
	//   "schemiaVersion": 0,
	//   "version": 0,
	//   "links": null,
	//   "time": {
	//     "from": "",
	//     "to": ""
	//   },
	//   "timepicker": {
	//     "refresh_intervals": null,
	//     "time_options": null
	//   }
	// }

}
<commit_msg>Fix unit test after types changed.<commit_after>package grafana_test

import (
	"encoding/json"
	"fmt"

	"github.com/grafov/autograf/grafana"
)

func ExampleNewBoard() {
	board := grafana.NewBoard("Sample dashboard title")
	row1 := board.AddRow("Sample row title")
	row1.AddGraph(grafana.NewGraph("Sample graph title"))
	data, _ := json.MarshalIndent(board, "", "  ")
	fmt.Printf("%s", data)
	// Output:
	// {
	//   "id": 1,
	//   "title": "Sample dashboard title",
	//   "originalTitle": "",
	//   "tags": null,
	//   "style": "dark",
	//   "timezone": "browser",
	//   "editable": true,
	//   "hideControls": false,
	//   "sharedCrosshair": false,
	//   "rows": [
	//     {
	//       "title": "Sample row title",
	//       "collapse": false,
	//       "editable": true,
	//       "height": "250px",
	//       "panels": [
	//         {
	//           "id": 1,
	//           "title": "Sample graph title",
	//           "renderer": "flot",
	//           "type": "graph",
	//           "error": false,
	//           "isNew": true,
	//           "aliasColors": null,
	//           "bars": false,
	//           "fill": 0,
	//           "grid": {
	//             "leftLogBase": null,
	//             "leftMax": null,
	//             "leftMin": null,
	//             "rightLogBase": null,
	//             "rightMax": null,
	//             "rightMin": null,
	//             "threshold1": null,
	//             "threshold1Color": "",
	//             "threshold2": null,
	//             "threshold2Color": "",
	//             "thresholdLine": false
	//           },
	//           "legend": {
	//             "avg": false,
	//             "current": false,
	//             "max": false,
	//             "min": false,
	//             "hideEmpty": false,
	//             "hideZero": false,
	//             "show": false,
	//             "total": false,
	//             "values": false
	//           },
	//           "lines": false,
	//           "linewidth": 0,
	//           "nullPointMode": "connected",
	//           "percentage": false,
	//           "pointradius": 5,
	//           "points": false,
	//           "seriesOverrides": null,
	//           "span": 12,
	//           "stack": false,
	//           "steppedLine": false,
	//           "timeFrom": null,
	//           "timeShift": null,
	//           "tooltip": {
	//             "shared": false,
	//             "value_type": ""
	//           },
	//           "x-axis": true,
	//           "y-axis": true,
	//           "y_formats": null
	//         }
	//       ]
	//     }
	//   ],
	//   "templating": {
	//     "list": null
	//   },
	//   "annotations": {
	//     "list": null
	//   },
	//   "schemiaVersion": 0,
	//   "version": 0,
	//   "links": null,
	//   "time": {
	//     "from": "",
	//     "to": ""
	//   },
	//   "timepicker": {
	//     "refresh_intervals": null,
	//     "time_options": null
	//   }
	// }
}
<|endoftext|>


<commit_before>package parser

import (
	"fmt"
	"io"
	"os"

	"github.com/flowdev/gflowparser/data"
	"github.com/flowdev/gparselib"
)

// ------------ HandleParseErrors:
// output: MainData with FlowFile filled if no errors were found or none otherwise
type HandleParseResult struct {
	outPort func(interface{})
}

func NewHandleParseResult() *HandleParseResult {
	return &HandleParseResult{}
}
func (op *HandleParseResult) InPort(dat interface{}) {
	md := dat.(*data.MainData)
	r := md.ParseData.Result

	if !r.HasError() {
		outputFeedback(os.Stdout, r.Feedback)
		md.FlowFile = r.Value.(*data.FlowFile)
		op.outPort(md)
	} else {
		outputFeedback(os.Stderr, r.Feedback)
	}
}
func (op *HandleParseResult) SetOutPort(port func(interface{})) {
	op.outPort = port
}
func outputFeedback(w io.Writer, msgs []*gparselib.FeedbackItem) {
	for msg := range msgs {
		fmt.Fprintln(w, msg)
	}
}
<commit_msg>Added TODO.<commit_after>package parser

import (
	"fmt"
	"io"
	"os"

	"github.com/flowdev/gflowparser/data"
	"github.com/flowdev/gparselib"
)

// ------------ HandleParseErrors:
// output: MainData with FlowFile filled if no errors were found or none otherwise
type HandleParseResult struct {
	outPort func(interface{})
}

func NewHandleParseResult() *HandleParseResult {
	return &HandleParseResult{}
}
func (op *HandleParseResult) InPort(dat interface{}) {
	md := dat.(*data.MainData)
	r := md.ParseData.Result

	// TODO: Better error handling with error port, ... for wiki
	if !r.HasError() {
		outputFeedback(os.Stdout, r.Feedback)
		md.FlowFile = r.Value.(*data.FlowFile)
		op.outPort(md)
	} else {
		outputFeedback(os.Stderr, r.Feedback)
	}
}
func (op *HandleParseResult) SetOutPort(port func(interface{})) {
	op.outPort = port
}
func outputFeedback(w io.Writer, msgs []*gparselib.FeedbackItem) {
	for msg := range msgs {
		fmt.Fprintln(w, msg)
	}
}
<|endoftext|>


<commit_before>package main

import "strings"

func normalizeFileName(filePath string) string {
	normalized := strings.Replace(strings.ToLower(filePath), "_", "-", -1)
	normalized = strings.Replace(normalized, ".", "-", -1)
	return normalized
}

func handlePypiFileNames(key string) string {
	pathParts := strings.Split(key, "/")
	nparts := len(pathParts)
	if nparts > 2 {
		// requests can come in the form: /packagename/packagename-version-blblablabla.xx
		// the real key in these cases is: /packagename-version-blablalbalbla.xx
		key = "/" + pathParts[nparts-1]
	}
	return key
}

// handlePypiDirlist works around the fact that dirlistings are case insensitive so direct search for the path might fail
func handlePypiListDir(fetcher FileFetcher, path string) ([]ListDirEntry, error) {

	prefix := strings.TrimPrefix(path, "/")  // remove initial /
	prefix = strings.TrimSuffix(prefix, "/") // and last one

	// case-insensitive search, search for X* + x*
	firstLetter := prefix[0:1]
	lowerFiles, err := fetcher.ListDir(strings.ToLower(firstLetter))
	if err != nil {
		return lowerFiles, err
	}
	upperFiles, err := fetcher.ListDir(strings.ToUpper(firstLetter))
	if err != nil {
		return upperFiles, err
	}

	// now merge both and filter by normalized prefix comparison.
	allFiles := append(lowerFiles, upperFiles...)
	normalizedPrefix := normalizeFileName(prefix)
	var results []ListDirEntry
	for _, entry := range allFiles {
		fileName := normalizeFileName(entry.Name)
		if strings.HasPrefix(fileName, normalizedPrefix) {
			results = append(results, entry)
		}
	}
	return results, nil
}
<commit_msg>Ensure we have a prefix<commit_after>package main

import (
	"fmt"
	"strings"
)

func normalizeFileName(filePath string) string {
	normalized := strings.Replace(strings.ToLower(filePath), "_", "-", -1)
	normalized = strings.Replace(normalized, ".", "-", -1)
	return normalized
}

func handlePypiFileNames(key string) string {
	pathParts := strings.Split(key, "/")
	nparts := len(pathParts)
	if nparts > 2 {
		// requests can come in the form: /packagename/packagename-version-blblablabla.xx
		// the real key in these cases is: /packagename-version-blablalbalbla.xx
		key = "/" + pathParts[nparts-1]
	}
	return key
}

// handlePypiDirlist works around the fact that dirlistings are case insensitive so direct search for the path might fail
func handlePypiListDir(fetcher FileFetcher, path string) ([]ListDirEntry, error) {
	prefix := strings.TrimPrefix(path, "/")  // remove initial /
	prefix = strings.TrimSuffix(prefix, "/") // and last one

	if len(prefix) < 1 {
		return nil, fmt.Errorf("expected a directory to list")
	}

	// case-insensitive search, search for X* + x*
	firstLetter := prefix[0:1]
	lowerFiles, err := fetcher.ListDir(strings.ToLower(firstLetter))
	if err != nil {
		return lowerFiles, err
	}
	upperFiles, err := fetcher.ListDir(strings.ToUpper(firstLetter))
	if err != nil {
		return upperFiles, err
	}

	// now merge both and filter by normalized prefix comparison.
	allFiles := append(lowerFiles, upperFiles...)
	normalizedPrefix := normalizeFileName(prefix)
	var results []ListDirEntry
	for _, entry := range allFiles {
		fileName := normalizeFileName(entry.Name)
		if strings.HasPrefix(fileName, normalizedPrefix) {
			results = append(results, entry)
		}
	}
	return results, nil
}
<|endoftext|>


<commit_before>package netutil

import (
	"net"

	"testing"

	"sync"

	"github.com/xiaonanln/goworld/gwlog"
)

var (
	listener net.Listener
)

func init() {
	var err error
	listener, err = net.Listen("tcp", "0.0.0.0:13001")
	paniciferror(err)
	gwlog.Info("Listening ...")
}

func paniciferror(err error) {
	if err != nil {
		gwlog.Panicf("error: %s", err.Error())
	}
}

func TestCompressedConnection_Read(t *testing.T) {
	var wait sync.WaitGroup
	wait.Add(2)
	go func() {
		defer wait.Done()
		conn, err := net.Dial("tcp", "localhost:13001")
		println("dial", conn, err)
		paniciferror(err)
		cc := NewCompressedConnection(NetConnection{conn})
		println("NewCompressedConnection", cc)
		n, err := cc.Write([]byte("hello"))
		println("write", n, err)
		err = cc.Flush()
		paniciferror(err)
		println("flush", err)
		cc.Write([]byte("world"))
		cc.Flush()
		cc.Write([]byte("bigaa"))
		cc.Flush()

		cc.Write([]byte("bigha"))
		cc.Flush()
	}()
	go func() {
		defer wait.Done()

		conn, err := listener.Accept()
		println("accept", conn, err)
		paniciferror(err)
		cc := NewCompressedConnection(NetConnection{conn})
		println("NewCompressedConnection", cc)
		buf := make([]byte, 5)
		n, err := cc.Read(buf)
		paniciferror(err)
		println("read", n, err, string(buf[:n]))
		if string(buf[:n]) != "hello" {
			gwlog.Panicf("recv error")
		}

		n, err = cc.Read(buf)
		paniciferror(err)
		println("read", n, err, string(buf[:n]))
		if string(buf[:n]) != "world" {
			gwlog.Panicf("recv error")
		}
		buf = make([]byte, 3)
		n, err = cc.Read(buf)
		paniciferror(err)
		println("read", n, err, string(buf[:n]))
		if string(buf[:n]) != "big" {
			gwlog.Panicf("recv error")
		}
		n, err = cc.Read(buf)
		paniciferror(err)
		println("read", n, err, string(buf[:n]))
		if string(buf[:n]) != "aa" {
			gwlog.Panicf("recv error")
		}
		n, err = cc.Read(buf)
		paniciferror(err)
		println("read", n, err, string(buf[:n]))
		if string(buf[:n]) != "big" {
			gwlog.Panicf("recv error")
		}
		n, err = cc.Read(buf)
		paniciferror(err)
		println("read", n, err, string(buf[:n]))
		if string(buf[:n]) != "ha" {
			gwlog.Panicf("recv error")
		}
	}()

	wait.Wait()
}
<commit_msg>Compressed connection working on<commit_after>package netutil

import (
	"net"

	"testing"

	"sync"

	"fmt"

	"time"

	"github.com/xiaonanln/goworld/gwlog"
)

var (
	listener net.Listener
)

func init() {
	var err error
	listener, err = net.Listen("tcp", "0.0.0.0:13001")
	paniciferror(err)
	gwlog.Info("Listening ...")
}

func paniciferror(err error) {
	if err != nil {
		gwlog.Panicf("error: %s", err.Error())
	}
}

func TestCompressedConnection_Read(t *testing.T) {
	var wait sync.WaitGroup
	wait.Add(2)
	MSGCOUNT := 1000
	go func() {
		defer wait.Done()
		conn, err := net.Dial("tcp", "localhost:13001")
		println("dial", conn, err)
		paniciferror(err)
		cc := NewCompressedConnection(NetConnection{conn})
		println("NewCompressedConnection", cc)
		for i := 0; i < MSGCOUNT; i++ {
			cc.Write([]byte(fmt.Sprintf("test message %d", i)))
			cc.Flush()
		}
	}()
	go func() {
		defer wait.Done()

		conn, err := listener.Accept()
		println("accept", conn, err)
		paniciferror(err)
		cc := NewCompressedConnection(NetConnection{conn})
		println("NewCompressedConnection", cc)

		buf := make([]byte, 1024)
		for i := 0; i < MSGCOUNT; i++ {
			cc.SetReadDeadline(time.Now().Add(time.Millisecond))
			n, err := cc.Read(buf)
			if err != nil && IsTemporaryNetError(err) {
				continue
			}

			paniciferror(err)
			msg := string(buf[:n])
			if msg != fmt.Sprintf("test message %d", i) {
				t.Error("wrong message")
			}
		}
	}()

	wait.Wait()
}
<|endoftext|>