<commit_before>package appfiles_test

import (
	"archive/zip"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"

	. "github.com/cloudfoundry/cli/cf/appfiles"
	"github.com/cloudfoundry/gofileutils/fileutils"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

func readFile(file *os.File) []byte {
	bytes, err := ioutil.ReadAll(file)
	Expect(err).NotTo(HaveOccurred())
	return bytes
}

// Thanks to Svett Ralchev
// http://blog.ralch.com/tutorial/golang-working-with-zip/
func zipit(source, target, prefix string) error {
	zipfile, err := os.Create(target)
	if err != nil {
		return err
	}
	defer zipfile.Close()

	if prefix != "" {
		_, err = io.WriteString(zipfile, prefix)
		if err != nil {
			return err
		}
	}

	archive := zip.NewWriter(zipfile)
	defer archive.Close()

	err = filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		header, err := zip.FileInfoHeader(info)
		if err != nil {
			return err
		}

		header.Name = strings.TrimPrefix(path, source)

		if info.IsDir() {
			header.Name += string(os.PathSeparator)
		} else {
			header.Method = zip.Deflate
		}

		writer, err := archive.CreateHeader(header)
		if err != nil {
			return err
		}

		if info.IsDir() {
			return nil
		}

		file, err := os.Open(path)
		if err != nil {
			return err
		}
		defer file.Close()

		_, err = io.Copy(writer, file)
		return err
	})

	return err
}

func readFileInZip(index int, reader *zip.Reader) (string, string) {
	buf := &bytes.Buffer{}
	file := reader.File[index]
	fReader, err := file.Open()
	_, err = io.Copy(buf, fReader)

	Expect(err).NotTo(HaveOccurred())

	return file.Name, string(buf.Bytes())
}

var _ = Describe("Zipper", func() {
	Describe("Zip", func() {
		var zipFile *os.File
		var filesInZip = []string{
			"foo.txt",
			"fooDir/",
			"fooDir/bar/",
			"largeblankfile/",
			"largeblankfile/file.txt",
			"lastDir/",
			"subDir/",
			"subDir/bar.txt",
			"subDir/otherDir/",
			"subDir/otherDir/file.txt",
		}
		var zipper ApplicationZipper

		BeforeEach(func() {
			var err error
			zipFile, err = ioutil.TempFile("", "zip_test")
			Expect(err).NotTo(HaveOccurred())

			zipper = ApplicationZipper{}
		})

		AfterEach(func() {
			zipFile.Close()
			os.Remove(zipFile.Name())
		})

		It("creates a zip with all files and directories from the source directory", func() {
			workingDir, err := os.Getwd()
			Expect(err).NotTo(HaveOccurred())

			dir := filepath.Join(workingDir, "../../fixtures/zip/")
			err = zipper.Zip(dir, zipFile)
			Expect(err).NotTo(HaveOccurred())

			fileStat, err := zipFile.Stat()
			Expect(err).NotTo(HaveOccurred())

			reader, err := zip.NewReader(zipFile, fileStat.Size())
			Expect(err).NotTo(HaveOccurred())

			filenames := []string{}
			for _, file := range reader.File {
				filenames = append(filenames, file.Name)
			}
			Expect(filenames).To(Equal(filesInZip))

			name, contents := readFileInZip(0, reader)
			Expect(name).To(Equal("foo.txt"))
			Expect(contents).To(Equal("This is a simple text file."))
		})

		It("creates a zip with the original file modes", func() {
			if runtime.GOOS == "windows" {
				Skip("This test does not run on Windows")
			}

			workingDir, err := os.Getwd()
			Expect(err).NotTo(HaveOccurred())

			dir := filepath.Join(workingDir, "../../fixtures/zip/")
			err = os.Chmod(filepath.Join(dir, "subDir/bar.txt"), 0666)
			Expect(err).NotTo(HaveOccurred())

			err = zipper.Zip(dir, zipFile)
			Expect(err).NotTo(HaveOccurred())

			fileStat, err := zipFile.Stat()
			Expect(err).NotTo(HaveOccurred())

			reader, err := zip.NewReader(zipFile, fileStat.Size())
			Expect(err).NotTo(HaveOccurred())

			readFileInZip(7, reader)
			Expect(reader.File[7].FileInfo().Mode()).To(Equal(os.FileMode(0666)))
		})

		It("creates a zip with executable file modes", func() {
			if runtime.GOOS != "windows" {
				Skip("This test only runs on Windows")
			}

			workingDir, err := os.Getwd()
			Expect(err).NotTo(HaveOccurred())

			dir := filepath.Join(workingDir, "../../fixtures/zip/")
			err = os.Chmod(filepath.Join(dir, "subDir/bar.txt"), 0666)
			Expect(err).NotTo(HaveOccurred())

			err = zipper.Zip(dir, zipFile)
			Expect(err).NotTo(HaveOccurred())

			fileStat, err := zipFile.Stat()
			Expect(err).NotTo(HaveOccurred())

			reader, err := zip.NewReader(zipFile, fileStat.Size())
			Expect(err).NotTo(HaveOccurred())

			readFileInZip(5, reader)
			Expect(fmt.Sprintf("%o", reader.File[5].FileInfo().Mode())).To(Equal("766"))
		})

		It("is a no-op for a zipfile", func() {
			dir, err := os.Getwd()
			Expect(err).NotTo(HaveOccurred())

			zipper := ApplicationZipper{}
			fixture := filepath.Join(dir, "../../fixtures/applications/example-app.zip")
			err = zipper.Zip(fixture, zipFile)
			Expect(err).NotTo(HaveOccurred())

			zippedFile, err := os.Open(fixture)
			Expect(err).NotTo(HaveOccurred())
			Expect(readFile(zipFile)).To(Equal(readFile(zippedFile)))
		})

		It("compresses the files", func() {
			workingDir, err := os.Getwd()
			Expect(err).NotTo(HaveOccurred())

			dir := filepath.Join(workingDir, "../../fixtures/zip/largeblankfile/")
			fileStat, err := os.Stat(filepath.Join(dir, "file.txt"))
			Expect(err).NotTo(HaveOccurred())
			originalFileSize := fileStat.Size()

			err = zipper.Zip(dir, zipFile)
			Expect(err).NotTo(HaveOccurred())

			fileStat, err = zipFile.Stat()
			Expect(err).NotTo(HaveOccurred())

			compressedFileSize := fileStat.Size()
			Expect(compressedFileSize).To(BeNumerically("<", originalFileSize))
		})

		It("returns an error when zipping fails", func() {
			zipper := ApplicationZipper{}
			err := zipper.Zip("/a/bogus/directory", zipFile)
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("open /a/bogus/directory"))
		})

		It("returns an error when the directory is empty", func() {
			fileutils.TempDir("zip_test", func(emptyDir string, err error) {
				zipper := ApplicationZipper{}
				err = zipper.Zip(emptyDir, zipFile)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(ContainSubstring("is empty"))
			})
		})
	})

	Describe("IsZipFile", func() {
		var (
			inDir, outDir string
			zipper        ApplicationZipper
		)

		AfterEach(func() {
			os.RemoveAll(inDir)
			os.RemoveAll(outDir)
		})

		Context("when given a zip without prefix bytes", func() {
			BeforeEach(func() {
				var err error
				inDir, err = ioutil.TempDir("", "zipper-unzip-in")
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(path.Join(inDir, "file1"), []byte("file-1-contents"), 0664)
				Expect(err).NotTo(HaveOccurred())

				outDir, err = ioutil.TempDir("", "zipper-unzip-out")
				Expect(err).NotTo(HaveOccurred())

				err = zipit(path.Join(inDir, "/"), path.Join(outDir, "out.zip"), "")
				Expect(err).NotTo(HaveOccurred())

				zipper = ApplicationZipper{}
			})

			It("returns true", func() {
				Expect(zipper.IsZipFile(path.Join(outDir, "out.zip"))).To(BeTrue())
			})
		})

		Context("when given a zip with prefix bytes", func() {
			BeforeEach(func() {
				var err error
				inDir, err = ioutil.TempDir("", "zipper-unzip-in")
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(path.Join(inDir, "file1"), []byte("file-1-contents"), 0664)
				Expect(err).NotTo(HaveOccurred())

				outDir, err = ioutil.TempDir("", "zipper-unzip-out")
				Expect(err).NotTo(HaveOccurred())

				err = zipit(path.Join(inDir, "/"), path.Join(outDir, "out.zip"), "prefix-bytes")
				Expect(err).NotTo(HaveOccurred())

				zipper = ApplicationZipper{}
			})

			It("returns true", func() {
				Expect(zipper.IsZipFile(path.Join(outDir, "out.zip"))).To(BeTrue())
			})
		})

		Context("when given a file that is not a zip", func() {
			var fileName string

			BeforeEach(func() {
				f, err := ioutil.TempFile("", "zipper-test")
				Expect(err).NotTo(HaveOccurred())

				fi, err := f.Stat()
				Expect(err).NotTo(HaveOccurred())
				fileName = fi.Name()
			})

			AfterEach(func() {
				defer os.RemoveAll(fileName)
			})

			It("returns false", func() {
				Expect(zipper.IsZipFile(fileName)).To(BeFalse())
			})
		})

		Context("when given a directory", func() {
			var dirName string

			BeforeEach(func() {
				var err error
				dirName, err = ioutil.TempDir("", "zipper-test")
				Expect(err).NotTo(HaveOccurred())
			})

			AfterEach(func() {
				defer os.RemoveAll(dirName)
			})

			It("returns false", func() {
				Expect(zipper.IsZipFile(dirName)).To(BeFalse())
			})
		})
	})

	Describe(".Unzip", func() {
		var (
			inDir, outDir string
			zipper        ApplicationZipper
		)

		AfterEach(func() {
			os.RemoveAll(inDir)
			os.RemoveAll(outDir)
		})

		Context("when the zipfile has prefix bytes", func() {
			BeforeEach(func() {
				var err error
				inDir, err = ioutil.TempDir("", "zipper-unzip-in")
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(path.Join(inDir, "file1"), []byte("file-1-contents"), 0664)
				Expect(err).NotTo(HaveOccurred())

				outDir, err = ioutil.TempDir("", "zipper-unzip-out")
				Expect(err).NotTo(HaveOccurred())

				err = zipit(path.Join(inDir, "/"), path.Join(outDir, "out.zip"), "prefix-bytes")
				Expect(err).NotTo(HaveOccurred())

				zipper = ApplicationZipper{}
			})

			It("successfully extracts the zip", func() {
				destDir, err := ioutil.TempDir("", "dest-dir")
				Expect(err).NotTo(HaveOccurred())

				defer os.RemoveAll(destDir)

				err = zipper.Unzip(path.Join(outDir, "out.zip"), destDir)
				Expect(err).NotTo(HaveOccurred())

				_, err = os.Stat(filepath.Join(destDir, "file1"))
				Expect(err).NotTo(HaveOccurred())
			})
		})

		Context("when the zipfile has an empty directory", func() {
			BeforeEach(func() {
				var err error
				inDir, err = ioutil.TempDir("", "zipper-unzip-in")
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(path.Join(inDir, "file1"), []byte("file-1-contents"), 0664)
				Expect(err).NotTo(HaveOccurred())

				err = os.MkdirAll(path.Join(inDir, "dir1"), os.ModeDir|os.ModePerm)
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(path.Join(inDir, "dir1", "file2"), []byte("file-2-contents"), 0644)
				Expect(err).NotTo(HaveOccurred())

				err = os.MkdirAll(path.Join(inDir, "dir2"), os.ModeDir|os.ModePerm)
				Expect(err).NotTo(HaveOccurred())

				outDir, err = ioutil.TempDir("", "zipper-unzip-out")
				Expect(err).NotTo(HaveOccurred())

				err = zipit(path.Join(inDir, "/"), path.Join(outDir, "out.zip"), "")
				Expect(err).NotTo(HaveOccurred())

				zipper = ApplicationZipper{}
			})

			It("includes all entries from the zip file in the destination", func() {
				destDir, err := ioutil.TempDir("", "dest-dir")
				Expect(err).NotTo(HaveOccurred())

				defer os.RemoveAll(destDir)

				err = zipper.Unzip(path.Join(outDir, "out.zip"), destDir)
				Expect(err).NotTo(HaveOccurred())

				expected := []string{
					"file1",
					"dir1/",
					"dir1/file2",
					"dir2",
				}

				for _, f := range expected {
					_, err := os.Stat(filepath.Join(destDir, f))
					Expect(err).NotTo(HaveOccurred())
				}
			})
		})
	})

	Describe(".GetZipSize", func() {
		var zipper = ApplicationZipper{}

		It("returns the size of the zip file", func() {
			dir, err := os.Getwd()
			Expect(err).NotTo(HaveOccurred())
			zipFile := filepath.Join(dir, "../../fixtures/applications/example-app.zip")

			file, err := os.Open(zipFile)
			Expect(err).NotTo(HaveOccurred())

			fileSize, err := zipper.GetZipSize(file)
			Expect(err).NotTo(HaveOccurred())
			Expect(fileSize).To(Equal(int64(1803)))
		})

		It("returns  an error if the zip file cannot be found", func() {
			tmpFile, _ := os.Open("fooBar")
			_, sizeErr := zipper.GetZipSize(tmpFile)
			Expect(sizeErr).To(HaveOccurred())
		})
	})
})
<commit_msg>fix bug for windows appfiles test<commit_after>package appfiles_test

