<commit_before>/*
Copyright 2018 Google LLC

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 util

import (
	"github.com/docker/docker/builder/dockerfile/instructions"
	"github.com/docker/docker/builder/dockerfile/parser"
	"github.com/docker/docker/builder/dockerfile/shell"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

// ResolveEnvironmentReplacement resolves a list of values by calling resolveEnvironmentReplacement
func ResolveEnvironmentReplacementList(values, envs []string, isFilepath bool) ([]string, error) {
	var resolvedValues []string
	for _, value := range values {
		if IsSrcRemoteFileURL(value) {
			resolvedValues = append(resolvedValues, value)
			continue
		}
		resolved, err := ResolveEnvironmentReplacement(value, envs, isFilepath)
		logrus.Debugf("Resolved %s to %s", value, resolved)
		if err != nil {
			return nil, err
		}
		resolvedValues = append(resolvedValues, resolved)
	}
	return resolvedValues, nil
}

// ResolveEnvironmentReplacement resolves replacing env variables in some text from envs
// It takes in a string representation of the command, the value to be resolved, and a list of envs (config.Env)
// Ex: fp = $foo/newdir, envs = [foo=/foodir], then this should return /foodir/newdir
// The dockerfile/shell package handles processing env values
// It handles escape characters and supports expansion from the config.Env array
// Shlex handles some of the following use cases (these and more are tested in integration tests)
// ""a'b'c"" -> "a'b'c"
// "Rex\ The\ Dog \" -> "Rex The Dog"
// "a\"b" -> "a"b"
func ResolveEnvironmentReplacement(value string, envs []string, isFilepath bool) (string, error) {
	shlex := shell.NewLex(parser.DefaultEscapeToken)
	fp, err := shlex.ProcessWord(value, envs)
	if !isFilepath {
		return fp, err
	}
	if err != nil {
		return "", err
	}
	fp = filepath.Clean(fp)
	if IsDestDir(value) {
		fp = fp + "/"
	}
	return fp, nil
}

// ContainsWildcards returns true if any entry in paths contains wildcards
func ContainsWildcards(paths []string) bool {
	for _, path := range paths {
		if strings.ContainsAny(path, "*?[") {
			return true
		}
	}
	return false
}

// ResolveSources resolves the given sources if the sources contains wildcards
// It returns a map of [src]:[files rooted at src]
func ResolveSources(srcsAndDest instructions.SourcesAndDest, root string) (map[string][]string, error) {
	srcs := srcsAndDest[:len(srcsAndDest)-1]
	// If sources contain wildcards, we first need to resolve them to actual paths
	if ContainsWildcards(srcs) {
		logrus.Debugf("Resolving srcs %v...", srcs)
		files, err := RelativeFiles("", root)
		if err != nil {
			return nil, err
		}
		srcs, err = matchSources(srcs, files)
		if err != nil {
			return nil, err
		}
		logrus.Debugf("Resolved sources to %v", srcs)
	}
	// Now, get a map of [src]:[files rooted at src]
	srcMap, err := SourcesToFilesMap(srcs, root)
	if err != nil {
		return nil, err
	}
	// Check to make sure the sources are valid
	return srcMap, IsSrcsValid(srcsAndDest, srcMap)
}

// matchSources returns a list of sources that match wildcards
func matchSources(srcs, files []string) ([]string, error) {
	var matchedSources []string
	for _, src := range srcs {
		if IsSrcRemoteFileURL(src) {
			matchedSources = append(matchedSources, src)
			continue
		}
		src = filepath.Clean(src)
		for _, file := range files {
			matched, err := filepath.Match(src, file)
			if err != nil {
				return nil, err
			}
			if matched || src == file {
				matchedSources = append(matchedSources, file)
			}
		}
	}
	return matchedSources, nil
}

func IsDestDir(path string) bool {
	return strings.HasSuffix(path, "/") || path == "."
}

// DestinationFilepath returns the destination filepath from the build context to the image filesystem
// If source is a file:
//	If dest is a dir, copy it to /dest/relpath
// 	If dest is a file, copy directly to dest
// If source is a dir:
//	Assume dest is also a dir, and copy to dest/relpath
// If dest is not an absolute filepath, add /cwd to the beginning
func DestinationFilepath(filename, srcName, dest, cwd, buildcontext string) (string, error) {
	fi, err := os.Stat(filepath.Join(buildcontext, filename))
	if err != nil {
		return "", err
	}
	src, err := os.Stat(filepath.Join(buildcontext, srcName))
	if err != nil {
		return "", err
	}
	if src.IsDir() || IsDestDir(dest) {
		relPath, err := filepath.Rel(srcName, filename)
		if err != nil {
			return "", err
		}
		if relPath == "." && !fi.IsDir() {
			relPath = filepath.Base(filename)
		}
		destPath := filepath.Join(dest, relPath)
		if filepath.IsAbs(dest) {
			return destPath, nil
		}
		return filepath.Join(cwd, destPath), nil
	}
	if filepath.IsAbs(dest) {
		return dest, nil
	}
	return filepath.Join(cwd, dest), nil
}

// URLDestinationFilepath gives the destintion a file from a remote URL should be saved to
func URLDestinationFilepath(rawurl, dest, cwd string) string {
	if !IsDestDir(dest) {
		if !filepath.IsAbs(dest) {
			return filepath.Join(cwd, dest)
		}
		return dest
	}
	urlBase := filepath.Base(rawurl)
	destPath := filepath.Join(dest, urlBase)

	if !filepath.IsAbs(dest) {
		destPath = filepath.Join(cwd, destPath)
	}
	return destPath
}

// SourcesToFilesMap returns a map of [src]:[files rooted at source]
func SourcesToFilesMap(srcs []string, root string) (map[string][]string, error) {
	srcMap := make(map[string][]string)
	for _, src := range srcs {
		if IsSrcRemoteFileURL(src) {
			srcMap[src] = []string{src}
			continue
		}
		src = filepath.Clean(src)
		files, err := RelativeFiles(src, root)
		if err != nil {
			return nil, err
		}
		srcMap[src] = files
	}
	return srcMap, nil
}

// IsSrcsValid returns an error if the sources provided are invalid, or nil otherwise
func IsSrcsValid(srcsAndDest instructions.SourcesAndDest, srcMap map[string][]string) error {
	srcs := srcsAndDest[:len(srcsAndDest)-1]
	dest := srcsAndDest[len(srcsAndDest)-1]

	totalFiles := 0
	for _, files := range srcMap {
		totalFiles += len(files)
	}
	if totalFiles == 0 {
		return errors.New("copy failed: no source files specified")
	}

	if !ContainsWildcards(srcs) {
		// If multiple sources and destination isn't a directory, return an error
		if len(srcs) > 1 && !IsDestDir(dest) {
			return errors.New("when specifying multiple sources in a COPY command, destination must be a directory and end in '/'")
		}
		return nil
	}

	// If there are wildcards, and the destination is a file, there must be exactly one file to copy over,
	// Otherwise, return an error
	if !IsDestDir(dest) && totalFiles > 1 {
		return errors.New("when specifying multiple sources in a COPY command, destination must be a directory and end in '/'")
	}
	return nil
}

func IsSrcRemoteFileURL(rawurl string) bool {
	_, err := url.ParseRequestURI(rawurl)
	if err != nil {
		return false
	}
	_, err = http.Get(rawurl)
	if err != nil {
		return false
	}
	return true
}
<commit_msg>fixed comment<commit_after>/*
Copyright 2018 Google LLC

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 util

import (
	"github.com/docker/docker/builder/dockerfile/instructions"
	"github.com/docker/docker/builder/dockerfile/parser"
	"github.com/docker/docker/builder/dockerfile/shell"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"
)

// ResolveEnvironmentReplacement resolves a list of values by calling resolveEnvironmentReplacement
func ResolveEnvironmentReplacementList(values, envs []string, isFilepath bool) ([]string, error) {
	var resolvedValues []string
	for _, value := range values {
		if IsSrcRemoteFileURL(value) {
			resolvedValues = append(resolvedValues, value)
			continue
		}
		resolved, err := ResolveEnvironmentReplacement(value, envs, isFilepath)
		logrus.Debugf("Resolved %s to %s", value, resolved)
		if err != nil {
			return nil, err
		}
		resolvedValues = append(resolvedValues, resolved)
	}
	return resolvedValues, nil
}

// ResolveEnvironmentReplacement resolves replacing env variables in some text from envs
// It takes in a string representation of the command, the value to be resolved, and a list of envs (config.Env)
// Ex: fp = $foo/newdir, envs = [foo=/foodir], then this should return /foodir/newdir
// The dockerfile/shell package handles processing env values
// It handles escape characters and supports expansion from the config.Env array
// Shlex handles some of the following use cases (these and more are tested in integration tests)
// ""a'b'c"" -> "a'b'c"
// "Rex\ The\ Dog \" -> "Rex The Dog"
// "a\"b" -> "a"b"
func ResolveEnvironmentReplacement(value string, envs []string, isFilepath bool) (string, error) {
	shlex := shell.NewLex(parser.DefaultEscapeToken)
	fp, err := shlex.ProcessWord(value, envs)
	if !isFilepath {
		return fp, err
	}
	if err != nil {
		return "", err
	}
	fp = filepath.Clean(fp)
	if IsDestDir(value) {
		fp = fp + "/"
	}
	return fp, nil
}

// ContainsWildcards returns true if any entry in paths contains wildcards
func ContainsWildcards(paths []string) bool {
	for _, path := range paths {
		if strings.ContainsAny(path, "*?[") {
			return true
		}
	}
	return false
}

// ResolveSources resolves the given sources if the sources contains wildcards
// It returns a map of [src]:[files rooted at src]
func ResolveSources(srcsAndDest instructions.SourcesAndDest, root string) (map[string][]string, error) {
	srcs := srcsAndDest[:len(srcsAndDest)-1]
	// If sources contain wildcards, we first need to resolve them to actual paths
	if ContainsWildcards(srcs) {
		logrus.Debugf("Resolving srcs %v...", srcs)
		files, err := RelativeFiles("", root)
		if err != nil {
			return nil, err
		}
		srcs, err = matchSources(srcs, files)
		if err != nil {
			return nil, err
		}
		logrus.Debugf("Resolved sources to %v", srcs)
	}
	// Now, get a map of [src]:[files rooted at src]
	srcMap, err := SourcesToFilesMap(srcs, root)
	if err != nil {
		return nil, err
	}
	// Check to make sure the sources are valid
	return srcMap, IsSrcsValid(srcsAndDest, srcMap)
}

// matchSources returns a list of sources that match wildcards
func matchSources(srcs, files []string) ([]string, error) {
	var matchedSources []string
	for _, src := range srcs {
		if IsSrcRemoteFileURL(src) {
			matchedSources = append(matchedSources, src)
			continue
		}
		src = filepath.Clean(src)
		for _, file := range files {
			matched, err := filepath.Match(src, file)
			if err != nil {
				return nil, err
			}
			if matched || src == file {
				matchedSources = append(matchedSources, file)
			}
		}
	}
	return matchedSources, nil
}

func IsDestDir(path string) bool {
	return strings.HasSuffix(path, "/") || path == "."
}

// DestinationFilepath returns the destination filepath from the build context to the image filesystem
// If source is a file:
//	If dest is a dir, copy it to /dest/relpath
// 	If dest is a file, copy directly to dest
// If source is a dir:
//	Assume dest is also a dir, and copy to dest/relpath
// If dest is not an absolute filepath, add /cwd to the beginning
func DestinationFilepath(filename, srcName, dest, cwd, buildcontext string) (string, error) {
	fi, err := os.Stat(filepath.Join(buildcontext, filename))
	if err != nil {
		return "", err
	}
	src, err := os.Stat(filepath.Join(buildcontext, srcName))
	if err != nil {
		return "", err
	}
	if src.IsDir() || IsDestDir(dest) {
		relPath, err := filepath.Rel(srcName, filename)
		if err != nil {
			return "", err
		}
		if relPath == "." && !fi.IsDir() {
			relPath = filepath.Base(filename)
		}
		destPath := filepath.Join(dest, relPath)
		if filepath.IsAbs(dest) {
			return destPath, nil
		}
		return filepath.Join(cwd, destPath), nil
	}
	if filepath.IsAbs(dest) {
		return dest, nil
	}
	return filepath.Join(cwd, dest), nil
}

// URLDestinationFilepath gives the destination a file from a remote URL should be saved to
func URLDestinationFilepath(rawurl, dest, cwd string) string {
	if !IsDestDir(dest) {
		if !filepath.IsAbs(dest) {
			return filepath.Join(cwd, dest)
		}
		return dest
	}
	urlBase := filepath.Base(rawurl)
	destPath := filepath.Join(dest, urlBase)

	if !filepath.IsAbs(dest) {
		destPath = filepath.Join(cwd, destPath)
	}
	return destPath
}

// SourcesToFilesMap returns a map of [src]:[files rooted at source]
func SourcesToFilesMap(srcs []string, root string) (map[string][]string, error) {
	srcMap := make(map[string][]string)
	for _, src := range srcs {
		if IsSrcRemoteFileURL(src) {
			srcMap[src] = []string{src}
			continue
		}
		src = filepath.Clean(src)
		files, err := RelativeFiles(src, root)
		if err != nil {
			return nil, err
		}
		srcMap[src] = files
	}
	return srcMap, nil
}

// IsSrcsValid returns an error if the sources provided are invalid, or nil otherwise
func IsSrcsValid(srcsAndDest instructions.SourcesAndDest, srcMap map[string][]string) error {
	srcs := srcsAndDest[:len(srcsAndDest)-1]
	dest := srcsAndDest[len(srcsAndDest)-1]

	totalFiles := 0
	for _, files := range srcMap {
		totalFiles += len(files)
	}
	if totalFiles == 0 {
		return errors.New("copy failed: no source files specified")
	}

	if !ContainsWildcards(srcs) {
		// If multiple sources and destination isn't a directory, return an error
		if len(srcs) > 1 && !IsDestDir(dest) {
			return errors.New("when specifying multiple sources in a COPY command, destination must be a directory and end in '/'")
		}
		return nil
	}

	// If there are wildcards, and the destination is a file, there must be exactly one file to copy over,
	// Otherwise, return an error
	if !IsDestDir(dest) && totalFiles > 1 {
		return errors.New("when specifying multiple sources in a COPY command, destination must be a directory and end in '/'")
	}
	return nil
}

func IsSrcRemoteFileURL(rawurl string) bool {
	_, err := url.ParseRequestURI(rawurl)
	if err != nil {
		return false
	}
	_, err = http.Get(rawurl)
	if err != nil {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>// Copyright 2016 IBM Corporation
//
//   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 sidecar

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

	"github.com/Sirupsen/logrus"
	"github.com/urfave/cli"

	"encoding/json"
	"net/http"
	"time"

	controllerclient "github.com/amalgam8/amalgam8/controller/client"
	"github.com/amalgam8/amalgam8/controller/rules"
	"github.com/amalgam8/amalgam8/pkg/version"
	registryclient "github.com/amalgam8/amalgam8/registry/client"
	"github.com/amalgam8/amalgam8/sidecar/api"
	"github.com/amalgam8/amalgam8/sidecar/config"
	"github.com/amalgam8/amalgam8/sidecar/proxy"
	"github.com/amalgam8/amalgam8/sidecar/proxy/monitor"
	"github.com/amalgam8/amalgam8/sidecar/proxy/nginx"
	"github.com/amalgam8/amalgam8/sidecar/register"
	"github.com/amalgam8/amalgam8/sidecar/register/healthcheck"
	"github.com/amalgam8/amalgam8/sidecar/supervisor"
	"github.com/ant0ine/go-json-rest/rest"
)

// Main is the entrypoint for the sidecar when running as an executable
func Main() {
	logrus.ErrorKey = "error"
	logrus.SetLevel(logrus.DebugLevel) // Initial logging until we parse the user provided log level argument
	logrus.SetOutput(os.Stderr)

	app := cli.NewApp()

	app.Name = "sidecar"
	app.Usage = "Amalgam8 Sidecar"
	app.Version = version.Build.Version
	app.Flags = config.Flags
	app.Action = sidecarCommand

	err := app.Run(os.Args)
	if err != nil {
		logrus.WithError(err).Error("Failure launching sidecar")
	}
}

func sidecarCommand(context *cli.Context) error {
	conf, err := config.New(context)
	if err != nil {
		return err
	}
	return Run(*conf)
}

// Run the sidecar with the given configuration
func Run(conf config.Config) error {
	var err error
	var agent *register.RegistrationAgent
	appSupervisor := supervisor.AppSupervisor{}

	if conf.Debug != "" {
		cliCommand(conf.Debug)
		return nil
	}

	if err = conf.Validate(); err != nil {
		logrus.WithError(err).Error("Validation of config failed")
		return err
	}

	logrusLevel, err := logrus.ParseLevel(conf.LogLevel)
	if err != nil {
		logrus.WithError(err).Errorf("Failure parsing requested log level (%v)", conf.LogLevel)
		logrusLevel = logrus.DebugLevel
	}
	logrus.SetLevel(logrusLevel)

	if conf.Log {
		//Replace the LOGSTASH_REPLACEME string in filebeat.yml with
		//the value provided by the user
		//TODO: Make this configurable
		filebeatConf := "/etc/filebeat/filebeat.yml"
		filebeat, err := ioutil.ReadFile(filebeatConf)
		if err != nil {
			logrus.WithError(err).Error("Could not read filebeat conf")
			return err
		}

		fileContents := strings.Replace(string(filebeat), "LOGSTASH_REPLACEME", conf.LogstashServer, -1)

		err = ioutil.WriteFile("/tmp/filebeat.yml", []byte(fileContents), 0)
		if err != nil {
			logrus.WithError(err).Error("Could not write filebeat conf")
			return err
		}

		// TODO: Log failure?
		go appSupervisor.DoLogManagement("/tmp/filebeat.yml")
	}

	if conf.Proxy {
		if err = startProxy(&conf); err != nil {
			logrus.WithError(err).Error("Could not start proxy")
		}
	}

	if conf.Register {
		logrus.Info("Registering")

		registryClient, err := registryclient.New(registryclient.Config{
			URL:       conf.Registry.URL,
			AuthToken: conf.Registry.Token,
		})
		if err != nil {
			logrus.WithError(err).Error("Could not create registry client")
			return err
		}

		address := fmt.Sprintf("%v:%v", conf.Endpoint.Host, conf.Endpoint.Port)
		serviceInstance := &registryclient.ServiceInstance{
			ServiceName: conf.Service.Name,
			Tags:        conf.Service.Tags,
			Endpoint: registryclient.ServiceEndpoint{
				Type:  conf.Endpoint.Type,
				Value: address,
			},
			TTL: 60,
		}

		agent, err = register.NewRegistrationAgent(register.RegistrationConfig{
			Client:          registryClient,
			ServiceInstance: serviceInstance,
		})
		if err != nil {
			logrus.WithError(err).Error("Could not create registry agent")
			return err
		}

		healthCheckAgents, err := healthcheck.BuildAgents(conf.HealthChecks)
		if err != nil {
			logrus.WithError(err).Error("Could not build health checks")
			return err
		}

		// Control the registration agent via the health checker if any health checks were provided. If no
		// health checks are provided, just start the registration agent.
		if len(healthCheckAgents) > 0 {
			checker := register.NewHealthChecker(agent, healthCheckAgents)
			checker.Start()
		} else {
			agent.Start()
		}
	}

	if conf.Supervise {
		appSupervisor.DoAppSupervision(conf.App, agent)
	} else {
		select {}
	}

	return nil
}

func startProxy(conf *config.Config) error {
	var err error

	nginxClient := nginx.NewClient("http://localhost:5813")
	nginxManager := nginx.NewManager(
		nginx.Config{
			Service: nginx.NewService(fmt.Sprintf("%v:%v", conf.Service.Name, strings.Join(conf.Service.Tags, ","))),
			Client:  nginxClient,
		},
	)
	nginxProxy := proxy.NewNGINXProxy(nginxManager)

	controllerClient, err := controllerclient.New(controllerclient.Config{
		URL:       conf.Controller.URL,
		AuthToken: conf.Controller.Token,
	})
	if err != nil {
		logrus.WithError(err).Error("Could not create controller client")
		return err
	}

	registryClient, err := registryclient.New(registryclient.Config{
		URL:       conf.Registry.URL,
		AuthToken: conf.Registry.Token,
	})
	if err != nil {
		logrus.WithError(err).Error("Could not create registry client")
		return err
	}

	controllerMonitor := monitor.NewController(monitor.ControllerConfig{
		Client: controllerClient,
		Listeners: []monitor.ControllerListener{
			nginxProxy,
		},
		PollInterval: conf.Controller.Poll,
	})
	go func() {
		if err = controllerMonitor.Start(); err != nil {
			logrus.WithError(err).Error("Controller monitor failed")
		}
	}()

	registryMonitor := monitor.NewRegistry(monitor.RegistryConfig{
		PollInterval: conf.Registry.Poll,
		Listeners: []monitor.RegistryListener{
			nginxProxy,
		},
		RegistryClient: registryClient,
	})
	go func() {
		if err = registryMonitor.Start(); err != nil {
			logrus.WithError(err).Error("Registry monitor failed")
		}
	}()

	debugger := api.NewDebugAPI(nginxProxy)

	a := rest.NewApi()
	a.Use(
		&rest.TimerMiddleware{},
		&rest.RecorderMiddleware{},
		&rest.RecoverMiddleware{
			EnableResponseStackTrace: false,
		},
		&rest.ContentTypeCheckerMiddleware{},
		//&middleware.RequestIDMiddleware{},
		//&middleware.LoggingMiddleware{},
		//middleware.NewRequireHTTPS(middleware.CheckRequest{
		//	IsSecure: middleware.IsUsingSecureConnection,
		//	Disabled: !conf.RequireHTTPS,
		//}),
	)

	routes := debugger.Routes()
	router, err := rest.MakeRouter(
		routes...,
	)
	if err != nil {
		logrus.WithError(err).Error("Could not start API server")
		return err
	}
	a.SetApp(router)

	go func() {
		http.ListenAndServe(fmt.Sprintf(":%v", 6116), a.MakeHandler())
	}()

	return nil
}

// Instance TODO
type Instance struct {
	Tags string `json:"tags"`
	Type string `json:"type"`
	Host string `json:"host"`
	Port int    `json:"port"`
}

// NGINXState nginx cached lua state
type NGINXState struct {
	Routes    map[string][]rules.Rule `json:"routes"`
	Instances map[string][]Instance   `json:"instances"`
	Actions   map[string][]rules.Rule `json:"actions"`
}

func cliCommand(command string) {

	switch command {
	case "show-state":
		httpClient := http.Client{
			Timeout: time.Second * 10,
		}
		req, err := http.NewRequest("GET", "http://localhost:6116/state", nil)
		if err != nil {
			fmt.Println("Error occurred building the request:", err.Error())
			return
		}

		resp, err := httpClient.Do(req)
		if err != nil {
			fmt.Println("Error occurred sending the request:", err.Error())
			return
		}

		respBytes, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println("Error occurred reading response body:", err.Error())
			return
		}

		sidecarstate := struct {
			Instances []registryclient.ServiceInstance `json:"instances"`
			Rules     []rules.Rule                     `json:"rules"`
		}{}

		err = json.Unmarshal(respBytes, &sidecarstate)
		if err != nil {
			fmt.Println("Error occurred loading JSON response:", err.Error())
			return
		}

		req, err = http.NewRequest("GET", "http://localhost:5813/a8-admin", nil)
		if err != nil {
			fmt.Println("Error occurred building the request:", err.Error())
			return
		}

		resp, err = httpClient.Do(req)
		if err != nil {
			fmt.Println("Error occurred sending the request:", err.Error())
			return
		}

		respBytes, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println("Error occurred reading response body:", err.Error())
			return
		}

		nginxstate := NGINXState{}

		err = json.Unmarshal(respBytes, &nginxstate)
		if err != nil {
			fmt.Println("Error occurred loading JSON response:", err.Error())
			return
		}

		sidecarBytes, _ := json.MarshalIndent(&sidecarstate, "", "   ")
		nginxBytes, _ := json.MarshalIndent(&nginxstate, "", "   ")
		fmt.Println("\n**************\nSidecar cached state:\n**************")
		fmt.Println(string(sidecarBytes))
		fmt.Println("\n**************\nNginx cached state:\n**************")
		fmt.Println(string(nginxBytes))

	default:
		fmt.Println("Unrecognized command: ", command)
	}
}
<commit_msg>Added hard coded delay to start of health checker so that the application has time to start up. This needs a better solution in the long run.<commit_after>// Copyright 2016 IBM Corporation
//
//   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 sidecar

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

	"github.com/Sirupsen/logrus"
	"github.com/urfave/cli"

	"encoding/json"
	"net/http"
	"time"

	controllerclient "github.com/amalgam8/amalgam8/controller/client"
	"github.com/amalgam8/amalgam8/controller/rules"
	"github.com/amalgam8/amalgam8/pkg/version"
	registryclient "github.com/amalgam8/amalgam8/registry/client"
	"github.com/amalgam8/amalgam8/sidecar/api"
	"github.com/amalgam8/amalgam8/sidecar/config"
	"github.com/amalgam8/amalgam8/sidecar/proxy"
	"github.com/amalgam8/amalgam8/sidecar/proxy/monitor"
	"github.com/amalgam8/amalgam8/sidecar/proxy/nginx"
	"github.com/amalgam8/amalgam8/sidecar/register"
	"github.com/amalgam8/amalgam8/sidecar/register/healthcheck"
	"github.com/amalgam8/amalgam8/sidecar/supervisor"
	"github.com/ant0ine/go-json-rest/rest"
)

// Main is the entrypoint for the sidecar when running as an executable
func Main() {
	logrus.ErrorKey = "error"
	logrus.SetLevel(logrus.DebugLevel) // Initial logging until we parse the user provided log level argument
	logrus.SetOutput(os.Stderr)

	app := cli.NewApp()

	app.Name = "sidecar"
	app.Usage = "Amalgam8 Sidecar"
	app.Version = version.Build.Version
	app.Flags = config.Flags
	app.Action = sidecarCommand

	err := app.Run(os.Args)
	if err != nil {
		logrus.WithError(err).Error("Failure launching sidecar")
	}
}

func sidecarCommand(context *cli.Context) error {
	conf, err := config.New(context)
	if err != nil {
		return err
	}
	return Run(*conf)
}

// Run the sidecar with the given configuration
func Run(conf config.Config) error {
	var err error
	var registrationAgent *register.RegistrationAgent
	appSupervisor := supervisor.AppSupervisor{}

	if conf.Debug != "" {
		cliCommand(conf.Debug)
		return nil
	}

	if err = conf.Validate(); err != nil {
		logrus.WithError(err).Error("Validation of config failed")
		return err
	}

	logrusLevel, err := logrus.ParseLevel(conf.LogLevel)
	if err != nil {
		logrus.WithError(err).Errorf("Failure parsing requested log level (%v)", conf.LogLevel)
		logrusLevel = logrus.DebugLevel
	}
	logrus.SetLevel(logrusLevel)

	if conf.Log {
		//Replace the LOGSTASH_REPLACEME string in filebeat.yml with
		//the value provided by the user
		//TODO: Make this configurable
		filebeatConf := "/etc/filebeat/filebeat.yml"
		filebeat, err := ioutil.ReadFile(filebeatConf)
		if err != nil {
			logrus.WithError(err).Error("Could not read filebeat conf")
			return err
		}

		fileContents := strings.Replace(string(filebeat), "LOGSTASH_REPLACEME", conf.LogstashServer, -1)

		err = ioutil.WriteFile("/tmp/filebeat.yml", []byte(fileContents), 0)
		if err != nil {
			logrus.WithError(err).Error("Could not write filebeat conf")
			return err
		}

		// TODO: Log failure?
		go appSupervisor.DoLogManagement("/tmp/filebeat.yml")
	}

	if conf.Proxy {
		if err = startProxy(&conf); err != nil {
			logrus.WithError(err).Error("Could not start proxy")
		}
	}

	if conf.Register {
		logrus.Info("Registering")

		registryClient, err := registryclient.New(registryclient.Config{
			URL:       conf.Registry.URL,
			AuthToken: conf.Registry.Token,
		})
		if err != nil {
			logrus.WithError(err).Error("Could not create registry client")
			return err
		}

		address := fmt.Sprintf("%v:%v", conf.Endpoint.Host, conf.Endpoint.Port)
		serviceInstance := &registryclient.ServiceInstance{
			ServiceName: conf.Service.Name,
			Tags:        conf.Service.Tags,
			Endpoint: registryclient.ServiceEndpoint{
				Type:  conf.Endpoint.Type,
				Value: address,
			},
			TTL: 60,
		}

		registrationAgent, err = register.NewRegistrationAgent(register.RegistrationConfig{
			Client:          registryClient,
			ServiceInstance: serviceInstance,
		})
		if err != nil {
			logrus.WithError(err).Error("Could not create registry agent")
			return err
		}

		hcAgents, err := healthcheck.BuildAgents(conf.HealthChecks)
		if err != nil {
			logrus.WithError(err).Error("Could not build health checks")
			return err
		}

		// Control the registration agent via the health checker if any health checks were provided. If no
		// health checks are provided, just start the registration agent.
		if len(hcAgents) > 0 {
			checker := register.NewHealthChecker(registrationAgent, hcAgents)

			// Delay slightly to give time for the application to start
			time.AfterFunc(1 * time.Second, checker.Start) // TODO: make this delay configurable or implement a better solution.
		} else {
			registrationAgent.Start()
		}
	}

	if conf.Supervise {
		appSupervisor.DoAppSupervision(conf.App, registrationAgent)
	} else {
		select {}
	}

	return nil
}

func startProxy(conf *config.Config) error {
	var err error

	nginxClient := nginx.NewClient("http://localhost:5813")
	nginxManager := nginx.NewManager(
		nginx.Config{
			Service: nginx.NewService(fmt.Sprintf("%v:%v", conf.Service.Name, strings.Join(conf.Service.Tags, ","))),
			Client:  nginxClient,
		},
	)
	nginxProxy := proxy.NewNGINXProxy(nginxManager)

	controllerClient, err := controllerclient.New(controllerclient.Config{
		URL:       conf.Controller.URL,
		AuthToken: conf.Controller.Token,
	})
	if err != nil {
		logrus.WithError(err).Error("Could not create controller client")
		return err
	}

	registryClient, err := registryclient.New(registryclient.Config{
		URL:       conf.Registry.URL,
		AuthToken: conf.Registry.Token,
	})
	if err != nil {
		logrus.WithError(err).Error("Could not create registry client")
		return err
	}

	controllerMonitor := monitor.NewController(monitor.ControllerConfig{
		Client: controllerClient,
		Listeners: []monitor.ControllerListener{
			nginxProxy,
		},
		PollInterval: conf.Controller.Poll,
	})
	go func() {
		if err = controllerMonitor.Start(); err != nil {
			logrus.WithError(err).Error("Controller monitor failed")
		}
	}()

	registryMonitor := monitor.NewRegistry(monitor.RegistryConfig{
		PollInterval: conf.Registry.Poll,
		Listeners: []monitor.RegistryListener{
			nginxProxy,
		},
		RegistryClient: registryClient,
	})
	go func() {
		if err = registryMonitor.Start(); err != nil {
			logrus.WithError(err).Error("Registry monitor failed")
		}
	}()

	debugger := api.NewDebugAPI(nginxProxy)

	a := rest.NewApi()
	a.Use(
		&rest.TimerMiddleware{},
		&rest.RecorderMiddleware{},
		&rest.RecoverMiddleware{
			EnableResponseStackTrace: false,
		},
		&rest.ContentTypeCheckerMiddleware{},
		//&middleware.RequestIDMiddleware{},
		//&middleware.LoggingMiddleware{},
		//middleware.NewRequireHTTPS(middleware.CheckRequest{
		//	IsSecure: middleware.IsUsingSecureConnection,
		//	Disabled: !conf.RequireHTTPS,
		//}),
	)

	routes := debugger.Routes()
	router, err := rest.MakeRouter(
		routes...,
	)
	if err != nil {
		logrus.WithError(err).Error("Could not start API server")
		return err
	}
	a.SetApp(router)

	go func() {
		http.ListenAndServe(fmt.Sprintf(":%v", 6116), a.MakeHandler())
	}()

	return nil
}

// Instance TODO
type Instance struct {
	Tags string `json:"tags"`
	Type string `json:"type"`
	Host string `json:"host"`
	Port int    `json:"port"`
}

// NGINXState nginx cached lua state
type NGINXState struct {
	Routes    map[string][]rules.Rule `json:"routes"`
	Instances map[string][]Instance   `json:"instances"`
	Actions   map[string][]rules.Rule `json:"actions"`
}

func cliCommand(command string) {

	switch command {
	case "show-state":
		httpClient := http.Client{
			Timeout: time.Second * 10,
		}
		req, err := http.NewRequest("GET", "http://localhost:6116/state", nil)
		if err != nil {
			fmt.Println("Error occurred building the request:", err.Error())
			return
		}

		resp, err := httpClient.Do(req)
		if err != nil {
			fmt.Println("Error occurred sending the request:", err.Error())
			return
		}

		respBytes, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println("Error occurred reading response body:", err.Error())
			return
		}

		sidecarstate := struct {
			Instances []registryclient.ServiceInstance `json:"instances"`
			Rules     []rules.Rule                     `json:"rules"`
		}{}

		err = json.Unmarshal(respBytes, &sidecarstate)
		if err != nil {
			fmt.Println("Error occurred loading JSON response:", err.Error())
			return
		}

		req, err = http.NewRequest("GET", "http://localhost:5813/a8-admin", nil)
		if err != nil {
			fmt.Println("Error occurred building the request:", err.Error())
			return
		}

		resp, err = httpClient.Do(req)
		if err != nil {
			fmt.Println("Error occurred sending the request:", err.Error())
			return
		}

		respBytes, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println("Error occurred reading response body:", err.Error())
			return
		}

		nginxstate := NGINXState{}

		err = json.Unmarshal(respBytes, &nginxstate)
		if err != nil {
			fmt.Println("Error occurred loading JSON response:", err.Error())
			return
		}

		sidecarBytes, _ := json.MarshalIndent(&sidecarstate, "", "   ")
		nginxBytes, _ := json.MarshalIndent(&nginxstate, "", "   ")
		fmt.Println("\n**************\nSidecar cached state:\n**************")
		fmt.Println(string(sidecarBytes))
		fmt.Println("\n**************\nNginx cached state:\n**************")
		fmt.Println(string(nginxBytes))

	default:
		fmt.Println("Unrecognized command: ", command)
	}
}
<|endoftext|>


<commit_before>package vegeta

import (
	"code.google.com/p/plotinum/plot"
	"code.google.com/p/plotinum/plotter"
	"code.google.com/p/plotinum/plotutil"
	"code.google.com/p/plotinum/vg"
	"code.google.com/p/plotinum/vg/vgsvg"
	"container/list"
	"io"
	"time"
)

type TimingsPlotReporter struct {
	responses *list.List
}

// NewTimingsPlotReporter initializes a TimingsPlotReporter
func NewTimingsPlotReporter() *TimingsPlotReporter {
	return &TimingsPlotReporter{responses: list.New()}
}

// add inserts response to be used in the report, sorted by timestamp.
func (r *TimingsPlotReporter) add(res *result) {
	// Empty list
	if r.responses.Len() == 0 {
		r.responses.PushFront(res)
		return
	}
	// Happened after all others
	if last := r.responses.Back().Value.(*result); last.timestamp.Before(res.timestamp) {
		r.responses.PushBack(res)
		return
	}
	// Happened before all others
	if first := r.responses.Front().Value.(*result); first.timestamp.After(res.timestamp) {
		r.responses.PushFront(res)
		return
	}
	// O(n) worst case insertion time
	for e := r.responses.Front(); e != nil; e = e.Next() {
		needle := e.Value.(*result)
		if res.timestamp.Before(needle.timestamp) {
			r.responses.InsertBefore(res, e)
			return
		}
	}
}

// Report builds up a plot of the response times of the requests
// in SVG format and writes it to out
func (r *TimingsPlotReporter) Report(out io.Writer) error {
	timestamps := make([]time.Time, 0)
	timings := make([]time.Duration, 0)

	for e := r.responses.Front(); e != nil; e = e.Next() {
		r := e.Value.(*result)
		timestamps = append(timestamps, r.timestamp)
		timings = append(timings, r.timing)
	}

	p, err := plot.New()
	if err != nil {
		return err
	}
	pts := make(plotter.XYs, len(timestamps))
	for i := 0; i < len(pts); i++ {
		pts[i].X = timestamps[i].Sub(timestamps[0]).Seconds()
		pts[i].Y = timings[i].Seconds()
	}

	line, err := plotter.NewLine(pts)
	if err != nil {
		return err
	}
	line.Color = plotutil.Color(1)

	p.Add(line)
	p.X.Padding = vg.Length(3.0)
	p.X.Label.Text = "Time elapsed"
	p.Y.Padding = vg.Length(3.0)
	p.Y.Label.Text = "Latency (seconds)"

	w, h := vg.Millimeters(float64(len(timestamps))), vg.Centimeters(12.0)
	canvas := vgsvg.New(w, h)
	p.Draw(plot.MakeDrawArea(canvas))

	_, err = canvas.WriteTo(out)
	return err
}
<commit_msg>TimingsPlotReporter: Y axis in milliseconds<commit_after>package vegeta

import (
	"code.google.com/p/plotinum/plot"
	"code.google.com/p/plotinum/plotter"
	"code.google.com/p/plotinum/plotutil"
	"code.google.com/p/plotinum/vg"
	"code.google.com/p/plotinum/vg/vgsvg"
	"container/list"
	"io"
	"time"
)

type TimingsPlotReporter struct {
	responses *list.List
}

// NewTimingsPlotReporter initializes a TimingsPlotReporter
func NewTimingsPlotReporter() *TimingsPlotReporter {
	return &TimingsPlotReporter{responses: list.New()}
}

// add inserts response to be used in the report, sorted by timestamp.
func (r *TimingsPlotReporter) add(res *result) {
	// Empty list
	if r.responses.Len() == 0 {
		r.responses.PushFront(res)
		return
	}
	// Happened after all others
	if last := r.responses.Back().Value.(*result); last.timestamp.Before(res.timestamp) {
		r.responses.PushBack(res)
		return
	}
	// Happened before all others
	if first := r.responses.Front().Value.(*result); first.timestamp.After(res.timestamp) {
		r.responses.PushFront(res)
		return
	}
	// O(n) worst case insertion time
	for e := r.responses.Front(); e != nil; e = e.Next() {
		needle := e.Value.(*result)
		if res.timestamp.Before(needle.timestamp) {
			r.responses.InsertBefore(res, e)
			return
		}
	}
}

// Report builds up a plot of the response times of the requests
// in SVG format and writes it to out
func (r *TimingsPlotReporter) Report(out io.Writer) error {
	timestamps := make([]time.Time, 0)
	timings := make([]time.Duration, 0)

	for e := r.responses.Front(); e != nil; e = e.Next() {
		r := e.Value.(*result)
		timestamps = append(timestamps, r.timestamp)
		timings = append(timings, r.timing)
	}

	p, err := plot.New()
	if err != nil {
		return err
	}
	pts := make(plotter.XYs, len(timestamps))
	for i := 0; i < len(pts); i++ {
		pts[i].X = timestamps[i].Sub(timestamps[0]).Seconds()
		pts[i].Y = timings[i].Seconds() * 1000
	}

	line, err := plotter.NewLine(pts)
	if err != nil {
		return err
	}
	line.Color = plotutil.Color(1)

	p.Add(line)
	p.X.Padding = vg.Length(3.0)
	p.X.Label.Text = "Time elapsed"
	p.Y.Padding = vg.Length(3.0)
	p.Y.Label.Text = "Latency (ms)"

	w, h := vg.Millimeters(float64(len(timestamps))), vg.Centimeters(12.0)
	canvas := vgsvg.New(w, h)
	p.Draw(plot.MakeDrawArea(canvas))

	_, err = canvas.WriteTo(out)
	return err
}
<|endoftext|>


<commit_before>package boss

import (
	"strconv"
	"strings"

	"github.com/pajlada/pajbot2/common"
)

type parse struct {
	m *common.Msg
}

/*
Parse parses an IRC message into a more readable bot.Msg
*/
func (p *parse) Parse(line string) common.Msg {
	p.m = &common.Msg{
		User: common.User{},
		Type: common.MsgUnknown,
	}

	// msg is the string we will keep working on/reducing as we parse things
	msg := line

	var splitLine []string

	// The message starts with @, that means there are IRCv3 tags available to parse
	if strings.HasPrefix(line, "@") {
		splitLine = strings.SplitN(msg, " ", 2)
		p.parseTags(splitLine[0][1:])
		msg = splitLine[1]
	}

	// Parse source
	splitLine = strings.SplitN(msg, " ", 2)
	p.parseSource(splitLine[0])
	msg = splitLine[1]

	// Parse message type
	splitLine = strings.SplitN(msg, " ", 2)
	p.parseMsgType(splitLine[0])
	msg = splitLine[1]

	if p.m.Type == common.MsgUnknown {
		p.m.Type = common.MsgThrowAway
		return *p.m
	}

	splitLine = strings.SplitN(msg, " ", 2)
	p.parseChannel(splitLine[0])

	if len(splitLine) == 2 {
		msg = splitLine[1]

		// Parse message text + msg type (if it's a /me message or not)
		p.parseText(msg)

		if p.m.User.Name == "twitchnotify" {
			if !strings.Contains(p.m.Text, " to ") && !strings.Contains(p.m.Text, " while ") {
				p.parseNewSub()
			}
		}
	}

	// If the destination of the message is the same as the username,
	// then we tag the user as the channel owner. This will automatically
	// give him access to broadcaster commands
	if p.m.Channel == p.m.User.Name {
		p.m.User.ChannelOwner = true
	}

	if p.m.Tags != nil {
		// Parse tags further, such as the msg-id value for determinig the msg type
		p.parseExtendedTags()
	}

	return *p.m
}

