<commit_before>// Copyright © 2017 NAME HERE <EMAIL ADDRESS>
// 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 cmd

import (
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
	Aws "github.com/cm-igarashi-ryosuke/lazy-awslogs/lib/aws"
	Config "github.com/cm-igarashi-ryosuke/lazy-awslogs/lib/config"
	"github.com/spf13/cobra"

	"github.com/cm-igarashi-ryosuke/lazy-awslogs/lib/flags"
)

type GetFlags struct {
	Profile      string
	Region       string
	Log          flags.CWLogIdentifyFlags
	Pattern      string
	TimeRange    flags.CWLogTimeRange
	Watch        bool
}

const watchInterval = 5 // seconds

// Create FilterLogEventsInput by GetFlags
func (this *GetFlags) GetCloudWatchLogsFilterLogEventsParam(nextToken *string) cloudwatchlogs.FilterLogEventsInput {
	input := cloudwatchlogs.FilterLogEventsInput{
		LogGroupName: &this.Log.Group,
		NextToken:    nextToken,
	}
	if this.Pattern != "" {
		pattern := fmt.Sprintf("\"%s\"", this.Pattern)
		input.FilterPattern = &pattern
	}
	if this.Log.Stream != "" {
		input.LogStreamNames = []*string{&this.Log.Stream}
	}
	if startTime := this.TimeRange.StartTimeMilliseconds(); startTime != 0 {
		input.StartTime = &startTime
	}
	if endTime := this.TimeRange.EndTimeMilliseconds(); endTime != 0 {
		input.EndTime = &endTime
	}
	return input
}

// Create GetLogEventsInput by GetFlags
func (this *GetFlags) GetCloudWatchLogsGetLogEventsParam(nextToken *string) cloudwatchlogs.GetLogEventsInput {
	input := cloudwatchlogs.GetLogEventsInput{
		LogGroupName:  &this.Log.Group,
		LogStreamName: &this.Log.Stream,
		NextToken:     nextToken,
	}
	if startTime := this.TimeRange.StartTimeMilliseconds(); startTime != 0 {
		input.StartTime = &startTime
	}
	if endTime := this.TimeRange.EndTimeMilliseconds(); endTime != 0 {
		input.EndTime = &endTime
	}
	return input
}

// Print any events to stdout
func printEvents(any interface{}) {
	if events, ok := any.([]*cloudwatchlogs.FilteredLogEvent); ok {
		for _, event := range events {
			fmt.Println(strings.TrimRight(*event.Message, "\n"))
		}
	} else if events, ok := any.([]*cloudwatchlogs.OutputLogEvent); ok {
		for _, event := range events {
			fmt.Println(strings.TrimRight(*event.Message, "\n"))
		}
	}
}

var _getFlags = &GetFlags{}

// getCmd represents the get command
var getCmd = &cobra.Command{
	Use:   "get",
	Short: "Lists log events from the specified log stream.",
	Long: `Lists log events from the specified log stream. You can list all the log events or filter using a time range.

By default, this operation returns as many log events as can fit in a response  size of 1MB (up to 10,000 log events).
If the results include tokens, there are more log events available.
You can get additional log events by specifying one of the tokens in a subsequent call.`,
	Run:    getRun,
	PreRun: preRun,
}

func preRun(cmd *cobra.Command, args []string) {
	if rootFlag.profile == "" {
		fmt.Printf("%v\n\n", fmt.Errorf("Error: Profile is not specified."))
		cmd.Usage()
		os.Exit(1)
	}

	config := Config.Load()
	env := config.CurrentEnvironment()

	if _getFlags.Log.Group == "" && env.DefaultGroup != "" {
		_getFlags.Log.Group = env.DefaultGroup
	}
	if _getFlags.Log.Group == "" {
		fmt.Printf("%v\n\n", fmt.Errorf("Error: Group is not specified."))
		cmd.Usage()
		os.Exit(1)
	}

	// if _getFlags.Log.Stream == "" && env.DefaultStream != "" {
	// 	_getFlags.Log.Stream = env.DefaultStream
	// }
	// if _getFlags.Log.Stream == "" {
	// 	fmt.Printf("%v\n\n", fmt.Errorf("Error: Stream is not specified."))
	// 	cmd.Usage()
	// 	os.Exit(1)
	// }

	if rootFlag.verbose {
		fmt.Printf("Local flags: %#v\n", _getFlags)
	}
}

func getRun(cmd *cobra.Command, args []string) {
	// fmt.Printf(">>>>> _getFlags: %#v\n", _getFlags)

	cwlogsClient := Aws.NewCloudWatchLogsClient(rootFlag.GetCloudWatchLogsClientParams())

	var nextToken *string

Start:
	var err error
	if _getFlags.Pattern != "" || _getFlags.Log.Stream == "" {
		options := _getFlags.GetCloudWatchLogsFilterLogEventsParam(nextToken)
		if rootFlag.verbose {
			fmt.Printf("FilterLogEvents: options=%v\n", options)
		}
		err = cwlogsClient.FilterLogEvents(&options, func(out *cloudwatchlogs.FilterLogEventsOutput) {
			printEvents(out.Events)
			nextToken = out.NextToken
		})
	} else {
		options := _getFlags.GetCloudWatchLogsGetLogEventsParam(nextToken)
		if rootFlag.verbose {
			fmt.Printf("GetLogEvents: options=%v\n", options)
		}
		err = cwlogsClient.GetLogEvents(&options, func(out *cloudwatchlogs.GetLogEventsOutput) {
			printEvents(out.Events)
			nextToken = out.NextForwardToken
		})
	}
	if _getFlags.Watch && nextToken != nil {
		if rootFlag.verbose {
			fmt.Printf("`watch` enabled. now sleep(%d) Zzz...\n", watchInterval)
		}
		time.Sleep(watchInterval * time.Second)
		if rootFlag.verbose {
			fmt.Println("`watch` enabled. wakeup now!")
		}
		goto Start
	}
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(2)
	}
}

func init() {
	RootCmd.AddCommand(getCmd)

	localFlags := getCmd.Flags()
	_getFlags.Log.Load(localFlags)
	_getFlags.TimeRange.Load(localFlags)
	localFlags.StringVarP(&_getFlags.Pattern, "filter-pattern", "f", "", "The filter pattern to use. If not provided, all the events are matched.")
	localFlags.BoolVarP(&_getFlags.Watch, "watch", "w", false, "Do not stop when end of log is reached, but rather to wait for additional data to be appended to the input.")

	// There is no guarantee that _getFlags will have a value here
	// I do not know until getRun function
}
<commit_msg>DefaultGroup,DefaultStreamの読み込みを削除<commit_after>// Copyright © 2017 NAME HERE <EMAIL ADDRESS>
// 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 cmd

import (
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
	Aws "github.com/cm-igarashi-ryosuke/lazy-awslogs/lib/aws"
	"github.com/spf13/cobra"

	"github.com/cm-igarashi-ryosuke/lazy-awslogs/lib/flags"
)

type GetFlags struct {
	Profile      string
	Region       string
	Log          flags.CWLogIdentifyFlags
	Pattern      string
	TimeRange    flags.CWLogTimeRange
	Watch        bool
}

const watchInterval = 5 // seconds

// Create FilterLogEventsInput by GetFlags
func (this *GetFlags) GetCloudWatchLogsFilterLogEventsParam(nextToken *string) cloudwatchlogs.FilterLogEventsInput {
	input := cloudwatchlogs.FilterLogEventsInput{
		LogGroupName: &this.Log.Group,
		NextToken:    nextToken,
	}
	if this.Pattern != "" {
		pattern := fmt.Sprintf("\"%s\"", this.Pattern)
		input.FilterPattern = &pattern
	}
	if this.Log.Stream != "" {
		input.LogStreamNames = []*string{&this.Log.Stream}
	}
	if startTime := this.TimeRange.StartTimeMilliseconds(); startTime != 0 {
		input.StartTime = &startTime
	}
	if endTime := this.TimeRange.EndTimeMilliseconds(); endTime != 0 {
		input.EndTime = &endTime
	}
	return input
}

// Create GetLogEventsInput by GetFlags
func (this *GetFlags) GetCloudWatchLogsGetLogEventsParam(nextToken *string) cloudwatchlogs.GetLogEventsInput {
	input := cloudwatchlogs.GetLogEventsInput{
		LogGroupName:  &this.Log.Group,
		LogStreamName: &this.Log.Stream,
		NextToken:     nextToken,
	}
	if startTime := this.TimeRange.StartTimeMilliseconds(); startTime != 0 {
		input.StartTime = &startTime
	}
	if endTime := this.TimeRange.EndTimeMilliseconds(); endTime != 0 {
		input.EndTime = &endTime
	}
	return input
}

// Print any events to stdout
func printEvents(any interface{}) {
	if events, ok := any.([]*cloudwatchlogs.FilteredLogEvent); ok {
		for _, event := range events {
			fmt.Println(strings.TrimRight(*event.Message, "\n"))
		}
	} else if events, ok := any.([]*cloudwatchlogs.OutputLogEvent); ok {
		for _, event := range events {
			fmt.Println(strings.TrimRight(*event.Message, "\n"))
		}
	}
}

var _getFlags = &GetFlags{}

// getCmd represents the get command
var getCmd = &cobra.Command{
	Use:   "get",
	Short: "Lists log events from the specified log stream.",
	Long: `Lists log events from the specified log stream. You can list all the log events or filter using a time range.

By default, this operation returns as many log events as can fit in a response  size of 1MB (up to 10,000 log events).
If the results include tokens, there are more log events available.
You can get additional log events by specifying one of the tokens in a subsequent call.`,
	Run:    getRun,
	PreRun: preRun,
}

func preRun(cmd *cobra.Command, args []string) {
	if rootFlag.profile == "" {
		fmt.Printf("%v\n\n", fmt.Errorf("Error: Profile is not specified."))
		cmd.Usage()
		os.Exit(1)
	}

	if _getFlags.Log.Group == "" {
		fmt.Printf("%v\n\n", fmt.Errorf("Error: Group is not specified."))
		cmd.Usage()
		os.Exit(1)
	}

	if rootFlag.verbose {
		fmt.Printf("Local flags: %#v\n", _getFlags)
	}
}

func getRun(cmd *cobra.Command, args []string) {
	// fmt.Printf(">>>>> _getFlags: %#v\n", _getFlags)

	cwlogsClient := Aws.NewCloudWatchLogsClient(rootFlag.GetCloudWatchLogsClientParams())

	var nextToken *string

Start:
	var err error
	if _getFlags.Pattern != "" || _getFlags.Log.Stream == "" {
		options := _getFlags.GetCloudWatchLogsFilterLogEventsParam(nextToken)
		if rootFlag.verbose {
			fmt.Printf("FilterLogEvents: options=%v\n", options)
		}
		err = cwlogsClient.FilterLogEvents(&options, func(out *cloudwatchlogs.FilterLogEventsOutput) {
			printEvents(out.Events)
			nextToken = out.NextToken
		})
	} else {
		options := _getFlags.GetCloudWatchLogsGetLogEventsParam(nextToken)
		if rootFlag.verbose {
			fmt.Printf("GetLogEvents: options=%v\n", options)
		}
		err = cwlogsClient.GetLogEvents(&options, func(out *cloudwatchlogs.GetLogEventsOutput) {
			printEvents(out.Events)
			nextToken = out.NextForwardToken
		})
	}
	if _getFlags.Watch && nextToken != nil {
		if rootFlag.verbose {
			fmt.Printf("`watch` enabled. now sleep(%d) Zzz...\n", watchInterval)
		}
		time.Sleep(watchInterval * time.Second)
		if rootFlag.verbose {
			fmt.Println("`watch` enabled. wakeup now!")
		}
		goto Start
	}
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(2)
	}
}

