<commit_before>package precise

import "fmt"

/* FloatU struct - a float with uncertainty
 *
 * Pointers to this structure are used to represent floating point values with uncertainty
 * use NewFloatU(value, uncertainty, sigFig) to create new floating point numbers
*/
type FloatU struct {
    value float64
    uncertainty float64
    sigFig uint
}

/* NewFloatU()
 *
 * Used to create new float64 with an uncertainty
 * value float64        - self-explanatory
 * uncertainty float64  - the uncertainty of your value
 * sigFig uint          - number of significant figures
*/
func NewFloatU(value, uncertainty float64, sigFig uint) (f *FloatU) {
    return &FloatU{value, uncertainty, sigFig}
}

// Add u into f with respect to the significant figures and uncertainty
func (f *FloatU) Add(u *FloatU)  {
    f.value += u.value
    f.uncertainty += u.uncertainty // uncertainties add

    if (f.sigFig > u.sigFig) { // significat figures can not be more then any of the operands
        f.sigFig = u.sigFig
    }
}

// Subtract u from f
func (f *FloatU) Sub(u *FloatU) {
    f.value -= u.value
    f.uncertainty += u.uncertainty

    if (f.sigFig > u.sigFig) {
        f.sigFig = u.sigFig
    }
}

// Multiply f times u
func (f *FloatU) Mul(u *FloatU) {
    fRelUncertainty := f.Relative() // relative uncertainties add
    fRelUncertainty += u.Relative()

    f.value *= u.value
    f.uncertainty = f.value * fRelUncertainty

    if (f.sigFig > u.sigFig) {
        f.sigFig = u.sigFig
    }
}

// Divide f by u
func (f *FloatU) Div(u* FloatU) {
    fRelUncertainty := f.Relative()
    fRelUncertainty += u.Relative()

    f.value /= u.value
    f.uncertainty = f.value * fRelUncertainty

    if (f.sigFig > u.sigFig) {
        f.sigFig = u.sigFig
    }
}

// Raise f to the power of p
func (f *FloatU)Pow(p int) {
    temp := new(FloatU)
    *temp = *f

    if p == 0 {
        f.value = 1.0
        return
    }

    for i:=1; i< p; i++ {
        f.Mul(temp)
    }
}

// Interface for scalars
func (f *FloatU)AddS(u float64) {
    f.value += u
}
func (f *FloatU)SubS(u float64) {
    f.value -= u
}
func (f *FloatU)MulS(u float64) {
    f.value *= u
}
func (f *FloatU)DivS(u float64) {
    f.value /= u
}

// FloatU implements the Stringer interface so variables of type FloatU can be used in fmt.Print()
func (f FloatU) String() string {
    format := fmt.Sprintf("%%.%df +-%%.%df",f.sigFig, f.sigFig)
    return fmt.Sprintf(format, f.value, f.uncertainty)
}

// What is the relative uncertainty of f
func (f FloatU) Relative() float64 {
    return f.uncertainty/f.value
}

// Compare f to u within the limmits of both uncertainties

// f == u
func (f *FloatU) Eql(u *FloatU) bool {
    if  (f.value + f.uncertainty) >= (u.value - u.uncertainty) &&
        (f.value - f.uncertainty) <= (u.value + u.uncertainty) {
        return true
    } else {
        return false
    }
}

// f < u
func (f *FloatU) Lt(u *FloatU) bool {
    return f.value + f.uncertainty < u.value - u.uncertainty
}

// f > u
func (f *FloatU) Gt(u *FloatU) bool {
    return f.value - f.uncertainty > u.value + u.uncertainty
}

// f <= u
func (f *FloatU) LtE(u *FloatU) bool {
    return f.value - f.uncertainty <= u.value + u.uncertainty
}

// f >= u
func (f *FloatU) GtE(u *FloatU) bool {
    return f.value + f.uncertainty >= u.value - u.uncertainty
}

// Compare f to a Scalar within the limmits of uncertainty

// f == u
func (f *FloatU) EqlS(u float64) bool {
    if (f.value + f.uncertainty) >= u &&
       (f.value - f.uncertainty) <= u {
       return true
    } else {
        return false
    }
}

// f > u
func (f *FloatU) GtS(u float64) bool {
    return f.value - f.uncertainty > u
}

// f < u
func (f *FloatU) LtS(u float64) bool {
    return f.value + f.uncertainty < u
}

// f >= u
func (f *FloatU) GtES(u float64) bool {
    return f.value + f.uncertainty >= u
}

// f <= u
func (f *FloatU) LtES(u float64) bool {
    return f.value - f.uncertainty <= u
}

// Round value to i sigFig
func (f FloatU)roundSigFig(i float64) {

}
<commit_msg>update docs<commit_after>package precise

import "fmt"

/* FloatU struct - a float with uncertainty

  Pointers to this structure are used to represent floating point values with uncertainty
  use NewFloatU(value, uncertainty, sigFig) to create new floating point numbers
*/
type FloatU struct {
    value float64
    uncertainty float64
    sigFig uint
}

/* NewFloatU()

  Used to create new float64 with an uncertainty
  value float64        - self-explanatory
  uncertainty float64  - the uncertainty of your value
  sigFig uint          - number of significant figures
*/
func NewFloatU(value, uncertainty float64, sigFig uint) (f *FloatU) {
    return &FloatU{value, uncertainty, sigFig}
}

// Add u into f with respect to the significant figures and uncertainty
func (f *FloatU) Add(u *FloatU)  {
    f.value += u.value
    f.uncertainty += u.uncertainty // uncertainties add

    if (f.sigFig > u.sigFig) { // significat figures can not be more then any of the operands
        f.sigFig = u.sigFig
    }
}

// Subtract u from f with respect to the significant figures and uncertainty
func (f *FloatU) Sub(u *FloatU) {
    f.value -= u.value
    f.uncertainty += u.uncertainty

    if (f.sigFig > u.sigFig) {
        f.sigFig = u.sigFig
    }
}

// Multiply f times u with respect to the significant figures and uncertainty
func (f *FloatU) Mul(u *FloatU) {
    fRelUncertainty := f.Relative() // relative uncertainties add
    fRelUncertainty += u.Relative()

    f.value *= u.value
    f.uncertainty = f.value * fRelUncertainty

    if (f.sigFig > u.sigFig) {
        f.sigFig = u.sigFig
    }
}

// Divide f by u with respect to the significant figures and uncertainty
func (f *FloatU) Div(u* FloatU) {
    fRelUncertainty := f.Relative()
    fRelUncertainty += u.Relative()

    f.value /= u.value
    f.uncertainty = f.value * fRelUncertainty

    if (f.sigFig > u.sigFig) {
        f.sigFig = u.sigFig
    }
}

// Raise f to the power of p with respect to the significant figures and uncertainty
func (f *FloatU)Pow(p int) {
    temp := new(FloatU)
    *temp = *f

    if p == 0 {
        f.value = 1.0
        return
    }

    for i:=1; i< p; i++ {
        f.Mul(temp)
    }
}

// Interface for scalars
func (f *FloatU)AddS(u float64) {
    f.value += u
}
func (f *FloatU)SubS(u float64) {
    f.value -= u
}
func (f *FloatU)MulS(u float64) {
    f.value *= u
}
func (f *FloatU)DivS(u float64) {
    f.value /= u
}

// FloatU implements the Stringer interface so variables of type FloatU can be used in fmt.Print()
func (f FloatU) String() string {
    format := fmt.Sprintf("%%.%df +-%%.%df",f.sigFig, f.sigFig)
    return fmt.Sprintf(format, f.value, f.uncertainty)
}

// Return the relative uncertainty of f
func (f FloatU) Relative() float64 {
    return f.uncertainty/f.value
}

// Test f == u within the limits of both uncertainties
func (f *FloatU) Eql(u *FloatU) bool {
    if  (f.value + f.uncertainty) >= (u.value - u.uncertainty) &&
        (f.value - f.uncertainty) <= (u.value + u.uncertainty) {
        return true
    } else {
        return false
    }
}

// Test f < u within the limits of both uncertainties
func (f *FloatU) Lt(u *FloatU) bool {
    return f.value + f.uncertainty < u.value - u.uncertainty
}

// Test f > u within the limits of both uncertainties
func (f *FloatU) Gt(u *FloatU) bool {
    return f.value - f.uncertainty > u.value + u.uncertainty
}

// Test f <= u within the limits of both uncertainties
func (f *FloatU) LtE(u *FloatU) bool {
    return f.value - f.uncertainty <= u.value + u.uncertainty
}

// Test f >= u within the limits of both uncertainties
func (f *FloatU) GtE(u *FloatU) bool {
    return f.value + f.uncertainty >= u.value - u.uncertainty
}

// Test f == Scalar within the limits of uncertainty
func (f *FloatU) EqlS(u float64) bool {
    if (f.value + f.uncertainty) >= u &&
       (f.value - f.uncertainty) <= u {
       return true
    } else {
        return false
    }
}

// Test f > Scalar within the limits of uncertainty
func (f *FloatU) GtS(u float64) bool {
    return f.value - f.uncertainty > u
}

// Test f < Scalar within the limits of uncertainty
func (f *FloatU) LtS(u float64) bool {
    return f.value + f.uncertainty < u
}

// Test f >= Scalar within the limits of uncertainty
func (f *FloatU) GtES(u float64) bool {
    return f.value + f.uncertainty >= u
}

// Test f <= Scalar within the limits of uncertainty
func (f *FloatU) LtES(u float64) bool {
    return f.value - f.uncertainty <= u
}

// Round value to i sigFig
func (f FloatU)roundSigFig(i float64) {

}
<|endoftext|>


<commit_before>// Package zipexe attempts to open an executable binary file as a zip file.
package zipexe

import (
	"archive/zip"
	"debug/elf"
	"debug/macho"
	"debug/pe"
	"errors"
	"io"
	"os"
)

// Opens a zip file by path.
func Open(path string) (*zip.Reader, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	finfo, err := file.Stat()
	if err != nil {
		return nil, err
	}
	zr, err := NewReader(file, finfo.Size())
	if err != nil {
		return nil, err
	}
	return zr, nil
}

// Open a zip file, specially handling various binaries that may have been
// augmented with zip data.
func NewReader(rda io.ReaderAt, size int64) (*zip.Reader, error) {
	handlers := []func(io.ReaderAt, int64) (*zip.Reader, error){
		zip.NewReader,
		zipExeReaderMacho,
		zipExeReaderElf,
		zipExeReaderPe,
	}

	for _, handler := range handlers {
		zfile, err := handler(rda, size)
		if err == nil {
			return zfile, nil
		}
	}
	return nil, errors.New("Couldn't Open As Executable")
}

// zipExeReaderMacho treats the file as a Mach-O binary
// (Mac OS X / Darwin executable) and attempts to find a zip archive.
func zipExeReaderMacho(rda io.ReaderAt, size int64) (*zip.Reader, error) {
	file, err := macho.NewFile(rda)
	if err != nil {
		return nil, err
	}

	var max int64
	for _, load := range file.Loads {
		seg, ok := load.(*macho.Segment)
		if ok {
			// Check if the segment contains a zip file
			if zfile, err := zip.NewReader(seg, int64(seg.Filesz)); err == nil {
				return zfile, nil
			}

			// Otherwise move end of file pointer
			end := int64(seg.Offset + seg.Filesz)
			if end > max {
				max = end
			}
		}
	}

	// No zip file within binary, try appended to end
	section := io.NewSectionReader(rda, max, size-max)
	return zip.NewReader(section, section.Size())
}

// zipExeReaderPe treats the file as a Portable Exectuable binary
// (Windows executable) and attempts to find a zip archive.
func zipExeReaderPe(rda io.ReaderAt, size int64) (*zip.Reader, error) {
	file, err := pe.NewFile(rda)
	if err != nil {
		return nil, err
	}

	var max int64
	for _, sec := range file.Sections {
		// Check if this section has a zip file
		if zfile, err := zip.NewReader(sec, int64(sec.Size)); err == nil {
			return zfile, nil
		}

		// Otherwise move end of file pointer
		end := int64(sec.Offset + sec.Size)
		if end > max {
			max = end
		}
	}

	// No zip file within binary, try appended to end
	section := io.NewSectionReader(rda, max, size-max)
	return zip.NewReader(section, section.Size())
}

