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

package main

import (
	"bytes"
	"container/vector"
	"exec"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"patch"
	"path/filepath"
	"sort"
	"strings"
)

var checkSync = flag.Bool("checksync", true, "check whether repository is out of sync")

func usage() {
	fmt.Fprintf(os.Stderr, "usage: hgpatch [options] [patchfile]\n")
	flag.PrintDefaults()
	os.Exit(2)
}

func main() {
	flag.Usage = usage
	flag.Parse()

	args := flag.Args()
	var data []byte
	var err os.Error
	switch len(args) {
	case 0:
		data, err = ioutil.ReadAll(os.Stdin)
	case 1:
		data, err = ioutil.ReadFile(args[0])
	default:
		usage()
	}
	chk(err)

	pset, err := patch.Parse(data)
	chk(err)

	// Change to hg root directory, because
	// patch paths are relative to root.
	root, err := hgRoot()
	chk(err)
	chk(os.Chdir(root))

	// Make sure there are no pending changes on the server.
	if *checkSync && hgIncoming() {
		fmt.Fprintf(os.Stderr, "incoming changes waiting; run hg sync first\n")
		os.Exit(2)
	}

	// Make sure we won't be editing files with local pending changes.
	dirtylist, err := hgModified()
	chk(err)
	dirty := make(map[string]bool)
	for _, f := range dirtylist {
		dirty[f] = true
	}
	conflict := make(map[string]bool)
	for _, f := range pset.File {
		if f.Verb == patch.Delete || f.Verb == patch.Rename {
			if dirty[f.Src] {
				conflict[f.Src] = true
			}
		}
		if f.Verb != patch.Delete {
			if dirty[f.Dst] {
				conflict[f.Dst] = true
			}
		}
	}
	if len(conflict) > 0 {
		fmt.Fprintf(os.Stderr, "cannot apply patch to locally modified files:\n")
		for name := range conflict {
			fmt.Fprintf(os.Stderr, "\t%s\n", name)
		}
		os.Exit(2)
	}

	// Apply changes in memory.
	op, err := pset.Apply(ioutil.ReadFile)
	chk(err)

	// Write changes to disk copy: order of commands matters.
	// Accumulate undo log as we go, in case there is an error.
	// Also accumulate list of modified files to print at end.
	changed := make(map[string]int)

	// Copy, Rename create the destination file, so they
	// must happen before we write the data out.
	// A single patch may have a Copy and a Rename
	// with the same source, so we have to run all the
	// Copy in one pass, then all the Rename.
	for i := range op {
		o := &op[i]
		if o.Verb == patch.Copy {
			makeParent(o.Dst)
			chk(hgCopy(o.Dst, o.Src))
			undoRevert(o.Dst)
			changed[o.Dst] = 1
		}
	}
	for i := range op {
		o := &op[i]
		if o.Verb == patch.Rename {
			makeParent(o.Dst)
			chk(hgRename(o.Dst, o.Src))
			undoRevert(o.Dst)
			undoRevert(o.Src)
			changed[o.Src] = 1
			changed[o.Dst] = 1
		}
	}

	// Run Delete before writing to files in case one of the
	// deleted paths is becoming a directory.
	for i := range op {
		o := &op[i]
		if o.Verb == patch.Delete {
			chk(hgRemove(o.Src))
			undoRevert(o.Src)
			changed[o.Src] = 1
		}
	}

	// Write files.
	for i := range op {
		o := &op[i]
		if o.Verb == patch.Delete {
			continue
		}
		if o.Verb == patch.Add {
			makeParent(o.Dst)
			changed[o.Dst] = 1
		}
		if o.Data != nil {
			chk(ioutil.WriteFile(o.Dst, o.Data, 0644))
			if o.Verb == patch.Add {
				undoRm(o.Dst)
			} else {
				undoRevert(o.Dst)
			}
			changed[o.Dst] = 1
		}
		if o.Mode != 0 {
			chk(os.Chmod(o.Dst, uint32(o.Mode&0755)))
			undoRevert(o.Dst)
			changed[o.Dst] = 1
		}
	}

	// hg add looks at the destination file, so it must happen
	// after we write the data out.
	for i := range op {
		o := &op[i]
		if o.Verb == patch.Add {
			chk(hgAdd(o.Dst))
			undoRevert(o.Dst)
			changed[o.Dst] = 1
		}
	}

	// Finished editing files.  Write the list of changed files to stdout.
	list := make([]string, len(changed))
	i := 0
	for f := range changed {
		list[i] = f
		i++
	}
	sort.Strings(list)
	for _, f := range list {
		fmt.Printf("%s\n", f)
	}
}

// make parent directory for name, if necessary
func makeParent(name string) {
	parent, _ := filepath.Split(name)
	chk(mkdirAll(parent, 0755))
}

// Copy of os.MkdirAll but adds to undo log after
// creating a directory.
func mkdirAll(path string, perm uint32) os.Error {
	dir, err := os.Lstat(path)
	if err == nil {
		if dir.IsDirectory() {
			return nil
		}
		return &os.PathError{"mkdir", path, os.ENOTDIR}
	}

	i := len(path)
	for i > 0 && path[i-1] == '/' { // Skip trailing slashes.
		i--
	}

	j := i
	for j > 0 && path[j-1] != '/' { // Scan backward over element.
		j--
	}

	if j > 0 {
		err = mkdirAll(path[0:j-1], perm)
		if err != nil {
			return err
		}
	}

	err = os.Mkdir(path, perm)
	if err != nil {
		// Handle arguments like "foo/." by
		// double-checking that directory doesn't exist.
		dir, err1 := os.Lstat(path)
		if err1 == nil && dir.IsDirectory() {
			return nil
		}
		return err
	}
	undoRm(path)
	return nil
}

// If err != nil, process the undo log and exit.
func chk(err os.Error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		runUndo()
		os.Exit(2)
	}
}

// Undo log
type undo func() os.Error

var undoLog vector.Vector // vector of undo

func undoRevert(name string) { undoLog.Push(undo(func() os.Error { return hgRevert(name) })) }

func undoRm(name string) { undoLog.Push(undo(func() os.Error { return os.Remove(name) })) }

func runUndo() {
	for i := undoLog.Len() - 1; i >= 0; i-- {
		if err := undoLog.At(i).(undo)(); err != nil {
			fmt.Fprintf(os.Stderr, "%s\n", err)
		}
	}
}

// hgRoot returns the root directory of the repository.
func hgRoot() (string, os.Error) {
	out, err := run([]string{"hg", "root"}, nil)
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(out), nil
}

// hgIncoming returns true if hg sync will pull in changes.
func hgIncoming() bool {
	// hg -q incoming exits 0 when there is nothing incoming, 1 otherwise.
	_, err := run([]string{"hg", "-q", "incoming"}, nil)
	return err == nil
}

// hgModified returns a list of the modified files in the
// repository.
func hgModified() ([]string, os.Error) {
	out, err := run([]string{"hg", "status", "-n"}, nil)
	if err != nil {
		return nil, err
	}
	return strings.Split(strings.TrimSpace(out), "\n"), nil
}

// hgAdd adds name to the repository.
func hgAdd(name string) os.Error {
	_, err := run([]string{"hg", "add", name}, nil)
	return err
}

// hgRemove removes name from the repository.
func hgRemove(name string) os.Error {
	_, err := run([]string{"hg", "rm", name}, nil)
	return err
}

// hgRevert reverts name.
func hgRevert(name string) os.Error {
	_, err := run([]string{"hg", "revert", name}, nil)
	return err
}

// hgCopy copies src to dst in the repository.
// Note that the argument order matches io.Copy, not "hg cp".
func hgCopy(dst, src string) os.Error {
	_, err := run([]string{"hg", "cp", src, dst}, nil)
	return err
}

// hgRename renames src to dst in the repository.
// Note that the argument order matches io.Copy, not "hg mv".
func hgRename(dst, src string) os.Error {
	_, err := run([]string{"hg", "mv", src, dst}, nil)
	return err
}

func dup(a []string) []string {
	b := make([]string, len(a))
	copy(b, a)
	return b
}

var lookPathCache = make(map[string]string)

// run runs the command argv, resolving argv[0] if necessary by searching $PATH.
// It provides input on standard input to the command.
func run(argv []string, input []byte) (out string, err os.Error) {
	if len(argv) < 1 {
		return "", &runError{dup(argv), os.EINVAL}
	}

	prog, ok := lookPathCache[argv[0]]
	if !ok {
		prog, err = exec.LookPath(argv[0])
		if err != nil {
			return "", &runError{dup(argv), err}
		}
		lookPathCache[argv[0]] = prog
	}

	cmd := exec.Command(prog, argv[1:]...)
	if len(input) > 0 {
		cmd.Stdin = bytes.NewBuffer(input)
	}
	bs, err := cmd.CombinedOutput()
	if err != nil {
		return "", &runError{dup(argv), err}
	}
	return string(bs), nil
}

// A runError represents an error that occurred while running a command.
type runError struct {
	cmd []string
	err os.Error
}

func (e *runError) String() string { return strings.Join(e.cmd, " ") + ": " + e.err.String() }
<commit_msg>cmd/hgpatch: remove container/vector<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"exec"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"patch"
	"path/filepath"
	"sort"
	"strings"
)

var checkSync = flag.Bool("checksync", true, "check whether repository is out of sync")

func usage() {
	fmt.Fprintf(os.Stderr, "usage: hgpatch [options] [patchfile]\n")
	flag.PrintDefaults()
	os.Exit(2)
}

func main() {
	flag.Usage = usage
	flag.Parse()

	args := flag.Args()
	var data []byte
	var err os.Error
	switch len(args) {
	case 0:
		data, err = ioutil.ReadAll(os.Stdin)
	case 1:
		data, err = ioutil.ReadFile(args[0])
	default:
		usage()
	}
	chk(err)

	pset, err := patch.Parse(data)
	chk(err)

	// Change to hg root directory, because
	// patch paths are relative to root.
	root, err := hgRoot()
	chk(err)
	chk(os.Chdir(root))

	// Make sure there are no pending changes on the server.
	if *checkSync && hgIncoming() {
		fmt.Fprintf(os.Stderr, "incoming changes waiting; run hg sync first\n")
		os.Exit(2)
	}

	// Make sure we won't be editing files with local pending changes.
	dirtylist, err := hgModified()
	chk(err)
	dirty := make(map[string]bool)
	for _, f := range dirtylist {
		dirty[f] = true
	}
	conflict := make(map[string]bool)
	for _, f := range pset.File {
		if f.Verb == patch.Delete || f.Verb == patch.Rename {
			if dirty[f.Src] {
				conflict[f.Src] = true
			}
		}
		if f.Verb != patch.Delete {
			if dirty[f.Dst] {
				conflict[f.Dst] = true
			}
		}
	}
	if len(conflict) > 0 {
		fmt.Fprintf(os.Stderr, "cannot apply patch to locally modified files:\n")
		for name := range conflict {
			fmt.Fprintf(os.Stderr, "\t%s\n", name)
		}
		os.Exit(2)
	}

	// Apply changes in memory.
	op, err := pset.Apply(ioutil.ReadFile)
	chk(err)

	// Write changes to disk copy: order of commands matters.
	// Accumulate undo log as we go, in case there is an error.
	// Also accumulate list of modified files to print at end.
	changed := make(map[string]int)

	// Copy, Rename create the destination file, so they
	// must happen before we write the data out.
	// A single patch may have a Copy and a Rename
	// with the same source, so we have to run all the
	// Copy in one pass, then all the Rename.
	for i := range op {
		o := &op[i]
		if o.Verb == patch.Copy {
			makeParent(o.Dst)
			chk(hgCopy(o.Dst, o.Src))
			undoRevert(o.Dst)
			changed[o.Dst] = 1
		}
	}
	for i := range op {
		o := &op[i]
		if o.Verb == patch.Rename {
			makeParent(o.Dst)
			chk(hgRename(o.Dst, o.Src))
			undoRevert(o.Dst)
			undoRevert(o.Src)
			changed[o.Src] = 1
			changed[o.Dst] = 1
		}
	}

	// Run Delete before writing to files in case one of the
	// deleted paths is becoming a directory.
	for i := range op {
		o := &op[i]
		if o.Verb == patch.Delete {
			chk(hgRemove(o.Src))
			undoRevert(o.Src)
			changed[o.Src] = 1
		}
	}

	// Write files.
	for i := range op {
		o := &op[i]
		if o.Verb == patch.Delete {
			continue
		}
		if o.Verb == patch.Add {
			makeParent(o.Dst)
			changed[o.Dst] = 1
		}
		if o.Data != nil {
			chk(ioutil.WriteFile(o.Dst, o.Data, 0644))
			if o.Verb == patch.Add {
				undoRm(o.Dst)
			} else {
				undoRevert(o.Dst)
			}
			changed[o.Dst] = 1
		}
		if o.Mode != 0 {
			chk(os.Chmod(o.Dst, uint32(o.Mode&0755)))
			undoRevert(o.Dst)
			changed[o.Dst] = 1
		}
	}

	// hg add looks at the destination file, so it must happen
	// after we write the data out.
	for i := range op {
		o := &op[i]
		if o.Verb == patch.Add {
			chk(hgAdd(o.Dst))
			undoRevert(o.Dst)
			changed[o.Dst] = 1
		}
	}

	// Finished editing files.  Write the list of changed files to stdout.
	list := make([]string, len(changed))
	i := 0
	for f := range changed {
		list[i] = f
		i++
	}
	sort.Strings(list)
	for _, f := range list {
		fmt.Printf("%s\n", f)
	}
}

// make parent directory for name, if necessary
func makeParent(name string) {
	parent, _ := filepath.Split(name)
	chk(mkdirAll(parent, 0755))
}

// Copy of os.MkdirAll but adds to undo log after
// creating a directory.
func mkdirAll(path string, perm uint32) os.Error {
	dir, err := os.Lstat(path)
	if err == nil {
		if dir.IsDirectory() {
			return nil
		}
		return &os.PathError{"mkdir", path, os.ENOTDIR}
	}

	i := len(path)
	for i > 0 && path[i-1] == '/' { // Skip trailing slashes.
		i--
	}

	j := i
	for j > 0 && path[j-1] != '/' { // Scan backward over element.
		j--
	}

	if j > 0 {
		err = mkdirAll(path[0:j-1], perm)
		if err != nil {
			return err
		}
	}

	err = os.Mkdir(path, perm)
	if err != nil {
		// Handle arguments like "foo/." by
		// double-checking that directory doesn't exist.
		dir, err1 := os.Lstat(path)
		if err1 == nil && dir.IsDirectory() {
			return nil
		}
		return err
	}
	undoRm(path)
	return nil
}