func (p *parse) parseTwitchEmotes(emotetag string) {
	// TODO: Parse more emote information (bttv (and ffz?), name, size, isGif)
	// will we done by a module in the bot itself
	p.m.Emotes = make([]common.Emote, 0)
	if emotetag == "" {
		return
	}
	emoteSlice := strings.Split(emotetag, "/")
	for i := range emoteSlice {
		spl := strings.Split(emoteSlice[i], ":")
		id := spl[0]
		e := &common.Emote{}
		e.Type = "twitch"
		e.Name = p.getEmoteName(spl[1])
		e.ID = id
		// 28 px should be fine for twitch emotes
		e.SizeX = 28
		e.SizeY = 28
		e.Count = strings.Count(emoteSlice[i], "-")
		p.m.Emotes = append(p.m.Emotes, *e)
	}
}

func (p *parse) getEmoteName(pos string) string {
	pos = strings.Split(pos, ",")[0]
	spl := strings.Split(pos, "-")
	start, _ := strconv.Atoi(spl[0])
	end, _ := strconv.Atoi(spl[1])
	runes := []rune(p.m.Text)
	name := runes[start : end+1]
	return string(name)
}

func (p *parse) parseTagValues() {
	// TODO: Parse id and color
	// color and id is pretty useless imo
	if p.m.Tags["display-name"] == "" {
		p.m.User.DisplayName = p.m.User.Name
	} else {
		p.m.User.DisplayName = p.m.Tags["display-name"]
	}
	delete(p.m.Tags, "display-name")
	p.m.User.Type = p.m.Tags["user-type"]
	delete(p.m.Tags, "user-type")
	if p.m.Tags["turbo"] == "1" {
		p.m.User.Turbo = true
	}
	delete(p.m.Tags, "turbo")
	if p.m.Tags["mod"] == "1" {
		p.m.User.Mod = true
	}
	delete(p.m.Tags, "mod")
	if p.m.Tags["subscriber"] == "1" {
		p.m.User.Sub = true
	}
	delete(p.m.Tags, "subscriber")
}