// zipExeReaderElf treats the file as a ELF binary
// (linux/BSD/etc... executable) and attempts to find a zip archive.
func zipExeReaderElf(rda io.ReaderAt, size int64) (*zip.Reader, error) {
	file, err := elf.NewFile(rda)
	if err != nil {
		return nil, err
	}

	var max int64
	for _, sect := range file.Sections {
		if sect.Type == elf.SHT_NOBITS {
			continue
		}

		// Check if this section has a zip file
		if zfile, err := zip.NewReader(sect, int64(sect.Size)); err == nil {
			return zfile, nil
		}

		// Otherwise move end of file pointer
		end := int64(sect.Offset + sect.Size)
		if end > max {
			max = end
		}
	}

	// No zip file within binary, try appended to end
	section := io.NewSectionReader(rda, max, size-max)
	return zip.NewReader(section, section.Size())
}
<commit_msg>New "OpenCloser" function. Open uses it, but discards the file descriptor.<commit_after>// Package zipexe attempts to open an executable binary file as a zip file.
package zipexe

import (
	"archive/zip"
	"debug/elf"
	"debug/macho"
	"debug/pe"
	"errors"
	"io"
	"os"
)

// Opens a zip file by path.
func Open(path string) (*zip.Reader, error) {
	_, rd, err := OpenCloser(path)
	return rd, err
}

// OpenCloser is like Open but returns an additional Closer to avoid leaking open files.
func OpenCloser(path string) (io.Closer, *zip.Reader, error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, nil, err
	}
	finfo, err := file.Stat()
	if err != nil {
		return nil, nil, err
	}
	zr, err := NewReader(file, finfo.Size())
	if err != nil {
		return nil, nil, err
	}
	return file, zr, nil
}

// Open a zip file, specially handling various binaries that may have been
// augmented with zip data.
func NewReader(rda io.ReaderAt, size int64) (*zip.Reader, error) {
	handlers := []func(io.ReaderAt, int64) (*zip.Reader, error){
		zip.NewReader,
		zipExeReaderMacho,
		zipExeReaderElf,
		zipExeReaderPe,
	}

	for _, handler := range handlers {
		zfile, err := handler(rda, size)
		if err == nil {
			return zfile, nil
		}
	}
	return nil, errors.New("Couldn't Open As Executable")
}

// zipExeReaderMacho treats the file as a Mach-O binary
// (Mac OS X / Darwin executable) and attempts to find a zip archive.
func zipExeReaderMacho(rda io.ReaderAt, size int64) (*zip.Reader, error) {
	file, err := macho.NewFile(rda)
	if err != nil {
		return nil, err
	}

	var max int64
	for _, load := range file.Loads {
		seg, ok := load.(*macho.Segment)
		if ok {
			// Check if the segment contains a zip file
			if zfile, err := zip.NewReader(seg, int64(seg.Filesz)); err == nil {
				return zfile, nil
			}

			// Otherwise move end of file pointer
			end := int64(seg.Offset + seg.Filesz)
			if end > max {
				max = end
			}
		}
	}

	// No zip file within binary, try appended to end
	section := io.NewSectionReader(rda, max, size-max)
	return zip.NewReader(section, section.Size())
}

// zipExeReaderPe treats the file as a Portable Exectuable binary
// (Windows executable) and attempts to find a zip archive.
func zipExeReaderPe(rda io.ReaderAt, size int64) (*zip.Reader, error) {
	file, err := pe.NewFile(rda)
	if err != nil {
		return nil, err
	}

	var max int64
	for _, sec := range file.Sections {
		// Check if this section has a zip file
		if zfile, err := zip.NewReader(sec, int64(sec.Size)); err == nil {
			return zfile, nil
		}

		// Otherwise move end of file pointer
		end := int64(sec.Offset + sec.Size)
		if end > max {
			max = end
		}
	}

	// No zip file within binary, try appended to end
	section := io.NewSectionReader(rda, max, size-max)
	return zip.NewReader(section, section.Size())
}

// zipExeReaderElf treats the file as a ELF binary
// (linux/BSD/etc... executable) and attempts to find a zip archive.
func zipExeReaderElf(rda io.ReaderAt, size int64) (*zip.Reader, error) {
	file, err := elf.NewFile(rda)
	if err != nil {
		return nil, err
	}

	var max int64
	for _, sect := range file.Sections {
		if sect.Type == elf.SHT_NOBITS {
			continue
		}

		// Check if this section has a zip file
		if zfile, err := zip.NewReader(sect, int64(sect.Size)); err == nil {
			return zfile, nil
		}

		// Otherwise move end of file pointer
		end := int64(sect.Offset + sect.Size)
		if end > max {
			max = end
		}
	}

	// No zip file within binary, try appended to end
	section := io.NewSectionReader(rda, max, size-max)
	return zip.NewReader(section, section.Size())
}
<|endoftext|>