// If err != nil, process the undo log and exit.
func chk(err os.Error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		runUndo()
		os.Exit(2)
	}
}

// Undo log
type undo func() os.Error

var undoLog []undo

func undoRevert(name string) {
	undoLog = append(undoLog, undo(func() os.Error { return hgRevert(name) }))
}

func undoRm(name string) { undoLog = append(undoLog, undo(func() os.Error { return os.Remove(name) })) }

func runUndo() {
	for i := len(undoLog) - 1; i >= 0; i-- {
		if err := undoLog[i](); err != nil {
			fmt.Fprintf(os.Stderr, "%s\n", err)
		}
	}
}

// hgRoot returns the root directory of the repository.
func hgRoot() (string, os.Error) {
	out, err := run([]string{"hg", "root"}, nil)
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(out), nil
}

// hgIncoming returns true if hg sync will pull in changes.
func hgIncoming() bool {
	// hg -q incoming exits 0 when there is nothing incoming, 1 otherwise.
	_, err := run([]string{"hg", "-q", "incoming"}, nil)
	return err == nil
}

// hgModified returns a list of the modified files in the
// repository.
func hgModified() ([]string, os.Error) {
	out, err := run([]string{"hg", "status", "-n"}, nil)
	if err != nil {
		return nil, err
	}
	return strings.Split(strings.TrimSpace(out), "\n"), nil
}

// hgAdd adds name to the repository.
func hgAdd(name string) os.Error {
	_, err := run([]string{"hg", "add", name}, nil)
	return err
}

// hgRemove removes name from the repository.
func hgRemove(name string) os.Error {
	_, err := run([]string{"hg", "rm", name}, nil)
	return err
}

// hgRevert reverts name.
func hgRevert(name string) os.Error {
	_, err := run([]string{"hg", "revert", name}, nil)
	return err
}

// hgCopy copies src to dst in the repository.
// Note that the argument order matches io.Copy, not "hg cp".
func hgCopy(dst, src string) os.Error {
	_, err := run([]string{"hg", "cp", src, dst}, nil)
	return err
}

// hgRename renames src to dst in the repository.
// Note that the argument order matches io.Copy, not "hg mv".
func hgRename(dst, src string) os.Error {
	_, err := run([]string{"hg", "mv", src, dst}, nil)
	return err
}

func dup(a []string) []string {
	b := make([]string, len(a))
	copy(b, a)
	return b
}

var lookPathCache = make(map[string]string)

// run runs the command argv, resolving argv[0] if necessary by searching $PATH.
// It provides input on standard input to the command.
func run(argv []string, input []byte) (out string, err os.Error) {
	if len(argv) < 1 {
		return "", &runError{dup(argv), os.EINVAL}
	}

	prog, ok := lookPathCache[argv[0]]
	if !ok {
		prog, err = exec.LookPath(argv[0])
		if err != nil {
			return "", &runError{dup(argv), err}
		}
		lookPathCache[argv[0]] = prog
	}

	cmd := exec.Command(prog, argv[1:]...)
	if len(input) > 0 {
		cmd.Stdin = bytes.NewBuffer(input)
	}
	bs, err := cmd.CombinedOutput()
	if err != nil {
		return "", &runError{dup(argv), err}
	}
	return string(bs), nil
}

// A runError represents an error that occurred while running a command.
type runError struct {
	cmd []string
	err os.Error
}

func (e *runError) String() string { return strings.Join(e.cmd, " ") + ": " + e.err.String() }
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"bytes"
	"http"
	"json"
	"flag"
	"exec"
	"os"
	"io/ioutil"
	"strings"
	"net"
	daemon "flunky/daemon"
)

type outletNode struct {
	Address string
	Outlet  string
}

var resources map[string]outletNode
var powerDaemon *daemon.Daemon
var fileDir string

func dialServer() {
	byt := make([]byte, 82920)
	buf := bytes.NewBufferString("admn\n")
	finalBuf := bytes.NewBuffer(make([]byte, 82920))

	//Set up negoations to the telnet server. Default is accept everything.
	k, _ := net.Dial("tcp", "radix-pwr11:23")
	ret := []byte{255, 251, 253}
	for i := 0; i < 5; i++ {
		 k.Write(ret)
		 k.Read(byt)
	}

	for ;;{
	    n, _:= k.Read(byt)
	    m := strings.Index(string(byt[:n]), ":")
	    if m > 0{
	       k.Write(buf.Bytes())
	       break
	       }
	}

	for ;; {
            n, _ := k.Read(byt)
	    m := strings.Index(string(byt[:n]), ":")
	    if m > 0{
	       k.Write(buf.Bytes())
	       break
	   }
	}

	for ;; {
           n, _ := k.Read(byt)
	   m := strings.Index(string(byt[:n]), ":")
	   if m > 0{
	      k.Write([]byte("status\n"))
	      break
	   }
	}

	for ;; {
	    n, _  := k.Read(byt)
	       m := strings.Index(string(byt[:n]), "successful")
	       if m > 0{
	          break
                }
	       finalBuf.Write(byt[:n])

	}
	final := finalBuf.String()
	dex := strings.Index(final, "State")
	newFinal := final[dex:]
	dex = strings.Index(newFinal, "\n")
	fmt.Println(strings.TrimSpace(newFinal[dex:]))

	k.Close()
}

func DumpCall(w http.ResponseWriter, req *http.Request) {
	powerDaemon.DaemonLog.DebugHttp(req)
	req.ProtoMinor = 0
	err := powerDaemon.AuthN.HTTPAuthenticate(req, true)
	if err != nil {
		powerDaemon.DaemonLog.LogError("Unauthorized request for dump.", err)
		w.WriteHeader(http.StatusUnauthorized)
		return
	}
	tmp, err := json.Marshal(resources)
	powerDaemon.DaemonLog.LogError("Cannot Marshal power resources", err)
	_, err = w.Write(tmp)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
	}
	powerDaemon.DaemonLog.Log("Serviced request for data dump")
}

func printCmd(nodes []string, cmd string) {
	switch cmd {
	case "on":
		powerDaemon.DaemonLog.Log(fmt.Sprintf("%s have been turned %s", nodes, cmd))
		break
	case "off":
		powerDaemon.DaemonLog.Log(fmt.Sprintf("%s have been turned %s", nodes, cmd))
		break
	case "reboot":
		powerDaemon.DaemonLog.Log(fmt.Sprintf("%s have been %sed", nodes, cmd))
		break
	}
	return
}
func command(w http.ResponseWriter, req *http.Request) {
	var nodes []string
	req.ProtoMinor = 0
	powerDaemon.DaemonLog.DebugHttp(req)
	err := powerDaemon.AuthN.HTTPAuthenticate(req, true)
	if err != nil {
		powerDaemon.DaemonLog.LogError("Access not permitted.", err)
		w.WriteHeader(http.StatusUnauthorized)
		return
	}
	dex := strings.Split(req.RawURL, "/")
	cmd := dex[2]
	switch cmd {
	case "on", "off", "reboot":
		break
	default:
		powerDaemon.DaemonLog.LogError(fmt.Sprintf("%s command not supported", cmd), os.NewError("unsupported"))
		w.WriteHeader(http.StatusNotFound)
		return
		break
	}
	body, err := powerDaemon.ReadRequest(req)
	powerDaemon.DaemonLog.LogError("Unable to read request", err)

	err = json.Unmarshal(body, &nodes)
	powerDaemon.DaemonLog.LogError(fmt.Sprintf("Unable to unmarshal nodes for %s command.", cmd), err)

	for _, value := range nodes {
		if _, ok := resources[value]; ok {
			go func(value string) {
				err = exec.Command("./powerCont.sh", resources[value].Address, "admn", "admn", cmd, resources[value].Outlet).Run()
				powerDaemon.DaemonLog.LogError("Failed to run powerCont.sh in rebootList.", err)
			}(value)
		}
	}
	printCmd(nodes, cmd)
}

func statusList(w http.ResponseWriter, req *http.Request) {
	powerDaemon.DaemonLog.DebugHttp(req)
	powerDaemon.DaemonLog.LogDebug("Retreiving status for list given by client.")
	var nodes []string
	outletStatus := make(map[string]string)
	req.ProtoMinor = 0
	err := powerDaemon.AuthN.HTTPAuthenticate(req, true)
	if err != nil {
		powerDaemon.DaemonLog.LogError("Access not permitted.", err)
		w.WriteHeader(http.StatusUnauthorized)
		return
	}
	body, err := powerDaemon.ReadRequest(req)
	powerDaemon.DaemonLog.LogError("Could not read request", err)

	err = json.Unmarshal(body, &nodes)
	powerDaemon.DaemonLog.LogError("Unable to unmarshal nodes to be turned off.", err)

	for _, value := range nodes {
		_, ok := outletStatus[value]
		_, ok2 := resources[value]

		if !ok && ok2 {
			someBytes, err := exec.Command("./powerCont.sh", resources[value].Address, "admn", "admn", "status").Output()
			powerDaemon.DaemonLog.LogError("Failed to execute powerCont.sh and get out put in power status request.", err)

			tmpStatusLines := strings.Split(string(someBytes), "\n")

			for i := 18; i < 42; i++ {
				tmpStatusFields := strings.Split(tmpStatusLines[i], " ")

				for _, value2 := range nodes {
					if _, ok3 := resources[value2]; ok3 && ok2 {
						if resources[value2].Address == resources[value].Address && resources[value2].Outlet == tmpStatusFields[3] {
							outletStatus[value2] = tmpStatusFields[13]
						}
					}
				}
			}
		}
	}

	jsonStat, err := json.Marshal(outletStatus)
	powerDaemon.DaemonLog.LogError("Unable to marshal outlet status response.", err)

	_, err = w.Write(jsonStat)
	powerDaemon.DaemonLog.LogError("Unable to write outlet status response.", err)

}

func main() {
	dialServer()
	flag.Parse()
	var err os.Error

	powerDaemon, err = daemon.New("power")
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	user, pass, _ := powerDaemon.AuthN.GetUserAuth()
	err = powerDaemon.AuthN.Authenticate(user, pass, true)
	if err != nil {
		fmt.Println(fmt.Sprintf("You dont have permissions to start %s daemon.", powerDaemon.Name))
		os.Exit(1)
	}

	powerDB, err := ioutil.ReadFile(daemon.FileDir + "power.db")
	powerDaemon.DaemonLog.LogError("Unable to open power.db for reading.", err)

	err = json.Unmarshal(powerDB, &resources)
	powerDaemon.DaemonLog.LogError("Failed to unmarshal data read from power.db file.", err)

	http.HandleFunc("/dump", DumpCall)
	http.HandleFunc("/command/", command)
	http.HandleFunc("/status", statusList)
	powerDaemon.DaemonLog.Log(fmt.Sprintf("%s started on %s", powerDaemon.Name, powerDaemon.URL))
	err = powerDaemon.ListenAndServe()
	if err != nil {
		os.Exit(1)
	}
}
<commit_msg>MASTER: Added the information nessessary for status telnet<commit_after>package main

import (
	"fmt"
	"bytes"
	"http"
	"json"
	"flag"
	"exec"
	"os"
	"io/ioutil"
	"strings"
	"net"
	daemon "flunky/daemon"
)

type outletNode struct {
	Address string
	Outlet  string
}

var resources map[string]outletNode
var powerDaemon *daemon.Daemon
var fileDir string

//Add in error handling for the function
func returnStatus(status string, nodes []string) (outletStatus map[string]string) {
    outletStatus = make(map[string]string)

    for _, node := range(nodes){
    	dex := strings.Index(status, resources[node].Outlet)
    	first := status[dex:]

	dex = strings.Index(first, "\n")
	second := first[:dex]

    	dex = strings.Index(second, "On")
	if dex < 0 {
	    dex = strings.Index(second, "Off")
	    if dex < 0 {
	        fmt.Println("Node has no status")
		return
            }
	}
    	third := second[dex:]
    	dex = strings.Index(third, " ")
	outletStatus[node] = strings.TrimSpace(third[:dex])
  }
  return
}

//Add in error call back
func dialServer(cmd string) string {
	byt := make([]byte, 82920)
	buf := bytes.NewBufferString("admn\n")
	finalBuf := bytes.NewBuffer(make([]byte, 82920))

	//Set up negoations to the telnet server. Default is accept everything.
	k, _ := net.Dial("tcp", "radix-pwr11:23")
	ret := []byte{255, 251, 253}
	for i := 0; i < 5; i++ {
		 k.Write(ret)
		 k.Read(byt)
	}

	//All three for loops just send commands to the terminal
	for ;;{
	    n, _:= k.Read(byt)
	    m := strings.Index(string(byt[:n]), ":")
	    if m > 0{
	       k.Write(buf.Bytes())
	       break
	       }
	}

	for ;; {
            n, _ := k.Read(byt)
	    m := strings.Index(string(byt[:n]), ":")
	    if m > 0{
	       k.Write(buf.Bytes())
	       break
	   }
	}

	for ;; {
           n, _ := k.Read(byt)
	   m := strings.Index(string(byt[:n]), ":")
	   if m > 0{
	      k.Write([]byte(cmd + "\n"))
	      break
	   }
	}

       //See if the command is successful and then read the rest of the output.
	for ;; {
	    n, _  := k.Read(byt)
	       m := strings.Index(string(byt[:n]), "successful")
	       if m > 0{
	          break
                }
	       finalBuf.Write(byt[:n])

	}

	//Strip off the headers
	final := finalBuf.String()
	dex := strings.Index(final, "State")
	newFinal := final[dex:]
	dex = strings.Index(newFinal, "\n")

	//close connection and return
	k.Close()
	return strings.TrimSpace(newFinal[dex:])
}