func init() {
	RootCmd.AddCommand(getCmd)

	localFlags := getCmd.Flags()
	_getFlags.Log.Load(localFlags)
	_getFlags.TimeRange.Load(localFlags)
	localFlags.StringVarP(&_getFlags.Pattern, "filter-pattern", "f", "", "The filter pattern to use. If not provided, all the events are matched.")
	localFlags.BoolVarP(&_getFlags.Watch, "watch", "w", false, "Do not stop when end of log is reached, but rather to wait for additional data to be appended to the input.")

	// There is no guarantee that _getFlags will have a value here
	// I do not know until getRun function
}
<|endoftext|>


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

package main

import (
	"encoding/binary"
	"fmt"
	"strings"
	"syscall"

	"github.com/TheNewNormal/corectl/components/host/session"
	"github.com/TheNewNormal/corectl/components/server"
	"github.com/TheNewNormal/corectl/components/target/coreos"
	"github.com/deis/pkg/log"
	"github.com/satori/go.uuid"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

var (
	runCmd = &cobra.Command{
		Use:     "run",
		Aliases: []string{"start"},
		Short:   "Boots a new CoreOS instance",
		RunE:    runCommand,
	}
)

func runCommand(cmd *cobra.Command, args []string) (err error) {
	var (
		vm  *server.VMInfo
		cli = session.Caller.CmdLine
	)

	if _, err = server.Daemon.Running(); err != nil {
		return session.ErrServerUnreachable
	}
	if vm, err = vmBootstrap(cli); err != nil {
		return
	}
	return bootIt(vm)
}

func bootIt(vm *server.VMInfo) (err error) {
	var reply = &server.RPCreply{}
	if reply, err =
		server.RPCQuery("Run", &server.RPCquery{VM: vm}); err != nil {
		return
	}
	log.Info("'%v' started successfuly with address %v and PID %v",
		reply.VM.Name, reply.VM.PublicIP, reply.VM.Pid)
	log.Info("'%v' boot logs can be found at '%v'",
		reply.VM.Name, reply.VM.Log())
	log.Info("'%v' console can be found at '%v'", reply.VM.Name, reply.VM.TTY())
	return
}

func vmBootstrap(args *viper.Viper) (vm *server.VMInfo, err error) {
	var (
		reply           = &server.RPCreply{}
		HostPhysicalMem uint64
		// only thing we need from github.com shirou/gopsutil
		getHwMemsize = func() (v uint64, err error) {
			var tStr string
			if tStr, err = syscall.Sysctl("hw.memsize"); err == nil {
				v = uint64(binary.LittleEndian.Uint64([]byte(tStr + "\x00")))
			}
			return
		}
	)
	vm = new(server.VMInfo)

	vm.OfflineMode = args.GetBool("offline")
	vm.Cpus = args.GetInt("cpus")
	vm.AddToHypervisor = args.GetString("extra")
	vm.AddToKernel = args.GetString("boot")
	vm.SSHkey = args.GetString("sshkey")
	vm.Pid = -1

	vm.Name = strings.ToLower(args.GetString("name"))
	vm.UUID = args.GetString("uuid")

	vm.Memory = args.GetInt("memory")
	if vm.Memory < 1024 {
		log.Warn("'%v' not a reasonable memory value. %s\n", vm.Memory,
			"Using '1024', the default")
		vm.Memory = 1024
	} else if vm.Memory > 8192 {
		log.Warn("'%v' not a reasonable memory value, as presently "+
			"we only support VMs with up to 8GB of RAM. setting "+
			"it to '8192'", vm.Memory)
		vm.Memory = 8192
	}

	if reply, err =
		server.RPCQuery("ActiveVMs", &server.RPCquery{}); err != nil {
		return
	}

	totalM := 0
	for _, v := range reply.Running {
		totalM = totalM + v.Memory
	}

	if HostPhysicalMem, err = getHwMemsize(); err != nil {
		return
	}

	if uint64(totalM+vm.Memory) > HostPhysicalMem/1024/1024*2/3 {
		err = fmt.Errorf("Aborted. Aggregated VMs memory usage would " +
			"become higher than 66pc of total host physical memory which " +
			"would lead to system unstability")
		return
	}

	if vm.UUID == "random" {
		vm.UUID = uuid.NewV4().String()
	} else if _, err = uuid.FromString(vm.UUID); err != nil {

		log.Warn("%s not a valid UUID as it doesn't follow RFC "+
			"4122. %s\n", vm.UUID, "Using a randomly generated one")
		vm.UUID = uuid.NewV4().String()
	}
	vm.UUID = strings.ToUpper(vm.UUID)

	reply, err = server.RPCQuery("UUIDtoMACaddr",
		&server.RPCquery{Input: []string{vm.UUID, args.GetString("uuid")}})
	if err != nil {
		return
	}
	vm.MacAddress, vm.UUID = reply.Output[0], reply.Output[1]

	vm.SharedHomedir = args.GetBool("shared-homedir")
	if vm.SharedHomedir == true {
		if reply, err = server.RPCQuery("HandlesNFS",
			&server.RPCquery{}); err != nil {
			return
		}
		if reply.WorkingNFS == false {
			log.Warn("NFS is qnot supported by running 'corectld'")
			vm.SharedHomedir = false
		}
	}

	if vm.Name == "" {
		vm.Name = vm.UUID
	}

	vm.Channel = coreos.Channel(args.GetString("channel"))

	vm.Version = coreos.Version(args.GetString("version"))
	vm.Version, err =
		server.PullImage(vm.Channel, vm.Version, false, vm.OfflineMode)
	if err != nil {
		return
	}

	vm.ValidateCDROM("")
	if args.GetBool("format-root") {
		if args.GetString("root") == "" {
			err = fmt.Errorf("unable to format root volume as it wasn't set...")
			return
		}
		vm.FormatRoot = true
	}
	if err = vm.ValidateVolumes([]string{args.GetString("root")},
		true); err != nil {
		return
	}
	if err = vm.ValidateVolumes(
		viperStringSliceBugWorkaround(args.GetStringSlice("volume")),
		false); err != nil {
		return
	}

	vm.Ethernet =
		append(vm.Ethernet, server.NetworkInterface{Type: server.Raw})

	err = vm.ValidateCloudConfig(args.GetString("cloud_config"))
	if err != nil {
		return
	}

	if err = vm.SSHkeyGen(); err != nil {
		err = fmt.Errorf("Aborting: unable to generate internal SSH "+
			"key pair (!) (%v)", err)
	}

	return
}

func runFlagsDefaults(setFlag *pflag.FlagSet) {
	setFlag.StringP("channel", "c", "alpha", "CoreOS channel stream")
	setFlag.StringP("version", "v", "latest", "CoreOS version")
	setFlag.StringP("uuid", "u", "random", "VM's UUID")
	setFlag.IntP("memory", "m", 1024,
		"VM's RAM, in MB, per instance (1024 < memory < 8192)")
	setFlag.IntP("cpus", "N", 1, "VM number of virtual CPUs")
	setFlag.StringP("cloud_config", "L", "",
		"cloud-config file location (either an URL or a local path)")
	setFlag.StringP("sshkey", "k", "", "VM's default ssh key")
	setFlag.StringP("root", "r", "", "append a (persistent) root volume to VM")
	setFlag.BoolP("format-root", "F", false,
		"formats and partitions the (persistent) root volume")
	setFlag.StringSliceP("volume", "p", nil, "append disk volumes to VM")
	setFlag.BoolP("offline", "o", false,
		"doesn't go online to check for newer images than the "+
			"locally available ones unless there is none available.")
	setFlag.StringP("name", "n", "",
		"names the VM (default is VM's UUID)")
	setFlag.BoolP("shared-homedir", "H", false,
		"mounts (via NFS) host's homedir inside VM")
	setFlag.StringP("extra", "x", "", "additional arguments to the hypervisor")
	setFlag.StringP("boot", "b", "", "additional arguments to the kernel boot")
	// available but hidden...
	setFlag.StringP("tap", "t", "", "append tap interface to VM")
	setFlag.MarkHidden("tap")
}

func init() {
	runFlagsDefaults(runCmd.Flags())
	if session.AppName() != "corectld" {
		rootCmd.AddCommand(runCmd)
	}
}
<commit_msg>fix typo<commit_after>// Copyright (c) 2016 by António Meireles  <antonio.meireles@reformi.st>.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package main

import (
	"encoding/binary"
	"fmt"
	"strings"
	"syscall"

	"github.com/TheNewNormal/corectl/components/host/session"
	"github.com/TheNewNormal/corectl/components/server"
	"github.com/TheNewNormal/corectl/components/target/coreos"
	"github.com/deis/pkg/log"
	"github.com/satori/go.uuid"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

var (
	runCmd = &cobra.Command{
		Use:     "run",
		Aliases: []string{"start"},
		Short:   "Boots a new CoreOS instance",
		RunE:    runCommand,
	}
)

func runCommand(cmd *cobra.Command, args []string) (err error) {
	var (
		vm  *server.VMInfo
		cli = session.Caller.CmdLine
	)

	if _, err = server.Daemon.Running(); err != nil {
		return session.ErrServerUnreachable
	}
	if vm, err = vmBootstrap(cli); err != nil {
		return
	}
	return bootIt(vm)
}

func bootIt(vm *server.VMInfo) (err error) {
	var reply = &server.RPCreply{}
	if reply, err =
		server.RPCQuery("Run", &server.RPCquery{VM: vm}); err != nil {
		return
	}
	log.Info("'%v' started successfuly with address %v and PID %v",
		reply.VM.Name, reply.VM.PublicIP, reply.VM.Pid)
	log.Info("'%v' boot logs can be found at '%v'",
		reply.VM.Name, reply.VM.Log())
	log.Info("'%v' console can be found at '%v'", reply.VM.Name, reply.VM.TTY())
	return
}

func vmBootstrap(args *viper.Viper) (vm *server.VMInfo, err error) {
	var (
		reply           = &server.RPCreply{}
		HostPhysicalMem uint64
		// only thing we need from github.com shirou/gopsutil
		getHwMemsize = func() (v uint64, err error) {
			var tStr string
			if tStr, err = syscall.Sysctl("hw.memsize"); err == nil {
				v = uint64(binary.LittleEndian.Uint64([]byte(tStr + "\x00")))
			}
			return
		}
	)
	vm = new(server.VMInfo)

	vm.OfflineMode = args.GetBool("offline")
	vm.Cpus = args.GetInt("cpus")
	vm.AddToHypervisor = args.GetString("extra")
	vm.AddToKernel = args.GetString("boot")
	vm.SSHkey = args.GetString("sshkey")
	vm.Pid = -1

	vm.Name = strings.ToLower(args.GetString("name"))
	vm.UUID = args.GetString("uuid")

	vm.Memory = args.GetInt("memory")
	if vm.Memory < 1024 {
		log.Warn("'%v' not a reasonable memory value. %s\n", vm.Memory,
			"Using '1024', the default")
		vm.Memory = 1024
	} else if vm.Memory > 8192 {
		log.Warn("'%v' not a reasonable memory value, as presently "+
			"we only support VMs with up to 8GB of RAM. setting "+
			"it to '8192'", vm.Memory)
		vm.Memory = 8192
	}

	if reply, err =
		server.RPCQuery("ActiveVMs", &server.RPCquery{}); err != nil {
		return
	}

	totalM := 0
	for _, v := range reply.Running {
		totalM = totalM + v.Memory
	}

	if HostPhysicalMem, err = getHwMemsize(); err != nil {
		return
	}

	if uint64(totalM+vm.Memory) > HostPhysicalMem/1024/1024*2/3 {
		err = fmt.Errorf("Aborted. Aggregated VMs memory usage would " +
			"become higher than 66pc of total host physical memory which " +
			"would lead to system unstability")
		return
	}

	if vm.UUID == "random" {
		vm.UUID = uuid.NewV4().String()
	} else if _, err = uuid.FromString(vm.UUID); err != nil {

		log.Warn("%s not a valid UUID as it doesn't follow RFC "+
			"4122. %s\n", vm.UUID, "Using a randomly generated one")
		vm.UUID = uuid.NewV4().String()
	}
	vm.UUID = strings.ToUpper(vm.UUID)

	reply, err = server.RPCQuery("UUIDtoMACaddr",
		&server.RPCquery{Input: []string{vm.UUID, args.GetString("uuid")}})
	if err != nil {
		return
	}
	vm.MacAddress, vm.UUID = reply.Output[0], reply.Output[1]

	vm.SharedHomedir = args.GetBool("shared-homedir")
	if vm.SharedHomedir == true {
		if reply, err = server.RPCQuery("HandlesNFS",
			&server.RPCquery{}); err != nil {
			return
		}
		if reply.WorkingNFS == false {
			log.Warn("NFS is not supported by the running 'corectld'")
			vm.SharedHomedir = false
		}
	}

	if vm.Name == "" {
		vm.Name = vm.UUID
	}

	vm.Channel = coreos.Channel(args.GetString("channel"))

	vm.Version = coreos.Version(args.GetString("version"))
	vm.Version, err =
		server.PullImage(vm.Channel, vm.Version, false, vm.OfflineMode)
	if err != nil {
		return
	}

	vm.ValidateCDROM("")
	if args.GetBool("format-root") {
		if args.GetString("root") == "" {
			err = fmt.Errorf("unable to format root volume as it wasn't set...")
			return
		}
		vm.FormatRoot = true
	}
	if err = vm.ValidateVolumes([]string{args.GetString("root")},
		true); err != nil {
		return
	}
	if err = vm.ValidateVolumes(
		viperStringSliceBugWorkaround(args.GetStringSlice("volume")),
		false); err != nil {
		return
	}

	vm.Ethernet =
		append(vm.Ethernet, server.NetworkInterface{Type: server.Raw})

	err = vm.ValidateCloudConfig(args.GetString("cloud_config"))
	if err != nil {
		return
	}

	if err = vm.SSHkeyGen(); err != nil {
		err = fmt.Errorf("Aborting: unable to generate internal SSH "+
			"key pair (!) (%v)", err)
	}

	return
}

func runFlagsDefaults(setFlag *pflag.FlagSet) {
	setFlag.StringP("channel", "c", "alpha", "CoreOS channel stream")
	setFlag.StringP("version", "v", "latest", "CoreOS version")
	setFlag.StringP("uuid", "u", "random", "VM's UUID")
	setFlag.IntP("memory", "m", 1024,
		"VM's RAM, in MB, per instance (1024 < memory < 8192)")
	setFlag.IntP("cpus", "N", 1, "VM number of virtual CPUs")
	setFlag.StringP("cloud_config", "L", "",
		"cloud-config file location (either an URL or a local path)")
	setFlag.StringP("sshkey", "k", "", "VM's default ssh key")
	setFlag.StringP("root", "r", "", "append a (persistent) root volume to VM")
	setFlag.BoolP("format-root", "F", false,
		"formats and partitions the (persistent) root volume")
	setFlag.StringSliceP("volume", "p", nil, "append disk volumes to VM")
	setFlag.BoolP("offline", "o", false,
		"doesn't go online to check for newer images than the "+
			"locally available ones unless there is none available.")
	setFlag.StringP("name", "n", "",
		"names the VM (default is VM's UUID)")
	setFlag.BoolP("shared-homedir", "H", false,
		"mounts (via NFS) host's homedir inside VM")
	setFlag.StringP("extra", "x", "", "additional arguments to the hypervisor")
	setFlag.StringP("boot", "b", "", "additional arguments to the kernel boot")
	// available but hidden...
	setFlag.StringP("tap", "t", "", "append tap interface to VM")
	setFlag.MarkHidden("tap")
}

func init() {
	runFlagsDefaults(runCmd.Flags())
	if session.AppName() != "corectld" {
		rootCmd.AddCommand(runCmd)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"compress/gzip"
	"flag"
	"fmt"
	"github.com/icha024/go-collect-logs/sse"
	"gopkg.in/mcuadros/go-syslog.v2"
	"gopkg.in/mcuadros/go-syslog.v2/format"
	"io"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"
)

// Gzip Compression
// Ref: https://gist.github.com/bryfry/09a650eb8aac0fb76c24
type gzipResponseWriter struct {
	io.Writer
	http.ResponseWriter
}

func (w gzipResponseWriter) Write(b []byte) (int, error) {
	return w.Writer.Write(b)
}

func main() {
	var maxLogEntries = flag.Int("max-log-entries", 50000, "Maximum number of log entries to keep. Approx 1KB/entry.")
	var maxFilterEntries = flag.Int("max-filter-entries", 100, "Maximum number of fitlered log entries to return.")
	var logReadInteval = flag.Int("log-read-inteval", 3, "Interval, in seconds, to read syslog into memory.")
	var syslogHost = flag.String("syslog-host", "0.0.0.0", "Syslog host to listen on.")
	var syslogPort = flag.Int("syslog-port", 10514, "Syslog port to listen on.")
	var host = flag.String("host", "0.0.0.0", "Service host to listen on.")
	var port = flag.Int("port", 3000, "Service port to listen on.")
	var enableParseSev = flag.Bool("sev", false, "Parse the syslog severity header")
	var enableStdout = flag.Bool("stdout", true, "Print syslog received to stdout")
	flag.Parse()

	channel := make(syslog.LogPartsChannel)
	handler := syslog.NewChannelHandler(channel)

	server := syslog.NewServer()
	server.SetFormat(syslog.Automatic)
	server.SetHandler(handler)
	syslogServerDetail := fmt.Sprintf("%s:%d", *syslogHost, *syslogPort)
	server.ListenUDP(syslogServerDetail)
	server.ListenTCP(syslogServerDetail)
	server.Boot()

	logArr := make([]string, *maxLogEntries, *maxLogEntries)
	var writeIdx int
	broker := sse.NewServer()
	fmt.Printf("Syslog collector started on: %s \n", syslogServerDetail)

	go func(channel syslog.LogPartsChannel) {
		var logEntry string
		for logParts := range channel {
			// fmt.Println(logParts)
			logEntry = *parseLogEntry(logParts, *enableParseSev)
			newWriteIdx := writeIdx + 1
			if newWriteIdx >= *maxLogEntries {
				newWriteIdx = 0
			}
			logArr[newWriteIdx] = logEntry
			writeIdx = newWriteIdx
			// fmt.Printf(logArr[newWriteIdx])
		}
	}(channel)

	ticker := time.NewTicker(time.Duration(*logReadInteval) * time.Second)
	go func() {
		var readIdx int
		for {
			select {
			case <-ticker.C:
				var buf bytes.Buffer
				tmp := writeIdx
				searchIdx := tmp
				for readIdx != searchIdx {
					buf.Write([]byte(logArr[searchIdx]))
					searchIdx--
				}
				if *enableStdout {
					for readIdx != writeIdx {
						fmt.Printf(logArr[readIdx])
						readIdx++
						if readIdx == *maxLogEntries {
							readIdx = 0
						}
					}
				}
				readIdx = tmp
				broker.Notifier <- buf.Bytes()
			}
		}
	}()

	http.HandleFunc("/filter", func(w http.ResponseWriter, r *http.Request) {
		// println("TRIGGER 1")
		query, err := url.QueryUnescape(r.URL.Query().Get("q"))
		if err != nil {
			println("invalid query: ", err)
			return
		}

		var buf bytes.Buffer
		searchIdx := writeIdx
		for i := 0; i < *maxLogEntries; i++ {
			if searchIdx < 0 {
				searchIdx = *maxLogEntries - 1
			}
			logEntry := logArr[searchIdx]
			match := true
			if len(query) > 0 {
				match = strings.Contains(logEntry, query)
			}

			if match {
				// fmt.Fprintf(w, "%s", logArr[searchIdx])
				buf.Write([]byte(logArr[searchIdx]))
			}
			if i > *maxFilterEntries {
				break
			}
			searchIdx--
		}
		// // fmt.Fprint(w, "hello")
		// // println("TRIGGER 2")
		// // fmt.Fprint(w, "hello")
		// bufWriter := bufio.NewWriter(w)
		// bufWriter.Write(buf.Bytes())
		// bufWriter.Flush()
		// // fmt.Fprint(w, buf)

		// fmt.Fprintf(w, "%s", buf)
		if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
			// handler.ServeHTTP(w, r)
			// w.Write(buf.Bytes())
			bufWriter := bufio.NewWriter(w)
			bufWriter.Write(buf.Bytes())
			bufWriter.Flush()
		}
		w.Header().Set("Content-Encoding", "gzip")
		w.Header().Set("Content-Type", "text/plain")
		gz := gzip.NewWriter(w)
		defer gz.Close()
		gzw := gzipResponseWriter{Writer: gz, ResponseWriter: w}
		gzw.Write(buf.Bytes())
		// handler.ServeHTTP(gzw, r)
	})
	http.Handle("/stream", broker)
	serverDetail := fmt.Sprintf("%s:%d", *host, *port)
	log.Fatal("HTTP server error: ", http.ListenAndServe(serverDetail, nil))
	server.Wait()
}

// func Gzip(handler http.Handler) http.Handler {
// 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 		if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
// 			handler.ServeHTTP(w, r)
// 		}
// 		w.Header().Set("Content-Encoding", "gzip")
// 		w.Header().Set("Content-Type", "text/plain")
// 		gz := gzip.NewWriter(w)
// 		defer gz.Close()
// 		gzw := gzipResponseWriter{Writer: gz, ResponseWriter: w}
// 		handler.ServeHTTP(gzw, r)
// 	})
// }

func parseLogEntry(logParts format.LogParts, enableParseSev bool) *string {
	// RFC3164
	// 	"timestamp": p.header.timestamp,
	// 	"hostname":  p.header.hostname,
	// 	"tag":       p.message.tag,
	// 	"content":   p.message.content,
	// 	"priority":  p.priority.P,
	// 	"facility":  p.priority.F.Value,
	// 	"severity":  p.priority.S.Value,

	// RFC5424
	// "priority":        p.header.priority.P,
	// "facility":        p.header.priority.F.Value,
	// "severity":        p.header.priority.S.Value,
	// "version":         p.header.version,
	// "timestamp":       p.header.timestamp,
	// "hostname":        p.header.hostname,
	// "app_name":        p.header.appName,
	// "proc_id":         p.header.procId,
	// "msg_id":          p.header.msgId,
	// "structured_data": p.structuredData,
	// "message":         p.message,

	ts := logParts["timestamp"]
	hostname := logParts["hostname"]
	tag := logParts["tag"]
	if tag == nil {
		tag = logParts["app_name"]
	}
	msg := logParts["message"]
	if msg == nil {
		msg = logParts["content"]
	}
	var logStr string
	if enableParseSev {
		sev := parseSeverity(logParts["severity"])
		logStr = fmt.Sprintf("[%s][%s][%s][%s]: %s\n", ts, hostname, tag, sev, msg)
	} else {
		logStr = fmt.Sprintf("[%s][%s][%s]: %s\n", ts, hostname, tag, msg)
	}
	return &logStr
}

func parseSeverity(sev interface{}) string {
	sevNum, ok := sev.(int)
	if !ok {
		return ""
	}
	switch sevNum {
	case 0:
		return "emerg"
	case 1:
		return "alert"
	case 2:
		return "crit"
	case 3:
		return "err"
	case 4:
		return "warning"
	case 5:
		return "notice"
	case 6:
		return "info"
	case 7:
		return "debug"
	}
	return ""
}
<commit_msg>Polishing<commit_after>package main

import (
	"bufio"
	"bytes"
	"compress/gzip"
	"flag"
	"fmt"
	"github.com/icha024/go-collect-logs/sse"
	"gopkg.in/mcuadros/go-syslog.v2"
	"gopkg.in/mcuadros/go-syslog.v2/format"
	"io"
	"log"
	"net/http"
	"net/url"
	"strings"
	"time"
)

// Gzip Compression
// Ref: https://gist.github.com/bryfry/09a650eb8aac0fb76c24
type gzipResponseWriter struct {
	io.Writer
	http.ResponseWriter
}

func (w gzipResponseWriter) Write(b []byte) (int, error) {
	return w.Writer.Write(b)
}

func main() {
	var maxLogEntries = flag.Int("max-log-entries", 50000, "Maximum number of log entries to keep. Approx 1KB/entry.")
	var maxFilterEntries = flag.Int("max-filter-entries", 100, "Maximum number of fitlered log entries to return.")
	var logReadInteval = flag.Int("log-read-inteval", 3, "Interval, in seconds, to read syslog into memory.")
	var syslogHost = flag.String("syslog-host", "0.0.0.0", "Syslog host to listen on.")
	var syslogPort = flag.Int("syslog-port", 10514, "Syslog port to listen on.")
	var host = flag.String("host", "0.0.0.0", "Service host to listen on.")
	var port = flag.Int("port", 3000, "Service port to listen on.")
	var enableParseSev = flag.Bool("sev", false, "Parse the syslog severity header")
	var enableStdout = flag.Bool("stdout", true, "Print syslog received to stdout")
	flag.Parse()

	channel := make(syslog.LogPartsChannel)
	handler := syslog.NewChannelHandler(channel)

	server := syslog.NewServer()
	server.SetFormat(syslog.Automatic)
	server.SetHandler(handler)
	syslogServerDetail := fmt.Sprintf("%s:%d", *syslogHost, *syslogPort)
	server.ListenUDP(syslogServerDetail)
	server.ListenTCP(syslogServerDetail)
	server.Boot()

	logArr := make([]string, *maxLogEntries, *maxLogEntries)
	var writeIdx int
	broker := sse.NewServer()
	fmt.Printf("Syslog collector started on: %s \n", syslogServerDetail)

	go func(channel syslog.LogPartsChannel) {
		var logEntry string
		for logParts := range channel {
			// fmt.Println(logParts)
			logEntry = *parseLogEntry(logParts, *enableParseSev)
			newWriteIdx := writeIdx + 1
			if newWriteIdx >= *maxLogEntries {
				newWriteIdx = 0
			}
			logArr[newWriteIdx] = logEntry
			writeIdx = newWriteIdx
			// fmt.Printf(logArr[newWriteIdx])
		}
	}(channel)

	ticker := time.NewTicker(time.Duration(*logReadInteval) * time.Second)
	go func() {
		var readIdx int
		for {
			select {
			case <-ticker.C:
				var buf bytes.Buffer
				tmp := writeIdx
				searchIdx := tmp
				for readIdx != searchIdx {
					buf.Write([]byte(logArr[searchIdx]))
					searchIdx--
				}
				if *enableStdout {
					for readIdx != writeIdx {
						fmt.Printf(logArr[readIdx])
						readIdx++
						if readIdx == *maxLogEntries {
							readIdx = 0
						}
					}
				}
				readIdx = tmp
				broker.Notifier <- buf.Bytes()
			}
		}
	}()

	http.HandleFunc("/filter", func(w http.ResponseWriter, r *http.Request) {
		query, err := url.QueryUnescape(r.URL.Query().Get("q"))
		if err != nil {
			println("invalid query: ", err)
			return
		}

		var buf bytes.Buffer
		searchIdx := writeIdx
		for i := 0; i < *maxLogEntries; i++ {
			if searchIdx < 0 {
				searchIdx = *maxLogEntries - 1
			}
			logEntry := logArr[searchIdx]
			match := true
			if len(query) > 0 {
				match = strings.Contains(logEntry, query)
			}

			if match {
				// fmt.Fprintf(w, "%s", logArr[searchIdx])
				buf.Write([]byte(logArr[searchIdx]))
			}
			if i > *maxFilterEntries {
				break
			}
			searchIdx--
		}
		if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
			w.Write(buf.Bytes())
		}
		w.Header().Set("Content-Encoding", "gzip")
		w.Header().Set("Content-Type", "text/plain")
		gz := gzip.NewWriter(w)
		defer gz.Close()
		gzw := gzipResponseWriter{Writer: gz, ResponseWriter: w}
		gzw.Write(buf.Bytes())
		// handler.ServeHTTP(gzw, r)
	})
	http.Handle("/stream", broker)
	serverDetail := fmt.Sprintf("%s:%d", *host, *port)
	log.Fatal("HTTP server error: ", http.ListenAndServe(serverDetail, nil))
	server.Wait()
}

func parseLogEntry(logParts format.LogParts, enableParseSev bool) *string {
	// RFC3164
	// 	"timestamp": p.header.timestamp,
	// 	"hostname":  p.header.hostname,
	// 	"tag":       p.message.tag,
	// 	"content":   p.message.content,
	// 	"priority":  p.priority.P,
	// 	"facility":  p.priority.F.Value,
	// 	"severity":  p.priority.S.Value,

	// RFC5424
	// "priority":        p.header.priority.P,
	// "facility":        p.header.priority.F.Value,
	// "severity":        p.header.priority.S.Value,
	// "version":         p.header.version,
	// "timestamp":       p.header.timestamp,
	// "hostname":        p.header.hostname,
	// "app_name":        p.header.appName,
	// "proc_id":         p.header.procId,
	// "msg_id":          p.header.msgId,
	// "structured_data": p.structuredData,
	// "message":         p.message,

	ts := logParts["timestamp"]
	hostname := logParts["hostname"]
	tag := logParts["tag"]
	if tag == nil {
		tag = logParts["app_name"]
	}
	msg := logParts["message"]
	if msg == nil {
		msg = logParts["content"]
	}
	var logStr string
	if enableParseSev {
		sev := parseSeverity(logParts["severity"])
		logStr = fmt.Sprintf("[%s][%s][%s][%s]: %s\n", ts, hostname, tag, sev, msg)
	} else {
		logStr = fmt.Sprintf("[%s][%s][%s]: %s\n", ts, hostname, tag, msg)
	}
	return &logStr
}

func parseSeverity(sev interface{}) string {
	sevNum, ok := sev.(int)
	if !ok {
		return ""
	}
	switch sevNum {
	case 0:
		return "emerg"
	case 1:
		return "alert"
	case 2:
		return "crit"
	case 3:
		return "err"
	case 4:
		return "warning"
	case 5:
		return "notice"
	case 6:
		return "info"
	case 7:
		return "debug"
	}
	return ""
}
<|endoftext|>


<commit_before>package gocalc

import (
	_ "fmt"
	"strings"
	"testing"
)

func TestLexDigit(t *testing.T) {
	s := "1"
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenNumber, t)
	checkVal(to, s, t)
}