<commit_before>/*

   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 client

import "encoding/json"

// UserResponse ...
type UserResponse struct {
	Response []User `json:"response"`
}

// User contains information about a given user in Traffic Ops.
type User struct {
	Username     string `json:"username,omitempty"`
	PublicSSHKey string `json:"publicSshKey,omitempty"`
	Role         int    `json:"role,omitempty"`
	RoleName     string `json:"rolename,omitempty"`
	ID           int    `json:"id,omitempty"`
	UID          int    `json:"uid,omitempty"`
	GID          int    `json:"gid,omitempty"`
	Company      string `json:"company,omitempty"`
	Email        string `json:"email,omitempty"`
	FullName     string `json:"fullName,omitempty"`
	NewUser      bool   `json:"newUser,omitempty"`
	LastUpdated  string `json:"lastUpdated,omitempty"`
}

// Users gets an array of Users.
func (to *Session) Users() ([]User, error) {
	url := "/api/1.2/users.json"
	resp, err := to.request("GET", url, nil)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var data UserResponse
	if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
		return nil, err
	}

	return data.Response, nil
}
<commit_msg>refactored to use the lib/go-tc users.go<commit_after>/*

   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 client

import (
	"encoding/json"

	tc "github.com/apache/incubator-trafficcontrol/lib/go-tc"
)

// Users gets an array of Users.
func (to *Session) Users() ([]tc.User, error) {
	url := "/api/1.2/users.json"
	resp, err := to.request("GET", url, nil)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var data tc.UsersResponse
	if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
		return nil, err
	}

	return data.Response, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"launchpad.net/goyaml"
	"os"
	"text/template"
)

type Task struct {
	Name       string
	Parameters map[string]string
}

type Node struct {
	Name  string
	Tests []Task
	Steps []Task
}

type TaskResult struct {
	Success bool
	Message string
}

var boxkitePath string

func loadNode(path string) Node {
	file, e := ioutil.ReadFile(path)
	if e != nil {
		fmt.Printf("File error: %v\n", e)
		os.Exit(1)
	}

	var n Node

	err := goyaml.Unmarshal(file, &n)
	if err != nil {
		fmt.Printf("YAML error: %v\n", err)
		os.Exit(1)
	}
	return n
}

func (t Task) doTask(params map[string]string) <-chan TaskResult {
	c := make(chan TaskResult)
	go func() {
		fmt.Println("Params:", params)
		if t.Name == "core.Exec" {

			var command bytes.Buffer

			template, err := template.New("command").Parse(t.Parameters["command"])
			if err != nil {
				panic(err)
			}

			err = template.Execute(&command, params)
			if err != nil {
				panic(err)
			}

			result := fmt.Sprintf("core.Exec: %s", command.String())

			c <- TaskResult{true, result}
		} else {
			n := loadNode(fmt.Sprintf("%s/%s.yaml", boxkitePath, t.Name))
			tc := n.doNode(t.Parameters)
			result := <-tc
			if result.Success {
				fmt.Println("SUCCESS:", result.Message)
			} else {
				fmt.Println("FAILURE:", result.Message)
			}
			c <- result
		}
	}()
	return c
}

func (n Node) doNode(params map[string]string) <-chan TaskResult {

	c := make(chan TaskResult)

	go func() {

		fmt.Println("Node name:", n.Name)

		for _, test := range n.Tests {
			fmt.Println("Test:", test.Name)
			tc := test.doTask(params)
			result := <-tc
			fmt.Println("--", result.Message)
		}

		for _, step := range n.Steps {
			fmt.Println("Step:", step.Name)

			sc := step.doTask(params)
			result := <-sc
			fmt.Println("--", result.Message)

		}

		c <- TaskResult{true, "Hooray!"}
	}()
	return c
}

func main() {
	flag.StringVar(&boxkitePath, "b", "/etc/boxkite", "Directory where Boxkite files live")

	flag.Parse()

	// You must provide at least one boxkite file to start with
	if len(flag.Args()) != 1 {
		flag.Usage()
		os.Exit(1)
	}

	fmt.Println("Path is:", boxkitePath)
	fmt.Println("Root is:", flag.Arg(0))
	n := loadNode(flag.Arg(0))
	c := n.doNode(make(map[string]string))

	result := <-c

	if result.Success {
		fmt.Println("SUCCESS:", result.Message)
	} else {
		fmt.Println("FAILURE:", result.Message)
	}

}
<commit_msg>params work in nested tasks<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"launchpad.net/goyaml"
	"os"
	"text/template"
)

type Task struct {
	Name       string
	Parameters map[string]string
}

type Node struct {
	Name  string
	Tests []Task
	Steps []Task
}

type TaskResult struct {
	Success bool
	Message string
}

var boxkitePath string

func loadNode(path string) Node {
	file, e := ioutil.ReadFile(path)
	if e != nil {
		fmt.Printf("File error: %v\n", e)
		os.Exit(1)
	}

	var n Node

	err := goyaml.Unmarshal(file, &n)
	if err != nil {
		fmt.Printf("YAML error: %v\n", err)
		os.Exit(1)
	}
	return n
}

func templatize(s string, p map[string]string) string {
	var result bytes.Buffer

	template, err := template.New("result").Parse(s)
	if err != nil {
		panic(err)
	}

	err = template.Execute(&result, p)
	if err != nil {
		panic(err)
	}
	return result.String()
}

func (t Task) doTask(params map[string]string) <-chan TaskResult {
	c := make(chan TaskResult)
	go func() {
		fmt.Println("In Task:", t.Name)
		fmt.Println("Params are:", params)

		if t.Name == "core.Exec" {
			command := templatize(t.Parameters["command"], params)

			result := fmt.Sprintf("core.Exec: %s", command)

			c <- TaskResult{true, result}
		} else {
			n := loadNode(fmt.Sprintf("%s/%s.yaml", boxkitePath, t.Name))

			for k, v := range t.Parameters {

				t.Parameters[k] = templatize(v, params)

			}

			tc := n.doNode(t.Parameters)

			result := <-tc
			if result.Success {
				fmt.Println("SUCCESS:", result.Message)
			} else {
				fmt.Println("FAILURE:", result.Message)
			}
			c <- result
		}
	}()
	return c
}

func (n Node) doNode(params map[string]string) <-chan TaskResult {

	c := make(chan TaskResult)

	go func() {

		fmt.Println("In Node:", n.Name)
		fmt.Println("Params are:", params)
		for _, test := range n.Tests {
			fmt.Println(n.Name, "- Test:", test.Name)
			tc := test.doTask(params)
			result := <-tc
			fmt.Println("--", result.Message)
		}

		for _, step := range n.Steps {
			fmt.Println(n.Name, "- Step:", step.Name)

			sc := step.doTask(params)
			result := <-sc
			fmt.Println("--", result.Message)

		}

		c <- TaskResult{true, "Hooray!"}
	}()
	return c
}

func main() {
	flag.StringVar(&boxkitePath, "b", "/etc/boxkite", "Directory where Boxkite files live")

	flag.Parse()

	// You must provide at least one boxkite file to start with
	if len(flag.Args()) != 1 {
		flag.Usage()
		os.Exit(1)
	}

	fmt.Println("Path is:", boxkitePath)
	fmt.Println("Root is:", flag.Arg(0))
	n := loadNode(flag.Arg(0))
	c := n.doNode(make(map[string]string))

	result := <-c

	if result.Success {
		fmt.Println("SUCCESS:", result.Message)
	} else {
		fmt.Println("FAILURE:", result.Message)
	}

}
<|endoftext|>


<commit_before>package main

import (
	"github.com/aws/aws-sdk-go/service/cloudwatchevents"
)

// Associate ClowdWatchEvent Rule and descripbed Rule(name based)
func AssociateRules(cweRules []*cloudwatchevents.Rule, describedRules []Rule) []Rule {
	dupCWERules := make([]*cloudwatchevents.Rule, len(cweRules))
	copy(dupCWERules, cweRules)

	for i, rule := range describedRules {
		for j, cweRule := range dupCWERules {
			if *cweRule.Name == rule.Name {
				describedRules[i].ActualRule = *cweRule
				dupCWERules = DeleteRuleFromSlice(dupCWERules, j)
				break
			}
		}
	}
	if len(dupCWERules) > 0 {
		for _, dupRule := range dupCWERules {
			describedRules = append(describedRules, Rule{
				ActualRule: *dupRule,
			})
		}
	}
	return describedRules
}

func AssociateTargets(cweTargets []*cloudwatchevents.Target, describedTargets []Target) []Target {
	// if ClowdWatchEvents Targets is more than declareted targets, append number of lack target{}
	if l := len(cweTargets) - len(describedTargets); l > 0 {
		t := make([]Target, l)
		describedTargets = append(describedTargets, t...)
	}
	dupCWETargets := make([]*cloudwatchevents.Target, len(cweTargets))
	copy(dupCWETargets, cweTargets)

	for i, target := range describedTargets {
		for j, cweTarget := range dupCWETargets {
			if CompareString(&target.Arn, cweTarget.Arn) && CompareString(&target.Id, cweTarget.Id) {
				describedTargets[i].ActualTarget = *cweTarget
				dupCWETargets = DeleteTargetFromSlice(dupCWETargets, j)
				break
			}
		}
	}
	if len(dupCWETargets) > 0 {
		for _, dupTarget := range dupCWETargets {
			for j, target := range describedTargets {
				if target.ActualTarget.Arn == nil {
					describedTargets[j].ActualTarget = *dupTarget
				}
			}
		}
	}

	return describedTargets
}

// judge is rule need update
// compare rule and ActualRule
func JudgeRuleNeedUpdate(r *Rule) {
	if !CompareString(&r.Name, r.ActualRule.Name) ||
		!CompareString(&r.Description, r.ActualRule.Description) ||
		!CompareString(&r.EventPattern, r.ActualRule.EventPattern) ||
		!CompareString(&r.ScheduleExpression, r.ActualRule.ScheduleExpression) ||
		!CompareString(&r.State, r.ActualRule.State) {
		r.NeedUpdate = true
	}
}

func JudgeRuleNeedDelete(r *Rule) {
	if r.Name == "" &&
		r.Description == "" &&
		r.EventPattern == "" &&
		r.ScheduleExpression == "" &&
		r.RoleArn == "" &&
		r.State == "" &&
		r.ActualRule.Name != nil {
		r.NeedDelete = true
	}
}

// judge is target need update
// compare target and ActualTarget
func JudgeTargetNeedUpdate(t *Target) {
	if !CompareString(&t.Arn, t.ActualTarget.Arn) ||
		!CompareString(&t.Id, t.ActualTarget.Id) ||
		!CompareString(&t.Input, t.ActualTarget.Input) ||
		!CompareString(&t.InputPath, t.ActualTarget.InputPath) {
		t.NeedUpdate = true
	}
}

func JudgeTargetNeedDelete(t *Target) {
	if t.Arn == "" &&
		t.Id == "" &&
		t.ActualTarget.Arn != nil {
		t.NeedDelete = true
	}
}

// check all rules and targets, update "NeedUpdate" and "NeedDelete" field
func CheckIsNeedUpdateOrDelete(rules []Rule) {
	for i, _ := range rules {
		JudgeRuleNeedUpdate(&rules[i])
		JudgeRuleNeedDelete(&rules[i])
		for j, _ := range rules[i].Targets {
			JudgeTargetNeedUpdate(&rules[i].Targets[j])
			JudgeTargetNeedDelete(&rules[i].Targets[j])
		}
	}
}
<commit_msg>Associate empty target if actual target is surplus<commit_after>package main

import (
	"github.com/aws/aws-sdk-go/service/cloudwatchevents"
)

// Associate ClowdWatchEvent Rule and descripbed Rule(name based)
func AssociateRules(cweRules []*cloudwatchevents.Rule, describedRules []Rule) []Rule {
	dupCWERules := make([]*cloudwatchevents.Rule, len(cweRules))
	copy(dupCWERules, cweRules)

	for i, rule := range describedRules {
		for j, cweRule := range dupCWERules {
			if *cweRule.Name == rule.Name {
				describedRules[i].ActualRule = *cweRule
				dupCWERules = DeleteRuleFromSlice(dupCWERules, j)
				break
			}
		}
	}
	if len(dupCWERules) > 0 {
		for _, dupRule := range dupCWERules {
			describedRules = append(describedRules, Rule{
				ActualRule: *dupRule,
			})
		}
	}
	return describedRules
}

func AssociateTargets(cweTargets []*cloudwatchevents.Target, describedTargets []Target) []Target {
	// if ClowdWatchEvents Targets is more than declareted targets, append number of lack target{}
	dupCWETargets := make([]*cloudwatchevents.Target, len(cweTargets))
	copy(dupCWETargets, cweTargets)

	for i, target := range describedTargets {
		for j, cweTarget := range dupCWETargets {
			if CompareString(&target.Arn, cweTarget.Arn) && CompareString(&target.Id, cweTarget.Id) {
				describedTargets[i].ActualTarget = *cweTarget
				dupCWETargets = DeleteTargetFromSlice(dupCWETargets, j)
				break
			}
		}
	}
	if len(dupCWETargets) > 0 {
		for _, dupTarget := range dupCWETargets {
			describedTargets = append(describedTargets, Target{
				ActualTarget: *dupTarget,
			})
		}
	}
	return describedTargets
}

// judge is rule need update
// compare rule and ActualRule
func JudgeRuleNeedUpdate(r *Rule) {
	if !CompareString(&r.Name, r.ActualRule.Name) ||
		!CompareString(&r.Description, r.ActualRule.Description) ||
		!CompareString(&r.EventPattern, r.ActualRule.EventPattern) ||
		!CompareString(&r.ScheduleExpression, r.ActualRule.ScheduleExpression) ||
		!CompareString(&r.State, r.ActualRule.State) {
		r.NeedUpdate = true
	}
}

func JudgeRuleNeedDelete(r *Rule) {
	if r.Name == "" &&
		r.Description == "" &&
		r.EventPattern == "" &&
		r.ScheduleExpression == "" &&
		r.RoleArn == "" &&
		r.State == "" &&
		r.ActualRule.Name != nil {
		r.NeedDelete = true
	}
}

// judge is target need update
// compare target and ActualTarget
func JudgeTargetNeedUpdate(t *Target) {
	if !CompareString(&t.Arn, t.ActualTarget.Arn) ||
		!CompareString(&t.Id, t.ActualTarget.Id) ||
		!CompareString(&t.Input, t.ActualTarget.Input) ||
		!CompareString(&t.InputPath, t.ActualTarget.InputPath) {
		t.NeedUpdate = true
	}
}

func JudgeTargetNeedDelete(t *Target) {
	if t.Arn == "" &&
		t.Id == "" &&
		t.ActualTarget.Arn != nil {
		t.NeedDelete = true
	}
}

// check all rules and targets, update "NeedUpdate" and "NeedDelete" field
func CheckIsNeedUpdateOrDelete(rules []Rule) {
	for i, _ := range rules {
		JudgeRuleNeedUpdate(&rules[i])
		JudgeRuleNeedDelete(&rules[i])
		for j, _ := range rules[i].Targets {
			JudgeTargetNeedUpdate(&rules[i].Targets[j])
			JudgeTargetNeedDelete(&rules[i].Targets[j])
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"github.com/gorilla/mux"
	"log"
	"net/http"
)

// HTTPServer represents the http endpoint
type HTTPServer struct {
	config *Config
	list   ServiceListProvider
	server *http.Server
}

// NewHTTPServer create a new http endpoint
func NewHTTPServer(c *Config, list ServiceListProvider) *HTTPServer {
	s := &HTTPServer{
		config: c,
		list:   list,
	}

	router := mux.NewRouter()
	router.HandleFunc("/services", s.getServices).Methods("GET")
	router.HandleFunc("/services/{id}", s.getService).Methods("GET")
	router.HandleFunc("/services/{id}", s.addService).Methods("PUT")
	router.HandleFunc("/services/{id}", s.updateService).Methods("PATCH")
	router.HandleFunc("/services/{id}", s.removeService).Methods("DELETE")

	router.HandleFunc("/set/ttl", s.setTTL).Methods("PUT")

	s.server = &http.Server{Addr: c.httpAddr, Handler: router}

	return s
}

// Start starts the http endpoint
func (s *HTTPServer) Start() error {
	return s.server.ListenAndServe()
}

func (s *HTTPServer) getServices(w http.ResponseWriter, req *http.Request) {
	if err := json.NewEncoder(w).Encode(s.list.GetAllServices()); err != nil {
		log.Println("Error encoding: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func (s *HTTPServer) getService(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)

	id, ok := vars["id"]
	if !ok {
		http.Error(w, "ID required", http.StatusBadRequest)
		return
	}

	service, err := s.list.GetService(id)
	if err != nil {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}

	if err := json.NewEncoder(w).Encode(service); err != nil {
		log.Println("Error: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func (s *HTTPServer) addService(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)

	id, ok := vars["id"]
	if !ok {
		http.Error(w, "ID required", http.StatusBadRequest)
		return
	}

	service := NewService()
	if err := json.NewDecoder(req.Body).Decode(&service); err != nil {
		log.Println("Error decoding JSON: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if service.Name == "" {
		http.Error(w, "Property \"name\" is required", http.StatusInternalServerError)
		return
	}

	if service.Image == "" {
		http.Error(w, "Property \"image\" is required", http.StatusInternalServerError)
		return
	}

	if service.IP == nil {
		http.Error(w, "Property \"ip\" is required", http.StatusInternalServerError)
		return
	}

	s.list.AddService(id, *service)
}

func (s *HTTPServer) removeService(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)

	id, ok := vars["id"]
	if !ok {
		http.Error(w, "ID required", http.StatusBadRequest)
		return
	}

	if err := s.list.RemoveService(id); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	}

}

func (s *HTTPServer) updateService(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)

	id, ok := vars["id"]
	if !ok {
		http.Error(w, "ID required", http.StatusBadRequest)
		return
	}

	service, err := s.list.GetService(id)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	var input map[string]interface{}
	if err := json.NewDecoder(req.Body).Decode(&input); err != nil {
		log.Println("Error decoding JSON: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if ttl, ok := input["ttl"]; ok {
		if value, ok := ttl.(float64); ok {
			service.TTL = int(value)
		}
	}

	if name, ok := input["name"]; ok {
		if value, ok := name.(string); ok {
			service.Name = value
		}
	}

	if image, ok := input["image"]; ok {
		if value, ok := image.(string); ok {
			service.Image = value
		}
	}

	if image, ok := input["alias"]; ok {
		if value, ok := image.([]string); ok {
			service.Aliases = value
		}
	}

	// todo: this probably needs to be moved. consider stop event in the
	// middle of sending PATCH. container would not be removed.
	s.list.AddService(id, service)

}

func (s *HTTPServer) setTTL(w http.ResponseWriter, req *http.Request) {
	var value int
	if err := json.NewDecoder(req.Body).Decode(&value); err != nil {
		log.Println("Error decoding value: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	s.config.ttl = value

}
<commit_msg>Add content-type header<commit_after>package main

import (
	"encoding/json"
	"github.com/gorilla/mux"
	"log"
	"net/http"
)

// HTTPServer represents the http endpoint
type HTTPServer struct {
	config *Config
	list   ServiceListProvider
	server *http.Server
}

// NewHTTPServer create a new http endpoint
func NewHTTPServer(c *Config, list ServiceListProvider) *HTTPServer {
	s := &HTTPServer{
		config: c,
		list:   list,
	}

	router := mux.NewRouter()
	router.HandleFunc("/services", s.getServices).Methods("GET")
	router.HandleFunc("/services/{id}", s.getService).Methods("GET")
	router.HandleFunc("/services/{id}", s.addService).Methods("PUT")
	router.HandleFunc("/services/{id}", s.updateService).Methods("PATCH")
	router.HandleFunc("/services/{id}", s.removeService).Methods("DELETE")

	router.HandleFunc("/set/ttl", s.setTTL).Methods("PUT")

	s.server = &http.Server{Addr: c.httpAddr, Handler: router}

	return s
}

// Start starts the http endpoint
func (s *HTTPServer) Start() error {
	return s.server.ListenAndServe()
}

func (s *HTTPServer) getServices(w http.ResponseWriter, req *http.Request) {

        w.Header().Set("Content-Type", "application/json; charset=UTF-8")

	if err := json.NewEncoder(w).Encode(s.list.GetAllServices()); err != nil {
		log.Println("Error encoding: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func (s *HTTPServer) getService(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)

        w.Header().Set("Content-Type", "application/json; charset=UTF-8")

	id, ok := vars["id"]
	if !ok {
		http.Error(w, "ID required", http.StatusBadRequest)
		return
	}

	service, err := s.list.GetService(id)
	if err != nil {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}

	if err := json.NewEncoder(w).Encode(service); err != nil {
		log.Println("Error: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func (s *HTTPServer) addService(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)

	id, ok := vars["id"]
	if !ok {
		http.Error(w, "ID required", http.StatusBadRequest)
		return
	}

	service := NewService()
	if err := json.NewDecoder(req.Body).Decode(&service); err != nil {
		log.Println("Error decoding JSON: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if service.Name == "" {
		http.Error(w, "Property \"name\" is required", http.StatusInternalServerError)
		return
	}

	if service.Image == "" {
		http.Error(w, "Property \"image\" is required", http.StatusInternalServerError)
		return
	}

	if service.IP == nil {
		http.Error(w, "Property \"ip\" is required", http.StatusInternalServerError)
		return
	}

	s.list.AddService(id, *service)
}

func (s *HTTPServer) removeService(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)

	id, ok := vars["id"]
	if !ok {
		http.Error(w, "ID required", http.StatusBadRequest)
		return
	}

	if err := s.list.RemoveService(id); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
	}

}

func (s *HTTPServer) updateService(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)

	id, ok := vars["id"]
	if !ok {
		http.Error(w, "ID required", http.StatusBadRequest)
		return
	}

	service, err := s.list.GetService(id)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	var input map[string]interface{}
	if err := json.NewDecoder(req.Body).Decode(&input); err != nil {
		log.Println("Error decoding JSON: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	if ttl, ok := input["ttl"]; ok {
		if value, ok := ttl.(float64); ok {
			service.TTL = int(value)
		}
	}

	if name, ok := input["name"]; ok {
		if value, ok := name.(string); ok {
			service.Name = value
		}
	}

	if image, ok := input["image"]; ok {
		if value, ok := image.(string); ok {
			service.Image = value
		}
	}

	if image, ok := input["alias"]; ok {
		if value, ok := image.([]string); ok {
			service.Aliases = value
		}
	}

	// todo: this probably needs to be moved. consider stop event in the
	// middle of sending PATCH. container would not be removed.
	s.list.AddService(id, service)

}

func (s *HTTPServer) setTTL(w http.ResponseWriter, req *http.Request) {
	var value int
	if err := json.NewDecoder(req.Body).Decode(&value); err != nil {
		log.Println("Error decoding value: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	s.config.ttl = value

}
<|endoftext|>


<commit_before>package ca

import (
	"crypto/tls"
	"crypto/x509/pkix"
	"strings"

	"github.com/Sirupsen/logrus"

	"github.com/docker/swarm-v2/log"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/peer"
)

// LogTLSState logs information about the TLS connection and remote peers
func LogTLSState(ctx context.Context, tlsState *tls.ConnectionState) {
	if tlsState == nil {
		log.G(ctx).Debugf("no TLS Chains found")
		return
	}

	peerCerts := []string{}
	verifiedChain := []string{}
	for _, cert := range tlsState.PeerCertificates {
		peerCerts = append(peerCerts, cert.Subject.CommonName)
	}
	for _, chain := range tlsState.VerifiedChains {
		subjects := []string{}
		for _, cert := range chain {
			subjects = append(subjects, cert.Subject.CommonName)
		}
		verifiedChain = append(verifiedChain, strings.Join(subjects, ","))
	}

	log.G(ctx).WithFields(logrus.Fields{
		"peer.peerCert": peerCerts,
		// "peer.verifiedChain": verifiedChain},
	}).Debugf("")
}

// getCertificateSubject extracts the subject from a verified client certificate
func getCertificateSubject(tlsState *tls.ConnectionState) (pkix.Name, error) {
	if tlsState == nil {
		return pkix.Name{}, grpc.Errorf(codes.PermissionDenied, "request is not using TLS")
	}
	if len(tlsState.PeerCertificates) == 0 {
		return pkix.Name{}, grpc.Errorf(codes.PermissionDenied, "no client certificates in request")
	}
	if len(tlsState.VerifiedChains) == 0 {
		return pkix.Name{}, grpc.Errorf(codes.PermissionDenied, "no verified chains for remote certificate")
	}

	return tlsState.VerifiedChains[0][0].Subject, nil
}

func tlsConnStateFromContext(ctx context.Context) (*tls.ConnectionState, error) {
	peer, ok := peer.FromContext(ctx)
	if !ok {
		return nil, grpc.Errorf(codes.PermissionDenied, "Permission denied: no peer info")
	}
	tlsInfo, ok := peer.AuthInfo.(credentials.TLSInfo)
	if !ok {
		return nil, grpc.Errorf(codes.PermissionDenied, "Permission denied: peer didn't not present valid peer certificate")
	}
	return &tlsInfo.State, nil
}

// certSubjectFromContext extracts pkix.Name from context.
func certSubjectFromContext(ctx context.Context) (pkix.Name, error) {
	connState, err := tlsConnStateFromContext(ctx)
	if err != nil {
		return pkix.Name{}, err
	}
	return getCertificateSubject(connState)
}

// AuthorizeRole takes in a context and a list of organizations, and returns
// the CN of the certificate if one of the OU matches.
func AuthorizeRole(ctx context.Context, ou []string) (string, error) {
	return authorizeRole(ctx, ou)
}

// AuthorizeForwardedRole takes in a context and a list of organizations, and returns
// the CN of the certificate if one of the OU matches.
func AuthorizeForwardedRole(ctx context.Context, role string) (string, error) {
	return authorizeForwardedRole(ctx, role, []string{ManagerRole})
}

// authorizeForwardedRole checks for proper roles of caller. It can be manager who
// forward agent request or agent itself. It returns agent id.
func authorizeForwardedRole(ctx context.Context, forwardedRole string, forwarderRoles []string) (string, error) {
	// If the call is being done directly by an accepted role, return the CN
	cn, err := authorizeRole(ctx, []string{forwardedRole})
	if err == nil {
		return cn, nil
	}

	// If the call is being done by a manager, return the forwarded CN
	_, err = authorizeRole(ctx, forwarderRoles)
	if err == nil {
		return forwardCNFromContext(ctx)
	}

	// If this wasn't an agent or a manager, fail
	return "", grpc.Errorf(codes.PermissionDenied, "Permission denied: unknown peer role.")
}

// authorizeRole takes in a context and a list of organizations, and returns
// the CN of the certificate if one of the OU matches.
func authorizeRole(ctx context.Context, ou []string) (string, error) {
	certSubj, err := certSubjectFromContext(ctx)
	if err != nil {
		return "", err
	}
	// Check if the current certificate has an OU that authorizes
	// access to this method
	if intersectArrays(certSubj.OrganizationalUnit, ou) {
		return certSubj.CommonName, nil
	}
	return "", grpc.Errorf(codes.PermissionDenied, "Permission denied: remote certificate not part of OU %v", ou)
}

// intersectArrays returns true when there is at least one element in common
// between the two arrays
func intersectArrays(orig, tgt []string) bool {
	for _, i := range orig {
		for _, x := range tgt {
			if i == x {
				return true
			}
		}
	}
	return false
}
<commit_msg>Addressing nits<commit_after>package ca

import (
	"crypto/tls"
	"crypto/x509/pkix"
	"strings"

	"github.com/Sirupsen/logrus"

	"github.com/docker/swarm-v2/log"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/peer"
)

// LogTLSState logs information about the TLS connection and remote peers
func LogTLSState(ctx context.Context, tlsState *tls.ConnectionState) {
	if tlsState == nil {
		log.G(ctx).Debugf("no TLS Chains found")
		return
	}

	peerCerts := []string{}
	verifiedChain := []string{}
	for _, cert := range tlsState.PeerCertificates {
		peerCerts = append(peerCerts, cert.Subject.CommonName)
	}
	for _, chain := range tlsState.VerifiedChains {
		subjects := []string{}
		for _, cert := range chain {
			subjects = append(subjects, cert.Subject.CommonName)
		}
		verifiedChain = append(verifiedChain, strings.Join(subjects, ","))
	}

	log.G(ctx).WithFields(logrus.Fields{
		"peer.peerCert": peerCerts,
		// "peer.verifiedChain": verifiedChain},
	}).Debugf("")
}

// getCertificateSubject extracts the subject from a verified client certificate
func getCertificateSubject(tlsState *tls.ConnectionState) (pkix.Name, error) {
	if tlsState == nil {
		return pkix.Name{}, grpc.Errorf(codes.PermissionDenied, "request is not using TLS")
	}
	if len(tlsState.PeerCertificates) == 0 {
		return pkix.Name{}, grpc.Errorf(codes.PermissionDenied, "no client certificates in request")
	}
	if len(tlsState.VerifiedChains) == 0 {
		return pkix.Name{}, grpc.Errorf(codes.PermissionDenied, "no verified chains for remote certificate")
	}

	return tlsState.VerifiedChains[0][0].Subject, nil
}

func tlsConnStateFromContext(ctx context.Context) (*tls.ConnectionState, error) {
	peer, ok := peer.FromContext(ctx)
	if !ok {
		return nil, grpc.Errorf(codes.PermissionDenied, "Permission denied: no peer info")
	}
	tlsInfo, ok := peer.AuthInfo.(credentials.TLSInfo)
	if !ok {
		return nil, grpc.Errorf(codes.PermissionDenied, "Permission denied: peer didn't not present valid peer certificate")
	}
	return &tlsInfo.State, nil
}

// certSubjectFromContext extracts pkix.Name from context.
func certSubjectFromContext(ctx context.Context) (pkix.Name, error) {
	connState, err := tlsConnStateFromContext(ctx)
	if err != nil {
		return pkix.Name{}, err
	}
	return getCertificateSubject(connState)
}

// AuthorizeRole takes in a context and a list of organizations, and returns
// the CN of the certificate if one of the OU matches.
func AuthorizeRole(ctx context.Context, ou []string) (string, error) {
	certSubj, err := certSubjectFromContext(ctx)
	if err != nil {
		return "", err
	}
	// Check if the current certificate has an OU that authorizes
	// access to this method
	if intersectArrays(certSubj.OrganizationalUnit, ou) {
		return certSubj.CommonName, nil
	}
	return "", grpc.Errorf(codes.PermissionDenied, "Permission denied: remote certificate not part of OU %v", ou)
}

// AuthorizeForwardedRole takes in a context and a list of organizations, and returns
// the CN of the certificate if one of the OU matches.
func AuthorizeForwardedRole(ctx context.Context, role string) (string, error) {
	return authorizeForwardedRole(ctx, role, []string{ManagerRole})
}

// authorizeForwardedRole checks for proper roles of caller. It can be manager who
// forward agent request or agent itself. It returns agent id.
func authorizeForwardedRole(ctx context.Context, forwardedRole string, forwarderRoles []string) (string, error) {
	// If the call is being done directly by an accepted role, return the CN
	cn, err := AuthorizeRole(ctx, []string{forwardedRole})
	if err == nil {
		return cn, nil
	}

	// If the call is being done by a manager, return the forwarded CN
	_, err = AuthorizeRole(ctx, forwarderRoles)
	if err == nil {
		return forwardCNFromContext(ctx)
	}

	return "", grpc.Errorf(codes.PermissionDenied, "Permission denied: unknown peer role.")
}

// intersectArrays returns true when there is at least one element in common
// between the two arrays
func intersectArrays(orig, tgt []string) bool {
	for _, i := range orig {
		for _, x := range tgt {
			if i == x {
				return true
			}
		}
	}
	return false
}
<|endoftext|>


<commit_before>package osutil

/*
#include <stdio.h>
#include <stdlib.h>
*/
import "C"