import (
	"archive/zip"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"

	. "github.com/cloudfoundry/cli/cf/appfiles"
	"github.com/cloudfoundry/gofileutils/fileutils"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

func readFile(file *os.File) []byte {
	bytes, err := ioutil.ReadAll(file)
	Expect(err).NotTo(HaveOccurred())
	return bytes
}

// Thanks to Svett Ralchev
// http://blog.ralch.com/tutorial/golang-working-with-zip/
func zipit(source, target, prefix string) error {
	zipfile, err := os.Create(target)
	if err != nil {
		return err
	}
	defer zipfile.Close()

	if prefix != "" {
		_, err = io.WriteString(zipfile, prefix)
		if err != nil {
			return err
		}
	}

	archive := zip.NewWriter(zipfile)
	defer archive.Close()

	err = filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		header, err := zip.FileInfoHeader(info)
		if err != nil {
			return err
		}

		header.Name = strings.TrimPrefix(path, source)

		if info.IsDir() {
			header.Name += string(os.PathSeparator)
		} else {
			header.Method = zip.Deflate
		}

		writer, err := archive.CreateHeader(header)
		if err != nil {
			return err
		}

		if info.IsDir() {
			return nil
		}

		file, err := os.Open(path)
		if err != nil {
			return err
		}
		defer file.Close()

		_, err = io.Copy(writer, file)
		return err
	})

	return err
}

func readFileInZip(index int, reader *zip.Reader) (string, string) {
	buf := &bytes.Buffer{}
	file := reader.File[index]
	fReader, err := file.Open()
	_, err = io.Copy(buf, fReader)

	Expect(err).NotTo(HaveOccurred())

	return file.Name, string(buf.Bytes())
}

var _ = Describe("Zipper", func() {
	Describe("Zip", func() {
		var zipFile *os.File
		var filesInZip = []string{
			"foo.txt",
			"fooDir/",
			"fooDir/bar/",
			"largeblankfile/",
			"largeblankfile/file.txt",
			"lastDir/",
			"subDir/",
			"subDir/bar.txt",
			"subDir/otherDir/",
			"subDir/otherDir/file.txt",
		}
		var zipper ApplicationZipper

		BeforeEach(func() {
			var err error
			zipFile, err = ioutil.TempFile("", "zip_test")
			Expect(err).NotTo(HaveOccurred())

			zipper = ApplicationZipper{}
		})

		AfterEach(func() {
			zipFile.Close()
			os.Remove(zipFile.Name())
		})

		It("creates a zip with all files and directories from the source directory", func() {
			workingDir, err := os.Getwd()
			Expect(err).NotTo(HaveOccurred())

			dir := filepath.Join(workingDir, "../../fixtures/zip/")
			err = zipper.Zip(dir, zipFile)
			Expect(err).NotTo(HaveOccurred())

			fileStat, err := zipFile.Stat()
			Expect(err).NotTo(HaveOccurred())

			reader, err := zip.NewReader(zipFile, fileStat.Size())
			Expect(err).NotTo(HaveOccurred())

			filenames := []string{}
			for _, file := range reader.File {
				filenames = append(filenames, file.Name)
			}
			Expect(filenames).To(Equal(filesInZip))

			name, contents := readFileInZip(0, reader)
			Expect(name).To(Equal("foo.txt"))
			Expect(contents).To(Equal("This is a simple text file."))
		})

		It("creates a zip with the original file modes", func() {
			if runtime.GOOS == "windows" {
				Skip("This test does not run on Windows")
			}

			workingDir, err := os.Getwd()
			Expect(err).NotTo(HaveOccurred())

			dir := filepath.Join(workingDir, "../../fixtures/zip/")
			err = os.Chmod(filepath.Join(dir, "subDir/bar.txt"), 0666)
			Expect(err).NotTo(HaveOccurred())

			err = zipper.Zip(dir, zipFile)
			Expect(err).NotTo(HaveOccurred())

			fileStat, err := zipFile.Stat()
			Expect(err).NotTo(HaveOccurred())

			reader, err := zip.NewReader(zipFile, fileStat.Size())
			Expect(err).NotTo(HaveOccurred())

			readFileInZip(7, reader)
			Expect(reader.File[7].FileInfo().Mode()).To(Equal(os.FileMode(0666)))
		})

		It("creates a zip with executable file modes", func() {
			if runtime.GOOS != "windows" {
				Skip("This test only runs on Windows")
			}

			workingDir, err := os.Getwd()
			Expect(err).NotTo(HaveOccurred())

			dir := filepath.Join(workingDir, "../../fixtures/zip/")
			err = os.Chmod(filepath.Join(dir, "subDir/bar.txt"), 0666)
			Expect(err).NotTo(HaveOccurred())

			err = zipper.Zip(dir, zipFile)
			Expect(err).NotTo(HaveOccurred())

			fileStat, err := zipFile.Stat()
			Expect(err).NotTo(HaveOccurred())

			reader, err := zip.NewReader(zipFile, fileStat.Size())
			Expect(err).NotTo(HaveOccurred())

			readFileInZip(7, reader)
			Expect(fmt.Sprintf("%o", reader.File[5].FileInfo().Mode())).To(Equal("766"))
		})

		It("is a no-op for a zipfile", func() {
			dir, err := os.Getwd()
			Expect(err).NotTo(HaveOccurred())

			zipper := ApplicationZipper{}
			fixture := filepath.Join(dir, "../../fixtures/applications/example-app.zip")
			err = zipper.Zip(fixture, zipFile)
			Expect(err).NotTo(HaveOccurred())

			zippedFile, err := os.Open(fixture)
			Expect(err).NotTo(HaveOccurred())
			Expect(readFile(zipFile)).To(Equal(readFile(zippedFile)))
		})

		It("compresses the files", func() {
			workingDir, err := os.Getwd()
			Expect(err).NotTo(HaveOccurred())

			dir := filepath.Join(workingDir, "../../fixtures/zip/largeblankfile/")
			fileStat, err := os.Stat(filepath.Join(dir, "file.txt"))
			Expect(err).NotTo(HaveOccurred())
			originalFileSize := fileStat.Size()

			err = zipper.Zip(dir, zipFile)
			Expect(err).NotTo(HaveOccurred())

			fileStat, err = zipFile.Stat()
			Expect(err).NotTo(HaveOccurred())

			compressedFileSize := fileStat.Size()
			Expect(compressedFileSize).To(BeNumerically("<", originalFileSize))
		})

		It("returns an error when zipping fails", func() {
			zipper := ApplicationZipper{}
			err := zipper.Zip("/a/bogus/directory", zipFile)
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(ContainSubstring("open /a/bogus/directory"))
		})

		It("returns an error when the directory is empty", func() {
			fileutils.TempDir("zip_test", func(emptyDir string, err error) {
				zipper := ApplicationZipper{}
				err = zipper.Zip(emptyDir, zipFile)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(ContainSubstring("is empty"))
			})
		})
	})

	Describe("IsZipFile", func() {
		var (
			inDir, outDir string
			zipper        ApplicationZipper
		)

		AfterEach(func() {
			os.RemoveAll(inDir)
			os.RemoveAll(outDir)
		})

		Context("when given a zip without prefix bytes", func() {
			BeforeEach(func() {
				var err error
				inDir, err = ioutil.TempDir("", "zipper-unzip-in")
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(path.Join(inDir, "file1"), []byte("file-1-contents"), 0664)
				Expect(err).NotTo(HaveOccurred())

				outDir, err = ioutil.TempDir("", "zipper-unzip-out")
				Expect(err).NotTo(HaveOccurred())

				err = zipit(path.Join(inDir, "/"), path.Join(outDir, "out.zip"), "")
				Expect(err).NotTo(HaveOccurred())

				zipper = ApplicationZipper{}
			})

			It("returns true", func() {
				Expect(zipper.IsZipFile(path.Join(outDir, "out.zip"))).To(BeTrue())
			})
		})

		Context("when given a zip with prefix bytes", func() {
			BeforeEach(func() {
				var err error
				inDir, err = ioutil.TempDir("", "zipper-unzip-in")
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(path.Join(inDir, "file1"), []byte("file-1-contents"), 0664)
				Expect(err).NotTo(HaveOccurred())

				outDir, err = ioutil.TempDir("", "zipper-unzip-out")
				Expect(err).NotTo(HaveOccurred())

				err = zipit(path.Join(inDir, "/"), path.Join(outDir, "out.zip"), "prefix-bytes")
				Expect(err).NotTo(HaveOccurred())

				zipper = ApplicationZipper{}
			})

			It("returns true", func() {
				Expect(zipper.IsZipFile(path.Join(outDir, "out.zip"))).To(BeTrue())
			})
		})

		Context("when given a file that is not a zip", func() {
			var fileName string

			BeforeEach(func() {
				f, err := ioutil.TempFile("", "zipper-test")
				Expect(err).NotTo(HaveOccurred())

				fi, err := f.Stat()
				Expect(err).NotTo(HaveOccurred())
				fileName = fi.Name()
			})

			AfterEach(func() {
				defer os.RemoveAll(fileName)
			})

			It("returns false", func() {
				Expect(zipper.IsZipFile(fileName)).To(BeFalse())
			})
		})

		Context("when given a directory", func() {
			var dirName string

			BeforeEach(func() {
				var err error
				dirName, err = ioutil.TempDir("", "zipper-test")
				Expect(err).NotTo(HaveOccurred())
			})

			AfterEach(func() {
				defer os.RemoveAll(dirName)
			})

			It("returns false", func() {
				Expect(zipper.IsZipFile(dirName)).To(BeFalse())
			})
		})
	})

	Describe(".Unzip", func() {
		var (
			inDir, outDir string
			zipper        ApplicationZipper
		)

		AfterEach(func() {
			os.RemoveAll(inDir)
			os.RemoveAll(outDir)
		})

		Context("when the zipfile has prefix bytes", func() {
			BeforeEach(func() {
				var err error
				inDir, err = ioutil.TempDir("", "zipper-unzip-in")
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(path.Join(inDir, "file1"), []byte("file-1-contents"), 0664)
				Expect(err).NotTo(HaveOccurred())

				outDir, err = ioutil.TempDir("", "zipper-unzip-out")
				Expect(err).NotTo(HaveOccurred())

				err = zipit(path.Join(inDir, "/"), path.Join(outDir, "out.zip"), "prefix-bytes")
				Expect(err).NotTo(HaveOccurred())

				zipper = ApplicationZipper{}
			})

			It("successfully extracts the zip", func() {
				destDir, err := ioutil.TempDir("", "dest-dir")
				Expect(err).NotTo(HaveOccurred())

				defer os.RemoveAll(destDir)

				err = zipper.Unzip(path.Join(outDir, "out.zip"), destDir)
				Expect(err).NotTo(HaveOccurred())

				_, err = os.Stat(filepath.Join(destDir, "file1"))
				Expect(err).NotTo(HaveOccurred())
			})
		})

		Context("when the zipfile has an empty directory", func() {
			BeforeEach(func() {
				var err error
				inDir, err = ioutil.TempDir("", "zipper-unzip-in")
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(path.Join(inDir, "file1"), []byte("file-1-contents"), 0664)
				Expect(err).NotTo(HaveOccurred())

				err = os.MkdirAll(path.Join(inDir, "dir1"), os.ModeDir|os.ModePerm)
				Expect(err).NotTo(HaveOccurred())

				err = ioutil.WriteFile(path.Join(inDir, "dir1", "file2"), []byte("file-2-contents"), 0644)
				Expect(err).NotTo(HaveOccurred())

				err = os.MkdirAll(path.Join(inDir, "dir2"), os.ModeDir|os.ModePerm)
				Expect(err).NotTo(HaveOccurred())

				outDir, err = ioutil.TempDir("", "zipper-unzip-out")
				Expect(err).NotTo(HaveOccurred())

				err = zipit(path.Join(inDir, "/"), path.Join(outDir, "out.zip"), "")
				Expect(err).NotTo(HaveOccurred())

				zipper = ApplicationZipper{}
			})

			It("includes all entries from the zip file in the destination", func() {
				destDir, err := ioutil.TempDir("", "dest-dir")
				Expect(err).NotTo(HaveOccurred())

				defer os.RemoveAll(destDir)

				err = zipper.Unzip(path.Join(outDir, "out.zip"), destDir)
				Expect(err).NotTo(HaveOccurred())

				expected := []string{
					"file1",
					"dir1/",
					"dir1/file2",
					"dir2",
				}

				for _, f := range expected {
					_, err := os.Stat(filepath.Join(destDir, f))
					Expect(err).NotTo(HaveOccurred())
				}
			})
		})
	})

	Describe(".GetZipSize", func() {
		var zipper = ApplicationZipper{}

		It("returns the size of the zip file", func() {
			dir, err := os.Getwd()
			Expect(err).NotTo(HaveOccurred())
			zipFile := filepath.Join(dir, "../../fixtures/applications/example-app.zip")

			file, err := os.Open(zipFile)
			Expect(err).NotTo(HaveOccurred())

			fileSize, err := zipper.GetZipSize(file)
			Expect(err).NotTo(HaveOccurred())
			Expect(fileSize).To(Equal(int64(1803)))
		})

		It("returns  an error if the zip file cannot be found", func() {
			tmpFile, _ := os.Open("fooBar")
			_, sizeErr := zipper.GetZipSize(tmpFile)
			Expect(sizeErr).To(HaveOccurred())
		})
	})
})
<|endoftext|>