func (p *parse) parseExtendedTags() {
	// Parse twitch emotes from the "emotes" tag
	p.parseTwitchEmotes(p.m.Tags["emotes"])
	delete(p.m.Tags, "emotes")

	switch p.m.Tags["msg-id"] {
	case "resub":
		p.m.Type = common.MsgReSub

	case "subs_on":
		p.m.Type = common.MsgSubsOn

	case "subs_off":
		p.m.Type = common.MsgSubsOff

	case "slow_on":
		// Slow mode duration is found in the tag slow_duration
		p.m.Type = common.MsgSlowOn

	case "slow_off":
		p.m.Type = common.MsgSlowOff

	case "r9k_on":
		p.m.Type = common.MsgR9kOn

	case "r9k_off":
		p.m.Type = common.MsgR9kOff

	case "host_on":
		// Host target can be found in target_channel tag
		p.m.Type = common.MsgHostOn

	case "host_off":
		p.m.Type = common.MsgHostOff

	case "":
		break

	default:
		p.m.Type = common.MsgUnknown
	}

	if p.m.Tags["login"] != "" {
		p.m.User.Name = p.m.Tags["login"]
	}
}

/*
XXX: Should user properties stay at their zero value when there are no tags? Do we even care about this scenario?
*/
func (p *parse) parseTags(msg string) {
	p.m.Tags = make(map[string]string)
	// IRCv3-tags are separated by semicolons
	for _, tagValue := range strings.Split(msg, ";") {
		spl := strings.Split(tagValue, "=")
		k := spl[0]
		v := strings.Replace(spl[1], "\\s", " ", -1)
		p.m.Tags[k] = v
	}

	p.parseTagValues()

}

