<commit_before>package main

// TODO:
//  - then, forward-emulate one instruction (via code hook) to get next insn

import (
	"bufio"
	"debug/pe"
	"fmt"
	"github.com/anmitsu/go-shlex"
	"github.com/codegangsta/cli"
	uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"
	peloader "github.com/williballenthin/CrystalTiger/loader/pe"
	"github.com/williballenthin/CrystalTiger/utils"
	"github.com/williballenthin/CrystalTiger/utils/hexdump"
	"github.com/williballenthin/CrystalTiger/workspace"
	"log"
	"os"
	"strconv"
	"strings"
)

var inputFlag = cli.StringFlag{
	Name:  "input_file",
	Usage: "file to decode",
}

var outputFlag = cli.StringFlag{
	Name:  "output_file",
	Usage: "where to write decoded data",
}

var verboseFlag = cli.BoolFlag{
	Name:  "verbose",
	Usage: "print debugging output",
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func getLine() (string, error) {
	bio := bufio.NewReader(os.Stdin)
	// TODO: there might be really long lines here that we should handle
	line, _, e := bio.ReadLine()
	return string(line), e
}

// parse a string containing a hexidecimal number.
// may have prefix '0x', or not
func parseNumber(s string) (uint64, error) {
	if strings.HasPrefix(s, "0x") {
		s = s[2:]
	}
	return strconv.ParseUint(s, 0x10, 64)
}

func doloop(emu *workspace.Emulator) error {
	done := false
	for !done {
		s, _, e := emu.FormatAddress(emu.GetInstructionPointer())
		check(e)
		fmt.Printf("next:\n" + s)

		fmt.Printf("%08x >", emu.GetInstructionPointer())
		line, e := getLine()
		if e != nil {
			line = ""
			done = true
		}
		words, e := shlex.Split(line, true)
		check(e)
		if e != nil {
			return e
		}
		if len(words) == 0 {
			words = []string{""}
		}

		switch words[0] {
		case "":
			break
		case "q":
			done = true
			break
		case "?", "h", "help":
			fmt.Printf("help:\n")
			fmt.Printf("  q - quit\n")
			fmt.Printf("  ?/h/help - help\n")
			fmt.Printf("  t/stepo - step into\n")
			fmt.Printf("  p/stepi - step over\n")
			fmt.Printf("  r - show register(s)\n")
			fmt.Printf("  u - disassemble\n")
			break
		case "t", "stepi":
			e = emu.StepInto()
			check(e)
			break
		case "p", "stepo":
			e = emu.StepOver()
			check(e)
			break
		case "r":
			eax, e := emu.RegRead(uc.X86_REG_EAX)
			ebx, e := emu.RegRead(uc.X86_REG_EBX)
			ecx, e := emu.RegRead(uc.X86_REG_ECX)
			edx, e := emu.RegRead(uc.X86_REG_EDX)
			esi, e := emu.RegRead(uc.X86_REG_ESI)
			edi, e := emu.RegRead(uc.X86_REG_EDI)
			ebp, e := emu.RegRead(uc.X86_REG_EBP)
			esp, e := emu.RegRead(uc.X86_REG_ESP)
			eip, e := emu.RegRead(uc.X86_REG_EIP)
			check(e)

			fmt.Printf("eax: 0x%08x\n", eax)
			fmt.Printf("ebx: 0x%08x\n", ebx)
			fmt.Printf("ecx: 0x%08x\n", ecx)
			fmt.Printf("edx: 0x%08x\n", edx)
			fmt.Printf("esi: 0x%08x\n", esi)
			fmt.Printf("edi: 0x%08x\n", edi)
			fmt.Printf("ebp: 0x%08x\n", ebp)
			fmt.Printf("esp: 0x%08x\n", esp)
			fmt.Printf("eip: 0x%08x\n", eip)
			// TODO: show flags
			break
		case "u":
			// usage: u [addr|. [length]]
			addr := emu.GetInstructionPointer()
			length := uint64(3)

			if len(words) > 1 {
				// using '.' refers to the current PC value
				if words[1] != "." {
					// otherwise, parse int
					addrInt, e := parseNumber(words[1])
					check(e)
					addr = workspace.VA(addrInt)
				}
			}

			if len(words) > 2 {
				length, e = parseNumber(words[2])
				check(e)
			}

			for i := uint64(0); i < length; i++ {
				s, read, e := emu.FormatAddress(addr)
				check(e)
				fmt.Printf(s)
				addr = workspace.VA(uint64(addr) + read)
			}
			break
		case "dc":
			// usage: dc [addr|. [length]]
			addr := emu.GetInstructionPointer()
			length := uint64(0x40)

			if len(words) > 1 {
				// using '.' refers to the current PC value
				if words[1] != "." {
					// otherwise, parse int
					addrInt, e := parseNumber(words[1])
					check(e)
					addr = workspace.VA(addrInt)
				}
			}

			if len(words) > 2 {
				length, e = parseNumber(words[2])
				check(e)
			}

			b, e := emu.MemRead(addr, length)
			check(e)

			e = hexdump.DumpFromOffset(b, uint64(addr), os.Stdout)
			check(e)

			break
		}
	}

	return nil
}

func doit(path string) error {
	f, e := pe.Open(path)
	check(e)

	ws, e := workspace.New(workspace.ARCH_X86, workspace.MODE_32)
	check(e)

	loader, e := peloader.New(path, f)
	check(e)

	m, e := loader.Load(ws)
	check(e)

	e = ws.Disassemble(m.EntryPoint, 0x30, os.Stdout)
	check(e)

	emu, e := ws.GetEmulator()
	check(e)

	emu.SetInstructionPointer(m.EntryPoint)

	log.Printf("emudbg: start: 0x%x", emu.GetInstructionPointer())

	//e = emu.RunTo(m.EntryPoint + 0x7)
	e = emu.RunTo(m.EntryPoint + 0xe)
	check(e)
	/*
		log.Printf("emudbg: run: 0x%x", emu.GetInstructionPointer())
		e = emu.StepInto()
		check(e)
		log.Printf("emudbg: step into: 0x%x", emu.GetInstructionPointer())
		e = emu.StepInto()
		check(e)
		log.Printf("emudbg: step into: 0x%x", emu.GetInstructionPointer())
	*/

	e = doloop(emu)
	check(e)

	return nil
}

func doesPathExist(p string) bool {
	_, e := os.Stat(p)
	if e == nil {
		return true
	}
	if os.IsNotExist(e) {
		return false
	}
	return true
}

func main() {
	app := cli.NewApp()
	app.Version = "0.1"
	app.Name = "crystal-tiger-emulator-debugger"
	app.Usage = "Interactively emulate a binary."
	app.Flags = []cli.Flag{inputFlag}
	app.Action = func(c *cli.Context) {
		if utils.CheckRequiredArgs(c, []cli.StringFlag{inputFlag}) != nil {
			return
		}

		inputFile := c.String("input_file")
		if !doesPathExist(inputFile) {
			log.Printf("Error: file %s must exist", inputFile)
			return
		}

		check(doit(inputFile))
	}
	fmt.Printf("%s\n", os.Args)
	app.Run(os.Args)
}
<commit_msg>emudbg: resolve some registers when parsing addrs/lengths<commit_after>package main

// TODO:
//  - then, forward-emulate one instruction (via code hook) to get next insn

import (
	"bufio"
	"debug/pe"
	"fmt"
	"github.com/anmitsu/go-shlex"
	"github.com/codegangsta/cli"
	uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"
	peloader "github.com/williballenthin/CrystalTiger/loader/pe"
	"github.com/williballenthin/CrystalTiger/utils"
	"github.com/williballenthin/CrystalTiger/utils/hexdump"
	"github.com/williballenthin/CrystalTiger/workspace"
	"log"
	"os"
	"strconv"
	"strings"
)

var inputFlag = cli.StringFlag{
	Name:  "input_file",
	Usage: "file to decode",
}

var outputFlag = cli.StringFlag{
	Name:  "output_file",
	Usage: "where to write decoded data",
}

var verboseFlag = cli.BoolFlag{
	Name:  "verbose",
	Usage: "print debugging output",
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func getLine() (string, error) {
	bio := bufio.NewReader(os.Stdin)
	// TODO: there might be really long lines here that we should handle
	line, _, e := bio.ReadLine()
	return string(line), e
}

// parse a string containing a hexidecimal number.
// may have prefix '0x', or not
func parseNumber(s string) (uint64, error) {
	if strings.HasPrefix(s, "0x") {
		s = s[2:]
	}
	return strconv.ParseUint(s, 0x10, 64)
}

func resolveNumber(emu *workspace.Emulator, s string) (uint64, error) {
	// using '.' refers to the current PC value
	if s == "." {
		return uint64(emu.GetInstructionPointer()), nil
	} else if s == "esp" {
		return uint64(emu.GetStackPointer()), nil
	} else if s == "eip" {
		return uint64(emu.GetInstructionPointer()), nil
	} else {
		// otherwise, parse int
		addrInt, e := parseNumber(s)
		check(e)
		return addrInt, nil
	}
}

func doloop(emu *workspace.Emulator) error {
	done := false
	for !done {
		s, _, e := emu.FormatAddress(emu.GetInstructionPointer())
		check(e)
		fmt.Printf("next:\n" + s)

		fmt.Printf("%08x >", emu.GetInstructionPointer())
		line, e := getLine()
		if e != nil {
			line = ""
			done = true
		}
		words, e := shlex.Split(line, true)
		check(e)
		if e != nil {
			return e
		}
		if len(words) == 0 {
			words = []string{""}
		}

		switch words[0] {
		case "":
			break
		case "q":
			done = true
			break
		case "?", "h", "help":
			fmt.Printf("help:\n")
			fmt.Printf("  q - quit\n")
			fmt.Printf("  ?/h/help - help\n")
			fmt.Printf("  t/stepo - step into\n")
			fmt.Printf("  p/stepi - step over\n")
			fmt.Printf("  r - show register(s)\n")
			fmt.Printf("  u - disassemble\n")
			break
		case "t", "stepi":
			e = emu.StepInto()
			check(e)
			break
		case "p", "stepo":
			e = emu.StepOver()
			check(e)
			break
		case "r":
			eax, e := emu.RegRead(uc.X86_REG_EAX)
			ebx, e := emu.RegRead(uc.X86_REG_EBX)
			ecx, e := emu.RegRead(uc.X86_REG_ECX)
			edx, e := emu.RegRead(uc.X86_REG_EDX)
			esi, e := emu.RegRead(uc.X86_REG_ESI)
			edi, e := emu.RegRead(uc.X86_REG_EDI)
			ebp, e := emu.RegRead(uc.X86_REG_EBP)
			esp, e := emu.RegRead(uc.X86_REG_ESP)
			eip, e := emu.RegRead(uc.X86_REG_EIP)
			check(e)

			fmt.Printf("eax: 0x%08x\n", eax)
			fmt.Printf("ebx: 0x%08x\n", ebx)
			fmt.Printf("ecx: 0x%08x\n", ecx)
			fmt.Printf("edx: 0x%08x\n", edx)
			fmt.Printf("esi: 0x%08x\n", esi)
			fmt.Printf("edi: 0x%08x\n", edi)
			fmt.Printf("ebp: 0x%08x\n", ebp)
			fmt.Printf("esp: 0x%08x\n", esp)
			fmt.Printf("eip: 0x%08x\n", eip)
			// TODO: show flags
			break
		case "u":
			// usage: u [addr|. [num instructions]]
			addr := emu.GetInstructionPointer()
			length := uint64(3)

			if len(words) > 1 {
				addrInt, e := resolveNumber(emu, words[1])
				check(e)
				addr = workspace.VA(addrInt)
			}

			if len(words) > 2 {
				length, e = resolveNumber(emu, words[2])
				check(e)
			}

			for i := uint64(0); i < length; i++ {
				s, read, e := emu.FormatAddress(addr)
				check(e)
				fmt.Printf(s)
				addr = workspace.VA(uint64(addr) + read)
			}
			break
		case "dc":
			// usage: dc [addr|. [num bytes]]
			addr := emu.GetInstructionPointer()
			length := uint64(0x40)

			if len(words) > 1 {
				addrInt, e := resolveNumber(emu, words[1])
				check(e)
				addr = workspace.VA(addrInt)
			}

			if len(words) > 2 {
				length, e = resolveNumber(emu, words[2])
				check(e)
			}

			b, e := emu.MemRead(addr, length)
			check(e)

			e = hexdump.DumpFromOffset(b, uint64(addr), os.Stdout)
			check(e)

			break
		}
	}

	return nil
}

func doit(path string) error {
	f, e := pe.Open(path)
	check(e)

	ws, e := workspace.New(workspace.ARCH_X86, workspace.MODE_32)
	check(e)

	loader, e := peloader.New(path, f)
	check(e)

	m, e := loader.Load(ws)
	check(e)

	e = ws.Disassemble(m.EntryPoint, 0x30, os.Stdout)
	check(e)

	emu, e := ws.GetEmulator()
	check(e)

	emu.SetInstructionPointer(m.EntryPoint)

	log.Printf("emudbg: start: 0x%x", emu.GetInstructionPointer())

	//e = emu.RunTo(m.EntryPoint + 0x7)
	e = emu.RunTo(m.EntryPoint + 0xe)
	check(e)
	/*
		log.Printf("emudbg: run: 0x%x", emu.GetInstructionPointer())
		e = emu.StepInto()
		check(e)
		log.Printf("emudbg: step into: 0x%x", emu.GetInstructionPointer())
		e = emu.StepInto()
		check(e)
		log.Printf("emudbg: step into: 0x%x", emu.GetInstructionPointer())
	*/

	e = doloop(emu)
	check(e)

	return nil
}

func doesPathExist(p string) bool {
	_, e := os.Stat(p)
	if e == nil {
		return true
	}
	if os.IsNotExist(e) {
		return false
	}
	return true
}

func main() {
	app := cli.NewApp()
	app.Version = "0.1"
	app.Name = "crystal-tiger-emulator-debugger"
	app.Usage = "Interactively emulate a binary."
	app.Flags = []cli.Flag{inputFlag}
	app.Action = func(c *cli.Context) {
		if utils.CheckRequiredArgs(c, []cli.StringFlag{inputFlag}) != nil {
			return
		}

		inputFile := c.String("input_file")
		if !doesPathExist(inputFile) {
			log.Printf("Error: file %s must exist", inputFile)
			return
		}

		check(doit(inputFile))
	}
	fmt.Printf("%s\n", os.Args)
	app.Run(os.Args)
}
<|endoftext|>


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

package docker

import (
	dockerClient "github.com/fsouza/go-dockerclient"
	"github.com/globocom/tsuru/action"
	rtesting "github.com/globocom/tsuru/router/testing"
	"github.com/globocom/tsuru/testing"
	"launchpad.net/gocheck"
)

func (s *S) TestCreateContainerName(c *gocheck.C) {
	c.Assert(createContainer.Name, gocheck.Equals, "create-container")
}

func (s *S) TestCreateContainerForward(c *gocheck.C) {
	err := s.newImage()
	c.Assert(err, gocheck.IsNil)
	client, err := dockerClient.NewClient(s.server.URL())
	c.Assert(err, gocheck.IsNil)
	images, err := client.ListImages(true)
	c.Assert(err, gocheck.IsNil)
	cmds := []string{"ps", "-ef"}
	context := action.FWContext{Params: []interface{}{images[0].ID, cmds}}
	r, err := createContainer.Forward(context)
	c.Assert(err, gocheck.IsNil)
	cont := r.(container)
	defer cont.remove()
	c.Assert(cont, gocheck.FitsTypeOf, container{})
}

func (s *S) TestCreateContainerBackward(c *gocheck.C) {
	cont := container{ID: "ble"}
	context := action.BWContext{Params: []interface{}{cont}}
	createContainer.Backward(context)
}

func (s *S) TestInsertContainerName(c *gocheck.C) {
	c.Assert(insertContainer.Name, gocheck.Equals, "insert-container")
}

func (s *S) TestInsertContainerForward(c *gocheck.C) {
	cont := container{ID: "someid"}
	context := action.FWContext{Params: []interface{}{cont}}
	r, err := insertContainer.Forward(context)
	c.Assert(err, gocheck.IsNil)
	coll := s.conn.Collection(s.collName)
	defer coll.RemoveId(cont.ID)
	cont = r.(container)
	var retrieved container
	err = coll.FindId(cont.ID).One(&retrieved)
	c.Assert(retrieved.ID, gocheck.Equals, cont.ID)
	c.Assert(retrieved.Status, gocheck.Equals, "created")
	c.Assert(cont, gocheck.FitsTypeOf, container{})
}

func (s *S) TestInsertContainerBackward(c *gocheck.C) {
	cont := container{ID: "someid"}
	coll := s.conn.Collection(s.collName)
	err := coll.Insert(&cont)
	c.Assert(err, gocheck.IsNil)
	context := action.BWContext{Params: []interface{}{cont}}
	insertContainer.Backward(context)
	err = coll.FindId(cont.ID).One(&cont)
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, "not found")
}

func (s *S) TestAddRouteName(c *gocheck.C) {
	c.Assert(addRoute.Name, gocheck.Equals, "add-route")
}

func (s *S) TestAddRouteForward(c *gocheck.C) {
	app := testing.NewFakeApp("myapp", "python", 1)
	rtesting.FakeRouter.AddBackend(app.GetName())
	defer rtesting.FakeRouter.RemoveBackend(app.GetName())
	cont := container{ID: "ble", AppName: app.GetName()}
	context := action.FWContext{Params: []interface{}{cont}}
	r, err := addRoute.Forward(context)
	c.Assert(err, gocheck.IsNil)
	c.Assert(r, gocheck.IsNil)
	hasRoute := rtesting.FakeRouter.HasRoute(app.GetName(), cont.getAddress())
	c.Assert(hasRoute, gocheck.Equals, true)
}

func (s *S) TestSetIpName(c *gocheck.C) {
	c.Assert(setIp.Name, gocheck.Equals, "set-ip")
}

func (s *S) TestSetIp(c *gocheck.C) {
	err := s.newImage()
	c.Assert(err, gocheck.IsNil)
	conta, err := s.newContainer()
	c.Assert(err, gocheck.IsNil)
	defer rtesting.FakeRouter.RemoveBackend(conta.AppName)
	cont := *conta
	context := action.FWContext{Params: []interface{}{cont}}
	r, err := setIp.Forward(context)
	c.Assert(err, gocheck.IsNil)
	cont = r.(container)
	c.Assert(cont, gocheck.FitsTypeOf, container{})
	c.Assert(cont.ip, gocheck.Not(gocheck.Equals), "")
}

func (s *S) TestSetHostPortName(c *gocheck.C) {
	c.Assert(setHostPort.Name, gocheck.Equals, "set-host-port")
}
<commit_msg>docker: fixed test name.<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package docker

import (
	dockerClient "github.com/fsouza/go-dockerclient"
	"github.com/globocom/tsuru/action"
	rtesting "github.com/globocom/tsuru/router/testing"
	"github.com/globocom/tsuru/testing"
	"launchpad.net/gocheck"
)

func (s *S) TestCreateContainerName(c *gocheck.C) {
	c.Assert(createContainer.Name, gocheck.Equals, "create-container")
}

func (s *S) TestCreateContainerForward(c *gocheck.C) {
	err := s.newImage()
	c.Assert(err, gocheck.IsNil)
	client, err := dockerClient.NewClient(s.server.URL())
	c.Assert(err, gocheck.IsNil)
	images, err := client.ListImages(true)
	c.Assert(err, gocheck.IsNil)
	cmds := []string{"ps", "-ef"}
	context := action.FWContext{Params: []interface{}{images[0].ID, cmds}}
	r, err := createContainer.Forward(context)
	c.Assert(err, gocheck.IsNil)
	cont := r.(container)
	defer cont.remove()
	c.Assert(cont, gocheck.FitsTypeOf, container{})
}

func (s *S) TestCreateContainerBackward(c *gocheck.C) {
	cont := container{ID: "ble"}
	context := action.BWContext{Params: []interface{}{cont}}
	createContainer.Backward(context)
}

func (s *S) TestInsertContainerName(c *gocheck.C) {
	c.Assert(insertContainer.Name, gocheck.Equals, "insert-container")
}

func (s *S) TestInsertContainerForward(c *gocheck.C) {
	cont := container{ID: "someid"}
	context := action.FWContext{Params: []interface{}{cont}}
	r, err := insertContainer.Forward(context)
	c.Assert(err, gocheck.IsNil)
	coll := s.conn.Collection(s.collName)
	defer coll.RemoveId(cont.ID)
	cont = r.(container)
	var retrieved container
	err = coll.FindId(cont.ID).One(&retrieved)
	c.Assert(retrieved.ID, gocheck.Equals, cont.ID)
	c.Assert(retrieved.Status, gocheck.Equals, "created")
	c.Assert(cont, gocheck.FitsTypeOf, container{})
}

func (s *S) TestInsertContainerBackward(c *gocheck.C) {
	cont := container{ID: "someid"}
	coll := s.conn.Collection(s.collName)
	err := coll.Insert(&cont)
	c.Assert(err, gocheck.IsNil)
	context := action.BWContext{Params: []interface{}{cont}}
	insertContainer.Backward(context)
	err = coll.FindId(cont.ID).One(&cont)
	c.Assert(err, gocheck.NotNil)
	c.Assert(err.Error(), gocheck.Equals, "not found")
}

func (s *S) TestAddRouteName(c *gocheck.C) {
	c.Assert(addRoute.Name, gocheck.Equals, "add-route")
}

func (s *S) TestAddRouteForward(c *gocheck.C) {
	app := testing.NewFakeApp("myapp", "python", 1)
	rtesting.FakeRouter.AddBackend(app.GetName())
	defer rtesting.FakeRouter.RemoveBackend(app.GetName())
	cont := container{ID: "ble", AppName: app.GetName()}
	context := action.FWContext{Params: []interface{}{cont}}
	r, err := addRoute.Forward(context)
	c.Assert(err, gocheck.IsNil)
	c.Assert(r, gocheck.IsNil)
	hasRoute := rtesting.FakeRouter.HasRoute(app.GetName(), cont.getAddress())
	c.Assert(hasRoute, gocheck.Equals, true)
}

func (s *S) TestSetIpName(c *gocheck.C) {
	c.Assert(setIp.Name, gocheck.Equals, "set-ip")
}

func (s *S) TestSetIpForward(c *gocheck.C) {
	err := s.newImage()
	c.Assert(err, gocheck.IsNil)
	conta, err := s.newContainer()
	c.Assert(err, gocheck.IsNil)
	defer rtesting.FakeRouter.RemoveBackend(conta.AppName)
	cont := *conta
	context := action.FWContext{Params: []interface{}{cont}}
	r, err := setIp.Forward(context)
	c.Assert(err, gocheck.IsNil)
	cont = r.(container)
	c.Assert(cont, gocheck.FitsTypeOf, container{})
	c.Assert(cont.ip, gocheck.Not(gocheck.Equals), "")
}

func (s *S) TestSetHostPortName(c *gocheck.C) {
	c.Assert(setHostPort.Name, gocheck.Equals, "set-host-port")
}
<|endoftext|>


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

package lucicfg

import (
	"fmt"

	"go.starlark.net/starlark"
)

const (
	// Version is the version of lucicfg tool.
	//
	// It ends up in CLI output and in User-Agent headers.
	Version = "1.9.0"

	// UserAgent is used for User-Agent header in HTTP requests from lucicfg.
	UserAgent = "lucicfg v" + Version
)

func init() {
	// See //internal/lucicfg.star.
	declNative("version", func(call nativeCall) (starlark.Value, error) {
		if err := call.unpack(0); err != nil {
			return nil, err
		}
		var major, minor, rev int
		_, err := fmt.Sscanf(Version, "%d.%d.%d", &major, &minor, &rev)
		if err != nil {
			panic(err)
		}
		return starlark.Tuple{
			starlark.MakeInt(major),
			starlark.MakeInt(minor),
			starlark.MakeInt(rev),
		}, nil
	})
}
<commit_msg>lucicfg: bump version to 1.10.0 to signal minor incompatibility.<commit_after>// Copyright 2018 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package lucicfg

import (
	"fmt"

	"go.starlark.net/starlark"
)

const (
	// Version is the version of lucicfg tool.
	//
	// It ends up in CLI output and in User-Agent headers.
	Version = "1.10.0"

	// UserAgent is used for User-Agent header in HTTP requests from lucicfg.
	UserAgent = "lucicfg v" + Version
)

func init() {
	// See //internal/lucicfg.star.
	declNative("version", func(call nativeCall) (starlark.Value, error) {
		if err := call.unpack(0); err != nil {
			return nil, err
		}
		var major, minor, rev int
		_, err := fmt.Sscanf(Version, "%d.%d.%d", &major, &minor, &rev)
		if err != nil {
			panic(err)
		}
		return starlark.Tuple{
			starlark.MakeInt(major),
			starlark.MakeInt(minor),
			starlark.MakeInt(rev),
		}, nil
	})
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/url"
	"os"

	"github.com/spf13/cobra"

	"github.com/lxc/lxd/client"
)

type cmdImport struct {
	global *cmdGlobal

	flagForce   bool
	flagProject string
}

func (c *cmdImport) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = "import <container name>"
	cmd.Short = "Import existing containers"
	cmd.Long = `Description:
  Import existing containers

  This command is mostly used for disaster recovery. It lets you attempt
  to recreate all database entries for containers that LXD no longer knows
  about.

  To do so, you must first mount your container storage at the expected
  path inside the storage-pools directory. Once that's in place,
  ` + "`lxd import`" + ` can be called for each individual container.
`
	cmd.RunE = c.Run
	cmd.Flags().BoolVarP(&c.flagForce, "force", "f", false, "Force the import (override existing data or partial restore)")
	cmd.Flags().StringVar(&c.flagProject, "project", "", "Specify the project")

	return cmd
}