<commit_before>package config

import (
	"encoding/json"
	"io/ioutil"
	"log"
)

// MongoConfig has config values for MongoDB
type MongoConfig string

// RedisConfig has config values for Redis
type RedisConfig struct {
	Addr                string `json:"addr"`
	Pwd                 string `json:"pwd"`
	PendingAlertsKey    string `json:"pendingAlertsKey"`
	ProcessingAlertsKey string `json:"processingAlertsKey"`
}

// Config struct defines the config structure
type Config struct {
	Mongo  MongoConfig `json:"mongo"`
	Redis  RedisConfig `json:"redis"`
	Secret string      `json:"secret"`
}

// NewConfig parses config file and return Config struct
func NewConfig(configPath string) *Config {
	var file []byte
	var err error

	if configPath != "" {
		file, err = ioutil.ReadFile(configPath)

		if err != nil {
			log.Fatalf("Config file '%s' file not found", configPath)
		}
	} else {
		file, err = ioutil.ReadFile("./config.json")

		if err != nil {
			file, err = ioutil.ReadFile("/etc/finch/config.json")

			if err != nil {
				log.Fatalf("Config file is not found")
			}
		}
	}

	config := &Config{}
	err = json.Unmarshal(file, config)

	if err != nil {
		panic(err)
	}

	return config
}
<commit_msg>Add app config<commit_after>package config

import (
	"encoding/json"
	"io/ioutil"
	"log"
)

// MongoConfig has config values for MongoDB
type MongoConfig string

// RedisConfig has config values for Redis
type RedisConfig struct {
	Addr                string `json:"addr"`
	Pwd                 string `json:"pwd"`
	PendingAlertsKey    string `json:"pendingAlertsKey"`
	ProcessingAlertsKey string `json:"processingAlertsKey"`
}

// AppConfig contains app's business logic config values
type AppConfig struct {
	AlertLogLimit int `json:"alertLogLimit"`
}

// Config struct defines the config structure
type Config struct {
	Mongo  MongoConfig `json:"mongo"`
	Redis  RedisConfig `json:"redis"`
	App    AppConfig   `json:"app"`
	Secret string      `json:"secret"`
}

// NewConfig parses config file and return Config struct
func NewConfig(configPath string) *Config {
	var file []byte
	var err error

	if configPath != "" {
		file, err = ioutil.ReadFile(configPath)

		if err != nil {
			log.Fatalf("Config file '%s' file not found", configPath)
		}
	} else {
		file, err = ioutil.ReadFile("./config.json")

		if err != nil {
			file, err = ioutil.ReadFile("/etc/finch/config.json")

			if err != nil {
				log.Fatalf("Config file is not found")
			}
		}
	}

	config := &Config{}
	err = json.Unmarshal(file, config)

	if err != nil {
		panic(err)
	}

	return config
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"strings"
)

const pathToDokugenAnalysis = "../../"
const pathFromDokugenAnalysis = "internal/a-b-tester/"

const pathToWekaTrainer = "../weka-trainer/"
const pathFromWekaTrainer = "../a-b-tester/"

//TODO: amek this resilient to not being run in the package's directory

//TODO: allow the user to specify multiple branches/configs to test, and it reports the best config.

//TODO: allow the user to generate relativedifficulties from scratch, too, which automates the entire pipeline.

type appOptions struct {
	relativeDifficultiesFile string
	solvesFile               string
	analysisFile             string
	branches                 string
	branchesList             []string
	help                     bool
	flagSet                  *flag.FlagSet
}

func (a *appOptions) defineFlags() {
	if a.flagSet == nil {
		return
	}
	a.flagSet.StringVar(&a.branches, "b", "", "Git branch to checkout. Can also be a space delimited list of multiple branches to checkout.")
	a.flagSet.StringVar(&a.relativeDifficultiesFile, "r", "relativedifficulties_SAMPLED.csv", "The file to use as relative difficulties input")
	a.flagSet.StringVar(&a.solvesFile, "s", "solves.csv", "The file to output solves to")
	a.flagSet.StringVar(&a.analysisFile, "a", "analysis.txt", "The file to output analysis to")
	a.flagSet.BoolVar(&a.help, "h", false, "If provided, will print help and exit.")
}

func (a *appOptions) fixUp() {
	a.branchesList = strings.Split(a.branches, " ")
	a.solvesFile = strings.Replace(a.solvesFile, ".csv", "", -1)
	a.analysisFile = strings.Replace(a.analysisFile, ".txt", "", -1)
}

func (a *appOptions) parse(args []string) {
	a.flagSet.Parse(args)
	a.fixUp()
}

func newAppOptions(flagSet *flag.FlagSet) *appOptions {
	a := &appOptions{
		flagSet: flagSet,
	}
	a.defineFlags()
	return a
}

func main() {
	a := newAppOptions(flag.CommandLine)
	a.parse(os.Args[1:])

	for _, branch := range a.branchesList {

		if branch == "" {
			log.Println("Staying on the current branch.")
		} else {
			log.Println("Switching to branch", branch)
		}

		//a.analysisFile and a.solvesFile have had their extension removed, if they had one.
		effectiveSolvesFile := a.solvesFile + ".csv"
		effectiveAnalysisFile := a.analysisFile + ".txt"

		if branch != "" {

			effectiveSolvesFile = a.solvesFile + "_" + strings.ToUpper(branch) + ".csv"
			effectiveAnalysisFile = a.analysisFile + "_" + strings.ToUpper(branch) + ".txt"
		}

		if !checkoutGitBranch(branch) {
			log.Println("Couldn't switch to branch", branch, " (perhaps you have uncommitted changes?). Quitting.")
			return
		}

		//TODO: support sampling from relative_difficulties via command line option here.

		runSolves(a.relativeDifficultiesFile, effectiveSolvesFile)

		runWeka(effectiveSolvesFile, effectiveAnalysisFile)

		//TODO: understand r2 so we can compare and find the best branch.
	}

	//TODO: print out remembered r2 here, bolding the one that is best.

	//TODO: should we be cleaning up the files we output (perhaps only if option provided?0)
}

func runSolves(difficultiesFile, solvesOutputFile string) {

	os.Chdir(pathToDokugenAnalysis)

	defer func() {
		os.Chdir(pathFromDokugenAnalysis)
	}()

	//Build the dokugen-analysis executable to make sure we get the freshest version of the sudoku pacakge.
	cmd := exec.Command("go", "build")
	err := cmd.Run()

	if err != nil {
		log.Println(err)
		return
	}

	outFile, err := os.Create(path.Join(pathFromDokugenAnalysis, solvesOutputFile))

	if err != nil {
		log.Println(err)
		return
	}

	analysisCmd := exec.Command("./dokugen-analysis", "-a", "-v", "-w", "-t", "-h", "-no-cache", path.Join(pathFromDokugenAnalysis, difficultiesFile))
	analysisCmd.Stdout = outFile
	analysisCmd.Stderr = os.Stderr
	err = analysisCmd.Run()

	if err != nil {
		log.Println(err)
	}
}

func runWeka(solvesFile string, analysisFile string) {

	os.Chdir(pathToWekaTrainer)

	defer func() {
		os.Chdir(pathFromWekaTrainer)
	}()

	//Build the weka-trainer executable to make sure we get the freshest version of the sudoku pacakge.
	cmd := exec.Command("go", "build")
	err := cmd.Run()

	if err != nil {
		log.Println(err)
		return
	}

	trainCmd := exec.Command("./weka-trainer", "-i", path.Join(pathFromWekaTrainer, solvesFile), "-o", path.Join(pathFromWekaTrainer, analysisFile))
	trainCmd.Stderr = os.Stderr
	output, err := trainCmd.Output()

	if err != nil {
		log.Println(err)
		return
	}

	fmt.Printf("%s", string(output))

}

//gitCurrentBranch returns the current branch that the current repo is in.
func gitCurrentBranch() string {
	branchCmd := exec.Command("git", "branch")

	output, err := branchCmd.Output()

	if err != nil {
		log.Println(err)
		return ""
	}

	for _, line := range strings.Split(string(output), "\n") {
		if strings.Contains(line, "*") {
			//Found it!
			line = strings.Replace(line, "*", "", -1)
			line = strings.TrimSpace(line)
			return line
		}
	}

	return ""
}

func checkoutGitBranch(branch string) bool {

	if branch == "" {
		return true
	}

	checkoutCmd := exec.Command("git", "checkout", branch)
	checkoutCmd.Run()

	if gitCurrentBranch() != branch {
		return false
	}

	return true

}
<commit_msg>Print out results table at the end (left a number of TODOs). Discovered that extract R2 not working.<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"strconv"
	"strings"
)

const pathToDokugenAnalysis = "../../"
const pathFromDokugenAnalysis = "internal/a-b-tester/"

const pathToWekaTrainer = "../weka-trainer/"
const pathFromWekaTrainer = "../a-b-tester/"

//TODO: amek this resilient to not being run in the package's directory

//TODO: allow the user to specify multiple branches/configs to test, and it reports the best config.

//TODO: allow the user to generate relativedifficulties from scratch, too, which automates the entire pipeline.

type appOptions struct {
	relativeDifficultiesFile string
	solvesFile               string
	analysisFile             string
	branches                 string
	branchesList             []string
	help                     bool
	flagSet                  *flag.FlagSet
}

func (a *appOptions) defineFlags() {
	if a.flagSet == nil {
		return
	}
	a.flagSet.StringVar(&a.branches, "b", "", "Git branch to checkout. Can also be a space delimited list of multiple branches to checkout.")
	a.flagSet.StringVar(&a.relativeDifficultiesFile, "r", "relativedifficulties_SAMPLED.csv", "The file to use as relative difficulties input")
	a.flagSet.StringVar(&a.solvesFile, "s", "solves.csv", "The file to output solves to")
	a.flagSet.StringVar(&a.analysisFile, "a", "analysis.txt", "The file to output analysis to")
	a.flagSet.BoolVar(&a.help, "h", false, "If provided, will print help and exit.")
}

func (a *appOptions) fixUp() {
	a.branchesList = strings.Split(a.branches, " ")
	a.solvesFile = strings.Replace(a.solvesFile, ".csv", "", -1)
	a.analysisFile = strings.Replace(a.analysisFile, ".txt", "", -1)
}

func (a *appOptions) parse(args []string) {
	a.flagSet.Parse(args)
	a.fixUp()
}

func newAppOptions(flagSet *flag.FlagSet) *appOptions {
	a := &appOptions{
		flagSet: flagSet,
	}
	a.defineFlags()
	return a
}

func main() {
	a := newAppOptions(flag.CommandLine)
	a.parse(os.Args[1:])

	results := make(map[string]float64)

	for _, branch := range a.branchesList {

		if branch == "" {
			log.Println("Staying on the current branch.")
		} else {
			log.Println("Switching to branch", branch)
		}

		//a.analysisFile and a.solvesFile have had their extension removed, if they had one.
		effectiveSolvesFile := a.solvesFile + ".csv"
		effectiveAnalysisFile := a.analysisFile + ".txt"

		if branch != "" {

			effectiveSolvesFile = a.solvesFile + "_" + strings.ToUpper(branch) + ".csv"
			effectiveAnalysisFile = a.analysisFile + "_" + strings.ToUpper(branch) + ".txt"
		}

		if !checkoutGitBranch(branch) {
			log.Println("Couldn't switch to branch", branch, " (perhaps you have uncommitted changes?). Quitting.")
			return
		}

		//TODO: support sampling from relative_difficulties via command line option here.

		runSolves(a.relativeDifficultiesFile, effectiveSolvesFile)

		branchKey := branch

		if branchKey == "" {
			branchKey = "DEFAULT"
		}

		results[branchKey] = runWeka(effectiveSolvesFile, effectiveAnalysisFile)
	}

	fmt.Println("Results:")
	for key, val := range results {
		//TODO: pretty print in a table
		fmt.Println(key, "=", val)
	}

	//TODO: highlight the branch with highest r2

	//TODO: should we be cleaning up the files we output (perhaps only if option provided?0)

	//TODO: switch back to the branch we started on.
}

func runSolves(difficultiesFile, solvesOutputFile string) {

	os.Chdir(pathToDokugenAnalysis)

	defer func() {
		os.Chdir(pathFromDokugenAnalysis)
	}()

	//Build the dokugen-analysis executable to make sure we get the freshest version of the sudoku pacakge.
	cmd := exec.Command("go", "build")
	err := cmd.Run()

	if err != nil {
		log.Println(err)
		return
	}

	outFile, err := os.Create(path.Join(pathFromDokugenAnalysis, solvesOutputFile))

	if err != nil {
		log.Println(err)
		return
	}

	analysisCmd := exec.Command("./dokugen-analysis", "-a", "-v", "-w", "-t", "-h", "-no-cache", path.Join(pathFromDokugenAnalysis, difficultiesFile))
	analysisCmd.Stdout = outFile
	analysisCmd.Stderr = os.Stderr
	err = analysisCmd.Run()

	if err != nil {
		log.Println(err)
	}
}

func runWeka(solvesFile string, analysisFile string) float64 {

	os.Chdir(pathToWekaTrainer)

	defer func() {
		os.Chdir(pathFromWekaTrainer)
	}()

	//Build the weka-trainer executable to make sure we get the freshest version of the sudoku pacakge.
	cmd := exec.Command("go", "build")
	err := cmd.Run()

	if err != nil {
		log.Println(err)
		return 0.0
	}

	trainCmd := exec.Command("./weka-trainer", "-i", path.Join(pathFromWekaTrainer, solvesFile), "-o", path.Join(pathFromWekaTrainer, analysisFile))
	trainCmd.Stderr = os.Stderr
	output, err := trainCmd.Output()

	if err != nil {
		log.Println(err)
		return 0.0
	}

	fmt.Printf("%s", string(output))

	return extractR2(string(output))

}