import (
	"bytes"
	"errors"
	"io"
	"os"
	"sync"
	"unsafe"
)

var (
	// ErrFDOpenFailed indicates that C's fdopen has failed
	ErrFDOpenFailed = errors.New("fdopen returned nil")
)

var lockStdFileDescriptorsSwapping sync.Mutex // FIXME our solution is not concurrent-safe. Find a better solution because this might be a bottleneck in the future.

// Capture captures stderr and stdout of a given function call.
func Capture(call func()) (output []byte, err error) {
	lockStdFileDescriptorsSwapping.Lock()
	defer lockStdFileDescriptorsSwapping.Unlock()

	originalStdErr, originalStdOut := os.Stderr, os.Stdout
	defer func() {
		os.Stderr, os.Stdout = originalStdErr, originalStdOut
	}()

	r, w, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	defer func() {
		e := r.Close()
		if e != nil {
			err = e
		}
	}()

	os.Stderr, os.Stdout = w, w

	out := make(chan []byte)
	go func() {
		var b bytes.Buffer

		_, err := io.Copy(&b, r)
		if err != nil {
			panic(err)
		}

		out <- b.Bytes()
	}()

	call()

	err = w.Close()
	if err != nil {
		return nil, err
	}

	return <-out, err
}

// CaptureWithCGo captures stderr and stdout as well as stderr and stdout of C of a given function call.
func CaptureWithCGo(call func()) (output []byte, err error) {
	lockStdFileDescriptorsSwapping.Lock()
	defer lockStdFileDescriptorsSwapping.Unlock()

	originalStdErr, originalStdOut := os.Stderr, os.Stdout
	originalCStdErr, originalCStdOut := C.stderr, C.stdout
	defer func() {
		os.Stderr, os.Stdout = originalStdErr, originalStdOut
		C.stderr, C.stdout = originalCStdErr, originalCStdOut
	}()

	r, w, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	defer func() {
		e := r.Close()
		if e != nil {
			err = e
		}
	}()

	cw := C.CString("w")
	defer C.free(unsafe.Pointer(cw))

	f := C.fdopen((C.int)(w.Fd()), cw)
	if f == nil {
		return nil, ErrFDOpenFailed
	}
	defer C.fclose(f)

	os.Stderr, os.Stdout = w, w
	C.stderr, C.stdout = f, f

	out := make(chan []byte)
	go func() {
		var b bytes.Buffer

		_, err := io.Copy(&b, r)
		if err != nil {
			panic(err)
		}

		out <- b.Bytes()
	}()

	call()

	C.fflush(f)

	err = w.Close()
	if err != nil {
		return nil, err
	}

	return <-out, err
}
<commit_msg>Use syscall.Dup2 capture cgo output<commit_after>package osutil