func (c *cmdImport) Run(cmd *cobra.Command, args []string) error {
	// Quick checks.
	if len(args) < 1 {
		cmd.Help()

		if len(args) == 0 {
			return nil
		}

		return fmt.Errorf("Missing required arguments")
	}

	// Only root should run this
	if os.Geteuid() != 0 {
		return fmt.Errorf("This must be run as root")
	}

	name := args[0]
	req := map[string]interface{}{
		"name":  name,
		"force": c.flagForce,
	}

	d, err := lxd.ConnectLXDUnix("", nil)
	if err != nil {
		return err
	}

	v := url.Values{}
	v.Set("project", c.flagProject)

	_, _, err = d.RawQuery("POST", fmt.Sprintf("/internal/containers?%s", v.Encode()), req, "")
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>lxd/main/import: Modify lxd import to error with instructions to use lxd recover command<commit_after>package main

import (
	"fmt"

	"github.com/spf13/cobra"
)

type cmdImport struct {
	global *cmdGlobal
}

func (c *cmdImport) Command() *cobra.Command {
	cmd := &cobra.Command{}
	cmd.Use = "import"
	cmd.Short = `Command has been replaced with "lxd recover"`
	cmd.Long = `Description:
  This command has been replaced with "lxd recover". Please use that instead.
`
	cmd.RunE = c.Run
	return cmd
}

func (c *cmdImport) Run(cmd *cobra.Command, args []string) error {
	return fmt.Errorf(`Command has been replaced with "lxd recover"`)
}
<|endoftext|>


<commit_before>package mackerelplugin

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"math"
	"os"
	"reflect"
	"strconv"
	"time"
)