func (p *parse) parseSource(msg string) {
	msg = msg[1:]
	// Check if the source is a user
	userSepPos := strings.Index(msg, "!")
	hostSepPos := strings.Index(msg, "@")
	if userSepPos > -1 && hostSepPos > -1 && userSepPos < hostSepPos {
		// A valid user address is found!
		p.m.User.Name = msg[0:userSepPos]
	}
	log.Debug(msg)
}

func (p *parse) parseMsgType(msg string) {
	switch msg {
	case "PRIVMSG":
		p.m.Type = common.MsgPrivmsg

	case "WHISPER":
		p.m.Type = common.MsgWhisper

	case "USERNOTICE":
		p.m.Type = common.MsgUserNotice

	case "NOTICE":
		p.m.Type = common.MsgNotice

	case "ROOMSTATE":
		p.m.Type = common.MsgRoomState
	}
}

func (p *parse) parseChannel(msg string) {
	p.m.Channel = strings.Replace(msg[1:], "#", "", 0)
}

func (p *parse) parseText(msg string) {
	p.m.Text = msg[1:]

	// figure out whether the message is an ACTION or not
	p.getAction()
}

// regex in 2016 LUL
func (p *parse) getAction() {
	if strings.HasPrefix(p.m.Text, "\u0001ACTION ") && strings.HasSuffix(p.m.Text, "\u0001") {
		p.m.Me = true
		m := p.m.Text
		m = strings.Replace(m, "\u0001ACTION ", "", 1)
		m = strings.Replace(m, "\u0001", "", 1)
		p.m.Text = m
	}
}

func (p *parse) parseNewSub() {
	p.m.Type = common.MsgSub
	p.m.Length = 1
	p.m.User.DisplayName = strings.Split(p.m.Text, " ")[0]
	p.m.User.Name = strings.ToLower(p.m.User.DisplayName)
}
<commit_msg>fixed whispers<commit_after>package boss

import (
	"strconv"
	"strings"

	"github.com/pajlada/pajbot2/common"
)

type parse struct {
	m *common.Msg
}

/*
Parse parses an IRC message into a more readable bot.Msg
*/
func (p *parse) Parse(line string) common.Msg {
	p.m = &common.Msg{
		User: common.User{},
		Type: common.MsgUnknown,
	}

	// msg is the string we will keep working on/reducing as we parse things
	msg := line

	var splitLine []string

	// The message starts with @, that means there are IRCv3 tags available to parse
	if strings.HasPrefix(line, "@") {
		splitLine = strings.SplitN(msg, " ", 2)
		p.parseTags(splitLine[0][1:])
		msg = splitLine[1]
	}

	// Parse source
	splitLine = strings.SplitN(msg, " ", 2)
	p.parseSource(splitLine[0])
	msg = splitLine[1]

	// Parse message type
	splitLine = strings.SplitN(msg, " ", 2)
	p.parseMsgType(splitLine[0])
	msg = splitLine[1]

	if p.m.Type == common.MsgUnknown {
		p.m.Type = common.MsgThrowAway
		return *p.m
	}

	splitLine = strings.SplitN(msg, " ", 2)
	p.parseChannel(splitLine[0])

	if len(splitLine) == 2 {
		msg = splitLine[1]

		// Parse message text + msg type (if it's a /me message or not)
		p.parseText(msg)

		if p.m.User.Name == "twitchnotify" {
			if !strings.Contains(p.m.Text, " to ") && !strings.Contains(p.m.Text, " while ") {
				p.parseNewSub()
			}
		}
	}

	// If the destination of the message is the same as the username,
	// then we tag the user as the channel owner. This will automatically
	// give him access to broadcaster commands
	if p.m.Channel == p.m.User.Name {
		p.m.User.ChannelOwner = true
	}

	if p.m.Tags != nil {
		// Parse tags further, such as the msg-id value for determinig the msg type
		p.parseExtendedTags()
	}

	return *p.m
}

func (p *parse) parseTwitchEmotes(emotetag string) {
	// TODO: Parse more emote information (bttv (and ffz?), name, size, isGif)
	// will we done by a module in the bot itself
	p.m.Emotes = make([]common.Emote, 0)
	if emotetag == "" {
		return
	}
	emoteSlice := strings.Split(emotetag, "/")
	for i := range emoteSlice {
		spl := strings.Split(emoteSlice[i], ":")
		id := spl[0]
		e := &common.Emote{}
		e.Type = "twitch"
		e.Name = p.getEmoteName(spl[1])
		e.ID = id
		// 28 px should be fine for twitch emotes
		e.SizeX = 28
		e.SizeY = 28
		e.Count = strings.Count(emoteSlice[i], "-")
		p.m.Emotes = append(p.m.Emotes, *e)
	}
}

func (p *parse) getEmoteName(pos string) string {
	pos = strings.Split(pos, ",")[0]
	spl := strings.Split(pos, "-")
	start, _ := strconv.Atoi(spl[0])
	end, _ := strconv.Atoi(spl[1])
	runes := []rune(p.m.Text)
	name := runes[start : end+1]
	return string(name)
}

func (p *parse) parseTagValues() {
	// TODO: Parse id and color
	// color and id is pretty useless imo
	if p.m.Tags["display-name"] == "" {
		p.m.User.DisplayName = p.m.User.Name
	} else {
		p.m.User.DisplayName = p.m.Tags["display-name"]
	}
	delete(p.m.Tags, "display-name")
	p.m.User.Type = p.m.Tags["user-type"]
	delete(p.m.Tags, "user-type")
	if p.m.Tags["turbo"] == "1" {
		p.m.User.Turbo = true
	}
	delete(p.m.Tags, "turbo")
	if p.m.Tags["mod"] == "1" {
		p.m.User.Mod = true
	}
	delete(p.m.Tags, "mod")
	if p.m.Tags["subscriber"] == "1" {
		p.m.User.Sub = true
	}
	delete(p.m.Tags, "subscriber")
}

func (p *parse) parseExtendedTags() {
	// Parse twitch emotes from the "emotes" tag
	p.parseTwitchEmotes(p.m.Tags["emotes"])
	delete(p.m.Tags, "emotes")

	switch p.m.Tags["msg-id"] {
	case "resub":
		p.m.Type = common.MsgReSub

	case "subs_on":
		p.m.Type = common.MsgSubsOn

	case "subs_off":
		p.m.Type = common.MsgSubsOff

	case "slow_on":
		// Slow mode duration is found in the tag slow_duration
		p.m.Type = common.MsgSlowOn

	case "slow_off":
		p.m.Type = common.MsgSlowOff

	case "r9k_on":
		p.m.Type = common.MsgR9kOn

	case "r9k_off":
		p.m.Type = common.MsgR9kOff

	case "host_on":
		// Host target can be found in target_channel tag
		p.m.Type = common.MsgHostOn

	case "host_off":
		p.m.Type = common.MsgHostOff

	case "":
		break

	default:
		p.m.Type = common.MsgUnknown
	}

	if p.m.Tags["login"] != "" {
		p.m.User.Name = p.m.Tags["login"]
	}
}

/*
XXX: Should user properties stay at their zero value when there are no tags? Do we even care about this scenario?
*/
func (p *parse) parseTags(msg string) {
	p.m.Tags = make(map[string]string)
	// IRCv3-tags are separated by semicolons
	for _, tagValue := range strings.Split(msg, ";") {
		spl := strings.Split(tagValue, "=")
		k := spl[0]
		v := strings.Replace(spl[1], "\\s", " ", -1)
		p.m.Tags[k] = v
	}

	p.parseTagValues()

}

func (p *parse) parseSource(msg string) {
	if strings.HasPrefix(msg, ":") {
		msg = msg[1:]
	}
	// Check if the source is a user
	userSepPos := strings.Index(msg, "!")
	hostSepPos := strings.Index(msg, "@")
	if userSepPos > -1 && hostSepPos > -1 && userSepPos < hostSepPos {
		// A valid user address is found!
		p.m.User.Name = msg[0:userSepPos]
	}
	log.Debug(msg)
}

func (p *parse) parseMsgType(msg string) {
	switch msg {
	case "PRIVMSG":
		p.m.Type = common.MsgPrivmsg

	case "WHISPER":
		p.m.Type = common.MsgWhisper

	case "USERNOTICE":
		p.m.Type = common.MsgUserNotice

	case "NOTICE":
		p.m.Type = common.MsgNotice

	case "ROOMSTATE":
		p.m.Type = common.MsgRoomState
	}
}

func (p *parse) parseChannel(msg string) {
	p.m.Channel = strings.Replace(msg[1:], "#", "", 0)
}

func (p *parse) parseText(msg string) {
	p.m.Text = msg[1:]

	// figure out whether the message is an ACTION or not
	p.getAction()
}

// regex in 2016 LUL
func (p *parse) getAction() {
	if strings.HasPrefix(p.m.Text, "\u0001ACTION ") && strings.HasSuffix(p.m.Text, "\u0001") {
		p.m.Me = true
		m := p.m.Text
		m = strings.Replace(m, "\u0001ACTION ", "", 1)
		m = strings.Replace(m, "\u0001", "", 1)
		p.m.Text = m
	}
}

func (p *parse) parseNewSub() {
	p.m.Type = common.MsgSub
	p.m.Length = 1
	p.m.User.DisplayName = strings.Split(p.m.Text, " ")[0]
	p.m.User.Name = strings.ToLower(p.m.User.DisplayName)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	//"fmt"
	"encoding/binary"
	"image"
	"log"
	"net"
	"reflect"
	"time"

	"azul3d.org/gfx.v1"
	"azul3d.org/gfx/window.v2"
	"azul3d.org/keyboard.v1"
	"azul3d.org/mouse.v1"
	"github.com/xa4a/go-roomba"
)

const (
	defaultSerial  = "/dev/cu.usbserial-DA017N8D"
	velocityChange = 300
	rotationChange = 400
)