/*
#include <stdio.h>
#include <stdlib.h>
*/
import "C"

import (
	"bytes"
	"io"
	"os"
	"sync"
	"syscall"
	"unsafe"
)

var lockStdFileDescriptorsSwapping sync.Mutex // FIXME our solution is not concurrent-safe. Find a better solution because this might be a bottleneck in the future.

// Capture captures stderr and stdout of a given function call.
func Capture(call func()) (output []byte, err error) {
	lockStdFileDescriptorsSwapping.Lock()
	defer lockStdFileDescriptorsSwapping.Unlock()

	originalStdErr, originalStdOut := os.Stderr, os.Stdout
	defer func() {
		os.Stderr, os.Stdout = originalStdErr, originalStdOut
	}()

	r, w, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	defer func() {
		e := r.Close()
		if e != nil {
			err = e
		}
	}()

	os.Stderr, os.Stdout = w, w

	out := make(chan []byte)
	go func() {
		var b bytes.Buffer

		_, err := io.Copy(&b, r)
		if err != nil {
			panic(err)
		}

		out <- b.Bytes()
	}()

	call()

	err = w.Close()
	if err != nil {
		return nil, err
	}

	return <-out, err
}

// CaptureWithCGo captures stderr and stdout as well as stderr and stdout of C of a given function call.
func CaptureWithCGo(call func()) (output []byte, err error) {
	lockStdFileDescriptorsSwapping.Lock()
	defer lockStdFileDescriptorsSwapping.Unlock()

	originalStdout, e := syscall.Dup(syscall.Stdout)
	if e != nil {
		return nil, e
	}

	originalStderr, e := syscall.Dup(syscall.Stderr)
	if e != nil {
		return nil, e
	}

	defer func() {
		if e := syscall.Dup2(originalStdout, syscall.Stdout); e != nil {
			err = e
		}
		if e := syscall.Close(originalStdout); e != nil {
			err = e
		}
		if e := syscall.Dup2(originalStderr, syscall.Stderr); e != nil {
			err = e
		}
		if e := syscall.Close(originalStderr); e != nil {
			err = e
		}
	}()

	r, w, err := os.Pipe()
	if err != nil {
		return nil, err
	}
	defer func() {
		e := r.Close()
		if e != nil {
			err = e
		}
	}()

	cw := C.CString("w")
	defer C.free(unsafe.Pointer(cw))

	if e := syscall.Dup2(int(w.Fd()), syscall.Stdout); e != nil {
		return nil, e
	}
	if e := syscall.Dup2(int(w.Fd()), syscall.Stderr); e != nil {
		return nil, e
	}

	out := make(chan []byte)
	go func() {
		var b bytes.Buffer

		_, err := io.Copy(&b, r)
		if err != nil {
			panic(err)
		}

		out <- b.Bytes()
	}()

	call()

	C.fflush(C.stdout)

	err = w.Close()
	if err != nil {
		return nil, err
	}
	if e := syscall.Close(syscall.Stdout); e != nil {
		return nil, e
	}
	if e := syscall.Close(syscall.Stderr); e != nil {
		return nil, e
	}

	return <-out, err
}
<|endoftext|>


<commit_before>/* vim: set sw=4 sts=4 et foldmethod=syntax : */

/*
 * Copyright (c) 2011 Alexander Færøy <ahf@0x90.dk>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package main

import (
    "crypto/rand"
    "crypto/tls"
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "strconv"
    "strings"
    "time"
)
type Ircd struct {
    *log.Logger
    listeners []Listener
    config *ConfigurationFile

    motd_file string
    motd_content []string
}

func NewIrcd() *Ircd {
    ircd := new(Ircd)
    ircd.Logger = log.New(os.Stderr, "", log.Ldate | log.Ltime)
    ircd.listeners = make([]Listener, 0)

    return ircd
}

func (this *Ircd) SetConfigurationFile(config *ConfigurationFile) {
    this.config = config

    for i := range this.config.Ircd.Listeners {
        listener := this.config.Ircd.Listeners[i]
        hostport := listener.Host + ":" + strconv.Itoa(listener.Port)
        protocol := ProtocolFromString(listener.Type)

        if protocol == nil {
            this.Printf("Unknown protocol type: %s\n", listener.Type)
            continue
        }

        if listener.Tls {
            this.addSecureListener(*protocol, hostport)
        } else {
            this.addListener(*protocol, hostport)
        }
    }
}

func (this *Ircd) addCommonListener(p Protocol, address string, config *tls.Config) {
    var listener Listener

    switch p {
        case TCP: listener = NewTCPListener(this, address, config)
        case WebSocket: listener = NewWebSocketListener(this, address, config)
        default: panic("Unhandled Protocol.")
    }

    if listener != nil {
        this.listeners = append(this.listeners, listener)
    }
}

func (this *Ircd) addListener(protocol Protocol, address string) {
    this.addCommonListener(protocol, address, nil)
}

func (this *Ircd) addSecureListener(protocol Protocol, address string) {
    cert := this.config.Ircd.ServerInfo.Tls.Certificate
    key := this.config.Ircd.ServerInfo.Tls.Key
    errorMessage := fmt.Sprintf("Unable to add secure listener for %s", address)

    if cert == "" {
        this.Printf("%s: %s", errorMessage, "Empty TLS certificate in configuration file.")
        return
    }

    if key == "" {
        this.Printf("%s: %s", errorMessage, "Empty TLS key in configuration file.")
        return
    }

    certificate, error := tls.LoadX509KeyPair(cert, key)

    if error != nil {
        this.Printf("Error Loading Certificate: %s", error)
        return
    }

    config := &tls.Config{
        Rand: rand.Reader,
        Time: time.Seconds,
    }

    config.Certificates = make([]tls.Certificate, 1)
    config.Certificates[0] = certificate

    if protocol == WebSocket {
        config.NextProtos = []string{"http/1.1"}
    }

    this.addCommonListener(protocol, address, config)
}

func (this *Ircd) Run() {
    if len(this.listeners) == 0 {
        fmt.Printf("Error: No Listeners Defined...\n")
        os.Exit(1)
    }

    this.Printf("Opening up for incoming connections")

    for i := range this.listeners {
        listener := this.listeners[i]

        this.Printf("Listening on %s (%s %s)", listener.Address(), listener.Secure(), listener.Protocol())
        go listener.Listen()
    }
}

func (this *Ircd) Me() string {
    return this.config.Ircd.ServerInfo.Name
}

func (this *Ircd) SetMotdFile(path string) {
    this.motd_file = path

    this.LoadMotd()
}

func (this *Ircd) LoadMotd() {
    content, error := ioutil.ReadFile(this.motd_file)

    if error != nil {
        this.Printf("Unable to load MOTD file: %s", error)
        return
    }

    this.motd_content = strings.Split(string(content), "\n", -1)
}
<commit_msg>Add Description() config accessor for the Ircd type.<commit_after>/* vim: set sw=4 sts=4 et foldmethod=syntax : */