type Metrics struct {
	Name    string  `json:"name"`
	Label   string  `json:"label"`
	Diff    bool    `json:"diff"`
	Type    string  `json:"type"`
	Stacked bool    `json:"stacked"`
	Scale   float64 `json:"scale"`
}

type Graphs struct {
	Label   string    `json:"label"`
	Unit    string    `json:"unit"`
	Metrics []Metrics `json:"metrics"`
}

type Plugin interface {
	FetchMetrics() (map[string]interface{}, error)
	GraphDefinition() map[string]Graphs
}

type MackerelPlugin struct {
	Plugin
	Tempfile string
}

func NewMackerelPlugin(plugin Plugin) MackerelPlugin {
	mp := MackerelPlugin{plugin, "/tmp/mackerel-plugin-default"}
	return mp
}

func (h *MackerelPlugin) printValue(w io.Writer, key string, value interface{}, now time.Time) {
	if reflect.TypeOf(value).String() == "float64" && (math.IsNaN(value.(float64)) || math.IsInf(value.(float64), 0)) {
		log.Printf("Invalid value: key = %s, value = %f\n", key, value)
		return
	}

	switch reflect.TypeOf(value).String() {
	case "uint32":
		fmt.Fprintf(w, "%s\t%d\t%d\n", key, value.(uint32), now.Unix())
	case "uint64":
		fmt.Fprintf(w, "%s\t%d\t%d\n", key, value.(uint64), now.Unix())
	default:
		fmt.Fprintf(w, "%s\t%f\t%d\n", key, value, now.Unix())
	}
}

func (h *MackerelPlugin) fetchLastValues() (map[string]interface{}, time.Time, error) {
	lastTime := time.Now()

	f, err := os.Open(h.Tempfilename())
	if err != nil {
		if os.IsNotExist(err) {
			return nil, lastTime, nil
		}
		return nil, lastTime, err
	}
	defer f.Close()

	stat := make(map[string]interface{})
	decoder := json.NewDecoder(f)
	err = decoder.Decode(&stat)
	lastTime = time.Unix(stat["_lastTime"].(int64), 0)
	if err != nil {
		return stat, lastTime, err
	}
	return stat, lastTime, nil
}

func (h *MackerelPlugin) saveValues(values map[string]interface{}, now time.Time) error {
	f, err := os.Create(h.Tempfilename())
	if err != nil {
		return err
	}
	defer f.Close()

	values["_lastTime"] = float64(now.Unix())
	encoder := json.NewEncoder(f)
	err = encoder.Encode(values)
	if err != nil {
		return err
	}

	return nil
}

func (h *MackerelPlugin) calcDiff(value float64, now time.Time, lastValue float64, lastTime time.Time) (float64, error) {
	diffTime := now.Unix() - lastTime.Unix()
	if diffTime > 600 {
		return 0, errors.New("Too long duration")
	}

	diff := (value - lastValue) * 60 / float64(diffTime)

	return diff, nil
}

func (h *MackerelPlugin) calcDiffUint32(value uint32, now time.Time, lastValue uint32, lastTime time.Time, lastDiff float64) (float64, error) {
	diffTime := now.Unix() - lastTime.Unix()
	if diffTime > 600 {
		return 0, errors.New("Too long duration")
	}

	diff := float64((value-lastValue)*60) / float64(diffTime)

	if lastValue < value || diff < lastDiff*10 {
		return diff, nil
	}
	return 0.0, errors.New("Counter seems to be reseted.")

}

func (h *MackerelPlugin) calcDiffUint64(value uint64, now time.Time, lastValue uint64, lastTime time.Time, lastDiff float64) (float64, error) {
	diffTime := now.Unix() - lastTime.Unix()
	if diffTime > 600 {
		return 0, errors.New("Too long duration")
	}

	diff := float64((value-lastValue)*60) / float64(diffTime)

	if lastValue < value || diff < lastDiff*10 {
		return diff, nil
	}
	return 0.0, errors.New("Counter seems to be reseted.")
}

func (h *MackerelPlugin) Tempfilename() string {
	return h.Tempfile
}

func (h *MackerelPlugin) OutputValues() {
	now := time.Now()
	stat, err := h.FetchMetrics()
	if err != nil {
		log.Fatalln("OutputValues: ", err)
	}

	lastStat, lastTime, err := h.fetchLastValues()
	if err != nil {
		log.Println("fetchLastValues (ignore):", err)
	}

	for key, graph := range h.GraphDefinition() {
		for _, metric := range graph.Metrics {
			var value interface{}
			value = stat[metric.Name]

			switch reflect.TypeOf(value).String() {
			case "string":
				switch metric.Type {
				case "uint64":
					value, _ = strconv.ParseUint(value.(string), 10, 64)
				case "float64":
					value, _ = strconv.ParseFloat(value.(string), 64)
				}
			}

			if metric.Diff {
				_, ok := lastStat[metric.Name]
				if ok {
					lastDiff := lastStat[".last_diff."+metric.Name]
					switch metric.Type {
					case "uint32":
						value, err = h.calcDiffUint32(value.(uint32), now, lastStat[metric.Name].(uint32), lastTime, lastDiff.(float64))
						stat[".last_diff."+metric.Name] = value
					case "uint64":
						value, err = h.calcDiffUint64(value.(uint64), now, lastStat[metric.Name].(uint64), lastTime, lastDiff.(float64))
						stat[".last_diff."+metric.Name] = value
					default:
						value, err = h.calcDiff(value.(float64), now, lastStat[metric.Name].(float64), lastTime)
					}
					if err != nil {
						log.Println("OutputValues: ", err)
					}
				} else {
					log.Printf("%s is not exist at last fetch\n", metric.Name)
				}
			}

			if metric.Scale != 0 {
				switch metric.Type {
				case "uint32":
					value = value.(uint32) * uint32(metric.Scale)
				case "uint64":
					value = value.(uint64) * uint64(metric.Scale)
				default:
					value = value.(float64) * metric.Scale
				}
			}

			h.printValue(os.Stdout, key+"."+metric.Name, value, now)
		}
	}

	err = h.saveValues(stat, now)
	if err != nil {
		log.Fatalf("saveValues: ", err)
	}

}

type GraphDef struct {
	Graphs map[string]Graphs `json:"graphs"`
}

func (h *MackerelPlugin) OutputDefinitions() {
	fmt.Println("# mackerel-agent-plugin")
	var graphs GraphDef
	graphs.Graphs = h.GraphDefinition()

	b, err := json.Marshal(graphs)
	if err != nil {
		log.Fatalln("OutputDefinitions: ", err)
	}
	fmt.Println(string(b))
}
<commit_msg>error handling for nil value<commit_after>package mackerelplugin

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"log"
	"math"
	"os"
	"reflect"
	"strconv"
	"time"
)

type Metrics struct {
	Name    string  `json:"name"`
	Label   string  `json:"label"`
	Diff    bool    `json:"diff"`
	Type    string  `json:"type"`
	Stacked bool    `json:"stacked"`
	Scale   float64 `json:"scale"`
}

type Graphs struct {
	Label   string    `json:"label"`
	Unit    string    `json:"unit"`
	Metrics []Metrics `json:"metrics"`
}

type Plugin interface {
	FetchMetrics() (map[string]interface{}, error)
	GraphDefinition() map[string]Graphs
}

type MackerelPlugin struct {
	Plugin
	Tempfile string
}

func NewMackerelPlugin(plugin Plugin) MackerelPlugin {
	mp := MackerelPlugin{plugin, "/tmp/mackerel-plugin-default"}
	return mp
}

func (h *MackerelPlugin) printValue(w io.Writer, key string, value interface{}, now time.Time) {
	valueType := reflect.TypeOf(value)
	if valueType == nil {
		return
	}
	if valueType.String() == "float64" && (math.IsNaN(value.(float64)) || math.IsInf(value.(float64), 0)) {
		log.Printf("Invalid value: key = %s, value = %f\n", key, value)
		return
	}

	switch valueType.String() {
	case "uint32":
		fmt.Fprintf(w, "%s\t%d\t%d\n", key, value.(uint32), now.Unix())
	case "uint64":
		fmt.Fprintf(w, "%s\t%d\t%d\n", key, value.(uint64), now.Unix())
	default:
		fmt.Fprintf(w, "%s\t%f\t%d\n", key, value, now.Unix())
	}
}

func (h *MackerelPlugin) fetchLastValues() (map[string]interface{}, time.Time, error) {
	lastTime := time.Now()

	f, err := os.Open(h.Tempfilename())
	if err != nil {
		if os.IsNotExist(err) {
			return nil, lastTime, nil
		}
		return nil, lastTime, err
	}
	defer f.Close()

	stat := make(map[string]interface{})
	decoder := json.NewDecoder(f)
	err = decoder.Decode(&stat)
	lastTime = time.Unix(stat["_lastTime"].(int64), 0)
	if err != nil {
		return stat, lastTime, err
	}
	return stat, lastTime, nil
}

func (h *MackerelPlugin) saveValues(values map[string]interface{}, now time.Time) error {
	f, err := os.Create(h.Tempfilename())
	if err != nil {
		return err
	}
	defer f.Close()

	values["_lastTime"] = float64(now.Unix())
	encoder := json.NewEncoder(f)
	err = encoder.Encode(values)
	if err != nil {
		return err
	}

	return nil
}

func (h *MackerelPlugin) calcDiff(value float64, now time.Time, lastValue float64, lastTime time.Time) (float64, error) {
	diffTime := now.Unix() - lastTime.Unix()
	if diffTime > 600 {
		return 0, errors.New("Too long duration")
	}

	diff := (value - lastValue) * 60 / float64(diffTime)

	return diff, nil
}

func (h *MackerelPlugin) calcDiffUint32(value uint32, now time.Time, lastValue uint32, lastTime time.Time, lastDiff float64) (float64, error) {
	diffTime := now.Unix() - lastTime.Unix()
	if diffTime > 600 {
		return 0, errors.New("Too long duration")
	}

	diff := float64((value-lastValue)*60) / float64(diffTime)

	if lastValue < value || diff < lastDiff*10 {
		return diff, nil
	}
	return 0.0, errors.New("Counter seems to be reseted.")

}

func (h *MackerelPlugin) calcDiffUint64(value uint64, now time.Time, lastValue uint64, lastTime time.Time, lastDiff float64) (float64, error) {
	diffTime := now.Unix() - lastTime.Unix()
	if diffTime > 600 {
		return 0, errors.New("Too long duration")
	}

	diff := float64((value-lastValue)*60) / float64(diffTime)

	if lastValue < value || diff < lastDiff*10 {
		return diff, nil
	}
	return 0.0, errors.New("Counter seems to be reseted.")
}

func (h *MackerelPlugin) Tempfilename() string {
	return h.Tempfile
}

func (h *MackerelPlugin) OutputValues() {
	now := time.Now()
	stat, err := h.FetchMetrics()
	if err != nil {
		log.Fatalln("OutputValues: ", err)
	}

	lastStat, lastTime, err := h.fetchLastValues()
	if err != nil {
		log.Println("fetchLastValues (ignore):", err)
	}

	for key, graph := range h.GraphDefinition() {
		for _, metric := range graph.Metrics {
			var value interface{}
			value = stat[metric.Name]
			valueType := reflect.TypeOf(value)
			if valueType == nil {
				continue
			}

			switch valueType.String() {
			case "string":
				switch metric.Type {
				case "uint64":
					value, _ = strconv.ParseUint(value.(string), 10, 64)
				case "float64":
					value, _ = strconv.ParseFloat(value.(string), 64)
				}
			}

			if metric.Diff {
				_, ok := lastStat[metric.Name]
				if ok {
					lastDiff := lastStat[".last_diff."+metric.Name]
					switch metric.Type {
					case "uint32":
						value, err = h.calcDiffUint32(value.(uint32), now, lastStat[metric.Name].(uint32), lastTime, lastDiff.(float64))
						stat[".last_diff."+metric.Name] = value
					case "uint64":
						value, err = h.calcDiffUint64(value.(uint64), now, lastStat[metric.Name].(uint64), lastTime, lastDiff.(float64))
						stat[".last_diff."+metric.Name] = value
					default:
						value, err = h.calcDiff(value.(float64), now, lastStat[metric.Name].(float64), lastTime)
					}
					if err != nil {
						log.Println("OutputValues: ", err)
					}
				} else {
					log.Printf("%s is not exist at last fetch\n", metric.Name)
				}
			}

			if metric.Scale != 0 {
				switch metric.Type {
				case "uint32":
					value = value.(uint32) * uint32(metric.Scale)
				case "uint64":
					value = value.(uint64) * uint64(metric.Scale)
				default:
					value = value.(float64) * metric.Scale
				}
			}

			h.printValue(os.Stdout, key+"."+metric.Name, value, now)
		}
	}

	err = h.saveValues(stat, now)
	if err != nil {
		log.Fatalf("saveValues: ", err)
	}

}