//extractR2 extracts R2 out of the string formatted like "R2 = <float>"
func extractR2(input string) float64 {

	input = strings.TrimPrefix(input, "R2 = ")

	result, _ := strconv.ParseFloat(input, 64)

	return result

}

//gitCurrentBranch returns the current branch that the current repo is in.
func gitCurrentBranch() string {
	branchCmd := exec.Command("git", "branch")

	output, err := branchCmd.Output()

	if err != nil {
		log.Println(err)
		return ""
	}

	for _, line := range strings.Split(string(output), "\n") {
		if strings.Contains(line, "*") {
			//Found it!
			line = strings.Replace(line, "*", "", -1)
			line = strings.TrimSpace(line)
			return line
		}
	}

	return ""
}

func checkoutGitBranch(branch string) bool {

	if branch == "" {
		return true
	}

	checkoutCmd := exec.Command("git", "checkout", branch)
	checkoutCmd.Run()

	if gitCurrentBranch() != branch {
		return false
	}

	return true

}
<|endoftext|>


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

package testing

import (
	"time"

	"github.com/juju/juju/state/backups/metadata"
)

const (
	// ID is the backups ID used by the metadata helper functions.
	ID = "49db53ac-a42f-4ab2-86e1-0c6fa0fec762.20140924-010319"
	// EnvID is the env ID used by metadata helper functions.
	EnvID = "49db53ac-a42f-4ab2-86e1-0c6fa0fec762"
	// Machine is the machine ID used by metadata helper functions.
	Machine = "0"
	// Hostname is the hostname used by metadata helper functions.
	Hostname = "main-host"
	// Notes is the notes value used by metadata helper functions.
	Notes = ""
	// Size is the size used by metadata helper functions.
	Size = 10
	// Checksum is the checksum used by metadata helper functions.
	Checksum = "787b8915389d921fa23fb40e16ae81ea979758bf"
	// CsFormat is the checksum format used by metadata helper functions.
	CsFormat = metadata.ChecksumFormat
)

// NewMetadata returns a Metadata to use for testing.
func NewMetadata() *metadata.Metadata {
	meta := NewMetadataStarted(ID, Notes)
	FinishMetadata(meta)
	meta.SetStored()
	return meta
}

// NewMetadataStarted returns a Metadata to use for testing.
func NewMetadataStarted(id, notes string) *metadata.Metadata {
	origin := metadata.NewOrigin(EnvID, Machine, Hostname)
	started := time.Now().UTC()

	meta := metadata.NewMetadata(*origin, notes, &started)
	meta.SetID(id)
	return meta
}

// FinishMetadata finishes a metadata with test values.
func FinishMetadata(meta *metadata.Metadata) {
	finished := meta.Started().Add(time.Minute)
	meta.Finish(Size, Checksum, CsFormat, &finished)
}

// UpdateNotes derives a new Metadata with new notes.
func UpdateNotes(meta *metadata.Metadata, notes string) *metadata.Metadata {
	started := meta.Started()
	newMeta := metadata.NewMetadata(meta.Origin(), notes, &started)
	newMeta.SetID(meta.ID())
	newMeta.Finish(meta.Size(), meta.Checksum(), meta.ChecksumFormat(), meta.Finished())
	if meta.Stored() {
		newMeta.SetStored()
	}
	return newMeta
}
<commit_msg>Get rid of unnecessary constants.<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package testing

import (
	"time"

	"github.com/juju/juju/state/backups/metadata"
)

const (
	envID = "49db53ac-a42f-4ab2-86e1-0c6fa0fec762"
)

// NewMetadata returns a Metadata to use for testing.
func NewMetadata() *metadata.Metadata {
	timestamp := "20140924-010319"
	id := envID + "." + timestamp
	notes := ""
	meta := NewMetadataStarted(id, notes)

	FinishMetadata(meta)
	meta.SetStored()
	return meta
}

// NewMetadataStarted returns a Metadata to use for testing.
func NewMetadataStarted(id, notes string) *metadata.Metadata {
	machine := "0"
	hostname := "main-host"
	origin := metadata.NewOrigin(envID, machine, hostname)
	started := time.Now().UTC()

	meta := metadata.NewMetadata(*origin, notes, &started)
	meta.SetID(id)
	return meta
}

// FinishMetadata finishes a metadata with test values.
func FinishMetadata(meta *metadata.Metadata) {
	var size int64 = 10
	checksum := "787b8915389d921fa23fb40e16ae81ea979758bf"
	finished := meta.Started().Add(time.Minute)
	meta.Finish(size, checksum, metadata.ChecksumFormat, &finished)
}

// UpdateNotes derives a new Metadata with new notes.
func UpdateNotes(meta *metadata.Metadata, notes string) *metadata.Metadata {
	started := meta.Started()
	newMeta := metadata.NewMetadata(meta.Origin(), notes, &started)
	newMeta.SetID(meta.ID())
	newMeta.Finish(meta.Size(), meta.Checksum(), meta.ChecksumFormat(), meta.Finished())
	if meta.Stored() {
		newMeta.SetStored()
	}
	return newMeta
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/pelletier/go-toml"
	//"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"strings"
	"text/template"
)

type config struct {
	emails      []string
	mailBinPath string
	ikachanUrl  string
	channel     string
}

type consulAlert struct {
	Timestamp string
	Node      string
	ServiceId string
	Service   string
	CheckId   string
	Check     string
	Status    string
	Output    string
	Notes     string
}

func (c *consulAlert) TrimmedOutput() string {
	return strings.TrimSpace(c.Output)
}

func (c *consulAlert) StatusString() string {
	status := strings.ToUpper(c.Status)
	switch c.Status {
	case "passing":
		return colorMsg(status, cGreen, cNone)
	case "critical":
		return colorMsg(status, cBlack, cRed)
	default:
		return colorMsg(status, cYellow, cNone)
	}
}

func (c *consulAlert) NodeString() string {
	return setIrcMode(ircUnderline) + c.Node + setIrcMode(ircCReset)
}

const (
	version = "0.0.1"
)

var (
	ircBodyTemplate = setIrcMode(ircBold) +
		"{{.Service}}({{.CheckId}}) is now {{.StatusString}}" +
		setIrcMode(ircBold) +
		" on {{.NodeString}}" +
		" - {{.TrimmedOutput}}"

	mailTitleTemplate = "Check {{.CheckId}} is now {{.Status}} on {{.Node}}"
	mailBodyTemplate  = `
{{.Service}}({{.CheckId}}) is now {{.Status}}
On node {{.Node}}

Output is:
  {{.TrimmedOutput}}
`

	logger = log.New(os.Stdout, "[consul-simple-notifier] ", log.LstdFlags)
)

func main() {
	var (
		justShowVersion bool
		configPath      string
		conf            config
		input           []consulAlert
	)

	flag.BoolVar(&justShowVersion, "v", false, "Show version")
	flag.BoolVar(&justShowVersion, "version", false, "Show version")

	flag.StringVar(&configPath, "c", "/etc/consul-simple-notifier.ini", "Config path")
	flag.Parse()

	if justShowVersion {
		showVersion()
		return
	}

	parsed, err := toml.LoadFile(configPath)
	if err != nil {
		panic(err.Error())
	}

	binPath := parsed.Get("email.binpath")
	if binPath == nil {
		conf.mailBinPath = "/bin/mail"
	} else {
		conf.mailBinPath = binPath.(string)
	}

	recipients := parsed.Get("email.recipients")
	for _, address := range recipients.([]interface{}) {
		conf.emails = append(conf.emails, address.(string))
	}

	conf.ikachanUrl = parsed.Get("ikachan.url").(string)
	conf.channel = parsed.Get("ikachan.channel").(string)
	logger.Printf("conf is: %+v\n", conf)

	err = json.NewDecoder(os.Stdin).Decode(&input)
	if err != nil {
		panic(err.Error())
	}
	logger.Printf("input json is: %+v\n", input)

	for _, content := range input {
		err := notifyEmail(conf.mailBinPath, conf.emails, content)
		if err != nil {
			panic(err)
		}
		err = notifyIkachan(conf.ikachanUrl, conf.channel, content)
		if err != nil {
			panic(err)
		}
	}
}

func notifyEmail(mainBinPath string, recipients []string, content consulAlert) error {
	for _, address := range recipients {
		var titleBuf, bodyBuf bytes.Buffer
		titleTmpl := template.Must(template.New("emailTitle").Parse(mailTitleTemplate))
		bodyTmpl := template.Must(template.New("emailBody").Parse(mailBodyTemplate))
		err := titleTmpl.Execute(&titleBuf, &content)
		err = bodyTmpl.Execute(&bodyBuf, &content)
		if err != nil {
			return err
		}
		title := titleBuf.String()

		logger.Printf("Sending... %s to %s\n", title, address)
		cmd := exec.Command(mainBinPath, "-s", title, address)
		stdin, err := cmd.StdinPipe()
		if err != nil {
			return err
		}

		if err := cmd.Start(); err != nil {
			return err
		}

		fmt.Fprint(stdin, bodyBuf.String())
		stdin.Close()
		logger.Printf("Send!\n")
		cmd.Wait()
	}
	return nil
}

func notifyIkachan(ikachanUrl string, channel string, content consulAlert) error {
	joinUrl := fmt.Sprintf("%s/join", ikachanUrl)
	noticeUrl := fmt.Sprintf("%s/notice", ikachanUrl)

	values := make(url.Values)
	values.Set("channel", channel)

	resp1, err := http.PostForm(joinUrl, values)
	if err != nil {
		return err
	}
	defer resp1.Body.Close()

	var bodyBuf bytes.Buffer
	bodyTmpl := template.Must(template.New("ircBody").Parse(ircBodyTemplate))
	err = bodyTmpl.Execute(&bodyBuf, &content)
	if err != nil {
		return err
	}
	body := bodyBuf.String()

	values.Set("message", body)

	logger.Printf("Posted! %+v", values)
	resp2, err := http.PostForm(noticeUrl, values)
	if err != nil {
		return err
	}
	defer resp2.Body.Close()

	return nil
}

func showVersion() {
	fmt.Printf("consul-simple-notifier version: %s\n", version)
}
<commit_msg>Small change of message<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/pelletier/go-toml"
	//"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"strings"
	"text/template"
)

type config struct {
	emails      []string
	mailBinPath string
	ikachanUrl  string
	channel     string
}

type consulAlert struct {
	Timestamp string
	Node      string
	ServiceId string
	Service   string
	CheckId   string
	Check     string
	Status    string
	Output    string
	Notes     string
}

func (c *consulAlert) TrimmedOutput() string {
	return strings.TrimSpace(c.Output)
}

func (c *consulAlert) StatusString() string {
	status := strings.ToUpper(c.Status)
	switch c.Status {
	case "passing":
		return colorMsg(status, cGreen, cNone)
	case "critical":
		return colorMsg(status, cBlack, cRed)
	default:
		return colorMsg(status, cYellow, cNone)
	}
}

func (c *consulAlert) NodeString() string {
	return setIrcMode(ircUnderline) + c.Node + setIrcMode(ircCReset)
}

const (
	version = "0.0.1"
)

var (
	ircBodyTemplate = setIrcMode(ircBold) +
		"*** {{.Service}}({{.CheckId}}) is now {{.StatusString}}" +
		setIrcMode(ircBold) +
		" on {{.NodeString}}" +
		" - {{.TrimmedOutput}}"

	mailTitleTemplate = "Check {{.CheckId}} is now {{.Status}} on {{.Node}}"
	mailBodyTemplate  = `
{{.Service}}({{.CheckId}}) is now {{.Status}}
On node {{.Node}}

Output is:
  {{.TrimmedOutput}}
`

	logger = log.New(os.Stdout, "[consul-simple-notifier] ", log.LstdFlags)
)

func main() {
	var (
		justShowVersion bool
		configPath      string
		conf            config
		input           []consulAlert
	)

	flag.BoolVar(&justShowVersion, "v", false, "Show version")
	flag.BoolVar(&justShowVersion, "version", false, "Show version")

	flag.StringVar(&configPath, "c", "/etc/consul-simple-notifier.ini", "Config path")
	flag.Parse()

	if justShowVersion {
		showVersion()
		return
	}

	parsed, err := toml.LoadFile(configPath)
	if err != nil {
		panic(err.Error())
	}

	binPath := parsed.Get("email.binpath")
	if binPath == nil {
		conf.mailBinPath = "/bin/mail"
	} else {
		conf.mailBinPath = binPath.(string)
	}

	recipients := parsed.Get("email.recipients")
	for _, address := range recipients.([]interface{}) {
		conf.emails = append(conf.emails, address.(string))
	}

	conf.ikachanUrl = parsed.Get("ikachan.url").(string)
	conf.channel = parsed.Get("ikachan.channel").(string)
	logger.Printf("conf is: %+v\n", conf)

	err = json.NewDecoder(os.Stdin).Decode(&input)
	if err != nil {
		panic(err.Error())
	}
	logger.Printf("input json is: %+v\n", input)

	for _, content := range input {
		err := notifyEmail(conf.mailBinPath, conf.emails, content)
		if err != nil {
			panic(err)
		}
		err = notifyIkachan(conf.ikachanUrl, conf.channel, content)
		if err != nil {
			panic(err)
		}
	}
}