func TestLexMultiDigit(t *testing.T) {
	s := "111"
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenNumber, t)
	checkVal(to, s, t)
}

func TestLexMultipleNumbers(t *testing.T) {
	s := "1 2 3"
	l := newLexer(s)

	strs := strings.Split(s, " ")
	for _, str := range strs {
		to := l.token()
		checkType(to, tokenNumber, t)
		checkVal(to, str, t)
	}
}

func TestLexNumberWithLeadingWhitespace(t *testing.T) {
	s := "5"
	l := newLexer("  " + s)
	to := l.token()

	checkType(to, tokenNumber, t)
	checkVal(to, s, t)
}

func TestLexNumberWithSurroundingWhitespace(t *testing.T) {
	s := "99"
	l := newLexer("  " + s + "  ")
	to := l.token()

	checkType(to, tokenNumber, t)
	checkVal(to, s, t)
}

func TestLexPlus(t *testing.T) {
	s := "+"
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenPlus, t)
}

func TestLexMinus(t *testing.T) {
	s := "-"
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenMinus, t)
}

func TestLexLeftParen(t *testing.T) {
	s := "("
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenLeftParen, t)
}

func TestLexRightParen(t *testing.T) {
	s := ")"
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenRightParen, t)
}

func checkVal(to token, exp string, t *testing.T) {
	if to.val != exp {
		t.Errorf("Wrong token value: %s", to.val)
	}
}