type GraphDef struct {
	Graphs map[string]Graphs `json:"graphs"`
}

func (h *MackerelPlugin) OutputDefinitions() {
	fmt.Println("# mackerel-agent-plugin")
	var graphs GraphDef
	graphs.Graphs = h.GraphDefinition()

	b, err := json.Marshal(graphs)
	if err != nil {
		log.Fatalln("OutputDefinitions: ", err)
	}
	fmt.Println(string(b))
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/takama/daemon"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"
)

// #include <wiringPi.h>
// #cgo LDFLAGS: -lwiringPi
import "C"

const (
	// CPU temperature target, degrees C
	defaultTempTarget = 65.
	hysteresis        = float32(1.)

	/* This puts our PWM frequency at 19.2 MHz / 2048 =
	/* 9.4kHz. Higher frequencies will reduce audible switching
	/* noise but will be less efficient */
	pwmClockDivisor = 2048

	/* Minimum duty cycle is the point below which the fan does
	/* not spin. This depends on both your fan and the switching
	/* transistor used. */
	defaultPwmDutyMin = 80
	pwmDutyMax        = 256

	// how often to update
	delaySeconds = 2

	// GPIO-12 on a Raspberry PI 3
	defaultPin = 26

	// name of the service
	name        = "fancontrol"
	description = "cooling fan speed control based on CPU temperature"

	// port which daemon should be listen
	port = ":9977"
)

var stdlog, errlog *log.Logger

func fanControl(pwmDutyMin int, pin int, tempTarget float32) {
	cPin := C.int(pin)
	C.wiringPiSetup()
	C.pwmSetMode(C.PWM_MODE_BAL)
	C.pinMode(cPin, C.PWM_OUTPUT)
	C.pwmSetRange(pwmDutyMax)
	C.pwmSetClock(pwmClockDivisor)
	C.pwmWrite(cPin, C.int(pwmDutyMin))
	temp := float32(0.)
	go cpuTempMonitor(func(cpuTemp float32) {
		if isCPUTempValid(cpuTemp) {
			temp = cpuTemp
		}
	})
	pwmDuty := 0
	for {
		if temp > (tempTarget + hysteresis) {
			pwmDuty = iMax(iMin(pwmDutyMax, pwmDuty+1), pwmDutyMin)
		} else if temp < (tempTarget - hysteresis) {
			pwmDuty = iMax(pwmDuty-1, 0)
			if pwmDuty < pwmDutyMin {
				pwmDuty = 0
			}
		}
		//log.Println(temp, " ", pwmDuty)
		C.pwmWrite(cPin, C.int(pwmDuty))
		time.Sleep(delaySeconds * time.Second)
	}
}

// Service has embedded daemon
type Service struct {
	daemon.Daemon
}

// Manage by daemon commands or run the daemon
func (service *Service) Manage() (string, error) {

	tempTarget := flag.Float64("temp", defaultTempTarget, "Target CPU Temperature, degrees C")
	pwmDutyMin := flag.Int("minduty", defaultPwmDutyMin, "Minimum PWM duty cycle")
	pin := flag.Int("pin", defaultPin, "PWM pin (wiringPi numbering)")
	flag.Parse()

	usage := "Usage: " + name + " install | remove | start | stop | status"
	// if received any kind of command, do it
	if flag.NArg() > 0 {
		command := os.Args[flag.NFlag()+1]
		switch command {
		case "install":
			return service.Install()
		case "remove":
			return service.Remove()
		case "start":
			return service.Start()
		case "stop":
			return service.Stop()
		case "status":
			return service.Status()
		default:
			return usage, nil
		}
	}

	go fanControl(*pwmDutyMin, *pin, float32(*tempTarget))

	// Set up channel on which to send signal notifications.
	// We must use a buffered channel or risk missing the signal
	// if we're not ready to receive when the signal is sent.
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)

	// Set up listener for defined host and port
	listener, err := net.Listen("tcp", port)
	if err != nil {
		return "Possibly was a problem with the port binding", err
	}

	// set up channel on which to send accepted connections
	listen := make(chan net.Conn, 100)
	go acceptConnection(listener, listen)

	// loop work cycle with accept connections or interrupt
	// by system signal
	for {
		select {
		case conn := <-listen:
			go handleClient(conn)
		case killSignal := <-interrupt:
			stdlog.Println("Got signal:", killSignal)
			stdlog.Println("Stoping listening on ", listener.Addr())
			listener.Close()
			if killSignal == os.Interrupt {
				return "Daemon was interrupted by system signal", nil
			}
			return "Daemon was killed", nil
		}
	}
}

// Accept a client connection and collect it in a channel
func acceptConnection(listener net.Listener, listen chan<- net.Conn) {
	for {
		conn, err := listener.Accept()
		if err != nil {
			continue
		}
		listen <- conn
	}
}

func handleClient(client net.Conn) {
	for {
		buf := make([]byte, 4096)
		numbytes, err := client.Read(buf)
		if numbytes == 0 || err != nil {
			return
		}
		client.Write(buf[:numbytes])
	}
}

func init() {
	stdlog = log.New(os.Stdout, "", 0)
	errlog = log.New(os.Stderr, "", 0)
}

func main() {
	srv, err := daemon.New(name, description, []string{}...)
	if err != nil {
		errlog.Println("Error: ", err)
		os.Exit(1)
	}
	service := &Service{srv}
	status, err := service.Manage()
	if err != nil {
		errlog.Println(status, "\nError: ", err)
		os.Exit(1)
	}
	fmt.Println(status)
}
<commit_msg>Change pinout. Increase PWM frequency. Decrease min duty cycle.<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/takama/daemon"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"
)

// #include <wiringPi.h>
// #cgo LDFLAGS: -lwiringPi
import "C"

const (
	// CPU temperature target, degrees C
	defaultTempTarget = 65.
	hysteresis        = float32(1.)

	/* This puts our PWM frequency at 19.2 MHz / 128 =
	/* 150kHz. Higher frequencies will reduce audible switching
	/* noise but will be less efficient */
	pwmClockDivisor = 128

	/* Minimum duty cycle is the point below which the fan does
	/* not spin. This depends on both your fan and the switching
	/* transistor used. */
	defaultPwmDutyMin = 20
	pwmDutyMax        = 256

	// how often to update
	delaySeconds = 2

	// GPIO-1/BCM "18"/Pin 12 on a Raspberry PI 3
	defaultPin = 1

	// name of the service
	name        = "fancontrol"
	description = "cooling fan speed control based on CPU temperature"

	// port which daemon should be listen
	port = ":9977"
)

var stdlog, errlog *log.Logger

func fanControl(pwmDutyMin int, pin int, tempTarget float32) {
	cPin := C.int(pin)
	C.wiringPiSetup()
	C.pwmSetMode(C.PWM_MODE_BAL)
	C.pinMode(cPin, C.PWM_OUTPUT)
	C.pwmSetRange(pwmDutyMax)
	C.pwmSetClock(pwmClockDivisor)
	C.pwmWrite(cPin, C.int(pwmDutyMin))
	temp := float32(0.)
	go cpuTempMonitor(func(cpuTemp float32) {
		if isCPUTempValid(cpuTemp) {
			temp = cpuTemp
		}
	})
	pwmDuty := 0
	for {
		if temp > (tempTarget + hysteresis) {
			pwmDuty = iMax(iMin(pwmDutyMax, pwmDuty+1), pwmDutyMin)
		} else if temp < (tempTarget - hysteresis) {
			pwmDuty = iMax(pwmDuty-1, 0)
			if pwmDuty < pwmDutyMin {
				pwmDuty = 0
			}
		}
		//log.Println(temp, " ", pwmDuty)
		C.pwmWrite(cPin, C.int(pwmDuty))
		time.Sleep(delaySeconds * time.Second)
	}
}

// Service has embedded daemon
type Service struct {
	daemon.Daemon
}

// Manage by daemon commands or run the daemon
func (service *Service) Manage() (string, error) {

	tempTarget := flag.Float64("temp", defaultTempTarget, "Target CPU Temperature, degrees C")
	pwmDutyMin := flag.Int("minduty", defaultPwmDutyMin, "Minimum PWM duty cycle")
	pin := flag.Int("pin", defaultPin, "PWM pin (wiringPi numbering)")
	flag.Parse()

	usage := "Usage: " + name + " install | remove | start | stop | status"
	// if received any kind of command, do it
	if flag.NArg() > 0 {
		command := os.Args[flag.NFlag()+1]
		switch command {
		case "install":
			return service.Install()
		case "remove":
			return service.Remove()
		case "start":
			return service.Start()
		case "stop":
			return service.Stop()
		case "status":
			return service.Status()
		default:
			return usage, nil
		}
	}

	go fanControl(*pwmDutyMin, *pin, float32(*tempTarget))

	// Set up channel on which to send signal notifications.
	// We must use a buffered channel or risk missing the signal
	// if we're not ready to receive when the signal is sent.
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)

	// Set up listener for defined host and port
	listener, err := net.Listen("tcp", port)
	if err != nil {
		return "Possibly was a problem with the port binding", err
	}

	// set up channel on which to send accepted connections
	listen := make(chan net.Conn, 100)
	go acceptConnection(listener, listen)

	// loop work cycle with accept connections or interrupt
	// by system signal
	for {
		select {
		case conn := <-listen:
			go handleClient(conn)
		case killSignal := <-interrupt:
			stdlog.Println("Got signal:", killSignal)
			stdlog.Println("Stoping listening on ", listener.Addr())
			listener.Close()
			if killSignal == os.Interrupt {
				return "Daemon was interrupted by system signal", nil
			}
			return "Daemon was killed", nil
		}
	}
}

// Accept a client connection and collect it in a channel
func acceptConnection(listener net.Listener, listen chan<- net.Conn) {
	for {
		conn, err := listener.Accept()
		if err != nil {
			continue
		}
		listen <- conn
	}
}

func handleClient(client net.Conn) {
	for {
		buf := make([]byte, 4096)
		numbytes, err := client.Read(buf)
		if numbytes == 0 || err != nil {
			return
		}
		client.Write(buf[:numbytes])
	}
}

func init() {
	stdlog = log.New(os.Stdout, "", 0)
	errlog = log.New(os.Stderr, "", 0)
}

func main() {
	srv, err := daemon.New(name, description, []string{}...)
	if err != nil {
		errlog.Println("Error: ", err)
		os.Exit(1)
	}
	service := &Service{srv}
	status, err := service.Manage()
	if err != nil {
		errlog.Println(status, "\nError: ", err)
		os.Exit(1)
	}
	fmt.Println(status)
}
<|endoftext|>


<commit_before>package sweetiebot

import (
	"math/rand"
	"strconv"
	"strings"

	"github.com/bwmarrin/discordgo"
)

type QuoteCommand struct {
}

func (c *QuoteCommand) Name() string {
	return "Quote"
}
func (c *QuoteCommand) Process(args []string, msg *discordgo.Message, info *GuildInfo) (string, bool) {
	if len(args) < 1 {
		l := 0
		for _, v := range info.config.Quotes {
			l += len(v)
		}
		if l <= 0 {
			return "```There are no quotes.```", false
		}
		i := rand.Intn(l)

		for k, v := range info.config.Quotes {
			if i < len(v) {
				return "**" + getUserName(k) + "**: " + v[i], false
			}
			i -= len(v)
		}
		return "```Error: invalid random quote chosen???```", false
	}

	arg := strings.ToLower(args[0])
	IDs := FindUsername(arg)
	if len(IDs) == 0 { // no matches!
		return "```Error: Could not find any usernames or aliases matching " + arg + "!```", false
	}
	if len(IDs) > 1 {
		return "```Could be any of the following users or their aliases:\n" + strings.Join(IDsToUsernames(IDs), "\n") + "```", len(IDs) > 5
	}

	q, ok := info.config.Quotes[IDs[0]]
	l := len(q)
	if !ok || l <= 0 {
		return "```That user has no quotes.```", false
	}
	i := rand.Intn(l)
	if len(args) >= 2 {
		var err error
		i, err = strconv.Atoi(args[1])
		if err != nil {
			return "```Could not parse quote index. Make sure your username is in quotes.```", false
		}
		if i >= l || i < 0 {
			return "```Invalid quote index. Use !searchquote [user] to list a user's quotes and their indexes.```", false
		}
	}
	return "**" + getUserName(IDs[0]) + "**: " + q[i], false
}
func (c *QuoteCommand) Usage(info *GuildInfo) string {
	return info.FormatUsage(c, "[user] [quote index]", "If no arguments are specified, returns a random quote. If a user is specified, returns a random quote from that user. If a quote index is specified, returns that specific quote.")
}
func (c *QuoteCommand) UsageShort() string { return "Quotes a user." }

type AddQuoteCommand struct {
}