var (
	serialPort = flag.String("serial", defaultSerial, "Local serial port name.")
	remoteAddr = flag.String("remote", "", "Remote Roomba's network address and port.")
	modes      = []string{"Off", "Passive", "Safe", "Full"}
)

type TimeEvent struct{}

func (e *TimeEvent) Time() time.Time {
	return time.Now()
}

type SensorInfo struct {
	voltage  uint
	current  int
	temp     int
	charge   uint
	capacity uint
	// TODO - add enum for mode (careful, can get whacky modes...)
	mode uint
}

func getSensorInfo(bot *roomba.Roomba) (*SensorInfo, error) {
	si := &SensorInfo{}
	log.Println()
	log.Printf("GETTING SENSOR INFO")
	// TODO - check for error return from sensor stuff
	si.voltage, _ = sensorU16(bot, 22)
	log.Printf("Voltage: %dmV", si.voltage)

	si.current, _ = sensorS16(bot, 23)
	log.Printf("Current: %dmA", si.current)

	si.temp, _ = sensorS8(bot, 24)
	log.Printf("Temp: %dC", si.temp)

	si.charge, _ = sensorU16(bot, 25)
	log.Printf("Charge: %dmAh", si.charge)

	si.capacity, _ = sensorU16(bot, 26)
	log.Printf("Capacity: %dmAh", si.capacity)

	si.mode, _ = sensorU8(bot, 35)
	log.Printf("Mode: %d", si.mode)

	log.Println()

	return si, nil
}

func makeRemoteRoomba(remoteAddr string) (*roomba.Roomba, error) {
	// from MakeRoomba()...
	roomba := &roomba.Roomba{PortName: remoteAddr, StreamPaused: make(chan bool, 1)}
	conn, err := net.Dial("tcp", remoteAddr)
	if err != nil {
		return nil, err
	}
	roomba.S = conn
	return roomba, nil
}

func sensorS8(bot *roomba.Roomba, sensor byte) (int, error) {
	bytes, err := bot.Sensors(sensor)
	if err != nil {
		return 0, err
	}
	//log.Printf(" s8 bytes %v", bytes)
	val := bytes[0]
	return int(val), nil
}

func sensorS16(bot *roomba.Roomba, sensor byte) (int, error) {
	bytes, err := bot.Sensors(sensor)
	if err != nil {
		return 0, err
	}
	//log.Printf(" s16 bytes %v", bytes)
	val := binary.BigEndian.Uint16(bytes)
	return int(val), nil
}

func sensorU8(bot *roomba.Roomba, sensor byte) (uint, error) {
	bytes, err := bot.Sensors(sensor)
	if err != nil {
		return 0, err
	}
	//log.Printf(" u8 bytes %v", bytes)
	val := bytes[0]
	return uint(val), nil
}

func sensorU16(bot *roomba.Roomba, sensor byte) (uint, error) {
	bytes, err := bot.Sensors(sensor)
	if err != nil {
		return 0, err
	}
	//log.Printf(" u16 bytes %v", bytes)
	val := binary.BigEndian.Uint16(bytes)
	return uint(val), nil
}

// gfxLoop is responsible for drawing things to the window.
func gfxLoop(w window.Window, r gfx.Renderer) {

	log.Printf("gfxLoop")
	flag.Parse()

	// Who we gonna call? Default to local serial unless a remote addr was given
	var bot *roomba.Roomba
	if *remoteAddr != "" {
		log.Printf("Connecting to remote Doombot @ %s", *remoteAddr)
		var err error
		bot, err = makeRemoteRoomba(*remoteAddr)
		if err != nil {
			log.Fatalf("Connecting to remote Doombot @ %s failed", *remoteAddr)
		}
	} else {
		log.Printf("Connecting to local serial Doombot @ %s", *serialPort)
		var err error
		bot, err = roomba.MakeRoomba(*serialPort)
		if err != nil {
			log.Fatalf("Connecting to local serial Doombot @ %s failed", *serialPort)
		}
	}

	// Start the Doombot & put it into Safe mode
	log.Println()
	log.Printf("Starting Doombot %s", bot.PortName)
	err := bot.Start()
	if err != nil {
		log.Fatal("Starting failed")
	}

	mode, _ := sensorU8(bot, 35)
	log.Printf("Mode: %d", mode)
	//log.Printf("Mode: %s", modes[mode])

	charging, _ := sensorU8(bot, 21)
	log.Printf("Charging state: %d", charging)
	log.Println()

	log.Printf("Entering Safe mode")
	err = bot.Safe()
	if err != nil {
		log.Fatal("Entering Safe mode failed")
	}
	log.Println()

	charging, _ = sensorU8(bot, 21)
	log.Printf("Charging state: %d", charging)
	/*
		0 Not charging
		1 Reconditioning Charging 2 Full Charging
		3 Trickle Charging
		4 Waiting
		5 Charging Fault Condition
	*/

	// to be populated by a timer and dumped to the UI
	var sensor *SensorInfo

	// Create our events channel with sufficient buffer size.
	events := make(chan window.Event, 256)

	// collect sensor data in a separate goroutine
	go func() {
		time.Sleep(500)
		events <- &TimeEvent{}
	}()

	// Handle window events in a seperate goroutine
	go func() {
		// Notify our channel anytime any event occurs.
		w.Notify(events, window.AllEvents)

		log.Printf("Event handler gorouting running")

		// Wait for events.
		for event := range events {
			switch event.(type) {
			case keyboard.StateEvent:
				log.Println()
				log.Printf("Event type %s: %v", reflect.TypeOf(event), event)
				ke := event.(keyboard.StateEvent)

				motionChange := ke.Key == keyboard.ArrowUp || ke.Key == keyboard.ArrowDown ||
					ke.Key == keyboard.ArrowLeft || ke.Key == keyboard.ArrowRight

				if motionChange {
					velocity := 0
					if w.Keyboard().Down(keyboard.ArrowUp) {
						velocity = velocityChange
					}
					if w.Keyboard().Down(keyboard.ArrowDown) {
						velocity = -velocityChange
					}
					rotation := 0
					if w.Keyboard().Down(keyboard.ArrowLeft) {
						rotation = rotationChange
					}
					if w.Keyboard().Down(keyboard.ArrowRight) {
						rotation = -rotationChange
					}

					// compute left and right wheel velocities
					vr := velocity + (rotation / 2)
					vl := velocity - (rotation / 2)

					log.Printf("Updating Right:%d Left:%d", vr, vl)
					bot.DirectDrive(int16(vr), int16(vl))

				} else {
					if w.Keyboard().Down(keyboard.R) {
						log.Printf("Resetting to safe mode")
						err = bot.Start()
						err = bot.Safe()
						if err != nil {
							log.Fatal("Entering Safe mode failed")
						}
					} else if w.Keyboard().Down(keyboard.D) {
						log.Printf("Seeking Dock")
						err = bot.WriteByte(143) // Seek Dock
					}
				}
			case *TimeEvent:
				// grab all the sensor info
				sensor, _ = getSensorInfo(bot)
			}
		}
	}()

	// cheesy block direction signals
	upArr := image.Rect(100, 0, 100+100, 0+100)
	dnArr := image.Rect(100, 200, 100+100, 200+100)
	lfArr := image.Rect(0, 100, 0+100, 100+100)
	rtArr := image.Rect(200, 100, 200+100, 100+100)

	for {
		//log.Printf("Rendering")
		// Clear the entire area (empty rectangle means "the whole area").
		r.Clear(image.Rect(0, 0, 0, 0), gfx.Color{1, 1, 1, 1})

		// The keyboard is monitored for you, simply check if a key is down:
		if w.Keyboard().Down(keyboard.ArrowUp) {
			// Clear a red rectangle.
			r.Clear(upArr, gfx.Color{1, 0, 0, 1})
		}
		if w.Keyboard().Down(keyboard.ArrowDown) {
			// Clear a red rectangle.
			r.Clear(dnArr, gfx.Color{1, 0, 0, 1})
		}
		if w.Keyboard().Down(keyboard.ArrowLeft) {
			// Clear a red rectangle.
			r.Clear(lfArr, gfx.Color{1, 0, 0, 1})
		}
		if w.Keyboard().Down(keyboard.ArrowRight) {
			// Clear a red rectangle.
			r.Clear(rtArr, gfx.Color{1, 0, 0, 1})
		}

		if w.Keyboard().Down(keyboard.Q) {
			log.Println()
			log.Printf("Quitting")
			bot.Stop()         // Motor Stop
			bot.WriteByte(173) // Create 2 Stop
			//bot.Power()

			w.Close()
		}

		// And the same thing with the mouse, check if a mouse button is down:
		if w.Mouse().Down(mouse.Left) {
			// Clear a blue rectangle.
			r.Clear(image.Rect(100, 100, 200, 200), gfx.Color{0, 0, 1, 1})
		}

		// Render the whole frame.
		r.Render()
	}
}

func main() {
	log.Printf("Main")
	window.Run(gfxLoop, nil)
}
<commit_msg>improvements to d-pad on screen<commit_after>package main

import (
	"flag"
	//"fmt"
	"encoding/binary"
	"image"
	"log"
	"net"
	"reflect"
	"time"

	"azul3d.org/gfx.v1"
	"azul3d.org/gfx/window.v2"
	"azul3d.org/keyboard.v1"
	"azul3d.org/mouse.v1"
	"github.com/xa4a/go-roomba"
)

const (
	defaultSerial  = "/dev/cu.usbserial-DA017N8D"
	velocityChange = 300
	rotationChange = 400
)

var (
	serialPort = flag.String("serial", defaultSerial, "Local serial port name.")
	remoteAddr = flag.String("remote", "", "Remote Roomba's network address and port.")
	modes      = []string{"Off", "Passive", "Safe", "Full"}
)

type TimeEvent struct{}

func (e *TimeEvent) Time() time.Time {
	return time.Now()
}

type SensorInfo struct {
	voltage  uint
	current  int
	temp     int
	charge   uint
	capacity uint
	// TODO - add enum for mode (careful, can get whacky modes...)
	mode uint
}

func getSensorInfo(bot *roomba.Roomba) (*SensorInfo, error) {
	si := &SensorInfo{}
	log.Println()
	log.Printf("GETTING SENSOR INFO")
	// TODO - check for error return from sensor stuff
	si.voltage, _ = sensorU16(bot, 22)
	log.Printf("Voltage: %dmV", si.voltage)

	si.current, _ = sensorS16(bot, 23)
	log.Printf("Current: %dmA", si.current)

	si.temp, _ = sensorS8(bot, 24)
	log.Printf("Temp: %dC", si.temp)

	si.charge, _ = sensorU16(bot, 25)
	log.Printf("Charge: %dmAh", si.charge)

	si.capacity, _ = sensorU16(bot, 26)
	log.Printf("Capacity: %dmAh", si.capacity)

	si.mode, _ = sensorU8(bot, 35)
	log.Printf("Mode: %d", si.mode)

	log.Println()

	return si, nil
}

func makeRemoteRoomba(remoteAddr string) (*roomba.Roomba, error) {
	// from MakeRoomba()...
	roomba := &roomba.Roomba{PortName: remoteAddr, StreamPaused: make(chan bool, 1)}
	conn, err := net.Dial("tcp", remoteAddr)
	if err != nil {
		return nil, err
	}
	roomba.S = conn
	return roomba, nil
}

func sensorS8(bot *roomba.Roomba, sensor byte) (int, error) {
	bytes, err := bot.Sensors(sensor)
	if err != nil {
		return 0, err
	}
	//log.Printf(" s8 bytes %v", bytes)
	val := bytes[0]
	return int(val), nil
}

func sensorS16(bot *roomba.Roomba, sensor byte) (int, error) {
	bytes, err := bot.Sensors(sensor)
	if err != nil {
		return 0, err
	}
	//log.Printf(" s16 bytes %v", bytes)
	val := binary.BigEndian.Uint16(bytes)
	return int(val), nil
}

func sensorU8(bot *roomba.Roomba, sensor byte) (uint, error) {
	bytes, err := bot.Sensors(sensor)
	if err != nil {
		return 0, err
	}
	//log.Printf(" u8 bytes %v", bytes)
	val := bytes[0]
	return uint(val), nil
}

func sensorU16(bot *roomba.Roomba, sensor byte) (uint, error) {
	bytes, err := bot.Sensors(sensor)
	if err != nil {
		return 0, err
	}
	//log.Printf(" u16 bytes %v", bytes)
	val := binary.BigEndian.Uint16(bytes)
	return uint(val), nil
}