func notifyEmail(mainBinPath string, recipients []string, content consulAlert) error {
	for _, address := range recipients {
		var titleBuf, bodyBuf bytes.Buffer
		titleTmpl := template.Must(template.New("emailTitle").Parse(mailTitleTemplate))
		bodyTmpl := template.Must(template.New("emailBody").Parse(mailBodyTemplate))
		err := titleTmpl.Execute(&titleBuf, &content)
		err = bodyTmpl.Execute(&bodyBuf, &content)
		if err != nil {
			return err
		}
		title := titleBuf.String()

		logger.Printf("Sending... %s to %s\n", title, address)
		cmd := exec.Command(mainBinPath, "-s", title, address)
		stdin, err := cmd.StdinPipe()
		if err != nil {
			return err
		}

		if err := cmd.Start(); err != nil {
			return err
		}

		fmt.Fprint(stdin, bodyBuf.String())
		stdin.Close()
		logger.Printf("Send!\n")
		cmd.Wait()
	}
	return nil
}

func notifyIkachan(ikachanUrl string, channel string, content consulAlert) error {
	joinUrl := fmt.Sprintf("%s/join", ikachanUrl)
	noticeUrl := fmt.Sprintf("%s/notice", ikachanUrl)

	values := make(url.Values)
	values.Set("channel", channel)

	resp1, err := http.PostForm(joinUrl, values)
	if err != nil {
		return err
	}
	defer resp1.Body.Close()

	var bodyBuf bytes.Buffer
	bodyTmpl := template.Must(template.New("ircBody").Parse(ircBodyTemplate))
	err = bodyTmpl.Execute(&bodyBuf, &content)
	if err != nil {
		return err
	}
	body := bodyBuf.String()

	values.Set("message", body)

	logger.Printf("Posted! %+v", values)
	resp2, err := http.PostForm(noticeUrl, values)
	if err != nil {
		return err
	}
	defer resp2.Body.Close()

	return nil
}

func showVersion() {
	fmt.Printf("consul-simple-notifier version: %s\n", version)
}
<|endoftext|>


<commit_before>// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package boltdb

import (
	"os"
	"path"

	"github.com/boltdb/bolt"
	"github.com/juju/errors"
	"github.com/pingcap/tidb/store/localstore/engine"
	"github.com/pingcap/tidb/util/bytes"
)

var (
	_ engine.DB = (*db)(nil)
)

var (
	bucketName = []byte("tidb")
)

type db struct {
	*bolt.DB
}

func (d *db) Get(key []byte) ([]byte, error) {
	var value []byte

	err := d.DB.View(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketName)
		v := b.Get(key)
		if v == nil {
			return errors.Trace(engine.ErrNotFound)
		}
		value = bytes.CloneBytes(v)
		return nil
	})

	return value, errors.Trace(err)
}

func (d *db) MultiSeek(keys [][]byte) []*engine.MSeekResult {
	res := make([]*engine.MSeekResult, 0, len(keys))
	d.DB.View(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketName)
		c := b.Cursor()
		for _, key := range keys {
			var k, v []byte
			if key == nil {
				k, v = c.First()
			} else {
				k, v = c.Seek(key)
			}

			r := &engine.MSeekResult{}
			r.Key, r.Value, r.Err = bytes.CloneBytes(k), bytes.CloneBytes(v), nil
			if k == nil {
				r.Err = engine.ErrNotFound
			}
			res = append(res, r)
		}
		return nil
	})

	return res
}

func (d *db) Seek(startKey []byte) ([]byte, []byte, error) {
	var key, value []byte
	err := d.DB.View(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketName)
		c := b.Cursor()
		var k, v []byte
		if startKey == nil {
			k, v = c.First()
		} else {
			k, v = c.Seek(startKey)
		}
		if k != nil {
			key, value = bytes.CloneBytes(k), bytes.CloneBytes(v)
		}
		return nil
	})

	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	if key == nil {
		return nil, nil, errors.Trace(engine.ErrNotFound)
	}
	return key, value, nil
}

func (d *db) NewBatch() engine.Batch {
	return &batch{}
}

func (d *db) Commit(b engine.Batch) error {
	bt, ok := b.(*batch)
	if !ok {
		return errors.Errorf("invalid batch type %T", b)
	}
	err := d.DB.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketName)
		// err1 is used for passing `go tool vet --shadow` check.
		var err1 error
		for _, w := range bt.writes {
			if !w.isDelete {
				err1 = b.Put(w.key, w.value)
			} else {
				err1 = b.Delete(w.key)
			}

			if err1 != nil {
				return errors.Trace(err1)
			}
		}

		return nil
	})
	return errors.Trace(err)
}

func (d *db) Close() error {
	return d.DB.Close()
}

type write struct {
	key      []byte
	value    []byte
	isDelete bool
}

type batch struct {
	writes []write
}

func (b *batch) Put(key []byte, value []byte) {
	w := write{
		key:   append([]byte(nil), key...),
		value: append([]byte(nil), value...),
	}
	b.writes = append(b.writes, w)
}

func (b *batch) Delete(key []byte) {
	w := write{
		key:      append([]byte(nil), key...),
		value:    nil,
		isDelete: true,
	}
	b.writes = append(b.writes, w)
}

func (b *batch) Len() int {
	return len(b.writes)
}

// Driver implements engine Driver.
type Driver struct {
}

// Open opens or creates a local storage database with given path.
func (driver Driver) Open(dbPath string) (engine.DB, error) {
	base := path.Dir(dbPath)
	os.MkdirAll(base, 0755)

	d, err := bolt.Open(dbPath, 0600, nil)
	if err != nil {
		return nil, err
	}

	tx, err := d.Begin(true)
	if err != nil {
		return nil, err
	}

	if _, err = tx.CreateBucketIfNotExists(bucketName); err != nil {
		tx.Rollback()
		return nil, err
	}

	if err = tx.Commit(); err != nil {
		return nil, err
	}

	return &db{d}, nil
}
<commit_msg>Address comments<commit_after>// Copyright 2015 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package boltdb

import (
	"os"
	"path"

	"github.com/boltdb/bolt"
	"github.com/juju/errors"
	"github.com/pingcap/tidb/store/localstore/engine"
	"github.com/pingcap/tidb/util/bytes"
)

var (
	_ engine.DB = (*db)(nil)
)

var (
	bucketName = []byte("tidb")
)

type db struct {
	*bolt.DB
}

func (d *db) Get(key []byte) ([]byte, error) {
	var value []byte

	err := d.DB.View(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketName)
		v := b.Get(key)
		if v == nil {
			return errors.Trace(engine.ErrNotFound)
		}
		value = bytes.CloneBytes(v)
		return nil
	})

	return value, errors.Trace(err)
}

func (d *db) MultiSeek(keys [][]byte) []*engine.MSeekResult {
	res := make([]*engine.MSeekResult, 0, len(keys))
	d.DB.View(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketName)
		c := b.Cursor()
		for _, key := range keys {
			var k, v []byte
			if key == nil {
				k, v = c.First()
			} else {
				k, v = c.Seek(key)
			}

			r := &engine.MSeekResult{}
			if k == nil {
				r.Err = engine.ErrNotFound
			} else {
				r.Key, r.Value, r.Err = bytes.CloneBytes(k), bytes.CloneBytes(v), nil
			}

			res = append(res, r)
		}
		return nil
	})

	return res
}

func (d *db) Seek(startKey []byte) ([]byte, []byte, error) {
	var key, value []byte
	err := d.DB.View(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketName)
		c := b.Cursor()
		var k, v []byte
		if startKey == nil {
			k, v = c.First()
		} else {
			k, v = c.Seek(startKey)
		}
		if k != nil {
			key, value = bytes.CloneBytes(k), bytes.CloneBytes(v)
		}
		return nil
	})

	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	if key == nil {
		return nil, nil, errors.Trace(engine.ErrNotFound)
	}
	return key, value, nil
}

func (d *db) NewBatch() engine.Batch {
	return &batch{}
}

func (d *db) Commit(b engine.Batch) error {
	bt, ok := b.(*batch)
	if !ok {
		return errors.Errorf("invalid batch type %T", b)
	}
	err := d.DB.Update(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucketName)
		// err1 is used for passing `go tool vet --shadow` check.
		var err1 error
		for _, w := range bt.writes {
			if !w.isDelete {
				err1 = b.Put(w.key, w.value)
			} else {
				err1 = b.Delete(w.key)
			}

			if err1 != nil {
				return errors.Trace(err1)
			}
		}

		return nil
	})
	return errors.Trace(err)
}

func (d *db) Close() error {
	return d.DB.Close()
}

type write struct {
	key      []byte
	value    []byte
	isDelete bool
}

type batch struct {
	writes []write
}

func (b *batch) Put(key []byte, value []byte) {
	w := write{
		key:   append([]byte(nil), key...),
		value: append([]byte(nil), value...),
	}
	b.writes = append(b.writes, w)
}

func (b *batch) Delete(key []byte) {
	w := write{
		key:      append([]byte(nil), key...),
		value:    nil,
		isDelete: true,
	}
	b.writes = append(b.writes, w)
}

func (b *batch) Len() int {
	return len(b.writes)
}

// Driver implements engine Driver.
type Driver struct {
}

// Open opens or creates a local storage database with given path.
func (driver Driver) Open(dbPath string) (engine.DB, error) {
	base := path.Dir(dbPath)
	os.MkdirAll(base, 0755)

	d, err := bolt.Open(dbPath, 0600, nil)
	if err != nil {
		return nil, err
	}

	tx, err := d.Begin(true)
	if err != nil {
		return nil, err
	}

	if _, err = tx.CreateBucketIfNotExists(bucketName); err != nil {
		tx.Rollback()
		return nil, err
	}

	if err = tx.Commit(); err != nil {
		return nil, err
	}

	return &db{d}, nil
}
<|endoftext|>


<commit_before>package models

import (
	"reflect"
	"strconv"
	"strings"

	"github.com/SpectoLabs/hoverfly/core/state"
)

type Simulation struct {
	matchingPairs  []RequestMatcherResponsePair
	ResponseDelays ResponseDelays
}

func NewSimulation() *Simulation {

	return &Simulation{
		matchingPairs:  []RequestMatcherResponsePair{},
		ResponseDelays: &ResponseDelayList{},
	}
}

func (this *Simulation) AddPair(pair *RequestMatcherResponsePair) {
	var duplicate bool
	for _, savedPair := range this.matchingPairs {
		duplicate = reflect.DeepEqual(pair.RequestMatcher, savedPair.RequestMatcher)
		if duplicate {
			break
		}
	}
	if !duplicate {
		this.matchingPairs = append(this.matchingPairs, *pair)
	}
}

func (this *Simulation) AddPairInSequence(pair *RequestMatcherResponsePair, state *state.State) {
	var duplicate bool

	updates := map[int]RequestMatcherResponsePair{}

	var counter int
	sequenceKey := "sequence:0"

	for i, savedPair := range this.matchingPairs {

		pairNoState := pair.RequestMatcher
		pairNoState.RequiresState = nil

		savedPairNoState := savedPair.RequestMatcher
		savedPairNoState.RequiresState = nil

		duplicate = reflect.DeepEqual(pairNoState, savedPairNoState)
		if duplicate {
			counter = counter + 1

			if savedPair.RequestMatcher.RequiresState == nil {
				savedPair.RequestMatcher.RequiresState = map[string]string{}
			}

			if savedPair.Response.TransitionsState == nil {
				savedPair.Response.TransitionsState = map[string]string{}
			}

			if pair.RequestMatcher.RequiresState == nil {
				pair.RequestMatcher.RequiresState = map[string]string{}
			}
			sequenceKey = state.GetNewSequenceKey()
			for key, _ := range savedPair.RequestMatcher.RequiresState {
				if strings.Contains(key, "sequence:") {
					sequenceKey = key
					break
				}
			}

			sequenceState := savedPair.RequestMatcher.RequiresState[sequenceKey]
			nextSequenceState := ""
			if sequenceState == "" {
				sequenceState = "1"
				nextSequenceState = "2"
				state.SetState(map[string]string{sequenceKey: "1"})

			} else {
				currentSequenceState, _ := strconv.Atoi(sequenceState)
				nextSequenceState = strconv.Itoa(currentSequenceState + 1)
			}
			savedPair.RequestMatcher.RequiresState[sequenceKey] = sequenceState
			savedPair.Response.TransitionsState[sequenceKey] = nextSequenceState
			updates[i] = savedPair
		}
	}

	for i, updatedPair := range updates {
		this.matchingPairs[i] = updatedPair
	}

	if counter != 0 {
		pair.RequestMatcher.RequiresState[sequenceKey] = strconv.Itoa(counter + 1)
	}

	this.matchingPairs = append(this.matchingPairs, *pair)
}

func (this *Simulation) GetMatchingPairs() []RequestMatcherResponsePair {
	return this.matchingPairs
}

func (this *Simulation) DeleteMatchingPairs() {
	var pairs []RequestMatcherResponsePair
	this.matchingPairs = pairs
}
<commit_msg>Maintain existing state instead of overwriting<commit_after>package models

import (
	"reflect"
	"strconv"
	"strings"

	"github.com/SpectoLabs/hoverfly/core/state"
)