func (c *AddQuoteCommand) Name() string {
	return "AddQuote"
}
func (c *AddQuoteCommand) Process(args []string, msg *discordgo.Message, info *GuildInfo) (string, bool) {
	if len(args) < 1 {
		return "```Must specify username.```", false
	}
	if len(args) < 2 {
		return "```Can't add a blank quote!```", false
	}

	arg := strings.ToLower(args[0])
	IDs := FindUsername(arg)
	if len(IDs) == 0 { // no matches!
		return "```Error: Could not find any usernames or aliases matching " + arg + "!```", false
	}
	if len(IDs) > 1 {
		return "```Could be any of the following users or their aliases:\n" + strings.Join(IDsToUsernames(IDs), "\n") + "```", len(IDs) > 5
	}

	if len(info.config.Quotes) == 0 {
		info.config.Quotes = make(map[uint64][]string)
	}
	info.config.Quotes[IDs[0]] = append(info.config.Quotes[IDs[0]], strings.Join(args[1:], " "))
	info.SaveConfig()
	return "```Quote added to " + getUserName(IDs[0]) + ".```", false
}
func (c *AddQuoteCommand) Usage(info *GuildInfo) string {
	return info.FormatUsage(c, "[user] [quote]", "Adds a quote to the quote database for the given user. If the username has spaces, it must be in quotes. If the user is ambiguous, sweetiebot will return all possible matches.")
}
func (c *AddQuoteCommand) UsageShort() string { return "Adds a quote." }

type RemoveQuoteCommand struct {
}

func (c *RemoveQuoteCommand) Name() string {
	return "RemoveQuote"
}
func (c *RemoveQuoteCommand) Process(args []string, msg *discordgo.Message, info *GuildInfo) (string, bool) {
	if len(args) < 1 {
		return "```Must specify username.```", false
	}
	if len(args) < 2 {
		return "```Must specify quote index. Use !searchquote to list them.```", false
	}

	arg := strings.ToLower(args[0])
	index, err := strconv.Atoi(args[1])
	if err != nil {
		return "```Error: could not parse quote index. Did you surround your username with quotes?```", false
	}

	IDs := FindUsername(arg)
	if len(IDs) == 0 { // no matches!
		return "```Error: Could not find any usernames or aliases matching " + arg + "!```", false
	}
	if len(IDs) > 1 {
		return "```Could be any of the following users or their aliases:\n" + strings.Join(IDsToUsernames(IDs), "\n") + "```", len(IDs) > 5
	}

	index--
	if index >= len(info.config.Quotes[IDs[0]]) || index < 0 {
		return "```Invalid quote index. Use !searchquote [user] to list a user's quotes and their indexes.```", false
	}
	info.config.Quotes[IDs[0]] = append(info.config.Quotes[IDs[0]][:index], info.config.Quotes[IDs[0]][index+1:]...)
	info.SaveConfig()
	return "```Deleted quote #" + strconv.Itoa(index+1) + " from " + getUserName(IDs[0]) + ".```", false
}
func (c *RemoveQuoteCommand) Usage(info *GuildInfo) string {
	return info.FormatUsage(c, "[user] [quote index]", "Removes the quote with the given quote index from the user's set of quotes. If the username has spaces, it must be in quotes. If the user is ambiguous, sweetiebot will return all possible matches.")
}
func (c *RemoveQuoteCommand) UsageShort() string { return "Removes a quote." }

type SearchQuoteCommand struct {
}

func (c *SearchQuoteCommand) Name() string {
	return "SearchQuote"
}
func (c *SearchQuoteCommand) Process(args []string, msg *discordgo.Message, info *GuildInfo) (string, bool) {
	if len(args) < 1 {
		return "```Must specify username.```", false
	}

	arg := strings.ToLower(args[0])
	IDs := FindUsername(arg)
	if len(IDs) == 0 { // no matches!
		return "```Error: Could not find any usernames or aliases matching " + arg + "!```", false
	}
	if len(IDs) > 1 {
		return "```Could be any of the following users or their aliases:\n" + strings.Join(IDsToUsernames(IDs), "\n") + "```", len(IDs) > 5
	}
	l := len(info.config.Quotes[IDs[0]])
	if l == 0 {
		return "```That user has no quotes.```", false
	}
	quotes := make([]string, l, l)
	for i := 0; i < l; i++ {
		quotes[i] = strconv.Itoa(i+1) + ". " + info.config.Quotes[IDs[0]][i]
	}
	return "All quotes for " + getUserName(IDs[0]) + ":\n" + strings.Join(quotes, "\n"), l > 6
}
func (c *SearchQuoteCommand) Usage(info *GuildInfo) string {
	return info.FormatUsage(c, "[user]", "Lists all quotes for the given user.")
}
func (c *SearchQuoteCommand) UsageShort() string { return "Finds a quote." }
<commit_msg>Fix off by one error<commit_after>package sweetiebot

import (
	"math/rand"
	"strconv"
	"strings"

	"github.com/bwmarrin/discordgo"
)

type QuoteCommand struct {
}

func (c *QuoteCommand) Name() string {
	return "Quote"
}
func (c *QuoteCommand) Process(args []string, msg *discordgo.Message, info *GuildInfo) (string, bool) {
	if len(args) < 1 {
		l := 0
		for _, v := range info.config.Quotes {
			l += len(v)
		}
		if l <= 0 {
			return "```There are no quotes.```", false
		}
		i := rand.Intn(l)

		for k, v := range info.config.Quotes {
			if i < len(v) {
				return "**" + getUserName(k) + "**: " + v[i], false
			}
			i -= len(v)
		}
		return "```Error: invalid random quote chosen???```", false
	}

	arg := strings.ToLower(args[0])
	IDs := FindUsername(arg)
	if len(IDs) == 0 { // no matches!
		return "```Error: Could not find any usernames or aliases matching " + arg + "!```", false
	}
	if len(IDs) > 1 {
		return "```Could be any of the following users or their aliases:\n" + strings.Join(IDsToUsernames(IDs), "\n") + "```", len(IDs) > 5
	}

	q, ok := info.config.Quotes[IDs[0]]
	l := len(q)
	if !ok || l <= 0 {
		return "```That user has no quotes.```", false
	}
	i := rand.Intn(l)
	if len(args) >= 2 {
		var err error
		i, err = strconv.Atoi(args[1])
		if err != nil {
			return "```Could not parse quote index. Make sure your username is in quotes.```", false
		}
		i--
		if i >= l || i < 0 {
			return "```Invalid quote index. Use !searchquote [user] to list a user's quotes and their indexes.```", false
		}
	}
	return "**" + getUserName(IDs[0]) + "**: " + q[i], false
}
func (c *QuoteCommand) Usage(info *GuildInfo) string {
	return info.FormatUsage(c, "[user] [quote index]", "If no arguments are specified, returns a random quote. If a user is specified, returns a random quote from that user. If a quote index is specified, returns that specific quote.")
}
func (c *QuoteCommand) UsageShort() string { return "Quotes a user." }

type AddQuoteCommand struct {
}

func (c *AddQuoteCommand) Name() string {
	return "AddQuote"
}
func (c *AddQuoteCommand) Process(args []string, msg *discordgo.Message, info *GuildInfo) (string, bool) {
	if len(args) < 1 {
		return "```Must specify username.```", false
	}
	if len(args) < 2 {
		return "```Can't add a blank quote!```", false
	}

	arg := strings.ToLower(args[0])
	IDs := FindUsername(arg)
	if len(IDs) == 0 { // no matches!
		return "```Error: Could not find any usernames or aliases matching " + arg + "!```", false
	}
	if len(IDs) > 1 {
		return "```Could be any of the following users or their aliases:\n" + strings.Join(IDsToUsernames(IDs), "\n") + "```", len(IDs) > 5
	}

	if len(info.config.Quotes) == 0 {
		info.config.Quotes = make(map[uint64][]string)
	}
	info.config.Quotes[IDs[0]] = append(info.config.Quotes[IDs[0]], strings.Join(args[1:], " "))
	info.SaveConfig()
	return "```Quote added to " + getUserName(IDs[0]) + ".```", false
}
func (c *AddQuoteCommand) Usage(info *GuildInfo) string {
	return info.FormatUsage(c, "[user] [quote]", "Adds a quote to the quote database for the given user. If the username has spaces, it must be in quotes. If the user is ambiguous, sweetiebot will return all possible matches.")
}
func (c *AddQuoteCommand) UsageShort() string { return "Adds a quote." }

type RemoveQuoteCommand struct {
}

func (c *RemoveQuoteCommand) Name() string {
	return "RemoveQuote"
}
func (c *RemoveQuoteCommand) Process(args []string, msg *discordgo.Message, info *GuildInfo) (string, bool) {
	if len(args) < 1 {
		return "```Must specify username.```", false
	}
	if len(args) < 2 {
		return "```Must specify quote index. Use !searchquote to list them.```", false
	}

	arg := strings.ToLower(args[0])
	index, err := strconv.Atoi(args[1])
	if err != nil {
		return "```Error: could not parse quote index. Did you surround your username with quotes?```", false
	}

	IDs := FindUsername(arg)
	if len(IDs) == 0 { // no matches!
		return "```Error: Could not find any usernames or aliases matching " + arg + "!```", false
	}
	if len(IDs) > 1 {
		return "```Could be any of the following users or their aliases:\n" + strings.Join(IDsToUsernames(IDs), "\n") + "```", len(IDs) > 5
	}

	index--
	if index >= len(info.config.Quotes[IDs[0]]) || index < 0 {
		return "```Invalid quote index. Use !searchquote [user] to list a user's quotes and their indexes.```", false
	}
	info.config.Quotes[IDs[0]] = append(info.config.Quotes[IDs[0]][:index], info.config.Quotes[IDs[0]][index+1:]...)
	info.SaveConfig()
	return "```Deleted quote #" + strconv.Itoa(index+1) + " from " + getUserName(IDs[0]) + ".```", false
}
func (c *RemoveQuoteCommand) Usage(info *GuildInfo) string {
	return info.FormatUsage(c, "[user] [quote index]", "Removes the quote with the given quote index from the user's set of quotes. If the username has spaces, it must be in quotes. If the user is ambiguous, sweetiebot will return all possible matches.")
}
func (c *RemoveQuoteCommand) UsageShort() string { return "Removes a quote." }

type SearchQuoteCommand struct {
}

func (c *SearchQuoteCommand) Name() string {
	return "SearchQuote"
}
func (c *SearchQuoteCommand) Process(args []string, msg *discordgo.Message, info *GuildInfo) (string, bool) {
	if len(args) < 1 {
		return "```Must specify username.```", false
	}

	arg := strings.ToLower(args[0])
	IDs := FindUsername(arg)
	if len(IDs) == 0 { // no matches!
		return "```Error: Could not find any usernames or aliases matching " + arg + "!```", false
	}
	if len(IDs) > 1 {
		return "```Could be any of the following users or their aliases:\n" + strings.Join(IDsToUsernames(IDs), "\n") + "```", len(IDs) > 5
	}
	l := len(info.config.Quotes[IDs[0]])
	if l == 0 {
		return "```That user has no quotes.```", false
	}
	quotes := make([]string, l, l)
	for i := 0; i < l; i++ {
		quotes[i] = strconv.Itoa(i+1) + ". " + info.config.Quotes[IDs[0]][i]
	}
	return "All quotes for " + getUserName(IDs[0]) + ":\n" + strings.Join(quotes, "\n"), l > 6
}
func (c *SearchQuoteCommand) Usage(info *GuildInfo) string {
	return info.FormatUsage(c, "[user]", "Lists all quotes for the given user.")
}
func (c *SearchQuoteCommand) UsageShort() string { return "Finds a quote." }
<|endoftext|>


<commit_before>package site

import (
	"fmt"
	"github.com/materials-commons/gohandy/ezhttp"
	"github.com/materials-commons/gohandy/handyfile"
	"github.com/materials-commons/materials"
	"os"
	"path/filepath"
)

// Download will attempt to download the materials.tar.gz file from the
// MCDownload site. If it downloads the file it will return the path to
// the downloaded file. It downloads to the OS TempDir.
func Download() (to string, err error) {
	client := ezhttp.NewClient()
	url := fmt.Sprintf("%s/%s", materials.Config.MCDownload(), materialsArchive)
	to = filepath.Join(os.TempDir(), materialsArchive)
	status, err := client.FileGet(url, to)
	switch {
	case err != nil:
		return
	case status != 200:
		return to, fmt.Errorf("Download failed with HTTP status code %d", status)
	default:
		return to, nil
	}
}

// IsNew checks if a downloaded file is newer than the current file. It does
// this by comparing the checksum of the currently downloaded file to the
// newly downloaded one. If they are different then it assumes the new one
// is more recent. If there is no currently downloaded file then by default
// the new one is more recent.
func IsNew(downloaded string) bool {
	currentArchivePath := filepath.Join(materials.Config.DotMaterials(), materialsArchive)
	if !handyfile.Exists(currentArchivePath) {
		return true
	}

	downloadedChecksum := handyfile.Checksum32(downloaded)
	currentArchiveChecksum := handyfile.Checksum32(currentArchivePath)
	if currentArchiveChecksum != downloadedChecksum {
		return true
	}
	return false
}

// Deploy attempts to deploy the new materials website archive. It will replace
// the current archive with newly downloaded one and unpack it.
func Deploy(downloaded string) bool {
	currentArchivePath := filepath.Join(materials.Config.DotMaterials(), materialsArchive)

	err := moveFile(downloaded, currentArchivePath)
	if err != nil {
		return false
	}

	tr, err := handyfile.NewTarGz(currentArchivePath)
	if err != nil {
		return false
	}

	if err := tr.Unpack(materials.Config.WebDir()); err != nil {
		return false
	}
	return true
}

func moveFile(src, dest string) error {
	err := handyfile.Copy(src, dest)
	if err != nil {
		return err
	}
	os.Remove(src)
	return nil
}
<commit_msg>Move constant from a different file.<commit_after>package site