/*
 * Copyright (c) 2011 Alexander Færøy <ahf@0x90.dk>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package main

import (
    "crypto/rand"
    "crypto/tls"
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "strconv"
    "strings"
    "time"
)
type Ircd struct {
    *log.Logger
    listeners []Listener
    config *ConfigurationFile

    motd_file string
    motd_content []string
}

func NewIrcd() *Ircd {
    ircd := new(Ircd)
    ircd.Logger = log.New(os.Stderr, "", log.Ldate | log.Ltime)
    ircd.listeners = make([]Listener, 0)

    return ircd
}

func (this *Ircd) SetConfigurationFile(config *ConfigurationFile) {
    this.config = config

    for i := range this.config.Ircd.Listeners {
        listener := this.config.Ircd.Listeners[i]
        hostport := listener.Host + ":" + strconv.Itoa(listener.Port)
        protocol := ProtocolFromString(listener.Type)

        if protocol == nil {
            this.Printf("Unknown protocol type: %s\n", listener.Type)
            continue
        }

        if listener.Tls {
            this.addSecureListener(*protocol, hostport)
        } else {
            this.addListener(*protocol, hostport)
        }
    }
}

func (this *Ircd) addCommonListener(p Protocol, address string, config *tls.Config) {
    var listener Listener

    switch p {
        case TCP: listener = NewTCPListener(this, address, config)
        case WebSocket: listener = NewWebSocketListener(this, address, config)
        default: panic("Unhandled Protocol.")
    }

    if listener != nil {
        this.listeners = append(this.listeners, listener)
    }
}

func (this *Ircd) addListener(protocol Protocol, address string) {
    this.addCommonListener(protocol, address, nil)
}

func (this *Ircd) addSecureListener(protocol Protocol, address string) {
    cert := this.config.Ircd.ServerInfo.Tls.Certificate
    key := this.config.Ircd.ServerInfo.Tls.Key
    errorMessage := fmt.Sprintf("Unable to add secure listener for %s", address)

    if cert == "" {
        this.Printf("%s: %s", errorMessage, "Empty TLS certificate in configuration file.")
        return
    }

    if key == "" {
        this.Printf("%s: %s", errorMessage, "Empty TLS key in configuration file.")
        return
    }

    certificate, error := tls.LoadX509KeyPair(cert, key)

    if error != nil {
        this.Printf("Error Loading Certificate: %s", error)
        return
    }

    config := &tls.Config{
        Rand: rand.Reader,
        Time: time.Seconds,
    }

    config.Certificates = make([]tls.Certificate, 1)
    config.Certificates[0] = certificate

    if protocol == WebSocket {
        config.NextProtos = []string{"http/1.1"}
    }

    this.addCommonListener(protocol, address, config)
}

func (this *Ircd) Run() {
    if len(this.listeners) == 0 {
        fmt.Printf("Error: No Listeners Defined...\n")
        os.Exit(1)
    }

    this.Printf("Opening up for incoming connections")

    for i := range this.listeners {
        listener := this.listeners[i]

        this.Printf("Listening on %s (%s %s)", listener.Address(), listener.Secure(), listener.Protocol())
        go listener.Listen()
    }
}

func (this *Ircd) Me() string {
    return this.config.Ircd.ServerInfo.Name
}

func (this *Ircd) Description() string {
    return this.config.Ircd.ServerInfo.Description
}

func (this *Ircd) SetMotdFile(path string) {
    this.motd_file = path

    this.LoadMotd()
}

func (this *Ircd) LoadMotd() {
    content, error := ioutil.ReadFile(this.motd_file)

    if error != nil {
        this.Printf("Unable to load MOTD file: %s", error)
        return
    }

    this.motd_content = strings.Split(string(content), "\n", -1)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"errors"
	"net/http"
	"sort"

	"github.com/samsarahq/thunder/graphql"
	"github.com/samsarahq/thunder/graphql/introspection"
	"github.com/samsarahq/thunder/graphql/schemabuilder"
	"github.com/samsarahq/thunder/livesql"
	"github.com/samsarahq/thunder/sqlgen"
)

type Server struct {
	db *livesql.LiveDB
}

type Message struct {
	Id   int64 `sql:",primary" graphql:",key"`
	Text string
}

var reactionTypes = map[string]bool{
	":)": true,
	":(": true,
}

type ReactionInstance struct {
	Id        int64 `sql:",primary"`
	MessageId int64
	Reaction  string
}

type Reaction struct {
	Reaction string `graphql:",key"`
	Count    int
}

func (s *Server) registerMessage(schema *schemabuilder.Schema) {
	object := schema.Object("Message", Message{})

	object.Description = "A single message."

	object.FieldFunc("reactions", func(ctx context.Context, m *Message) ([]*Reaction, error) {
		reactions := make(map[string]*Reaction)
		for reactionType := range reactionTypes {
			reactions[reactionType] = &Reaction{
				Reaction: reactionType,
			}
		}

		var instances []*ReactionInstance
		if err := s.db.Query(ctx, &instances, sqlgen.Filter{"message_id": m.Id}, nil); err != nil {
			return nil, err
		}
		for _, instance := range instances {
			reactions[instance.Reaction].Count++
		}

		var result []*Reaction
		for _, reaction := range reactions {
			result = append(result, reaction)
		}
		sort.Slice(result, func(a, b int) bool { return result[a].Reaction < result[b].Reaction })

		return result, nil
	})
}

func (s *Server) registerQuery(schema *schemabuilder.Schema) {
	object := schema.Query()

	object.FieldFunc("messages", func(ctx context.Context) ([]*Message, error) {
		var result []*Message
		if err := s.db.Query(ctx, &result, nil, nil); err != nil {
			return nil, err
		}
		return result, nil
	})
}

func (s *Server) registerMutation(schema *schemabuilder.Schema) {
	object := schema.Mutation()

	object.FieldFunc("addMessage", func(ctx context.Context, args struct{ Text string }) error {
		_, err := s.db.InsertRow(ctx, &Message{Text: args.Text})
		return err
	})

	object.FieldFunc("deleteMessage", func(ctx context.Context, args struct{ Id int64 }) error {
		return s.db.DeleteRow(ctx, &Message{Id: args.Id})
	})

	object.FieldFunc("addReaction", func(ctx context.Context, args struct {
		MessageId int64
		Reaction  string
	}) error {
		if _, ok := reactionTypes[args.Reaction]; !ok {
			return errors.New("reaction not allowed")
		}
		_, err := s.db.InsertRow(ctx, &ReactionInstance{MessageId: args.MessageId, Reaction: args.Reaction})
		return err
	})
}

func (s *Server) SchemaBuilderSchema() *schemabuilder.Schema {
	schema := schemabuilder.NewSchema()

	s.registerQuery(schema)
	s.registerMutation(schema)
	s.registerMessage(schema)

	return schema
}

func (s *Server) Schema() *graphql.Schema {
	return s.SchemaBuilderSchema().MustBuild()
}

func main() {
	sqlgenSchema := sqlgen.NewSchema()
	sqlgenSchema.MustRegisterType("messages", sqlgen.AutoIncrement, Message{})
	sqlgenSchema.MustRegisterType("reaction_instances", sqlgen.AutoIncrement, ReactionInstance{})

	db, err := livesql.Open("localhost", 3307, "root", "", "chat", sqlgenSchema)
	if err != nil {
		panic(err)
	}

	server := &Server{db: db}
	graphqlSchema := server.Schema()
	introspection.AddIntrospectionToSchema(graphqlSchema)

	http.Handle("/graphql", graphql.Handler(graphqlSchema))
	if err := http.ListenAndServe(":3030", nil); err != nil {
		panic(err)
	}
}
<commit_msg>example main: add graphiql <commit_after>package main

import (
	"context"
	"errors"
	"net/http"
	"sort"

	"github.com/samsarahq/thunder/graphql"
	"github.com/samsarahq/thunder/graphql/graphiql"
	"github.com/samsarahq/thunder/graphql/introspection"
	"github.com/samsarahq/thunder/graphql/schemabuilder"
	"github.com/samsarahq/thunder/livesql"
	"github.com/samsarahq/thunder/sqlgen"
)

type Server struct {
	db *livesql.LiveDB
}

type Message struct {
	Id   int64 `sql:",primary" graphql:",key"`
	Text string
}

var reactionTypes = map[string]bool{
	":)": true,
	":(": true,
}

type ReactionInstance struct {
	Id        int64 `sql:",primary"`
	MessageId int64
	Reaction  string
}

type Reaction struct {
	Reaction string `graphql:",key"`
	Count    int
}

func (s *Server) registerMessage(schema *schemabuilder.Schema) {
	object := schema.Object("Message", Message{})

	object.Description = "A single message."

	object.FieldFunc("reactions", func(ctx context.Context, m *Message) ([]*Reaction, error) {
		reactions := make(map[string]*Reaction)
		for reactionType := range reactionTypes {
			reactions[reactionType] = &Reaction{
				Reaction: reactionType,
			}
		}

		var instances []*ReactionInstance
		if err := s.db.Query(ctx, &instances, sqlgen.Filter{"message_id": m.Id}, nil); err != nil {
			return nil, err
		}
		for _, instance := range instances {
			reactions[instance.Reaction].Count++
		}

		var result []*Reaction
		for _, reaction := range reactions {
			result = append(result, reaction)
		}
		sort.Slice(result, func(a, b int) bool { return result[a].Reaction < result[b].Reaction })

		return result, nil
	})
}

func (s *Server) registerQuery(schema *schemabuilder.Schema) {
	object := schema.Query()

	object.FieldFunc("messages", func(ctx context.Context) ([]*Message, error) {
		var result []*Message
		if err := s.db.Query(ctx, &result, nil, nil); err != nil {
			return nil, err
		}
		return result, nil
	})
}

func (s *Server) registerMutation(schema *schemabuilder.Schema) {
	object := schema.Mutation()

	object.FieldFunc("addMessage", func(ctx context.Context, args struct{ Text string }) error {
		_, err := s.db.InsertRow(ctx, &Message{Text: args.Text})
		return err
	})

	object.FieldFunc("deleteMessage", func(ctx context.Context, args struct{ Id int64 }) error {
		return s.db.DeleteRow(ctx, &Message{Id: args.Id})
	})

	object.FieldFunc("addReaction", func(ctx context.Context, args struct {
		MessageId int64
		Reaction  string
	}) error {
		if _, ok := reactionTypes[args.Reaction]; !ok {
			return errors.New("reaction not allowed")
		}
		_, err := s.db.InsertRow(ctx, &ReactionInstance{MessageId: args.MessageId, Reaction: args.Reaction})
		return err
	})
}

func (s *Server) SchemaBuilderSchema() *schemabuilder.Schema {
	schema := schemabuilder.NewSchema()

	s.registerQuery(schema)
	s.registerMutation(schema)
	s.registerMessage(schema)

	return schema
}

func (s *Server) Schema() *graphql.Schema {
	return s.SchemaBuilderSchema().MustBuild()
}

func main() {
	sqlgenSchema := sqlgen.NewSchema()
	sqlgenSchema.MustRegisterType("messages", sqlgen.AutoIncrement, Message{})
	sqlgenSchema.MustRegisterType("reaction_instances", sqlgen.AutoIncrement, ReactionInstance{})

	db, err := livesql.Open("localhost", 3307, "root", "", "chat", sqlgenSchema)
	if err != nil {
		panic(err)
	}

	server := &Server{db: db}
	graphqlSchema := server.Schema()
	introspection.AddIntrospectionToSchema(graphqlSchema)

	http.Handle("/graphql", graphql.Handler(graphqlSchema))
	http.Handle("/graphiql/", http.StripPrefix("/graphiql/", graphiql.Handler()))
	if err := http.ListenAndServe(":3030", nil); err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package lexer

import (
	"bufio"
	"code.google.com/p/go.text/transform"
	"io"
)

// Alphabet in Latin-1 order
const (
	ALPHABET  = "ABCDEFGHIJKLMNOPQRSTUVWXYZÄÅÖ"
	BASE      = uint64(len(ALPHABET) + 1)
	MAX_VALUE = BASE*BASE*BASE + 1
)

// Normalization translation table
var normalize table

type table map[byte]byte

func (t *table) Transform(dst, src []byte, atEOF bool) (int, int, error) {
	for i, b := range src {
		dst[i] = t[b]
	}
	return len(src), len(src), nil
}

func init() {
	var ch rune
	runes := make(map[rune]rune)
	table = make(map[byte]byte)

	// Början på översatt kod från tokenizer.c

	/*
	 * tokenizer.c delar upp en text i sina ord och matar ut orden
	 * omvandlade till små bokstäver, ett ord per rad följt av ordets
	 * teckenposition i texten. Ett ord definieras som en eller flera
	 * på varandra följande bokstäver i det svenska alfabetet.
	 * Copyright Viggo Kann, viggo@nada.kth.se, 1999
	 *
	 * Lätt omhackad av Jakob Nordström 2003 för att klara tecken med accenter
	 * (t.ex. á, è. ü osv.).
	 */

	for i := rune(0); i < 256; i++ {
		runes[i] = 0
	}

	for _, s := range ALPHABET {
		ch = s + 'a' - 'A'
		runes[s] = ch
		runes[ch] = ch
	}

	/*
	 * Nedan följer speciallösning för att klara accenterade tecken
	 *
	 */

	for ch = 224; ch <= 227; ch++ { /* a med accent (utom å och ä) */
		runes[ch] = 'a'
		runes[ch+-'a'+'A'] = 'a'
	}

	ch = 230 /* ae till ä */
	runes[ch] = 'ä'
	runes[ch+-'a'+'A'] = 'ä'

	ch = 231 /* c med cedilj till c*/
	runes[ch] = 'c'
	runes[ch+-'a'+'A'] = 'c'

	for ch = 232; ch <= 235; ch++ { /* e med accent (även é) */
		runes[ch] = 'e'
		runes[ch+-'a'+'A'] = 'e'
	}

	for ch = 236; ch <= 239; ch++ { /* i med accent */
		runes[ch] = 'i'
		runes[ch+-'a'+'A'] = 'i'
	}

	ch = 241 /* n med ~ rill n */
	runes[ch] = 'n'
	runes[ch+-'a'+'A'] = 'n'

	for ch = 242; ch <= 245; ch++ { /* o med accent (förutom ö) */
		runes[ch] = 'o'
		runes[ch+-'a'+'A'] = 'o'
	}

	ch = 248 /* o genomskuret till ö */
	runes[ch] = 'ö'
	runes[ch+-'a'+'A'] = 'ö'

	for ch = 249; ch <= 252; ch++ { /* u med accent */
		runes[ch] = 'u'
		runes[ch+-'a'+'A'] = 'u'
	}

	ch = 253 /* y med accent */
	runes[ch] = 'y'
	runes[ch+-'a'+'A'] = 'y'
	ch = 255
	runes[ch] = 'y'
	runes[ch+-'a'+'A'] = 'y'

	// Slut på översatt kod från tokenizer.c

	for from, to := range runes {
		table[byte(from)] = byte(to)
	}
}

func Hash(word string) uint64 {
	switch len(word) {
	case 0:
		return 0
	case 1:
		return hash(word[0])
	case 2:
		return hash(word[1]) + hash(word[0])*BASE
	default:
		return hash(word[2]) + hash(word[1])*BASE + hash(word[0])*BASE*BASE
	}
}

func hash(b byte) rune {
	if table[b] == 0 {
		return 0
	} else {
		return table[b] - 'a' + 1
	}
}

type tokenizer struct {
	input    *bufio.Reader
	position uint64
}

func New(reader io.Reader) *tokenizer {
	return &tokenizer{bufio.NewReader(transform.NewReader(reader, normalize)), 0}
}

func (t *tokenizer) ReadToken() (advance uint64, token string, err error) {
	// Consume non-alphabet characters
	for ch := byte(0); ch == 0; ch, err = t.input.ReadByte() {
		advance++
		if err != nil {
			return
		}
	}

	err = t.input.UnreadByte()
	if err != nil {
		return
	}
	advance--

	token, err = t.input.ReadString(0)
	if len(token) > 0 {
		// Remove the trailing zero byte
		advance += uint64(len(token))
		token = token[:len(token)-1]
	}
	return
}
<commit_msg>Fix table implementation of transform.Transformer<commit_after>package lexer

import (
	"bufio"
	"code.google.com/p/go.text/transform"
	"io"
)

// Alphabet in Latin-1 order
const (
	ALPHABET  = "ABCDEFGHIJKLMNOPQRSTUVWXYZÄÅÖ"
	BASE      = uint64(len(ALPHABET) + 1)
	MAX_VALUE = BASE*BASE*BASE + 1
)

// Normalization translation table
var normalize *table

type table struct {
	tranlation map[byte]byte
}