func checkType(to token, exp tokenType, t *testing.T) {
	if to.typ != exp {
		t.Errorf("Wrong token type: %d", to.typ)
	}
}

/*
func TestLexMultipleNumbers(t *testing.T) {
	str := " 1 2 3 44 123 "
	errs := testLex(t, str, NumberToken, []string{"1", "2", "3", "44", "123"})
	if errs != nil {
		for _, err := range errs {
			t.Errorf("Error: %s", err.Error())
		}
	}
}

func TestLexWhitespace(t *testing.T) {
	strs := []string{"", "  "}
	for _, str := range strs {
		err := testLexSingle(t, str, 0, "")
		if err == nil {
			t.Error("Did not error")
		}
	}
}

func TestLexPlus(t *testing.T) {
	str := "+"
	err := testLexSingle(t, str, PlusToken, str)
	if err != nil {
		t.Error(err.Error())
	}
}

func testLexSingle(t *testing.T, sequence string, expectedType int, expectedValue string) error {
	l := NewLexer([]byte(sequence))
	token, err := l.Token()

	if err != nil {
		return err
	}

	if token.Type != expectedType {
		t.Errorf("Wrong token type: %d", token.Type)
	}

	if token.Value == "" {
		t.Error("Token value is empty")
	} else if token.Value != expectedValue {
		t.Errorf("Wrong token value: %s", token.Value)
	}
	return nil
}

func testLex(t *testing.T, sequence string, expectedType int, expectedValues []string) []error {
	l := NewLexer([]byte(sequence))
	errs := []error{}
	for _, expectedValue := range expectedValues {
		token, err := l.Token()

		if err != nil {
			errs = append(errs, err)
			continue
		}

		if token.Type != expectedType {
			t.Errorf("Wrong token type: %d", token.Type)
		}

		if token.Value == "" {
			t.Error("Token value is empty")
		} else if token.Value != expectedValue {
			t.Errorf("Wrong token value: %sz", token.Value)
		}
	}

	if len(errs) > 0 {
		return errs
	}

	return nil
}*/
<commit_msg>A few more lexer tests<commit_after>package gocalc

import (
	_ "fmt"
	"strings"
	"testing"
)