// gfxLoop is responsible for drawing things to the window.
func gfxLoop(w window.Window, r gfx.Renderer) {

	log.Printf("gfxLoop")
	flag.Parse()

	// Who we gonna call? Default to local serial unless a remote addr was given
	var bot *roomba.Roomba
	if *remoteAddr != "" {
		log.Printf("Connecting to remote Doombot @ %s", *remoteAddr)
		var err error
		bot, err = makeRemoteRoomba(*remoteAddr)
		if err != nil {
			log.Fatalf("Connecting to remote Doombot @ %s failed", *remoteAddr)
		}
	} else {
		log.Printf("Connecting to local serial Doombot @ %s", *serialPort)
		var err error
		bot, err = roomba.MakeRoomba(*serialPort)
		if err != nil {
			log.Fatalf("Connecting to local serial Doombot @ %s failed", *serialPort)
		}
	}

	// Start the Doombot & put it into Safe mode
	log.Println()
	log.Printf("Starting Doombot %s", bot.PortName)
	err := bot.Start()
	if err != nil {
		log.Fatal("Starting failed")
	}

	mode, _ := sensorU8(bot, 35)
	log.Printf("Mode: %d", mode)
	//log.Printf("Mode: %s", modes[mode])

	charging, _ := sensorU8(bot, 21)
	log.Printf("Charging state: %d", charging)
	log.Println()

	log.Printf("Entering Safe mode")
	err = bot.Safe()
	if err != nil {
		log.Fatal("Entering Safe mode failed")
	}
	log.Println()

	charging, _ = sensorU8(bot, 21)
	log.Printf("Charging state: %d", charging)
	/*
		0 Not charging
		1 Reconditioning Charging 2 Full Charging
		3 Trickle Charging
		4 Waiting
		5 Charging Fault Condition
	*/

	// to be populated by a timer and dumped to the UI
	var sensor *SensorInfo

	// Create our events channel with sufficient buffer size.
	events := make(chan window.Event, 256)

	// collect sensor data in a separate goroutine
	go func() {
		time.Sleep(500)
		events <- &TimeEvent{}
	}()

	// Handle window events in a seperate goroutine
	go func() {
		// Notify our channel anytime any event occurs.
		w.Notify(events, window.AllEvents)

		log.Printf("Event handler gorouting running")

		// Wait for events.
		for event := range events {
			switch event.(type) {
			case keyboard.StateEvent:
				log.Println()
				log.Printf("Event type %s: %v", reflect.TypeOf(event), event)
				ke := event.(keyboard.StateEvent)

				motionChange := ke.Key == keyboard.ArrowUp || ke.Key == keyboard.ArrowDown ||
					ke.Key == keyboard.ArrowLeft || ke.Key == keyboard.ArrowRight

				if motionChange {
					velocity := 0
					if w.Keyboard().Down(keyboard.ArrowUp) {
						velocity = velocityChange
					}
					if w.Keyboard().Down(keyboard.ArrowDown) {
						velocity = -velocityChange
					}
					rotation := 0
					if w.Keyboard().Down(keyboard.ArrowLeft) {
						rotation = rotationChange
					}
					if w.Keyboard().Down(keyboard.ArrowRight) {
						rotation = -rotationChange
					}

					// compute left and right wheel velocities
					vr := velocity + (rotation / 2)
					vl := velocity - (rotation / 2)

					log.Printf("Updating Right:%d Left:%d", vr, vl)
					bot.DirectDrive(int16(vr), int16(vl))

				} else {
					if w.Keyboard().Down(keyboard.R) {
						log.Printf("Resetting to safe mode")
						err = bot.Start()
						err = bot.Safe()
						if err != nil {
							log.Fatal("Entering Safe mode failed")
						}
					} else if w.Keyboard().Down(keyboard.D) {
						log.Printf("Seeking Dock")
						err = bot.WriteByte(143) // Seek Dock
					}
				}
			case *TimeEvent:
				// grab all the sensor info
				sensor, _ = getSensorInfo(bot)
			}
		}
	}()

	// cheesy block direction signals
	upArr := image.Rect(150, 100, 150+50, 100+50)
	dnArr := image.Rect(150, 200, 150+50, 200+50)
	lfArr := image.Rect(100, 150, 100+50, 150+50)
	rtArr := image.Rect(200, 150, 200+50, 150+50)

	for {
		//log.Printf("Rendering")
		// Clear the entire area (empty rectangle means "the whole area").
		r.Clear(image.Rect(0, 0, 0, 0), gfx.Color{1, 1, 1, 1})

		r.Clear(upArr, gfx.Color{0.5, 0, 0, 0.1})
		r.Clear(dnArr, gfx.Color{0.5, 0, 0, 0.1})
		r.Clear(lfArr, gfx.Color{0.5, 0, 0, 0.1})
		r.Clear(rtArr, gfx.Color{0.5, 0, 0, 0.1})
		// The keyboard is monitored for you, simply check if a key is down:
		if w.Keyboard().Down(keyboard.ArrowUp) {
			// Clear a red rectangle.
			r.Clear(upArr, gfx.Color{1, 0, 0, 1})
		}
		if w.Keyboard().Down(keyboard.ArrowDown) {
			// Clear a red rectangle.
			r.Clear(dnArr, gfx.Color{1, 0, 0, 1})
		}
		if w.Keyboard().Down(keyboard.ArrowLeft) {
			// Clear a red rectangle.
			r.Clear(lfArr, gfx.Color{1, 0, 0, 1})
		}
		if w.Keyboard().Down(keyboard.ArrowRight) {
			// Clear a red rectangle.
			r.Clear(rtArr, gfx.Color{1, 0, 0, 1})
		}

		if w.Keyboard().Down(keyboard.Q) {
			log.Println()
			log.Printf("Quitting")
			bot.Stop()         // Motor Stop
			bot.WriteByte(173) // Create 2 Stop
			//bot.Power()

			w.Close()
		}

		// And the same thing with the mouse, check if a mouse button is down:
		if w.Mouse().Down(mouse.Left) {
			// Clear a blue rectangle.
			r.Clear(image.Rect(100, 100, 200, 200), gfx.Color{0, 0, 1, 1})
		}

		// Render the whole frame.
		r.Render()
	}
}

func main() {
	log.Printf("Main")
	window.Run(gfxLoop, nil)
}
<|endoftext|>


<commit_before>// This package provides a framework for creating powerful lexical
// preprocessors for go code.
package goprep

import (
	"fmt"
	"io"
	"io/ioutil"
	"go/printer"
	"go/parser"
	"go/scanner"
	"go/token"
	"os"
)

// Represents a token as returned by scanner.Scanner.Scan(), with the position,
// token type, and string representation.
type TokenInfo struct {
	Pos   token.Pos
	Token token.Token
	Str   string
}

// StdInit initializes appropriate processing channels for os.Stdin and
// os.Stdout. For the most part, this should be used instead of specific calls
// to Write and Read.
func StdInit() (<-chan TokenInfo, chan<- string, <-chan interface{}) {
	tokIn := Read(os.Stdin)
	tokOut, done := Write(os.Stdout)
	return tokIn, tokOut, done
}

// Write allows writing properly formatted go code to a given io.Writer via a
// series of token strings passed to the returned channel. The second returned
// channel will have a single nil value sent when writing is complete.
func Write(output io.Writer) (chan<- string, <-chan interface{}) {
	tokC := make(chan string)
	done := make(chan interface{})

	reader, writer := io.Pipe()

	// spit the tokens to the write end of the pipe
	go func(output io.WriteCloser, tokC <-chan string) {
		for tok := range tokC {
			fmt.Fprintf(output, " %s", tok)
		}
		output.Close()
	}(writer, tokC)

	// parse the tokens into an AST and write to output
	go func(reader io.ReadCloser, output io.Writer, done chan interface{}) {
		fset := token.NewFileSet()
		file, err := parser.ParseFile(
			fset, "<stdin>", reader, parser.ParseComments)
		if err != nil {
			panic(err)
		}
		printer.Fprint(output, fset, file)
		done <- nil
	}(reader, output, done)

	return tokC, done
}

// Read reads from the given io.Reader and writes a series of TokenInfo objects
// to the returned channel.
func Read(input io.Reader) <-chan TokenInfo {
	// start reading
	src, err := ioutil.ReadAll(input)
	if err != nil { panic(err) }

	fset := token.NewFileSet()
	file := fset.AddFile("<stdin>", fset.Base(), len(src))

	s := scanner.Scanner{}
	s.Init(file, src, nil, scanner.InsertSemis | scanner.ScanComments)

	tokC := make(chan TokenInfo)

	go func(s scanner.Scanner, tokC chan<- TokenInfo) {
		pos, tok, str := s.Scan()
		for tok != token.EOF {
			if tok == token.COMMENT {
				str = str + "\n"
			}
			tokC <- TokenInfo{pos, tok, str}
			pos, tok, str = s.Scan()
		}
		close(tokC)
	}(s, tokC)

	return tokC
}

func Ignore(tIn <-chan TokenInfo, out chan<- string, f func(TokenInfo) bool) <-chan TokenInfo {
	tOut := make(chan TokenInfo)
	go func() {
		for tok := range tIn {
			if !f(tok) {
				tOut <- tok
			}
		}
		close(tOut)
	}()
	return tOut
}
<commit_msg>Documentation<commit_after>// This package provides a framework for creating powerful lexical
// preprocessors for go code.
package goprep

import (
	"fmt"
	"io"
	"io/ioutil"
	"go/printer"
	"go/parser"
	"go/scanner"
	"go/token"
	"os"
)

// Represents a token as returned by scanner.Scanner.Scan(), with the position,
// token type, and string representation.
type TokenInfo struct {
	Pos   token.Pos
	Token token.Token
	Str   string
}

// StdInit initializes appropriate processing channels for os.Stdin and
// os.Stdout. For the most part, this should be used instead of specific calls
// to Write and Read.
func StdInit() (<-chan TokenInfo, chan<- string, <-chan interface{}) {
	tokIn := Read(os.Stdin)
	tokOut, done := Write(os.Stdout)
	return tokIn, tokOut, done
}

// Write allows writing properly formatted go code to a given io.Writer via a
// series of token strings passed to the returned channel. The second returned
// channel will have a single nil value sent when writing is complete.
func Write(output io.Writer) (chan<- string, <-chan interface{}) {
	tokC := make(chan string)
	done := make(chan interface{})

	reader, writer := io.Pipe()

	// spit the tokens to the write end of the pipe
	go func(output io.WriteCloser, tokC <-chan string) {
		for tok := range tokC {
			fmt.Fprintf(output, " %s", tok)
		}
		output.Close()
	}(writer, tokC)

	// parse the tokens into an AST and write to output
	go func(reader io.ReadCloser, output io.Writer, done chan interface{}) {
		fset := token.NewFileSet()
		file, err := parser.ParseFile(
			fset, "<stdin>", reader, parser.ParseComments)
		if err != nil {
			panic(err)
		}
		printer.Fprint(output, fset, file)
		done <- nil
	}(reader, output, done)

	return tokC, done
}

// Read reads from the given io.Reader and writes a series of TokenInfo objects
// to the returned channel.
func Read(input io.Reader) <-chan TokenInfo {
	// start reading
	src, err := ioutil.ReadAll(input)
	if err != nil { panic(err) }

	fset := token.NewFileSet()
	file := fset.AddFile("<stdin>", fset.Base(), len(src))

	s := scanner.Scanner{}
	s.Init(file, src, nil, scanner.InsertSemis | scanner.ScanComments)

	tokC := make(chan TokenInfo)

	go func(s scanner.Scanner, tokC chan<- TokenInfo) {
		pos, tok, str := s.Scan()
		for tok != token.EOF {
			if tok == token.COMMENT {
				str = str + "\n"
			}
			tokC <- TokenInfo{pos, tok, str}
			pos, tok, str = s.Scan()
		}
		close(tokC)
	}(s, tokC)

	return tokC
}

// Ignore produces a modified input stream that does not include any tokens for
// which f evaluates to true.
func Ignore(tIn <-chan TokenInfo, out chan<- string, f func(TokenInfo) bool) <-chan TokenInfo {
	tOut := make(chan TokenInfo)
	go func() {
		for tok := range tIn {
			if !f(tok) {
				tOut <- tok
			}
		}
		close(tOut)
	}()
	return tOut
}
<|endoftext|>


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

package rnd

import (
	"math/rand"
	"testing"
)

var __bench_nsamples int
var __bench_ints []int
var __bench_result int

func init() {
	rand.Seed(4321)
	Init(4321)
	__bench_nsamples = 1000
	__bench_ints = make([]int, __bench_nsamples)
	for i := 0; i < __bench_nsamples; i++ {
		__bench_ints[i] = i
	}
}

func Benchmark_go_int(b *testing.B) {
	var res int
	lo, hi := 0, 50
	for i := 0; i < b.N; i++ {
		for j := 0; j < __bench_nsamples; j++ {
			res = Int(lo, hi)
		}
	}
	__bench_result = res
}
<commit_msg>Rename vars<commit_after>// Copyright 2016 The Gosl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package rnd

import (
	"math/rand"
	"testing"
)

var (
	benchNsamples int
	benchInts     []int
	benchResult   int
)

func init() {
	rand.Seed(4321)
	Init(4321)
	benchNsamples = 1000
	benchInts = make([]int, benchNsamples)
	for i := 0; i < benchNsamples; i++ {
		benchInts[i] = i
	}
}

func Benchmark_go_int(b *testing.B) {
	var res int
	lo, hi := 0, 50
	for i := 0; i < b.N; i++ {
		for j := 0; j < benchNsamples; j++ {
			res = Int(lo, hi)
		}
	}
	benchResult = res
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/KIT-MAMID/mamid/msp"
	. "github.com/KIT-MAMID/mamid/slave"
	"golang.org/x/sys/unix"
	"os/exec"
)

const MongodExecutableDefaultName = "mongod"

func main() {

	var (
		mongodExecutable, dataDir string
	)

	flag.StringVar(&dataDir, "data", "", "Persistent data and slave configuration directory")
	mongodExecutableLookupPath, _ := exec.LookPath(MongodExecutableDefaultName)
	flag.StringVar(&mongodExecutable, "mongodExecutable", mongodExecutableLookupPath, "Path to or name of Mongod binary")

	flag.Parse()

	if dataDir == "" {
		println("No root data directory passed; specify with -data=/path/to/root/dir")
		return
	}

	if err := unix.Access(dataDir, unix.W_OK); err != nil {
		println(fmt.Sprintf("Root data directory %s does not exist or is not writable", dataDir))
		return
	}
	dbDir := fmt.Sprintf("%s/%s", dataDir, DataDBDir)
	if err := unix.Access(dbDir, unix.R_OK|unix.W_OK|unix.X_OK); err != nil {
		if err := unix.Mkdir(dbDir, 0700); err != nil {
			fmt.Printf("Could not create a readable and writable directory at %s", dbDir)
			return
		}
	}

	controller := NewController(mongodExecutable, dataDir)
	server := msp.NewServer(controller)
	server.Run()
}
<commit_msg>UPD: slave: log error on failure.<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/KIT-MAMID/mamid/msp"
	. "github.com/KIT-MAMID/mamid/slave"
	"golang.org/x/sys/unix"
	"os/exec"
)

const MongodExecutableDefaultName = "mongod"