func (t *table) Transform(dst, src []byte, atEOF bool) (int, int, error) {
	for i, b := range src {
		dst[i] = t.tranlation[b]
	}
	return len(src), len(src), nil
}

func init() {
	var ch rune
	runes := make(map[rune]rune)

	// Början på översatt kod från tokenizer.c

	/*
	 * tokenizer.c delar upp en text i sina ord och matar ut orden
	 * omvandlade till små bokstäver, ett ord per rad följt av ordets
	 * teckenposition i texten. Ett ord definieras som en eller flera
	 * på varandra följande bokstäver i det svenska alfabetet.
	 * Copyright Viggo Kann, viggo@nada.kth.se, 1999
	 *
	 * Lätt omhackad av Jakob Nordström 2003 för att klara tecken med accenter
	 * (t.ex. á, è. ü osv.).
	 */

	for i := rune(0); i < 256; i++ {
		runes[i] = 0
	}

	for _, s := range ALPHABET {
		ch = s + 'a' - 'A'
		runes[s] = ch
		runes[ch] = ch
	}

	/*
	 * Nedan följer speciallösning för att klara accenterade tecken
	 *
	 */

	for ch = 224; ch <= 227; ch++ { /* a med accent (utom å och ä) */
		runes[ch] = 'a'
		runes[ch+-'a'+'A'] = 'a'
	}

	ch = 230 /* ae till ä */
	runes[ch] = 'ä'
	runes[ch+-'a'+'A'] = 'ä'

	ch = 231 /* c med cedilj till c*/
	runes[ch] = 'c'
	runes[ch+-'a'+'A'] = 'c'

	for ch = 232; ch <= 235; ch++ { /* e med accent (även é) */
		runes[ch] = 'e'
		runes[ch+-'a'+'A'] = 'e'
	}

	for ch = 236; ch <= 239; ch++ { /* i med accent */
		runes[ch] = 'i'
		runes[ch+-'a'+'A'] = 'i'
	}

	ch = 241 /* n med ~ rill n */
	runes[ch] = 'n'
	runes[ch+-'a'+'A'] = 'n'

	for ch = 242; ch <= 245; ch++ { /* o med accent (förutom ö) */
		runes[ch] = 'o'
		runes[ch+-'a'+'A'] = 'o'
	}

	ch = 248 /* o genomskuret till ö */
	runes[ch] = 'ö'
	runes[ch+-'a'+'A'] = 'ö'

	for ch = 249; ch <= 252; ch++ { /* u med accent */
		runes[ch] = 'u'
		runes[ch+-'a'+'A'] = 'u'
	}

	ch = 253 /* y med accent */
	runes[ch] = 'y'
	runes[ch+-'a'+'A'] = 'y'
	ch = 255
	runes[ch] = 'y'
	runes[ch+-'a'+'A'] = 'y'

	// Slut på översatt kod från tokenizer.c

	normalize = &table{make(map[byte]byte)}
	for from, to := range runes {
		normalize.tranlation[byte(from)] = byte(to)
	}
}

func Hash(word string) uint64 {
	switch len(word) {
	case 0:
		return 0
	case 1:
		return hash(word[0])
	case 2:
		return hash(word[1]) + hash(word[0])*BASE
	default:
		return hash(word[2]) + hash(word[1])*BASE + hash(word[0])*BASE*BASE
	}
}

func hash(b byte) uint64 {
	if normalize.tranlation[b] == 0 {
		return 0
	} else {
		return uint64(normalize.tranlation[b] - 'a' + 1)
	}
}

type tokenizer struct {
	input    *bufio.Reader
	position uint64
}

func New(reader io.Reader) *tokenizer {
	return &tokenizer{bufio.NewReader(transform.NewReader(reader, normalize)), 0}
}

func (t *tokenizer) ReadToken() (advance uint64, token string, err error) {
	// Consume non-alphabet characters
	for ch := byte(0); ch == 0; ch, err = t.input.ReadByte() {
		advance++
		if err != nil {
			return
		}
	}

	err = t.input.UnreadByte()
	if err != nil {
		return
	}
	advance--

	token, err = t.input.ReadString(0)
	if len(token) > 0 {
		// Remove the trailing zero byte
		advance += uint64(len(token))
		token = token[:len(token)-1]
	}
	return
}
<|endoftext|>


<commit_before>/* Copyright 2015 Google Inc. All Rights Reserved.
 * Kevin Klues <klueska@google.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"bytes"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/kardianos/osext"
	"github.com/docopt/docopt-go"
)

var APP_NAME string
var RUN_SCRIPT string = "run-script.sh"
var SCRIPT_PATH_SCRIPT string = "scripts/"+APP_NAME+"-print-scripts-path.sh"

func init() {
	exec_folder, _ := osext.ExecutableFolder()
	SCRIPT_PATH_SCRIPT = filepath.Join(exec_folder, SCRIPT_PATH_SCRIPT)
	RUN_SCRIPT = filepath.Join(exec_folder, RUN_SCRIPT)
	cli.CommandHelpTemplate = CommandHelpTemplate
	cli.AppHelpTemplate = AppHelpTemplate
	if len(os.Args) >= 2 {
		prepended := append([]string{"--"}, os.Args[2:]...)
		os.Args = append(os.Args[0:2], prepended...)
	}
}

func main() {
	app := cli.NewApp()
	app.EnableBashCompletion = true
	app.Name = APP_NAME
	app.Version = ""
	app.Usage = "Run a set of '"+APP_NAME+"' related scripts from a single command"
	app.Commands = addScripts(app)
	app.Run(os.Args)
}

func addScripts(app *cli.App) []cli.Command {
	cmds := []cli.Command{}
	dirs := parseScriptsPath(RunScriptSubCmd(SCRIPT_PATH_SCRIPT, "run"))
	scripts := getSortedScriptPaths(dirs)
	for _, s := range scripts {
		cmds = append(cmds, addOneScript(app, s.Path, s.Name))
	}
	return cmds
}

func getSortedScriptPaths(dirs []string) (Scripts) {
	scripts := Scripts{}
	for _, d := range dirs {
		files, _ := ioutil.ReadDir(d)
		for _, f := range files {
			s := filepath.Base(f.Name())
			if s[:len(APP_NAME) + 1] == APP_NAME + "-" {
				scripts = append(scripts, Script{s, d})
			}
		}
	}
	sort.Sort(scripts)
	return scripts
}

func addOneScript(app *cli.App, dir, script string) cli.Command {
	abspath, _ := filepath.Abs(filepath.Join(dir, script))
	name := script[len(APP_NAME) + 1:len(script)-len(filepath.Ext(script))]
	desc := fmtDescription(RunScriptSubCmd(abspath, "description"))
	usage := fmtUsage(RunScriptSubCmd(abspath, "usage"))

	return cli.Command{
		Name: name,
		Description: desc,
		Usage: usage,
		Action: func(c *cli.Context) {
			if InterceptHelp() {
				cli.ShowCommandHelp(c, name)
				return
			}
			if InterceptBashAutocomplete() {
				args, _ := parseArgs(usage, name, os.Args[3:])
				for k := range args {
					if k[0] != '<' {
						fmt.Println(k)
					}
				}
				return
			}
			args, err := parseArgs(usage, name, os.Args[3:])
			if _, ok := err.(*docopt.UserError); ok {
				fmt.Printf("Error: Illegal option, wrong argument, or missing argument\n\n")
				cli.ShowCommandHelp(c, name)
			} else if err != nil {
				fmt.Printf("Error: %s %s\n", APP_NAME, name)
				fmt.Printf("    %T\n", err)
				fmt.Printf("    %v\n", err)
			} else {
				err = RunScriptMain(abspath, args)
				if err != nil {
					cli.ShowCommandHelp(c, name)
				}
			}
		},
	}
}

func InterceptHelp() bool {
	for _, b := range os.Args {
		if b == "--help" || b == "-h" {
			return true
		}
	}
	return false
}

func InterceptBashAutocomplete() bool {
	for i, b := range os.Args {
		if b == "--generate-bash-completion" {
			os.Args = append(os.Args[:i], os.Args[i+1:]...)
			return true
		}
	}
	return false
}

func RunScriptSubCmd(script, subcmd string) (output string) {
	r, w, _ := os.Pipe()
	cmd := exec.Command("/bin/bash", RUN_SCRIPT, script, subcmd)
	cmd.Stdout = w
	cmd.Stderr = w
	cmd.Run()

    outC := make(chan string)
    go func() {
        var buf bytes.Buffer
        io.Copy(&buf, r)
        outC <- buf.String()
		r.Close()
    }()
    w.Close()
    out := <-outC
	return out
}

func RunScriptMain(script string, args map[string]interface{}) error {
	cmdArgs := TranslateCmdArgsForBash(args)
	origArgs := strings.Join(os.Args[3:], " ")
	bashArgs := []string{RUN_SCRIPT, script, "run", cmdArgs, origArgs}
	cmd := exec.Command("/bin/bash", bashArgs...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func parseArgs(usage, name string, args []string) (val map[string]interface{}, err error) {
	stdout := os.Stdout
	os.Stdout = nil
	cmdUsage := strings.Replace(usage, APP_NAME+" "+name, APP_NAME+"-"+name, -1)
    val, err = docopt.Parse(cmdUsage, args, false, "", false, false)
	os.Stdout = stdout
	return
}

func TranslateCmdArgsForBash(args map[string]interface{}) string {
	str := ""
	for k, v := range args {
		k = strings.Replace(strings.TrimPrefix(k, "--"), "-", "_", -1)
		k = strings.Replace(k, "<", "", -1)
		k = strings.Replace(k, ">", "", -1)
		str += fmt.Sprintf("local %v=%v;", k, v)
	}
	return str
}

func parseScriptsPath(path string) []string {
	array := strings.Split(path, ":")
	for i, s := range array {
		array[i] = strings.TrimSpace(s)
	}
	return array
}

func fmtUsage(usage string) string {
	return strings.TrimSpace(usage)
}

func fmtDescription(desc string) string {
	return strings.TrimSpace(desc)
}
<commit_msg>Move help interception after bash completion<commit_after>/* Copyright 2015 Google Inc. All Rights Reserved.
 * Kevin Klues <klueska@google.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"bytes"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/kardianos/osext"
	"github.com/docopt/docopt-go"
)

var APP_NAME string
var RUN_SCRIPT string = "run-script.sh"
var SCRIPT_PATH_SCRIPT string = "scripts/"+APP_NAME+"-print-scripts-path.sh"

func init() {
	exec_folder, _ := osext.ExecutableFolder()
	SCRIPT_PATH_SCRIPT = filepath.Join(exec_folder, SCRIPT_PATH_SCRIPT)
	RUN_SCRIPT = filepath.Join(exec_folder, RUN_SCRIPT)
	cli.CommandHelpTemplate = CommandHelpTemplate
	cli.AppHelpTemplate = AppHelpTemplate
	if len(os.Args) >= 2 {
		prepended := append([]string{"--"}, os.Args[2:]...)
		os.Args = append(os.Args[0:2], prepended...)
	}
}

func main() {
	app := cli.NewApp()
	app.EnableBashCompletion = true
	app.Name = APP_NAME
	app.Version = ""
	app.Usage = "Run a set of '"+APP_NAME+"' related scripts from a single command"
	app.Commands = addScripts(app)
	app.Run(os.Args)
}

func addScripts(app *cli.App) []cli.Command {
	cmds := []cli.Command{}
	dirs := parseScriptsPath(RunScriptSubCmd(SCRIPT_PATH_SCRIPT, "run"))
	scripts := getSortedScriptPaths(dirs)
	for _, s := range scripts {
		cmds = append(cmds, addOneScript(app, s.Path, s.Name))
	}
	return cmds
}

func getSortedScriptPaths(dirs []string) (Scripts) {
	scripts := Scripts{}
	for _, d := range dirs {
		files, _ := ioutil.ReadDir(d)
		for _, f := range files {
			s := filepath.Base(f.Name())
			if s[:len(APP_NAME) + 1] == APP_NAME + "-" {
				scripts = append(scripts, Script{s, d})
			}
		}
	}
	sort.Sort(scripts)
	return scripts
}

func addOneScript(app *cli.App, dir, script string) cli.Command {
	abspath, _ := filepath.Abs(filepath.Join(dir, script))
	name := script[len(APP_NAME) + 1:len(script)-len(filepath.Ext(script))]
	desc := fmtDescription(RunScriptSubCmd(abspath, "description"))
	usage := fmtUsage(RunScriptSubCmd(abspath, "usage"))

	return cli.Command{
		Name: name,
		Description: desc,
		Usage: usage,
		Action: func(c *cli.Context) {
			if InterceptBashAutocomplete() {
				args, _ := parseArgs(usage, name, os.Args[3:])
				for k := range args {
					if k[0] != '<' {
						fmt.Println(k)
					}
				}
				return
			}
			if InterceptHelp() {
				cli.ShowCommandHelp(c, name)
				return
			}
			args, err := parseArgs(usage, name, os.Args[3:])
			if _, ok := err.(*docopt.UserError); ok {
				fmt.Printf("Error: Illegal option, wrong argument, or missing argument\n\n")
				cli.ShowCommandHelp(c, name)
			} else if err != nil {
				fmt.Printf("Error: %s %s\n", APP_NAME, name)
				fmt.Printf("    %T\n", err)
				fmt.Printf("    %v\n", err)
			} else {
				err = RunScriptMain(abspath, args)
				if err != nil {
					cli.ShowCommandHelp(c, name)
				}
			}
		},
	}
}

func InterceptHelp() bool {
	for _, b := range os.Args {
		if b == "--help" || b == "-h" {
			return true
		}
	}
	return false
}

func InterceptBashAutocomplete() bool {
	for i, b := range os.Args {
		if b == "--generate-bash-completion" {
			os.Args = append(os.Args[:i], os.Args[i+1:]...)
			return true
		}
	}
	return false
}

func RunScriptSubCmd(script, subcmd string) (output string) {
	r, w, _ := os.Pipe()
	cmd := exec.Command("/bin/bash", RUN_SCRIPT, script, subcmd)
	cmd.Stdout = w
	cmd.Stderr = w
	cmd.Run()

    outC := make(chan string)
    go func() {
        var buf bytes.Buffer
        io.Copy(&buf, r)
        outC <- buf.String()
		r.Close()
    }()
    w.Close()
    out := <-outC
	return out
}

func RunScriptMain(script string, args map[string]interface{}) error {
	cmdArgs := TranslateCmdArgsForBash(args)
	origArgs := strings.Join(os.Args[3:], " ")
	bashArgs := []string{RUN_SCRIPT, script, "run", cmdArgs, origArgs}
	cmd := exec.Command("/bin/bash", bashArgs...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func parseArgs(usage, name string, args []string) (val map[string]interface{}, err error) {
	stdout := os.Stdout
	os.Stdout = nil
	cmdUsage := strings.Replace(usage, APP_NAME+" "+name, APP_NAME+"-"+name, -1)
    val, err = docopt.Parse(cmdUsage, args, false, "", false, false)
	os.Stdout = stdout
	return
}

func TranslateCmdArgsForBash(args map[string]interface{}) string {
	str := ""
	for k, v := range args {
		k = strings.Replace(strings.TrimPrefix(k, "--"), "-", "_", -1)
		k = strings.Replace(k, "<", "", -1)
		k = strings.Replace(k, ">", "", -1)
		str += fmt.Sprintf("local %v=%v;", k, v)
	}
	return str
}

func parseScriptsPath(path string) []string {
	array := strings.Split(path, ":")
	for i, s := range array {
		array[i] = strings.TrimSpace(s)
	}
	return array
}

func fmtUsage(usage string) string {
	return strings.TrimSpace(usage)
}

func fmtDescription(desc string) string {
	return strings.TrimSpace(desc)
}
<|endoftext|>


<commit_before>/*
   PulseHA - HA Cluster Daemon
   Copyright (C) 2017-2019  Andrew Zak <andrew@linux.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package main

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/Syleron/PulseHA/src/config"
	"github.com/Syleron/PulseHA/src/logging"
	"github.com/Syleron/PulseHA/src/server"
	"os"
	"os/signal"
	"strings"
	"sync"
	"syscall"
	"time"
)

const (
	PRE_SIGNAL = iota
	POST_SIGNAL
)

var (
	Version         string
	Build           string
	hookableSignals []os.Signal
)

var pulse *Pulse

/**
 * Main Pulse struct type
 */