type Simulation struct {
	matchingPairs  []RequestMatcherResponsePair
	ResponseDelays ResponseDelays
}

func NewSimulation() *Simulation {

	return &Simulation{
		matchingPairs:  []RequestMatcherResponsePair{},
		ResponseDelays: &ResponseDelayList{},
	}
}

func (this *Simulation) AddPair(pair *RequestMatcherResponsePair) {
	var duplicate bool
	for _, savedPair := range this.matchingPairs {
		duplicate = reflect.DeepEqual(pair.RequestMatcher, savedPair.RequestMatcher)
		if duplicate {
			break
		}
	}
	if !duplicate {
		this.matchingPairs = append(this.matchingPairs, *pair)
	}
}

func (this *Simulation) AddPairInSequence(pair *RequestMatcherResponsePair, state *state.State) {
	var duplicate bool

	updates := map[int]RequestMatcherResponsePair{}

	var counter int
	sequenceKey := "sequence:0"

	for i, savedPair := range this.matchingPairs {

		pairNoState := pair.RequestMatcher
		pairNoState.RequiresState = nil

		savedPairNoState := savedPair.RequestMatcher
		savedPairNoState.RequiresState = nil

		duplicate = reflect.DeepEqual(pairNoState, savedPairNoState)
		if duplicate {
			counter = counter + 1

			if savedPair.RequestMatcher.RequiresState == nil {
				savedPair.RequestMatcher.RequiresState = map[string]string{}
			}

			if savedPair.Response.TransitionsState == nil {
				savedPair.Response.TransitionsState = map[string]string{}
			}

			if pair.RequestMatcher.RequiresState == nil {
				pair.RequestMatcher.RequiresState = map[string]string{}
			}
			sequenceKey = state.GetNewSequenceKey()
			for key, _ := range savedPair.RequestMatcher.RequiresState {
				if strings.Contains(key, "sequence:") {
					sequenceKey = key
					break
				}
			}

			sequenceState := savedPair.RequestMatcher.RequiresState[sequenceKey]
			nextSequenceState := ""
			if sequenceState == "" {
				sequenceState = "1"
				nextSequenceState = "2"
				state.PatchState(map[string]string{sequenceKey: "1"})

			} else {
				currentSequenceState, _ := strconv.Atoi(sequenceState)
				nextSequenceState = strconv.Itoa(currentSequenceState + 1)
			}
			savedPair.RequestMatcher.RequiresState[sequenceKey] = sequenceState
			savedPair.Response.TransitionsState[sequenceKey] = nextSequenceState
			updates[i] = savedPair
		}
	}

	for i, updatedPair := range updates {
		this.matchingPairs[i] = updatedPair
	}

	if counter != 0 {
		pair.RequestMatcher.RequiresState[sequenceKey] = strconv.Itoa(counter + 1)
	}

	this.matchingPairs = append(this.matchingPairs, *pair)
}

func (this *Simulation) GetMatchingPairs() []RequestMatcherResponsePair {
	return this.matchingPairs
}

func (this *Simulation) DeleteMatchingPairs() {
	var pairs []RequestMatcherResponsePair
	this.matchingPairs = pairs
}
<|endoftext|>


<commit_before>package firewall

import (
	//"fmt"
	"labix.org/v2/mgo"
)

func SaveFirewall(fwreq map[string]interface{}) {
	session, err := mgo.Dial("localhost")
	if err != nil {
		panic(err)
	}
	defer session.Close()

	requestCollection := session.DB("firewallapp").C("fwreq")
	err = requestCollection.Insert(fwreq)
	if err != nil {
		panic(err)
	}
}
<commit_msg>Added Firewall Data Structures<commit_after>package firewall

import (
	//"fmt"
	"labix.org/v2/mgo"
	"log"
)

type firewall_request struct {
	requestor         string
	service_date      string
	service_term_date string
	leader            string
	business_approver string
	service_number    string
	firewall_rules    []firewall_rule
}

type firewall_rule struct {
	source_zone      string
	source_ips       string
	dest_zone        string
	data_type        string
	network_protocol string
	dest_ips         string
	dest_ports       string
	app_name         string
	server_loc       string
}

//Saves Firewall Request to MongoDB
func SaveFirewall(fwreq map[string]interface{}) {
	log.Println("%s", fwreq)
	session, err := mgo.Dial("localhost")
	if err != nil {
		panic(err)
	}
	defer session.Close()

	requestCollection := session.DB("firewallapp").C("fwreq")
	err = requestCollection.Insert(fwreq)
	if err != nil {
		panic(err)
	}
}
<|endoftext|>


<commit_before>package stringconcat

import (
	"bytes"
	"fmt"
	"strconv"
	"testing"
)

func BenchmarkPlusConcat(b *testing.B) {
	var s string
	for i := 0; i < b.N; i++ {
		s = ""
		s = s +
			"abcdefghijklmnopqrstuvwxyz" +
			string([]byte{'a', 'b', 'c'}) +
			strconv.Itoa(100)
	}
}

func BenchmarkFmtSprintf(b *testing.B) {
	var s string
	for i := 0; i < b.N; i++ {
		s = fmt.Sprintf("%s%s%d",
			"abcdefghijklmnopqrstuvwxyz",
			[]byte{'a', 'b', 'c'},
			100,
		)
		_ = s
	}
}

func BenchmarkBytesBuffer(b *testing.B) {
	var buf bytes.Buffer
	for i := 0; i < b.N; i++ {
		buf.Reset()
		buf.WriteString("abcdefghijklmnopqrstuvwxyz")
		buf.Write([]byte{'a', 'b', 'c'})
		buf.WriteString(strconv.Itoa(100))
	}
}
<commit_msg>Add BenchmarkApeendBytes<commit_after>package stringconcat

import (
	"bytes"
	"fmt"
	"strconv"
	"testing"
)

func BenchmarkPlusConcat(b *testing.B) {
	var s string
	for i := 0; i < b.N; i++ {
		s = ""
		s = s +
			"abcdefghijklmnopqrstuvwxyz" +
			string([]byte{'a', 'b', 'c'}) +
			strconv.Itoa(100)
	}
}

func BenchmarkFmtSprintf(b *testing.B) {
	var s string
	for i := 0; i < b.N; i++ {
		s = fmt.Sprintf("%s%s%d",
			"abcdefghijklmnopqrstuvwxyz",
			[]byte{'a', 'b', 'c'},
			100,
		)
		_ = s
	}
}

func BenchmarkBytesBuffer(b *testing.B) {
	var buf bytes.Buffer
	for i := 0; i < b.N; i++ {
		buf.Reset()
		buf.WriteString("abcdefghijklmnopqrstuvwxyz")
		buf.Write([]byte{'a', 'b', 'c'})
		buf.WriteString(strconv.Itoa(100))
	}
}

func BenchmarkApeendBytes(b *testing.B) {
	for i := 0; i < b.N; i++ {
		buf := make([]byte, 0, 64)
		buf = append(buf, "abcdefghijklmnopqrstuvwxyz"...)
		buf = append(buf, []byte{'a', 'b', 'c'}...)
		buf = strconv.AppendInt(buf, 100, 10)
	}
}
<|endoftext|>


<commit_before>package cloudformation

import (
	"encoding/json"

	"github.com/sanathkr/yaml"
)

// Template represents an AWS CloudFormation template
// see: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html
type Template struct {
	AWSTemplateFormatVersion string                 `json:"AWSTemplateFormatVersion,omitempty"`
	Description              string                 `json:"Description,omitempty"`
	Metadata                 map[string]interface{} `json:"Metadata,omitempty"`
	Parameters               map[string]interface{} `json:"Parameters,omitempty"`
	Mappings                 map[string]interface{} `json:"Mappings,omitempty"`
	Conditions               map[string]interface{} `json:"Conditions,omitempty"`
	Resources                map[string]interface{} `json:"Resources,omitempty"`
	Outputs                  map[string]interface{} `json:"Outputs,omitempty"`
}

// NewTemplate creates a new AWS CloudFormation template struct
func NewTemplate() *Template {
	return &Template{
		AWSTemplateFormatVersion: "2010-09-09",
		Description:              "",
		Metadata:                 map[string]interface{}{},
		Parameters:               map[string]interface{}{},
		Mappings:                 map[string]interface{}{},
		Conditions:               map[string]interface{}{},
		Resources:                map[string]interface{}{},
		Outputs:                  map[string]interface{}{},
	}
}

// JSON converts an AWS CloudFormation template object to JSON
func (t *Template) JSON() ([]byte, error) {
	return json.Marshal(t)
}

// YAML converts an AWS CloudFormation template object to YAML
func (t *Template) YAML() ([]byte, error) {
	return yaml.Marshal(t)
}
<commit_msg>Transform is missing.<commit_after>package cloudformation

import (
	"encoding/json"

	"github.com/sanathkr/yaml"
)

// Template represents an AWS CloudFormation template
// see: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html
type Template struct {
	AWSTemplateFormatVersion string                 `json:"AWSTemplateFormatVersion,omitempty"`
	Transform                string                 `json:"Transform,omitempty"`
	Description              string                 `json:"Description,omitempty"`
	Metadata                 map[string]interface{} `json:"Metadata,omitempty"`
	Parameters               map[string]interface{} `json:"Parameters,omitempty"`
	Mappings                 map[string]interface{} `json:"Mappings,omitempty"`
	Conditions               map[string]interface{} `json:"Conditions,omitempty"`
	Resources                map[string]interface{} `json:"Resources,omitempty"`
	Outputs                  map[string]interface{} `json:"Outputs,omitempty"`
}

// NewTemplate creates a new AWS CloudFormation template struct
func NewTemplate() *Template {
	return &Template{
		AWSTemplateFormatVersion: "2010-09-09",
		Description:              "",
		Metadata:                 map[string]interface{}{},
		Parameters:               map[string]interface{}{},
		Mappings:                 map[string]interface{}{},
		Conditions:               map[string]interface{}{},
		Resources:                map[string]interface{}{},
		Outputs:                  map[string]interface{}{},
	}
}

// JSON converts an AWS CloudFormation template object to JSON
func (t *Template) JSON() ([]byte, error) {
	return json.Marshal(t)
}

// YAML converts an AWS CloudFormation template object to YAML
func (t *Template) YAML() ([]byte, error) {
	return yaml.Marshal(t)
}
<|endoftext|>


<commit_before>//
// Monitor Middlware Library
//
// Copyright (C) Philip Schlump, 2014-2016
//
package MonAliveLib

import (
	"os"
	"testing"

	"github.com/pschlump/mon-alive/qdemolib"
	"github.com/pschlump/radix.v2/redis"
)

// -----------------------------------------------------------------------------------------------------------------------------------------------
func Test_MonAliveLib(t *testing.T) {

	tests := []struct {
		cmd      string
		expect   string
		itemName string
	}{
		{
			cmd:      "SendIAmAlive",
			expect:   `?TODO?`,
			itemName: `bob`,
		},
	}

	qdemolib.SetupRedisForTest("../global_cfg.json")

	monClient, isCon := qdemolib.GetRedisClient()
	if !isCon {
		t.Fatalf("Error connecting to Redis - fatal\n")
		os.Exit(1)
	}
	mon := NewMonIt(func() *redis.Client { return monClient }, func(conn *redis.Client) {})

	for ii, test := range tests {

		//if b != test.expectedBody {
		//	t.Errorf("Error %2d, reject error got: %s, expected %s\n", ii, b, test.expectedBody)
		//}

		switch test.cmd {
		case "SendIAmAlive":
			myStatus := make(map[string]interface{})
			mon.SendIAmAlive(test.itemName, myStatus)
		default:
			t.Errorf("Test %2d,  invalid test case, %s\n", ii, test.cmd)
		}
	}

}

/*
func (mon *MonIt) SendIAmAlive(itemName string, myStatus map[string]interface{}) {
func (mon *MonIt) SendIAmShutdown(itemName string) {
func (mon *MonIt) GetNotifyItem() (rv []string) {
func (mon *MonIt) GetItemStatus() (rv []ItemStatus) {
func (mon *MonIt) GetAllItem() (rv []string) {
func (mon *MonIt) AddNewItem(itemName string, ttl uint64) {
func (mon *MonIt) RemoveItem(itemName string) {
func (mon *MonIt) ChangeConfigOnItem(itemName string, newConfig map[string]interface{}) {
func (mon *MonIt) SetConfigFromFile(fn string) {
func (mon *MonIt) GetListOfPotentialItem() (rv []string) {
	! TODO !
* func (mon *MonIt) SendPeriodicIAmAlive(itemName string) {

	// mon.SendPeriodicIAmAlive("Go-FTL")
	_ = mon
*/

/* vim: set noai ts=4 sw=4: */
<commit_msg>Start of library test<commit_after>//
// Monitor Middlware Library
//
// Copyright (C) Philip Schlump, 2014-2016
//
package MonAliveLib

import (
	"os"
	"testing"

	"github.com/pschlump/mon-alive/qdemolib"
	"github.com/pschlump/radix.v2/redis"
)