func main() {

	var (
		mongodExecutable, dataDir string
	)

	flag.StringVar(&dataDir, "data", "", "Persistent data and slave configuration directory")
	mongodExecutableLookupPath, _ := exec.LookPath(MongodExecutableDefaultName)
	flag.StringVar(&mongodExecutable, "mongodExecutable", mongodExecutableLookupPath, "Path to or name of Mongod binary")

	flag.Parse()

	if dataDir == "" {
		println("No root data directory passed; specify with -data=/path/to/root/dir")
		return
	}

	if err := unix.Access(dataDir, unix.W_OK); err != nil {
		println(fmt.Sprintf("Root data directory %s does not exist or is not writable", dataDir))
		return
	}
	dbDir := fmt.Sprintf("%s/%s", dataDir, DataDBDir)
	if err := unix.Access(dbDir, unix.R_OK|unix.W_OK|unix.X_OK); err != nil {
		if err := unix.Mkdir(dbDir, 0700); err != nil {
			fmt.Printf("Could not create a readable and writable directory at %s: %s", dbDir, err)
			return
		}
	}

	controller := NewController(mongodExecutable, dataDir)
	server := msp.NewServer(controller)
	server.Run()
}
<|endoftext|>


<commit_before>package routing

/*
Copyright 2019 Crunchy Data Solutions, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

import (
	"github.com/crunchydata/postgres-operator/apiserver/backrestservice"
	"github.com/crunchydata/postgres-operator/apiserver/backupservice"
	"github.com/crunchydata/postgres-operator/apiserver/benchmarkservice"
	"github.com/crunchydata/postgres-operator/apiserver/catservice"
	"github.com/crunchydata/postgres-operator/apiserver/cloneservice"
	"github.com/crunchydata/postgres-operator/apiserver/clusterservice"
	"github.com/crunchydata/postgres-operator/apiserver/configservice"
	"github.com/crunchydata/postgres-operator/apiserver/dfservice"
	"github.com/crunchydata/postgres-operator/apiserver/failoverservice"
	"github.com/crunchydata/postgres-operator/apiserver/labelservice"
	"github.com/crunchydata/postgres-operator/apiserver/loadservice"
	"github.com/crunchydata/postgres-operator/apiserver/lsservice"
	"github.com/crunchydata/postgres-operator/apiserver/namespaceservice"
	"github.com/crunchydata/postgres-operator/apiserver/pgbouncerservice"
	"github.com/crunchydata/postgres-operator/apiserver/pgdumpservice"
	"github.com/crunchydata/postgres-operator/apiserver/pgoroleservice"
	"github.com/crunchydata/postgres-operator/apiserver/pgouserservice"
	"github.com/crunchydata/postgres-operator/apiserver/policyservice"
	"github.com/crunchydata/postgres-operator/apiserver/pvcservice"
	"github.com/crunchydata/postgres-operator/apiserver/reloadservice"
	"github.com/crunchydata/postgres-operator/apiserver/scheduleservice"
	"github.com/crunchydata/postgres-operator/apiserver/statusservice"
	"github.com/crunchydata/postgres-operator/apiserver/upgradeservice"
	"github.com/crunchydata/postgres-operator/apiserver/userservice"
	"github.com/crunchydata/postgres-operator/apiserver/versionservice"
	"github.com/crunchydata/postgres-operator/apiserver/workflowservice"

	"github.com/gorilla/mux"
)

// RegisterAllRoutes adds all routes supported by the apiserver to the
// provided router
func RegisterAllRoutes(r *mux.Router) {
	r.HandleFunc("/version", versionservice.VersionHandler)
	r.HandleFunc("/health", versionservice.HealthHandler)
	r.HandleFunc("/policies", policyservice.CreatePolicyHandler)
	r.HandleFunc("/showpolicies", policyservice.ShowPolicyHandler).Methods("POST")
	r.HandleFunc("/policiesdelete", policyservice.DeletePolicyHandler).Methods("POST")
	r.HandleFunc("/workflow/{id}", workflowservice.ShowWorkflowHandler).Methods("GET")
	r.HandleFunc("/showpvc", pvcservice.ShowPVCHandler).Methods("POST")
	r.HandleFunc("/pgouserupdate", pgouserservice.UpdatePgouserHandler).Methods("POST")
	r.HandleFunc("/pgouserdelete", pgouserservice.DeletePgouserHandler).Methods("POST")
	r.HandleFunc("/pgousercreate", pgouserservice.CreatePgouserHandler).Methods("POST")
	r.HandleFunc("/pgousershow", pgouserservice.ShowPgouserHandler).Methods("POST")
	r.HandleFunc("/pgoroleupdate", pgoroleservice.UpdatePgoroleHandler).Methods("POST")
	r.HandleFunc("/pgoroledelete", pgoroleservice.DeletePgoroleHandler).Methods("POST")
	r.HandleFunc("/pgorolecreate", pgoroleservice.CreatePgoroleHandler).Methods("POST")
	r.HandleFunc("/pgoroleshow", pgoroleservice.ShowPgoroleHandler).Methods("POST")
	r.HandleFunc("/policies/apply", policyservice.ApplyPolicyHandler).Methods("POST")
	r.HandleFunc("/label", labelservice.LabelHandler).Methods("POST")
	r.HandleFunc("/labeldelete", labelservice.DeleteLabelHandler).Methods("POST")
	r.HandleFunc("/load", loadservice.LoadHandler).Methods("POST")

	r.HandleFunc("/userupdate", userservice.UpdateUserHandler).Methods("POST")
	r.HandleFunc("/usercreate", userservice.CreateUserHandler).Methods("POST")
	r.HandleFunc("/usershow", userservice.ShowUserHandler).Methods("POST")
	r.HandleFunc("/userdelete", userservice.DeleteUserHandler).Methods("POST")

	r.HandleFunc("/upgrades", upgradeservice.CreateUpgradeHandler).Methods("POST")
	r.HandleFunc("/clusters", clusterservice.CreateClusterHandler).Methods("POST")
	r.HandleFunc("/showclusters", clusterservice.ShowClusterHandler).Methods("POST")
	r.HandleFunc("/clustersdelete", clusterservice.DeleteClusterHandler).Methods("POST")
	r.HandleFunc("/clustersupdate", clusterservice.UpdateClusterHandler).Methods("POST")
	r.HandleFunc("/testclusters", clusterservice.TestClusterHandler).Methods("POST")
	r.HandleFunc("/clusters/scale/{name}", clusterservice.ScaleClusterHandler)
	r.HandleFunc("/scale/{name}", clusterservice.ScaleQueryHandler).Methods("GET")
	r.HandleFunc("/scaledown/{name}", clusterservice.ScaleDownHandler).Methods("GET")
	r.HandleFunc("/status", statusservice.StatusHandler)
	r.HandleFunc("/df/{name}", dfservice.DfHandler)
	r.HandleFunc("/config", configservice.ShowConfigHandler)
	r.HandleFunc("/namespace", namespaceservice.ShowNamespaceHandler).Methods("POST")
	r.HandleFunc("/namespacedelete", namespaceservice.DeleteNamespaceHandler).Methods("POST")
	r.HandleFunc("/namespacecreate", namespaceservice.CreateNamespaceHandler).Methods("POST")
	r.HandleFunc("/namespaceupdate", namespaceservice.UpdateNamespaceHandler).Methods("POST")

	// backups / backrest
	r.HandleFunc("/backups/{name}", backupservice.ShowBackupHandler).Methods("GET")
	r.HandleFunc("/backupsdelete/{name}", backupservice.DeleteBackupHandler).Methods("GET")
	r.HandleFunc("/backups", backupservice.CreateBackupHandler).Methods("POST")
	r.HandleFunc("/pgbasebackuprestore", backupservice.RestoreHandler).Methods("POST")
	r.HandleFunc("/backrestbackup", backrestservice.CreateBackupHandler).Methods("POST")
	r.HandleFunc("/backrest/{name}", backrestservice.ShowBackrestHandler).Methods("GET")
	r.HandleFunc("/restore", backrestservice.RestoreHandler).Methods("POST")

	// pgdump
	r.HandleFunc("/pgdumpbackup", pgdumpservice.BackupHandler).Methods("POST")
	r.HandleFunc("/pgdump/{name}", pgdumpservice.ShowDumpHandler).Methods("GET")
	r.HandleFunc("/pgdumprestore", pgdumpservice.RestoreHandler).Methods("POST")

	r.HandleFunc("/reload", reloadservice.ReloadHandler).Methods("POST")
	r.HandleFunc("/ls", lsservice.LsHandler).Methods("POST")
	r.HandleFunc("/cat", catservice.CatHandler).Methods("POST")
	r.HandleFunc("/failover", failoverservice.CreateFailoverHandler).Methods("POST")
	r.HandleFunc("/failover/{name}", failoverservice.QueryFailoverHandler).Methods("GET")
	r.HandleFunc("/pgbouncer", pgbouncerservice.CreatePgbouncerHandler).Methods("POST")
	r.HandleFunc("/pgbouncer", pgbouncerservice.DeletePgbouncerHandler).Methods("DELETE")
	r.HandleFunc("/pgbouncerdelete", pgbouncerservice.DeletePgbouncerHandler).Methods("POST")

	//schedule
	r.HandleFunc("/schedule", scheduleservice.CreateScheduleHandler).Methods("POST")
	r.HandleFunc("/scheduledelete", scheduleservice.DeleteScheduleHandler).Methods("POST")
	r.HandleFunc("/scheduleshow", scheduleservice.ShowScheduleHandler).Methods("POST")

	//benchmark
	r.HandleFunc("/benchmark", benchmarkservice.CreateBenchmarkHandler).Methods("POST")
	r.HandleFunc("/benchmarkdelete", benchmarkservice.DeleteBenchmarkHandler).Methods("POST")
	r.HandleFunc("/benchmarkshow", benchmarkservice.ShowBenchmarkHandler).Methods("POST")

	//clone
	r.HandleFunc("/clone", cloneservice.CloneHandler).Methods("POST")}
<commit_msg>breaks out service route registration for testing<commit_after>package routing

/*
Copyright 2019 Crunchy Data Solutions, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

import (
	"github.com/crunchydata/postgres-operator/apiserver/backrestservice"
	"github.com/crunchydata/postgres-operator/apiserver/backupservice"
	"github.com/crunchydata/postgres-operator/apiserver/benchmarkservice"
	"github.com/crunchydata/postgres-operator/apiserver/catservice"
	"github.com/crunchydata/postgres-operator/apiserver/cloneservice"
	"github.com/crunchydata/postgres-operator/apiserver/clusterservice"
	"github.com/crunchydata/postgres-operator/apiserver/configservice"
	"github.com/crunchydata/postgres-operator/apiserver/dfservice"
	"github.com/crunchydata/postgres-operator/apiserver/failoverservice"
	"github.com/crunchydata/postgres-operator/apiserver/labelservice"
	"github.com/crunchydata/postgres-operator/apiserver/loadservice"
	"github.com/crunchydata/postgres-operator/apiserver/lsservice"
	"github.com/crunchydata/postgres-operator/apiserver/namespaceservice"
	"github.com/crunchydata/postgres-operator/apiserver/pgbouncerservice"
	"github.com/crunchydata/postgres-operator/apiserver/pgdumpservice"
	"github.com/crunchydata/postgres-operator/apiserver/pgoroleservice"
	"github.com/crunchydata/postgres-operator/apiserver/pgouserservice"
	"github.com/crunchydata/postgres-operator/apiserver/policyservice"
	"github.com/crunchydata/postgres-operator/apiserver/pvcservice"
	"github.com/crunchydata/postgres-operator/apiserver/reloadservice"
	"github.com/crunchydata/postgres-operator/apiserver/scheduleservice"
	"github.com/crunchydata/postgres-operator/apiserver/statusservice"
	"github.com/crunchydata/postgres-operator/apiserver/upgradeservice"
	"github.com/crunchydata/postgres-operator/apiserver/userservice"
	"github.com/crunchydata/postgres-operator/apiserver/versionservice"
	"github.com/crunchydata/postgres-operator/apiserver/workflowservice"

	"github.com/gorilla/mux"
)

// RegisterAllRoutes adds all routes supported by the apiserver to the
// provided router
func RegisterAllRoutes(r *mux.Router) {
	RegisterVersionSvcRoutes(r)
	RegisterPolicySvcRoutes(r)
	RegisterWorkflowSvcRoutes(r)
	RegisterPVCSvcRoutes(r)
	RegisterPGOUserSvcRoutes(r)
	RegisterPGORoleSvcRoutes(r)
	RegisterLabelSvcRoutes(r)
	RegisterLoadSvcRoutes(r)
	RegisterUserSvcRoutes(r)
	RegisterUpgradeSvcRoutes(r)
	RegisterClusterSvcRoutes(r)
	RegisterStatusSvcRoutes(r)
	RegisterDfSvcRoutes(r)
	RegisterConfigSvcRoutes(r)
	RegisterNamespaceSvcRoutes(r)
	RegisterBackupSvcRoutes(r)
	RegisterBackrestSvcRoutes(r)
	RegisterPGDumpSvcRoutes(r)
	RegisterReloadSvcRoutes(r)
	RegisterLsSvcRoutes(r)
	RegisterCatSvcRoutes(r)
	RegisterFailoverSvcRoutes(r)
	RegisterPGBouncerSvcRoutes(r)
	RegisterPGPoolSvcRoutes(r)
	RegisterScheduleSvcRoutes(r)
	RegisterBenchmarkSvcRoutes(r)

}

// RegisterVersionSvcRoutes registers all routes from the Version Service
func RegisterVersionSvcRoutes(r *mux.Router) {
	r.HandleFunc("/version", versionservice.VersionHandler)
	r.HandleFunc("/health", versionservice.HealthHandler)
}

// RegisterPolicySvcRoutes registers all routes from the Policy Service
func RegisterPolicySvcRoutes(r *mux.Router) {
	r.HandleFunc("/policies", policyservice.CreatePolicyHandler)
	r.HandleFunc("/showpolicies", policyservice.ShowPolicyHandler).Methods("POST")
	r.HandleFunc("/policiesdelete", policyservice.DeletePolicyHandler).Methods("POST")
	r.HandleFunc("/policies/apply", policyservice.ApplyPolicyHandler).Methods("POST")
}

// RegisterWorkflowSvcRoutes registers all routes from the Workflow Service
func RegisterWorkflowSvcRoutes(r *mux.Router) {
	r.HandleFunc("/workflow/{id}", workflowservice.ShowWorkflowHandler).Methods("GET")
}

// RegisterPVCSvcRoutes registers all routes from the PVC Service
func RegisterPVCSvcRoutes(r *mux.Router) {
	r.HandleFunc("/showpvc", pvcservice.ShowPVCHandler).Methods("POST")
}

// RegisterPGOUserSvcRoutes registers all routes from the PGOUser Service
func RegisterPGOUserSvcRoutes(r *mux.Router) {
	r.HandleFunc("/pgouserupdate", pgouserservice.UpdatePgouserHandler).Methods("POST")
	r.HandleFunc("/pgouserdelete", pgouserservice.DeletePgouserHandler).Methods("POST")
	r.HandleFunc("/pgousercreate", pgouserservice.CreatePgouserHandler).Methods("POST")
	r.HandleFunc("/pgousershow", pgouserservice.ShowPgouserHandler).Methods("POST")
}

// RegisterPGORoleSvcRoutes registers all routes from the PGORole Service
func RegisterPGORoleSvcRoutes(r *mux.Router) {
	r.HandleFunc("/pgoroleupdate", pgoroleservice.UpdatePgoroleHandler).Methods("POST")
	r.HandleFunc("/pgoroledelete", pgoroleservice.DeletePgoroleHandler).Methods("POST")
	r.HandleFunc("/pgorolecreate", pgoroleservice.CreatePgoroleHandler).Methods("POST")
	r.HandleFunc("/pgoroleshow", pgoroleservice.ShowPgoroleHandler).Methods("POST")
}

// RegisterLabelSvcRoutes registers all routes from the Label Service
func RegisterLabelSvcRoutes(r *mux.Router) {
	r.HandleFunc("/label", labelservice.LabelHandler).Methods("POST")
	r.HandleFunc("/labeldelete", labelservice.DeleteLabelHandler).Methods("POST")
}

// RegisterLoadSvcRoutes registers all routes from the Load Service
func RegisterLoadSvcRoutes(r *mux.Router) {
	r.HandleFunc("/load", loadservice.LoadHandler).Methods("POST")
}

// RegisterUserSvcRoutes registers all routes from the User Service
func RegisterUserSvcRoutes(r *mux.Router) {
	r.HandleFunc("/userupdate", userservice.UpdateUserHandler).Methods("POST")
	r.HandleFunc("/usercreate", userservice.CreateUserHandler).Methods("POST")
	r.HandleFunc("/usershow", userservice.ShowUserHandler).Methods("POST")
	r.HandleFunc("/userdelete", userservice.DeleteUserHandler).Methods("POST")
}

// RegisterUpgradeSvcRoutes registers all routes from the Upgrade Service
func RegisterUpgradeSvcRoutes(r *mux.Router) {
	r.HandleFunc("/upgrades", upgradeservice.CreateUpgradeHandler).Methods("POST")
}

// RegisterClusterSvcRoutes registers all routes from the Cluster Service
func RegisterClusterSvcRoutes(r *mux.Router) {
	r.HandleFunc("/clusters", clusterservice.CreateClusterHandler).Methods("POST")
	r.HandleFunc("/showclusters", clusterservice.ShowClusterHandler).Methods("POST")
	r.HandleFunc("/clustersdelete", clusterservice.DeleteClusterHandler).Methods("POST")
	r.HandleFunc("/clustersupdate", clusterservice.UpdateClusterHandler).Methods("POST")
	r.HandleFunc("/testclusters", clusterservice.TestClusterHandler).Methods("POST")
	r.HandleFunc("/clusters/scale/{name}", clusterservice.ScaleClusterHandler)
	r.HandleFunc("/scale/{name}", clusterservice.ScaleQueryHandler).Methods("GET")
	r.HandleFunc("/scaledown/{name}", clusterservice.ScaleDownHandler).Methods("GET")
}

// RegisterStatusSvcRoutes registers all routes from the Status Service
func RegisterStatusSvcRoutes(r *mux.Router) {
	r.HandleFunc("/status", statusservice.StatusHandler)
}

// RegisterDfSvcRoutes registers all routes from the Df Service
func RegisterDfSvcRoutes(r *mux.Router) {
	r.HandleFunc("/df/{name}", dfservice.DfHandler)
}

// RegisterConfigSvcRoutes registers all routes from the Config Service
func RegisterConfigSvcRoutes(r *mux.Router) {
	r.HandleFunc("/config", configservice.ShowConfigHandler)
}

// RegisterNamespaceSvcRoutes registers all routes from the Namespace Service
func RegisterNamespaceSvcRoutes(r *mux.Router) {
	r.HandleFunc("/namespace", namespaceservice.ShowNamespaceHandler).Methods("POST")
	r.HandleFunc("/namespacedelete", namespaceservice.DeleteNamespaceHandler).Methods("POST")
	r.HandleFunc("/namespacecreate", namespaceservice.CreateNamespaceHandler).Methods("POST")
	r.HandleFunc("/namespaceupdate", namespaceservice.UpdateNamespaceHandler).Methods("POST")
}

// RegisterBackupSvcRoutes registers all routes from the Backup Service
func RegisterBackupSvcRoutes(r *mux.Router) {
	r.HandleFunc("/backups/{name}", backupservice.ShowBackupHandler).Methods("GET")
	r.HandleFunc("/backupsdelete/{name}", backupservice.DeleteBackupHandler).Methods("GET")
	r.HandleFunc("/backups", backupservice.CreateBackupHandler).Methods("POST")
	r.HandleFunc("/pgbasebackuprestore", backupservice.RestoreHandler).Methods("POST")
}

// RegisterBackrestSvcRoutes registers all routes from the Backrest Service
func RegisterBackrestSvcRoutes(r *mux.Router) {
	r.HandleFunc("/backrestbackup", backrestservice.CreateBackupHandler).Methods("POST")
	r.HandleFunc("/backrest/{name}", backrestservice.ShowBackrestHandler).Methods("GET")
	r.HandleFunc("/restore", backrestservice.RestoreHandler).Methods("POST")
}

// RegisterPGDumpSvcRoutes registers all routes from the PGDump Service
func RegisterPGDumpSvcRoutes(r *mux.Router) {
	r.HandleFunc("/pgdumpbackup", pgdumpservice.BackupHandler).Methods("POST")
	r.HandleFunc("/pgdump/{name}", pgdumpservice.ShowDumpHandler).Methods("GET")
	r.HandleFunc("/pgdumprestore", pgdumpservice.RestoreHandler).Methods("POST")
}

// RegisterReloadSvcRoutes registers all routes from the Reload Service
func RegisterReloadSvcRoutes(r *mux.Router) {
	r.HandleFunc("/reload", reloadservice.ReloadHandler).Methods("POST")
}

// RegisterLsSvcRoutes registers all routes from the Ls Service
func RegisterLsSvcRoutes(r *mux.Router) {
	r.HandleFunc("/ls", lsservice.LsHandler).Methods("POST")
}

// RegisterCatSvcRoutes registers all routes from the Cat Service
func RegisterCatSvcRoutes(r *mux.Router) {
	r.HandleFunc("/cat", catservice.CatHandler).Methods("POST")
}

// RegisterFailoverSvcRoutes registers all routes from the Failover Service
func RegisterFailoverSvcRoutes(r *mux.Router) {
	r.HandleFunc("/failover", failoverservice.CreateFailoverHandler).Methods("POST")
	r.HandleFunc("/failover/{name}", failoverservice.QueryFailoverHandler).Methods("GET")
}

// RegisterPGBouncerSvcRoutes registers all routes from the PGBouncer Service
func RegisterPGBouncerSvcRoutes(r *mux.Router) {
	r.HandleFunc("/pgbouncer", pgbouncerservice.CreatePgbouncerHandler).Methods("POST")
	r.HandleFunc("/pgbouncer", pgbouncerservice.DeletePgbouncerHandler).Methods("DELETE")
	r.HandleFunc("/pgbouncerdelete", pgbouncerservice.DeletePgbouncerHandler).Methods("POST")
}

// RegisterScheduleSvcRoutes registers all routes from the Schedule Service
func RegisterScheduleSvcRoutes(r *mux.Router) {
	r.HandleFunc("/schedule", scheduleservice.CreateScheduleHandler).Methods("POST")
	r.HandleFunc("/scheduledelete", scheduleservice.DeleteScheduleHandler).Methods("POST")
	r.HandleFunc("/scheduleshow", scheduleservice.ShowScheduleHandler).Methods("POST")
}

// RegisterBenchmarkSvcRoutes registers all routes from the Benchmark Service
func RegisterBenchmarkSvcRoutes(r *mux.Router) {
	r.HandleFunc("/benchmark", benchmarkservice.CreateBenchmarkHandler).Methods("POST")
	r.HandleFunc("/benchmarkdelete", benchmarkservice.DeleteBenchmarkHandler).Methods("POST")
	r.HandleFunc("/benchmarkshow", benchmarkservice.ShowBenchmarkHandler).Methods("POST")

	//clone
	r.HandleFunc("/clone", cloneservice.CloneHandler).Methods("POST")}
<|endoftext|>


<commit_before>package secret

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/cli"
	"github.com/docker/docker/cli/command"
	"github.com/docker/docker/opts"
	runconfigopts "github.com/docker/docker/runconfig/opts"
	"github.com/spf13/cobra"
	"golang.org/x/net/context"
)

type createOptions struct {
	name   string
	labels opts.ListOpts
}

func newSecretCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
	createOpts := createOptions{
		labels: opts.NewListOpts(runconfigopts.ValidateEnv),
	}

	cmd := &cobra.Command{
		Use:   "create [OPTIONS] SECRET [SECRET...]",
		Short: "Create a secret using stdin as content",
		Args:  cli.RequiresMinArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			createOpts.name = args[0]
			return runSecretCreate(dockerCli, createOpts)
		},
	}
	flags := cmd.Flags()
	flags.VarP(&createOpts.labels, "label", "l", "Secret labels")

	return cmd
}

func runSecretCreate(dockerCli *command.DockerCli, options createOptions) error {
	client := dockerCli.Client()
	ctx := context.Background()

	secretData, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		return fmt.Errorf("Error reading content from STDIN: %v", err)
	}

	spec := swarm.SecretSpec{
		Annotations: swarm.Annotations{
			Name:   options.name,
			Labels: runconfigopts.ConvertKVStringsToMap(options.labels.GetAll()),
		},
		Data: secretData,
	}

	r, err := client.SecretCreate(ctx, spec)
	if err != nil {
		return err
	}

	fmt.Fprintln(dockerCli.Out(), r.ID)
	return nil
}
<commit_msg>Fix the use for secret create<commit_after>package secret

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/docker/docker/api/types/swarm"
	"github.com/docker/docker/cli"
	"github.com/docker/docker/cli/command"
	"github.com/docker/docker/opts"
	runconfigopts "github.com/docker/docker/runconfig/opts"
	"github.com/spf13/cobra"
	"golang.org/x/net/context"
)

type createOptions struct {
	name   string
	labels opts.ListOpts
}

func newSecretCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
	createOpts := createOptions{
		labels: opts.NewListOpts(runconfigopts.ValidateEnv),
	}

	cmd := &cobra.Command{
		Use:   "create [OPTIONS] SECRET",
		Short: "Create a secret using stdin as content",
		Args:  cli.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			createOpts.name = args[0]
			return runSecretCreate(dockerCli, createOpts)
		},
	}
	flags := cmd.Flags()
	flags.VarP(&createOpts.labels, "label", "l", "Secret labels")

	return cmd
}

func runSecretCreate(dockerCli *command.DockerCli, options createOptions) error {
	client := dockerCli.Client()
	ctx := context.Background()

	secretData, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		return fmt.Errorf("Error reading content from STDIN: %v", err)
	}

	spec := swarm.SecretSpec{
		Annotations: swarm.Annotations{
			Name:   options.name,
			Labels: runconfigopts.ConvertKVStringsToMap(options.labels.GetAll()),
		},
		Data: secretData,
	}

	r, err := client.SecretCreate(ctx, spec)
	if err != nil {
		return err
	}

	fmt.Fprintln(dockerCli.Out(), r.ID)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/trasa/watchmud-message"
)

func (c *Client) handleDropResponse(r *message.DropResponse) {
	if r.GetSuccess() {
		UIPrintln("Dropped.")
		return
	}
	//otherwise...
	switch r.GetResultCode() {
	case "NO_TARGET":
		UIPrintln("Drop what?")

	case "TARGET_NOT_FOUND":
		UIPrintln("You don't have one of those.")

	default:
		UIPrintResponseError(r, r.GetResultCode())
	}
}

func (c *Client) handleDropNotification(n *message.DropNotification) {
	if n.GetSuccess() {
		// TODO clauses, articles, plural and so on...
		UIPrintf("%s drops a %s.\n", n.PlayerName, n.Target)
		return
	}
	// weird error case
	UIPrintResponseError(n, n.GetResultCode())
}
<commit_msg>can't drop something you're using<commit_after>package main

import (
	"github.com/trasa/watchmud-message"
)

func (c *Client) handleDropResponse(r *message.DropResponse) {
	if r.GetSuccess() {
		UIPrintln("Dropped.")
		return
	}
	//otherwise...
	switch r.GetResultCode() {
	case "NO_TARGET":
		UIPrintln("Drop what?")

	case "TARGET_NOT_FOUND":
		UIPrintln("You don't have one of those.")

	case "TARGET_IN_USE":
		UIPrintln("You're still using that!")

	default:
		UIPrintResponseError(r, r.GetResultCode())
	}
}

func (c *Client) handleDropNotification(n *message.DropNotification) {
	if n.GetSuccess() {
		// TODO clauses, articles, plural and so on...
		UIPrintf("%s drops a %s.\n", n.PlayerName, n.Target)
		return
	}
	// weird error case
	UIPrintResponseError(n, n.GetResultCode())
}
<|endoftext|>