func TestLexDigit(t *testing.T) {
	s := "1"
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenNumber, t)
	checkVal(to, s, t)
}

func TestLexMultiDigit(t *testing.T) {
	s := "111"
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenNumber, t)
	checkVal(to, s, t)
}

func TestLexMultipleNumbers(t *testing.T) {
	s := "1 2 3"
	l := newLexer(s)

	strs := strings.Split(s, " ")
	for _, str := range strs {
		to := l.token()
		checkType(to, tokenNumber, t)
		checkVal(to, str, t)
	}
}

func TestLexNumberWithLeadingWhitespace(t *testing.T) {
	s := "5"
	l := newLexer("  " + s)
	to := l.token()

	checkType(to, tokenNumber, t)
	checkVal(to, s, t)
}

func TestLexNumberWithSurroundingWhitespace(t *testing.T) {
	s := "99"
	l := newLexer("  " + s + "  ")
	to := l.token()

	checkType(to, tokenNumber, t)
	checkVal(to, s, t)
}

func TestLexPlus(t *testing.T) {
	s := "+"
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenPlus, t)
}

func TestLexMinus(t *testing.T) {
	s := "-"
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenMinus, t)
}

func TestLexLeftParen(t *testing.T) {
	s := "("
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenLeftParen, t)
}

func TestLexRightParen(t *testing.T) {
	s := ")"
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenRightParen, t)
}

func TestLexNumberWithSurroundingParentheses(t *testing.T) {
	s := "(5)"
	l := newLexer(s)
	to := l.token()

	checkType(to, tokenLeftParen, t)

	to = l.token()
	checkType(to, tokenNumber, t)
	checkVal(to, "5", t)

	to = l.token()
	checkType(to, tokenRightParen, t)
}

func TestLexComplex(t *testing.T) {
	s := "5 - (10 - 5)"
	l := newLexer(s)
	eTypes := []tokenType{tokenNumber, tokenMinus, tokenLeftParen, tokenNumber, tokenMinus, tokenNumber, tokenRightParen}
	eVals := []string{"5", "-", "(", "10", "-", "5", ")"}

	for i, eType := range eTypes {
		eVal := eVals[i]
		to := l.token()

		checkType(to, eType, t)
		checkVal(to, eVal, t)
	}
}

func checkVal(to token, exp string, t *testing.T) {
	if to.val != exp {
		t.Errorf("Wrong token value: %s", to.val)
	}
}

func checkType(to token, exp tokenType, t *testing.T) {
	if to.typ != exp {
		t.Errorf("Wrong token type: %d", to.typ)
	}
}

/*
func TestLexMultipleNumbers(t *testing.T) {
	str := " 1 2 3 44 123 "
	errs := testLex(t, str, NumberToken, []string{"1", "2", "3", "44", "123"})
	if errs != nil {
		for _, err := range errs {
			t.Errorf("Error: %s", err.Error())
		}
	}
}

func TestLexWhitespace(t *testing.T) {
	strs := []string{"", "  "}
	for _, str := range strs {
		err := testLexSingle(t, str, 0, "")
		if err == nil {
			t.Error("Did not error")
		}
	}
}

func TestLexPlus(t *testing.T) {
	str := "+"
	err := testLexSingle(t, str, PlusToken, str)
	if err != nil {
		t.Error(err.Error())
	}
}

func testLexSingle(t *testing.T, sequence string, expectedType int, expectedValue string) error {
	l := NewLexer([]byte(sequence))
	token, err := l.Token()

	if err != nil {
		return err
	}

	if token.Type != expectedType {
		t.Errorf("Wrong token type: %d", token.Type)
	}

	if token.Value == "" {
		t.Error("Token value is empty")
	} else if token.Value != expectedValue {
		t.Errorf("Wrong token value: %s", token.Value)
	}
	return nil
}

func testLex(t *testing.T, sequence string, expectedType int, expectedValues []string) []error {
	l := NewLexer([]byte(sequence))
	errs := []error{}
	for _, expectedValue := range expectedValues {
		token, err := l.Token()

		if err != nil {
			errs = append(errs, err)
			continue
		}

		if token.Type != expectedType {
			t.Errorf("Wrong token type: %d", token.Type)
		}

		if token.Value == "" {
			t.Error("Token value is empty")
		} else if token.Value != expectedValue {
			t.Errorf("Wrong token value: %sz", token.Value)
		}
	}

	if len(errs) > 0 {
		return errs
	}

	return nil
}*/
<|endoftext|>


<commit_before>package gmock_test

import (
	. "github.com/cfmobile/gmock"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

const (
	kOriginalValue = "original value"
	kMockValue = "mock value"
)

var _ = Describe("GMock", func() {
	var subject *GMock // Test subject

	var constructSubject func()
	var panicked bool

	var someVar string // Target variable to mock in our tests
	var mockValue string // Variable containing the mock value to be set to the target

	BeforeEach(func() { // Reset all base values for each test
		subject = nil
		constructSubject = nil
		panicked = false
		someVar = kOriginalValue
		mockValue = kMockValue
	})

	var panicRecover = func() {
		panicked = recover() != nil
	}

	JustBeforeEach(func() {
		defer panicRecover()
		constructSubject()
	})

	Describe("MockTarget", func() {

		Context("when creating a new GMock with a target", func() {

			Context("and the target is not passed as a pointer", func() {
				BeforeEach(func() {
					constructSubject = func() {
						subject = CreateMockWithTarget(someVar)
					}
				})

				It("should panic", func() {
					Expect(panicked).To(BeTrue())
				})

				It("should not have constructed the mock", func() {
				    Expect(subject).To(BeNil())
				})
			})

			Context("and the target is passed as a pointer", func() {
				BeforeEach(func() {
					constructSubject = func() {
						subject = CreateMockWithTarget(&someVar)
					}
				})

				It("should not panic", func() {
					Expect(panicked).To(BeFalse())
				})

				It("should return a valid GMock object", func() {
					Expect(subject).NotTo(BeNil())
				})

				It("should not have altered the value of the target", func() {
					Expect(someVar).To(Equal(kOriginalValue))
				})

				It("should have backed up the pointer to the original target", func() {
					var originalPtr = subject.GetOriginal().Addr().Interface()
					Expect(originalPtr).To(Equal(&someVar))
				})

				It("should not have a mock value defined by default", func() {
					var mockTargetPtr = subject.GetTarget().Addr().Interface()
					Expect(mockTargetPtr).To(Equal(&someVar))
				})
			})
	    })
	})

	Describe("GMock", func() {

		BeforeEach(func() {
		    constructSubject = func() { // Construct a valid GMock for this set of tests
				subject = CreateMockWithTarget(&someVar)
			}
		})

	    Context("when calling Replace on a GMock object with a valid mock value", func() {

	        JustBeforeEach(func() { // It has to be a JustBeforeEach so that it happens after subject is constructed
	            subject.Replace(mockValue)
	        })

			It("should replace the value in the original var with the mock value", func() {
			    Expect(someVar).To(Equal(kMockValue))
			})

			It("should have retained the original value for restoring later", func() {
				Expect(subject.GetOriginal().Interface()).To(Equal(kOriginalValue))
			})

			It("should have a Target that points to the mock value", func() {
			    Expect(subject.GetTarget().Interface()).To(Equal(mockValue))
			})
	    })

		Context("when calling Replace on a GMock object with an invalid mock value", func() {

			It("should not have panicked when creating the mock", func() {
			    Expect(panicked).To(BeFalse())
			})

			Context("- mock value with a different type", func() {
				invalidMockValue := 21

				JustBeforeEach(func() {
					defer panicRecover()
					subject.Replace(invalidMockValue)
				})

				It("should have panicked", func() {
					Expect(panicked).To(BeTrue())
				})
			})

			Context("- mock value is a pointer to the same type as the target", func() {

				JustBeforeEach(func() {
				    defer panicRecover()
					subject.Replace(&mockValue)
				})

				It("should have panicked", func() {
				    Expect(panicked).To(BeTrue())
				})
			})

			Context("- mock value is nil", func() {
			    JustBeforeEach(func() {
					defer panicRecover()
			        subject.Replace(nil)
			    })

				It("should not have panicked", func() {
				    Expect(panicked).To(BeFalse())
				})

				It("should have assigned a default value of that type to the mock", func() {
				    Expect(someVar).To(Equal(""))
				})
			})
		})
	})

})
<commit_msg>RS - Added GMock.Restore() tests<commit_after>package gmock_test

import (
	. "github.com/cfmobile/gmock"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

const (
	kOriginalValue = "original value"
	kMockValue = "mock value"
)

var _ = Describe("GMock", func() {
	var subject *GMock // Test subject

	var constructSubject func()
	var panicked bool

	var someVar string // Target variable to mock in our tests
	var mockValue string // Variable containing the mock value to be set to the target

	BeforeEach(func() { // Reset all base values for each test
		subject = nil
		constructSubject = nil
		panicked = false
		someVar = kOriginalValue
		mockValue = kMockValue
	})

	var panicRecover = func() {
		panicked = recover() != nil
	}

	JustBeforeEach(func() {
		defer panicRecover()
		constructSubject()
	})

	Describe("MockTarget", func() {

		Context("when creating a new GMock with a target", func() {

			Context("and the target is not passed as a pointer", func() {
				BeforeEach(func() {
					constructSubject = func() {
						subject = CreateMockWithTarget(someVar)
					}
				})

				It("should panic", func() {
					Expect(panicked).To(BeTrue())
				})

				It("should not have constructed the mock", func() {
				    Expect(subject).To(BeNil())
				})
			})

			Context("and the target is passed as a pointer", func() {
				BeforeEach(func() {
					constructSubject = func() {
						subject = CreateMockWithTarget(&someVar)
					}
				})

				It("should not panic", func() {
					Expect(panicked).To(BeFalse())
				})

				It("should return a valid GMock object", func() {
					Expect(subject).NotTo(BeNil())
				})

				It("should not have altered the value of the target", func() {
					Expect(someVar).To(Equal(kOriginalValue))
				})

				It("should have backed up the pointer to the original target", func() {
					var originalPtr = subject.GetOriginal().Addr().Interface()
					Expect(originalPtr).To(Equal(&someVar))
				})

				It("should not have a mock value defined by default", func() {
					var mockTargetPtr = subject.GetTarget().Addr().Interface()
					Expect(mockTargetPtr).To(Equal(&someVar))
				})
			})
	    })
	})

	Describe("GMock", func() {

		BeforeEach(func() {
		    constructSubject = func() { // Construct a valid GMock for this set of tests
				subject = CreateMockWithTarget(&someVar)
			}
		})

	    Context("when calling Replace on a GMock object with a valid mock value", func() {

	        JustBeforeEach(func() { // It has to be a JustBeforeEach so that it happens after subject is constructed
	            subject.Replace(mockValue)
	        })

			It("should replace the value in the original var with the mock value", func() {
			    Expect(someVar).To(Equal(kMockValue))
			})

			It("should have retained the original value for restoring later", func() {
				Expect(subject.GetOriginal().Interface()).To(Equal(kOriginalValue))
			})

			It("should have a Target that points to the mock value", func() {
			    Expect(subject.GetTarget().Interface()).To(Equal(mockValue))
			})
	    })

		Context("when calling Replace on a GMock object with an invalid mock value", func() {

			It("should not have panicked when creating the mock", func() {
			    Expect(panicked).To(BeFalse())
			})

			Context("- mock value with a different type", func() {
				invalidMockValue := 21

				JustBeforeEach(func() {
					defer panicRecover()
					subject.Replace(invalidMockValue)
				})

				It("should have panicked", func() {
					Expect(panicked).To(BeTrue())
				})
			})

			Context("- mock value is a pointer to the same type as the target", func() {

				JustBeforeEach(func() {
				    defer panicRecover()
					subject.Replace(&mockValue)
				})

				It("should have panicked", func() {
				    Expect(panicked).To(BeTrue())
				})
			})

			Context("- mock value is nil", func() {
			    JustBeforeEach(func() {
					defer panicRecover()
			        subject.Replace(nil)
			    })

				It("should not have panicked", func() {
				    Expect(panicked).To(BeFalse())
				})

				It("should have assigned a default value of that type to the mock", func() {
				    Expect(someVar).To(Equal(""))
				})
			})
		})

		Context("before calling Restore on a GMock with a mock value set", func() {

			JustBeforeEach(func() {
			    subject.Replace(mockValue)
			})

			It("the target should equal to the mock value", func() {
			    Expect(someVar).To(Equal(kMockValue))
			})

			Context("when Restore is called", func() {
			    JustBeforeEach(func() {
			        subject.Restore()
			    })

				It("should have restored the target to the original value", func() {
				    Expect(someVar).To(Equal(kOriginalValue))
				})
			})
		})
	})

})
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"koding/oskite"
	"koding/terminal"
	"koding/tools/build"
	"koding/tools/config"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"text/template"

	"github.com/koding/kite/reverseproxy"
)

var (
	flagProfile     = flag.String("c", "", "Define config profile to be included")
	flagRegion      = flag.String("r", "", "Define region profile to be included")
	flagEnvironment = flag.String("e", "", "Define environment profile to be included")
	flagHost        = flag.String("h", "", "Define hostname for kite reveseproxy")
	flagApp         = flag.String("a", "", "App to be build")
	flagBuildNumber = flag.Int("b", 0, "Build number is added to the generated file if specified")

	// kontrolproxy specific flags
	flagProxy = flag.String("p", "", "Select user proxy or koding proxy") // Proxy only

	flagDisableUpstart = flag.Bool("u", false, "Disable including upstart script")
	flagDebug          = flag.Bool("d", false, "Enable debug mode")

	packages = map[string]func() error{
		"oskite":       buildOsKite,
		"kontrolproxy": buildKontrolProxy,
		"reverseproxy": buildProxyKite,
		"terminal":     buildTerminal,
		"kontrol":      buildKontrol,
		"klient":       buildKlient,
	}
)

type pkg struct {
	appName       string
	importPath    string
	files         []string
	version       string
	upstartScript string
	symbolname    string
	symbolvalue   string
}

func main() {
	flag.Parse()
	if *flagApp == "" {
		fmt.Printf("Please define package with -a to be build. Available apps:\n%s\n", packageList())
		os.Exit(1)
	}

	build, ok := packages[*flagApp]
	if !ok {
		log.Fatal("package to be build is not available")
	}

	if err := build(); err != nil {
		fmt.Println(err)
	}
}

func packageList() string {
	pkgs := "\n"
	count := 1
	for pkg := range packages {
		pkgs += strconv.Itoa(count) + ". " + pkg + "\n"
		count++
	}

	return pkgs
}

func buildProxyKite() error {
	if *flagEnvironment == "" || *flagRegion == "" || *flagHost == "" {
		return errors.New("Please define environment -e , region -r and host -h")
	}

	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return errors.New("GOPATH is not set")
	}

	importPath := "github.com/koding/kite/reverseproxy/reverseproxy"
	upstartPath := filepath.Join(gopath, "src/koding/kites/reverseproxy/files/reverseproxy.conf")

	temps := struct {
		Environment string
		Region      string
		Host        string
	}{
		Environment: *flagEnvironment,
		Region:      *flagRegion,
		Host:        *flagHost,
	}

	files := []string{}
	files = append(files, "certs/koding_com_cert.pem", "certs/koding_com_key.pem")

	// change our upstartscript because it's a template
	configUpstart, err := prepareUpstart(upstartPath, temps)
	if err != nil {
		return err
	}
	defer os.Remove(configUpstart)

	kiteproxy := pkg{
		appName:       *flagApp,
		importPath:    importPath,
		files:         files,
		version:       reverseproxy.Version,
		upstartScript: configUpstart,
	}

	return kiteproxy.build()
}