// -----------------------------------------------------------------------------------------------------------------------------------------------
func Test_MonAliveLib(t *testing.T) {

	tests := []struct {
		cmd      string
		expect   string
		itemName string
	}{
		{
			cmd:      "SendIAmAlive",
			expect:   `?TODO?`,
			itemName: `bob`,
		},
	}

	qdemolib.SetupRedisForTest("../global_cfg.json")

	monClient, isCon := qdemolib.GetRedisClient()
	if !isCon {
		t.Fatalf("Error connecting to Redis - fatal\n")
		os.Exit(1)
	}
	mon := NewMonIt(func() *redis.Client { return monClient }, func(conn *redis.Client) {})

	conn, _ := qdemolib.GetRedisClient()

	for ii, test := range tests {

		switch test.cmd {
		case "SendIAmAlive":
			myStatus := make(map[string]interface{})
			mon.SendIAmAlive(test.itemName, myStatus)
			err := conn.Cmd("GET", "monitor:bob").Err
			if err != nil {
				t.Errorf("Test %2d, Expected to find a key - did not\n", ii)
			}
		default:
			t.Errorf("Test %2d,  invalid test case, %s\n", ii, test.cmd)
		}
	}

}

/*
func (mon *MonIt) SendIAmAlive(itemName string, myStatus map[string]interface{}) {
func (mon *MonIt) SendIAmShutdown(itemName string) {
func (mon *MonIt) GetNotifyItem() (rv []string) {
func (mon *MonIt) GetItemStatus() (rv []ItemStatus) {
func (mon *MonIt) GetAllItem() (rv []string) {
func (mon *MonIt) AddNewItem(itemName string, ttl uint64) {
func (mon *MonIt) RemoveItem(itemName string) {
func (mon *MonIt) ChangeConfigOnItem(itemName string, newConfig map[string]interface{}) {
func (mon *MonIt) SetConfigFromFile(fn string) {
func (mon *MonIt) GetListOfPotentialItem() (rv []string) {
	! TODO !
* func (mon *MonIt) SendPeriodicIAmAlive(itemName string) {

		//if b != test.expectedBody {
		//	t.Errorf("Error %2d, reject error got: %s, expected %s\n", ii, b, test.expectedBody)
		//}

	// mon.SendPeriodicIAmAlive("Go-FTL")
	_ = mon
*/

/* vim: set noai ts=4 sw=4: */
<|endoftext|>


<commit_before>package main

import (
	"colorlog"
	"conf"
	"dmserver"
	"encoding/json"
	"fmt"
	"ftrans"
	"io/ioutil"
	"net/http"
	"os"
	"os/user"
	"strconv"
	"time"
	"fgplugin"
	"C"
)

/*
VERSION定义了FrozenGo的当前版本
 */
const VERSION string = "v1.0.0"

/*
定义了项目的配置文件目录
 */
const FILE_CONFIGURATION string = "../conf/fg.json"

/*
版本检测地址.
这是一个Golang写的服务器(by Axoford12),不要抱有任何幻想去日~,
日进去算我输>.<
 */
const UPDATE_CURRENT_VERSION = "http://119.29.7.229/version"

/*
全局变量conf.
 */
var config conf.Cnf
func main() {
	// 检测是否有定义FGO_DEBUG变量,定义了就直接跳过Banner打印
	if os.Getenv("FGO_DEBUG") != "Yes" {
		banner()
	}
	// 检查是否为root
	if !isRoot() {
		fmt.Println(colorlog.ColorSprint("Need root permission.", colorlog.FR_RED))
		return
	}
	checkEnv()
	if _,err := os.Stat("../cgroup");err != nil{
		b := []byte(`
case $1 in
	"cg") case $2 in
			"init")
				mkdir /sys/fs/cgroup/cpu/${3} /sys/fs/cgroup/memory/${3} /sys/fs/cgroup/blkio/${3} /sys/fs/cgroup/net_cls/${3}
				# ${4} cpu $5 memmax $6 $7 $8 blkio blkio.throttle.read_bps_device $9 netcls
				tmp=$(cat /sys/fs/cgroup/cpu/${3}/cpu.cfs_period_us)
				cpux=$4
				rmb=$6
				wmb=$7
				mmb=$5
				let rmb=1024*1024*rmb
				let wmb=1024*1024*wmb
				let mmb=1024*1024*mmb
				let tmp=tmp*cpux/100
				echo $tmp > /sys/fs/cgroup/cpu/${3}/cpu.cfs_quota_us
				echo $mmb > /sys/fs/cgroup/memory/${3}/memory.max_usage_in_bytes
				echo "0x0001${9}" > /sys/fs/cgroup/net_cls/${3}/net_cls.classid
				echo "${8} ${rmb}" > /sys/fs/cgroup/blkio/${3}/blkio.throttle.read_bps_device
				echo "${8} ${wmb}" > /sys/fs/cgroup/blkio/${3}/blkio.throttle.write_bps_device
				;;
			"del")
				rmdir /sys/fs/cgroup/cpu/${3} /sys/fs/cgroup/memory/${3} /sys/fs/cgroup/blkio/${3} /sys/fs/cgroup/net_cls/${3}
				;;
			"run")
				/bin/echo ${4} |tee /sys/fs/cgroup/cpu/${3}/tasks /sys/fs/cgroup/memory/${3}/tasks /sys/fs/cgroup/blkio/${3}/tasks /sys/fs/cgroup/net_cls/${3}/tasks
				;;
			esac;;
	"net") DEV=$6;
			case $2 in
				"add")
				tc class add dev $DEV parent 1: classid 1:${3} htb rate ${4}mbit ceil ${5}mbit;
				tc filter add dev $DEV protocol ip parent 1:0 prio 1 handle 1:${3} cgroup;;
				"change")
				tc class change dev $DEV parent 1: classid 1:${3} htb rate ${4}mbit ceil ${5}mbit;;
				"del")
				tc class del dev $DEV parent 1: classid 1:${3};
				tc filter del dev $DEV protocol ip parent 1:0 prio 1 handle 1:${3} cgroup;;

			esac;;
	"init")
	DEV=$2;
	#tc qdisc del dev $DEV root
	tc qdisc add dev $DEV root handle 1: htb;
	tc class add dev $DEV parent 1: classid 1: htb rate 10000mbit ceil 10000mbit;
	service cgconfig restart;
	;;
	esac`)
		os.MkdirAll("../cgroup",755)
		ioutil.WriteFile("../cgroup/cg.sh",b,755)
	}
	colorlog.LogPrint("Reading config file")
	config, _ = conf.GetConfig(FILE_CONFIGURATION)
	if config.DaemonServer.HardDiskMethod == conf.HDM_MOUNT {
		colorlog.WarningPrint("You are running in MOUNT HardDisk Method!")
		colorlog.LogPrint("You must know its risk and willing to take responsibility for incorrect use")
		colorlog.WarningPrint(fmt.Sprint("Please type:", colorlog.ColorSprint("I_KNOW", colorlog.FR_PURPLE)))
		check := ""
		fmt.Scanf("%s", &check)
		if check != "I_KNOW" {
			colorlog.WarningPrint("You must know the warning")
			return
		}
	}
	colorlog.LogPrint("Configuration file got.")
	colorlog.LogPrint("Checking Update")
	if versionCode, err := checkUpdate(); err != nil {
		colorlog.ErrorPrint("checking update...",err)
	} else {
		colorlog.LogPrint("Version Check done:")
		if versionCode < -1 {
			colorlog.WarningPrint("|---Daemon out of date")
			colorlog.WarningPrint("|---Your daemon need to be updated!")
			return
		} else if versionCode == -1 {
			colorlog.WarningPrint("Small bugs fixed,You choose to updated it or not.")
		} else {
			colorlog.LogPrint("Version up to date.")
		}
	}

	colorlog.PointPrint("Loading plugins...")
	fgplugin.LoadPlugin(config.DaemonServer.PluginPath)
	colorlog.PointPrint("Starting Server Manager...")
	go dmserver.StartDaemonServer(config)
	go ftrans.Start(config)
	colorlog.PointPrint("Starting websocket server...")
	go dmserver.Webskt()
	colorlog.PointPrint("Starting ValidationKeyUpdater...")
	colorlog.LogPrint("Done,type \"?\" for help. ")
	// 处理一些非常非常基本的指令,因为基本不用,所以并不是很想写这一块的内容
	for {
		var s string
		fmt.Scanf("%s", &s)
		processLocalCommand(s)
	}
}

func banner() {
	fmt.Println(colorlog.ColorSprint(`

    ______                                ______
   / ____/_____ ____  ____  ___   ____   / ____/____
  / /_   / ___// __ \/_  / / _ \ / __ \ / / __ / __ \
 / __/  / /   / /_/ / / /_/  __// / / // /_/ // /_/ /
/_/    /_/    \____/ /___/\___//_/ /_/ \____/ \____/

	`, colorlog.FR_CYAN))
	time.Sleep(2 * time.Second)
	fmt.Println("---------------------")
	time.Sleep(100 * time.Microsecond)
	fmt.Print("Powered by ")
	for _, v := range []byte("Axoford12") {
		time.Sleep(240 * time.Millisecond)
		fmt.Print(colorlog.ColorSprint(string(v), colorlog.FR_GREEN))
	}
	fmt.Println()
	time.Sleep(1000 * time.Millisecond)
	time.Sleep(100 * time.Microsecond)
	fmt.Println("---------------------")
	time.Sleep(300 * time.Millisecond)
	colorlog.LogPrint("version:" + VERSION)
	time.Sleep(1 * time.Second)
}