func DumpCall(w http.ResponseWriter, req *http.Request) {
	powerDaemon.DaemonLog.DebugHttp(req)
	req.ProtoMinor = 0
	err := powerDaemon.AuthN.HTTPAuthenticate(req, true)
	if err != nil {
		powerDaemon.DaemonLog.LogError("Unauthorized request for dump.", err)
		w.WriteHeader(http.StatusUnauthorized)
		return
	}
	tmp, err := json.Marshal(resources)
	powerDaemon.DaemonLog.LogError("Cannot Marshal power resources", err)
	_, err = w.Write(tmp)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
	}
	powerDaemon.DaemonLog.Log("Serviced request for data dump")
}

func printCmd(nodes []string, cmd string) {
	switch cmd {
	case "on":
		powerDaemon.DaemonLog.Log(fmt.Sprintf("%s have been turned %s", nodes, cmd))
		break
	case "off":
		powerDaemon.DaemonLog.Log(fmt.Sprintf("%s have been turned %s", nodes, cmd))
		break
	case "reboot":
		powerDaemon.DaemonLog.Log(fmt.Sprintf("%s have been %sed", nodes, cmd))
		break
	}
	return
}

func command(w http.ResponseWriter, req *http.Request) {
	var nodes []string
	req.ProtoMinor = 0
	powerDaemon.DaemonLog.DebugHttp(req)
	err := powerDaemon.AuthN.HTTPAuthenticate(req, true)
	if err != nil {
		powerDaemon.DaemonLog.LogError("Access not permitted.", err)
		w.WriteHeader(http.StatusUnauthorized)
		return
	}
	dex := strings.Split(req.RawURL, "/")
	cmd := dex[2]
	switch cmd {
	case "on", "off", "reboot":
		break
	default:
		powerDaemon.DaemonLog.LogError(fmt.Sprintf("%s command not supported", cmd), os.NewError("unsupported"))
		w.WriteHeader(http.StatusNotFound)
		return
		break
	}
	body, err := powerDaemon.ReadRequest(req)
	powerDaemon.DaemonLog.LogError("Unable to read request", err)

	err = json.Unmarshal(body, &nodes)
	powerDaemon.DaemonLog.LogError(fmt.Sprintf("Unable to unmarshal nodes for %s command.", cmd), err)

	for _, value := range nodes {
		if _, ok := resources[value]; ok {
			go func(value string) {
				err = exec.Command("./powerCont.sh", resources[value].Address, "admn", "admn", cmd, resources[value].Outlet).Run()
				powerDaemon.DaemonLog.LogError("Failed to run powerCont.sh in rebootList.", err)
			}(value)
		}
	}
	printCmd(nodes, cmd)
}

func statusList(w http.ResponseWriter, req *http.Request) {
	powerDaemon.DaemonLog.DebugHttp(req)
	powerDaemon.DaemonLog.LogDebug("Retreiving status for list given by client.")
	var nodes []string
	outletStatus := make(map[string]string)
	req.ProtoMinor = 0
	err := powerDaemon.AuthN.HTTPAuthenticate(req, true)
	if err != nil {
		powerDaemon.DaemonLog.LogError("Access not permitted.", err)
		w.WriteHeader(http.StatusUnauthorized)
		return
	}
	body, err := powerDaemon.ReadRequest(req)
	powerDaemon.DaemonLog.LogError("Could not read request", err)

	err = json.Unmarshal(body, &nodes)
	powerDaemon.DaemonLog.LogError("Unable to unmarshal nodes to be turned off.", err)

	ret := dialServer("status")
	out := returnStatus(ret, nodes)
	fmt.Println(out)

	for _, value := range nodes {
		_, ok := outletStatus[value]
		_, ok2 := resources[value]

		if !ok && ok2 {
			someBytes, err := exec.Command("./powerCont.sh", resources[value].Address, "admn", "admn", "status").Output()
			powerDaemon.DaemonLog.LogError("Failed to execute powerCont.sh and get out put in power status request.", err)

			tmpStatusLines := strings.Split(string(someBytes), "\n")

			for i := 18; i < 42; i++ {
				tmpStatusFields := strings.Split(tmpStatusLines[i], " ")

				for _, value2 := range nodes {
					if _, ok3 := resources[value2]; ok3 && ok2 {
						if resources[value2].Address == resources[value].Address && resources[value2].Outlet == tmpStatusFields[3] {
							outletStatus[value2] = tmpStatusFields[13]
						}
					}
				}
			}
		}
	}

	jsonStat, err := json.Marshal(outletStatus)
	powerDaemon.DaemonLog.LogError("Unable to marshal outlet status response.", err)

	_, err = w.Write(jsonStat)
	powerDaemon.DaemonLog.LogError("Unable to write outlet status response.", err)

}