func buildKlient() error {
	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return errors.New("GOPATH is not set")
	}

	importPath := "koding/kites/klient"
	upstartPath := filepath.Join(gopath, "src", importPath, "files/klient.conf")

	symbolvalue := "0.0.1"
	if *flagBuildNumber != 0 {
		symbolvalue = "0.1." + strconv.Itoa(*flagBuildNumber)
	}

	kclient := pkg{
		appName:       *flagApp,
		importPath:    importPath,
		version:       "0.0.1",
		upstartScript: upstartPath,
		symbolname:    "koding/kites/klient/protocol.Version",
		symbolvalue:   symbolvalue,
	}

	return kclient.build()
}

func buildKontrol() error {
	if *flagProfile == "" || *flagRegion == "" {
		return errors.New("Please define config -c and region -r")
	}

	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return errors.New("GOPATH is not set")
	}

	kontrolPath := "koding/kites/kontrol"
	temps := struct {
		Profile string
		Region  string
	}{
		Profile: *flagProfile,
		Region:  *flagRegion,
	}

	var files = make([]string, 0)
	files = append(files, filepath.Join(gopath, "src", kontrolPath, "files"))

	// change our upstartscript because it's a template
	var configUpstart string
	var err error
	if !*flagDisableUpstart {
		kontrolUpstart := filepath.Join(gopath, "src", kontrolPath, "files/kontrol.conf")
		configUpstart, err = prepareUpstart(kontrolUpstart, temps)
		if err != nil {
			return err
		}
		defer os.Remove(configUpstart)
	}

	term := pkg{
		appName:       *flagApp,
		importPath:    kontrolPath,
		files:         files,
		version:       "0.1.0",
		upstartScript: configUpstart,
	}

	return term.build()
}

func buildTerminal() error {
	if *flagProfile == "" || *flagRegion == "" {
		return errors.New("Please define config -c and region -r")
	}

	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return errors.New("GOPATH is not set")
	}

	terminalPath := "koding/kites/terminal"
	terminalPackage := "koding/terminal"
	temps := struct {
		Profile string
		Region  string
	}{
		Profile: *flagProfile,
		Region:  *flagRegion,
	}

	var files = make([]string, 0)
	files = append(files, filepath.Join(gopath, "src", terminalPackage, "files"))

	// change our upstartscript because it's a template
	var configUpstart string
	var err error
	if !*flagDisableUpstart {
		terminalUpstart := filepath.Join(gopath, "src", terminalPackage, "files/terminal.conf")
		configUpstart, err = prepareUpstart(terminalUpstart, temps)
		if err != nil {
			return err
		}
		defer os.Remove(configUpstart)
	}

	term := pkg{
		appName:       *flagApp,
		importPath:    terminalPath,
		files:         files,
		version:       terminal.TERMINAL_VERSION,
		upstartScript: configUpstart,
	}

	return term.build()
}

func buildOsKite() error {
	if *flagProfile == "" || *flagRegion == "" {
		return errors.New("Please define config -c and region -r")
	}

	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return errors.New("GOPATH is not set")
	}

	oskitePath := "koding/kites/os"
	oskitePackage := "koding/oskite"
	temps := struct {
		Profile string
		Region  string
	}{
		Profile: *flagProfile,
		Region:  *flagRegion,
	}

	var files = make([]string, 0)
	files = append(files, filepath.Join(gopath, "src", oskitePackage, "files"))
	files = append(files, filepath.Join(gopath, "bin-vagrant/vmtool")) // TODO add it to the list of importPaths

	// change our upstartscript because it's a template
	var configUpstart string
	var err error
	if !*flagDisableUpstart {
		oskiteUpstart := filepath.Join(gopath, "src", oskitePackage, "files/oskite.conf")
		configUpstart, err = prepareUpstart(oskiteUpstart, temps)
		if err != nil {
			return err
		}
		defer os.Remove(configUpstart)
	}

	oskite := pkg{
		appName:       *flagApp,
		importPath:    oskitePath,
		files:         files,
		version:       oskite.OSKITE_VERSION,
		upstartScript: configUpstart,
	}

	return oskite.build()
}

func buildKontrolProxy() error {
	if *flagProfile == "" || *flagRegion == "" {
		return errors.New("Please define config -c and region -r")
	}

	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return errors.New("GOPATH is not set")
	}

	kdproxyPath := "koding/kontrol/kontrolproxy"

	temps := struct {
		Profile   string
		Region    string
		UserProxy string
	}{
		Profile: *flagProfile,
		Region:  *flagRegion,
	}

	var files = make([]string, 0)
	switch *flagProxy {
	case "koding":
		files = append(files, "certs/koding_com_cert.pem", "certs/koding_com_key.pem")
	case "y":
		files = append(files, "certs/y_koding_com_cert.pem", "certs/y_koding_com_key.pem")
	case "x":
		files = append(files, "certs/x_koding_com_cert.pem", "certs/x_koding_com_key.pem")
	case "user":
		temps.UserProxy = "-v"
		files = append(files, "certs/kd_io_cert.pem", "certs/kd_io_key.pem")
	default:
		return errors.New("Please define certs to be included with -p. Available certs: [user | koding | x | y]")
	}

	files = append(files, filepath.Join(gopath, "src", kdproxyPath, "files"))

	// change our upstartscript because it's a template
	var configUpstart string
	var err error
	if !*flagDisableUpstart {
		kdproxyUpstart := filepath.Join(gopath, "src", kdproxyPath, "files/kontrolproxy.conf")
		configUpstart, err = prepareUpstart(kdproxyUpstart, temps)
		if err != nil {
			return err
		}
		defer os.Remove(configUpstart)
	}

	kontrolproxy := pkg{
		appName:       *flagApp,
		importPath:    kdproxyPath,
		files:         files,
		version:       "0.0.9",
		upstartScript: configUpstart,
	}

	return kontrolproxy.build()
}

func (p *pkg) build() error {
	if *flagProfile == "" || *flagRegion == "" {
		fmt.Printf("building '%s'\n", *flagApp)
	} else {
		fmt.Printf("building '%s' for config '%s' and region '%s'\n", *flagApp, *flagProfile, *flagRegion)

		// prepare config folder
		tempDir, err := ioutil.TempDir(".", "gopackage_")
		if err != nil {
			return err
		}
		defer os.RemoveAll(tempDir)

		configDir := filepath.Join(tempDir, "config")
		os.MkdirAll(configDir, 0755)

		// koding-config-manager needs it
		err = ioutil.WriteFile("VERSION", []byte(p.version), 0755)
		if err != nil {
			return err
		}
		defer os.Remove("VERSION")

		c, err := config.ReadConfigManager(*flagProfile)
		if err != nil {
			return err
		}

		configPretty, err := json.MarshalIndent(c, "", "  ")
		if err != nil {
			return err
		}

		configFile := filepath.Join(configDir, fmt.Sprintf("main.%s.json", *flagProfile))
		err = ioutil.WriteFile(configFile, configPretty, 0644)
		if err != nil {
			return err
		}

		p.files = append(p.files, configDir)
	}

	// Now it's time to build
	if runtime.GOOS != "linux" {
		return errors.New("Not supported. Please run on a linux machine.")
	}

	deb := &build.Deb{
		Debug:         *flagDebug,
		AppName:       p.appName,
		Version:       p.version,
		ImportPath:    p.importPath,
		Files:         strings.Join(p.files, ","),
		InstallPrefix: "opt/kite",
		UpstartScript: p.upstartScript,
		SymbolName:    p.symbolname,
		SymbolValue:   p.symbolvalue,
	}

	debFile, err := deb.Build()
	if err != nil {
		log.Println("linux:", err)
	}

	// customize our created file with the passed arguments
	oldname := debFile

	newname := p.appName + "_" + p.version
	if *flagBuildNumber != 0 {
		// http://semver.org/ see build-number paragraph
		newname = p.appName + "_0.1." + strconv.Itoa(*flagBuildNumber)
	}

	if *flagProfile == "" || *flagRegion == "" {
		newname += fmt.Sprintf("_%s.deb", deb.Arch)
	} else {
		newname += fmt.Sprintf("_%s-%s_%s.deb", *flagProfile, *flagRegion, deb.Arch)
	}

	if err := os.Rename(oldname, newname); err != nil {
		return err
	}

	fmt.Printf("success '%s' is ready. Some helpful commands for you:\n\n", newname)
	fmt.Printf("  show deb content   : dpkg -c %s\n", newname)
	fmt.Printf("  show basic info    : dpkg -f %s\n", newname)
	fmt.Printf("  install to machine : dpkg -i %s\n\n", newname)

	return nil
}