func processLocalCommand(c string) {
	switch c {
	case "stop":
		fmt.Println("Stopping...")
		dmserver.StopDaemonServer()
		os.Exit(0)
	case "?":
		fmt.Println("FrozenGo" + VERSION + " Help Manual -- by Axoford12")
		fmt.Println("stop: Stop the daemon.save server changes.")
		fmt.Println("status: Echo server status.")
		return
	case "status":
		b, _ := json.Marshal(dmserver.GetServerSaved())
		fmt.Println(string(b))
		return
	}
}
func isRoot() bool {
	nowUser, err := user.Current()
	if err != nil {
		panic(err)
	}
	userId, err2 := strconv.Atoi(nowUser.Uid)
	if err2 != nil {
		panic(err)
	}
	return userId == 0
}
func checkUpdate() (int, error) {
	colorlog.LogPrint("Starting Version check...")
	colorlog.LogPrint("This may take more time...")
	resp, err := http.Get(UPDATE_CURRENT_VERSION + "?v=" + VERSION)
	if err != nil {
		return -2, err
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	result,err := strconv.Atoi(string(body))
	if err != nil {
		return -2,err
	}
	return result,nil
	//return -2,errors.New("Unexpected error")
}

func checkEnv(){
	os.MkdirAll("../plugins",755)
	os.MkdirAll("../exec",755)
	os.MkdirAll("../data",755)
	os.MkdirAll("../conf",755)
}
<commit_msg>根据需要去除部分功能<commit_after>package main

import (
	"colorlog"
	"conf"
	"dmserver"
	"encoding/json"
	"fmt"
	"ftrans"
	"io/ioutil"
	"net/http"
	"os"
	"os/user"
	"strconv"
	"time"
	"fgplugin"
	"C"
)

/*
VERSION定义了FrozenGo的当前版本
 */
const VERSION string = "v1.0.1"

/*
定义了项目的配置文件目录
 */
const FILE_CONFIGURATION string = "../conf/fg.json"

/*
全局变量conf.
 */
var config conf.Cnf
func main() {
	// 检测是否有定义FGO_DEBUG变量,定义了就直接跳过Banner打印
	if os.Getenv("FGO_DEBUG") != "Yes" {
		banner()
	}
	// 检查是否为root
	if !isRoot() {
		fmt.Println(colorlog.ColorSprint("Need root permission.", colorlog.FR_RED))
		return
	}
	checkEnv()
	if _,err := os.Stat("../cgroup");err != nil{
		b := []byte(`
case $1 in
	"cg") case $2 in
			"init")
				mkdir /sys/fs/cgroup/cpu/${3} /sys/fs/cgroup/memory/${3} /sys/fs/cgroup/blkio/${3} /sys/fs/cgroup/net_cls/${3}
				# ${4} cpu $5 memmax $6 $7 $8 blkio blkio.throttle.read_bps_device $9 netcls
				tmp=$(cat /sys/fs/cgroup/cpu/${3}/cpu.cfs_period_us)
				cpux=$4
				rmb=$6
				wmb=$7
				mmb=$5
				let rmb=1024*1024*rmb
				let wmb=1024*1024*wmb
				let mmb=1024*1024*mmb
				let tmp=tmp*cpux/100
				echo $tmp > /sys/fs/cgroup/cpu/${3}/cpu.cfs_quota_us
				echo $mmb > /sys/fs/cgroup/memory/${3}/memory.max_usage_in_bytes
				echo "0x0001${9}" > /sys/fs/cgroup/net_cls/${3}/net_cls.classid
				echo "${8} ${rmb}" > /sys/fs/cgroup/blkio/${3}/blkio.throttle.read_bps_device
				echo "${8} ${wmb}" > /sys/fs/cgroup/blkio/${3}/blkio.throttle.write_bps_device
				;;
			"del")
				rmdir /sys/fs/cgroup/cpu/${3} /sys/fs/cgroup/memory/${3} /sys/fs/cgroup/blkio/${3} /sys/fs/cgroup/net_cls/${3}
				;;
			"run")
				/bin/echo ${4} |tee /sys/fs/cgroup/cpu/${3}/tasks /sys/fs/cgroup/memory/${3}/tasks /sys/fs/cgroup/blkio/${3}/tasks /sys/fs/cgroup/net_cls/${3}/tasks
				;;
			esac;;
	"net") DEV=$6;
			case $2 in
				"add")
				tc class add dev $DEV parent 1: classid 1:${3} htb rate ${4}mbit ceil ${5}mbit;
				tc filter add dev $DEV protocol ip parent 1:0 prio 1 handle 1:${3} cgroup;;
				"change")
				tc class change dev $DEV parent 1: classid 1:${3} htb rate ${4}mbit ceil ${5}mbit;;
				"del")
				tc class del dev $DEV parent 1: classid 1:${3};
				tc filter del dev $DEV protocol ip parent 1:0 prio 1 handle 1:${3} cgroup;;

			esac;;
	"init")
	DEV=$2;
	#tc qdisc del dev $DEV root
	tc qdisc add dev $DEV root handle 1: htb;
	tc class add dev $DEV parent 1: classid 1: htb rate 10000mbit ceil 10000mbit;
	service cgconfig restart;
	;;
	esac`)
		os.MkdirAll("../cgroup",755)
		ioutil.WriteFile("../cgroup/cg.sh",b,755)
	}
	colorlog.LogPrint("Reading config file")
	config, _ = conf.GetConfig(FILE_CONFIGURATION)
	if config.DaemonServer.HardDiskMethod == conf.HDM_MOUNT {
		colorlog.WarningPrint("You are running in MOUNT HardDisk Method!")
		colorlog.LogPrint("You must know its risk and willing to take responsibility for incorrect use")
		colorlog.WarningPrint(fmt.Sprint("Please type:", colorlog.ColorSprint("I_KNOW", colorlog.FR_PURPLE)))
		check := ""
		fmt.Scanf("%s", &check)
		if check != "I_KNOW" {
			colorlog.WarningPrint("You must know the warning")
			return
		}
	}
	colorlog.LogPrint("Configuration file got.")
	colorlog.LogPrint("This version is:"+VERSION)
	//去除了版本更新，不再会强制要求更新
	//2018年1月进行了修改
	colorlog.PointPrint("Loading plugins...")
	fgplugin.LoadPlugin(config.DaemonServer.PluginPath)
	colorlog.PointPrint("Starting Server Manager...")
	go dmserver.StartDaemonServer(config)
	go ftrans.Start(config)
	colorlog.PointPrint("Starting websocket server...")
	go dmserver.Webskt()
	colorlog.PointPrint("Starting ValidationKeyUpdater...")
	colorlog.LogPrint("Done,type \"?\" for help. ")
	// 处理一些非常非常基本的指令,因为基本不用,所以并不是很想写这一块的内容
	for {
		var s string
		fmt.Scanf("%s", &s)
		processLocalCommand(s)
	}
}

func banner() {
	fmt.Println(colorlog.ColorSprint(`

    ______                                ______
   / ____/_____ ____  ____  ___   ____   / ____/____
  / /_   / ___// __ \/_  / / _ \ / __ \ / / __ / __ \
 / __/  / /   / /_/ / / /_/  __// / / // /_/ // /_/ /
/_/    /_/    \____/ /___/\___//_/ /_/ \____/ \____/

	`, colorlog.FR_CYAN))
	time.Sleep(2 * time.Second)
	fmt.Println("---------------------")
	fmt.Println("Compliance with the MIT open source protocol...")
	time.Sleep(100 * time.Microsecond)
	fmt.Print("Powered by ")
	for _, v := range []byte("Axoford12") {
		time.Sleep(240 * time.Millisecond)
		fmt.Print(colorlog.ColorSprint(string(v), colorlog.FR_GREEN))
	}
	fmt.Println()
	time.Sleep(1000 * time.Millisecond)
	time.Sleep(100 * time.Microsecond)
	fmt.Println("---------------------")
	time.Sleep(300 * time.Millisecond)
	colorlog.LogPrint("version:" + VERSION)
	time.Sleep(1 * time.Second)
}

func processLocalCommand(c string) {
	switch c {
	case "stop":
		fmt.Println("Stopping...")
		dmserver.StopDaemonServer()
		os.Exit(0)
	case "?":
		fmt.Println("FrozenGo" + VERSION + " Help Manual -- by Axoford12")
		fmt.Println("stop: Stop the daemon.save server changes.")
		fmt.Println("status: Echo server status.")
		return
	case "status":
		b, _ := json.Marshal(dmserver.GetServerSaved())
		fmt.Println(string(b))
		return
	}
}
func isRoot() bool {
	nowUser, err := user.Current()
	if err != nil {
		panic(err)
	}
	userId, err2 := strconv.Atoi(nowUser.Uid)
	if err2 != nil {
		panic(err)
	}
	return userId == 0
}
/*func checkUpdate() (int, error) {
	colorlog.LogPrint("Starting Version check...")
	colorlog.LogPrint("This may take more time...")
	resp, err := http.Get(UPDATE_CURRENT_VERSION + "?v=" + VERSION)
	if err != nil {
		return -2, err
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)
	result,err := strconv.Atoi(string(body))
	if err != nil {
		return -2,err
	}
	return result,nil
	//return -2,errors.New("Unexpected error")
}
*/
/*
 更新部分，1.0.1以后不再需要
*/

func checkEnv(){
	os.MkdirAll("../plugins",755)
	os.MkdirAll("../exec",755)
	os.MkdirAll("../data",755)
	os.MkdirAll("../conf",755)
}
<|endoftext|>


<commit_before>//Package matterhook provides interaction with mattermost incoming/outgoing webhooks
package matterhook

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"github.com/gorilla/schema"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
)

// OMessage for mattermost incoming webhook. (send to mattermost)
type OMessage struct {
	Channel     string      `json:"channel,omitempty"`
	IconURL     string      `json:"icon_url,omitempty"`
	IconEmoji   string      `json:"icon_emoji,omitempty"`
	UserName    string      `json:"username,omitempty"`
	Text        string      `json:"text"`
	Attachments interface{} `json:"attachments,omitempty"`
	Type        string      `json:"type,omitempty"`
}

// IMessage for mattermost outgoing webhook. (received from mattermost)
type IMessage struct {
	Token       string `schema:"token"`
	TeamID      string `schema:"team_id"`
	TeamDomain  string `schema:"team_domain"`
	ChannelID   string `schema:"channel_id"`
	ServiceID   string `schema:"service_id"`
	ChannelName string `schema:"channel_name"`
	Timestamp   string `schema:"timestamp"`
	UserID      string `schema:"user_id"`
	UserName    string `schema:"user_name"`
	Text        string `schema:"text"`
	TriggerWord string `schema:"trigger_word"`
}

// Client for Mattermost.
type Client struct {
	Url        string // URL for incoming webhooks on mattermost.
	In         chan IMessage
	Out        chan OMessage
	httpclient *http.Client
	Config
}

// Config for client.
type Config struct {
	Port               int    // Port to listen on.
	BindAddress        string // Address to listen on
	Token              string // Only allow this token from Mattermost. (Allow everything when empty)
	InsecureSkipVerify bool   // disable certificate checking
	DisableServer      bool   // Do not start server for outgoing webhooks from Mattermost.
}

// New Mattermost client.
func New(url string, config Config) *Client {
	c := &Client{Url: url, In: make(chan IMessage), Out: make(chan OMessage), Config: config}
	if c.Port == 0 {
		c.Port = 9999
	}
	c.BindAddress += ":"
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: config.InsecureSkipVerify},
	}
	c.httpclient = &http.Client{Transport: tr}
	if !c.DisableServer {
		go c.StartServer()
	}
	return c
}

// StartServer starts a webserver listening for incoming mattermost POSTS.
func (c *Client) StartServer() {
	mux := http.NewServeMux()
	mux.Handle("/", c)
	log.Printf("Listening on http://%v:%v...\n", c.BindAddress, c.Port)
	if err := http.ListenAndServe((c.BindAddress + strconv.Itoa(c.Port)), mux); err != nil {
		log.Fatal(err)
	}
}

// ServeHTTP implementation.
func (c *Client) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		log.Println("invalid " + r.Method + " connection from " + r.RemoteAddr)
		http.NotFound(w, r)
		return
	}
	msg := IMessage{}
	err := r.ParseForm()
	if err != nil {
		log.Println(err)
		http.NotFound(w, r)
		return
	}
	defer r.Body.Close()
	decoder := schema.NewDecoder()
	err = decoder.Decode(&msg, r.PostForm)
	if err != nil {
		log.Println(err)
		http.NotFound(w, r)
		return
	}
	if msg.Token == "" {
		log.Println("no token from " + r.RemoteAddr)
		http.NotFound(w, r)
		return
	}
	if c.Token != "" {
		if msg.Token != c.Token {
			log.Println("invalid token " + msg.Token + " from " + r.RemoteAddr)
			http.NotFound(w, r)
			return
		}
	}
	c.In <- msg
}

// Receive returns an incoming message from mattermost outgoing webhooks URL.
func (c *Client) Receive() IMessage {
	for {
		select {
		case msg := <-c.In:
			return msg
		}
	}
}

// Send sends a msg to mattermost incoming webhooks URL.
func (c *Client) Send(msg OMessage) error {
	buf, err := json.Marshal(msg)
	if err != nil {
		return err
	}
	resp, err := c.httpclient.Post(c.Url, "application/json", bytes.NewReader(buf))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// Read entire body to completion to re-use keep-alive connections.
	io.Copy(ioutil.Discard, resp.Body)

	if resp.StatusCode != 200 {
		return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
	}
	return nil
}
<commit_msg>Fix mattermost 3.1.0 API change. Closes #24<commit_after>//Package matterhook provides interaction with mattermost incoming/outgoing webhooks
package matterhook

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"github.com/gorilla/schema"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
)

// OMessage for mattermost incoming webhook. (send to mattermost)
type OMessage struct {
	Channel     string      `json:"channel,omitempty"`
	IconURL     string      `json:"icon_url,omitempty"`
	IconEmoji   string      `json:"icon_emoji,omitempty"`
	UserName    string      `json:"username,omitempty"`
	Text        string      `json:"text"`
	Attachments interface{} `json:"attachments,omitempty"`
	Type        string      `json:"type,omitempty"`
}

// IMessage for mattermost outgoing webhook. (received from mattermost)
type IMessage struct {
	Token       string `schema:"token"`
	TeamID      string `schema:"team_id"`
	TeamDomain  string `schema:"team_domain"`
	ChannelID   string `schema:"channel_id"`
	ChannelName string `schema:"channel_name"`
	Timestamp   string `schema:"timestamp"`
	UserID      string `schema:"user_id"`
	UserName    string `schema:"user_name"`
	PostId      string `schema:"post_id"`
	Text        string `schema:"text"`
	TriggerWord string `schema:"trigger_word"`
}

// Client for Mattermost.
type Client struct {
	Url        string // URL for incoming webhooks on mattermost.
	In         chan IMessage
	Out        chan OMessage
	httpclient *http.Client
	Config
}

// Config for client.
type Config struct {
	Port               int    // Port to listen on.
	BindAddress        string // Address to listen on
	Token              string // Only allow this token from Mattermost. (Allow everything when empty)
	InsecureSkipVerify bool   // disable certificate checking
	DisableServer      bool   // Do not start server for outgoing webhooks from Mattermost.
}

// New Mattermost client.
func New(url string, config Config) *Client {
	c := &Client{Url: url, In: make(chan IMessage), Out: make(chan OMessage), Config: config}
	if c.Port == 0 {
		c.Port = 9999
	}
	c.BindAddress += ":"
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: config.InsecureSkipVerify},
	}
	c.httpclient = &http.Client{Transport: tr}
	if !c.DisableServer {
		go c.StartServer()
	}
	return c
}

// StartServer starts a webserver listening for incoming mattermost POSTS.
func (c *Client) StartServer() {
	mux := http.NewServeMux()
	mux.Handle("/", c)
	log.Printf("Listening on http://%v:%v...\n", c.BindAddress, c.Port)
	if err := http.ListenAndServe((c.BindAddress + strconv.Itoa(c.Port)), mux); err != nil {
		log.Fatal(err)
	}
}

// ServeHTTP implementation.
func (c *Client) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		log.Println("invalid " + r.Method + " connection from " + r.RemoteAddr)
		http.NotFound(w, r)
		return
	}
	msg := IMessage{}
	err := r.ParseForm()
	if err != nil {
		log.Println(err)
		http.NotFound(w, r)
		return
	}
	defer r.Body.Close()
	decoder := schema.NewDecoder()
	err = decoder.Decode(&msg, r.PostForm)
	if err != nil {
		log.Println(err)
		http.NotFound(w, r)
		return
	}
	if msg.Token == "" {
		log.Println("no token from " + r.RemoteAddr)
		http.NotFound(w, r)
		return
	}
	if c.Token != "" {
		if msg.Token != c.Token {
			log.Println("invalid token " + msg.Token + " from " + r.RemoteAddr)
			http.NotFound(w, r)
			return
		}
	}
	c.In <- msg
}

// Receive returns an incoming message from mattermost outgoing webhooks URL.
func (c *Client) Receive() IMessage {
	for {
		select {
		case msg := <-c.In:
			return msg
		}
	}
}

// Send sends a msg to mattermost incoming webhooks URL.
func (c *Client) Send(msg OMessage) error {
	buf, err := json.Marshal(msg)
	if err != nil {
		return err
	}
	resp, err := c.httpclient.Post(c.Url, "application/json", bytes.NewReader(buf))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// Read entire body to completion to re-use keep-alive connections.
	io.Copy(ioutil.Discard, resp.Body)

	if resp.StatusCode != 200 {
		return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
	}
	return nil
}
<|endoftext|>