type Pulse struct {
	DB          server.Database
	Server      *server.Server
	CLI         *server.CLIServer
	Sigs        chan os.Signal
	SignalHooks map[int]map[os.Signal][]func()
}

type PulseLogFormat struct{}

func (f *PulseLogFormat) Format(entry *log.Entry) ([]byte, error) {
	time := "[" + entry.Time.Format(time.Stamp) + "]"
	lvlOut := entry.Level.String()
	switch entry.Level {
	case log.ErrorLevel:
	case log.FatalLevel:
	case log.WarnLevel:
		lvlOut = strings.ToUpper(lvlOut)
	}
	level := "[" + lvlOut + "] "
	message := time + level + entry.Message
	return append([]byte(message), '\n'), nil
}

/**
 * Create a new instance of PulseHA
 */
func createPulse() *Pulse {
	// Create the Pulse object
	pulse := &Pulse{
		Server: &server.Server{},
		CLI:    &server.CLIServer{},
	}
	// Set our server variable
	pulse.CLI.Server = pulse.Server
	return pulse
}

func init() {
	hookableSignals = []os.Signal{
		syscall.SIGHUP,
		syscall.SIGUSR1,
		syscall.SIGUSR2,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGTSTP,
	}
}

/**
 * Essential Construct
 */
func main() {
	// Draw logo
	fmt.Printf(`
   ___       _                  _
  / _ \_   _| |___  ___  /\  /\/_\
 / /_)/ | | | / __|/ _ \/ /_/ //_\\
/ ___/| |_| | \__ \  __/ __  /  _  \  Version %s
\/     \__,_|_|___/\___\/ /_/\_/ \_/  Build   %s

`, Version, Build[0:7])
	log.SetFormatter(new(PulseLogFormat))
	pulse = createPulse()
	// listen for singals
	pulse.Sigs = make(chan os.Signal)
	signal.Notify(pulse.Sigs)
	// Handle the signals
	go handleSignals()
	// load the config
	pulse.DB = server.Database{
		Plugins:    &server.Plugins{},
		MemberList: &server.MemberList{},
	}
	// Setup a new pulse Logger
	pulseLogger, err := logging.NewLogger(pulse.DB.MemberList.Broadcast)
	if err != nil {
		panic("unable to create pulseha distributed logger")
	}
	// Set our pulse logger
	pulse.DB.Logging = pulseLogger
	// Load the config
	pulse.DB.Config = config.GetConfig()
	// Set the logging level
	setLogLevel(pulse.DB.Config.Logging.Level)
	// Setup wait group
	var wg sync.WaitGroup
	wg.Add(1)
	// Setup cli
	go pulse.CLI.Setup()
	// Setup server
	go pulse.Server.Init(&pulse.DB)
	wg.Wait()
}

/**

 */
func setLogLevel(level string) {
	logLevel, err := log.ParseLevel(level)
	if err != nil {
		panic(err.Error())
	}
	log.SetLevel(logLevel)
}

/**
Handle OS signals
*/
func handleSignals() {
	var sig os.Signal
	signal.Notify(pulse.Sigs, hookableSignals...)
	for {
		sig = <-pulse.Sigs
		signalHooks(PRE_SIGNAL, sig)
		switch sig {
		case syscall.SIGINT:
			// Bring down our floating IPS
			server.MakeLocalPassive()
			// Shutdown our server
			pulse.Server.Shutdown()
			// Reload our config
			pulse.DB.Config.Reload()
			// Start a new server
			go pulse.Server.Setup()
			break
		case syscall.SIGTERM:
			// Bring down floating IPS
			server.MakeLocalPassive()
			// Shutdown our service
			pulse.Server.Shutdown()
			os.Exit(1)
		}
		signalHooks(POST_SIGNAL, sig)
	}
}

/**

 */
func signalHooks(ppFlag int, sig os.Signal) {
	if _, notSet := pulse.SignalHooks[ppFlag][sig]; !notSet {
		return
	}
	for _, f := range pulse.SignalHooks[ppFlag][sig] {
		f()
	}
	return
}
<commit_msg>stuff<commit_after>/*
   PulseHA - HA Cluster Daemon
   Copyright (C) 2017-2019  Andrew Zak <andrew@linux.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package main

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/Syleron/PulseHA/src/config"
	"github.com/Syleron/PulseHA/src/logging"
	"github.com/Syleron/PulseHA/src/server"
	"os"
	"os/signal"
	"strings"
	"sync"
	"syscall"
	"time"
)

const (
	PRE_SIGNAL = iota
	POST_SIGNAL
)

var (
	Version         string
	Build           string
	hookableSignals []os.Signal
)

var pulse *Pulse

/**
 * Main Pulse struct type
 */
type Pulse struct {
	DB          server.Database
	Server      *server.Server
	CLI         *server.CLIServer
	Sigs        chan os.Signal
	SignalHooks map[int]map[os.Signal][]func()
}

type PulseLogFormat struct{}

func (f *PulseLogFormat) Format(entry *log.Entry) ([]byte, error) {
	time := "[" + entry.Time.Format(time.Stamp) + "]"
	lvlOut := entry.Level.String()
	switch entry.Level {
	case log.ErrorLevel:
	case log.FatalLevel:
	case log.WarnLevel:
		lvlOut = strings.ToUpper(lvlOut)
	}
	level := "[" + lvlOut + "] "
	message := time + level + entry.Message
	return append([]byte(message), '\n'), nil
}

/**
 * Create a new instance of PulseHA
 */
func createPulse() *Pulse {
	// Create the Pulse object
	pulse := &Pulse{
		Server: &server.Server{},
		CLI:    &server.CLIServer{},
	}
	// Set our server variable
	pulse.CLI.Server = pulse.Server
	return pulse
}

func init() {
	hookableSignals = []os.Signal{
		syscall.SIGHUP,
		syscall.SIGUSR1,
		syscall.SIGUSR2,
		syscall.SIGINT,
		syscall.SIGTERM,
		syscall.SIGTSTP,
	}
}

/**
 * Essential Construct
 */
func main() {
	// Draw logo
	fmt.Printf(`
   ___       _                  _
  / _ \_   _| |___  ___  /\  /\/_\
 / /_)/ | | | / __|/ _ \/ /_/ //_\\
/ ___/| |_| | \__ \  __/ __  /  _  \  Version %s
\/     \__,_|_|___/\___\/ /_/\_/ \_/  Build   %s

`, Version, Build[0:7])
	log.SetFormatter(new(PulseLogFormat))
	pulse = createPulse()
	// listen for singals
	pulse.Sigs = make(chan os.Signal)
	signal.Notify(pulse.Sigs)
	// Handle the signals
	go handleSignals()
	// load the config
	pulse.DB = server.Database{
		Plugins:    &server.Plugins{},
		MemberList: &server.MemberList{},
	}
	// Setup a new pulse Logger
	pulseLogger, err := logging.NewLogger(pulse.DB.MemberList.Broadcast)
	if err != nil {
		panic("unable to create pulseha distributed logger")
	}
	// Set our pulse logger
	pulse.DB.Logging = pulseLogger
	// Load the config
	pulse.DB.Config = config.GetConfig()
	// Set the logging level
	setLogLevel(pulse.DB.Config.Logging.Level)
	// Setup wait group
	var wg sync.WaitGroup
	wg.Add(1)
	// Setup cli
	go pulse.CLI.Setup()
	// Setup server
	go pulse.Server.Init(&pulse.DB)
	wg.Wait()
}

/**

 */
func setLogLevel(level string) {
	logLevel, err := log.ParseLevel(level)
	if err != nil {
		panic(err.Error())
	}
	log.SetLevel(logLevel)
}

/**
Handle OS signals
*/
func handleSignals() {
	var sig os.Signal
	signal.Notify(pulse.Sigs, hookableSignals...)
	for {
		sig = <-pulse.Sigs
		signalHooks(PRE_SIGNAL, sig)
		switch sig {
		case syscall.SIGINT:
			// Bring down our floating IPS
			//server.MakeLocalPassive()
			// Shutdown our server
			//pulse.Server.Shutdown()
			// Reload our config
			//pulse.DB.Config.Reload()
			// Start a new server
<<<<<<< HEAD
			go pulse.Server.Setup()
			break
=======
			//go pulse.Server.Setup()
		break
>>>>>>> 2ec9990be5ae743949ee5c0cd5f57593c9081ec0
		case syscall.SIGTERM:
			// Bring down floating IPS
			server.MakeLocalPassive()
			// Shutdown our service
			pulse.Server.Shutdown()
			os.Exit(1)
		}
		signalHooks(POST_SIGNAL, sig)
	}
}

/**

 */
func signalHooks(ppFlag int, sig os.Signal) {
	if _, notSet := pulse.SignalHooks[ppFlag][sig]; !notSet {
		return
	}
	for _, f := range pulse.SignalHooks[ppFlag][sig] {
		f()
	}
	return
}
<|endoftext|>