func prepareUpstart(path string, v interface{}) (string, error) {
	file, err := ioutil.TempFile(".", "gopackage_")
	if err != nil {
		return "", err
	}
	defer file.Close()

	t, err := template.ParseFiles(path)
	if err != nil {
		return "", err
	}

	if err := t.Execute(file, v); err != nil {
		return "", err
	}

	return file.Name(), nil
}
<commit_msg>go/package: fix version for deb package<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"koding/oskite"
	"koding/terminal"
	"koding/tools/build"
	"koding/tools/config"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"
	"text/template"

	"github.com/koding/kite/reverseproxy"
)

var (
	flagProfile     = flag.String("c", "", "Define config profile to be included")
	flagRegion      = flag.String("r", "", "Define region profile to be included")
	flagEnvironment = flag.String("e", "", "Define environment profile to be included")
	flagHost        = flag.String("h", "", "Define hostname for kite reveseproxy")
	flagApp         = flag.String("a", "", "App to be build")
	flagBuildNumber = flag.Int("b", 0, "Build number is added to the generated file if specified")

	// kontrolproxy specific flags
	flagProxy = flag.String("p", "", "Select user proxy or koding proxy") // Proxy only

	flagDisableUpstart = flag.Bool("u", false, "Disable including upstart script")
	flagDebug          = flag.Bool("d", false, "Enable debug mode")

	packages = map[string]func() error{
		"oskite":       buildOsKite,
		"kontrolproxy": buildKontrolProxy,
		"reverseproxy": buildProxyKite,
		"terminal":     buildTerminal,
		"kontrol":      buildKontrol,
		"klient":       buildKlient,
	}
)

type pkg struct {
	appName       string
	importPath    string
	files         []string
	version       string
	upstartScript string
	symbolname    string
	symbolvalue   string
}

func main() {
	flag.Parse()
	if *flagApp == "" {
		fmt.Printf("Please define package with -a to be build. Available apps:\n%s\n", packageList())
		os.Exit(1)
	}

	build, ok := packages[*flagApp]
	if !ok {
		log.Fatal("package to be build is not available")
	}

	if err := build(); err != nil {
		fmt.Println(err)
	}
}

func packageList() string {
	pkgs := "\n"
	count := 1
	for pkg := range packages {
		pkgs += strconv.Itoa(count) + ". " + pkg + "\n"
		count++
	}

	return pkgs
}

func buildProxyKite() error {
	if *flagEnvironment == "" || *flagRegion == "" || *flagHost == "" {
		return errors.New("Please define environment -e , region -r and host -h")
	}

	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return errors.New("GOPATH is not set")
	}

	importPath := "github.com/koding/kite/reverseproxy/reverseproxy"
	upstartPath := filepath.Join(gopath, "src/koding/kites/reverseproxy/files/reverseproxy.conf")

	temps := struct {
		Environment string
		Region      string
		Host        string
	}{
		Environment: *flagEnvironment,
		Region:      *flagRegion,
		Host:        *flagHost,
	}

	files := []string{}
	files = append(files, "certs/koding_com_cert.pem", "certs/koding_com_key.pem")

	// change our upstartscript because it's a template
	configUpstart, err := prepareUpstart(upstartPath, temps)
	if err != nil {
		return err
	}
	defer os.Remove(configUpstart)

	kiteproxy := pkg{
		appName:       *flagApp,
		importPath:    importPath,
		files:         files,
		version:       reverseproxy.Version,
		upstartScript: configUpstart,
	}

	return kiteproxy.build()
}

func buildKlient() error {
	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return errors.New("GOPATH is not set")
	}

	importPath := "koding/kites/klient"
	upstartPath := filepath.Join(gopath, "src", importPath, "files/klient.conf")

	symbolvalue := "0.0.1"
	if *flagBuildNumber != 0 {
		symbolvalue = "0.1." + strconv.Itoa(*flagBuildNumber)
	}

	kclient := pkg{
		appName:       *flagApp,
		importPath:    importPath,
		version:       symbolvalue,
		upstartScript: upstartPath,
		symbolname:    "koding/kites/klient/protocol.Version",
		symbolvalue:   symbolvalue,
	}

	return kclient.build()
}

func buildKontrol() error {
	if *flagProfile == "" || *flagRegion == "" {
		return errors.New("Please define config -c and region -r")
	}

	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return errors.New("GOPATH is not set")
	}

	kontrolPath := "koding/kites/kontrol"
	temps := struct {
		Profile string
		Region  string
	}{
		Profile: *flagProfile,
		Region:  *flagRegion,
	}

	var files = make([]string, 0)
	files = append(files, filepath.Join(gopath, "src", kontrolPath, "files"))

	// change our upstartscript because it's a template
	var configUpstart string
	var err error
	if !*flagDisableUpstart {
		kontrolUpstart := filepath.Join(gopath, "src", kontrolPath, "files/kontrol.conf")
		configUpstart, err = prepareUpstart(kontrolUpstart, temps)
		if err != nil {
			return err
		}
		defer os.Remove(configUpstart)
	}

	term := pkg{
		appName:       *flagApp,
		importPath:    kontrolPath,
		files:         files,
		version:       "0.1.0",
		upstartScript: configUpstart,
	}

	return term.build()
}

func buildTerminal() error {
	if *flagProfile == "" || *flagRegion == "" {
		return errors.New("Please define config -c and region -r")
	}

	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return errors.New("GOPATH is not set")
	}

	terminalPath := "koding/kites/terminal"
	terminalPackage := "koding/terminal"
	temps := struct {
		Profile string
		Region  string
	}{
		Profile: *flagProfile,
		Region:  *flagRegion,
	}

	var files = make([]string, 0)
	files = append(files, filepath.Join(gopath, "src", terminalPackage, "files"))

	// change our upstartscript because it's a template
	var configUpstart string
	var err error
	if !*flagDisableUpstart {
		terminalUpstart := filepath.Join(gopath, "src", terminalPackage, "files/terminal.conf")
		configUpstart, err = prepareUpstart(terminalUpstart, temps)
		if err != nil {
			return err
		}
		defer os.Remove(configUpstart)
	}

	term := pkg{
		appName:       *flagApp,
		importPath:    terminalPath,
		files:         files,
		version:       terminal.TERMINAL_VERSION,
		upstartScript: configUpstart,
	}

	return term.build()
}

func buildOsKite() error {
	if *flagProfile == "" || *flagRegion == "" {
		return errors.New("Please define config -c and region -r")
	}

	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return errors.New("GOPATH is not set")
	}

	oskitePath := "koding/kites/os"
	oskitePackage := "koding/oskite"
	temps := struct {
		Profile string
		Region  string
	}{
		Profile: *flagProfile,
		Region:  *flagRegion,
	}

	var files = make([]string, 0)
	files = append(files, filepath.Join(gopath, "src", oskitePackage, "files"))
	files = append(files, filepath.Join(gopath, "bin-vagrant/vmtool")) // TODO add it to the list of importPaths

	// change our upstartscript because it's a template
	var configUpstart string
	var err error
	if !*flagDisableUpstart {
		oskiteUpstart := filepath.Join(gopath, "src", oskitePackage, "files/oskite.conf")
		configUpstart, err = prepareUpstart(oskiteUpstart, temps)
		if err != nil {
			return err
		}
		defer os.Remove(configUpstart)
	}

	oskite := pkg{
		appName:       *flagApp,
		importPath:    oskitePath,
		files:         files,
		version:       oskite.OSKITE_VERSION,
		upstartScript: configUpstart,
	}

	return oskite.build()
}

func buildKontrolProxy() error {
	if *flagProfile == "" || *flagRegion == "" {
		return errors.New("Please define config -c and region -r")
	}

	gopath := os.Getenv("GOPATH")
	if gopath == "" {
		return errors.New("GOPATH is not set")
	}

	kdproxyPath := "koding/kontrol/kontrolproxy"

	temps := struct {
		Profile   string
		Region    string
		UserProxy string
	}{
		Profile: *flagProfile,
		Region:  *flagRegion,
	}

	var files = make([]string, 0)
	switch *flagProxy {
	case "koding":
		files = append(files, "certs/koding_com_cert.pem", "certs/koding_com_key.pem")
	case "y":
		files = append(files, "certs/y_koding_com_cert.pem", "certs/y_koding_com_key.pem")
	case "x":
		files = append(files, "certs/x_koding_com_cert.pem", "certs/x_koding_com_key.pem")
	case "user":
		temps.UserProxy = "-v"
		files = append(files, "certs/kd_io_cert.pem", "certs/kd_io_key.pem")
	default:
		return errors.New("Please define certs to be included with -p. Available certs: [user | koding | x | y]")
	}

	files = append(files, filepath.Join(gopath, "src", kdproxyPath, "files"))

	// change our upstartscript because it's a template
	var configUpstart string
	var err error
	if !*flagDisableUpstart {
		kdproxyUpstart := filepath.Join(gopath, "src", kdproxyPath, "files/kontrolproxy.conf")
		configUpstart, err = prepareUpstart(kdproxyUpstart, temps)
		if err != nil {
			return err
		}
		defer os.Remove(configUpstart)
	}

	kontrolproxy := pkg{
		appName:       *flagApp,
		importPath:    kdproxyPath,
		files:         files,
		version:       "0.0.9",
		upstartScript: configUpstart,
	}

	return kontrolproxy.build()
}