import (
	"fmt"
	"github.com/materials-commons/gohandy/ezhttp"
	"github.com/materials-commons/gohandy/handyfile"
	"github.com/materials-commons/materials"
	"os"
	"path/filepath"
)

// Name of archive file for the materials website.
const materialsArchive = "materials.tar.gz"

// Download will attempt to download the materials.tar.gz file from the
// MCDownload site. If it downloads the file it will return the path to
// the downloaded file. It downloads to the OS TempDir.
func Download() (to string, err error) {
	client := ezhttp.NewClient()
	url := fmt.Sprintf("%s/%s", materials.Config.MCDownload(), materialsArchive)
	to = filepath.Join(os.TempDir(), materialsArchive)
	status, err := client.FileGet(url, to)
	switch {
	case err != nil:
		return
	case status != 200:
		return to, fmt.Errorf("Download failed with HTTP status code %d", status)
	default:
		return to, nil
	}
}

// IsNew checks if a downloaded file is newer than the current file. It does
// this by comparing the checksum of the currently downloaded file to the
// newly downloaded one. If they are different then it assumes the new one
// is more recent. If there is no currently downloaded file then by default
// the new one is more recent.
func IsNew(downloaded string) bool {
	currentArchivePath := filepath.Join(materials.Config.DotMaterials(), materialsArchive)
	if !handyfile.Exists(currentArchivePath) {
		return true
	}

	downloadedChecksum := handyfile.Checksum32(downloaded)
	currentArchiveChecksum := handyfile.Checksum32(currentArchivePath)
	if currentArchiveChecksum != downloadedChecksum {
		return true
	}
	return false
}

// Deploy attempts to deploy the new materials website archive. It will replace
// the current archive with newly downloaded one and unpack it.
func Deploy(downloaded string) bool {
	currentArchivePath := filepath.Join(materials.Config.DotMaterials(), materialsArchive)

	err := moveFile(downloaded, currentArchivePath)
	if err != nil {
		return false
	}

	tr, err := handyfile.NewTarGz(currentArchivePath)
	if err != nil {
		return false
	}

	if err := tr.Unpack(materials.Config.WebDir()); err != nil {
		return false
	}
	return true
}

func moveFile(src, dest string) error {
	err := handyfile.Copy(src, dest)
	if err != nil {
		return err
	}
	os.Remove(src)
	return nil
}
<|endoftext|>


<commit_before>package skin

import (
	"errors"
	"fmt"
	"image/png"
	"net/http"
	"regexp"
)

const (
	skinURL = "http://skins.minecraft.net/MinecraftSkins/%s.png"
)

var (
	namePattern = regexp.MustCompile("^[a-zA-Z0-9_]{1,16}$")
	steve       = "https://minecraft.net/images/steve.png"
	alex        = "https://minecraft.net/images/alex.png" // TODO
)

func Download(player string) (skin *Skin, err error) {
	var url string
	if namePattern.MatchString(player) {
		url = fmt.Sprintf(skinURL, player)
	} else {
		url = steve
	}

	resp, err := http.Get(url)
	if err != nil {
		return
	}

	if resp.StatusCode != http.StatusOK {
		err = errors.New(resp.Request.URL.String() + " returned " + resp.Status)
		return
	}

	contentType := resp.Header.Get("Content-Type")
	if contentType != "image/png" {
		err = errors.New("expected image/png, " + resp.Request.URL.String() + " returned " + contentType + " instead")
		return
	}

	defer resp.Body.Close()
	img, err := png.Decode(resp.Body)
	if err != nil {
		return
	}

	return Create(img), nil
}
<commit_msg>Let "steve" and "alex" return the correct skins<commit_after>package skin

import (
	"errors"
	"fmt"
	"image/png"
	"net/http"
	"regexp"
	"strings"
)

const (
	skinURL = "http://skins.minecraft.net/MinecraftSkins/%s.png"
)

var (
	namePattern = regexp.MustCompile("^[a-zA-Z0-9_]{1,16}$")
	steve       = "https://minecraft.net/images/steve.png"
	alex        = "https://minecraft.net/images/alex.png" // TODO
)

func Download(player string) (skin *Skin, err error) {
	var url string
	// Char is only supported for compatibility with previous avatar services
	if strings.EqualFold(player, "steve") || strings.EqualFold(player, "char") {
		url = steve
	} else if strings.EqualFold(player, "alex") {
		url = alex
	} else if namePattern.MatchString(player) {
		url = fmt.Sprintf(skinURL, player)
	} else {
		url = steve
	}

	resp, err := http.Get(url)
	if err != nil {
		return
	}

	if resp.StatusCode != http.StatusOK {
		err = errors.New(resp.Request.URL.String() + " returned " + resp.Status)
		return
	}

	contentType := resp.Header.Get("Content-Type")
	if contentType != "image/png" {
		err = errors.New("expected image/png, " + resp.Request.URL.String() + " returned " + contentType + " instead")
		return
	}

	defer resp.Body.Close()
	img, err := png.Decode(resp.Body)
	if err != nil {
		return
	}

	return Create(img), nil
}
<|endoftext|>


<commit_before>package rat

import (
	"archive/tar"
	"bytes"
	"testing"
	"time"

	. "gopkg.in/check.v1"
)

func Test(t *testing.T) { TestingT(t) }

type TestSuite struct{}

var _ = Suite(&TestSuite{})

func (s *TestSuite) TestWriter(c *C) {
	f := bytes.NewBuffer(nil)
	w := NewWriter(f)

	h := &tar.Header{
		Name:    "foo.txt",
		Mode:    0640,
		Size:    3,
		ModTime: time.Unix(1244428340, 0),
	}

	c.Assert(w.WriteHeader(h), IsNil)
	n, err := w.Write([]byte("foo"))
	c.Assert(n, Equals, 3)
	c.Assert(err, IsNil)

	c.Assert(w.WriteHeader(&tar.Header{
		Name:    "bar.txt",
		Mode:    0640,
		Size:    3,
		ModTime: time.Unix(1244428340, 0),
	}), IsNil)

	n, err = w.Write([]byte("bar"))
	c.Assert(n, Equals, 3)
	c.Assert(err, IsNil)

	c.Assert(w.Close(), IsNil)

	r, err := NewReader(bytes.NewReader(f.Bytes()))
	c.Assert(err, IsNil)

	d, err := r.ReadFile("foo.txt")
	c.Assert(err, IsNil)
	c.Assert(string(d), Equals, "foo")

	d, err = r.ReadFile("bar.txt")
	c.Assert(err, IsNil)
	c.Assert(string(d), Equals, "bar")
}
<commit_msg>travis<commit_after>package rat

import (
	"archive/tar"
	"bytes"
	"os"
	"testing"
	"time"

	. "gopkg.in/check.v1"
)

func Test(t *testing.T) { TestingT(t) }

type TestSuite struct{}

var _ = Suite(&TestSuite{})

func (s *TestSuite) TestWriter(c *C) {
	f := bytes.NewBuffer(nil)
	w := NewWriter(f)

	h := &tar.Header{
		Name:    "foo.txt",
		Mode:    0640,
		Size:    3,
		ModTime: time.Unix(1244428340, 0),
	}

	c.Assert(w.WriteHeader(h), IsNil)
	n, err := w.Write([]byte("foo"))
	c.Assert(n, Equals, 3)
	c.Assert(err, IsNil)

	c.Assert(w.WriteHeader(&tar.Header{
		Name:    "bar.txt",
		Mode:    0640,
		Size:    3,
		ModTime: time.Unix(1244428340, 0),
	}), IsNil)

	n, err = w.Write([]byte("bar"))
	c.Assert(n, Equals, 3)
	c.Assert(err, IsNil)

	c.Assert(w.Close(), IsNil)

	r, err := NewReader(bytes.NewReader(f.Bytes()))
	c.Assert(err, IsNil)

	d, err := r.ReadFile("foo.txt")
	c.Assert(err, IsNil)
	c.Assert(string(d), Equals, "foo")

	d, err = r.ReadFile("bar.txt")
	c.Assert(err, IsNil)
	c.Assert(string(d), Equals, "bar")
}

func (s *TestSuite) TestWriterRealFile(c *C) {
	f, err := os.Create("/tmp/foo.tar")
	c.Assert(err, IsNil)

	w := NewWriter(f)

	h := &tar.Header{
		Name:    "foo.txt",
		Mode:    0640,
		Size:    3,
		ModTime: time.Unix(1244428340, 0),
	}

	c.Assert(w.WriteHeader(h), IsNil)
	n, err := w.Write([]byte("foo"))
	c.Assert(n, Equals, 3)
	c.Assert(err, IsNil)

	c.Assert(w.WriteHeader(&tar.Header{
		Name:    "bar.txt",
		Mode:    0640,
		Size:    3,
		ModTime: time.Unix(1244428340, 0),
	}), IsNil)

	n, err = w.Write([]byte("bar"))
	c.Assert(n, Equals, 3)
	c.Assert(err, IsNil)

	c.Assert(w.Close(), IsNil)

	f, err = os.Open("/tmp/foo.tar")
	c.Assert(err, IsNil)

	r, err := NewReader(f)
	c.Assert(err, IsNil)

	d, err := r.ReadFile("foo.txt")
	c.Assert(err, IsNil)
	c.Assert(string(d), Equals, "foo")

	d, err = r.ReadFile("bar.txt")
	c.Assert(err, IsNil)
	c.Assert(string(d), Equals, "bar")
}
<|endoftext|>


<commit_before>package app

import (
	"strings"

	"github.com/dtan4/paus-frontend/store"
)

func Create(etcd *store.Etcd, username, appName string) error {
	if err := etcd.Mkdir("/paus/users/" + username + "/apps/" + appName); err != nil {
		return err
	}

	for _, resource := range []string{"build-args", "envs", "deployments"} {
		if err := etcd.Mkdir("/paus/users/" + username + "/apps/" + appName + "/" + resource); err != nil {
			return err
		}
	}

	return nil
}

func Exists(etcd *store.Etcd, username, appName string) bool {
	return etcd.HasKey("/paus/users/" + username + "/apps/" + appName)
}

func List(etcd *store.Etcd, username string) ([]string, error) {
	apps, err := etcd.List("/paus/users/"+username+"/apps/", true)

	if err != nil {
		return nil, err
	}

	result := make([]string, 0)

	for _, app := range apps {
		appName := strings.Replace(app, "/paus/users/"+username+"/apps/", "", 1)
		result = append(result, appName)
	}

	return result, nil
}

func URL(uriScheme, identifier, baseDomain string) string {
	return strings.ToLower(uriScheme + "://" + identifier + "." + baseDomain)
}

func URLs(etcd *store.Etcd, uriScheme, baseDomain, username, appName string) ([]string, error) {
	deployments, err := etcd.List("/paus/users/"+username+"/apps/"+appName+"/deployments/", true)

	if err != nil {
		return nil, err
	}

	result := make([]string, 0)

	for _, deployment := range deployments {
		revision, err := etcd.Get(deployment)

		if err != nil {
			return nil, err
		}

		identifier := username + "-" + appName + "-" + revision[0:8]
		result = append(result, URL(uriScheme, identifier, baseDomain))
	}

	return result, nil
}

func LatestAppURLOfUser(uriScheme, baseDomain, username, appName string) string {
	identifier := username + "-" + appName

	return URL(uriScheme, identifier, baseDomain)
}
<commit_msg>Set default healthcheck params<commit_after>package app

import (
	"strings"

	"github.com/dtan4/paus-frontend/store"
)

var (
	defaultHealthCheck = map[string]string{
		"path":     "/",
		"interval": "5",
		"max-try":  "10",
	}
)

func Create(etcd *store.Etcd, username, appName string) error {
	appKey := "/paus/users/" + username + "/apps/" + appName

	if err := etcd.Mkdir(appKey); err != nil {
		return err
	}

	for _, resource := range []string{"build-args", "envs", "deployments", "healthcheck"} {
		if err := etcd.Mkdir(appKey + "/" + resource); err != nil {
			return err
		}
	}

	for k, v := range defaultHealthCheck {
		if err := etcd.Set(appKey+"/healthcheck/"+k, v); err != nil {
			return err
		}
	}

	return nil
}

func Exists(etcd *store.Etcd, username, appName string) bool {
	return etcd.HasKey("/paus/users/" + username + "/apps/" + appName)
}

func List(etcd *store.Etcd, username string) ([]string, error) {
	apps, err := etcd.List("/paus/users/"+username+"/apps/", true)

	if err != nil {
		return nil, err
	}

	result := make([]string, 0)

	for _, app := range apps {
		appName := strings.Replace(app, "/paus/users/"+username+"/apps/", "", 1)
		result = append(result, appName)
	}

	return result, nil
}

func URL(uriScheme, identifier, baseDomain string) string {
	return strings.ToLower(uriScheme + "://" + identifier + "." + baseDomain)
}

func URLs(etcd *store.Etcd, uriScheme, baseDomain, username, appName string) ([]string, error) {
	deployments, err := etcd.List("/paus/users/"+username+"/apps/"+appName+"/deployments/", true)

	if err != nil {
		return nil, err
	}

	result := make([]string, 0)

	for _, deployment := range deployments {
		revision, err := etcd.Get(deployment)

		if err != nil {
			return nil, err
		}

		identifier := username + "-" + appName + "-" + revision[0:8]
		result = append(result, URL(uriScheme, identifier, baseDomain))
	}

	return result, nil
}