func main() {

	flag.Parse()
	var err os.Error

	powerDaemon, err = daemon.New("power")
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	user, pass, _ := powerDaemon.AuthN.GetUserAuth()
	err = powerDaemon.AuthN.Authenticate(user, pass, true)
	if err != nil {
		fmt.Println(fmt.Sprintf("You dont have permissions to start %s daemon.", powerDaemon.Name))
		os.Exit(1)
	}

	powerDB, err := ioutil.ReadFile(daemon.FileDir + "power.db")
	powerDaemon.DaemonLog.LogError("Unable to open power.db for reading.", err)

	err = json.Unmarshal(powerDB, &resources)
	powerDaemon.DaemonLog.LogError("Failed to unmarshal data read from power.db file.", err)

	dialServer("status")

	http.HandleFunc("/dump", DumpCall)
	http.HandleFunc("/command/", command)
	http.HandleFunc("/status", statusList)
	powerDaemon.DaemonLog.Log(fmt.Sprintf("%s started on %s", powerDaemon.Name, powerDaemon.URL))
	err = powerDaemon.ListenAndServe()
	if err != nil {
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package caspercloud

import (
	"bytes"
	"compress/gzip"
	"encoding/json"
	"github.com/PuerkitoBio/goquery"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"
)

const (
	kParserServer = "http://parser.crawler.bdp.cc/submit"
)

type Mail struct {
	From  string `json:"from"`
	Title string `json:"title"`
}

type CasperOutput struct {
	Downloads []string `json:"downloads"`
	Mails     []Mail   `json:"mails"`
}

func LoadDownloads(fs []string) {
	for _, fn := range fs {
		ParseFile(fn)
	}
}

func ParseFile(fn string) error {
	f, err := os.Open(fn)
	if err != nil {
		log.Println("fail to load file:", err)
		return err
	}
	defer f.Close()

	doc, err := goquery.NewDocumentFromReader(f)
	if err != nil {
		log.Println("fail to get dom:", err)
		return err
	}
	log.Println("file length", len(doc.Text()))
	return nil
}

type MailProcessor struct {
}

func NewMailProcessor() *MailProcessor {
	return &MailProcessor{}
}

func (p *MailProcessor) postData(data string) bool {
	buf := bytes.NewBuffer(nil)
	w := gzip.NewWriter(buf)
	defer w.Close()

	if _, err := w.Write([]byte(data)); err != nil {
		log.Println("gzip compress err:", err)
	}
	w.Flush()

	params := url.Values{}
	params.Set("data", string(buf.Bytes()))
	response, err := http.PostForm(kParserServer, params)
	if err != nil || response == nil {
		log.Println("do request get error:", err.Error(), " response:", response)
		return false
	}
	defer response.Body.Close()

	body, _ := ioutil.ReadAll(response.Body)

	log.Println("|post result|", string(body))
	return true
}

func (p *MailProcessor) Process(metaInfo map[string]string, downloads []string) bool {
	var mails []string
	isZip := false
	for _, fn := range downloads {
		f, err := os.Open(fn)
		if strings.HasSuffix(fn, ".zip") {
			isZip = true
		}
		if err != nil {
			log.Fatal("open file get error:", err.Error())
		}

		fd, err := ioutil.ReadAll(f)
		if err != nil {
			log.Fatal("read file get error:", err.Error())
		}
		mails = append(mails, string(fd))
		f.Close()
	}
	htmls, err := json.Marshal(mails)
	if err != nil {
		log.Fatal("marshal mails get err:", err.Error())
	}
	metaInfo["raw_html"] = string(htmls)

	if isZip {
		metaInfo["is_zip"] = "true"
	} else {
		metaInfo["is_zip"] = "false"
	}

	data, err := json.Marshal(metaInfo)
	if err != nil {
		log.Fatal("marshal metainfo get error:", err.Error())
	}
	p.postData(string(data))
	return true
}
<commit_msg>add base64 encode<commit_after>package caspercloud

import (
	"bytes"
	"compress/gzip"
	"encoding/base64"
	"encoding/json"
	"github.com/PuerkitoBio/goquery"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"
)

const (
	kParserServer = "http://parser.crawler.bdp.cc/submit"
)

type Mail struct {
	From  string `json:"from"`
	Title string `json:"title"`
}

type CasperOutput struct {
	Downloads []string `json:"downloads"`
	Mails     []Mail   `json:"mails"`
}

func LoadDownloads(fs []string) {
	for _, fn := range fs {
		ParseFile(fn)
	}
}

func ParseFile(fn string) error {
	f, err := os.Open(fn)
	if err != nil {
		log.Println("fail to load file:", err)
		return err
	}
	defer f.Close()

	doc, err := goquery.NewDocumentFromReader(f)
	if err != nil {
		log.Println("fail to get dom:", err)
		return err
	}
	log.Println("file length", len(doc.Text()))
	return nil
}

type MailProcessor struct {
}

func NewMailProcessor() *MailProcessor {
	return &MailProcessor{}
}

func (p *MailProcessor) postData(data string) bool {
	buf := bytes.NewBuffer(nil)
	w := gzip.NewWriter(buf)
	defer w.Close()

	if _, err := w.Write([]byte(data)); err != nil {
		log.Println("gzip compress err:", err)
	}
	w.Flush()

	params := url.Values{}
	params.Set("data", string(buf.Bytes()))
	response, err := http.PostForm(kParserServer, params)
	if err != nil || response == nil {
		log.Println("do request get error:", err.Error(), " response:", response)
		return false
	}
	defer response.Body.Close()

	body, _ := ioutil.ReadAll(response.Body)

	log.Println("|post result|", string(body))
	return true
}

func (p *MailProcessor) Process(metaInfo map[string]string, downloads []string) bool {
	var mails []string
	isZip := false
	for _, fn := range downloads {
		f, err := os.Open(fn)
		if strings.HasSuffix(fn, ".zip") {
			isZip = true
		}
		if err != nil {
			log.Fatal("open file get error:", err.Error())
		}

		fd, err := ioutil.ReadAll(f)
		if err != nil {
			log.Fatal("read file get error:", err.Error())
		}

		mails = append(mails, base64.StdEncoding.EncodeToString(fd))
		f.Close()
	}
	htmls, err := json.Marshal(mails)
	if err != nil {
		log.Fatal("marshal mails get err:", err.Error())
	}
	metaInfo["raw_html"] = string(htmls)

	if isZip {
		metaInfo["is_zip"] = "true"
	} else {
		metaInfo["is_zip"] = "false"
	}

	data, err := json.Marshal(metaInfo)
	if err != nil {
		log.Fatal("marshal metainfo get error:", err.Error())
	}
	p.postData(string(data))
	return true
}
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.180"
<commit_msg>functions: 0.3.181 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.181"
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.281"
<commit_msg>fnserver: 0.3.282 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.282"
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.718"
<commit_msg>fnserver: v0.3.719 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.719"
<|endoftext|>


<commit_before>package docker

import (
	"context"
	"fmt"
	"github.com/ViBiOh/docker-deploy/jsonHttp"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/network"
	"github.com/docker/docker/api/types/strslice"
	"gopkg.in/yaml.v2"
	"log"
	"net/http"
	"regexp"
	"strings"
	"time"
)

const minMemory = 67108864
const maxMemory = 536870912
const defaultTag = `:latest`
const deploySuffix = `_deploy`
const linkSeparator = `:`

var networkConfig = network.NetworkingConfig{
	EndpointsConfig: map[string]*network.EndpointSettings{
		`traefik`: &network.EndpointSettings{},
	},
}

var imageTag = regexp.MustCompile(`^\S*?:\S+$`)
var commandSplit = regexp.MustCompile(`["']([^"']+)["']|(\S+)`)

type dockerComposeService struct {
	Image       string
	Command     string
	Environment map[string]string
	Labels      map[string]string
	Links       []string
	ReadOnly    bool  `yaml:"read_only"`
	CPUShares   int64 `yaml:"cpu_shares"`
	MemoryLimit int64 `yaml:"mem_limit"`
}

type dockerCompose struct {
	Version  string
	Services map[string]dockerComposeService
}

type deployedService struct {
	ID   string
	Name string
}

func getConfig(service *dockerComposeService, loggedUser *user, appName string) *container.Config {
	environments := make([]string, len(service.Environment))
	for key, value := range service.Environment {
		environments = append(environments, key+`=`+value)
	}

	if service.Labels == nil {
		service.Labels = make(map[string]string)
	}

	service.Labels[ownerLabel] = loggedUser.username
	service.Labels[appLabel] = appName

	config := container.Config{
		Image:  service.Image,
		Labels: service.Labels,
		Env:    environments,
	}

	if service.Command != `` {
		config.Cmd = strslice.StrSlice{}
		for _, args := range commandSplit.FindAllStringSubmatch(service.Command, -1) {
			config.Cmd = append(config.Cmd, args[1]+args[2])
		}
	}

	return &config
}

func getHostConfig(service *dockerComposeService, deployedServices map[string]deployedService) *container.HostConfig {
	hostConfig := container.HostConfig{
		LogConfig: container.LogConfig{Type: `json-file`, Config: map[string]string{
			`max-size`: `50m`,
		}},
		RestartPolicy: container.RestartPolicy{Name: `on-failure`, MaximumRetryCount: 5},
		Resources: container.Resources{
			CPUShares: 128,
			Memory:    minMemory,
		},
		SecurityOpt: []string{`no-new-privileges`},
	}

	if service.ReadOnly {
		hostConfig.ReadonlyRootfs = service.ReadOnly
	}

	if service.CPUShares != 0 {
		hostConfig.Resources.CPUShares = service.CPUShares
	}

	if service.MemoryLimit != 0 {
		if service.MemoryLimit < maxMemory {
			hostConfig.Resources.Memory = service.MemoryLimit
		} else {
			hostConfig.Resources.Memory = maxMemory
		}
	}

	for _, link := range service.Links {
		linkParts := strings.Split(link, linkSeparator)

		id := linkParts[0]
		if linkedService, ok := deployedServices[linkParts[0]]; ok {
			id := linkedService.ID
		}

		alias := linkParts[0]
		if len(linkParts) > 1 {
			alias = linkParts[1]
		}

		hostConfig.Links = append(hostConfig.Links, id+linkSeparator+alias)
	}

	return &hostConfig
}

func pullImage(image string, loggedUser *user) error {
	if !imageTag.MatchString(image) {
		image = image + defaultTag
	}

	log.Print(loggedUser.username + ` starts pulling for ` + image)
	pull, err := docker.ImagePull(context.Background(), image, types.ImagePullOptions{})
	if err != nil {
		return fmt.Errorf(`Error while pulling image: %v`, err)
	}

	readBody(pull)
	log.Print(loggedUser.username + ` ends pulling for ` + image)
	return nil
}

func cleanContainers(containers *[]types.Container, loggedUser *user) {
	for _, container := range *containers {
		log.Print(loggedUser.username + ` stops ` + strings.Join(container.Names, `, `))
		stopContainer(container.ID)
		log.Print(loggedUser.username + ` rm ` + strings.Join(container.Names, `, `))
		rmContainer(container.ID)
	}
}

func renameDeployedContainers(containers *map[string]deployedService) error {
	for _, service := range *containers {
		if err := docker.ContainerRename(context.Background(), service.ID, strings.TrimSuffix(service.Name, deploySuffix)); err != nil {
			return fmt.Errorf(`Error while renaming container %s: %v`, service.Name, err)
		}
	}

	return nil
}

func getServiceFullName(appName string, serviceName string) string {
	return appName + `_` + serviceName + deploySuffix
}

func createAppHandler(w http.ResponseWriter, loggedUser *user, appName []byte, composeFile []byte) {
	if len(appName) == 0 || len(composeFile) == 0 {
		http.Error(w, `An application name and a compose file are required`, http.StatusBadRequest)
		return
	}

	compose := dockerCompose{}
	if err := yaml.Unmarshal(composeFile, &compose); err != nil {
		errorHandler(w, fmt.Errorf(`Error while unmarshalling compose file: %v`, err))
		return
	}

	appNameStr := string(appName)
	log.Print(loggedUser.username + ` deploys ` + appNameStr)

	ownerContainers, err := listContainers(loggedUser, &appNameStr)
	if err != nil {
		errorHandler(w, err)
		return
	}

	deployedServices := make(map[string]deployedService)
	for serviceName, service := range compose.Services {
		if err := pullImage(service.Image, loggedUser); err != nil {
			errorHandler(w, err)
			return
		}

		serviceFullName := getServiceFullName(appNameStr, serviceName)
		log.Print(loggedUser.username + ` starts ` + serviceFullName)

		id, err := docker.ContainerCreate(context.Background(), getConfig(&service, loggedUser, appNameStr), getHostConfig(&service, deployedServices), &networkConfig, serviceFullName)
		if err != nil {
			errorHandler(w, fmt.Errorf(`Error while creating container: %v`, err))
			return
		}

		startContainer(id.ID)
		deployedServices[serviceName] = deployedService{ID: id.ID, Name: serviceFullName}
	}

	log.Print(`Waiting 10 seconds for containers to start...`)
	time.Sleep(10 * time.Second)

	cleanContainers(&ownerContainers, loggedUser)
	if err := renameDeployedContainers(&deployedServices); err != nil {
		errorHandler(w, err)
		return
	}

	jsonHttp.ResponseJSON(w, results{deployedServices})
}
<commit_msg>Fixing compilation error<commit_after>package docker

import (
	"context"
	"fmt"
	"github.com/ViBiOh/docker-deploy/jsonHttp"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/network"
	"github.com/docker/docker/api/types/strslice"
	"gopkg.in/yaml.v2"
	"log"
	"net/http"
	"regexp"
	"strings"
	"time"
)

const minMemory = 67108864
const maxMemory = 536870912
const defaultTag = `:latest`
const deploySuffix = `_deploy`
const linkSeparator = `:`

var networkConfig = network.NetworkingConfig{
	EndpointsConfig: map[string]*network.EndpointSettings{
		`traefik`: &network.EndpointSettings{},
	},
}

var imageTag = regexp.MustCompile(`^\S*?:\S+$`)
var commandSplit = regexp.MustCompile(`["']([^"']+)["']|(\S+)`)

type dockerComposeService struct {
	Image       string
	Command     string
	Environment map[string]string
	Labels      map[string]string
	Links       []string
	ReadOnly    bool  `yaml:"read_only"`
	CPUShares   int64 `yaml:"cpu_shares"`
	MemoryLimit int64 `yaml:"mem_limit"`
}

type dockerCompose struct {
	Version  string
	Services map[string]dockerComposeService
}

type deployedService struct {
	ID   string
	Name string
}

func getConfig(service *dockerComposeService, loggedUser *user, appName string) *container.Config {
	environments := make([]string, len(service.Environment))
	for key, value := range service.Environment {
		environments = append(environments, key+`=`+value)
	}

	if service.Labels == nil {
		service.Labels = make(map[string]string)
	}

	service.Labels[ownerLabel] = loggedUser.username
	service.Labels[appLabel] = appName

	config := container.Config{
		Image:  service.Image,
		Labels: service.Labels,
		Env:    environments,
	}

	if service.Command != `` {
		config.Cmd = strslice.StrSlice{}
		for _, args := range commandSplit.FindAllStringSubmatch(service.Command, -1) {
			config.Cmd = append(config.Cmd, args[1]+args[2])
		}
	}

	return &config
}

func getHostConfig(service *dockerComposeService, deployedServices map[string]deployedService) *container.HostConfig {
	hostConfig := container.HostConfig{
		LogConfig: container.LogConfig{Type: `json-file`, Config: map[string]string{
			`max-size`: `50m`,
		}},
		RestartPolicy: container.RestartPolicy{Name: `on-failure`, MaximumRetryCount: 5},
		Resources: container.Resources{
			CPUShares: 128,
			Memory:    minMemory,
		},
		SecurityOpt: []string{`no-new-privileges`},
	}

	if service.ReadOnly {
		hostConfig.ReadonlyRootfs = service.ReadOnly
	}

	if service.CPUShares != 0 {
		hostConfig.Resources.CPUShares = service.CPUShares
	}

	if service.MemoryLimit != 0 {
		if service.MemoryLimit < maxMemory {
			hostConfig.Resources.Memory = service.MemoryLimit
		} else {
			hostConfig.Resources.Memory = maxMemory
		}
	}

	for _, link := range service.Links {
		linkParts := strings.Split(link, linkSeparator)

		id := linkParts[0]
		if linkedService, ok := deployedServices[linkParts[0]]; ok {
			id = linkedService.ID
		}

		alias := linkParts[0]
		if len(linkParts) > 1 {
			alias = linkParts[1]
		}

		hostConfig.Links = append(hostConfig.Links, id+linkSeparator+alias)
	}

	return &hostConfig
}

func pullImage(image string, loggedUser *user) error {
	if !imageTag.MatchString(image) {
		image = image + defaultTag
	}

	log.Print(loggedUser.username + ` starts pulling for ` + image)
	pull, err := docker.ImagePull(context.Background(), image, types.ImagePullOptions{})
	if err != nil {
		return fmt.Errorf(`Error while pulling image: %v`, err)
	}

	readBody(pull)
	log.Print(loggedUser.username + ` ends pulling for ` + image)
	return nil
}

func cleanContainers(containers *[]types.Container, loggedUser *user) {
	for _, container := range *containers {
		log.Print(loggedUser.username + ` stops ` + strings.Join(container.Names, `, `))
		stopContainer(container.ID)
		log.Print(loggedUser.username + ` rm ` + strings.Join(container.Names, `, `))
		rmContainer(container.ID)
	}
}

func renameDeployedContainers(containers *map[string]deployedService) error {
	for _, service := range *containers {
		if err := docker.ContainerRename(context.Background(), service.ID, strings.TrimSuffix(service.Name, deploySuffix)); err != nil {
			return fmt.Errorf(`Error while renaming container %s: %v`, service.Name, err)
		}
	}

	return nil
}

func getServiceFullName(appName string, serviceName string) string {
	return appName + `_` + serviceName + deploySuffix
}

func createAppHandler(w http.ResponseWriter, loggedUser *user, appName []byte, composeFile []byte) {
	if len(appName) == 0 || len(composeFile) == 0 {
		http.Error(w, `An application name and a compose file are required`, http.StatusBadRequest)
		return
	}

	compose := dockerCompose{}
	if err := yaml.Unmarshal(composeFile, &compose); err != nil {
		errorHandler(w, fmt.Errorf(`Error while unmarshalling compose file: %v`, err))
		return
	}

	appNameStr := string(appName)
	log.Print(loggedUser.username + ` deploys ` + appNameStr)

	ownerContainers, err := listContainers(loggedUser, &appNameStr)
	if err != nil {
		errorHandler(w, err)
		return
	}

	deployedServices := make(map[string]deployedService)
	for serviceName, service := range compose.Services {
		if err := pullImage(service.Image, loggedUser); err != nil {
			errorHandler(w, err)
			return
		}

		serviceFullName := getServiceFullName(appNameStr, serviceName)
		log.Print(loggedUser.username + ` starts ` + serviceFullName)

		id, err := docker.ContainerCreate(context.Background(), getConfig(&service, loggedUser, appNameStr), getHostConfig(&service, deployedServices), &networkConfig, serviceFullName)
		if err != nil {
			errorHandler(w, fmt.Errorf(`Error while creating container: %v`, err))
			return
		}

		startContainer(id.ID)
		deployedServices[serviceName] = deployedService{ID: id.ID, Name: serviceFullName}
	}

	log.Print(`Waiting 10 seconds for containers to start...`)
	time.Sleep(10 * time.Second)

	cleanContainers(&ownerContainers, loggedUser)
	if err := renameDeployedContainers(&deployedServices); err != nil {
		errorHandler(w, err)
		return
	}

	jsonHttp.ResponseJSON(w, results{deployedServices})
}
<|endoftext|>


<commit_before>package vnc

import (
	"crypto/des"
	"encoding/binary"
	"net"
)

// ClientAuthVNC is the standard password authentication
type ClientAuthVNC struct {
	Password string
}

func (*ClientAuthVNC) SecurityType() uint8 {
	return 2
}

func (auth *ClientAuthVNC) Handshake(conn net.Conn) error {
	// Read challenge block
	var challenge [16]byte
	if err := binary.Read(conn, binary.BigEndian, &challenge); err != nil {
		return err
	}

	// Copy password string to 8 byte 0-padded slice
	key := make([]byte, 8)
	copy(key, auth.Password)

	// Each byte of the password needs to be reversed. This is a
	// non RFC-documented behaviour of VNC clients and servers
	for i := range key {
		key[i] = reverse(key[i])
	}
	cipher, err := des.NewCipher(key)
	if err != nil {
		return err
	}

	// Encrypt the challenge low 8 bytes then high 8 bytes
	challengeLow := challenge[0:8]
	challengeHigh := challenge[8:16]
	cipher.Encrypt(challengeLow, challengeLow)
	cipher.Encrypt(challengeHigh, challengeHigh)

	// Send the encrypted challenge back to server
	err = binary.Write(conn, binary.BigEndian, challenge)
	if err != nil {
		return err
	}

	return nil
}

func reverse(x byte) byte {
	x = (x&0x55)<<1 | (x&0xAA)>>1
	x = (x&0x33)<<2 | (x&0xCC)>>2
	x = (x&0x0F)<<4 | (x&0xF0)>>4
	return x
}
<commit_msg>Inline-d the byte reversal logic of VNC auth<commit_after>package vnc

import (
	"crypto/des"
	"encoding/binary"
	"net"
)

// ClientAuthVNC is the standard password authentication
type ClientAuthVNC struct {
	Password string
}

func (*ClientAuthVNC) SecurityType() uint8 {
	return 2
}

func (auth *ClientAuthVNC) Handshake(conn net.Conn) error {
	// Read challenge block
	var challenge [16]byte
	if err := binary.Read(conn, binary.BigEndian, &challenge); err != nil {
		return err
	}

	// Copy password string to 8 byte 0-padded slice
	key := make([]byte, 8)
	copy(key, auth.Password)

	// Each byte of the password needs to be reversed. This is a
	// non RFC-documented behaviour of VNC clients and servers
	for i := range key {
		key[i] = (key[i]&0x55)<<1 | (key[i]&0xAA)>>1 // Swap adjacent bits
		key[i] = (key[i]&0x33)<<2 | (key[i]&0xCC)>>2 // Swap adjacent pairs
		key[i] = (key[i]&0x0F)<<4 | (key[i]&0xF0)>>4 // Swap the 2 halves
	}

	cipher, err := des.NewCipher(key)
	if err != nil {
		return err
	}

	// Encrypt the challenge low 8 bytes then high 8 bytes
	challengeLow := challenge[0:8]
	challengeHigh := challenge[8:16]
	cipher.Encrypt(challengeLow, challengeLow)
	cipher.Encrypt(challengeHigh, challengeHigh)

	// Send the encrypted challenge back to server
	err = binary.Write(conn, binary.BigEndian, challenge)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package api

import (
	"fmt"
	"sort"
	"time"
)

const (
	// JobTypeService indicates a long-running processes
	JobTypeService = "service"

	// JobTypeBatch indicates a short-lived process
	JobTypeBatch = "batch"
)

const (
	// RegisterEnforceIndexErrPrefix is the prefix to use in errors caused by
	// enforcing the job modify index during registers.
	RegisterEnforceIndexErrPrefix = "Enforcing job modify index"
)

// Jobs is used to access the job-specific endpoints.
type Jobs struct {
	client *Client
}

// Jobs returns a handle on the jobs endpoints.
func (c *Client) Jobs() *Jobs {
	return &Jobs{client: c}
}

// Register is used to register a new job. It returns the ID
// of the evaluation, along with any errors encountered.
func (j *Jobs) Register(job *Job, q *WriteOptions) (string, *WriteMeta, error) {

	var resp registerJobResponse

	req := &RegisterJobRequest{Job: job}
	wm, err := j.client.write("/v1/jobs", req, &resp, q)
	if err != nil {
		return "", nil, err
	}
	return resp.EvalID, wm, nil
}

// EnforceRegister is used to register a job enforcing its job modify index.
func (j *Jobs) EnforceRegister(job *Job, modifyIndex uint64, q *WriteOptions) (string, *WriteMeta, error) {

	var resp registerJobResponse

	req := &RegisterJobRequest{
		Job:            job,
		EnforceIndex:   true,
		JobModifyIndex: modifyIndex,
	}
	wm, err := j.client.write("/v1/jobs", req, &resp, q)
	if err != nil {
		return "", nil, err
	}
	return resp.EvalID, wm, nil
}

// List is used to list all of the existing jobs.
func (j *Jobs) List(q *QueryOptions) ([]*JobListStub, *QueryMeta, error) {
	var resp []*JobListStub
	qm, err := j.client.query("/v1/jobs", &resp, q)
	if err != nil {
		return nil, qm, err
	}
	sort.Sort(JobIDSort(resp))
	return resp, qm, nil
}

// PrefixList is used to list all existing jobs that match the prefix.
func (j *Jobs) PrefixList(prefix string) ([]*JobListStub, *QueryMeta, error) {
	return j.List(&QueryOptions{Prefix: prefix})
}

// Info is used to retrieve information about a particular
// job given its unique ID.
func (j *Jobs) Info(jobID string, q *QueryOptions) (*Job, *QueryMeta, error) {
	var resp Job
	qm, err := j.client.query("/v1/job/"+jobID, &resp, q)
	if err != nil {
		return nil, nil, err
	}
	return &resp, qm, nil
}

// Allocations is used to return the allocs for a given job ID.
func (j *Jobs) Allocations(jobID string, q *QueryOptions) ([]*AllocationListStub, *QueryMeta, error) {
	var resp []*AllocationListStub
	qm, err := j.client.query("/v1/job/"+jobID+"/allocations", &resp, q)
	if err != nil {
		return nil, nil, err
	}
	sort.Sort(AllocIndexSort(resp))
	return resp, qm, nil
}

// Evaluations is used to query the evaluations associated with
// the given job ID.
func (j *Jobs) Evaluations(jobID string, q *QueryOptions) ([]*Evaluation, *QueryMeta, error) {
	var resp []*Evaluation
	qm, err := j.client.query("/v1/job/"+jobID+"/evaluations", &resp, q)
	if err != nil {
		return nil, nil, err
	}
	sort.Sort(EvalIndexSort(resp))
	return resp, qm, nil
}

// Deregister is used to remove an existing job.
func (j *Jobs) Deregister(jobID string, q *WriteOptions) (string, *WriteMeta, error) {
	var resp deregisterJobResponse
	wm, err := j.client.delete("/v1/job/"+jobID, &resp, q)
	if err != nil {
		return "", nil, err
	}
	return resp.EvalID, wm, nil
}

// ForceEvaluate is used to force-evaluate an existing job.
func (j *Jobs) ForceEvaluate(jobID string, q *WriteOptions) (string, *WriteMeta, error) {
	var resp registerJobResponse
	wm, err := j.client.write("/v1/job/"+jobID+"/evaluate", nil, &resp, q)
	if err != nil {
		return "", nil, err
	}
	return resp.EvalID, wm, nil
}

// PeriodicForce spawns a new instance of the periodic job and returns the eval ID
func (j *Jobs) PeriodicForce(jobID string, q *WriteOptions) (string, *WriteMeta, error) {
	var resp periodicForceResponse
	wm, err := j.client.write("/v1/job/"+jobID+"/periodic/force", nil, &resp, q)
	if err != nil {
		return "", nil, err
	}
	return resp.EvalID, wm, nil
}

func (j *Jobs) Plan(job *Job, diff bool, q *WriteOptions) (*JobPlanResponse, *WriteMeta, error) {
	if job == nil {
		return nil, nil, fmt.Errorf("must pass non-nil job")
	}

	var resp JobPlanResponse
	req := &JobPlanRequest{
		Job:  job,
		Diff: diff,
	}
	wm, err := j.client.write("/v1/job/"+job.ID+"/plan", req, &resp, q)
	if err != nil {
		return nil, nil, err
	}

	return &resp, wm, nil
}

func (j *Jobs) Summary(jobID string, q *QueryOptions) (*JobSummary, *QueryMeta, error) {
	var resp JobSummary
	qm, err := j.client.query("/v1/job/"+jobID+"/summary", &resp, q)
	if err != nil {
		return nil, nil, err
	}
	return &resp, qm, nil
}

// periodicForceResponse is used to deserialize a force response
type periodicForceResponse struct {
	EvalID string
}

// UpdateStrategy is for serializing update strategy for a job.
type UpdateStrategy struct {
	Stagger     time.Duration
	MaxParallel int
}

// PeriodicConfig is for serializing periodic config for a job.
type PeriodicConfig struct {
	Enabled         bool
	Spec            string
	SpecType        string
	ProhibitOverlap bool
}

// Job is used to serialize a job.
type Job struct {
	Region            string
	ID                string
	Name              string
	Type              string
	Priority          int
	AllAtOnce         bool
	Datacenters       []string
	Constraints       []*Constraint
	TaskGroups        []*TaskGroup
	Update            *UpdateStrategy
	Periodic          *PeriodicConfig
	Meta              map[string]string
	Status            string
	StatusDescription string
	CreateIndex       uint64
	ModifyIndex       uint64
	JobModifyIndex    uint64
}

// JobSummary summarizes the state of the allocations of a job
type JobSummary struct {
	JobID   string
	Summary map[string]TaskGroupSummary

	// Raft Indexes
	CreateIndex uint64
	ModifyIndex uint64
}

// TaskGroup summarizes the state of all the allocations of a particular
// TaskGroup
type TaskGroupSummary struct {
	Queued   int
	Complete int
	Failed   int
	Running  int
	Starting int
	Lost     int
}

// JobListStub is used to return a subset of information about
// jobs during list operations.
type JobListStub struct {
	ID                string
	ParentID          string
	Name              string
	Type              string
	Priority          int
	Status            string
	StatusDescription string
	JobSummary        *JobSummary
	CreateIndex       uint64
	ModifyIndex       uint64
	JobModifyIndex    uint64
}

// JobIDSort is used to sort jobs by their job ID's.
type JobIDSort []*JobListStub

func (j JobIDSort) Len() int {
	return len(j)
}

func (j JobIDSort) Less(a, b int) bool {
	return j[a].ID < j[b].ID
}

func (j JobIDSort) Swap(a, b int) {
	j[a], j[b] = j[b], j[a]
}

// NewServiceJob creates and returns a new service-style job
// for long-lived processes using the provided name, ID, and
// relative job priority.
func NewServiceJob(id, name, region string, pri int) *Job {
	return newJob(id, name, region, JobTypeService, pri)
}

// NewBatchJob creates and returns a new batch-style job for
// short-lived processes using the provided name and ID along
// with the relative job priority.
func NewBatchJob(id, name, region string, pri int) *Job {
	return newJob(id, name, region, JobTypeBatch, pri)
}

// newJob is used to create a new Job struct.
func newJob(id, name, region, typ string, pri int) *Job {
	return &Job{
		Region:   region,
		ID:       id,
		Name:     name,
		Type:     typ,
		Priority: pri,
	}
}

// SetMeta is used to set arbitrary k/v pairs of metadata on a job.
func (j *Job) SetMeta(key, val string) *Job {
	if j.Meta == nil {
		j.Meta = make(map[string]string)
	}
	j.Meta[key] = val
	return j
}

// AddDatacenter is used to add a datacenter to a job.
func (j *Job) AddDatacenter(dc string) *Job {
	j.Datacenters = append(j.Datacenters, dc)
	return j
}

// Constrain is used to add a constraint to a job.
func (j *Job) Constrain(c *Constraint) *Job {
	j.Constraints = append(j.Constraints, c)
	return j
}

// AddTaskGroup adds a task group to an existing job.
func (j *Job) AddTaskGroup(grp *TaskGroup) *Job {
	j.TaskGroups = append(j.TaskGroups, grp)
	return j
}

// AddPeriodicConfig adds a periodic config to an existing job.
func (j *Job) AddPeriodicConfig(cfg *PeriodicConfig) *Job {
	j.Periodic = cfg
	return j
}

// RegisterJobRequest is used to serialize a job registration
type RegisterJobRequest struct {
	Job            *Job
	EnforceIndex   bool
	JobModifyIndex uint64
}

// registerJobResponse is used to deserialize a job response
type registerJobResponse struct {
	EvalID string
}

// deregisterJobResponse is used to decode a deregister response
type deregisterJobResponse struct {
	EvalID string
}

type JobPlanRequest struct {
	Job  *Job
	Diff bool
}

type JobPlanResponse struct {
	JobModifyIndex     uint64
	CreatedEvals       []*Evaluation
	Diff               *JobDiff
	Annotations        *PlanAnnotations
	FailedTGAllocs     map[string]*AllocationMetric
	NextPeriodicLaunch time.Time
}

type JobDiff struct {
	Type       string
	ID         string
	Fields     []*FieldDiff
	Objects    []*ObjectDiff
	TaskGroups []*TaskGroupDiff
}

type TaskGroupDiff struct {
	Type    string
	Name    string
	Fields  []*FieldDiff
	Objects []*ObjectDiff
	Tasks   []*TaskDiff
	Updates map[string]uint64
}

type TaskDiff struct {
	Type        string
	Name        string
	Fields      []*FieldDiff
	Objects     []*ObjectDiff
	Annotations []string
}

type FieldDiff struct {
	Type        string
	Name        string
	Old, New    string
	Annotations []string
}

type ObjectDiff struct {
	Type    string
	Name    string
	Fields  []*FieldDiff
	Objects []*ObjectDiff
}

type PlanAnnotations struct {
	DesiredTGUpdates map[string]*DesiredUpdates
}

type DesiredUpdates struct {
	Ignore            uint64
	Place             uint64
	Migrate           uint64
	Stop              uint64
	InPlaceUpdate     uint64
	DestructiveUpdate uint64
}
<commit_msg>Fix nomad inspect output<commit_after>package api

import (
	"fmt"
	"sort"
	"time"
)

const (
	// JobTypeService indicates a long-running processes
	JobTypeService = "service"

	// JobTypeBatch indicates a short-lived process
	JobTypeBatch = "batch"
)

const (
	// RegisterEnforceIndexErrPrefix is the prefix to use in errors caused by
	// enforcing the job modify index during registers.
	RegisterEnforceIndexErrPrefix = "Enforcing job modify index"
)

// Jobs is used to access the job-specific endpoints.
type Jobs struct {
	client *Client
}

// Jobs returns a handle on the jobs endpoints.
func (c *Client) Jobs() *Jobs {
	return &Jobs{client: c}
}

// Register is used to register a new job. It returns the ID
// of the evaluation, along with any errors encountered.
func (j *Jobs) Register(job *Job, q *WriteOptions) (string, *WriteMeta, error) {

	var resp registerJobResponse

	req := &RegisterJobRequest{Job: job}
	wm, err := j.client.write("/v1/jobs", req, &resp, q)
	if err != nil {
		return "", nil, err
	}
	return resp.EvalID, wm, nil
}

// EnforceRegister is used to register a job enforcing its job modify index.
func (j *Jobs) EnforceRegister(job *Job, modifyIndex uint64, q *WriteOptions) (string, *WriteMeta, error) {

	var resp registerJobResponse

	req := &RegisterJobRequest{
		Job:            job,
		EnforceIndex:   true,
		JobModifyIndex: modifyIndex,
	}
	wm, err := j.client.write("/v1/jobs", req, &resp, q)
	if err != nil {
		return "", nil, err
	}
	return resp.EvalID, wm, nil
}

// List is used to list all of the existing jobs.
func (j *Jobs) List(q *QueryOptions) ([]*JobListStub, *QueryMeta, error) {
	var resp []*JobListStub
	qm, err := j.client.query("/v1/jobs", &resp, q)
	if err != nil {
		return nil, qm, err
	}
	sort.Sort(JobIDSort(resp))
	return resp, qm, nil
}

// PrefixList is used to list all existing jobs that match the prefix.
func (j *Jobs) PrefixList(prefix string) ([]*JobListStub, *QueryMeta, error) {
	return j.List(&QueryOptions{Prefix: prefix})
}

// Info is used to retrieve information about a particular
// job given its unique ID.
func (j *Jobs) Info(jobID string, q *QueryOptions) (*Job, *QueryMeta, error) {
	var resp Job
	qm, err := j.client.query("/v1/job/"+jobID, &resp, q)
	if err != nil {
		return nil, nil, err
	}
	return &resp, qm, nil
}

// Allocations is used to return the allocs for a given job ID.
func (j *Jobs) Allocations(jobID string, q *QueryOptions) ([]*AllocationListStub, *QueryMeta, error) {
	var resp []*AllocationListStub
	qm, err := j.client.query("/v1/job/"+jobID+"/allocations", &resp, q)
	if err != nil {
		return nil, nil, err
	}
	sort.Sort(AllocIndexSort(resp))
	return resp, qm, nil
}

// Evaluations is used to query the evaluations associated with
// the given job ID.
func (j *Jobs) Evaluations(jobID string, q *QueryOptions) ([]*Evaluation, *QueryMeta, error) {
	var resp []*Evaluation
	qm, err := j.client.query("/v1/job/"+jobID+"/evaluations", &resp, q)
	if err != nil {
		return nil, nil, err
	}
	sort.Sort(EvalIndexSort(resp))
	return resp, qm, nil
}

// Deregister is used to remove an existing job.
func (j *Jobs) Deregister(jobID string, q *WriteOptions) (string, *WriteMeta, error) {
	var resp deregisterJobResponse
	wm, err := j.client.delete("/v1/job/"+jobID, &resp, q)
	if err != nil {
		return "", nil, err
	}
	return resp.EvalID, wm, nil
}

// ForceEvaluate is used to force-evaluate an existing job.
func (j *Jobs) ForceEvaluate(jobID string, q *WriteOptions) (string, *WriteMeta, error) {
	var resp registerJobResponse
	wm, err := j.client.write("/v1/job/"+jobID+"/evaluate", nil, &resp, q)
	if err != nil {
		return "", nil, err
	}
	return resp.EvalID, wm, nil
}

// PeriodicForce spawns a new instance of the periodic job and returns the eval ID
func (j *Jobs) PeriodicForce(jobID string, q *WriteOptions) (string, *WriteMeta, error) {
	var resp periodicForceResponse
	wm, err := j.client.write("/v1/job/"+jobID+"/periodic/force", nil, &resp, q)
	if err != nil {
		return "", nil, err
	}
	return resp.EvalID, wm, nil
}

func (j *Jobs) Plan(job *Job, diff bool, q *WriteOptions) (*JobPlanResponse, *WriteMeta, error) {
	if job == nil {
		return nil, nil, fmt.Errorf("must pass non-nil job")
	}

	var resp JobPlanResponse
	req := &JobPlanRequest{
		Job:  job,
		Diff: diff,
	}
	wm, err := j.client.write("/v1/job/"+job.ID+"/plan", req, &resp, q)
	if err != nil {
		return nil, nil, err
	}

	return &resp, wm, nil
}

func (j *Jobs) Summary(jobID string, q *QueryOptions) (*JobSummary, *QueryMeta, error) {
	var resp JobSummary
	qm, err := j.client.query("/v1/job/"+jobID+"/summary", &resp, q)
	if err != nil {
		return nil, nil, err
	}
	return &resp, qm, nil
}

// periodicForceResponse is used to deserialize a force response
type periodicForceResponse struct {
	EvalID string
}

// UpdateStrategy is for serializing update strategy for a job.
type UpdateStrategy struct {
	Stagger     time.Duration
	MaxParallel int
}

// PeriodicConfig is for serializing periodic config for a job.
type PeriodicConfig struct {
	Enabled         bool
	Spec            string
	SpecType        string
	ProhibitOverlap bool
}

// Job is used to serialize a job.
type Job struct {
	Region            string
	ID                string
	Name              string
	Type              string
	Priority          int
	AllAtOnce         bool
	Datacenters       []string
	Constraints       []*Constraint
	TaskGroups        []*TaskGroup
	Update            *UpdateStrategy
	Periodic          *PeriodicConfig
	Meta              map[string]string
	Status            string
	StatusDescription string
	CreateIndex       uint64
	ModifyIndex       uint64
	JobModifyIndex    uint64
}

// JobSummary summarizes the state of the allocations of a job
type JobSummary struct {
	JobID   string
	Summary map[string]TaskGroupSummary

	// Raft Indexes
	CreateIndex uint64
	ModifyIndex uint64
}

// TaskGroup summarizes the state of all the allocations of a particular
// TaskGroup
type TaskGroupSummary struct {
	Queued   int
	Complete int
	Failed   int
	Running  int
	Starting int
	Lost     int
}

// JobListStub is used to return a subset of information about
// jobs during list operations.
type JobListStub struct {
	ID                string
	ParentID          string
	Name              string
	Type              string
	Priority          int
	Status            string
	StatusDescription string
	JobSummary        *JobSummary
	CreateIndex       uint64
	ModifyIndex       uint64
	JobModifyIndex    uint64
}

// JobIDSort is used to sort jobs by their job ID's.
type JobIDSort []*JobListStub

func (j JobIDSort) Len() int {
	return len(j)
}

func (j JobIDSort) Less(a, b int) bool {
	return j[a].ID < j[b].ID
}

func (j JobIDSort) Swap(a, b int) {
	j[a], j[b] = j[b], j[a]
}

// NewServiceJob creates and returns a new service-style job
// for long-lived processes using the provided name, ID, and
// relative job priority.
func NewServiceJob(id, name, region string, pri int) *Job {
	return newJob(id, name, region, JobTypeService, pri)
}

// NewBatchJob creates and returns a new batch-style job for
// short-lived processes using the provided name and ID along
// with the relative job priority.
func NewBatchJob(id, name, region string, pri int) *Job {
	return newJob(id, name, region, JobTypeBatch, pri)
}

// newJob is used to create a new Job struct.
func newJob(id, name, region, typ string, pri int) *Job {
	return &Job{
		Region:   region,
		ID:       id,
		Name:     name,
		Type:     typ,
		Priority: pri,
	}
}

// SetMeta is used to set arbitrary k/v pairs of metadata on a job.
func (j *Job) SetMeta(key, val string) *Job {
	if j.Meta == nil {
		j.Meta = make(map[string]string)
	}
	j.Meta[key] = val
	return j
}

// AddDatacenter is used to add a datacenter to a job.
func (j *Job) AddDatacenter(dc string) *Job {
	j.Datacenters = append(j.Datacenters, dc)
	return j
}

// Constrain is used to add a constraint to a job.
func (j *Job) Constrain(c *Constraint) *Job {
	j.Constraints = append(j.Constraints, c)
	return j
}

// AddTaskGroup adds a task group to an existing job.
func (j *Job) AddTaskGroup(grp *TaskGroup) *Job {
	j.TaskGroups = append(j.TaskGroups, grp)
	return j
}

// AddPeriodicConfig adds a periodic config to an existing job.
func (j *Job) AddPeriodicConfig(cfg *PeriodicConfig) *Job {
	j.Periodic = cfg
	return j
}

// RegisterJobRequest is used to serialize a job registration
type RegisterJobRequest struct {
	Job            *Job
	EnforceIndex   bool   `json:",omitempty"`
	JobModifyIndex uint64 `json:",omitempty"`
}

// registerJobResponse is used to deserialize a job response
type registerJobResponse struct {
	EvalID string
}

// deregisterJobResponse is used to decode a deregister response
type deregisterJobResponse struct {
	EvalID string
}

type JobPlanRequest struct {
	Job  *Job
	Diff bool
}

type JobPlanResponse struct {
	JobModifyIndex     uint64
	CreatedEvals       []*Evaluation
	Diff               *JobDiff
	Annotations        *PlanAnnotations
	FailedTGAllocs     map[string]*AllocationMetric
	NextPeriodicLaunch time.Time
}

type JobDiff struct {
	Type       string
	ID         string
	Fields     []*FieldDiff
	Objects    []*ObjectDiff
	TaskGroups []*TaskGroupDiff
}

type TaskGroupDiff struct {
	Type    string
	Name    string
	Fields  []*FieldDiff
	Objects []*ObjectDiff
	Tasks   []*TaskDiff
	Updates map[string]uint64
}

type TaskDiff struct {
	Type        string
	Name        string
	Fields      []*FieldDiff
	Objects     []*ObjectDiff
	Annotations []string
}

type FieldDiff struct {
	Type        string
	Name        string
	Old, New    string
	Annotations []string
}

type ObjectDiff struct {
	Type    string
	Name    string
	Fields  []*FieldDiff
	Objects []*ObjectDiff
}

type PlanAnnotations struct {
	DesiredTGUpdates map[string]*DesiredUpdates
}

type DesiredUpdates struct {
	Ignore            uint64
	Place             uint64
	Migrate           uint64
	Stop              uint64
	InPlaceUpdate     uint64
	DestructiveUpdate uint64
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"log"
	"os"
	"testing"
)

func runNakedret(t *testing.T, filename string, maxLength uint, expected string) {
	t.Helper()
	defer func() {
		// Reset logging
		log.SetOutput(os.Stderr)
		log.SetFlags(log.LstdFlags)
	}()
	var logBuf bytes.Buffer
	log.SetOutput(&logBuf)
	log.SetFlags(0)

	if err := checkNakedReturns([]string{filename}, &maxLength); err != nil {
		t.Fatal(err)
	}
	actual := string(logBuf.Bytes())
	if expected != actual {
		t.Errorf("Unexpected output:\n-----\n%s\n-----\n", actual)
	}
}

func TestReturnInBlock(t *testing.T) {
	expected := `testdata/ret-in-block.go:9: Dummy naked returns on 8 line function
`
	runNakedret(t, "testdata/ret-in-block.go", 0, expected)
}

func TestIgnoreShortFunctions(t *testing.T) {
	runNakedret(t, "testdata/ret-in-block.go", 10, "")
}

func TestNestedFunctionLiterals(t *testing.T) {
	expected := `testdata/nested.go:16: Bad naked returns on 6 line function
testdata/nested.go:21: <func():20> naked returns on 2 line function
`
	runNakedret(t, "testdata/nested.go", 0, expected)
}
<commit_msg>whoops, fix unit tests<commit_after>package main

import (
	"bytes"
	"log"
	"os"
	"testing"
)

func runNakedret(t *testing.T, filename string, maxLength uint, expected string) {
	t.Helper()
	defer func() {
		// Reset logging
		log.SetOutput(os.Stderr)
		log.SetFlags(log.LstdFlags)
	}()
	var logBuf bytes.Buffer
	log.SetOutput(&logBuf)
	log.SetFlags(0)

	if err := checkNakedReturns([]string{filename}, &maxLength, false); err != nil {
		t.Fatal(err)
	}
	actual := string(logBuf.Bytes())
	if expected != actual {
		t.Errorf("Unexpected output:\n-----\n%s\n-----\n", actual)
	}
}

func TestReturnInBlock(t *testing.T) {
	expected := `testdata/ret-in-block.go:9: Dummy naked returns on 8 line function
`
	runNakedret(t, "testdata/ret-in-block.go", 0, expected)
}

func TestIgnoreShortFunctions(t *testing.T) {
	runNakedret(t, "testdata/ret-in-block.go", 10, "")
}

func TestNestedFunctionLiterals(t *testing.T) {
	expected := `testdata/nested.go:16: Bad naked returns on 6 line function
testdata/nested.go:21: <func():20> naked returns on 2 line function
`
	runNakedret(t, "testdata/nested.go", 0, expected)
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/gorilla/mux"
)

type TeamsResponse struct {
	Teams   []Team `json:"teams"`
	Message string `json:"message"`
	Error   string `json:"error"`
}

// Fetches every team from the DB and returns them as JSON
func ListTeams(w http.ResponseWriter, r *http.Request) {
	var res TeamsResponse

	t, err := c.GetAllTeams()
	if err != nil {
		res.Error = err.Error()
		errjson, _ := json.Marshal(res)
		http.Error(w, string(errjson), http.StatusInternalServerError)
		return
	}

	for _, v := range t {
		res.Teams = append(res.Teams, *v)
	}

	json.NewEncoder(w).Encode(res)
}

// Fetches a single team from the DB and returns them as JSON
func ShowTeam(w http.ResponseWriter, r *http.Request) {
	var res TeamsResponse

	vars := mux.Vars(r)
	name := vars["team"]

	p, err := c.GetTeam(name)
	if err != nil {
		res.Error = err.Error()
		errjson, _ := json.Marshal(res)
		http.Error(w, string(errjson), http.StatusNotFound)
		return
	}

	res.Teams = append(res.Teams, *p)

	json.NewEncoder(w).Encode(res)
}

// Deletes the specified team from the database
func DeleteTeam(w http.ResponseWriter, r *http.Request) {
	var res PeopleResponse

	vars := mux.Vars(r)
	name := vars["team"]

	err := c.DeleteTeam(name)
	if err != nil {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}

	res.Message = fmt.Sprint("Team ", name, " deleted")

	json.NewEncoder(w).Encode(res)
}

// Creates a new team in the database
func CreateTeam(w http.ResponseWriter, r *http.Request) {
	var res TeamsResponse
	var t Team

	// We're getting the details of this new team from the POSTed JSON
	// so we first need to read in the body of the POST
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1024*10))
	// If something went wrong, return an error in the JSON response
	if err != nil {
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	err = r.Body.Close()
	if err != nil {
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	// Attempt to unmarshall the JSON into our Team struct
	err = json.Unmarshal(body, &t)
	if err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	// If a name was not provided, return an error
	if t.Name == "" {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = "Must provide a team name"
		json.NewEncoder(w).Encode(res)
		return
	}

	// Make sure that this team doesn't already exist
	fp, err := c.GetTeam(t.Name)
	if fp != nil && fp.Name != "" {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = fmt.Sprint("Team ", t.Name, " already exists. Use PUT /teams/", t.Name, " to update.")
		json.NewEncoder(w).Encode(res)
		return
	}
	if err != nil {
		log.Println("GetTeam() failed:", err)
	}

	// Store our new team in the DB
	err = c.StoreTeam(&t)
	if err != nil {
		log.Println("Error storing team:", err)
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	res.Message = fmt.Sprint("Team ", t.Name, " created")

	json.NewEncoder(w).Encode(res)
}

// Updates an existing team in the database
func UpdateTeam(w http.ResponseWriter, r *http.Request) {
	var res TeamsResponse
	var t Team

	vars := mux.Vars(r)
	name := vars["team"]

	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1024*10))
	// If something went wrong, return an error in the JSON response
	if err != nil {
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	err = r.Body.Close()
	if err != nil {
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	err = json.Unmarshal(body, &t)

	if err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	// Make sure the team actually exists before updating
	fp, err := c.GetTeam(name)
	if fp != nil && fp.Name == "" {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = fmt.Sprint("Team ", t.Name, " does not exist. Use POST to create.")
		json.NewEncoder(w).Encode(res)
		return
	}
	if err != nil {
		log.Println("GetTeam() failed for", name)
	}

	// Now that we know our team exists in the DB, copy the name from the URI path and add it to our struct
	t.Name = name

	// Store the updated team in the DB
	err = c.StoreTeam(&t)
	if err != nil {
		log.Println("Error storing team", err)
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	res.Teams = append(res.Teams, t)
	res.Message = fmt.Sprint("Team ", name, " updated")

	json.NewEncoder(w).Encode(res)

}
<commit_msg>Make sure a team exists before attempting to delete it<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/gorilla/mux"
)

type TeamsResponse struct {
	Teams   []Team `json:"teams"`
	Message string `json:"message"`
	Error   string `json:"error"`
}

// Fetches every team from the DB and returns them as JSON
func ListTeams(w http.ResponseWriter, r *http.Request) {
	var res TeamsResponse

	t, err := c.GetAllTeams()
	if err != nil {
		res.Error = err.Error()
		errjson, _ := json.Marshal(res)
		http.Error(w, string(errjson), http.StatusInternalServerError)
		return
	}

	for _, v := range t {
		res.Teams = append(res.Teams, *v)
	}

	json.NewEncoder(w).Encode(res)
}

// Fetches a single team from the DB and returns them as JSON
func ShowTeam(w http.ResponseWriter, r *http.Request) {
	var res TeamsResponse

	vars := mux.Vars(r)
	name := vars["team"]

	p, err := c.GetTeam(name)
	if err != nil {
		res.Error = err.Error()
		errjson, _ := json.Marshal(res)
		http.Error(w, string(errjson), http.StatusNotFound)
		return
	}

	res.Teams = append(res.Teams, *p)

	json.NewEncoder(w).Encode(res)
}

// Deletes the specified team from the database
func DeleteTeam(w http.ResponseWriter, r *http.Request) {
	var res TeamsResponse

	vars := mux.Vars(r)
	name := vars["team"]

	// Make sure the team actually exists before deleting
	t, err := c.GetTeam(name)
	if t == nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = fmt.Sprint("Team ", name, " does not exist and thus cannot be deleted")
		json.NewEncoder(w).Encode(res)
		return
	}
	if err != nil {
		log.Println("GetTeam() failed for", name)
	}

	err = c.DeleteTeam(name)
	if err != nil {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}

	res.Message = fmt.Sprint("Team ", name, " deleted")

	json.NewEncoder(w).Encode(res)
}

// Creates a new team in the database
func CreateTeam(w http.ResponseWriter, r *http.Request) {
	var res TeamsResponse
	var t Team

	// We're getting the details of this new team from the POSTed JSON
	// so we first need to read in the body of the POST
	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1024*10))
	// If something went wrong, return an error in the JSON response
	if err != nil {
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	err = r.Body.Close()
	if err != nil {
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	// Attempt to unmarshall the JSON into our Team struct
	err = json.Unmarshal(body, &t)
	if err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	// If a name was not provided, return an error
	if t.Name == "" {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = "Must provide a team name"
		json.NewEncoder(w).Encode(res)
		return
	}

	// Make sure that this team doesn't already exist
	fp, err := c.GetTeam(t.Name)
	if fp != nil && fp.Name != "" {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = fmt.Sprint("Team ", t.Name, " already exists. Use PUT /teams/", t.Name, " to update.")
		json.NewEncoder(w).Encode(res)
		return
	}
	if err != nil {
		log.Println("GetTeam() failed:", err)
	}

	// Store our new team in the DB
	err = c.StoreTeam(&t)
	if err != nil {
		log.Println("Error storing team:", err)
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	res.Message = fmt.Sprint("Team ", t.Name, " created")

	json.NewEncoder(w).Encode(res)
}

// Updates an existing team in the database
func UpdateTeam(w http.ResponseWriter, r *http.Request) {
	var res TeamsResponse
	var t Team

	vars := mux.Vars(r)
	name := vars["team"]

	body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1024*10))
	// If something went wrong, return an error in the JSON response
	if err != nil {
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	err = r.Body.Close()
	if err != nil {
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	err = json.Unmarshal(body, &t)

	if err != nil {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	// Make sure the team actually exists before updating
	fp, err := c.GetTeam(name)
	if fp != nil && fp.Name == "" {
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = fmt.Sprint("Team ", t.Name, " does not exist. Use POST to create.")
		json.NewEncoder(w).Encode(res)
		return
	}
	if err != nil {
		log.Println("GetTeam() failed for", name)
	}

	// Now that we know our team exists in the DB, copy the name from the URI path and add it to our struct
	t.Name = name

	// Store the updated team in the DB
	err = c.StoreTeam(&t)
	if err != nil {
		log.Println("Error storing team", err)
		w.Header().Set("Content-Type", "application/json; charset=UTF-8")
		w.WriteHeader(422) // unprocessable entity
		res.Error = err.Error()
		json.NewEncoder(w).Encode(res)
		return
	}

	res.Teams = append(res.Teams, t)
	res.Message = fmt.Sprint("Team ", name, " updated")

	json.NewEncoder(w).Encode(res)

}
<|endoftext|>


<commit_before>package mrt

import (
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
	monpb "github.com/CSUNetSec/netsec-protobufs/bgpmon"
	pbcom "github.com/CSUNetSec/netsec-protobufs/common"
	pbbgp "github.com/CSUNetSec/netsec-protobufs/protocol/bgp"
	"github.com/CSUNetSec/protoparse"
	pp "github.com/CSUNetSec/protoparse"
	bgp "github.com/CSUNetSec/protoparse/protocol/bgp"
	rib "github.com/CSUNetSec/protoparse/protocol/rib"
	util "github.com/CSUNetSec/protoparse/util"
	"net"
	"time"
)

const (
	MRT_HEADER_LEN    = 12
	BGP4MP            = 16
	BGP4MP_ET         = 17
	MESSAGE           = 1
	MESSAGE_AS4       = 4
	MESSAGE_LOCAL     = 7
	MESSAGE_AS4_LOCAL = 7
	TABLE_DUMP        = 12
	TABLE_DUMP_V2     = 13
	PEER_INDEX_TABLE  = 1
)

type MrtBufferStack struct {
	MrthBuf   protoparse.PbVal `json:"mrt_header,omitempty"`
	Bgp4mpbuf protoparse.PbVal `json:"bgp4mp_header,omitempty"`
	Bgphbuf   protoparse.PbVal `json:"bgp_header,omitempty"`
	Bgpupbuf  protoparse.PbVal `json:"bgp_update,omitempty"`

	Ribbuf protoparse.PbVal `json:"rib_entry,omitempty"`
}

func (mbs *MrtBufferStack) GetRawMessage() []byte {
	return mbs.MrthBuf.(*mrtHhdrBuf).buf
}

func (mbs *MrtBufferStack) IsRibStack() bool {
	return mbs.Ribbuf != nil
}

func (mbs *MrtBufferStack) GetRawMessage() []byte {
	return mbs.MrthBuf.(*mrtHhdrBuf).buf
}

func MrtToBGPCapture(data []byte) (*monpb.BGPCapture, error) {
	mrth := NewMrtHdrBuf(data)
	bgp4h, errmrt := mrth.Parse()
	if errmrt != nil {
		return nil, fmt.Errorf("Failed parsing MRT header:%s\n", errmrt)
	}
	bgph, errbgph := bgp4h.Parse()
	if errbgph != nil {
		return nil, fmt.Errorf("Failed parsing BGP4MP header:%s\n", errbgph)
	}
	bgpup, errbgpup := bgph.Parse()
	if errbgpup != nil {
		return nil, fmt.Errorf("Failed parsing BGP Header:%s\n", errbgpup)
	}
	_, errup := bgpup.Parse()
	if errup != nil {
		return nil, fmt.Errorf("Failed parsing BGP Update:%s\n", errup)
	}
	capture := new(monpb.BGPCapture)
	bgphpb := bgp4h.(pp.BGP4MPHeaderer).GetHeader()
	mrtpb := mrth.GetHeader()
	capture.Timestamp = mrtpb.Timestamp
	capture.PeerAs = bgphpb.PeerAs
	capture.LocalAs = bgphpb.LocalAs
	capture.InterfaceIndex = bgphpb.InterfaceIndex
	capture.AddressFamily = bgphpb.AddressFamily
	capture.PeerIp = bgphpb.PeerIp
	capture.LocalIp = bgphpb.LocalIp
	capture.Update = bgpup.(pp.BGPUpdater).GetUpdate()
	return capture, nil
}

type mrtHhdrBuf struct {
	dest  *pbbgp.MrtHeader
	buf   []byte
	isrib bool
	index pp.PbVal
}

type bgp4mpHdrBuf struct {
	dest  *pbbgp.BGP4MPHeader
	buf   []byte
	isv6  bool
	isAS4 bool
}

func NewMrtHdrBuf(buf []byte) *mrtHhdrBuf {
	return &mrtHhdrBuf{
		dest:  new(pbbgp.MrtHeader),
		buf:   buf,
		isrib: false,
	}
}

func NewRIBMrtHdrBuf(buf []byte, index pp.PbVal) *mrtHhdrBuf {
	return &mrtHhdrBuf{
		dest:  new(pbbgp.MrtHeader),
		buf:   buf,
		isrib: true,
		index: index,
	}
}

func NewBgp4mpHdrBuf(buf []byte, as4 bool) *bgp4mpHdrBuf {
	return &bgp4mpHdrBuf{
		dest:  new(pbbgp.BGP4MPHeader),
		buf:   buf,
		isAS4: as4,
		isv6:  false,
	}
}

func (m *mrtHhdrBuf) String() string {
	return fmt.Sprintf("Timestamp:%v Type:%d Subtype:%d Len:%d", time.Unix(int64(m.dest.Timestamp), 0).UTC(), m.dest.Type, m.dest.Subtype, m.dest.Len)
}

func (m *bgp4mpHdrBuf) String() string {
	formatstr := "peer_as:%d local_as:%d interface_index:%d address_family:%d peer_ip:%s local_ip:%s"
	return fmt.Sprintf(formatstr, m.dest.PeerAs, m.dest.LocalAs, m.dest.InterfaceIndex, m.dest.AddressFamily, net.IP(util.GetIP(m.dest.PeerIp)), net.IP(util.GetIP(m.dest.LocalIp)))
}

func IsRib(a []byte) (bool, error) {
	if len(a) < MRT_HEADER_LEN {
		return false, errors.New("Not enough bytes in data slice to decode MRT header")
	}
	u16type := binary.BigEndian.Uint16(a[4:6])
	if u16type == uint16(TABLE_DUMP) || u16type == uint16(TABLE_DUMP_V2) {
		return true, nil
	}
	return false, nil
}

func (mhb *mrtHhdrBuf) Parse() (protoparse.PbVal, error) {
	if len(mhb.buf) < MRT_HEADER_LEN {
		return nil, errors.New("Not enough bytes in data slice to decode MRT header")
	}
	mhb.dest.Timestamp = binary.BigEndian.Uint32(mhb.buf[:4])
	u16type := binary.BigEndian.Uint16(mhb.buf[4:6])
	mhb.dest.Type = uint32(u16type)
	u16subtype := binary.BigEndian.Uint16(mhb.buf[6:8])
	mhb.dest.Subtype = uint32(u16subtype)
	mhb.dest.Len = binary.BigEndian.Uint32(mhb.buf[8:12])
	if len(mhb.buf[MRT_HEADER_LEN:]) < int(mhb.dest.Len) {
		return nil, fmt.Errorf("Not enough bytes in data slice for underlying message.len of buf:%d len parsed:%d", len(mhb.buf[MRT_HEADER_LEN:]), mhb.dest.Len)
	}
	switch u16type {
	case uint16(BGP4MP), uint16(BGP4MP_ET):
		if u16subtype == MESSAGE_AS4 || u16subtype == MESSAGE_AS4_LOCAL {
			return NewBgp4mpHdrBuf(mhb.buf[MRT_HEADER_LEN:], true), nil
		}
		if u16subtype == MESSAGE || u16subtype == MESSAGE_LOCAL {
			return NewBgp4mpHdrBuf(mhb.buf[MRT_HEADER_LEN:], false), nil
		}
		return nil, errors.New("unsupported MRT subtype")
	//XXX: when we start to parse deeper we should remove the MRT header
	case uint16(TABLE_DUMP):
		mhb.isrib = true
		return nil, fmt.Errorf("TABLE_DUMP not implemented")
	case uint16(TABLE_DUMP_V2):
		mhb.isrib = true
		isInd := u16subtype == PEER_INDEX_TABLE
		if isInd {
			return rib.NewRibIndexBuf(mhb.buf[MRT_HEADER_LEN:]), nil
		} else {
			return rib.NewRibEntryBuf(mhb.buf[MRT_HEADER_LEN:], int(u16subtype), mhb.index), nil
		}
	}
	return nil, errors.New("unsupported MRT type")
}

func (b4hdrb *bgp4mpHdrBuf) Parse() (protoparse.PbVal, error) {
	if len(b4hdrb.buf) < 20 { //PeerAs + Local As + interface ind + AF + 2*ipv4 addres
		return nil, errors.New("Not enough bytes in data slice to decode BGP4MP hdr")
	}
	if b4hdrb.isAS4 {
		b4hdrb.dest.PeerAs = binary.BigEndian.Uint32(b4hdrb.buf[:4])
		b4hdrb.dest.LocalAs = binary.BigEndian.Uint32(b4hdrb.buf[4:8])
		b4hdrb.buf = b4hdrb.buf[8:]
	} else {
		b4hdrb.dest.PeerAs = uint32(binary.BigEndian.Uint16(b4hdrb.buf[:2]))
		b4hdrb.dest.LocalAs = uint32(binary.BigEndian.Uint16(b4hdrb.buf[2:4]))
		b4hdrb.buf = b4hdrb.buf[4:]
	}
	b4hdrb.dest.InterfaceIndex = uint32(binary.BigEndian.Uint16(b4hdrb.buf[:2]))
	u16af := binary.BigEndian.Uint16(b4hdrb.buf[2:4])
	b4hdrb.dest.AddressFamily = uint32(u16af)
	pip, lip := new(pbcom.IPAddressWrapper), new(pbcom.IPAddressWrapper)
	switch u16af {
	case bgp.AFI_IP:
		pip.Ipv4 = b4hdrb.buf[4:8]
		lip.Ipv4 = b4hdrb.buf[8:12]
		b4hdrb.dest.PeerIp = pip
		b4hdrb.dest.LocalIp = lip
		b4hdrb.buf = b4hdrb.buf[12:]
	case bgp.AFI_IP6:
		b4hdrb.isv6 = true
		pip.Ipv6 = b4hdrb.buf[4:20]
		lip.Ipv6 = b4hdrb.buf[20:36]
		b4hdrb.dest.PeerIp = pip
		b4hdrb.dest.LocalIp = lip
		b4hdrb.buf = b4hdrb.buf[36:]
	default:
		return nil, errors.New("unsupported BGP4MP address family")
	}
	return bgp.NewBgpHeaderBuf(b4hdrb.buf, b4hdrb.isv6, b4hdrb.isAS4), nil
}

func SplitMrt(data []byte, atEOF bool) (advance int, token []byte, err error) {
	dataLen := len(data)
	if atEOF && dataLen == 0 {
		return 0, nil, nil
	}
	if atEOF { //if at EOF return the data
		return dataLen, data, nil
	}

	if cap(data) < MRT_HEADER_LEN { // read more
		return 0, nil, nil
	}
	if dataLen < MRT_HEADER_LEN { //read more
		return 0, nil, nil
	}
	totlen := int(binary.BigEndian.Uint32(data[8:12])) + MRT_HEADER_LEN

	if dataLen < totlen { //need to read more
		return 0, nil, nil
	}
	return totlen, data[0:totlen], nil
}

func (m *mrtHhdrBuf) GetHeader() *pbbgp.MrtHeader {
	return m.dest
}

func (m *bgp4mpHdrBuf) GetHeader() *pbbgp.BGP4MPHeader {
	return m.dest
}

type bgp4mpHeaderWrapper struct {
	*pbbgp.BGP4MPHeader
	PeerIp  net.IP `json:"peer_ip,omitempty"`
	LocalIp net.IP `json:"local_ip,omitempty"`
}

type mrtHeaderWrapper struct {
	*pbbgp.MrtHeader
	Timestamp time.Time `json:"timestamp,omitempty"`
}

func NewMrtHeaderWrapper(m *mrtHhdrBuf) *mrtHeaderWrapper {
	header := m.dest
	return &mrtHeaderWrapper{header, time.Unix(int64(header.Timestamp), 0).UTC()}
}

func (mth *mrtHhdrBuf) MarshalJSON() ([]byte, error) {
	return json.Marshal(NewMrtHeaderWrapper(mth))
}

func NewBGP4MPHeaderWrapper(dest *pbbgp.BGP4MPHeader) *bgp4mpHeaderWrapper {
	peer := net.IP(util.GetIP(dest.PeerIp))
	local := net.IP(util.GetIP(dest.LocalIp))
	return &bgp4mpHeaderWrapper{dest, peer, local}
}

func (m *bgp4mpHdrBuf) MarshalJSON() (data []byte, err error) {
	return json.Marshal(NewBGP4MPHeaderWrapper(m.dest))
}
<commit_msg>Removed duplicate declaration that prevented compiling<commit_after>package mrt

import (
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
	monpb "github.com/CSUNetSec/netsec-protobufs/bgpmon"
	pbcom "github.com/CSUNetSec/netsec-protobufs/common"
	pbbgp "github.com/CSUNetSec/netsec-protobufs/protocol/bgp"
	"github.com/CSUNetSec/protoparse"
	pp "github.com/CSUNetSec/protoparse"
	bgp "github.com/CSUNetSec/protoparse/protocol/bgp"
	rib "github.com/CSUNetSec/protoparse/protocol/rib"
	util "github.com/CSUNetSec/protoparse/util"
	"net"
	"time"
)

const (
	MRT_HEADER_LEN    = 12
	BGP4MP            = 16
	BGP4MP_ET         = 17
	MESSAGE           = 1
	MESSAGE_AS4       = 4
	MESSAGE_LOCAL     = 7
	MESSAGE_AS4_LOCAL = 7
	TABLE_DUMP        = 12
	TABLE_DUMP_V2     = 13
	PEER_INDEX_TABLE  = 1
)

type MrtBufferStack struct {
	MrthBuf   protoparse.PbVal `json:"mrt_header,omitempty"`
	Bgp4mpbuf protoparse.PbVal `json:"bgp4mp_header,omitempty"`
	Bgphbuf   protoparse.PbVal `json:"bgp_header,omitempty"`
	Bgpupbuf  protoparse.PbVal `json:"bgp_update,omitempty"`

	Ribbuf protoparse.PbVal `json:"rib_entry,omitempty"`
}

func (mbs *MrtBufferStack) GetRawMessage() []byte {
	return mbs.MrthBuf.(*mrtHhdrBuf).buf
}

func (mbs *MrtBufferStack) IsRibStack() bool {
	return mbs.Ribbuf != nil
}

func MrtToBGPCapture(data []byte) (*monpb.BGPCapture, error) {
	mrth := NewMrtHdrBuf(data)
	bgp4h, errmrt := mrth.Parse()
	if errmrt != nil {
		return nil, fmt.Errorf("Failed parsing MRT header:%s\n", errmrt)
	}
	bgph, errbgph := bgp4h.Parse()
	if errbgph != nil {
		return nil, fmt.Errorf("Failed parsing BGP4MP header:%s\n", errbgph)
	}
	bgpup, errbgpup := bgph.Parse()
	if errbgpup != nil {
		return nil, fmt.Errorf("Failed parsing BGP Header:%s\n", errbgpup)
	}
	_, errup := bgpup.Parse()
	if errup != nil {
		return nil, fmt.Errorf("Failed parsing BGP Update:%s\n", errup)
	}
	capture := new(monpb.BGPCapture)
	bgphpb := bgp4h.(pp.BGP4MPHeaderer).GetHeader()
	mrtpb := mrth.GetHeader()
	capture.Timestamp = mrtpb.Timestamp
	capture.PeerAs = bgphpb.PeerAs
	capture.LocalAs = bgphpb.LocalAs
	capture.InterfaceIndex = bgphpb.InterfaceIndex
	capture.AddressFamily = bgphpb.AddressFamily
	capture.PeerIp = bgphpb.PeerIp
	capture.LocalIp = bgphpb.LocalIp
	capture.Update = bgpup.(pp.BGPUpdater).GetUpdate()
	return capture, nil
}

type mrtHhdrBuf struct {
	dest  *pbbgp.MrtHeader
	buf   []byte
	isrib bool
	index pp.PbVal
}

type bgp4mpHdrBuf struct {
	dest  *pbbgp.BGP4MPHeader
	buf   []byte
	isv6  bool
	isAS4 bool
}

func NewMrtHdrBuf(buf []byte) *mrtHhdrBuf {
	return &mrtHhdrBuf{
		dest:  new(pbbgp.MrtHeader),
		buf:   buf,
		isrib: false,
	}
}

func NewRIBMrtHdrBuf(buf []byte, index pp.PbVal) *mrtHhdrBuf {
	return &mrtHhdrBuf{
		dest:  new(pbbgp.MrtHeader),
		buf:   buf,
		isrib: true,
		index: index,
	}
}

func NewBgp4mpHdrBuf(buf []byte, as4 bool) *bgp4mpHdrBuf {
	return &bgp4mpHdrBuf{
		dest:  new(pbbgp.BGP4MPHeader),
		buf:   buf,
		isAS4: as4,
		isv6:  false,
	}
}

func (m *mrtHhdrBuf) String() string {
	return fmt.Sprintf("Timestamp:%v Type:%d Subtype:%d Len:%d", time.Unix(int64(m.dest.Timestamp), 0).UTC(), m.dest.Type, m.dest.Subtype, m.dest.Len)
}

func (m *bgp4mpHdrBuf) String() string {
	formatstr := "peer_as:%d local_as:%d interface_index:%d address_family:%d peer_ip:%s local_ip:%s"
	return fmt.Sprintf(formatstr, m.dest.PeerAs, m.dest.LocalAs, m.dest.InterfaceIndex, m.dest.AddressFamily, net.IP(util.GetIP(m.dest.PeerIp)), net.IP(util.GetIP(m.dest.LocalIp)))
}

func IsRib(a []byte) (bool, error) {
	if len(a) < MRT_HEADER_LEN {
		return false, errors.New("Not enough bytes in data slice to decode MRT header")
	}
	u16type := binary.BigEndian.Uint16(a[4:6])
	if u16type == uint16(TABLE_DUMP) || u16type == uint16(TABLE_DUMP_V2) {
		return true, nil
	}
	return false, nil
}

func (mhb *mrtHhdrBuf) Parse() (protoparse.PbVal, error) {
	if len(mhb.buf) < MRT_HEADER_LEN {
		return nil, errors.New("Not enough bytes in data slice to decode MRT header")
	}
	mhb.dest.Timestamp = binary.BigEndian.Uint32(mhb.buf[:4])
	u16type := binary.BigEndian.Uint16(mhb.buf[4:6])
	mhb.dest.Type = uint32(u16type)
	u16subtype := binary.BigEndian.Uint16(mhb.buf[6:8])
	mhb.dest.Subtype = uint32(u16subtype)
	mhb.dest.Len = binary.BigEndian.Uint32(mhb.buf[8:12])
	if len(mhb.buf[MRT_HEADER_LEN:]) < int(mhb.dest.Len) {
		return nil, fmt.Errorf("Not enough bytes in data slice for underlying message.len of buf:%d len parsed:%d", len(mhb.buf[MRT_HEADER_LEN:]), mhb.dest.Len)
	}
	switch u16type {
	case uint16(BGP4MP), uint16(BGP4MP_ET):
		if u16subtype == MESSAGE_AS4 || u16subtype == MESSAGE_AS4_LOCAL {
			return NewBgp4mpHdrBuf(mhb.buf[MRT_HEADER_LEN:], true), nil
		}
		if u16subtype == MESSAGE || u16subtype == MESSAGE_LOCAL {
			return NewBgp4mpHdrBuf(mhb.buf[MRT_HEADER_LEN:], false), nil
		}
		return nil, errors.New("unsupported MRT subtype")
	//XXX: when we start to parse deeper we should remove the MRT header
	case uint16(TABLE_DUMP):
		mhb.isrib = true
		return nil, fmt.Errorf("TABLE_DUMP not implemented")
	case uint16(TABLE_DUMP_V2):
		mhb.isrib = true
		isInd := u16subtype == PEER_INDEX_TABLE
		if isInd {
			return rib.NewRibIndexBuf(mhb.buf[MRT_HEADER_LEN:]), nil
		} else {
			return rib.NewRibEntryBuf(mhb.buf[MRT_HEADER_LEN:], int(u16subtype), mhb.index), nil
		}
	}
	return nil, errors.New("unsupported MRT type")
}

func (b4hdrb *bgp4mpHdrBuf) Parse() (protoparse.PbVal, error) {
	if len(b4hdrb.buf) < 20 { //PeerAs + Local As + interface ind + AF + 2*ipv4 addres
		return nil, errors.New("Not enough bytes in data slice to decode BGP4MP hdr")
	}
	if b4hdrb.isAS4 {
		b4hdrb.dest.PeerAs = binary.BigEndian.Uint32(b4hdrb.buf[:4])
		b4hdrb.dest.LocalAs = binary.BigEndian.Uint32(b4hdrb.buf[4:8])
		b4hdrb.buf = b4hdrb.buf[8:]
	} else {
		b4hdrb.dest.PeerAs = uint32(binary.BigEndian.Uint16(b4hdrb.buf[:2]))
		b4hdrb.dest.LocalAs = uint32(binary.BigEndian.Uint16(b4hdrb.buf[2:4]))
		b4hdrb.buf = b4hdrb.buf[4:]
	}
	b4hdrb.dest.InterfaceIndex = uint32(binary.BigEndian.Uint16(b4hdrb.buf[:2]))
	u16af := binary.BigEndian.Uint16(b4hdrb.buf[2:4])
	b4hdrb.dest.AddressFamily = uint32(u16af)
	pip, lip := new(pbcom.IPAddressWrapper), new(pbcom.IPAddressWrapper)
	switch u16af {
	case bgp.AFI_IP:
		pip.Ipv4 = b4hdrb.buf[4:8]
		lip.Ipv4 = b4hdrb.buf[8:12]
		b4hdrb.dest.PeerIp = pip
		b4hdrb.dest.LocalIp = lip
		b4hdrb.buf = b4hdrb.buf[12:]
	case bgp.AFI_IP6:
		b4hdrb.isv6 = true
		pip.Ipv6 = b4hdrb.buf[4:20]
		lip.Ipv6 = b4hdrb.buf[20:36]
		b4hdrb.dest.PeerIp = pip
		b4hdrb.dest.LocalIp = lip
		b4hdrb.buf = b4hdrb.buf[36:]
	default:
		return nil, errors.New("unsupported BGP4MP address family")
	}
	return bgp.NewBgpHeaderBuf(b4hdrb.buf, b4hdrb.isv6, b4hdrb.isAS4), nil
}

func SplitMrt(data []byte, atEOF bool) (advance int, token []byte, err error) {
	dataLen := len(data)
	if atEOF && dataLen == 0 {
		return 0, nil, nil
	}
	if atEOF { //if at EOF return the data
		return dataLen, data, nil
	}

	if cap(data) < MRT_HEADER_LEN { // read more
		return 0, nil, nil
	}
	if dataLen < MRT_HEADER_LEN { //read more
		return 0, nil, nil
	}
	totlen := int(binary.BigEndian.Uint32(data[8:12])) + MRT_HEADER_LEN

	if dataLen < totlen { //need to read more
		return 0, nil, nil
	}
	return totlen, data[0:totlen], nil
}

func (m *mrtHhdrBuf) GetHeader() *pbbgp.MrtHeader {
	return m.dest
}

func (m *bgp4mpHdrBuf) GetHeader() *pbbgp.BGP4MPHeader {
	return m.dest
}

type bgp4mpHeaderWrapper struct {
	*pbbgp.BGP4MPHeader
	PeerIp  net.IP `json:"peer_ip,omitempty"`
	LocalIp net.IP `json:"local_ip,omitempty"`
}

type mrtHeaderWrapper struct {
	*pbbgp.MrtHeader
	Timestamp time.Time `json:"timestamp,omitempty"`
}

func NewMrtHeaderWrapper(m *mrtHhdrBuf) *mrtHeaderWrapper {
	header := m.dest
	return &mrtHeaderWrapper{header, time.Unix(int64(header.Timestamp), 0).UTC()}
}

func (mth *mrtHhdrBuf) MarshalJSON() ([]byte, error) {
	return json.Marshal(NewMrtHeaderWrapper(mth))
}

func NewBGP4MPHeaderWrapper(dest *pbbgp.BGP4MPHeader) *bgp4mpHeaderWrapper {
	peer := net.IP(util.GetIP(dest.PeerIp))
	local := net.IP(util.GetIP(dest.LocalIp))
	return &bgp4mpHeaderWrapper{dest, peer, local}
}

func (m *bgp4mpHdrBuf) MarshalJSON() (data []byte, err error) {
	return json.Marshal(NewBGP4MPHeaderWrapper(m.dest))
}
<|endoftext|>