func (p *pkg) build() error {
	if *flagProfile == "" || *flagRegion == "" {
		fmt.Printf("building '%s'\n", *flagApp)
	} else {
		fmt.Printf("building '%s' for config '%s' and region '%s'\n", *flagApp, *flagProfile, *flagRegion)

		// prepare config folder
		tempDir, err := ioutil.TempDir(".", "gopackage_")
		if err != nil {
			return err
		}
		defer os.RemoveAll(tempDir)

		configDir := filepath.Join(tempDir, "config")
		os.MkdirAll(configDir, 0755)

		// koding-config-manager needs it
		err = ioutil.WriteFile("VERSION", []byte(p.version), 0755)
		if err != nil {
			return err
		}
		defer os.Remove("VERSION")

		c, err := config.ReadConfigManager(*flagProfile)
		if err != nil {
			return err
		}

		configPretty, err := json.MarshalIndent(c, "", "  ")
		if err != nil {
			return err
		}

		configFile := filepath.Join(configDir, fmt.Sprintf("main.%s.json", *flagProfile))
		err = ioutil.WriteFile(configFile, configPretty, 0644)
		if err != nil {
			return err
		}

		p.files = append(p.files, configDir)
	}

	// Now it's time to build
	if runtime.GOOS != "linux" {
		return errors.New("Not supported. Please run on a linux machine.")
	}

	deb := &build.Deb{
		Debug:         *flagDebug,
		AppName:       p.appName,
		Version:       p.version,
		ImportPath:    p.importPath,
		Files:         strings.Join(p.files, ","),
		InstallPrefix: "opt/kite",
		UpstartScript: p.upstartScript,
		SymbolName:    p.symbolname,
		SymbolValue:   p.symbolvalue,
	}

	debFile, err := deb.Build()
	if err != nil {
		log.Println("linux:", err)
	}

	// customize our created file with the passed arguments
	oldname := debFile

	newname := p.appName + "_" + p.version
	if *flagBuildNumber != 0 {
		// http://semver.org/ see build-number paragraph
		newname = p.appName + "_0.1." + strconv.Itoa(*flagBuildNumber)
	}

	if *flagProfile == "" || *flagRegion == "" {
		newname += fmt.Sprintf("_%s.deb", deb.Arch)
	} else {
		newname += fmt.Sprintf("_%s-%s_%s.deb", *flagProfile, *flagRegion, deb.Arch)
	}

	if err := os.Rename(oldname, newname); err != nil {
		return err
	}

	fmt.Printf("success '%s' is ready. Some helpful commands for you:\n\n", newname)
	fmt.Printf("  show deb content   : dpkg -c %s\n", newname)
	fmt.Printf("  show basic info    : dpkg -f %s\n", newname)
	fmt.Printf("  install to machine : dpkg -i %s\n\n", newname)

	return nil
}

func prepareUpstart(path string, v interface{}) (string, error) {
	file, err := ioutil.TempFile(".", "gopackage_")
	if err != nil {
		return "", err
	}
	defer file.Close()

	t, err := template.ParseFiles(path)
	if err != nil {
		return "", err
	}

	if err := t.Execute(file, v); err != nil {
		return "", err
	}

	return file.Name(), nil
}
<|endoftext|>


<commit_before>package go_geohash

import "strings"

// Static array of 0-9, a-z
var base32_codes [32]string

// Static map of character in "base32_codes" to it's position
// This is to improve performance of the DecodeBoundBox method
var base32_map map[string]uint8

func init() {
	base32_codes = [...]string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "b", "c", "d", "e", "f", "g", "h", "j", "k", "m", "n", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}

	base32_map = map[string]uint8{}
	for i, c := range base32_codes {
		base32_map[c] = uint8(i)
	}
}

//
// Bounded box for parsing latitude and longitude
//
type DecodedBoundBox struct {
	MinLatitude  float64
	MinLongitude float64

	MaxLatitude  float64
	MaxLongitude float64
}

//
// Decoded Latitude,Longitude + error position
//
type DecodedPosition struct {
	Latitude  float64
	Longitude float64

	LatitudeError  float64
	LongitudeError float64
}

//
// Encode a Latitude and Longitude as a string
//
// Arguments:
//  latitude  float64
//  longitude float64
//  precision uint8  (ie how long should the hash string be?)
//
func Encode(latitude float64, longitude float64, precision uint8) string {
	// Pre-Allocate the hash string
	// var output string = strings.Repeat(" ", int(precision))

	// DecodedBoundBox for the lat/lon + errors
	var bbox DecodedBoundBox = DecodedBoundBox{MaxLatitude: 90, MaxLongitude: 180, MinLatitude: -90, MinLongitude: -180}

	var min_max_avg float64 = 0
	var islon bool = true
	var num_bits uint = 0
	var hash_index int = 0

	var buffer = make([]string, precision)
	var output_length uint8 = 0
	for output_length < precision {
		if islon {
			min_max_avg = (bbox.MaxLongitude + bbox.MinLongitude) / 2
			if longitude > min_max_avg {
				hash_index = (hash_index << 1) + 1
				bbox.MinLongitude = min_max_avg
			} else {
				hash_index = (hash_index << 1) + 0
				bbox.MaxLongitude = min_max_avg
			}
		} else {
			min_max_avg = (bbox.MaxLatitude + bbox.MinLatitude) / 2
			if latitude > min_max_avg {
				hash_index = (hash_index << 1) + 1
				bbox.MinLatitude = min_max_avg
			} else {
				hash_index = (hash_index << 1) + 0
				bbox.MaxLatitude = min_max_avg
			}
		}
		islon = !islon

		num_bits++
		if 5 == num_bits {
			buffer[output_length] = base32_codes[hash_index]
			// output[output_length] = base32_codes[hash_index]

			output_length++
			num_bits = 0
			hash_index = 0
		}
	}

	var output = strings.Join(buffer, "")

	return output
}

func DecodeBoundBox(hash_string string) DecodedBoundBox {
	// Downcase the input string
	hash_string = strings.ToLower(hash_string)

	var output DecodedBoundBox = DecodedBoundBox{MaxLatitude: 90, MaxLongitude: 180, MinLatitude: -90, MinLongitude: -180}

	var islon bool = true
	for _, c := range hash_string {
		var index_of uint8 = base32_map[string(c)]

		for bits := 4; bits >= 0; bits-- {
			bit := (index_of >> uint8(bits)) & 1
			if islon {
				mid := (output.MaxLongitude + output.MinLongitude) / 2
				if bit == 1 {
					output.MinLongitude = mid
				} else {
					output.MaxLongitude = mid
				}
			} else {
				mid := (output.MaxLatitude + output.MinLatitude) / 2
				if bit == 1 {
					output.MinLatitude = mid
				} else {
					output.MaxLatitude = mid
				}
			}
			islon = !islon
		}
	}

	return output
}

func Decode(hash_string string) DecodedPosition {
	var bbox DecodedBoundBox = DecodeBoundBox(hash_string)
	var output DecodedPosition
	// Mid point of box
	output.Latitude = (bbox.MinLatitude + bbox.MaxLatitude) / 2
	output.Longitude = (bbox.MinLongitude + bbox.MaxLongitude) / 2
	// Mid Point -  Min/Max ==> Error
	output.LatitudeError = bbox.MaxLatitude - output.Latitude
	output.LongitudeError = bbox.MaxLongitude - output.Longitude

	return output
}

func Neighbor(hash_string string, direction [2]int) string {
	// Adjust the DecodedPosition for the direction of the neighbors
	var position DecodedPosition = Decode(hash_string)
	precision := uint8(len(hash_string))
	lat := position.Latitude + float64(direction[0])*position.LatitudeError*2
	lon := position.Longitude + float64(direction[1])*position.LongitudeError*2

	return Encode(lat, lon, precision)
}
<commit_msg>Updated to use a buffer for joining strings<commit_after>package go_geohash

import "strings"
import "bytes"

// Static array of 0-9, a-z
var base32_codes [32]string

// Static map of character in "base32_codes" to it's position
// This is to improve performance of the DecodeBoundBox method
var base32_map map[string]uint8

func init() {
	base32_codes = [...]string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "b", "c", "d", "e", "f", "g", "h", "j", "k", "m", "n", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}

	base32_map = map[string]uint8{}
	for i, c := range base32_codes {
		base32_map[c] = uint8(i)
	}
}

//
// Bounded box for parsing latitude and longitude
//
type DecodedBoundBox struct {
	MinLatitude  float64
	MinLongitude float64

	MaxLatitude  float64
	MaxLongitude float64
}

//
// Decoded Latitude,Longitude + error position
//
type DecodedPosition struct {
	Latitude  float64
	Longitude float64

	LatitudeError  float64
	LongitudeError float64
}

//
// Encode a Latitude and Longitude as a string
//
// Arguments:
//  latitude  float64
//  longitude float64
//  precision uint8  (ie how long should the hash string be?)
//
func Encode(latitude float64, longitude float64, precision uint8) string {
	// Pre-Allocate the hash string
	// var output string = strings.Repeat(" ", int(precision))

	// DecodedBoundBox for the lat/lon + errors
	var bbox DecodedBoundBox = DecodedBoundBox{MaxLatitude: 90, MaxLongitude: 180, MinLatitude: -90, MinLongitude: -180}

	var min_max_avg float64 = 0
	var islon bool = true
	var num_bits uint = 0
	var hash_index int = 0

	var buffer bytes.Buffer
	var output_length uint8 = 0
	for output_length < precision {
		if islon {
			min_max_avg = (bbox.MaxLongitude + bbox.MinLongitude) / 2
			if longitude > min_max_avg {
				hash_index = (hash_index << 1) + 1
				bbox.MinLongitude = min_max_avg
			} else {
				hash_index = (hash_index << 1) + 0
				bbox.MaxLongitude = min_max_avg
			}
		} else {
			min_max_avg = (bbox.MaxLatitude + bbox.MinLatitude) / 2
			if latitude > min_max_avg {
				hash_index = (hash_index << 1) + 1
				bbox.MinLatitude = min_max_avg
			} else {
				hash_index = (hash_index << 1) + 0
				bbox.MaxLatitude = min_max_avg
			}
		}
		islon = !islon

		num_bits++
		if 5 == num_bits {
			buffer.WriteString(base32_codes[hash_index])

			output_length++
			num_bits = 0
			hash_index = 0
		}
	}

	return buffer.String()
}

func DecodeBoundBox(hash_string string) DecodedBoundBox {
	// Downcase the input string
	hash_string = strings.ToLower(hash_string)

	var output DecodedBoundBox = DecodedBoundBox{MaxLatitude: 90, MaxLongitude: 180, MinLatitude: -90, MinLongitude: -180}

	var islon bool = true
	for _, c := range hash_string {
		var index_of uint8 = base32_map[string(c)]

		for bits := 4; bits >= 0; bits-- {
			bit := (index_of >> uint8(bits)) & 1
			if islon {
				mid := (output.MaxLongitude + output.MinLongitude) / 2
				if bit == 1 {
					output.MinLongitude = mid
				} else {
					output.MaxLongitude = mid
				}
			} else {
				mid := (output.MaxLatitude + output.MinLatitude) / 2
				if bit == 1 {
					output.MinLatitude = mid
				} else {
					output.MaxLatitude = mid
				}
			}
			islon = !islon
		}
	}

	return output
}

func Decode(hash_string string) DecodedPosition {
	var bbox DecodedBoundBox = DecodeBoundBox(hash_string)
	var output DecodedPosition
	// Mid point of box
	output.Latitude = (bbox.MinLatitude + bbox.MaxLatitude) / 2
	output.Longitude = (bbox.MinLongitude + bbox.MaxLongitude) / 2
	// Mid Point -  Min/Max ==> Error
	output.LatitudeError = bbox.MaxLatitude - output.Latitude
	output.LongitudeError = bbox.MaxLongitude - output.Longitude

	return output
}

func Neighbor(hash_string string, direction [2]int) string {
	// Adjust the DecodedPosition for the direction of the neighbors
	var position DecodedPosition = Decode(hash_string)
	precision := uint8(len(hash_string))
	lat := position.Latitude + float64(direction[0])*position.LatitudeError*2
	lon := position.Longitude + float64(direction[1])*position.LongitudeError*2

	return Encode(lat, lon, precision)
}
<|endoftext|>