func LatestAppURLOfUser(uriScheme, baseDomain, username, appName string) string {
	identifier := username + "-" + appName

	return URL(uriScheme, identifier, baseDomain)
}
<|endoftext|>


<commit_before>package model

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

func fixtureEmptySlave() *Slave {
	return &Slave{
		Hostname:             "host1",
		Port:                 1,
		MongodPortRangeBegin: 2,
		MongodPortRangeEnd:   3,
		PersistentStorage:    true,
		Mongods:              []*Mongod{},
		ConfiguedState:       SlaveStateActive,
	}
}

func fixtureEmptyMongod() *Mongod {
	return &Mongod{
		Port:        8080,
		ReplSetName: "repl1",
	}
}

func fixtureEmptyRiskGroup() *RiskGroup {
	return &RiskGroup{
		Name:   "rg1",
		Slaves: []*Slave{},
	}
}

func fixtureEmptyReplicaSet() *ReplicaSet {
	return &ReplicaSet{
		Name: "repl1",
		PersistentMemberCount:           1,
		VolatileMemberCount:             2,
		ConfigureAsShardingConfigServer: false,
	}
}

////////////////////////////////////////////////////////////////////////////////

func TestCanInitializeDB(t *testing.T) {
	_, err := InitializeInMemoryDB("")
	assert.NoError(t, err)
}

/*
 This elaborate test demonstrates how resolving an association works in gorm.
 Check the assertions to learn about the behavior of gorm.
*/
func TestRelationshipMongodParentSlave(t *testing.T) {

	db, _ := InitializeInMemoryDB("")

	s := fixtureEmptySlave()

	db.Create(s)

	m := fixtureEmptyMongod()
	m.ParentSlave = s

	db.Create(m)

	assert.Equal(t, m.ParentSlaveID, s.ID)

	assert.Equal(t, s.Mongods, []*Mongod{})

	var sdb Slave

	// Check what happens when just SELECTing the slave
	err := db.First(&sdb).Error

	assert.NoError(t, err)
	assert.Nil(t, sdb.Mongods)

	// Now resolve the slave->mongod 1:n association
	err = db.Model(&sdb).Related(&sdb.Mongods, "Mongods").Error

	assert.NoError(t, err)
	assert.Equal(t, len(sdb.Mongods), 1)
	assert.Equal(t, sdb.Mongods[0].ReplSetName, m.ReplSetName)
	assert.Zero(t, sdb.Mongods[0].ParentSlave)
	assert.Equal(t, sdb.Mongods[0].ParentSlaveID, s.ID)

	// Now resolve the mongod->(parent)slave relation
	parentSlave := &Slave{}
	err = db.Model(&sdb.Mongods[0]).Related(parentSlave, "ParentSlave").Error
	assert.NoError(t, err)
	assert.NotZero(t, parentSlave)
	assert.Equal(t, s.ID, parentSlave.ID)

}

// Test RiskGroup Slave relationship
func TestRiskGroupSlaveRelationship(t *testing.T) {

	db, _ := InitializeInMemoryDB("")

	s := fixtureEmptySlave()
	r := fixtureEmptyRiskGroup()
	r.Slaves = []*Slave{s}

	err := db.Create(&r).Error
	assert.NoError(t, err)

	var rdb RiskGroup

	err = db.First(&rdb).Error

	assert.NoError(t, err)
	assert.Zero(t, rdb.Slaves)

	err = db.Model(&rdb).Related(&rdb.Slaves, "Slaves").Error
	assert.NoError(t, err)
	assert.NotZero(t, rdb.Slaves)
	assert.Equal(t, len(rdb.Slaves), 1)
	assert.Equal(t, rdb.Slaves[0].ID, s.ID)

}

// Test ReplicaSet - Mongod Relationship
func TestReplicaSetMongodRelationship(t *testing.T) {

	db, _ := InitializeInMemoryDB("")

	r := fixtureEmptyReplicaSet()
	m := fixtureEmptyMongod()
	r.Mongods = []*Mongod{m}

	err := db.Create(&r).Error
	assert.NoError(t, err)

	var rdb ReplicaSet

	err = db.First(&rdb).Error

	assert.NoError(t, err)
	assert.Zero(t, rdb.Mongods)

	err = db.Model(&rdb).Related(&rdb.Mongods, "Mongods").Error
	assert.NoError(t, err)
	assert.NotZero(t, rdb.Mongods)
	assert.Equal(t, len(rdb.Mongods), 1)
	assert.Equal(t, rdb.Mongods[0].ID, m.ID)

}

// Test Mongod - MongodState relationship
func TestMongodMongodStateRelationship(t *testing.T) {

	db, _ := InitializeInMemoryDB("")

	m := fixtureEmptyMongod()

	o := MongodState{
		IsShardingConfigServer: false,
		ExecutionState:         MongodExecutionStateNotRunning,
		ReplicaSetMembers:      []ReplicaSetMember{},
	}

	d := MongodState{
		IsShardingConfigServer: false,
		ExecutionState:         MongodExecutionStateRunning,
		ReplicaSetMembers:      []ReplicaSetMember{},
	}

	m.ObservedState = o
	m.DesiredState = d

	assert.NoError(t, db.Create(m).Error)

	var mdb Mongod

	// Observed
	assert.NoError(t, db.First(&mdb).Error)
	assert.Zero(t, mdb.ObservedState)

	assert.NoError(t, db.Model(&mdb).Related(&mdb.ObservedState, "ObservedState").Error)
	assert.NotZero(t, mdb.ObservedState)
	assert.Equal(t, mdb.ObservedState.ExecutionState, MongodExecutionStateNotRunning)

	assert.NoError(t, db.Model(&mdb).Related(&mdb.DesiredState, "DesiredState").Error)
	assert.NotZero(t, mdb.DesiredState)
	assert.Equal(t, mdb.DesiredState.ExecutionState, MongodExecutionStateRunning)

}

// Test MongodState - ReplicaSetMember relationship
func TestMongodStateReplicaSetMembersRelationship(t *testing.T) {
	db, _ := InitializeInMemoryDB("")

	m := ReplicaSetMember{Hostname: "h1"}

	s := MongodState{ReplicaSetMembers: []ReplicaSetMember{m}}

	assert.NoError(t, db.Create(&s).Error)

	var sdb MongodState

	assert.NoError(t, db.First(&sdb).Error)
	assert.Zero(t, sdb.ReplicaSetMembers)

	assert.NoError(t, db.Model(&sdb).Related(&sdb.ReplicaSetMembers, "ReplicaSetMembers").Error)
	assert.NotZero(t, sdb.ReplicaSetMembers)
	assert.Equal(t, len(sdb.ReplicaSetMembers), 1)
	assert.Equal(t, sdb.ReplicaSetMembers[0].Hostname, m.Hostname)

}
<commit_msg>ADD: model: test on delete behavior of gorm.<commit_after>package model

import (
	"github.com/stretchr/testify/assert"
	"testing"
)

func fixtureEmptySlave() *Slave {
	return &Slave{
		Hostname:             "host1",
		Port:                 1,
		MongodPortRangeBegin: 2,
		MongodPortRangeEnd:   3,
		PersistentStorage:    true,
		Mongods:              []*Mongod{},
		ConfiguedState:       SlaveStateActive,
	}
}

func fixtureEmptyMongod() *Mongod {
	return &Mongod{
		Port:        8080,
		ReplSetName: "repl1",
	}
}

func fixtureEmptyRiskGroup() *RiskGroup {
	return &RiskGroup{
		Name:   "rg1",
		Slaves: []*Slave{},
	}
}

func fixtureEmptyReplicaSet() *ReplicaSet {
	return &ReplicaSet{
		Name: "repl1",
		PersistentMemberCount:           1,
		VolatileMemberCount:             2,
		ConfigureAsShardingConfigServer: false,
	}
}

////////////////////////////////////////////////////////////////////////////////

func TestCanInitializeDB(t *testing.T) {
	_, err := InitializeInMemoryDB("")
	assert.NoError(t, err)
}

/*
 This elaborate test demonstrates how resolving an association works in gorm.
 Check the assertions to learn about the behavior of gorm.
*/
func TestRelationshipMongodParentSlave(t *testing.T) {

	db, _ := InitializeInMemoryDB("")

	s := fixtureEmptySlave()

	db.Create(s)

	m := fixtureEmptyMongod()
	m.ParentSlave = s

	db.Create(m)

	assert.Equal(t, m.ParentSlaveID, s.ID)

	assert.Equal(t, s.Mongods, []*Mongod{})

	var sdb Slave

	// Check what happens when just SELECTing the slave
	err := db.First(&sdb).Error

	assert.NoError(t, err)
	assert.Nil(t, sdb.Mongods)

	// Now resolve the slave->mongod 1:n association
	err = db.Model(&sdb).Related(&sdb.Mongods, "Mongods").Error

	assert.NoError(t, err)
	assert.Equal(t, len(sdb.Mongods), 1)
	assert.Equal(t, sdb.Mongods[0].ReplSetName, m.ReplSetName)
	assert.Zero(t, sdb.Mongods[0].ParentSlave)
	assert.Equal(t, sdb.Mongods[0].ParentSlaveID, s.ID)

	// Now resolve the mongod->(parent)slave relation
	parentSlave := &Slave{}
	err = db.Model(&sdb.Mongods[0]).Related(parentSlave, "ParentSlave").Error
	assert.NoError(t, err)
	assert.NotZero(t, parentSlave)
	assert.Equal(t, s.ID, parentSlave.ID)

}

// Test RiskGroup Slave relationship
func TestRiskGroupSlaveRelationship(t *testing.T) {

	db, _ := InitializeInMemoryDB("")

	s := fixtureEmptySlave()
	r := fixtureEmptyRiskGroup()
	r.Slaves = []*Slave{s}

	err := db.Create(&r).Error
	assert.NoError(t, err)

	var rdb RiskGroup

	err = db.First(&rdb).Error

	assert.NoError(t, err)
	assert.Zero(t, rdb.Slaves)

	err = db.Model(&rdb).Related(&rdb.Slaves, "Slaves").Error
	assert.NoError(t, err)
	assert.NotZero(t, rdb.Slaves)
	assert.Equal(t, len(rdb.Slaves), 1)
	assert.Equal(t, rdb.Slaves[0].ID, s.ID)

}

// Test ReplicaSet - Mongod Relationship
func TestReplicaSetMongodRelationship(t *testing.T) {

	db, _ := InitializeInMemoryDB("")

	r := fixtureEmptyReplicaSet()
	m := fixtureEmptyMongod()
	r.Mongods = []*Mongod{m}

	err := db.Create(&r).Error
	assert.NoError(t, err)

	var rdb ReplicaSet

	err = db.First(&rdb).Error

	assert.NoError(t, err)
	assert.Zero(t, rdb.Mongods)

	err = db.Model(&rdb).Related(&rdb.Mongods, "Mongods").Error
	assert.NoError(t, err)
	assert.NotZero(t, rdb.Mongods)
	assert.Equal(t, len(rdb.Mongods), 1)
	assert.Equal(t, rdb.Mongods[0].ID, m.ID)

}

// Test Mongod - MongodState relationship
func TestMongodMongodStateRelationship(t *testing.T) {

	db, _ := InitializeInMemoryDB("")

	m := fixtureEmptyMongod()

	o := MongodState{
		IsShardingConfigServer: false,
		ExecutionState:         MongodExecutionStateNotRunning,
		ReplicaSetMembers:      []ReplicaSetMember{},
	}

	d := MongodState{
		IsShardingConfigServer: false,
		ExecutionState:         MongodExecutionStateRunning,
		ReplicaSetMembers:      []ReplicaSetMember{},
	}

	m.ObservedState = o
	m.DesiredState = d

	assert.NoError(t, db.Create(m).Error)

	var mdb Mongod

	// Observed
	assert.NoError(t, db.First(&mdb).Error)
	assert.Zero(t, mdb.ObservedState)

	assert.NoError(t, db.Model(&mdb).Related(&mdb.ObservedState, "ObservedState").Error)
	assert.NotZero(t, mdb.ObservedState)
	assert.Equal(t, mdb.ObservedState.ExecutionState, MongodExecutionStateNotRunning)

	assert.NoError(t, db.Model(&mdb).Related(&mdb.DesiredState, "DesiredState").Error)
	assert.NotZero(t, mdb.DesiredState)
	assert.Equal(t, mdb.DesiredState.ExecutionState, MongodExecutionStateRunning)

}

// Test MongodState - ReplicaSetMember relationship
func TestMongodStateReplicaSetMembersRelationship(t *testing.T) {
	db, _ := InitializeInMemoryDB("")

	m := ReplicaSetMember{Hostname: "h1"}

	s := MongodState{ReplicaSetMembers: []ReplicaSetMember{m}}

	assert.NoError(t, db.Create(&s).Error)

	var sdb MongodState

	assert.NoError(t, db.First(&sdb).Error)
	assert.Zero(t, sdb.ReplicaSetMembers)

	assert.NoError(t, db.Model(&sdb).Related(&sdb.ReplicaSetMembers, "ReplicaSetMembers").Error)
	assert.NotZero(t, sdb.ReplicaSetMembers)
	assert.Equal(t, len(sdb.ReplicaSetMembers), 1)
	assert.Equal(t, sdb.ReplicaSetMembers[0].Hostname, m.Hostname)

}

func TestDeleteBehavior(t *testing.T) {

	db, _ := InitializeInMemoryDB("")

	m := fixtureEmptyMongod()
	m.ID = 1000

	// Create it
	db.Create(&m)

	var mdb Mongod

	// Read it once
	d := db.First(&mdb)

	assert.NoError(t, d.Error)
	assert.Equal(t, mdb.ID, m.ID)

	// Destroy it once, by ID
	d = db.Delete(&Mongod{ID: 1000})

	assert.NoError(t, d.Error)
	assert.EqualValues(t, 1, d.RowsAffected)

	// Destroy it a second time.
	// No Error will occur, have to check RowsAffected if we deleted something
	d = db.Delete(&Mongod{ID: 1000})

	assert.NoError(t, d.Error)
	assert.EqualValues(t, 0, d.RowsAffected)

}
<|endoftext|>


<commit_before>package resource

import (
	"fmt"
	"log"

	"github.com/hashicorp/terraform/terraform"
)

// testStepConfig runs a config-mode test step
func testStepConfig(
	opts terraform.ContextOpts,
	state *terraform.State,
	step TestStep) (*terraform.State, error) {
	return testStep(opts, state, step)
}

func testStep(
	opts terraform.ContextOpts,
	state *terraform.State,
	step TestStep) (*terraform.State, error) {
	mod, err := testModule(opts, step)
	if err != nil {
		return state, err
	}

	// Build the context
	opts.Module = mod
	opts.State = state
	opts.Destroy = step.Destroy
	ctx, err := terraform.NewContext(&opts)
	if err != nil {
		return state, fmt.Errorf("Error initializing context: %s", err)
	}
	if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
		if len(es) > 0 {
			estrs := make([]string, len(es))
			for i, e := range es {
				estrs[i] = e.Error()
			}
			return state, fmt.Errorf(
				"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
				ws, estrs)
		}
		log.Printf("[WARN] Config warnings: %#v", ws)
	}

	// Refresh!
	state, err = ctx.Refresh()
	if err != nil {
		return state, fmt.Errorf(
			"Error refreshing: %s", err)
	}

	// Plan!
	if p, err := ctx.Plan(); err != nil {
		return state, fmt.Errorf(
			"Error planning: %s", err)
	} else {
		log.Printf("[WARN] Test: Step plan: %s", p)
	}

	// We need to keep a copy of the state prior to destroying
	// such that destroy steps can verify their behaviour in the check
	// function
	stateBeforeApplication := state.DeepCopy()

	// Apply!
	state, err = ctx.Apply()
	if err != nil {
		return state, fmt.Errorf("Error applying: %s", err)
	}

	// Check! Excitement!
	if step.Check != nil {
		if step.Destroy {
			if err := step.Check(stateBeforeApplication); err != nil {
				return state, fmt.Errorf("Check failed: %s", err)
			}
		} else {
			if err := step.Check(state); err != nil {
				return state, fmt.Errorf("Check failed: %s", err)
			}
		}
	}

	// Now, verify that Plan is now empty and we don't have a perpetual diff issue
	// We do this with TWO plans. One without a refresh.
	var p *terraform.Plan
	if p, err = ctx.Plan(); err != nil {
		return state, fmt.Errorf("Error on follow-up plan: %s", err)
	}
	if p.Diff != nil && !p.Diff.Empty() {
		if step.ExpectNonEmptyPlan {
			log.Printf("[INFO] Got non-empty plan, as expected:\n\n%s", p)
		} else {
			return state, fmt.Errorf(
				"After applying this step, the plan was not empty:\n\n%s", p)
		}
	}

	// And another after a Refresh.
	state, err = ctx.Refresh()
	if err != nil {
		return state, fmt.Errorf(
			"Error on follow-up refresh: %s", err)
	}
	if p, err = ctx.Plan(); err != nil {
		return state, fmt.Errorf("Error on second follow-up plan: %s", err)
	}
	if p.Diff != nil && !p.Diff.Empty() {
		if step.ExpectNonEmptyPlan {
			log.Printf("[INFO] Got non-empty plan, as expected:\n\n%s", p)
		} else {
			return state, fmt.Errorf(
				"After applying this step and refreshing, "+
					"the plan was not empty:\n\n%s", p)
		}
	}

	// Made it here, but expected a non-empty plan, fail!
	if step.ExpectNonEmptyPlan && (p.Diff == nil || p.Diff.Empty()) {
		return state, fmt.Errorf("Expected a non-empty plan, but got an empty plan!")
	}

	// Made it here? Good job test step!
	return state, nil
}
<commit_msg>helper/resource: ignore data resource diffs during destroy<commit_after>package resource

import (
	"fmt"
	"log"
	"strings"

	"github.com/hashicorp/terraform/terraform"
)

// testStepConfig runs a config-mode test step
func testStepConfig(
	opts terraform.ContextOpts,
	state *terraform.State,
	step TestStep) (*terraform.State, error) {
	return testStep(opts, state, step)
}

func testStep(
	opts terraform.ContextOpts,
	state *terraform.State,
	step TestStep) (*terraform.State, error) {
	mod, err := testModule(opts, step)
	if err != nil {
		return state, err
	}

	// Build the context
	opts.Module = mod
	opts.State = state
	opts.Destroy = step.Destroy
	ctx, err := terraform.NewContext(&opts)
	if err != nil {
		return state, fmt.Errorf("Error initializing context: %s", err)
	}
	if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
		if len(es) > 0 {
			estrs := make([]string, len(es))
			for i, e := range es {
				estrs[i] = e.Error()
			}
			return state, fmt.Errorf(
				"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
				ws, estrs)
		}
		log.Printf("[WARN] Config warnings: %#v", ws)
	}

	// Refresh!
	state, err = ctx.Refresh()
	if err != nil {
		return state, fmt.Errorf(
			"Error refreshing: %s", err)
	}

	// Plan!
	if p, err := ctx.Plan(); err != nil {
		return state, fmt.Errorf(
			"Error planning: %s", err)
	} else {
		log.Printf("[WARN] Test: Step plan: %s", p)
	}

	// We need to keep a copy of the state prior to destroying
	// such that destroy steps can verify their behaviour in the check
	// function
	stateBeforeApplication := state.DeepCopy()

	// Apply!
	state, err = ctx.Apply()
	if err != nil {
		return state, fmt.Errorf("Error applying: %s", err)
	}

	// Check! Excitement!
	if step.Check != nil {
		if step.Destroy {
			if err := step.Check(stateBeforeApplication); err != nil {
				return state, fmt.Errorf("Check failed: %s", err)
			}
		} else {
			if err := step.Check(state); err != nil {
				return state, fmt.Errorf("Check failed: %s", err)
			}
		}
	}

	// Now, verify that Plan is now empty and we don't have a perpetual diff issue
	// We do this with TWO plans. One without a refresh.
	var p *terraform.Plan
	if p, err = ctx.Plan(); err != nil {
		return state, fmt.Errorf("Error on follow-up plan: %s", err)
	}
	if p.Diff != nil && !p.Diff.Empty() {
		if step.ExpectNonEmptyPlan {
			log.Printf("[INFO] Got non-empty plan, as expected:\n\n%s", p)
		} else {
			return state, fmt.Errorf(
				"After applying this step, the plan was not empty:\n\n%s", p)
		}
	}

	// And another after a Refresh.
	state, err = ctx.Refresh()
	if err != nil {
		return state, fmt.Errorf(
			"Error on follow-up refresh: %s", err)
	}
	if p, err = ctx.Plan(); err != nil {
		return state, fmt.Errorf("Error on second follow-up plan: %s", err)
	}
	empty := p.Diff == nil || p.Diff.Empty()

	// Data resources are tricky because they legitimately get instantiated
	// during refresh so that they will be already populated during the
	// plan walk. Because of this, if we have any data resources in the
	// config we'll end up wanting to destroy them again here. This is
	// acceptable and expected, and we'll treat it as "empty" for the
	// sake of this testing.
	if step.Destroy {
		empty = true

		for _, moduleDiff := range p.Diff.Modules {
			for k, instanceDiff := range moduleDiff.Resources {
				if !strings.HasPrefix(k, "data.") {
					empty = false
					break
				}

				if !instanceDiff.Destroy {
					empty = false
				}
			}
		}
	}

	if !empty {
		if step.ExpectNonEmptyPlan {
			log.Printf("[INFO] Got non-empty plan, as expected:\n\n%s", p)
		} else {
			return state, fmt.Errorf(
				"After applying this step and refreshing, "+
					"the plan was not empty:\n\n%s", p)
		}
	}

	// Made it here, but expected a non-empty plan, fail!
	if step.ExpectNonEmptyPlan && (p.Diff == nil || p.Diff.Empty()) {
		return state, fmt.Errorf("Expected a non-empty plan, but got an empty plan!")
	}

	// Made it here? Good job test step!
	return state, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Huawei Technologies Co., Ltd. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package models

import (
	"os"

	log "github.com/Sirupsen/logrus"
	"github.com/jinzhu/gorm"

	"github.com/containerops/configure"
)

var (
	db *gorm.DB
)

// init()
func init() {

}

// OpenDatabase is
func OpenDatabase() {
	var err error
	if db, err = gorm.Open(configure.GetString("database.driver"), configure.GetString("database.uri")); err != nil {
		log.Fatal("Initlization database connection error.")
		os.Exit(1)
	} else {
		db.DB()
		db.DB().Ping()
		db.DB().SetMaxIdleConns(10)
		db.DB().SetMaxOpenConns(100)
		db.SingularTable(true)
	}
}

// Migrate is
func Migrate() {
	OpenDatabase()

	db.AutoMigrate(&AppcV1{}, &ACIv1{})
	db.AutoMigrate(&AppV1{}, &ArtifactV1{})
	db.AutoMigrate(&DockerV1{}, &DockerImageV1{}, &DockerTagV1{})
	db.AutoMigrate(&DockerV2{}, &DockerImageV2{}, &DockerTagV2{})
	db.AutoMigrate(&ImageV1{}, &VirtualV1{})

	log.Info("AutMigrate database structs.")
}
<commit_msg>Update the migrate done message<commit_after>/*
Copyright 2014 Huawei Technologies Co., Ltd. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package models

import (
	"os"

	log "github.com/Sirupsen/logrus"
	"github.com/jinzhu/gorm"

	"github.com/containerops/configure"
)

var (
	db *gorm.DB
)

// init()
func init() {

}

// OpenDatabase is
func OpenDatabase() {
	var err error
	if db, err = gorm.Open(configure.GetString("database.driver"), configure.GetString("database.uri")); err != nil {
		log.Fatal("Initlization database connection error.")
		os.Exit(1)
	} else {
		db.DB()
		db.DB().Ping()
		db.DB().SetMaxIdleConns(10)
		db.DB().SetMaxOpenConns(100)
		db.SingularTable(true)
	}
}

// Migrate is
func Migrate() {
	OpenDatabase()

	db.AutoMigrate(&AppcV1{}, &ACIv1{})
	db.AutoMigrate(&AppV1{}, &ArtifactV1{})
	db.AutoMigrate(&DockerV1{}, &DockerImageV1{}, &DockerTagV1{})
	db.AutoMigrate(&DockerV2{}, &DockerImageV2{}, &DockerTagV2{})
	db.AutoMigrate(&ImageV1{}, &VirtualV1{})

	log.Info("Auto Migrate Dockyard Database Structs Done.")
}
<|endoftext|>


<commit_before>package actions

import (
	"log"
	"net/http"
	"os"

	"github.com/gopheracademy/gcon/actions/admin"
	"github.com/gopheracademy/gcon/models"
	"github.com/markbates/buffalo"
	"github.com/markbates/buffalo/middleware"
	"github.com/markbates/going/defaults"
)

// App is where all routes and middleware for buffalo
// should be defined. This is the nerve center of your
// application.
var ENV string

func init() {
	ENV = defaults.String(os.Getenv("GO_ENV"), "development")
}
func App() http.Handler {
	a := buffalo.Automatic(buffalo.Options{
		Env: ENV,
	})
	log.Println("Environment:", ENV)
	log.Println("Assets:", assetsPath())
	log.Println("Templates:", templatesPath())
	a.Use(middleware.PopTransaction(models.DB))
	a.ServeFiles("/assets", assetsPath())
	a.GET("/", HomeHandler)
	adm := a.Group("/admin")
	adm.GET("/", admin.AdminHandler)

	return a
}
<commit_msg>fix vet<commit_after>package actions

import (
	"log"
	"net/http"
	"os"

	"github.com/gopheracademy/gcon/actions/admin"
	"github.com/gopheracademy/gcon/models"
	"github.com/markbates/buffalo"
	"github.com/markbates/buffalo/middleware"
	"github.com/markbates/going/defaults"
)

// ENV is the environment, computed below from environment variable or defaulted
// to development
var ENV string

func init() {
	ENV = defaults.String(os.Getenv("GO_ENV"), "development")
}

// App is where all routes and middleware for buffalo
// should be defined. This is the nerve center of your
// application.
func App() http.Handler {
	a := buffalo.Automatic(buffalo.Options{
		Env: ENV,
	})
	log.Println("Environment:", ENV)
	log.Println("Assets:", assetsPath())
	log.Println("Templates:", templatesPath())
	a.Use(middleware.PopTransaction(models.DB))
	a.ServeFiles("/assets", assetsPath())
	a.GET("/", HomeHandler)
	adm := a.Group("/admin")
	adm.GET("/", admin.AdminHandler)

	return a
}
<|endoftext|>